[analyzer] Don't inline constructors for objects allocated with operator new.
Because the CXXNewExpr appears after the CXXConstructExpr in the CFG, we don't
actually have the correct region to construct into at the time we decide
whether or not to inline. The long-term fix (discussed in PR12014) might be to
introduce a new CFG node (CFGAllocator) that appears before the constructor.
Tracking the short-term fix in <rdar://problem/12180598>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162689 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/Analysis/inline.cpp b/test/Analysis/inline.cpp
index 6590776..573b164 100644
--- a/test/Analysis/inline.cpp
+++ b/test/Analysis/inline.cpp
@@ -1,8 +1,18 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-ipa=inlining -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-ipa=inlining -verify %s
void clang_analyzer_eval(bool);
void clang_analyzer_checkInlined(bool);
+typedef __typeof__(sizeof(int)) size_t;
+extern "C" void *malloc(size_t);
+
+// This is the standard placement new.
+inline void* operator new(size_t, void* __p) throw()
+{
+ return __p;
+}
+
+
class A {
public:
int getZero() { return 0; }
@@ -227,3 +237,33 @@
clang_analyzer_eval(obj.get() == 42); // expected-warning{{UNKNOWN}}
}
}
+
+namespace OperatorNew {
+ class IntWrapper {
+ public:
+ int value;
+
+ IntWrapper(int input) : value(input) {
+ // We don't want this constructor to be inlined unless we can actually
+ // use the proper region for operator new.
+ // See PR12014 and <rdar://problem/12180598>.
+ clang_analyzer_checkInlined(false); // no-warning
+ }
+ };
+
+ void test() {
+ IntWrapper *obj = new IntWrapper(42);
+ // should be TRUE
+ clang_analyzer_eval(obj->value == 42); // expected-warning{{UNKNOWN}}
+ }
+
+ void testPlacement() {
+ IntWrapper *obj = static_cast<IntWrapper *>(malloc(sizeof(IntWrapper)));
+ IntWrapper *alias = new (obj) IntWrapper(42);
+
+ clang_analyzer_eval(alias == obj); // expected-warning{{TRUE}}
+
+ // should be TRUE
+ clang_analyzer_eval(obj->value == 42); // expected-warning{{UNKNOWN}}
+ }
+}