]> granicus.if.org Git - clang/commitdiff
Diagnose multiple initialzation of data-member/base
authorFariborz Jahanian <fjahanian@apple.com>
Mon, 29 Jun 2009 22:33:26 +0000 (22:33 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Mon, 29 Jun 2009 22:33:26 +0000 (22:33 +0000)
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

include/clang/AST/DeclCXX.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/class-base-member-init.cpp [new file with mode: 0644]

index 24c9d3e15dcd3919fbc1dec20a5767a2a4a8a671..2754c70f140ef1dd9d0454acd77fdc2cc897be5f 100644 (file)
@@ -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; }
index 4ba1083089e6d9d59dc2804ef11710a4f7f7cf6f..2af10b22fb687bf78a314026dc947fab4dabd146 100644 (file)
@@ -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">;
index e9a585f283695c07df55116578f159c0f4d547f3..fffa66c68fc81b0ee3de6ea0cdabbe6626421815 100644 (file)
@@ -766,6 +766,24 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
     Diag(ColonLoc, diag::err_only_constructors_take_base_inits);
     return;
   }
+  llvm::DenseSet<uintptr_t>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());
+    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 (file)
index 0000000..eca9fc3
--- /dev/null
@@ -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;
+
+};
+
+