diff options
author | Anders Carlsson <andersca@mac.com> | 2010-04-21 19:52:01 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2010-04-21 19:52:01 +0000 |
commit | 43c64af5f0fba76d5117668183c7b19ece140fdc (patch) | |
tree | cb3ea5fd978e337ef26f95f4f3aec710bb9d4604 | |
parent | 53fac692fa06c812490bbbc25cb14dae67c95685 (diff) | |
download | bcm5719-llvm-43c64af5f0fba76d5117668183c7b19ece140fdc.tar.gz bcm5719-llvm-43c64af5f0fba76d5117668183c7b19ece140fdc.zip |
Keep tack of whether a base in an InitializedEntity is an inherited virtual base or not. Use this in CheckConstructorAccess.
llvm-svn: 102020
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaAccess.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 25 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.h | 20 | ||||
-rw-r--r-- | clang/test/CXX/class.access/p4.cpp | 5 |
6 files changed, 51 insertions, 19 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 9a2a388bc0b..7919d8247a7 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -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; diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index 1658b699c6b..1a96c26be19 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -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); } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index ca23727c5b9..d52e9dd394c 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -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; diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index fe7f79f9c52..a015dd71042 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -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; } diff --git a/clang/lib/Sema/SemaInit.h b/clang/lib/Sema/SemaInit.h index db987ec2961..bfbb0f4049c 100644 --- a/clang/lib/Sema/SemaInit.h +++ b/clang/lib/Sema/SemaInit.h @@ -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 diff --git a/clang/test/CXX/class.access/p4.cpp b/clang/test/CXX/class.access/p4.cpp index 3d1578a4fc8..fdde7350622 100644 --- a/clang/test/CXX/class.access/p4.cpp +++ b/clang/test/CXX/class.access/p4.cpp @@ -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; } |