283 lines · cpp
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s2 3template <class T> void clang_analyzer_dump(T);4void clang_analyzer_eval(bool);5 6void usePointer(int * const *);7void useReference(int * const &);8 9void testPointer() {10 int x;11 int *p;12 13 p = &x;14 x = 42;15 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}16 usePointer(&p);17 clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}18 19 p = &x;20 x = 42;21 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}22 useReference(p);23 clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}24 25 int * const cp1 = &x;26 x = 42;27 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}28 usePointer(&cp1);29 clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}30 31 int * const cp2 = &x;32 x = 42;33 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}34 useReference(cp2);35 clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}36}37 38 39struct Wrapper {40 int *ptr;41};42 43void useStruct(Wrapper &w);44void useConstStruct(const Wrapper &w);45 46void testPointerStruct() {47 int x;48 Wrapper w;49 50 w.ptr = &x;51 x = 42;52 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}53 useStruct(w);54 clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}55 56 w.ptr = &x;57 x = 42;58 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}59 useConstStruct(w);60 clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}61}62 63 64struct RefWrapper {65 int &ref;66};67 68void useStruct(RefWrapper &w);69void useConstStruct(const RefWrapper &w);70 71void testReferenceStruct() {72 int x;73 RefWrapper w = { x };74 75 x = 42;76 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}77 useStruct(w);78 clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}79}80 81// FIXME: This test is split into two functions because region invalidation82// does not preserve reference bindings.83void testConstReferenceStruct() {84 int x;85 RefWrapper w = { x };86 87 x = 42;88 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}89 useConstStruct(w);90 clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}91}92 93 94int usePointerPure(int * const *) __attribute__((pure));95int usePointerConst(int * const *) __attribute__((const));96 97void testPureConst() {98 extern int global;99 int x;100 int *p;101 102 p = &x;103 x = 42;104 global = -5;105 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}106 clang_analyzer_eval(global == -5); // expected-warning{{TRUE}}107 108 (void)usePointerPure(&p);109 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}110 clang_analyzer_eval(global == -5); // expected-warning{{TRUE}}111 112 (void)usePointerConst(&p);113 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}114 clang_analyzer_eval(global == -5); // expected-warning{{TRUE}}115 116 usePointer(&p);117 clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}118 clang_analyzer_eval(global == -5); // expected-warning{{UNKNOWN}}119}120 121 122struct PlainStruct {123 int x, y;124 mutable int z;125};126 127PlainStruct glob;128 129void useAnything(void *);130void useAnythingConst(const void *);131 132void testInvalidationThroughBaseRegionPointer() {133 PlainStruct s1;134 s1.x = 1;135 s1.z = 1;136 clang_analyzer_eval(s1.x == 1); // expected-warning{{TRUE}}137 clang_analyzer_eval(s1.z == 1); // expected-warning{{TRUE}}138 // Not only passing a structure pointer through const pointer parameter,139 // but also passing a field pointer through const pointer parameter140 // should preserve the contents of the structure.141 useAnythingConst(&(s1.y));142 clang_analyzer_eval(s1.x == 1); // expected-warning{{TRUE}}143 // FIXME: Should say "UNKNOWN", because it is not uncommon to144 // modify a mutable member variable through const pointer.145 clang_analyzer_eval(s1.z == 1); // expected-warning{{TRUE}}146 useAnything(&(s1.y));147 clang_analyzer_eval(s1.x == 1); // expected-warning{{UNKNOWN}}148}149 150 151void useFirstConstSecondNonConst(const void *x, void *y);152void useFirstNonConstSecondConst(void *x, const void *y);153 154void testMixedConstNonConstCalls() {155 PlainStruct s2;156 s2.x = 1;157 useFirstConstSecondNonConst(&(s2.x), &(s2.y));158 clang_analyzer_eval(s2.x == 1); // expected-warning{{UNKNOWN}}159 s2.x = 1;160 useFirstNonConstSecondConst(&(s2.x), &(s2.y));161 clang_analyzer_eval(s2.x == 1); // expected-warning{{UNKNOWN}}162 s2.y = 1;163 useFirstConstSecondNonConst(&(s2.x), &(s2.y));164 clang_analyzer_eval(s2.y == 1); // expected-warning{{UNKNOWN}}165 s2.y = 1;166 useFirstNonConstSecondConst(&(s2.x), &(s2.y));167 clang_analyzer_eval(s2.y == 1); // expected-warning{{UNKNOWN}}168}169 170namespace std {171class Opaque {172public:173 Opaque();174 int nested_member;175};176} // namespace std177 178struct StdWrappingOpaque {179 std::Opaque o; // first member180 int uninit;181};182struct StdWrappingOpaqueSwapped {183 int uninit; // first member184 std::Opaque o;185};186 187int testStdCtorDoesNotInvalidateParentObject() {188 StdWrappingOpaque obj;189 int x = obj.o.nested_member; // no-garbage: std::Opaque::ctor might initialized this190 int y = obj.uninit; // FIXME: We should have a garbage read here. Read the details.191 // As the first member ("obj.o") is invalidated, a conjured default binding is bound192 // to the offset 0 within cluster "obj", and this masks every uninitialized fields193 // that follows. We need a better store with extents to fix this.194 return x + y;195}196 197int testStdCtorDoesNotInvalidateParentObjectSwapped() {198 StdWrappingOpaqueSwapped obj;199 int x = obj.o.nested_member; // no-garbage: std::Opaque::ctor might initialized this200 int y = obj.uninit; // expected-warning {{Assigned value is uninitialized}}201 return x + y;202}203 204class UserProvidedOpaque {205public:206 UserProvidedOpaque(); // might reinterpret_cast(this)207 int nested_member;208};209 210struct WrappingUserProvidedOpaque {211 UserProvidedOpaque o; // first member212 int uninit;213};214struct WrappingUserProvidedOpaqueSwapped {215 int uninit; // first member216 UserProvidedOpaque o;217};218 219int testUserProvidedCtorInvalidatesParentObject() {220 WrappingUserProvidedOpaque obj;221 int x = obj.o.nested_member; // no-garbage: UserProvidedOpaque::ctor might initialized this222 int y = obj.uninit; // no-garbage: UserProvidedOpaque::ctor might reinterpret_cast(this) and write to the "uninit" member.223 return x + y;224}225 226int testUserProvidedCtorInvalidatesParentObjectSwapped() {227 WrappingUserProvidedOpaqueSwapped obj;228 int x = obj.o.nested_member; // no-garbage: same as above229 int y = obj.uninit; // no-garbage: same as above230 return x + y;231}232 233struct WrappingStdWrappingOpaqueOuterInits {234 int first = 1;235 std::Opaque second;236 int third = 3;237 WrappingStdWrappingOpaqueOuterInits() {238 clang_analyzer_dump(first); // expected-warning {{1 S32b}}239 clang_analyzer_dump(second.nested_member); // expected-warning {{derived_}}240 clang_analyzer_dump(third); // expected-warning {{3 S32b}}241 }242};243 244struct WrappingUserProvidedOpaqueOuterInits {245 int first = 1; // Potentially overwritten by UserProvidedOpaque::ctor246 UserProvidedOpaque second; // Invalidates the object so far.247 int third = 3; // Happens after UserProvidedOpaque::ctor, thus preserved!248 WrappingUserProvidedOpaqueOuterInits() {249 clang_analyzer_dump(first); // expected-warning {{derived_}}250 clang_analyzer_dump(second.nested_member); // expected-warning {{derived_}}251 clang_analyzer_dump(third); // expected-warning {{3 S32b}}252 }253};254 255extern "C++" {256namespace std {257inline namespace v1 {258namespace custom_ranges {259struct Fancy {260struct iterator {261struct Opaque {262 Opaque();263 int nested_member;264}; // struct Opaque265}; // struct iterator266}; // struct Fancy267} // namespace custom_ranges268} // namespace v1269} // namespace std270} // extern "C++"271 272struct StdWrappingFancyOpaque {273 int uninit;274 std::custom_ranges::Fancy::iterator::Opaque o;275};276 277int testNestedStdNamespacesAndRecords() {278 StdWrappingFancyOpaque obj;279 int x = obj.o.nested_member; // no-garbage: ctor280 int y = obj.uninit; // expected-warning {{Assigned value is uninitialized}}281 return x + y;282}283