1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-ipa=inlining -verify %s
2 
3 void clang_analyzer_eval(bool);
4 void clang_analyzer_checkInlined(bool);
5 
6 class A {
7 public:
8   int getZero() { return 0; }
9   virtual int getNum() { return 0; }
10 };
11 
12 void test(A &a) {
13   clang_analyzer_eval(a.getZero() == 0); // expected-warning{{TRUE}}
14   clang_analyzer_eval(a.getNum() == 0); // expected-warning{{UNKNOWN}}
15 
16   A copy(a);
17   clang_analyzer_eval(copy.getZero() == 0); // expected-warning{{TRUE}}
18   clang_analyzer_eval(copy.getNum() == 0); // expected-warning{{TRUE}}
19 }
20 
21 
22 class One : public A {
23 public:
24   virtual int getNum() { return 1; }
25 };
26 
27 void testPathSensitivity(int x) {
28   A a;
29   One b;
30 
31   A *ptr;
32   switch (x) {
33   case 0:
34     ptr = &a;
35     break;
36   case 1:
37     ptr = &b;
38     break;
39   default:
40     return;
41   }
42 
43   // This should be true on both branches.
44   clang_analyzer_eval(ptr->getNum() == x); // expected-warning {{TRUE}}
45 }
46 
47 
48 namespace PureVirtualParent {
49   class Parent {
50   public:
51     virtual int pureVirtual() const = 0;
52     int callVirtual() const {
53       return pureVirtual();
54     }
55   };
56 
57   class Child : public Parent {
58   public:
59     virtual int pureVirtual() const {
60       clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
61       return 42;
62     }
63   };
64 
65   void testVirtual() {
66     Child x;
67 
68     clang_analyzer_eval(x.pureVirtual() == 42); // expected-warning{{TRUE}}
69     clang_analyzer_eval(x.callVirtual() == 42); // expected-warning{{TRUE}}
70   }
71 }
72 
73 
74 namespace PR13569 {
75   class Parent {
76   protected:
77     int m_parent;
78     virtual int impl() const = 0;
79 
80     Parent() : m_parent(0) {}
81 
82   public:
83     int interface() const {
84       clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
85       return impl();
86     }
87   };
88 
89   class Child : public Parent {
90   protected:
91     virtual int impl() const {
92       clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
93       return m_parent + m_child;
94     }
95 
96   public:
97     Child() : m_child(0) {}
98 
99     int m_child;
100   };
101 
102   void testVirtual() {
103     Child x;
104     x.m_child = 42;
105 
106     // Don't crash when inlining and devirtualizing.
107     x.interface();
108   }
109 
110 
111   class Grandchild : public Child {};
112 
113   void testDevirtualizeToMiddle() {
114     Grandchild x;
115     x.m_child = 42;
116 
117     // Don't crash when inlining and devirtualizing.
118     x.interface();
119   }
120 }
121 
122 namespace PR13569_virtual {
123   class Parent {
124   protected:
125     int m_parent;
126     virtual int impl() const = 0;
127 
128     Parent() : m_parent(0) {}
129 
130   public:
131     int interface() const {
132       clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
133       return impl();
134     }
135   };
136 
137   class Child : virtual public Parent {
138   protected:
139     virtual int impl() const {
140       clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
141       return m_parent + m_child;
142     }
143 
144   public:
145     Child() : m_child(0) {}
146 
147     int m_child;
148   };
149 
150   void testVirtual() {
151     Child x;
152     x.m_child = 42;
153 
154     // Don't crash when inlining and devirtualizing.
155     x.interface();
156   }
157 
158 
159   class Grandchild : virtual public Child {};
160 
161   void testDevirtualizeToMiddle() {
162     Grandchild x;
163     x.m_child = 42;
164 
165     // Don't crash when inlining and devirtualizing.
166     x.interface();
167   }
168 }
169 
170 namespace Invalidation {
171   struct X {
172     void touch(int &x) const {
173       x = 0;
174     }
175 
176     void touch2(int &x) const;
177 
178     virtual void touchV(int &x) const {
179       x = 0;
180     }
181 
182     virtual void touchV2(int &x) const;
183 
184     int test() const {
185       // We were accidentally not invalidating under -analyzer-ipa=inlining
186       // at one point for virtual methods with visible definitions.
187       int a, b, c, d;
188       touch(a);
189       touch2(b);
190       touchV(c);
191       touchV2(d);
192       return a + b + c + d; // no-warning
193     }
194   };
195 }
196