[analyzer] Handle dynamic_casts that turn out to be upcasts.

This can occur with multiple inheritance, which jumps from one parent to
the other, and with virtual inheritance, since virtual base regions always
wrap the actual object and can't be nested within other base regions.

This also exposed some incorrect logic for multiple inheritance: even if B
is known not to derive from C, D might still derive from both of them.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161798 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/Analysis/derived-to-base.cpp b/test/Analysis/derived-to-base.cpp
index b065bc2..f833678 100644
--- a/test/Analysis/derived-to-base.cpp
+++ b/test/Analysis/derived-to-base.cpp
@@ -85,3 +85,53 @@
     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}}
+  }
+}