aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2013-04-22 21:36:49 +0000
committerJordan Rose <jordan_rose@apple.com>2013-04-22 21:36:49 +0000
commitf2edbec1d9817df109304f9c19ae2b34fec1feea (patch)
tree6d7af3bf8ffca90a253c75e08fcc044e5609b458 /test
parentfbc4444eb2675934b44f3720ef9a5f368ecbeb0a (diff)
[analyzer] Treat reinterpret_cast like a base cast in certain cases.
The analyzer represents all pointer-to-pointer bitcasts the same way, but this can be problematic if an implicit base cast gets layered on top of a manual base cast (performed with reinterpret_cast instead of static_cast). Fix this (and avoid a valid assertion) by looking through cast regions. Using reinterpret_cast this way is only valid if the base class is at the same offset as the derived class; this is checked by -Wreinterpret-base-class. In the interest of performance, the analyzer doesn't repeat this check anywhere; it will just silently do the wrong thing (use the wrong offsets for fields of the base class) if the user code is wrong. PR15394 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@180052 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test')
-rw-r--r--test/Analysis/derived-to-base.cpp87
1 files changed, 87 insertions, 0 deletions
diff --git a/test/Analysis/derived-to-base.cpp b/test/Analysis/derived-to-base.cpp
index b846d2c28b..0664189a95 100644
--- a/test/Analysis/derived-to-base.cpp
+++ b/test/Analysis/derived-to-base.cpp
@@ -2,6 +2,7 @@
// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -DCONSTRUCTORS=1 -analyzer-config c++-inlining=constructors -verify %s
void clang_analyzer_eval(bool);
+void clang_analyzer_checkInlined(bool);
class A {
protected:
@@ -363,3 +364,89 @@ namespace Redeclaration {
}
};
+namespace PR15394 {
+ namespace Original {
+ class Base {
+ public:
+ virtual int f() = 0;
+ int i;
+ };
+
+ class Derived1 : public Base {
+ public:
+ int j;
+ };
+
+ class Derived2 : public Derived1 {
+ public:
+ virtual int f() {
+ clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
+ return i + j;
+ }
+ };
+
+ void testXXX() {
+ Derived1 *d1p = reinterpret_cast<Derived1*>(new Derived2);
+ d1p->i = 1;
+ d1p->j = 2;
+ clang_analyzer_eval(d1p->f() == 3); // expected-warning{{TRUE}}
+ }
+ }
+
+ namespace VirtualInDerived {
+ class Base {
+ public:
+ int i;
+ };
+
+ class Derived1 : public Base {
+ public:
+ virtual int f() = 0;
+ int j;
+ };
+
+ class Derived2 : public Derived1 {
+ public:
+ virtual int f() {
+ clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
+ return i + j;
+ }
+ };
+
+ void test() {
+ Derived1 *d1p = reinterpret_cast<Derived1*>(new Derived2);
+ d1p->i = 1;
+ d1p->j = 2;
+ clang_analyzer_eval(d1p->f() == 3); // expected-warning{{TRUE}}
+ }
+ }
+
+ namespace NoCast {
+ class Base {
+ public:
+ int i;
+ };
+
+ class Derived1 : public Base {
+ public:
+ virtual int f() = 0;
+ int j;
+ };
+
+ class Derived2 : public Derived1 {
+ public:
+ virtual int f() {
+ clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
+ return i + j;
+ }
+ };
+
+ void test() {
+ Derived1 *d1p = new Derived2;
+ d1p->i = 1;
+ d1p->j = 2;
+ clang_analyzer_eval(d1p->f() == 3); // expected-warning{{TRUE}}
+ }
+ }
+};
+