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

llvm-svn: 102020
This commit is contained in:
Anders Carlsson 2010-04-21 19:52:01 +00:00
parent 53fac692fa
commit 43c64af5f0
6 changed files with 51 additions and 19 deletions

View File

@ -462,6 +462,10 @@ def err_access_ctor :
def err_access_ctor_base : def err_access_ctor_base :
Error<"base class %0 has %select{private|protected}1 constructor">, Error<"base class %0 has %select{private|protected}1 constructor">,
NoSFINAE; NoSFINAE;
def err_access_ctor_vbase :
Error<"inherited virtual base class %0 has "
"%select{private|protected}1 constructor">,
NoSFINAE;
def err_access_dtor_base : def err_access_dtor_base :
Error<"base class %0 has %select{private|protected}1 destructor">, Error<"base class %0 has %select{private|protected}1 destructor">,
NoSFINAE; NoSFINAE;

View File

@ -1143,12 +1143,16 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
AccessEntity.setDiag(diag::err_access_ctor); AccessEntity.setDiag(diag::err_access_ctor);
break; break;
case InitializedEntity::EK_Base: case InitializedEntity::EK_Base: {
AccessEntity.setDiag(PDiag(diag::err_access_ctor_base) unsigned DiagID = Entity.isInheritedVirtualBase() ?
diag::err_access_ctor_vbase : diag::err_access_ctor_base;
AccessEntity.setDiag(PDiag(DiagID)
<< Entity.getBaseSpecifier()->getType()); << Entity.getBaseSpecifier()->getType());
break; break;
} }
}
return CheckAccess(*this, UseLoc, AccessEntity); return CheckAccess(*this, UseLoc, AccessEntity);
} }

View File

@ -1384,7 +1384,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
// Initialize the base. // Initialize the base.
InitializedEntity BaseEntity = InitializedEntity BaseEntity =
InitializedEntity::InitializeBase(Context, BaseSpec); InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec);
InitializationKind Kind = InitializationKind Kind =
InitializationKind::CreateDirect(BaseLoc, LParenLoc, RParenLoc); InitializationKind::CreateDirect(BaseLoc, LParenLoc, RParenLoc);
@ -1435,9 +1435,11 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
static CXXBaseOrMemberInitializer * static CXXBaseOrMemberInitializer *
BuildImplicitBaseInitializer(Sema &SemaRef, BuildImplicitBaseInitializer(Sema &SemaRef,
const CXXConstructorDecl *Constructor, const CXXConstructorDecl *Constructor,
CXXBaseSpecifier *BaseSpec) { CXXBaseSpecifier *BaseSpec,
bool IsInheritedVirtualBase) {
InitializedEntity InitEntity InitializedEntity InitEntity
= InitializedEntity::InitializeBase(SemaRef.Context, BaseSpec); = InitializedEntity::InitializeBase(SemaRef.Context, BaseSpec,
IsInheritedVirtualBase);
InitializationKind InitKind InitializationKind InitKind
= InitializationKind::CreateDefault(Constructor->getLocation()); = InitializationKind::CreateDefault(Constructor->getLocation());
@ -1502,6 +1504,14 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
AllBaseFields[Member->getMember()] = Member; 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. // Push virtual bases before others.
for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(), for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
E = ClassDecl->vbases_end(); VBase != E; ++VBase) { E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
@ -1510,8 +1520,10 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
= AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) { = AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
AllToInit.push_back(Value); AllToInit.push_back(Value);
} else if (!AnyErrors) { } else if (!AnyErrors) {
bool IsInheritedVirtualBase = !DirectVBases.count(VBase);
CXXBaseOrMemberInitializer *CXXBaseInit = CXXBaseOrMemberInitializer *CXXBaseInit =
BuildImplicitBaseInitializer(*this, Constructor, VBase); BuildImplicitBaseInitializer(*this, Constructor, VBase,
IsInheritedVirtualBase);
if (!CXXBaseInit) { if (!CXXBaseInit) {
HadError = true; HadError = true;
@ -1533,7 +1545,8 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
AllToInit.push_back(Value); AllToInit.push_back(Value);
} else if (!AnyErrors) { } else if (!AnyErrors) {
CXXBaseOrMemberInitializer *CXXBaseInit = CXXBaseOrMemberInitializer *CXXBaseInit =
BuildImplicitBaseInitializer(*this, Constructor, Base); BuildImplicitBaseInitializer(*this, Constructor, Base,
/*IsInheritedVirtualBase=*/false);
if (!CXXBaseInit) { if (!CXXBaseInit) {
HadError = true; HadError = true;

View File

@ -1921,11 +1921,15 @@ InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index,
} }
InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context, InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context,
CXXBaseSpecifier *Base) CXXBaseSpecifier *Base,
bool IsInheritedVirtualBase)
{ {
InitializedEntity Result; InitializedEntity Result;
Result.Kind = EK_Base; Result.Kind = EK_Base;
Result.Base = Base; Result.Base = reinterpret_cast<uintptr_t>(Base);
if (IsInheritedVirtualBase)
Result.Base |= 0x01;
Result.Type = Base->getType(); Result.Type = Base->getType();
return Result; return Result;
} }

View File

@ -92,10 +92,11 @@ private:
unsigned Location; unsigned Location;
/// \brief When Kind == EK_Base, the base specifier that provides the /// \brief When Kind == EK_Base, the base specifier that provides the
/// base class. /// base class. The lower bit specifies whether the base is an inherited
CXXBaseSpecifier *Base; /// virtual base.
uintptr_t Base;
/// \brief When Kind = EK_ArrayElement or EK_VectorElement, the /// \brief When Kind == EK_ArrayElement or EK_VectorElement, the
/// index of the array or vector element being initialized. /// index of the array or vector element being initialized.
unsigned Index; unsigned Index;
}; };
@ -168,7 +169,8 @@ public:
/// \brief Create the initialization entity for a base class subobject. /// \brief Create the initialization entity for a base class subobject.
static InitializedEntity InitializeBase(ASTContext &Context, static InitializedEntity InitializeBase(ASTContext &Context,
CXXBaseSpecifier *Base); CXXBaseSpecifier *Base,
bool IsInheritedVirtualBase);
/// \brief Create the initialization entity for a member subobject. /// \brief Create the initialization entity for a member subobject.
static InitializedEntity InitializeMember(FieldDecl *Member, static InitializedEntity InitializeMember(FieldDecl *Member,
@ -204,7 +206,13 @@ public:
/// \brief Retrieve the base specifier. /// \brief Retrieve the base specifier.
CXXBaseSpecifier *getBaseSpecifier() const { CXXBaseSpecifier *getBaseSpecifier() const {
assert(getKind() == EK_Base && "Not a base specifier"); 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 /// \brief Determine the location of the 'return' keyword when initializing

View File

@ -104,8 +104,7 @@ namespace test2 {
C(); C();
}; };
// FIXME: It would be better if this said something about A being an inherited virtual base. class D : C { }; // expected-error {{inherited virtual base class 'test2::A' has private constructor}}
class D : C { }; // expected-error {{base class 'test2::A' has private constructor}}
D d; D d;
} }