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