llvm-project/clang/test/Analysis/virtualcall.cpp
Devin Coughlin 3e5f0474ca [analyzer] Improve VirtualCallChecker diagnostics and move into optin package.
The VirtualCallChecker is in alpha because its interprocedural diagnostics
represent the call path textually in the diagnostic message rather than with a
path sensitive diagnostic.

This patch turns off the AST-based interprocedural analysis in the checker so
that no call path is needed and improves with diagnostic text. With these
changes, the checker is ready to be moved into the optin package.

Ultimately the right fix is to rewrite this checker to be path sensitive -- but
there is still value in enabling the checker for intraprocedural analysis only
The interprocedural mode can be re-enabled with an -analyzer-config flag.

Differential Revision: https://reviews.llvm.org/D26768

llvm-svn: 289309
2016-12-10 01:16:09 +00:00

131 lines
3.4 KiB
C++

// RUN: %clang_cc1 -analyze -analyzer-checker=optin.cplusplus.VirtualCall -analyzer-store region -verify -std=c++11 %s
// RUN: %clang_cc1 -analyze -analyzer-checker=optin.cplusplus.VirtualCall -analyzer-store region -analyzer-config optin.cplusplus.VirtualCall:Interprocedural=true -DINTERPROCEDURAL=1 -verify -std=c++11 %s
// RUN: %clang_cc1 -analyze -analyzer-checker=optin.cplusplus.VirtualCall -analyzer-store region -analyzer-config optin.cplusplus.VirtualCall:PureOnly=true -DPUREONLY=1 -verify -std=c++11 %s
/* When INTERPROCEDURAL is set, we expect diagnostics in all functions reachable
from a constructor or destructor. If it is not set, we expect diagnostics
only in the constructor or destructor.
When PUREONLY is set, we expect diagnostics only for calls to pure virtual
functions not to non-pure virtual functions.
*/
class A {
public:
A();
A(int i);
~A() {};
virtual int foo() = 0; // from Sema: expected-note {{'foo' declared here}}
virtual void bar() = 0;
void f() {
foo();
#if INTERPROCEDURAL
// expected-warning-re@-2 {{{{^}}Call Path : foo <-- fCall to pure virtual function during construction has undefined behavior}}
#endif
}
};
class B : public A {
public:
B() {
foo();
#if !PUREONLY
#if INTERPROCEDURAL
// expected-warning-re@-3 {{{{^}}Call Path : fooCall to virtual function during construction will not dispatch to derived class}}
#else
// expected-warning-re@-5 {{{{^}}Call to virtual function during construction will not dispatch to derived class}}
#endif
#endif
}
~B();
virtual int foo();
virtual void bar() { foo(); }
#if INTERPROCEDURAL
// expected-warning-re@-2 {{{{^}}Call Path : foo <-- barCall to virtual function during destruction will not dispatch to derived class}}
#endif
};
A::A() {
f();
}
A::A(int i) {
foo(); // From Sema: expected-warning {{call to pure virtual member function 'foo' has undefined behavior}}
#if INTERPROCEDURAL
// expected-warning-re@-2 {{{{^}}Call Path : fooCall to pure virtual function during construction has undefined behavior}}
#else
// expected-warning-re@-4 {{{{^}}Call to pure virtual function during construction has undefined behavior}}
#endif
}
B::~B() {
this->B::foo(); // no-warning
this->B::bar();
this->foo();
#if !PUREONLY
#if INTERPROCEDURAL
// expected-warning-re@-3 {{{{^}}Call Path : fooCall to virtual function during destruction will not dispatch to derived class}}
#else
// expected-warning-re@-5 {{{{^}}Call to virtual function during destruction will not dispatch to derived class}}
#endif
#endif
}
class C : public B {
public:
C();
~C();
virtual int foo();
void f(int i);
};
C::C() {
f(foo());
#if !PUREONLY
#if INTERPROCEDURAL
// expected-warning-re@-3 {{{{^}}Call Path : fooCall to virtual function during construction will not dispatch to derived class}}
#else
// expected-warning-re@-5 {{{{^}}Call to virtual function during construction will not dispatch to derived class}}
#endif
#endif
}
class D : public B {
public:
D() {
foo(); // no-warning
}
~D() { bar(); }
int foo() final;
void bar() final { foo(); } // no-warning
};
class E final : public B {
public:
E() {
foo(); // no-warning
}
~E() { bar(); }
int foo() override;
};
int main() {
A *a;
B *b;
C *c;
D *d;
E *e;
}
#include "virtualcall.h"
#define AS_SYSTEM
#include "virtualcall.h"
#undef AS_SYSTEM