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