forked from OSchip/llvm-project
[analyzer] Teach CallEvent about C++17 aligned operator new().
In C++17, when class C has large alignment value, a special case of overload resolution rule kicks in for expression new C that causes the aligned version of operator new() to be called. The aligned new has two arguments: size and alignment. However, the new-expression has only one "argument": the construct-expression for C(). This causes a false positive in core.CallAndMessage's check for matching number of arguments and number of parameters. Update CXXAllocatorCall, which is a CallEvent sub-class for operator new calls within new-expressions, so that the number of arguments always matched the number of parameters. rdar://problem/44738501 Differential Revision: https://reviews.llvm.org/D52957 llvm-svn: 344539
This commit is contained in:
parent
65b4d7ddd9
commit
fcf107d411
|
@ -921,15 +921,28 @@ public:
|
|||
return getOriginExpr()->getOperatorNew();
|
||||
}
|
||||
|
||||
// Size and maybe implicit alignment in C++17. Instead of size, the AST
|
||||
// contains the construct-expression. Alignment is always hidden.
|
||||
// We pretend that argument 0 is size and argument 1 is alignment (if passed
|
||||
// implicitly) and the rest are placement args. This makes sure that the
|
||||
// number of arguments is always the same as the number of parameters.
|
||||
unsigned getNumImplicitArgs() const {
|
||||
return getOriginExpr()->passAlignment() ? 2 : 1;
|
||||
}
|
||||
|
||||
unsigned getNumArgs() const override {
|
||||
return getOriginExpr()->getNumPlacementArgs() + 1;
|
||||
return getOriginExpr()->getNumPlacementArgs() + getNumImplicitArgs();
|
||||
}
|
||||
|
||||
const Expr *getArgExpr(unsigned Index) const override {
|
||||
// The first argument of an allocator call is the size of the allocation.
|
||||
if (Index == 0)
|
||||
if (Index < getNumImplicitArgs())
|
||||
return nullptr;
|
||||
return getOriginExpr()->getPlacementArg(Index - 1);
|
||||
return getOriginExpr()->getPlacementArg(Index - getNumImplicitArgs());
|
||||
}
|
||||
|
||||
const Expr *getPlacementArgExpr(unsigned Index) const {
|
||||
return getOriginExpr()->getPlacementArg(Index);
|
||||
}
|
||||
|
||||
Kind getKind() const override { return CE_CXXAllocator; }
|
||||
|
|
|
@ -503,10 +503,14 @@ static void addParameterValuesToBindings(const StackFrameContext *CalleeCtx,
|
|||
const ParmVarDecl *ParamDecl = *I;
|
||||
assert(ParamDecl && "Formal parameter has no decl?");
|
||||
|
||||
// TODO: Support allocator calls.
|
||||
if (Call.getKind() != CE_CXXAllocator)
|
||||
if (Call.isArgumentConstructedDirectly(Idx))
|
||||
continue;
|
||||
|
||||
// TODO: Allocators should receive the correct size and possibly alignment,
|
||||
// determined in compile-time but not represented as arg-expressions,
|
||||
// which makes getArgSVal() fail and return UnknownVal.
|
||||
SVal ArgVal = Call.getArgSVal(Idx);
|
||||
if (!ArgVal.isUnknown()) {
|
||||
Loc ParamLoc = SVB.makeLoc(MRMgr.getVarRegion(ParamDecl, CalleeCtx));
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
//RUN: %clang_analyze_cc1 -std=c++17 -analyze -analyzer-checker=core -verify %s
|
||||
|
||||
// expected-no-diagnostics
|
||||
|
||||
// Notice the weird alignment.
|
||||
struct alignas(1024) S {};
|
||||
|
||||
void foo() {
|
||||
// Operator new() here is the C++17 aligned new that takes two arguments:
|
||||
// size and alignment. Size is passed implicitly as usual, and alignment
|
||||
// is passed implicitly in a similar manner.
|
||||
S *s = new S; // no-warning
|
||||
delete s;
|
||||
}
|
Loading…
Reference in New Issue