1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++03 %s 2 // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++11 %s 3 4 extern bool clang_analyzer_eval(bool); 5 6 struct Trivial { 7 Trivial(int x) : value(x) {} 8 int value; 9 }; 10 11 struct NonTrivial : public Trivial { 12 NonTrivial(int x) : Trivial(x) {} 13 ~NonTrivial(); 14 }; 15 16 17 Trivial getTrivial() { 18 return Trivial(42); // no-warning 19 } 20 21 const Trivial &getTrivialRef() { 22 return Trivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'Trivial' returned to caller}} 23 } 24 25 26 NonTrivial getNonTrivial() { 27 return NonTrivial(42); // no-warning 28 } 29 30 const NonTrivial &getNonTrivialRef() { 31 return NonTrivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'NonTrivial' returned to caller}} 32 } 33 34 namespace rdar13265460 { 35 struct TrivialSubclass : public Trivial { 36 TrivialSubclass(int x) : Trivial(x), anotherValue(-x) {} 37 int anotherValue; 38 }; 39 40 TrivialSubclass getTrivialSub() { 41 TrivialSubclass obj(1); 42 obj.value = 42; 43 obj.anotherValue = -42; 44 return obj; 45 } 46 47 void testImmediate() { 48 TrivialSubclass obj = getTrivialSub(); 49 50 clang_analyzer_eval(obj.value == 42); // expected-warning{{TRUE}} 51 clang_analyzer_eval(obj.anotherValue == -42); // expected-warning{{TRUE}} 52 53 clang_analyzer_eval(getTrivialSub().value == 42); // expected-warning{{TRUE}} 54 clang_analyzer_eval(getTrivialSub().anotherValue == -42); // expected-warning{{TRUE}} 55 } 56 57 void testMaterializeTemporaryExpr() { 58 const TrivialSubclass &ref = getTrivialSub(); 59 clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}} 60 61 const Trivial &baseRef = getTrivialSub(); 62 clang_analyzer_eval(baseRef.value == 42); // expected-warning{{TRUE}} 63 } 64 } 65 66 namespace rdar13281951 { 67 struct Derived : public Trivial { 68 Derived(int value) : Trivial(value), value2(-value) {} 69 int value2; 70 }; 71 72 void test() { 73 Derived obj(1); 74 obj.value = 42; 75 const Trivial * const &pointerRef = &obj; 76 clang_analyzer_eval(pointerRef->value == 42); // expected-warning{{TRUE}} 77 } 78 } 79 80 namespace compound_literals { 81 struct POD { 82 int x, y; 83 }; 84 struct HasCtor { 85 HasCtor(int x, int y) : x(x), y(y) {} 86 int x, y; 87 }; 88 struct HasDtor { 89 int x, y; 90 ~HasDtor(); 91 }; 92 struct HasCtorDtor { 93 HasCtorDtor(int x, int y) : x(x), y(y) {} 94 ~HasCtorDtor(); 95 int x, y; 96 }; 97 98 void test() { 99 clang_analyzer_eval(((POD){1, 42}).y == 42); // expected-warning{{TRUE}} 100 clang_analyzer_eval(((HasDtor){1, 42}).y == 42); // expected-warning{{TRUE}} 101 102 #if __cplusplus >= 201103L 103 clang_analyzer_eval(((HasCtor){1, 42}).y == 42); // expected-warning{{TRUE}} 104 105 // FIXME: should be TRUE, but we don't inline the constructors of 106 // temporaries because we can't model their destructors yet. 107 clang_analyzer_eval(((HasCtorDtor){1, 42}).y == 42); // expected-warning{{UNKNOWN}} 108 #endif 109 } 110 } 111 112 namespace destructors { 113 void testPR16664Crash() { 114 struct Dtor { 115 ~Dtor(); 116 }; 117 extern bool coin(); 118 extern bool check(const Dtor &); 119 120 // Don't crash here. 121 if (coin() && (coin() || coin() || check(Dtor()))) { 122 Dtor(); 123 } 124 } 125 126 void testConsistency(int i) { 127 struct NoReturnDtor { 128 ~NoReturnDtor() __attribute__((noreturn)); 129 }; 130 extern bool check(const NoReturnDtor &); 131 132 if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor()))) 133 clang_analyzer_eval(true); // expected-warning{{TRUE}} 134 135 if (i != 5) 136 return; 137 if (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) { 138 // FIXME: Should be no-warning, because the noreturn destructor should 139 // fire on all paths. 140 clang_analyzer_eval(true); // expected-warning{{TRUE}} 141 } 142 } 143 } 144 145 void testStaticMaterializeTemporaryExpr() { 146 static const Trivial &ref = getTrivial(); 147 clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}} 148 149 static const Trivial &directRef = Trivial(42); 150 clang_analyzer_eval(directRef.value == 42); // expected-warning{{TRUE}} 151 152 #if __has_feature(cxx_thread_local) 153 thread_local static const Trivial &threadRef = getTrivial(); 154 clang_analyzer_eval(threadRef.value == 42); // expected-warning{{TRUE}} 155 156 thread_local static const Trivial &threadDirectRef = Trivial(42); 157 clang_analyzer_eval(threadDirectRef.value == 42); // expected-warning{{TRUE}} 158 #endif 159 } 160