forked from OSchip/llvm-project
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:
parent
53fac692fa
commit
43c64af5f0
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue