From 554bcb69c2d785a011a30e7db87a36a87fe7db10 Mon Sep 17 00:00:00 2001
From: dim <dim@FreeBSD.org>
Date: Wed, 15 Aug 2012 20:02:54 +0000
Subject: Vendor import of clang trunk r161861:
 http://llvm.org/svn/llvm-project/cfe/trunk@161861

---
 test/Analysis/derived-to-base.cpp | 124 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 123 insertions(+), 1 deletion(-)

(limited to 'test/Analysis/derived-to-base.cpp')

diff --git a/test/Analysis/derived-to-base.cpp b/test/Analysis/derived-to-base.cpp
index f65b9db..f833678 100644
--- a/test/Analysis/derived-to-base.cpp
+++ b/test/Analysis/derived-to-base.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store region %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-store=region -verify %s
+
+void clang_analyzer_eval(bool);
 
 class A {
 protected:
@@ -13,3 +15,123 @@ public:
 void B::f() {
   x = 3;
 }
+
+
+class C : public B {
+public:
+  void g() {
+    // This used to crash because we are upcasting through two bases.
+    x = 5;
+  }
+};
+
+
+namespace VirtualBaseClasses {
+  class A {
+  protected:
+    int x;
+  };
+
+  class B : public virtual A {
+  public:
+    int getX() { return x; }
+  };
+
+  class C : public virtual A {
+  public:
+    void setX() { x = 42; }
+  };
+
+  class D : public B, public C {};
+  class DV : virtual public B, public C {};
+  class DV2 : public B, virtual public C {};
+
+  void test() {
+    D d;
+    d.setX();
+    clang_analyzer_eval(d.getX() == 42); // expected-warning{{TRUE}}
+
+    DV dv;
+    dv.setX();
+    clang_analyzer_eval(dv.getX() == 42); // expected-warning{{TRUE}}
+
+    DV2 dv2;
+    dv2.setX();
+    clang_analyzer_eval(dv2.getX() == 42); // expected-warning{{TRUE}}
+  }
+
+
+  // Make sure we're consistent about the offset of the A subobject within an
+  // Intermediate virtual base class.
+  class Padding1 { int unused; };
+  class Padding2 { int unused; };
+  class Intermediate : public Padding1, public A, public Padding2 {};
+
+  class BI : public virtual Intermediate {
+  public:
+    int getX() { return x; }
+  };
+
+  class CI : public virtual Intermediate {
+  public:
+    void setX() { x = 42; }
+  };
+
+  class DI : public BI, public CI {};
+
+  void testIntermediate() {
+    DI d;
+    d.setX();
+    clang_analyzer_eval(d.getX() == 42); // expected-warning{{TRUE}}
+  }
+}
+
+
+namespace DynamicVirtualUpcast {
+  class A {
+  public:
+    virtual ~A();
+  };
+
+  class B : virtual public A {};
+  class C : virtual public B {};
+  class D : virtual public C {};
+
+  bool testCast(A *a) {
+    return dynamic_cast<B*>(a) && dynamic_cast<C*>(a);
+  }
+
+  void test() {
+    D d;
+    clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
+  }
+}
+
+namespace DynamicMultipleInheritanceUpcast {
+  class B {
+  public:
+    virtual ~B();
+  };
+  class C {
+  public:
+    virtual ~C();
+  };
+  class D : public B, public C {};
+
+  bool testCast(B *a) {
+    return dynamic_cast<C*>(a);
+  }
+
+  void test() {
+    D d;
+    clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
+  }
+
+
+  class DV : virtual public B, virtual public C {};
+
+  void testVirtual() {
+    DV d;
+    clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
+  }
+}
-- 
cgit v1.1