From: Fariborz Jahanian Date: Mon, 29 Jun 2009 22:33:26 +0000 (+0000) Subject: Diagnose multiple initialzation of data-member/base X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7881a0565893f1da6faafbd86377f5b50e4376a5;p=clang Diagnose multiple initialzation of data-member/base in the ctor-initializer list. More to come. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74465 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 24c9d3e15d..2754c70f14 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -609,6 +609,10 @@ public: /// arguments. typedef Expr * const * arg_const_iterator; + /// getBaseOrMember - get the generic 'member' representing either the field + /// or a base class. + uintptr_t getBaseOrMember() const { return BaseOrMember; } + /// isBaseInitializer - Returns true when this initializer is /// initializing a base class. bool isBaseInitializer() const { return (BaseOrMember & 0x1) != 0; } diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 4ba1083089..2af10b22fb 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1579,6 +1579,12 @@ def err_overload_multiple_match : Error< def err_only_constructors_take_base_inits : Error< "only constructors take base initializers">; +def error_multiple_mem_initialization : Error < + "multiple initializations given for non-static member '%0'">; + +def error_multiple_base_initialization : Error < + "multiple initializations given for base %0">; + def err_mem_init_not_member_or_class : Error< "member initializer %0 does not name a non-static data member or base " "class">; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index e9a585f283..fffa66c68f 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -766,6 +766,24 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, Diag(ColonLoc, diag::err_only_constructors_take_base_inits); return; } + llvm::DenseSetMembers; + + for (unsigned i = 0; i < NumMemInits; i++) { + CXXBaseOrMemberInitializer *Member = + static_cast(MemInits[i]); + if (Members.count(Member->getBaseOrMember()) == 0) + Members.insert(Member->getBaseOrMember()); + else { + if (FieldDecl *Field = Member->getMember()) + Diag(ColonLoc, diag::error_multiple_mem_initialization) + << Field->getNameAsString(); + else if (Type *BaseClass = Member->getBaseClass()) + Diag(ColonLoc, diag::error_multiple_base_initialization) + << BaseClass->getDesugaredType(true); + else + assert(false && "ActOnMemInitializers - neither field or base"); + } + } } namespace { diff --git a/test/SemaCXX/class-base-member-init.cpp b/test/SemaCXX/class-base-member-init.cpp new file mode 100644 index 0000000000..eca9fc3434 --- /dev/null +++ b/test/SemaCXX/class-base-member-init.cpp @@ -0,0 +1,17 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +class S { +public: + S (); +}; + +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'}} + + int b1; + int b2; + +}; + +