Re-apply "[analyzer] Model trivial copy/move ctors with an aggregate bind."
With the optimization in the previous commit, this should be safe again.
Originally applied in r173951, then reverted in r174069.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174212 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/Analysis/ctor-inlining.mm b/test/Analysis/ctor-inlining.mm
index be5d81a..1603ff3 100644
--- a/test/Analysis/ctor-inlining.mm
+++ b/test/Analysis/ctor-inlining.mm
@@ -1,8 +1,15 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify %s
void clang_analyzer_eval(bool);
void clang_analyzer_checkInlined(bool);
+// A simplified version of std::move.
+template <typename T>
+T &&move(T &obj) {
+ return static_cast<T &&>(obj);
+}
+
+
struct Wrapper {
__strong id obj;
};
@@ -117,3 +124,96 @@
clang_analyzer_eval(result); // expected-warning{{TRUE}}
}
}
+
+namespace PODUninitialized {
+ class POD {
+ public:
+ int x, y;
+ };
+
+ class PODWrapper {
+ public:
+ POD p;
+ };
+
+ class NonPOD {
+ public:
+ int x, y;
+
+ NonPOD() {}
+ NonPOD(const NonPOD &Other)
+ : x(Other.x), y(Other.y) // expected-warning {{undefined}}
+ {
+ }
+ NonPOD(NonPOD &&Other)
+ : x(Other.x), y(Other.y) // expected-warning {{undefined}}
+ {
+ }
+ };
+
+ class NonPODWrapper {
+ public:
+ class Inner {
+ public:
+ int x, y;
+
+ Inner() {}
+ Inner(const Inner &Other)
+ : x(Other.x), y(Other.y) // expected-warning {{undefined}}
+ {
+ }
+ Inner(Inner &&Other)
+ : x(Other.x), y(Other.y) // expected-warning {{undefined}}
+ {
+ }
+ };
+
+ Inner p;
+ };
+
+ void testPOD() {
+ POD p;
+ p.x = 1;
+ POD p2 = p; // no-warning
+ clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}}
+ POD p3 = move(p); // no-warning
+ clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}}
+
+ // Use rvalues as well.
+ clang_analyzer_eval(POD(p3).x == 1); // expected-warning{{TRUE}}
+
+ PODWrapper w;
+ w.p.y = 1;
+ PODWrapper w2 = w; // no-warning
+ clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}}
+ PODWrapper w3 = move(w); // no-warning
+ clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}}
+
+ // Use rvalues as well.
+ clang_analyzer_eval(PODWrapper(w3).p.y == 1); // expected-warning{{TRUE}}
+ }
+
+ void testNonPOD() {
+ NonPOD p;
+ p.x = 1;
+ NonPOD p2 = p;
+ }
+
+ void testNonPODMove() {
+ NonPOD p;
+ p.x = 1;
+ NonPOD p2 = move(p);
+ }
+
+ void testNonPODWrapper() {
+ NonPODWrapper w;
+ w.p.y = 1;
+ NonPODWrapper w2 = w;
+ }
+
+ void testNonPODWrapperMove() {
+ NonPODWrapper w;
+ w.p.y = 1;
+ NonPODWrapper w2 = move(w);
+ }
+}
diff --git a/test/Analysis/temporaries.cpp b/test/Analysis/temporaries.cpp
index 547be02..e885878 100644
--- a/test/Analysis/temporaries.cpp
+++ b/test/Analysis/temporaries.cpp
@@ -16,7 +16,7 @@
}
const Trivial &getTrivialRef() {
- return Trivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'struct Trivial' returned to caller}}
+ return Trivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'const struct Trivial' returned to caller}}
}
@@ -25,6 +25,6 @@
}
const NonTrivial &getNonTrivialRef() {
- return NonTrivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'struct NonTrivial' returned to caller}}
+ return NonTrivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'const struct NonTrivial' returned to caller}}
}