1// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s 2 3void clang_analyzer_eval(bool); 4 5struct A { 6 int x; 7 void foo() const; 8 void bar(); 9}; 10 11struct B { 12 mutable int mut; 13 void foo() const; 14}; 15 16struct C { 17 int *p; 18 void foo() const; 19}; 20 21struct MutBase { 22 mutable int b_mut; 23}; 24 25struct MutDerived : MutBase { 26 void foo() const; 27}; 28 29struct PBase { 30 int *p; 31}; 32 33struct PDerived : PBase { 34 void foo() const; 35}; 36 37struct Inner { 38 int x; 39 int *p; 40 void bar() const; 41}; 42 43struct Outer { 44 int x; 45 Inner in; 46 void foo() const; 47}; 48 49void checkThatConstMethodWithoutDefinitionDoesNotInvalidateObject() { 50 A t; 51 t.x = 3; 52 t.foo(); 53 clang_analyzer_eval(t.x == 3); // expected-warning{{TRUE}} 54 // Test non-const does invalidate 55 t.bar(); 56 clang_analyzer_eval(t.x); // expected-warning{{UNKNOWN}} 57} 58 59void checkThatConstMethodDoesInvalidateMutableFields() { 60 B t; 61 t.mut = 4; 62 t.foo(); 63 clang_analyzer_eval(t.mut); // expected-warning{{UNKNOWN}} 64} 65 66void checkThatConstMethodDoesInvalidatePointedAtMemory() { 67 int x = 1; 68 C t; 69 t.p = &x; 70 t.foo(); 71 clang_analyzer_eval(x); // expected-warning{{UNKNOWN}} 72 clang_analyzer_eval(t.p == &x); // expected-warning{{TRUE}} 73} 74 75void checkThatConstMethodDoesInvalidateInheritedMutableFields() { 76 MutDerived t; 77 t.b_mut = 4; 78 t.foo(); 79 clang_analyzer_eval(t.b_mut); // expected-warning{{UNKNOWN}} 80} 81 82void checkThatConstMethodDoesInvalidateInheritedPointedAtMemory() { 83 int x = 1; 84 PDerived t; 85 t.p = &x; 86 t.foo(); 87 clang_analyzer_eval(x); // expected-warning{{UNKNOWN}} 88 clang_analyzer_eval(t.p == &x); // expected-warning{{TRUE}} 89} 90 91void checkThatConstMethodDoesInvalidateContainedPointedAtMemory() { 92 int x = 1; 93 Outer t; 94 t.x = 2; 95 t.in.p = &x; 96 t.foo(); 97 clang_analyzer_eval(x); // expected-warning{{UNKNOWN}} 98 clang_analyzer_eval(t.x == 2); // expected-warning{{TRUE}} 99 clang_analyzer_eval(t.in.p == &x); // expected-warning{{TRUE}} 100} 101 102void checkThatContainedConstMethodDoesNotInvalidateObjects() { 103 Outer t; 104 t.x = 1; 105 t.in.x = 2; 106 t.in.bar(); 107 clang_analyzer_eval(t.x == 1); // expected-warning{{TRUE}} 108 clang_analyzer_eval(t.in.x == 2); // expected-warning{{TRUE}} 109} 110 111// --- Versions of the above tests where the const method is inherited --- // 112 113struct B1 { 114 void foo() const; 115}; 116 117struct D1 : public B1 { 118 int x; 119}; 120 121struct D2 : public B1 { 122 mutable int mut; 123}; 124 125struct D3 : public B1 { 126 int *p; 127}; 128 129struct DInner : public B1 { 130 int x; 131 int *p; 132}; 133 134struct DOuter : public B1 { 135 int x; 136 DInner in; 137}; 138 139void checkThatInheritedConstMethodDoesNotInvalidateObject() { 140 D1 t; 141 t.x = 1; 142 t.foo(); 143 clang_analyzer_eval(t.x == 1); // expected-warning{{TRUE}} 144} 145 146void checkThatInheritedConstMethodDoesInvalidateMutableFields() { 147 D2 t; 148 t.mut = 1; 149 t.foo(); 150 clang_analyzer_eval(t.mut); // expected-warning{{UNKNOWN}} 151} 152 153void checkThatInheritedConstMethodDoesInvalidatePointedAtMemory() { 154 int x = 1; 155 D3 t; 156 t.p = &x; 157 t.foo(); 158 clang_analyzer_eval(x); // expected-warning{{UNKNOWN}} 159 clang_analyzer_eval(t.p == &x); // expected-warning{{TRUE}} 160} 161 162void checkThatInheritedConstMethodDoesInvalidateContainedPointedAtMemory() { 163 int x = 1; 164 DOuter t; 165 t.x = 2; 166 t.in.x = 3; 167 t.in.p = &x; 168 t.foo(); 169 clang_analyzer_eval(x); // expected-warning{{UNKNOWN}} 170 clang_analyzer_eval(t.x == 2); // expected-warning{{TRUE}} 171 clang_analyzer_eval(t.in.x == 3); // expected-warning{{TRUE}} 172 clang_analyzer_eval(t.in.p == &x); // expected-warning{{TRUE}} 173} 174 175void checkThatInheritedContainedConstMethodDoesNotInvalidateObjects() { 176 DOuter t; 177 t.x = 1; 178 t.in.x = 2; 179 t.in.foo(); 180 clang_analyzer_eval(t.x == 1); // expected-warning{{TRUE}} 181 clang_analyzer_eval(t.in.x == 2); // expected-warning{{TRUE}} 182} 183 184// --- PR21606 --- // 185 186struct s1 { 187 void g(const int *i) const; 188}; 189 190struct s2 { 191 void f(int *i) { 192 m_i = i; 193 m_s.g(m_i); 194 if (m_i) 195 *i = 42; // no-warning 196 } 197 198 int *m_i; 199 s1 m_s; 200}; 201 202void PR21606() 203{ 204 s2().f(0); 205} 206 207// --- PR25392 --- // 208 209struct HasConstMemberFunction { 210public: 211 void constMemberFunction() const; 212}; 213 214HasConstMemberFunction hasNoReturn() { } // expected-warning {{control reaches end of non-void function}} 215 216void testUnknownWithConstMemberFunction() { 217 hasNoReturn().constMemberFunction(); 218} 219 220void testNonRegionLocWithConstMemberFunction() { 221 (*((HasConstMemberFunction *)(&&label))).constMemberFunction(); 222 223 label: return; 224} 225 226// FIXME 227// When there is a circular reference to an object and a const method is called 228// the object is not invalidated because TK_PreserveContents has already been 229// set. 230struct Outer2; 231 232struct InnerWithRef { 233 Outer2 *ref; 234}; 235 236struct Outer2 { 237 int x; 238 InnerWithRef in; 239 void foo() const; 240}; 241 242void checkThatConstMethodCallDoesInvalidateObjectForCircularReferences() { 243 Outer2 t; 244 t.x = 1; 245 t.in.ref = &t; 246 t.foo(); 247 // FIXME: Should be UNKNOWN. 248 clang_analyzer_eval(t.x); // expected-warning{{TRUE}} 249} 250