diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-06-30 00:02:17 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-06-30 00:02:17 +0000 |
commit | 651185bf47b70cfeab77aa16a71a0836ae6814f8 (patch) | |
tree | 8fde5da93265d58d375acf98312db5d6355bba50 | |
parent | 86e35b3aba8fc31bcaa8dffb05eaaef2aea3bce5 (diff) | |
download | bcm5719-llvm-651185bf47b70cfeab77aa16a71a0836ae6814f8.tar.gz bcm5719-llvm-651185bf47b70cfeab77aa16a71a0836ae6814f8.zip |
A more detailed diagnosis of ill-formed ctor-initializer
list.
llvm-svn: 74480
-rw-r--r-- | clang/include/clang/AST/DeclCXX.h | 11 | ||||
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 23 | ||||
-rw-r--r-- | clang/test/SemaCXX/class-base-member-init.cpp | 4 |
4 files changed, 33 insertions, 15 deletions
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 2754c70f140..05383d885d5 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -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. diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index bffa70f18ee..8b596e1e7c2 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -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"); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index fffa66c68fc..e59236c8a4e 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -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; } } } diff --git a/clang/test/SemaCXX/class-base-member-init.cpp b/clang/test/SemaCXX/class-base-member-init.cpp index eca9fc34349..c38c3d3337e 100644 --- a/clang/test/SemaCXX/class-base-member-init.cpp +++ b/clang/test/SemaCXX/class-base-member-init.cpp @@ -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; |