Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -3265,10 +3265,11 @@ class CallExpr : public Expr {
/// Try to get the alloc_size attribute of the callee. May return null.
const AllocSizeAttr *getCalleeAllocSizeAttr() const;

/// Get the total size in bytes allocated by calling a function decorated with
/// alloc_size. Returns std::nullopt if the the result cannot be evaluated.
/// Evaluates the total size in bytes allocated by calling a function
/// decorated with alloc_size. Returns std::nullopt if the the result cannot
/// be evaluated.
std::optional<llvm::APInt>
getBytesReturnedByAllocSizeCall(const ASTContext &Ctx) const;
evaluateBytesReturnedByAllocSizeCall(const ASTContext &Ctx) const;

bool isCallToStdMove() const;

Expand Down
10 changes: 5 additions & 5 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3533,14 +3533,14 @@ const AllocSizeAttr *CallExpr::getCalleeAllocSizeAttr() const {
}

std::optional<llvm::APInt>
CallExpr::getBytesReturnedByAllocSizeCall(const ASTContext &Ctx) const {
CallExpr::evaluateBytesReturnedByAllocSizeCall(const ASTContext &Ctx) const {
const AllocSizeAttr *AllocSize = getCalleeAllocSizeAttr();

assert(AllocSize && AllocSize->getElemSizeParam().isValid());
unsigned SizeArgNo = AllocSize->getElemSizeParam().getASTIndex();
unsigned BitsInSizeT = Ctx.getTypeSize(Ctx.getSizeType());
if (getNumArgs() <= SizeArgNo)
return {};
return std::nullopt;

auto EvaluateAsSizeT = [&](const Expr *E, llvm::APSInt &Into) {
Expr::EvalResult ExprResult;
Expand All @@ -3556,20 +3556,20 @@ CallExpr::getBytesReturnedByAllocSizeCall(const ASTContext &Ctx) const {

llvm::APSInt SizeOfElem;
if (!EvaluateAsSizeT(getArg(SizeArgNo), SizeOfElem))
return {};
return std::nullopt;

if (!AllocSize->getNumElemsParam().isValid())
return SizeOfElem;

llvm::APSInt NumberOfElems;
unsigned NumArgNo = AllocSize->getNumElemsParam().getASTIndex();
if (!EvaluateAsSizeT(getArg(NumArgNo), NumberOfElems))
return {};
return std::nullopt;

bool Overflow;
llvm::APInt BytesAvailable = SizeOfElem.umul_ov(NumberOfElems, Overflow);
if (Overflow)
return {};
return std::nullopt;

return BytesAvailable;
}
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9465,7 +9465,8 @@ static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx,
"Can't get the size of a non alloc_size function");
const auto *Base = LVal.getLValueBase().get<const Expr *>();
const CallExpr *CE = tryUnwrapAllocSizeCall(Base);
std::optional<llvm::APInt> Size = CE->getBytesReturnedByAllocSizeCall(Ctx);
std::optional<llvm::APInt> Size =
CE->evaluateBytesReturnedByAllocSizeCall(Ctx);
if (!Size)
return false;

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7836,7 +7836,7 @@ static void CheckSufficientAllocSize(Sema &S, QualType DestType,
if (!CE->getCalleeAllocSizeAttr())
return;
std::optional<llvm::APInt> AllocSize =
CE->getBytesReturnedByAllocSizeCall(S.Context);
CE->evaluateBytesReturnedByAllocSizeCall(S.Context);
if (!AllocSize)
return;
auto Size = CharUnits::fromQuantity(AllocSize->getZExtValue());
Expand Down