1a393e68bSGeorge Karpenkov // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
24f770deeSDevin Coughlin 
34f770deeSDevin Coughlin void clang_analyzer_eval(bool);
44f770deeSDevin Coughlin 
54f770deeSDevin Coughlin struct A {
64f770deeSDevin Coughlin   int x;
74f770deeSDevin Coughlin   void foo() const;
84f770deeSDevin Coughlin   void bar();
9f74ef4b1SArtem Dergachev 
testImplicitThisSyntaxA10f74ef4b1SArtem Dergachev   void testImplicitThisSyntax() {
11f74ef4b1SArtem Dergachev     x = 3;
12f74ef4b1SArtem Dergachev     foo();
13f74ef4b1SArtem Dergachev     clang_analyzer_eval(x == 3); // expected-warning{{TRUE}}
14f74ef4b1SArtem Dergachev     bar();
15f74ef4b1SArtem Dergachev     clang_analyzer_eval(x == 3); // expected-warning{{UNKNOWN}}
16f74ef4b1SArtem Dergachev   }
174f770deeSDevin Coughlin };
184f770deeSDevin Coughlin 
194f770deeSDevin Coughlin struct B {
204f770deeSDevin Coughlin   mutable int mut;
214f770deeSDevin Coughlin   void foo() const;
224f770deeSDevin Coughlin };
234f770deeSDevin Coughlin 
244f770deeSDevin Coughlin struct C {
254f770deeSDevin Coughlin   int *p;
264f770deeSDevin Coughlin   void foo() const;
274f770deeSDevin Coughlin };
284f770deeSDevin Coughlin 
294f770deeSDevin Coughlin struct MutBase {
304f770deeSDevin Coughlin   mutable int b_mut;
314f770deeSDevin Coughlin };
324f770deeSDevin Coughlin 
334f770deeSDevin Coughlin struct MutDerived : MutBase {
344f770deeSDevin Coughlin   void foo() const;
354f770deeSDevin Coughlin };
364f770deeSDevin Coughlin 
374f770deeSDevin Coughlin struct PBase {
384f770deeSDevin Coughlin   int *p;
394f770deeSDevin Coughlin };
404f770deeSDevin Coughlin 
414f770deeSDevin Coughlin struct PDerived : PBase {
424f770deeSDevin Coughlin   void foo() const;
434f770deeSDevin Coughlin };
444f770deeSDevin Coughlin 
454f770deeSDevin Coughlin struct Inner {
464f770deeSDevin Coughlin   int x;
474f770deeSDevin Coughlin   int *p;
484f770deeSDevin Coughlin   void bar() const;
494f770deeSDevin Coughlin };
504f770deeSDevin Coughlin 
514f770deeSDevin Coughlin struct Outer {
524f770deeSDevin Coughlin   int x;
534f770deeSDevin Coughlin   Inner in;
544f770deeSDevin Coughlin   void foo() const;
554f770deeSDevin Coughlin };
564f770deeSDevin Coughlin 
checkThatConstMethodWithoutDefinitionDoesNotInvalidateObject()574f770deeSDevin Coughlin void checkThatConstMethodWithoutDefinitionDoesNotInvalidateObject() {
584f770deeSDevin Coughlin   A t;
594f770deeSDevin Coughlin   t.x = 3;
604f770deeSDevin Coughlin   t.foo();
614f770deeSDevin Coughlin   clang_analyzer_eval(t.x == 3); // expected-warning{{TRUE}}
624f770deeSDevin Coughlin   // Test non-const does invalidate
634f770deeSDevin Coughlin   t.bar();
644f770deeSDevin Coughlin   clang_analyzer_eval(t.x); // expected-warning{{UNKNOWN}}
654f770deeSDevin Coughlin }
664f770deeSDevin Coughlin 
checkThatConstMethodDoesInvalidateMutableFields()674f770deeSDevin Coughlin void checkThatConstMethodDoesInvalidateMutableFields() {
684f770deeSDevin Coughlin   B t;
694f770deeSDevin Coughlin   t.mut = 4;
704f770deeSDevin Coughlin   t.foo();
714f770deeSDevin Coughlin   clang_analyzer_eval(t.mut); // expected-warning{{UNKNOWN}}
724f770deeSDevin Coughlin }
734f770deeSDevin Coughlin 
checkThatConstMethodDoesInvalidatePointedAtMemory()744f770deeSDevin Coughlin void checkThatConstMethodDoesInvalidatePointedAtMemory() {
754f770deeSDevin Coughlin   int x = 1;
764f770deeSDevin Coughlin   C t;
774f770deeSDevin Coughlin   t.p = &x;
784f770deeSDevin Coughlin   t.foo();
794f770deeSDevin Coughlin   clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}
804f770deeSDevin Coughlin   clang_analyzer_eval(t.p == &x); // expected-warning{{TRUE}}
814f770deeSDevin Coughlin }
824f770deeSDevin Coughlin 
checkThatConstMethodDoesInvalidateInheritedMutableFields()834f770deeSDevin Coughlin void checkThatConstMethodDoesInvalidateInheritedMutableFields() {
844f770deeSDevin Coughlin   MutDerived t;
854f770deeSDevin Coughlin   t.b_mut = 4;
864f770deeSDevin Coughlin   t.foo();
874f770deeSDevin Coughlin   clang_analyzer_eval(t.b_mut); // expected-warning{{UNKNOWN}}
884f770deeSDevin Coughlin }
894f770deeSDevin Coughlin 
checkThatConstMethodDoesInvalidateInheritedPointedAtMemory()904f770deeSDevin Coughlin void checkThatConstMethodDoesInvalidateInheritedPointedAtMemory() {
914f770deeSDevin Coughlin   int x = 1;
924f770deeSDevin Coughlin   PDerived t;
934f770deeSDevin Coughlin   t.p = &x;
944f770deeSDevin Coughlin   t.foo();
954f770deeSDevin Coughlin   clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}
964f770deeSDevin Coughlin   clang_analyzer_eval(t.p == &x); // expected-warning{{TRUE}}
974f770deeSDevin Coughlin }
984f770deeSDevin Coughlin 
checkThatConstMethodDoesInvalidateContainedPointedAtMemory()994f770deeSDevin Coughlin void checkThatConstMethodDoesInvalidateContainedPointedAtMemory() {
1004f770deeSDevin Coughlin   int x = 1;
1014f770deeSDevin Coughlin   Outer t;
1024f770deeSDevin Coughlin   t.x = 2;
1034f770deeSDevin Coughlin   t.in.p = &x;
1044f770deeSDevin Coughlin   t.foo();
1054f770deeSDevin Coughlin   clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}
1064f770deeSDevin Coughlin   clang_analyzer_eval(t.x == 2); // expected-warning{{TRUE}}
1074f770deeSDevin Coughlin   clang_analyzer_eval(t.in.p == &x); // expected-warning{{TRUE}}
1084f770deeSDevin Coughlin }
1094f770deeSDevin Coughlin 
checkThatContainedConstMethodDoesNotInvalidateObjects()1104f770deeSDevin Coughlin void checkThatContainedConstMethodDoesNotInvalidateObjects() {
1114f770deeSDevin Coughlin   Outer t;
1124f770deeSDevin Coughlin   t.x = 1;
1134f770deeSDevin Coughlin   t.in.x = 2;
1144f770deeSDevin Coughlin   t.in.bar();
1154f770deeSDevin Coughlin   clang_analyzer_eval(t.x == 1); // expected-warning{{TRUE}}
1164f770deeSDevin Coughlin   clang_analyzer_eval(t.in.x == 2); // expected-warning{{TRUE}}
1174f770deeSDevin Coughlin }
1184f770deeSDevin Coughlin 
checkPointerTypedThisExpression(A * a)119f74ef4b1SArtem Dergachev void checkPointerTypedThisExpression(A *a) {
120f74ef4b1SArtem Dergachev   a->x = 3;
121f74ef4b1SArtem Dergachev   a->foo();
122f74ef4b1SArtem Dergachev   clang_analyzer_eval(a->x == 3); // expected-warning{{TRUE}}
123f74ef4b1SArtem Dergachev   a->bar();
124f74ef4b1SArtem Dergachev   clang_analyzer_eval(a->x == 3); // expected-warning{{UNKNOWN}}
125f74ef4b1SArtem Dergachev }
126f74ef4b1SArtem Dergachev 
checkReferenceTypedThisExpression(A & a)127f74ef4b1SArtem Dergachev void checkReferenceTypedThisExpression(A &a) {
128f74ef4b1SArtem Dergachev   a.x = 3;
129f74ef4b1SArtem Dergachev   a.foo();
130f74ef4b1SArtem Dergachev   clang_analyzer_eval(a.x == 3); // expected-warning{{TRUE}}
131f74ef4b1SArtem Dergachev   a.bar();
132f74ef4b1SArtem Dergachev   clang_analyzer_eval(a.x == 3); // expected-warning{{UNKNOWN}}
133f74ef4b1SArtem Dergachev }
134f74ef4b1SArtem Dergachev 
1354f770deeSDevin Coughlin // --- Versions of the above tests where the const method is inherited --- //
1364f770deeSDevin Coughlin 
1374f770deeSDevin Coughlin struct B1 {
1384f770deeSDevin Coughlin   void foo() const;
1394f770deeSDevin Coughlin };
1404f770deeSDevin Coughlin 
1414f770deeSDevin Coughlin struct D1 : public B1 {
1424f770deeSDevin Coughlin   int x;
1434f770deeSDevin Coughlin };
1444f770deeSDevin Coughlin 
1454f770deeSDevin Coughlin struct D2 : public B1 {
1464f770deeSDevin Coughlin   mutable int mut;
1474f770deeSDevin Coughlin };
1484f770deeSDevin Coughlin 
1494f770deeSDevin Coughlin struct D3 : public B1 {
1504f770deeSDevin Coughlin   int *p;
1514f770deeSDevin Coughlin };
1524f770deeSDevin Coughlin 
1534f770deeSDevin Coughlin struct DInner : public B1 {
1544f770deeSDevin Coughlin   int x;
1554f770deeSDevin Coughlin   int *p;
1564f770deeSDevin Coughlin };
1574f770deeSDevin Coughlin 
1584f770deeSDevin Coughlin struct DOuter : public B1 {
1594f770deeSDevin Coughlin   int x;
1604f770deeSDevin Coughlin   DInner in;
1614f770deeSDevin Coughlin };
1624f770deeSDevin Coughlin 
checkThatInheritedConstMethodDoesNotInvalidateObject()1634f770deeSDevin Coughlin void checkThatInheritedConstMethodDoesNotInvalidateObject() {
1644f770deeSDevin Coughlin   D1 t;
1654f770deeSDevin Coughlin   t.x = 1;
1664f770deeSDevin Coughlin   t.foo();
1674f770deeSDevin Coughlin   clang_analyzer_eval(t.x == 1); // expected-warning{{TRUE}}
1684f770deeSDevin Coughlin }
1694f770deeSDevin Coughlin 
checkThatInheritedConstMethodDoesInvalidateMutableFields()1704f770deeSDevin Coughlin void checkThatInheritedConstMethodDoesInvalidateMutableFields() {
1714f770deeSDevin Coughlin   D2 t;
1724f770deeSDevin Coughlin   t.mut = 1;
1734f770deeSDevin Coughlin   t.foo();
1744f770deeSDevin Coughlin   clang_analyzer_eval(t.mut); // expected-warning{{UNKNOWN}}
1754f770deeSDevin Coughlin }
1764f770deeSDevin Coughlin 
checkThatInheritedConstMethodDoesInvalidatePointedAtMemory()1774f770deeSDevin Coughlin void checkThatInheritedConstMethodDoesInvalidatePointedAtMemory() {
1784f770deeSDevin Coughlin   int x = 1;
1794f770deeSDevin Coughlin   D3 t;
1804f770deeSDevin Coughlin   t.p = &x;
1814f770deeSDevin Coughlin   t.foo();
1824f770deeSDevin Coughlin   clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}
1834f770deeSDevin Coughlin   clang_analyzer_eval(t.p == &x); // expected-warning{{TRUE}}
1844f770deeSDevin Coughlin }
1854f770deeSDevin Coughlin 
checkThatInheritedConstMethodDoesInvalidateContainedPointedAtMemory()1864f770deeSDevin Coughlin void checkThatInheritedConstMethodDoesInvalidateContainedPointedAtMemory() {
1874f770deeSDevin Coughlin   int x = 1;
1884f770deeSDevin Coughlin   DOuter t;
1894f770deeSDevin Coughlin   t.x = 2;
1904f770deeSDevin Coughlin   t.in.x = 3;
1914f770deeSDevin Coughlin   t.in.p = &x;
1924f770deeSDevin Coughlin   t.foo();
1934f770deeSDevin Coughlin   clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}
1944f770deeSDevin Coughlin   clang_analyzer_eval(t.x == 2); // expected-warning{{TRUE}}
1954f770deeSDevin Coughlin   clang_analyzer_eval(t.in.x == 3); // expected-warning{{TRUE}}
1964f770deeSDevin Coughlin   clang_analyzer_eval(t.in.p == &x); // expected-warning{{TRUE}}
1974f770deeSDevin Coughlin }
1984f770deeSDevin Coughlin 
checkThatInheritedContainedConstMethodDoesNotInvalidateObjects()1994f770deeSDevin Coughlin void checkThatInheritedContainedConstMethodDoesNotInvalidateObjects() {
2004f770deeSDevin Coughlin   DOuter t;
2014f770deeSDevin Coughlin   t.x = 1;
2024f770deeSDevin Coughlin   t.in.x = 2;
2034f770deeSDevin Coughlin   t.in.foo();
2044f770deeSDevin Coughlin   clang_analyzer_eval(t.x == 1); // expected-warning{{TRUE}}
2054f770deeSDevin Coughlin   clang_analyzer_eval(t.in.x == 2); // expected-warning{{TRUE}}
2064f770deeSDevin Coughlin }
2074f770deeSDevin Coughlin 
2084f770deeSDevin Coughlin // --- PR21606 --- //
2094f770deeSDevin Coughlin 
2104f770deeSDevin Coughlin struct s1 {
2114f770deeSDevin Coughlin     void g(const int *i) const;
2124f770deeSDevin Coughlin };
2134f770deeSDevin Coughlin 
2144f770deeSDevin Coughlin struct s2 {
fs22154f770deeSDevin Coughlin     void f(int *i) {
2164f770deeSDevin Coughlin         m_i = i;
2174f770deeSDevin Coughlin         m_s.g(m_i);
2184f770deeSDevin Coughlin         if (m_i)
2194f770deeSDevin Coughlin             *i = 42; // no-warning
2204f770deeSDevin Coughlin     }
2214f770deeSDevin Coughlin 
2224f770deeSDevin Coughlin     int *m_i;
2234f770deeSDevin Coughlin     s1 m_s;
2244f770deeSDevin Coughlin };
2254f770deeSDevin Coughlin 
PR21606()2264f770deeSDevin Coughlin void PR21606()
2274f770deeSDevin Coughlin {
2284f770deeSDevin Coughlin     s2().f(0);
2294f770deeSDevin Coughlin }
2304f770deeSDevin Coughlin 
2319c76869bSDevin Coughlin // --- PR25392 --- //
2329c76869bSDevin Coughlin 
2339c76869bSDevin Coughlin struct HasConstMemberFunction {
2349c76869bSDevin Coughlin public:
2359c76869bSDevin Coughlin   void constMemberFunction() const;
2369c76869bSDevin Coughlin };
2379c76869bSDevin Coughlin 
hasNoReturn()238*1da13237SDávid Bolvanský HasConstMemberFunction hasNoReturn() { } // expected-warning {{non-void function does not return a value}}
2399c76869bSDevin Coughlin 
testUnknownWithConstMemberFunction()2409c76869bSDevin Coughlin void testUnknownWithConstMemberFunction() {
2419c76869bSDevin Coughlin   hasNoReturn().constMemberFunction();
2429c76869bSDevin Coughlin }
2439c76869bSDevin Coughlin 
testNonRegionLocWithConstMemberFunction()2449c76869bSDevin Coughlin void testNonRegionLocWithConstMemberFunction() {
2459c76869bSDevin Coughlin   (*((HasConstMemberFunction *)(&&label))).constMemberFunction();
2469c76869bSDevin Coughlin 
2479c76869bSDevin Coughlin   label: return;
2489c76869bSDevin Coughlin }
2499c76869bSDevin Coughlin 
2504f770deeSDevin Coughlin // FIXME
2514f770deeSDevin Coughlin // When there is a circular reference to an object and a const method is called
2524f770deeSDevin Coughlin // the object is not invalidated because TK_PreserveContents has already been
2534f770deeSDevin Coughlin // set.
2544f770deeSDevin Coughlin struct Outer2;
2554f770deeSDevin Coughlin 
2564f770deeSDevin Coughlin struct InnerWithRef {
2574f770deeSDevin Coughlin   Outer2 *ref;
2584f770deeSDevin Coughlin };
2594f770deeSDevin Coughlin 
2604f770deeSDevin Coughlin struct Outer2 {
2614f770deeSDevin Coughlin   int x;
2624f770deeSDevin Coughlin   InnerWithRef in;
2634f770deeSDevin Coughlin   void foo() const;
2644f770deeSDevin Coughlin };
2654f770deeSDevin Coughlin 
checkThatConstMethodCallDoesInvalidateObjectForCircularReferences()2664f770deeSDevin Coughlin void checkThatConstMethodCallDoesInvalidateObjectForCircularReferences() {
2674f770deeSDevin Coughlin   Outer2 t;
2684f770deeSDevin Coughlin   t.x = 1;
2694f770deeSDevin Coughlin   t.in.ref = &t;
2704f770deeSDevin Coughlin   t.foo();
2714f770deeSDevin Coughlin   // FIXME: Should be UNKNOWN.
2724f770deeSDevin Coughlin   clang_analyzer_eval(t.x); // expected-warning{{TRUE}}
2734f770deeSDevin Coughlin }
274