aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2010-04-02 05:42:15 +0000
committerAnders Carlsson <andersca@mac.com>2010-04-02 05:42:15 +0000
commitea356fb65cc844abeab1176f6333a86b69644735 (patch)
tree2f5f47917ba2d6e9e98d1cc541dc90ec32947142
parentec3332bcae6466dc69227742d2c4145fbe88e975 (diff)
Diagnose multiple base and member initializers in class templates.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100179 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaDeclCXX.cpp86
-rw-r--r--test/SemaCXX/class-base-member-init.cpp25
2 files changed, 65 insertions, 46 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 2289120bab..c77ff97f66 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1430,12 +1430,9 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
CXXBaseOrMemberInitializer **Initializers,
unsigned NumInitializers,
bool AnyErrors) {
-// assert((Constructor->isImplicit() == IsImplicitConstructor));
-
// We need to build the initializer AST according to order of construction
// and not what user specified in the Initializers list.
- CXXRecordDecl *ClassDecl
- = cast<CXXRecordDecl>(Constructor->getDeclContext())->getDefinition();
+ CXXRecordDecl *ClassDecl = Constructor->getParent()->getDefinition();
if (!ClassDecl)
return true;
@@ -1670,18 +1667,15 @@ static void *GetKeyForTopLevelField(FieldDecl *Field) {
return static_cast<void *>(Field);
}
-static void *GetKeyForBase(QualType BaseType) {
- if (const RecordType *RT = BaseType->getAs<RecordType>())
- return (void *)RT;
-
- assert(0 && "Unexpected base type!");
- return 0;
+static void *GetKeyForBase(ASTContext &Context, QualType BaseType) {
+ return Context.getCanonicalType(BaseType).getTypePtr();
}
-static void *GetKeyForMember(CXXBaseOrMemberInitializer *Member,
+static void *GetKeyForMember(ASTContext &Context,
+ CXXBaseOrMemberInitializer *Member,
bool MemberMaybeAnon = false) {
if (!Member->isMemberInitializer())
- return GetKeyForBase(QualType(Member->getBaseClass(), 0));
+ return GetKeyForBase(Context, QualType(Member->getBaseClass(), 0));
// For fields injected into the class via declaration of an anonymous union,
// use its anonymous union class declaration as the unique key.
@@ -1726,7 +1720,8 @@ DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef,
for (CXXRecordDecl::base_class_const_iterator VBase =
ClassDecl->vbases_begin(),
E = ClassDecl->vbases_end(); VBase != E; ++VBase)
- AllBaseOrMembers.push_back(GetKeyForBase(VBase->getType()));
+ AllBaseOrMembers.push_back(GetKeyForBase(SemaRef.Context,
+ VBase->getType()));
for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(),
E = ClassDecl->bases_end(); Base != E; ++Base) {
@@ -1734,7 +1729,8 @@ DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef,
// first.
if (Base->isVirtual())
continue;
- AllBaseOrMembers.push_back(GetKeyForBase(Base->getType()));
+ AllBaseOrMembers.push_back(GetKeyForBase(SemaRef.Context,
+ Base->getType()));
}
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
@@ -1746,7 +1742,7 @@ DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef,
CXXBaseOrMemberInitializer *PrevMember = 0;
for (unsigned i = 0; i < NumMemInits; i++) {
CXXBaseOrMemberInitializer *Member = MemInits[i];
- void *MemberInCtorList = GetKeyForMember(Member, true);
+ void *MemberInCtorList = GetKeyForMember(SemaRef.Context, Member, true);
for (; curIndex < Last; curIndex++)
if (MemberInCtorList == AllBaseOrMembers[curIndex])
@@ -1807,40 +1803,38 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
CXXBaseOrMemberInitializer **MemInits =
reinterpret_cast<CXXBaseOrMemberInitializer **>(meminits);
- if (!Constructor->isDependentContext()) {
- llvm::DenseMap<void*, CXXBaseOrMemberInitializer *> Members;
- bool err = false;
- for (unsigned i = 0; i < NumMemInits; i++) {
- CXXBaseOrMemberInitializer *Member = MemInits[i];
-
- void *KeyToMember = GetKeyForMember(Member);
- CXXBaseOrMemberInitializer *&PrevMember = Members[KeyToMember];
- if (!PrevMember) {
- PrevMember = Member;
- continue;
- }
- if (FieldDecl *Field = Member->getMember())
- Diag(Member->getSourceLocation(),
- diag::error_multiple_mem_initialization)
- << Field->getNameAsString()
- << Member->getSourceRange();
- else {
- Type *BaseClass = Member->getBaseClass();
- assert(BaseClass && "ActOnMemInitializers - neither field or base");
- Diag(Member->getSourceLocation(),
- diag::error_multiple_base_initialization)
- << QualType(BaseClass, 0)
- << Member->getSourceRange();
- }
- Diag(PrevMember->getSourceLocation(), diag::note_previous_initializer)
- << 0;
- err = true;
- }
+ llvm::DenseMap<void*, CXXBaseOrMemberInitializer *> Members;
+ bool HadError = false;
+ for (unsigned i = 0; i < NumMemInits; i++) {
+ CXXBaseOrMemberInitializer *Member = MemInits[i];
- if (err)
- return;
+ void *KeyToMember = GetKeyForMember(Context, Member);
+ CXXBaseOrMemberInitializer *&PrevMember = Members[KeyToMember];
+ if (!PrevMember) {
+ PrevMember = Member;
+ continue;
+ }
+ if (FieldDecl *Field = Member->getMember())
+ Diag(Member->getSourceLocation(),
+ diag::error_multiple_mem_initialization)
+ << Field->getNameAsString()
+ << Member->getSourceRange();
+ else {
+ Type *BaseClass = Member->getBaseClass();
+ assert(BaseClass && "ActOnMemInitializers - neither field or base");
+ Diag(Member->getSourceLocation(),
+ diag::error_multiple_base_initialization)
+ << QualType(BaseClass, 0)
+ << Member->getSourceRange();
+ }
+ Diag(PrevMember->getSourceLocation(), diag::note_previous_initializer)
+ << 0;
+ HadError = true;
}
+ if (HadError)
+ return;
+
DiagnoseBaseOrMemInitializerOrder(*this, Constructor, MemInits, NumMemInits);
SetBaseOrMemberInitializers(Constructor, MemInits, NumMemInits, AnyErrors);
diff --git a/test/SemaCXX/class-base-member-init.cpp b/test/SemaCXX/class-base-member-init.cpp
index 0821c34b02..7095d92d68 100644
--- a/test/SemaCXX/class-base-member-init.cpp
+++ b/test/SemaCXX/class-base-member-init.cpp
@@ -26,3 +26,28 @@ struct A {
};
A::A() : a(10), b(20) { }
+
+namespace Test1 {
+ template<typename T> struct A {};
+ template<typename T> struct B : A<T> {
+
+ B() : A<T>(), // expected-note {{previous initialization is here}}
+ A<T>() { } // expected-error {{multiple initializations given for base 'A<T>'}}
+ };
+}
+
+namespace Test2 {
+ template<typename T> struct A : T {
+ A() : T(), // expected-note {{previous initialization is here}}
+ T() { } // expected-error {{multiple initializations given for base 'T'}}
+ };
+}
+
+namespace Test3 {
+ template<typename T> struct A {
+ T t;
+
+ A() : t(1), // expected-note {{previous initialization is here}}
+ t(2) { } // expected-error {{multiple initializations given for non-static member 't'}}
+ };
+}