Keep tack of whether a base in an InitializedEntity is an inherited virtual base or not. Use this in CheckConstructorAccess.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102020 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index 1658b69..1a96c26 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -1143,12 +1143,16 @@
     AccessEntity.setDiag(diag::err_access_ctor);
     break;
 
-  case InitializedEntity::EK_Base:
-    AccessEntity.setDiag(PDiag(diag::err_access_ctor_base)
+  case InitializedEntity::EK_Base: {
+    unsigned DiagID = Entity.isInheritedVirtualBase() ?
+      diag::err_access_ctor_vbase : diag::err_access_ctor_base;
+    AccessEntity.setDiag(PDiag(DiagID)
                           << Entity.getBaseSpecifier()->getType());
     break;
   }
 
+  }
+
   return CheckAccess(*this, UseLoc, AccessEntity);
 }
 
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index ca23727..d52e9dd 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1384,7 +1384,7 @@
 
   // Initialize the base.
   InitializedEntity BaseEntity =
-    InitializedEntity::InitializeBase(Context, BaseSpec);
+    InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec);
   InitializationKind Kind = 
     InitializationKind::CreateDirect(BaseLoc, LParenLoc, RParenLoc);
   
@@ -1435,9 +1435,11 @@
 static CXXBaseOrMemberInitializer *
 BuildImplicitBaseInitializer(Sema &SemaRef, 
                              const CXXConstructorDecl *Constructor,
-                             CXXBaseSpecifier *BaseSpec) {
+                             CXXBaseSpecifier *BaseSpec,
+                             bool IsInheritedVirtualBase) {
   InitializedEntity InitEntity
-    = InitializedEntity::InitializeBase(SemaRef.Context, BaseSpec);
+    = InitializedEntity::InitializeBase(SemaRef.Context, BaseSpec,
+                                        IsInheritedVirtualBase);
 
   InitializationKind InitKind
     = InitializationKind::CreateDefault(Constructor->getLocation());
@@ -1502,6 +1504,14 @@
       AllBaseFields[Member->getMember()] = Member;
   }
 
+  // Keep track of the direct virtual bases.
+  llvm::SmallPtrSet<CXXBaseSpecifier *, 16> DirectVBases;
+  for (CXXRecordDecl::base_class_iterator I = ClassDecl->bases_begin(),
+       E = ClassDecl->bases_end(); I != E; ++I) {
+    if (I->isVirtual())
+      DirectVBases.insert(I);
+  }
+
   // Push virtual bases before others.
   for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
        E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
@@ -1510,8 +1520,10 @@
         = AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
       AllToInit.push_back(Value);
     } else if (!AnyErrors) {
+      bool IsInheritedVirtualBase = !DirectVBases.count(VBase);
       CXXBaseOrMemberInitializer *CXXBaseInit =
-        BuildImplicitBaseInitializer(*this, Constructor, VBase);
+        BuildImplicitBaseInitializer(*this, Constructor, VBase,
+                                     IsInheritedVirtualBase);
 
       if (!CXXBaseInit) {
         HadError = true;
@@ -1533,8 +1545,9 @@
       AllToInit.push_back(Value);
     } else if (!AnyErrors) {
       CXXBaseOrMemberInitializer *CXXBaseInit =
-        BuildImplicitBaseInitializer(*this, Constructor, Base);
-      
+        BuildImplicitBaseInitializer(*this, Constructor, Base,
+                                     /*IsInheritedVirtualBase=*/false);
+
       if (!CXXBaseInit) {
         HadError = true;
         continue;
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index fe7f79f..a015dd7 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -1921,11 +1921,15 @@
 }
 
 InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context, 
-                                                    CXXBaseSpecifier *Base)
+                                                    CXXBaseSpecifier *Base,
+                                                    bool IsInheritedVirtualBase)
 {
   InitializedEntity Result;
   Result.Kind = EK_Base;
-  Result.Base = Base;
+  Result.Base = reinterpret_cast<uintptr_t>(Base);
+  if (IsInheritedVirtualBase)
+    Result.Base |= 0x01;
+  
   Result.Type = Base->getType();
   return Result;
 }
diff --git a/lib/Sema/SemaInit.h b/lib/Sema/SemaInit.h
index db987ec..bfbb0f4 100644
--- a/lib/Sema/SemaInit.h
+++ b/lib/Sema/SemaInit.h
@@ -92,11 +92,12 @@
     unsigned Location;
     
     /// \brief When Kind == EK_Base, the base specifier that provides the 
-    /// base class.
-    CXXBaseSpecifier *Base;
+    /// base class. The lower bit specifies whether the base is an inherited
+    /// virtual base.
+    uintptr_t Base;
 
-    /// \brief When Kind = EK_ArrayElement or EK_VectorElement, the
-    /// index of the array or vector element being initialized.
+    /// \brief When Kind == EK_ArrayElement or EK_VectorElement, the
+    /// index of the array or vector element being initialized. 
     unsigned Index;
   };
 
@@ -168,7 +169,8 @@
   
   /// \brief Create the initialization entity for a base class subobject.
   static InitializedEntity InitializeBase(ASTContext &Context,
-                                          CXXBaseSpecifier *Base);
+                                          CXXBaseSpecifier *Base,
+                                          bool IsInheritedVirtualBase);
   
   /// \brief Create the initialization entity for a member subobject.
   static InitializedEntity InitializeMember(FieldDecl *Member,
@@ -204,7 +206,13 @@
   /// \brief Retrieve the base specifier.
   CXXBaseSpecifier *getBaseSpecifier() const {
     assert(getKind() == EK_Base && "Not a base specifier");
-    return Base;
+    return reinterpret_cast<CXXBaseSpecifier *>(Base & ~0x1);
+  }
+
+  /// \brief Return whether the base is an inherited virtual base.
+  bool isInheritedVirtualBase() const {
+    assert(getKind() == EK_Base && "Not a base specifier");
+    return Base & 0x1;
   }
 
   /// \brief Determine the location of the 'return' keyword when initializing