]> granicus.if.org Git - clang/commitdiff
A more detailed diagnosis of ill-formed ctor-initializer
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 30 Jun 2009 00:02:17 +0000 (00:02 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 30 Jun 2009 00:02:17 +0000 (00:02 +0000)
list.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74480 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclCXX.h
lib/AST/DeclCXX.cpp
lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/class-base-member-init.cpp

index 2754c70f140ef1dd9d0454acd77fdc2cc897be5f..05383d885d5bc3cfc81a755823a52fce62521dd8 100644 (file)
@@ -588,15 +588,20 @@ class CXXBaseOrMemberInitializer {
   /// Args - The arguments used to initialize the base or member.
   Expr **Args;
   unsigned NumArgs;
+  
+  /// IdLoc - Location of the id in ctor-initializer list.
+  SourceLocation IdLoc;
 
 public:
   /// CXXBaseOrMemberInitializer - Creates a new base-class initializer.
   explicit 
-  CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs);
+  CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs,
+                             SourceLocation L);
 
   /// CXXBaseOrMemberInitializer - Creates a new member initializer.
   explicit 
-  CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs);
+  CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs,
+                             SourceLocation L);
 
   /// ~CXXBaseOrMemberInitializer - Destroy the base or member initializer.
   ~CXXBaseOrMemberInitializer();
@@ -653,6 +658,8 @@ public:
       return 0;
   }
 
+  SourceLocation getSourceLocation() const { return IdLoc; }
+  
   /// begin() - Retrieve an iterator to the first initializer argument.
   arg_iterator       begin()       { return Args; }
   /// begin() - Retrieve an iterator to the first initializer argument.
index bffa70f18eeb783166c547b91eecd60ace912b87..8b596e1e7c22113478eff7c35ce3010b60b21fb1 100644 (file)
@@ -294,8 +294,9 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const {
 }
 
 CXXBaseOrMemberInitializer::
-CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs) 
-  : Args(0), NumArgs(0) {
+CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs,
+                           SourceLocation L) 
+  : Args(0), NumArgs(0), IdLoc(L) {
   BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr());
   assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer");
   BaseOrMember |= 0x01;
@@ -309,8 +310,9 @@ CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs)
 }
 
 CXXBaseOrMemberInitializer::
-CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs)
-  : Args(0), NumArgs(0) {
+CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs,
+                           SourceLocation L)
+  : Args(0), NumArgs(0), IdLoc(L) {
   BaseOrMember = reinterpret_cast<uintptr_t>(Member);
   assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer");  
 
index fffa66c68fc81b0ee3de6ea0cdabbe6626421815..e59236c8a4efc404ad6d6f0e976b3eb31dabc645 100644 (file)
@@ -688,7 +688,8 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
 
   if (Member) {
     // FIXME: Perform direct initialization of the member.
-    return new CXXBaseOrMemberInitializer(Member, (Expr **)Args, NumArgs);
+    return new CXXBaseOrMemberInitializer(Member, (Expr **)Args, NumArgs, 
+                                          IdLoc);
   }
 
   // It didn't name a member, so see if it names a class.
@@ -750,7 +751,8 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
     return Diag(IdLoc, diag::err_base_init_direct_and_virtual)
       << MemberOrBase << SourceRange(IdLoc, RParenLoc);
 
-  return new CXXBaseOrMemberInitializer(BaseType, (Expr **)Args, NumArgs);
+  return new CXXBaseOrMemberInitializer(BaseType, (Expr **)Args, NumArgs, 
+                                        IdLoc);
 }
 
 void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, 
@@ -766,22 +768,27 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
     Diag(ColonLoc, diag::err_only_constructors_take_base_inits);
     return;
   }
-  llvm::DenseSet<uintptr_t>Members;
+  llvm::DenseMap<uintptr_t, CXXBaseOrMemberInitializer *>Members;
   
   for (unsigned i = 0; i < NumMemInits; i++) {
     CXXBaseOrMemberInitializer *Member = 
       static_cast<CXXBaseOrMemberInitializer*>(MemInits[i]);
-    if (Members.count(Member->getBaseOrMember()) == 0)
-      Members.insert(Member->getBaseOrMember());
+    CXXBaseOrMemberInitializer *&PrevMember = Members[Member->getBaseOrMember()];
+    if (!PrevMember)
+      PrevMember = Member;
     else {
       if (FieldDecl *Field = Member->getMember())
-        Diag(ColonLoc, diag::error_multiple_mem_initialization)
-          << Field->getNameAsString();
+        Diag(Member->getSourceLocation(), 
+             diag::error_multiple_mem_initialization)
+        << Field->getNameAsString();
       else if (Type *BaseClass = Member->getBaseClass())
-        Diag(ColonLoc, diag::error_multiple_base_initialization)
+        Diag(Member->getSourceLocation(), 
+             diag::error_multiple_base_initialization)
           << BaseClass->getDesugaredType(true);
       else
         assert(false && "ActOnMemInitializers - neither field or base");
+      Diag(PrevMember->getSourceLocation(), diag::note_previous_initializer) 
+        << 0;
     }
   }
 }
index eca9fc343490a501ec7f2db46385c94ed58d1dc1..c38c3d3337e719162b9bfa7c935574c58d1942b2 100644 (file)
@@ -7,7 +7,9 @@ public:
 
 struct D : S {
   D() : b1(0), b2(1), b1(0), S(), S() {} // expected-error {{multiple initializations given for non-static member 'b1'}} \
-                                        // expected-error {{multiple initializations given for base 'class S'}}
+                                        // expected-note {{previous initialization is here}} \
+                                        // expected-error {{multiple initializations given for base 'class S'}} \
+                                        // expected-note {{previous initialization is here}}
 
   int b1;
   int b2;