1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s 2 3 void clang_analyzer_eval(bool); 4 5 struct A { 6 int x; 7 void foo() const; 8 void bar(); 9 }; 10 11 struct B { 12 mutable int mut; 13 void foo() const; 14 }; 15 16 struct C { 17 int *p; 18 void foo() const; 19 }; 20 21 struct MutBase { 22 mutable int b_mut; 23 }; 24 25 struct MutDerived : MutBase { 26 void foo() const; 27 }; 28 29 struct PBase { 30 int *p; 31 }; 32 33 struct PDerived : PBase { 34 void foo() const; 35 }; 36 37 struct Inner { 38 int x; 39 int *p; 40 void bar() const; 41 }; 42 43 struct Outer { 44 int x; 45 Inner in; 46 void foo() const; 47 }; 48 checkThatConstMethodWithoutDefinitionDoesNotInvalidateObject()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 checkThatConstMethodDoesInvalidateMutableFields()59void checkThatConstMethodDoesInvalidateMutableFields() { 60 B t; 61 t.mut = 4; 62 t.foo(); 63 clang_analyzer_eval(t.mut); // expected-warning{{UNKNOWN}} 64 } 65 checkThatConstMethodDoesInvalidatePointedAtMemory()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 checkThatConstMethodDoesInvalidateInheritedMutableFields()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 checkThatConstMethodDoesInvalidateInheritedPointedAtMemory()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 checkThatConstMethodDoesInvalidateContainedPointedAtMemory()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 checkThatContainedConstMethodDoesNotInvalidateObjects()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 113 struct B1 { 114 void foo() const; 115 }; 116 117 struct D1 : public B1 { 118 int x; 119 }; 120 121 struct D2 : public B1 { 122 mutable int mut; 123 }; 124 125 struct D3 : public B1 { 126 int *p; 127 }; 128 129 struct DInner : public B1 { 130 int x; 131 int *p; 132 }; 133 134 struct DOuter : public B1 { 135 int x; 136 DInner in; 137 }; 138 checkThatInheritedConstMethodDoesNotInvalidateObject()139void checkThatInheritedConstMethodDoesNotInvalidateObject() { 140 D1 t; 141 t.x = 1; 142 t.foo(); 143 clang_analyzer_eval(t.x == 1); // expected-warning{{TRUE}} 144 } 145 checkThatInheritedConstMethodDoesInvalidateMutableFields()146void checkThatInheritedConstMethodDoesInvalidateMutableFields() { 147 D2 t; 148 t.mut = 1; 149 t.foo(); 150 clang_analyzer_eval(t.mut); // expected-warning{{UNKNOWN}} 151 } 152 checkThatInheritedConstMethodDoesInvalidatePointedAtMemory()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 checkThatInheritedConstMethodDoesInvalidateContainedPointedAtMemory()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 checkThatInheritedContainedConstMethodDoesNotInvalidateObjects()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 186 struct s1 { 187 void g(const int *i) const; 188 }; 189 190 struct s2 { fs2191 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 PR21606()202void PR21606() 203 { 204 s2().f(0); 205 } 206 207 // --- PR25392 --- // 208 209 struct HasConstMemberFunction { 210 public: 211 void constMemberFunction() const; 212 }; 213 hasNoReturn()214HasConstMemberFunction hasNoReturn() { } // expected-warning {{control reaches end of non-void function}} 215 testUnknownWithConstMemberFunction()216void testUnknownWithConstMemberFunction() { 217 hasNoReturn().constMemberFunction(); 218 } 219 testNonRegionLocWithConstMemberFunction()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. 230 struct Outer2; 231 232 struct InnerWithRef { 233 Outer2 *ref; 234 }; 235 236 struct Outer2 { 237 int x; 238 InnerWithRef in; 239 void foo() const; 240 }; 241 checkThatConstMethodCallDoesInvalidateObjectForCircularReferences()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