| 1 | // RUN: %clang_analyze_cc1 -analyzer-checker=optin.cplusplus.VirtualCall -analyzer-store region -analyzer-output=text -verify -std=c++11 %s |
| 2 | |
| 3 | // RUN: %clang_analyze_cc1 -analyzer-checker=optin.cplusplus.VirtualCall -analyzer-store region -analyzer-config optin.cplusplus.VirtualCall:PureOnly=true -DPUREONLY=1 -analyzer-output=text -verify -std=c++11 %s |
| 4 | |
| 5 | #include "virtualcall.h" |
| 6 | |
| 7 | class A { |
| 8 | public: |
| 9 | A(); |
| 10 | |
| 11 | ~A(){}; |
| 12 | |
| 13 | virtual int foo() = 0; |
| 14 | virtual void bar() = 0; |
| 15 | void f() { |
| 16 | foo(); |
| 17 | // expected-warning-re@-1 {{{{^}}Call to pure virtual function during construction}} |
| 18 | // expected-note-re@-2 {{{{^}}Call to pure virtual function during construction}} |
| 19 | } |
| 20 | }; |
| 21 | |
| 22 | class B : public A { |
| 23 | public: |
| 24 | B() { // expected-note {{Calling default constructor for 'A'}} |
| 25 | foo(); |
| 26 | #if !PUREONLY |
| 27 | // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}} |
| 28 | // expected-note-re@-3 {{{{^}}This constructor of an object of type 'B' has not returned when the virtual method was called}} |
| 29 | // expected-note-re@-4 {{{{^}}Call to virtual function during construction}} |
| 30 | #endif |
| 31 | } |
| 32 | ~B(); |
| 33 | |
| 34 | virtual int foo(); |
| 35 | virtual void bar() { |
| 36 | foo(); |
| 37 | #if !PUREONLY |
| 38 | // expected-warning-re@-2 {{{{^}}Call to virtual function during destruction}} |
| 39 | // expected-note-re@-3 {{{{^}}Call to virtual function during destruction}} |
| 40 | #endif |
| 41 | } |
| 42 | }; |
| 43 | |
| 44 | A::A() { |
| 45 | f(); |
| 46 | // expected-note-re@-1 {{{{^}}This constructor of an object of type 'A' has not returned when the virtual method was called}} |
| 47 | // expected-note-re@-2 {{{{^}}Calling 'A::f'}} |
| 48 | } |
| 49 | |
| 50 | B::~B() { |
| 51 | this->B::foo(); // no-warning |
| 52 | this->B::bar(); |
| 53 | #if !PUREONLY |
| 54 | // expected-note-re@-2 {{{{^}}This destructor of an object of type '~B' has not returned when the virtual method was called}} |
| 55 | // expected-note-re@-3 {{{{^}}Calling 'B::bar'}} |
| 56 | #endif |
| 57 | this->foo(); |
| 58 | #if !PUREONLY |
| 59 | // expected-warning-re@-2 {{{{^}}Call to virtual function during destruction}} |
| 60 | // expected-note-re@-3 {{{{^}}This destructor of an object of type '~B' has not returned when the virtual method was called}} |
| 61 | // expected-note-re@-4 {{{{^}}Call to virtual function during destruction}} |
| 62 | #endif |
| 63 | |
| 64 | } |
| 65 | |
| 66 | class C : public B { |
| 67 | public: |
| 68 | C(); |
| 69 | ~C(); |
| 70 | |
| 71 | virtual int foo(); |
| 72 | void f(int i); |
| 73 | }; |
| 74 | |
| 75 | C::C() { |
| 76 | f(foo()); |
| 77 | #if !PUREONLY |
| 78 | // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}} |
| 79 | // expected-note-re@-3 {{{{^}}This constructor of an object of type 'C' has not returned when the virtual method was called}} |
| 80 | // expected-note-re@-4 {{{{^}}Call to virtual function during construction}} |
| 81 | #endif |
| 82 | } |
| 83 | |
| 84 | class D : public B { |
| 85 | public: |
| 86 | D() { |
| 87 | foo(); // no-warning |
| 88 | } |
| 89 | ~D() { bar(); } |
| 90 | int foo() final; |
| 91 | void bar() final { foo(); } // no-warning |
| 92 | }; |
| 93 | |
| 94 | class E final : public B { |
| 95 | public: |
| 96 | E() { |
| 97 | foo(); // no-warning |
| 98 | } |
| 99 | ~E() { bar(); } |
| 100 | #if !PUREONLY |
| 101 | // expected-note-re@-2 2{{{{^}}Calling '~B'}} |
| 102 | #endif |
| 103 | int foo() override; |
| 104 | }; |
| 105 | |
| 106 | class F { |
| 107 | public: |
| 108 | F() { |
| 109 | void (F::*ptr)() = &F::foo; |
| 110 | (this->*ptr)(); |
| 111 | } |
| 112 | void foo(); |
| 113 | }; |
| 114 | |
| 115 | class G { |
| 116 | public: |
| 117 | G() {} |
| 118 | virtual void bar(); |
| 119 | void foo() { |
| 120 | bar(); // no warning |
| 121 | } |
| 122 | }; |
| 123 | |
| 124 | class H { |
| 125 | public: |
| 126 | H() : initState(0) { init(); } |
| 127 | int initState; |
| 128 | virtual void f() const; |
| 129 | void init() { |
| 130 | if (initState) |
| 131 | f(); // no warning |
| 132 | } |
| 133 | |
| 134 | H(int i) { |
| 135 | G g; |
| 136 | g.foo(); |
| 137 | g.bar(); // no warning |
| 138 | f(); |
| 139 | #if !PUREONLY |
| 140 | // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}} |
| 141 | // expected-note-re@-3 {{{{^}}This constructor of an object of type 'H' has not returned when the virtual method was called}} |
| 142 | // expected-note-re@-4 {{{{^}}Call to virtual function during construction}} |
| 143 | #endif |
| 144 | H &h = *this; |
| 145 | h.f(); |
| 146 | #if !PUREONLY |
| 147 | // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}} |
| 148 | // expected-note-re@-3 {{{{^}}This constructor of an object of type 'H' has not returned when the virtual method was called}} |
| 149 | // expected-note-re@-4 {{{{^}}Call to virtual function during construction}} |
| 150 | #endif |
| 151 | } |
| 152 | }; |
| 153 | |
| 154 | class X { |
| 155 | public: |
| 156 | X() { |
| 157 | g(); |
| 158 | #if !PUREONLY |
| 159 | // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}} |
| 160 | // expected-note-re@-3 {{{{^}}This constructor of an object of type 'X' has not returned when the virtual method was called}} |
| 161 | // expected-note-re@-4 {{{{^}}Call to virtual function during construction}} |
| 162 | #endif |
| 163 | } |
| 164 | X(int i) { |
| 165 | if (i > 0) { |
| 166 | #if !PUREONLY |
| 167 | // expected-note-re@-2 {{{{^}}Taking true branch}} |
| 168 | // expected-note-re@-3 {{{{^}}Taking false branch}} |
| 169 | #endif |
| 170 | X x(i - 1); |
| 171 | #if !PUREONLY |
| 172 | // expected-note-re@-2 {{{{^}}Calling constructor for 'X'}} |
| 173 | #endif |
| 174 | x.g(); // no warning |
| 175 | } |
| 176 | g(); |
| 177 | #if !PUREONLY |
| 178 | // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}} |
| 179 | // expected-note-re@-3 {{{{^}}This constructor of an object of type 'X' has not returned when the virtual method was called}} |
| 180 | // expected-note-re@-4 {{{{^}}Call to virtual function during construction}} |
| 181 | #endif |
| 182 | } |
| 183 | virtual void g(); |
| 184 | }; |
| 185 | |
| 186 | class M; |
| 187 | class N { |
| 188 | public: |
| 189 | virtual void virtualMethod(); |
| 190 | void callFooOfM(M *); |
| 191 | }; |
| 192 | class M { |
| 193 | public: |
| 194 | M() { |
| 195 | N n; |
| 196 | n.virtualMethod(); // no warning |
| 197 | n.callFooOfM(this); |
| 198 | #if !PUREONLY |
| 199 | // expected-note-re@-2 {{{{^}}This constructor of an object of type 'M' has not returned when the virtual method was called}} |
| 200 | // expected-note-re@-3 {{{{^}}Calling 'N::callFooOfM'}} |
| 201 | #endif |
| 202 | } |
| 203 | virtual void foo(); |
| 204 | }; |
| 205 | void N::callFooOfM(M *m) { |
| 206 | m->foo(); |
| 207 | #if !PUREONLY |
| 208 | // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}} |
| 209 | // expected-note-re@-3 {{{{^}}Call to virtual function during construction}} |
| 210 | #endif |
| 211 | } |
| 212 | |
| 213 | class Y { |
| 214 | public: |
| 215 | virtual void foobar(); |
| 216 | void fooY() { |
| 217 | F f1; |
| 218 | foobar(); |
| 219 | #if !PUREONLY |
| 220 | // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}} |
| 221 | // expected-note-re@-3 {{{{^}}Call to virtual function during construction}} |
| 222 | #endif |
| 223 | } |
| 224 | Y() { fooY(); } |
| 225 | #if !PUREONLY |
| 226 | // expected-note-re@-2 {{{{^}}This constructor of an object of type 'Y' has not returned when the virtual method was called}} |
| 227 | // expected-note-re@-3 {{{{^}}Calling 'Y::fooY'}} |
| 228 | #endif |
| 229 | }; |
| 230 | |
| 231 | int main() { |
| 232 | B b; |
| 233 | #if PUREONLY |
| 234 | //expected-note-re@-2 {{{{^}}Calling default constructor for 'B'}} |
| 235 | #else |
| 236 | //expected-note-re@-4 2{{{{^}}Calling default constructor for 'B'}} |
| 237 | #endif |
| 238 | C c; |
| 239 | #if !PUREONLY |
| 240 | //expected-note-re@-2 {{{{^}}Calling default constructor for 'C'}} |
| 241 | #endif |
| 242 | D d; |
| 243 | E e; |
| 244 | F f; |
| 245 | G g; |
| 246 | H h; |
| 247 | H h1(1); |
| 248 | #if !PUREONLY |
| 249 | //expected-note-re@-2 {{{{^}}Calling constructor for 'H'}} |
| 250 | //expected-note-re@-3 {{{{^}}Calling constructor for 'H'}} |
| 251 | #endif |
| 252 | X x; |
| 253 | #if !PUREONLY |
| 254 | //expected-note-re@-2 {{{{^}}Calling default constructor for 'X'}} |
| 255 | #endif |
| 256 | X x1(1); |
| 257 | #if !PUREONLY |
| 258 | //expected-note-re@-2 {{{{^}}Calling constructor for 'X'}} |
| 259 | #endif |
| 260 | M m; |
| 261 | #if !PUREONLY |
| 262 | //expected-note-re@-2 {{{{^}}Calling default constructor for 'M'}} |
| 263 | #endif |
| 264 | Y *y = new Y; |
| 265 | #if !PUREONLY |
| 266 | //expected-note-re@-2 {{{{^}}Calling default constructor for 'Y'}} |
| 267 | #endif |
| 268 | delete y; |
| 269 | header::Z z; |
| 270 | #if !PUREONLY |
| 271 | // expected-note-re@-2 {{{{^}}Calling default constructor for 'Z'}} |
| 272 | #endif |
| 273 | } |
| 274 | #if !PUREONLY |
| 275 | //expected-note-re@-2 2{{{{^}}Calling '~E'}} |
| 276 | #endif |
| 277 | |
| 278 | namespace PR34451 { |
| 279 | struct a { |
| 280 | void b() { |
| 281 | a c[1]; |
| 282 | c->b(); |
| 283 | } |
| 284 | }; |
| 285 | |
| 286 | class e { |
| 287 | public: |
| 288 | void b() const; |
| 289 | }; |
| 290 | |
| 291 | class c { |
| 292 | void m_fn2() const; |
| 293 | e d[]; |
| 294 | }; |
| 295 | |
| 296 | void c::m_fn2() const { d->b(); } |
| 297 | } |
| 298 | |