Implement semantic checking of static_cast and dynamic_cast.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58509 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaInherit.cpp b/lib/Sema/SemaInherit.cpp
index ce48a43..b2d9b88 100644
--- a/lib/Sema/SemaInherit.cpp
+++ b/lib/Sema/SemaInherit.cpp
@@ -42,6 +42,7 @@
   Paths.clear();
   ClassSubobjects.clear();
   ScratchPath.clear();
+  DetectedVirtual = 0;
 }
 
 /// IsDerivedFrom - Determine whether the type Derived is derived from
@@ -50,7 +51,8 @@
 /// Derived* to a Base* is legal, because it does not account for
 /// ambiguous conversions or conversions to private/protected bases.
 bool Sema::IsDerivedFrom(QualType Derived, QualType Base) {
-  BasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false);
+  BasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false,
+                  /*DetectVirtual=*/false);
   return IsDerivedFrom(Derived, Base, Paths);
 }
 
@@ -64,10 +66,10 @@
 /// information about all of the paths (if @c Paths.isRecordingPaths()).
 bool Sema::IsDerivedFrom(QualType Derived, QualType Base, BasePaths &Paths) {
   bool FoundPath = false;
-  
+
   Derived = Context.getCanonicalType(Derived).getUnqualifiedType();
   Base = Context.getCanonicalType(Base).getUnqualifiedType();
-  
+
   if (!Derived->isRecordType() || !Base->isRecordType())
     return false;
 
@@ -87,9 +89,17 @@
       // updating the count of subobjects appropriately.
       std::pair<bool, unsigned>& Subobjects = Paths.ClassSubobjects[BaseType];
       bool VisitBase = true;
+      bool SetVirtual = false;
       if (BaseSpec->isVirtual()) {
         VisitBase = !Subobjects.first;
         Subobjects.first = true;
+        if (Paths.isDetectingVirtual() && Paths.DetectedVirtual == 0) {
+          // If this is the first virtual we find, remember it. If it turns out
+          // there is no base path here, we'll reset it later.
+          Paths.DetectedVirtual = static_cast<const CXXRecordType*>(
+            BaseType->getAsRecordType());
+          SetVirtual = true;
+        }
       } else
         ++Subobjects.second;
 
@@ -127,6 +137,10 @@
       // collecting paths).
       if (Paths.isRecordingPaths())
         Paths.ScratchPath.pop_back();
+      // If we set a virtual earlier, and this isn't a path, forget it again.
+      if (SetVirtual && !FoundPath) {
+        Paths.DetectedVirtual = 0;
+      }
     }
   }
 
@@ -148,7 +162,8 @@
   // ambiguous. This is slightly more expensive than checking whether
   // the Derived to Base conversion exists, because here we need to
   // explore multiple paths to determine if there is an ambiguity.
-  BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/false);
+  BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/false,
+                  /*DetectVirtual=*/false);
   bool DerivationOkay = IsDerivedFrom(Derived, Base, Paths);
   assert(DerivationOkay && "Can only be used with a derived-to-base conversion");
   if (!DerivationOkay)