[cfe-commits] r100179 - in /cfe/trunk: lib/Sema/SemaDeclCXX.cpp test/SemaCXX/class-base-member-init.cpp

Anders Carlsson andersca at mac.com
Thu Apr 1 22:42:15 PDT 2010


Author: andersca
Date: Fri Apr  2 00:42:15 2010
New Revision: 100179

URL: http://llvm.org/viewvc/llvm-project?rev=100179&view=rev
Log:
Diagnose multiple base and member initializers in class templates.

Modified:
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/SemaCXX/class-base-member-init.cpp

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=100179&r1=100178&r2=100179&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Apr  2 00:42:15 2010
@@ -1430,12 +1430,9 @@
                                   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 @@
   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 @@
   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 @@
     // 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 @@
   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 @@
   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);

Modified: cfe/trunk/test/SemaCXX/class-base-member-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/class-base-member-init.cpp?rev=100179&r1=100178&r2=100179&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/class-base-member-init.cpp (original)
+++ cfe/trunk/test/SemaCXX/class-base-member-init.cpp Fri Apr  2 00:42:15 2010
@@ -26,3 +26,28 @@
 };
 
 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'}}
+  };
+}





More information about the cfe-commits mailing list