summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2010-04-21 19:52:01 +0000
committerAnders Carlsson <andersca@mac.com>2010-04-21 19:52:01 +0000
commit43c64af5f0fba76d5117668183c7b19ece140fdc (patch)
treecb3ea5fd978e337ef26f95f4f3aec710bb9d4604
parent53fac692fa06c812490bbbc25cb14dae67c95685 (diff)
downloadbcm5719-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.td4
-rw-r--r--clang/lib/Sema/SemaAccess.cpp8
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp25
-rw-r--r--clang/lib/Sema/SemaInit.cpp8
-rw-r--r--clang/lib/Sema/SemaInit.h20
-rw-r--r--clang/test/CXX/class.access/p4.cpp5
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;
}
OpenPOWER on IntegriCloud