diff options
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 21 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 | ||||
-rw-r--r-- | test/SemaTemplate/instantiate-anonymous-union.cpp | 6 |
3 files changed, 19 insertions, 11 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 4acde29b7b..f22a3e88b7 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -912,11 +912,21 @@ 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 *GetKeyForMember(CXXBaseOrMemberInitializer *Member, - bool MemberMaybeAnon=false) { + bool MemberMaybeAnon = false) { // For fields injected into the class via declaration of an anonymous union, // use its anonymous union class declaration as the unique key. - if (FieldDecl *Field = Member->getMember()) { + if (Member->isMemberInitializer()) { + FieldDecl *Field = Member->getMember(); + // After BuildBaseOrMemberInitializers call, Field is the anonymous union // data member of the class. Data member used in the initializer list is // in AnonUnionMember field. @@ -929,7 +939,8 @@ static void *GetKeyForMember(CXXBaseOrMemberInitializer *Member, } return static_cast<void *>(Field); } - return static_cast<RecordType *>(Member->getBaseClass()); + + return GetKeyForBase(QualType(Member->getBaseClass(), 0)); } void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, @@ -1003,7 +1014,7 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(), E = ClassDecl->vbases_end(); VBase != E; ++VBase) - AllBaseOrMembers.push_back(VBase->getType()->getAs<RecordType>()); + AllBaseOrMembers.push_back(GetKeyForBase(VBase->getType())); for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), E = ClassDecl->bases_end(); Base != E; ++Base) { @@ -1011,7 +1022,7 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, // first. if (Base->isVirtual()) continue; - AllBaseOrMembers.push_back(Base->getType()->getAs<RecordType>()); + AllBaseOrMembers.push_back(GetKeyForBase(Base->getType())); } for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 82228143e4..99b237d04e 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1145,7 +1145,6 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, QualType BaseType(Init->getBaseClass(), 0); BaseType = SubstType(BaseType, TemplateArgs, Init->getSourceLocation(), New->getDeclName()); - BaseType = Context.getCanonicalType(BaseType); NewInit = BuildBaseInitializer(BaseType, (Expr **)NewArgs.data(), @@ -1158,7 +1157,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, // Is this an anonymous union? if (FieldDecl *UnionInit = Init->getAnonUnionMember()) - Member = cast<FieldDecl>(UnionInit); + Member = cast<FieldDecl>(FindInstantiatedDecl(UnionInit)); else Member = cast<FieldDecl>(FindInstantiatedDecl(Init->getMember())); diff --git a/test/SemaTemplate/instantiate-anonymous-union.cpp b/test/SemaTemplate/instantiate-anonymous-union.cpp index 2c1e9d4c19..375c1da3ca 100644 --- a/test/SemaTemplate/instantiate-anonymous-union.cpp +++ b/test/SemaTemplate/instantiate-anonymous-union.cpp @@ -1,6 +1,4 @@ -// RUN: clang-cc -fsyntax-only %s - -// FIXME: We need to test anonymous structs/unions in templates for real. +// RUN: clang-cc -fsyntax-only %s -Wall template <typename T> class A { struct { }; }; @@ -30,4 +28,4 @@ template <typename T> struct C { C(void* b) : b(b) { } }; -C<int> c0; +C<int> c0(0); |