]> granicus.if.org Git - clang/commitdiff
Keep tack of whether a base in an InitializedEntity is an inherited virtual base...
authorAnders Carlsson <andersca@mac.com>
Wed, 21 Apr 2010 19:52:01 +0000 (19:52 +0000)
committerAnders Carlsson <andersca@mac.com>
Wed, 21 Apr 2010 19:52:01 +0000 (19:52 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102020 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaAccess.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaInit.cpp
lib/Sema/SemaInit.h
test/CXX/class.access/p4.cpp

index 9a2a388bc0b56134919dd0a5b688636503f2d9d8..7919d8247a75ec60b62c57ad8d6094698eaa5066 100644 (file)
@@ -462,6 +462,10 @@ def err_access_ctor :
 def err_access_ctor_base :
     Error<"base class %0 has %select{private|protected}1 constructor">,
     NoSFINAE;
+def err_access_ctor_vbase :
+    Error<"inherited virtual base class %0 has "
+    "%select{private|protected}1 constructor">,
+    NoSFINAE;
 def err_access_dtor_base :
     Error<"base class %0 has %select{private|protected}1 destructor">,
     NoSFINAE;
index 1658b699c6b8ff1def9156390e284893478bc994..1a96c26be19cfdd0fe512652a0a61ba07a9c18dd 100644 (file)
@@ -1143,12 +1143,16 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
     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);
 }
 
index ca23727c5b9c3d72bad04d790f907f6302621a50..d52e9dd394c1597c8c16aaa260c8bd3475951543 100644 (file)
@@ -1384,7 +1384,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
 
   // 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 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
 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 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
       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 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
         = 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 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
       AllToInit.push_back(Value);
     } else if (!AnyErrors) {
       CXXBaseOrMemberInitializer *CXXBaseInit =
-        BuildImplicitBaseInitializer(*this, Constructor, Base);
-      
+        BuildImplicitBaseInitializer(*this, Constructor, Base,
+                                     /*IsInheritedVirtualBase=*/false);
+
       if (!CXXBaseInit) {
         HadError = true;
         continue;
index fe7f79f9c5232df69f7db915945ab9d8664417aa..a015dd71042956b5b93dcfa5566e04ce4a5334f9 100644 (file)
@@ -1921,11 +1921,15 @@ InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index,
 }
 
 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;
 }
index db987ec2961e43cb7561e68dd2c33b6b86961bcf..bfbb0f4049c28e8ccfcb5bfdcb2e352df82c6f1a 100644 (file)
@@ -92,11 +92,12 @@ private:
     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 @@ public:
   
   /// \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 @@ public:
   /// \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
index 3d1578a4fc8397633e73c816a3c2b4d4307897d7..fdde73506220d448018769ba990dca599c187af7 100644 (file)
@@ -103,9 +103,8 @@ namespace test2 {
   public:
     C();
   };
-  
-  // FIXME: It would be better if this said something about A being an inherited virtual base.
-  class D : C { }; // expected-error {{base class 'test2::A' has private constructor}}
+
+  class D : C { }; // expected-error {{inherited virtual base class 'test2::A' has private constructor}}
   D d;
 }