diff options
Diffstat (limited to 'test/Analysis/ctor-inlining.mm')
-rw-r--r-- | test/Analysis/ctor-inlining.mm | 385 |
1 files changed, 384 insertions, 1 deletions
diff --git a/test/Analysis/ctor-inlining.mm b/test/Analysis/ctor-inlining.mm index ac963e5..8cdb005 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-ipa=inlining -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,379 @@ 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}} + { + } + + NonPOD &operator=(const NonPOD &Other) + { + x = Other.x; + y = Other.y; // expected-warning {{undefined}} + return *this; + } + NonPOD &operator=(NonPOD &&Other) + { + x = Other.x; + y = Other.y; // expected-warning {{undefined}} + return *this; + } + }; + + 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 &operator=(const Inner &Other) + { + x = Other.x; // expected-warning {{undefined}} + y = Other.y; + return *this; + } + Inner &operator=(Inner &&Other) + { + x = Other.x; // expected-warning {{undefined}} + y = Other.y; + return *this; + } + }; + + 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); + } + + // Not strictly about constructors, but trivial assignment operators should + // essentially work the same way. + namespace AssignmentOperator { + void testPOD() { + POD p; + p.x = 1; + POD p2; + p2 = p; // no-warning + clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}} + POD p3; + p3 = move(p); // no-warning + clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}} + + PODWrapper w; + w.p.y = 1; + PODWrapper w2; + w2 = w; // no-warning + clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}} + PODWrapper w3; + w3 = move(w); // no-warning + clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}} + } + + void testReturnValue() { + POD p; + p.x = 1; + POD p2; + clang_analyzer_eval(&(p2 = p) == &p2); // expected-warning{{TRUE}} + + PODWrapper w; + w.p.y = 1; + PODWrapper w2; + clang_analyzer_eval(&(w2 = w) == &w2); // expected-warning{{TRUE}} + } + + void testNonPOD() { + NonPOD p; + p.x = 1; + NonPOD p2; + p2 = p; + } + + void testNonPODMove() { + NonPOD p; + p.x = 1; + NonPOD p2; + p2 = move(p); + } + + void testNonPODWrapper() { + NonPODWrapper w; + w.p.y = 1; + NonPODWrapper w2; + w2 = w; + } + + void testNonPODWrapperMove() { + NonPODWrapper w; + w.p.y = 1; + NonPODWrapper w2; + w2 = move(w); + } + } +} + +namespace ArrayMembers { + struct Primitive { + int values[3]; + }; + + void testPrimitive() { + Primitive a = { { 1, 2, 3 } }; + + clang_analyzer_eval(a.values[0] == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(a.values[1] == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(a.values[2] == 3); // expected-warning{{TRUE}} + + Primitive b = a; + + clang_analyzer_eval(b.values[0] == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(b.values[1] == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(b.values[2] == 3); // expected-warning{{TRUE}} + + Primitive c; + c = b; + + clang_analyzer_eval(c.values[0] == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(c.values[1] == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(c.values[2] == 3); // expected-warning{{TRUE}} + } + + struct NestedPrimitive { + int values[2][3]; + }; + + void testNestedPrimitive() { + NestedPrimitive a = { { { 0, 0, 0 }, { 1, 2, 3 } } }; + + clang_analyzer_eval(a.values[1][0] == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(a.values[1][1] == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(a.values[1][2] == 3); // expected-warning{{TRUE}} + + NestedPrimitive b = a; + + clang_analyzer_eval(b.values[1][0] == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(b.values[1][1] == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(b.values[1][2] == 3); // expected-warning{{TRUE}} + + NestedPrimitive c; + c = b; + + clang_analyzer_eval(c.values[1][0] == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(c.values[1][1] == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(c.values[1][2] == 3); // expected-warning{{TRUE}} + } + + struct POD { + IntWrapper values[3]; + }; + + void testPOD() { + POD a = { { { 1 }, { 2 }, { 3 } } }; + + clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}} + + POD b = a; + + clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{TRUE}} + + POD c; + c = b; + + clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{TRUE}} + } + + struct NestedPOD { + IntWrapper values[2][3]; + }; + + void testNestedPOD() { + NestedPOD a = { { { { 0 }, { 0 }, { 0 } }, { { 1 }, { 2 }, { 3 } } } }; + + clang_analyzer_eval(a.values[1][0].x == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(a.values[1][1].x == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(a.values[1][2].x == 3); // expected-warning{{TRUE}} + + NestedPOD b = a; + + clang_analyzer_eval(b.values[1][0].x == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(b.values[1][1].x == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(b.values[1][2].x == 3); // expected-warning{{TRUE}} + + NestedPOD c; + c = b; + + clang_analyzer_eval(c.values[1][0].x == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(c.values[1][1].x == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(c.values[1][2].x == 3); // expected-warning{{TRUE}} + } + + struct NonPOD { + NonPODIntWrapper values[3]; + }; + + void testNonPOD() { + NonPOD a; + a.values[0].x = 1; + a.values[1].x = 2; + a.values[2].x = 3; + + clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}} + + NonPOD b = a; + + clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{UNKNOWN}} + + NonPOD c; + c = b; + + clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{UNKNOWN}} + } + + struct NestedNonPOD { + NonPODIntWrapper values[2][3]; + }; + + void testNestedNonPOD() { + NestedNonPOD a; + a.values[0][0].x = 0; + a.values[0][1].x = 0; + a.values[0][2].x = 0; + a.values[1][0].x = 1; + a.values[1][1].x = 2; + a.values[1][2].x = 3; + + clang_analyzer_eval(a.values[1][0].x == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(a.values[1][1].x == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(a.values[1][2].x == 3); // expected-warning{{TRUE}} + + NestedNonPOD b = a; + + clang_analyzer_eval(b.values[1][0].x == 1); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(b.values[1][1].x == 2); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(b.values[1][2].x == 3); // expected-warning{{UNKNOWN}} + + NestedNonPOD c; + c = b; + + clang_analyzer_eval(c.values[1][0].x == 1); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(c.values[1][1].x == 2); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(c.values[1][2].x == 3); // expected-warning{{UNKNOWN}} + } + + struct NonPODDefaulted { + NonPODIntWrapper values[3]; + + NonPODDefaulted() = default; + NonPODDefaulted(const NonPODDefaulted &) = default; + NonPODDefaulted &operator=(const NonPODDefaulted &) = default; + }; + + void testNonPODDefaulted() { + NonPODDefaulted a; + a.values[0].x = 1; + a.values[1].x = 2; + a.values[2].x = 3; + + clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}} + + NonPODDefaulted b = a; + + clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{UNKNOWN}} + + NonPODDefaulted c; + c = b; + + clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{UNKNOWN}} + } +}; |