summaryrefslogtreecommitdiffstats
path: root/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2018-10-15 17:53:18 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2018-10-15 17:53:18 +0000
commitd51c720a61187043efecb7c3b44346e8d434bc43 (patch)
treef6bef184acaa77abe8853c8b5b05e03f992ef1fb /include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
parent753ce1e0a70d7a5907be8c20796c8e9c59faf64a (diff)
[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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@344539 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h')
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h19
1 files changed, 16 insertions, 3 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index 4c50eafbde..9430beed74 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -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; }