]> granicus.if.org Git - clang/commitdiff
Don't assume that a base is always a RecordType, it can also be a TemplateSpecializat...
authorAnders Carlsson <andersca@mac.com>
Tue, 1 Sep 2009 06:22:14 +0000 (06:22 +0000)
committerAnders Carlsson <andersca@mac.com>
Tue, 1 Sep 2009 06:22:14 +0000 (06:22 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80662 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaTemplate/instantiate-anonymous-union.cpp

index 4acde29b7b53e257d541e42bb229f41720668193..f22a3e88b72d28734a6d054b77d7c12e8bce09c2 100644 (file)
@@ -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(),
index 82228143e4bfb77037cd3383c70611207c703799..99b237d04e45c249f3fb0ff6d23365d0598917e5 100644 (file)
@@ -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()));
       
index 2c1e9d4c1919e1780b0403c36bc0c7d1a6f7e55d..375c1da3ca59a3ed93d90178ae30b3f11f07102a 100644 (file)
@@ -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);