1 // RUN: %clang_analyze_cc1 -analyzer-checker=optin.cplusplus.VirtualCall -analyzer-store region -verify -std=c++11 %s 2 // RUN: %clang_analyze_cc1 -analyzer-checker=optin.cplusplus.VirtualCall -analyzer-store region -analyzer-config optin.cplusplus.VirtualCall:Interprocedural=true -DINTERPROCEDURAL=1 -verify -std=c++11 %s 3 // RUN: %clang_analyze_cc1 -analyzer-checker=optin.cplusplus.VirtualCall -analyzer-store region -analyzer-config optin.cplusplus.VirtualCall:PureOnly=true -DPUREONLY=1 -verify -std=c++11 %s 4 5 /* When INTERPROCEDURAL is set, we expect diagnostics in all functions reachable 6 from a constructor or destructor. If it is not set, we expect diagnostics 7 only in the constructor or destructor. 8 9 When PUREONLY is set, we expect diagnostics only for calls to pure virtual 10 functions not to non-pure virtual functions. 11 */ 12 13 class A { 14 public: 15 A(); 16 A(int i); 17 18 ~A() {}; 19 20 virtual int foo() = 0; // from Sema: expected-note {{'foo' declared here}} 21 virtual void bar() = 0; 22 void f() { 23 foo(); 24 #if INTERPROCEDURAL 25 // expected-warning-re@-2 {{{{^}}Call Path : foo <-- fCall to pure virtual function during construction has undefined behavior}} 26 #endif 27 } 28 }; 29 30 class B : public A { 31 public: 32 B() { 33 foo(); 34 #if !PUREONLY 35 #if INTERPROCEDURAL 36 // expected-warning-re@-3 {{{{^}}Call Path : fooCall to virtual function during construction will not dispatch to derived class}} 37 #else 38 // expected-warning-re@-5 {{{{^}}Call to virtual function during construction will not dispatch to derived class}} 39 #endif 40 #endif 41 42 } 43 ~B(); 44 45 virtual int foo(); 46 virtual void bar() { foo(); } 47 #if INTERPROCEDURAL 48 // expected-warning-re@-2 {{{{^}}Call Path : foo <-- barCall to virtual function during destruction will not dispatch to derived class}} 49 #endif 50 }; 51 52 A::A() { 53 f(); 54 } 55 56 A::A(int i) { 57 foo(); // From Sema: expected-warning {{call to pure virtual member function 'foo' has undefined behavior}} 58 #if INTERPROCEDURAL 59 // expected-warning-re@-2 {{{{^}}Call Path : fooCall to pure virtual function during construction has undefined behavior}} 60 #else 61 // expected-warning-re@-4 {{{{^}}Call to pure virtual function during construction has undefined behavior}} 62 #endif 63 } 64 65 B::~B() { 66 this->B::foo(); // no-warning 67 this->B::bar(); 68 this->foo(); 69 #if !PUREONLY 70 #if INTERPROCEDURAL 71 // expected-warning-re@-3 {{{{^}}Call Path : fooCall to virtual function during destruction will not dispatch to derived class}} 72 #else 73 // expected-warning-re@-5 {{{{^}}Call to virtual function during destruction will not dispatch to derived class}} 74 #endif 75 #endif 76 77 } 78 79 class C : public B { 80 public: 81 C(); 82 ~C(); 83 84 virtual int foo(); 85 void f(int i); 86 }; 87 88 C::C() { 89 f(foo()); 90 #if !PUREONLY 91 #if INTERPROCEDURAL 92 // expected-warning-re@-3 {{{{^}}Call Path : fooCall to virtual function during construction will not dispatch to derived class}} 93 #else 94 // expected-warning-re@-5 {{{{^}}Call to virtual function during construction will not dispatch to derived class}} 95 #endif 96 #endif 97 } 98 99 class D : public B { 100 public: 101 D() { 102 foo(); // no-warning 103 } 104 ~D() { bar(); } 105 int foo() final; 106 void bar() final { foo(); } // no-warning 107 }; 108 109 class E final : public B { 110 public: 111 E() { 112 foo(); // no-warning 113 } 114 ~E() { bar(); } 115 int foo() override; 116 }; 117 118 // Regression test: don't crash when there's no direct callee. 119 class F { 120 public: 121 F() { 122 void (F::* ptr)() = &F::foo; 123 (this->*ptr)(); 124 } 125 void foo(); 126 }; 127 128 int main() { 129 A *a; 130 B *b; 131 C *c; 132 D *d; 133 E *e; 134 F *f; 135 } 136 137 #include "virtualcall.h" 138 139 #define AS_SYSTEM 140 #include "virtualcall.h" 141 #undef AS_SYSTEM 142