1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.cplusplus.VirtualCall \ 2 // RUN: -analyzer-checker=debug.ExprInspection \ 3 // RUN: -std=c++11 -verify=impure %s 4 5 // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.PureVirtualCall \ 6 // RUN: -analyzer-checker=debug.ExprInspection \ 7 // RUN: -std=c++11 -verify=pure -std=c++11 %s 8 9 // RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.cplusplus.VirtualCall \ 10 // RUN: -analyzer-config \ 11 // RUN: optin.cplusplus.VirtualCall:PureOnly=true \ 12 // RUN: -analyzer-checker=debug.ExprInspection \ 13 // RUN: -std=c++11 -verify=none %s 14 15 // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.PureVirtualCall \ 16 // RUN: -analyzer-checker=optin.cplusplus.VirtualCall \ 17 // RUN: -analyzer-checker=debug.ExprInspection \ 18 // RUN: -std=c++11 -verify=pure,impure -std=c++11 %s 19 20 // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.PureVirtualCall \ 21 // RUN: -analyzer-checker=optin.cplusplus.VirtualCall \ 22 // RUN: -analyzer-config \ 23 // RUN: optin.cplusplus.VirtualCall:PureOnly=true \ 24 // RUN: -analyzer-checker=debug.ExprInspection \ 25 // RUN: -std=c++11 -verify=pure %s 26 27 28 // We expect no diagnostics when all checks are disabled. 29 // none-no-diagnostics 30 31 32 #include "virtualcall.h" 33 34 void clang_analyzer_warnIfReached(); 35 36 class A { 37 public: 38 A(); 39 ~A()40 ~A(){}; 41 42 virtual int foo() = 0; 43 virtual void bar() = 0; f()44 void f() { 45 foo(); // pure-warning{{Call to pure virtual method 'A::foo' during construction has undefined behavior}} 46 clang_analyzer_warnIfReached(); // no-warning 47 } 48 }; 49 A()50A::A() { 51 f(); 52 } 53 54 class B { 55 public: B()56 B() { 57 foo(); // impure-warning {{Call to virtual method 'B::foo' during construction bypasses virtual dispatch}} 58 } 59 ~B(); 60 61 virtual int foo(); bar()62 virtual void bar() { 63 foo(); // impure-warning {{Call to virtual method 'B::foo' during destruction bypasses virtual dispatch}} 64 } 65 }; 66 ~B()67B::~B() { 68 this->B::foo(); // no-warning 69 this->B::bar(); 70 this->foo(); // impure-warning {{Call to virtual method 'B::foo' during destruction bypasses virtual dispatch}} 71 } 72 73 class C : public B { 74 public: 75 C(); 76 ~C(); 77 78 virtual int foo(); 79 void f(int i); 80 }; 81 C()82C::C() { 83 f(foo()); // impure-warning {{Call to virtual method 'C::foo' during construction bypasses virtual dispatch}} 84 } 85 86 class D : public B { 87 public: D()88 D() { 89 foo(); // no-warning 90 } ~D()91 ~D() { bar(); } 92 int foo() final; bar()93 void bar() final { foo(); } // no-warning 94 }; 95 96 class E final : public B { 97 public: E()98 E() { 99 foo(); // no-warning 100 } ~E()101 ~E() { bar(); } 102 int foo() override; 103 }; 104 105 class F { 106 public: F()107 F() { 108 void (F::*ptr)() = &F::foo; 109 (this->*ptr)(); 110 } 111 void foo(); 112 }; 113 114 class G { 115 public: G()116 G() {} 117 virtual void bar(); foo()118 void foo() { 119 bar(); // no warning 120 } 121 }; 122 123 class H { 124 public: H()125 H() : initState(0) { init(); } 126 int initState; 127 virtual void f() const; init()128 void init() { 129 if (initState) 130 f(); // no warning 131 } 132 H(int i)133 H(int i) { 134 G g; 135 g.foo(); 136 g.bar(); // no warning 137 f(); // impure-warning {{Call to virtual method 'H::f' during construction bypasses virtual dispatch}} 138 H &h = *this; 139 h.f(); // impure-warning {{Call to virtual method 'H::f' during construction bypasses virtual dispatch}} 140 } 141 }; 142 143 class X { 144 public: X()145 X() { 146 g(); // impure-warning {{Call to virtual method 'X::g' during construction bypasses virtual dispatch}} 147 } X(int i)148 X(int i) { 149 if (i > 0) { 150 X x(i - 1); 151 x.g(); // no warning 152 } 153 g(); // impure-warning {{Call to virtual method 'X::g' during construction bypasses virtual dispatch}} 154 } 155 virtual void g(); 156 }; 157 158 class M; 159 class N { 160 public: 161 virtual void virtualMethod(); 162 void callFooOfM(M *); 163 }; 164 class M { 165 public: M()166 M() { 167 N n; 168 n.virtualMethod(); // no warning 169 n.callFooOfM(this); 170 } 171 virtual void foo(); 172 }; callFooOfM(M * m)173void N::callFooOfM(M *m) { 174 m->foo(); // impure-warning {{Call to virtual method 'M::foo' during construction bypasses virtual dispatch}} 175 } 176 177 class Y { 178 public: 179 virtual void foobar(); fooY()180 void fooY() { 181 F f1; 182 foobar(); // impure-warning {{Call to virtual method 'Y::foobar' during construction bypasses virtual dispatch}} 183 } Y()184 Y() { fooY(); } 185 }; 186 main()187int main() { 188 B b; 189 C c; 190 D d; 191 E e; 192 F f; 193 G g; 194 H h; 195 H h1(1); 196 X x; 197 X x1(1); 198 M m; 199 Y *y = new Y; 200 delete y; 201 header::Z z; 202 } 203 204 namespace PR34451 { 205 struct a { bPR34451::a206 void b() { 207 a c[1]; 208 c->b(); 209 } 210 }; 211 212 class e { 213 public: 214 void b() const; 215 }; 216 217 class c { 218 void m_fn2() const; 219 e d[]; 220 }; 221 m_fn2() const222void c::m_fn2() const { d->b(); } 223 } 224