[cfe-commits] r100923 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDeclCXX.cpp test/SemaCXX/class-base-member-init.cpp test/SemaCXX/constructor-initializer.cpp test/SemaCXX/warn-reorder-ctor-initialization.cpp
John McCall
rjmccall at apple.com
Sat Apr 10 02:28:51 PDT 2010
Author: rjmccall
Date: Sat Apr 10 04:28:51 2010
New Revision: 100923
URL: http://llvm.org/viewvc/llvm-project?rev=100923&view=rev
Log:
Diagnose more cases of initializing distinct members of an anonymous union
member. Use a better diagnostic for this case. Also fix a bug with nested
anonymous structs/unions for -Wreorder; this last was PR6575.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/test/SemaCXX/class-base-member-init.cpp
cfe/trunk/test/SemaCXX/constructor-initializer.cpp
cfe/trunk/test/SemaCXX/warn-reorder-ctor-initialization.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=100923&r1=100922&r2=100923&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Apr 10 04:28:51 2010
@@ -2461,10 +2461,11 @@
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 <
+def err_multiple_mem_initialization : Error <
+ "multiple initializations given for non-static member %0">;
+def err_multiple_mem_union_initialization : Error <
+ "initializing multiple members of anonymous union">;
+def err_multiple_base_initialization : Error <
"multiple initializations given for base %0">;
def err_mem_init_not_member_or_class : Error<
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=100923&r1=100922&r2=100923&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sat Apr 10 04:28:51 2010
@@ -1660,11 +1660,20 @@
if (MemberMaybeAnon && Field->isAnonymousStructOrUnion())
Field = Member->getAnonUnionMember();
- // If the field is a member of an anonymous union, we use record decl of the
- // union as the key.
+ // If the field is a member of an anonymous struct or union, our key
+ // is the anonymous record decl that's a direct child of the class.
RecordDecl *RD = Field->getParent();
- if (RD->isAnonymousStructOrUnion() && RD->isUnion())
+ if (RD->isAnonymousStructOrUnion()) {
+ while (true) {
+ RecordDecl *Parent = cast<RecordDecl>(RD->getDeclContext());
+ if (Parent->isAnonymousStructOrUnion())
+ RD = Parent;
+ else
+ break;
+ }
+
return static_cast<void *>(RD);
+ }
return static_cast<void *>(Field);
}
@@ -1754,6 +1763,71 @@
}
}
+namespace {
+bool CheckRedundantInit(Sema &S,
+ CXXBaseOrMemberInitializer *Init,
+ CXXBaseOrMemberInitializer *&PrevInit) {
+ if (!PrevInit) {
+ PrevInit = Init;
+ return false;
+ }
+
+ if (FieldDecl *Field = Init->getMember())
+ S.Diag(Init->getSourceLocation(),
+ diag::err_multiple_mem_initialization)
+ << Field->getDeclName()
+ << Init->getSourceRange();
+ else {
+ Type *BaseClass = Init->getBaseClass();
+ assert(BaseClass && "neither field nor base");
+ S.Diag(Init->getSourceLocation(),
+ diag::err_multiple_base_initialization)
+ << QualType(BaseClass, 0)
+ << Init->getSourceRange();
+ }
+ S.Diag(PrevInit->getSourceLocation(), diag::note_previous_initializer)
+ << 0 << PrevInit->getSourceRange();
+
+ return true;
+}
+
+typedef std::pair<NamedDecl *, CXXBaseOrMemberInitializer *> UnionEntry;
+typedef llvm::DenseMap<RecordDecl*, UnionEntry> RedundantUnionMap;
+
+bool CheckRedundantUnionInit(Sema &S,
+ CXXBaseOrMemberInitializer *Init,
+ RedundantUnionMap &Unions) {
+ FieldDecl *Field = Init->getMember();
+ RecordDecl *Parent = Field->getParent();
+ if (!Parent->isAnonymousStructOrUnion())
+ return false;
+
+ NamedDecl *Child = Field;
+ do {
+ if (Parent->isUnion()) {
+ UnionEntry &En = Unions[Parent];
+ if (En.first && En.first != Child) {
+ S.Diag(Init->getSourceLocation(),
+ diag::err_multiple_mem_union_initialization)
+ << Field->getDeclName()
+ << Init->getSourceRange();
+ S.Diag(En.second->getSourceLocation(), diag::note_previous_initializer)
+ << 0 << En.second->getSourceRange();
+ return true;
+ } else if (!En.first) {
+ En.first = Child;
+ En.second = Init;
+ }
+ }
+
+ Child = Parent;
+ Parent = cast<RecordDecl>(Parent->getDeclContext());
+ } while (Parent->isAnonymousStructOrUnion());
+
+ return false;
+}
+}
+
/// ActOnMemInitializers - Handle the member initializers for a constructor.
void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
SourceLocation ColonLoc,
@@ -1774,34 +1848,29 @@
CXXBaseOrMemberInitializer **MemInits =
reinterpret_cast<CXXBaseOrMemberInitializer **>(meminits);
-
+
+ // Mapping for the duplicate initializers check.
+ // For member initializers, this is keyed with a FieldDecl*.
+ // For base initializers, this is keyed with a Type*.
llvm::DenseMap<void*, CXXBaseOrMemberInitializer *> Members;
+
+ // Mapping for the inconsistent anonymous-union initializers check.
+ RedundantUnionMap MemberUnions;
+
bool HadError = false;
for (unsigned i = 0; i < NumMemInits; i++) {
- CXXBaseOrMemberInitializer *Member = MemInits[i];
+ CXXBaseOrMemberInitializer *Init = MemInits[i];
- void *KeyToMember = GetKeyForMember(Context, Member);
- CXXBaseOrMemberInitializer *&PrevMember = Members[KeyToMember];
- if (!PrevMember) {
- PrevMember = Member;
- continue;
+ if (Init->isMemberInitializer()) {
+ FieldDecl *Field = Init->getMember();
+ if (CheckRedundantInit(*this, Init, Members[Field]) ||
+ CheckRedundantUnionInit(*this, Init, MemberUnions))
+ HadError = true;
+ } else {
+ void *Key = GetKeyForBase(Context, QualType(Init->getBaseClass(), 0));
+ if (CheckRedundantInit(*this, Init, Members[Key]))
+ HadError = true;
}
- 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)
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=100923&r1=100922&r2=100923&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/class-base-member-init.cpp (original)
+++ cfe/trunk/test/SemaCXX/class-base-member-init.cpp Sat Apr 10 04:28:51 2010
@@ -51,3 +51,26 @@
t(2) { } // expected-error {{multiple initializations given for non-static member 't'}}
};
}
+
+namespace test4 {
+ class A {
+ union {
+ struct {
+ int a;
+ int b;
+ };
+
+ int c;
+
+ union {
+ int d;
+ int e;
+ };
+ };
+
+ A(char _) : a(0), b(0) {}
+ A(short _) : a(0), c(0) {} // expected-error {{initializing multiple members of anonymous union}} expected-note {{previous initialization is here}}
+ A(int _) : d(0), e(0) {} // expected-error {{initializing multiple members of anonymous union}} expected-note {{previous initialization is here}}
+ A(long _) : a(0), d(0) {} // expected-error {{initializing multiple members of anonymous union}} expected-note {{previous initialization is here}}
+ };
+}
Modified: cfe/trunk/test/SemaCXX/constructor-initializer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constructor-initializer.cpp?rev=100923&r1=100922&r2=100923&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constructor-initializer.cpp (original)
+++ cfe/trunk/test/SemaCXX/constructor-initializer.cpp Sat Apr 10 04:28:51 2010
@@ -73,8 +73,9 @@
union { int a; char* p; };
union { int b; double d; };
- U() : a(1), p(0), d(1.0) {} // expected-error {{multiple initializations given for non-static member 'p'}} \
- // expected-note {{previous initialization is here}}
+ U() : a(1), // expected-note {{previous initialization is here}}
+ p(0), // expected-error {{initializing multiple members of anonymous union}}
+ d(1.0) {}
};
struct V {};
Modified: cfe/trunk/test/SemaCXX/warn-reorder-ctor-initialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-reorder-ctor-initialization.cpp?rev=100923&r1=100922&r2=100923&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-reorder-ctor-initialization.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-reorder-ctor-initialization.cpp Sat Apr 10 04:28:51 2010
@@ -108,3 +108,15 @@
Foo y;
};
}
+
+// PR6575: this should not crash
+namespace test3 {
+ struct MyClass {
+ MyClass() : m_int(0) {}
+ union {
+ struct {
+ int m_int;
+ };
+ };
+ };
+}
More information about the cfe-commits
mailing list