Skip to content

Commit 43c64af

Browse files
author
Anders Carlsson
committed
Keep tack of whether a base in an InitializedEntity is an inherited virtual base or not. Use this in CheckConstructorAccess.
llvm-svn: 102020
1 parent 53fac69 commit 43c64af

File tree

6 files changed

+51
-19
lines changed

6 files changed

+51
-19
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,10 @@ def err_access_ctor :
462462
def err_access_ctor_base :
463463
Error<"base class %0 has %select{private|protected}1 constructor">,
464464
NoSFINAE;
465+
def err_access_ctor_vbase :
466+
Error<"inherited virtual base class %0 has "
467+
"%select{private|protected}1 constructor">,
468+
NoSFINAE;
465469
def err_access_dtor_base :
466470
Error<"base class %0 has %select{private|protected}1 destructor">,
467471
NoSFINAE;

clang/lib/Sema/SemaAccess.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,12 +1143,16 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
11431143
AccessEntity.setDiag(diag::err_access_ctor);
11441144
break;
11451145

1146-
case InitializedEntity::EK_Base:
1147-
AccessEntity.setDiag(PDiag(diag::err_access_ctor_base)
1146+
case InitializedEntity::EK_Base: {
1147+
unsigned DiagID = Entity.isInheritedVirtualBase() ?
1148+
diag::err_access_ctor_vbase : diag::err_access_ctor_base;
1149+
AccessEntity.setDiag(PDiag(DiagID)
11481150
<< Entity.getBaseSpecifier()->getType());
11491151
break;
11501152
}
11511153

1154+
}
1155+
11521156
return CheckAccess(*this, UseLoc, AccessEntity);
11531157
}
11541158

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,7 +1384,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
13841384

13851385
// Initialize the base.
13861386
InitializedEntity BaseEntity =
1387-
InitializedEntity::InitializeBase(Context, BaseSpec);
1387+
InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec);
13881388
InitializationKind Kind =
13891389
InitializationKind::CreateDirect(BaseLoc, LParenLoc, RParenLoc);
13901390

@@ -1435,9 +1435,11 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
14351435
static CXXBaseOrMemberInitializer *
14361436
BuildImplicitBaseInitializer(Sema &SemaRef,
14371437
const CXXConstructorDecl *Constructor,
1438-
CXXBaseSpecifier *BaseSpec) {
1438+
CXXBaseSpecifier *BaseSpec,
1439+
bool IsInheritedVirtualBase) {
14391440
InitializedEntity InitEntity
1440-
= InitializedEntity::InitializeBase(SemaRef.Context, BaseSpec);
1441+
= InitializedEntity::InitializeBase(SemaRef.Context, BaseSpec,
1442+
IsInheritedVirtualBase);
14411443

14421444
InitializationKind InitKind
14431445
= InitializationKind::CreateDefault(Constructor->getLocation());
@@ -1502,6 +1504,14 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
15021504
AllBaseFields[Member->getMember()] = Member;
15031505
}
15041506

1507+
// Keep track of the direct virtual bases.
1508+
llvm::SmallPtrSet<CXXBaseSpecifier *, 16> DirectVBases;
1509+
for (CXXRecordDecl::base_class_iterator I = ClassDecl->bases_begin(),
1510+
E = ClassDecl->bases_end(); I != E; ++I) {
1511+
if (I->isVirtual())
1512+
DirectVBases.insert(I);
1513+
}
1514+
15051515
// Push virtual bases before others.
15061516
for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
15071517
E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
@@ -1510,8 +1520,10 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
15101520
= AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
15111521
AllToInit.push_back(Value);
15121522
} else if (!AnyErrors) {
1523+
bool IsInheritedVirtualBase = !DirectVBases.count(VBase);
15131524
CXXBaseOrMemberInitializer *CXXBaseInit =
1514-
BuildImplicitBaseInitializer(*this, Constructor, VBase);
1525+
BuildImplicitBaseInitializer(*this, Constructor, VBase,
1526+
IsInheritedVirtualBase);
15151527

15161528
if (!CXXBaseInit) {
15171529
HadError = true;
@@ -1533,8 +1545,9 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
15331545
AllToInit.push_back(Value);
15341546
} else if (!AnyErrors) {
15351547
CXXBaseOrMemberInitializer *CXXBaseInit =
1536-
BuildImplicitBaseInitializer(*this, Constructor, Base);
1537-
1548+
BuildImplicitBaseInitializer(*this, Constructor, Base,
1549+
/*IsInheritedVirtualBase=*/false);
1550+
15381551
if (!CXXBaseInit) {
15391552
HadError = true;
15401553
continue;

clang/lib/Sema/SemaInit.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1921,11 +1921,15 @@ InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index,
19211921
}
19221922

19231923
InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context,
1924-
CXXBaseSpecifier *Base)
1924+
CXXBaseSpecifier *Base,
1925+
bool IsInheritedVirtualBase)
19251926
{
19261927
InitializedEntity Result;
19271928
Result.Kind = EK_Base;
1928-
Result.Base = Base;
1929+
Result.Base = reinterpret_cast<uintptr_t>(Base);
1930+
if (IsInheritedVirtualBase)
1931+
Result.Base |= 0x01;
1932+
19291933
Result.Type = Base->getType();
19301934
return Result;
19311935
}

clang/lib/Sema/SemaInit.h

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,12 @@ class InitializedEntity {
9292
unsigned Location;
9393

9494
/// \brief When Kind == EK_Base, the base specifier that provides the
95-
/// base class.
96-
CXXBaseSpecifier *Base;
95+
/// base class. The lower bit specifies whether the base is an inherited
96+
/// virtual base.
97+
uintptr_t Base;
9798

98-
/// \brief When Kind = EK_ArrayElement or EK_VectorElement, the
99-
/// index of the array or vector element being initialized.
99+
/// \brief When Kind == EK_ArrayElement or EK_VectorElement, the
100+
/// index of the array or vector element being initialized.
100101
unsigned Index;
101102
};
102103

@@ -168,7 +169,8 @@ class InitializedEntity {
168169

169170
/// \brief Create the initialization entity for a base class subobject.
170171
static InitializedEntity InitializeBase(ASTContext &Context,
171-
CXXBaseSpecifier *Base);
172+
CXXBaseSpecifier *Base,
173+
bool IsInheritedVirtualBase);
172174

173175
/// \brief Create the initialization entity for a member subobject.
174176
static InitializedEntity InitializeMember(FieldDecl *Member,
@@ -204,7 +206,13 @@ class InitializedEntity {
204206
/// \brief Retrieve the base specifier.
205207
CXXBaseSpecifier *getBaseSpecifier() const {
206208
assert(getKind() == EK_Base && "Not a base specifier");
207-
return Base;
209+
return reinterpret_cast<CXXBaseSpecifier *>(Base & ~0x1);
210+
}
211+
212+
/// \brief Return whether the base is an inherited virtual base.
213+
bool isInheritedVirtualBase() const {
214+
assert(getKind() == EK_Base && "Not a base specifier");
215+
return Base & 0x1;
208216
}
209217

210218
/// \brief Determine the location of the 'return' keyword when initializing

clang/test/CXX/class.access/p4.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,8 @@ namespace test2 {
103103
public:
104104
C();
105105
};
106-
107-
// FIXME: It would be better if this said something about A being an inherited virtual base.
108-
class D : C { }; // expected-error {{base class 'test2::A' has private constructor}}
106+
107+
class D : C { }; // expected-error {{inherited virtual base class 'test2::A' has private constructor}}
109108
D d;
110109
}
111110

0 commit comments

Comments
 (0)