aboutsummaryrefslogtreecommitdiff
path: root/test/Analysis/ctor-inlining.mm
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2013-01-30 18:16:06 +0000
committerJordan Rose <jordan_rose@apple.com>2013-01-30 18:16:06 +0000
commitbaa7ca1142990e1ad6d4e9d2c73adb749ff50789 (patch)
tree453101a8e843fd9be1ec32b0ac255dcd7f3a834d /test/Analysis/ctor-inlining.mm
parent74149595de064572661d10f736c6cb2eda78db8d (diff)
[analyzer] Model trivial copy/move ctors with an aggregate bind.
This is faster for the analyzer to process than inlining the constructor and performing a member-wise copy, and it also solves the problem of warning when a partially-initialized POD struct is copied. Before: CGPoint p; p.x = 0; CGPoint p2 = p; <-- assigned value is garbage or undefined After: CGPoint p; p.x = 0; CGPoint p2 = p; // no-warning This matches our behavior in C, where we don't see a field-by-field copy. <rdar://problem/12305288> git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@173951 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/Analysis/ctor-inlining.mm')
-rw-r--r--test/Analysis/ctor-inlining.mm102
1 files changed, 101 insertions, 1 deletions
diff --git a/test/Analysis/ctor-inlining.mm b/test/Analysis/ctor-inlining.mm
index be5d81a58e..1603ff3893 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 @@ namespace ConstructorUsedAsRValue {
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);
+ }
+}