[cfe-commits] r104292 - in /cfe/trunk: lib/Sema/SemaDeclCXX.cpp test/CodeGenCXX/anonymous-union-member-initializer.cpp
John McCall
rjmccall at apple.com
Thu May 20 16:23:51 PDT 2010
Author: rjmccall
Date: Thu May 20 18:23:51 2010
New Revision: 104292
URL: http://llvm.org/viewvc/llvm-project?rev=104292&view=rev
Log:
Be sure to apply initializers to members of anonymous structs and unions
recursively, e.g. so that members of anonymous unions inside anonymous structs
still get initialized. Also generate default constructor calls for anonymous
struct members when necessary.
Modified:
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/test/CodeGenCXX/anonymous-union-member-initializer.cpp
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=104292&r1=104291&r2=104292&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu May 20 18:23:51 2010
@@ -1717,6 +1717,81 @@
CXXMemberInit = 0;
return false;
}
+
+namespace {
+struct BaseAndFieldInfo {
+ Sema &S;
+ CXXConstructorDecl *Ctor;
+ bool AnyErrorsInInits;
+ ImplicitInitializerKind IIK;
+ llvm::DenseMap<const void *, CXXBaseOrMemberInitializer*> AllBaseFields;
+ llvm::SmallVector<CXXBaseOrMemberInitializer*, 8> AllToInit;
+
+ BaseAndFieldInfo(Sema &S, CXXConstructorDecl *Ctor, bool ErrorsInInits)
+ : S(S), Ctor(Ctor), AnyErrorsInInits(ErrorsInInits) {
+ // FIXME: Handle implicit move constructors.
+ if (Ctor->isImplicit() && Ctor->isCopyConstructor())
+ IIK = IIK_Copy;
+ else
+ IIK = IIK_Default;
+ }
+};
+}
+
+static bool CollectFieldInitializer(BaseAndFieldInfo &Info,
+ FieldDecl *Top, FieldDecl *Field) {
+
+ // Overwhelmingly common case: we have a direct initializer for this field.
+ if (CXXBaseOrMemberInitializer *Init = Info.AllBaseFields.lookup(Field)) {
+ Info.AllToInit.push_back(Init);
+
+ if (Field != Top) {
+ Init->setMember(Top);
+ Init->setAnonUnionMember(Field);
+ }
+ return false;
+ }
+
+ if (Info.IIK == IIK_Default && Field->isAnonymousStructOrUnion()) {
+ const RecordType *FieldClassType = Field->getType()->getAs<RecordType>();
+ assert(FieldClassType && "anonymous struct/union without record type");
+
+ // Walk through the members, tying in any initializers for fields
+ // we find. The earlier semantic checks should prevent redundant
+ // initialization of union members, given the requirement that
+ // union members never have non-trivial default constructors.
+
+ // TODO: in C++0x, it might be legal to have union members with
+ // non-trivial default constructors in unions. Revise this
+ // implementation then with the appropriate semantics.
+ CXXRecordDecl *FieldClassDecl
+ = cast<CXXRecordDecl>(FieldClassType->getDecl());
+ for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(),
+ EA = FieldClassDecl->field_end(); FA != EA; FA++)
+ if (CollectFieldInitializer(Info, Top, *FA))
+ return true;
+ }
+
+ // Don't try to build an implicit initializer if there were semantic
+ // errors in any of the initializers (and therefore we might be
+ // missing some that the user actually wrote).
+ if (Info.AnyErrorsInInits)
+ return false;
+
+ CXXBaseOrMemberInitializer *Init = 0;
+ if (BuildImplicitMemberInitializer(Info.S, Info.Ctor, Info.IIK, Field, Init))
+ return true;
+
+ // If the member doesn't need to be initialized, Init will still be null.
+ if (!Init) return false;
+
+ Info.AllToInit.push_back(Init);
+ if (Top != Field) {
+ Init->setMember(Top);
+ Init->setAnonUnionMember(Field);
+ }
+ return false;
+}
bool
Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
@@ -1738,11 +1813,7 @@
return false;
}
- ImplicitInitializerKind ImplicitInitKind = IIK_Default;
-
- // FIXME: Handle implicit move constructors.
- if (Constructor->isImplicit() && Constructor->isCopyConstructor())
- ImplicitInitKind = IIK_Copy;
+ BaseAndFieldInfo Info(*this, Constructor, AnyErrors);
// We need to build the initializer AST according to order of construction
// and not what user specified in the Initializers list.
@@ -1750,17 +1821,15 @@
if (!ClassDecl)
return true;
- llvm::SmallVector<CXXBaseOrMemberInitializer*, 32> AllToInit;
- llvm::DenseMap<const void *, CXXBaseOrMemberInitializer*> AllBaseFields;
bool HadError = false;
for (unsigned i = 0; i < NumInitializers; i++) {
CXXBaseOrMemberInitializer *Member = Initializers[i];
if (Member->isBaseInitializer())
- AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member;
+ Info.AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member;
else
- AllBaseFields[Member->getMember()] = Member;
+ Info.AllBaseFields[Member->getMember()] = Member;
}
// Keep track of the direct virtual bases.
@@ -1776,22 +1845,23 @@
E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
if (CXXBaseOrMemberInitializer *Value
- = AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
- AllToInit.push_back(Value);
+ = Info.AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
+ Info.AllToInit.push_back(Value);
} else if (!AnyErrors) {
bool IsInheritedVirtualBase = !DirectVBases.count(VBase);
CXXBaseOrMemberInitializer *CXXBaseInit;
- if (BuildImplicitBaseInitializer(*this, Constructor, ImplicitInitKind,
+ if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK,
VBase, IsInheritedVirtualBase,
CXXBaseInit)) {
HadError = true;
continue;
}
- AllToInit.push_back(CXXBaseInit);
+ Info.AllToInit.push_back(CXXBaseInit);
}
}
+ // Non-virtual bases.
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
E = ClassDecl->bases_end(); Base != E; ++Base) {
// Virtuals are in the virtual base list and already constructed.
@@ -1799,72 +1869,33 @@
continue;
if (CXXBaseOrMemberInitializer *Value
- = AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) {
- AllToInit.push_back(Value);
+ = Info.AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) {
+ Info.AllToInit.push_back(Value);
} else if (!AnyErrors) {
CXXBaseOrMemberInitializer *CXXBaseInit;
- if (BuildImplicitBaseInitializer(*this, Constructor, ImplicitInitKind,
+ if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK,
Base, /*IsInheritedVirtualBase=*/false,
CXXBaseInit)) {
HadError = true;
continue;
}
- AllToInit.push_back(CXXBaseInit);
+ Info.AllToInit.push_back(CXXBaseInit);
}
}
- // non-static data members.
+ // Fields.
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- E = ClassDecl->field_end(); Field != E; ++Field) {
- if ((*Field)->isAnonymousStructOrUnion()) {
- if (const RecordType *FieldClassType =
- Field->getType()->getAs<RecordType>()) {
- CXXRecordDecl *FieldClassDecl
- = cast<CXXRecordDecl>(FieldClassType->getDecl());
- for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(),
- EA = FieldClassDecl->field_end(); FA != EA; FA++) {
- if (CXXBaseOrMemberInitializer *Value = AllBaseFields.lookup(*FA)) {
- // 'Member' is the anonymous union field and 'AnonUnionMember' is
- // set to the anonymous union data member used in the initializer
- // list.
- Value->setMember(*Field);
- Value->setAnonUnionMember(*FA);
- AllToInit.push_back(Value);
- break;
- }
- }
- }
-
- if (ImplicitInitKind == IIK_Default)
- continue;
- }
- if (CXXBaseOrMemberInitializer *Value = AllBaseFields.lookup(*Field)) {
- AllToInit.push_back(Value);
- continue;
- }
-
- if (AnyErrors)
- continue;
-
- CXXBaseOrMemberInitializer *Member;
- if (BuildImplicitMemberInitializer(*this, Constructor, ImplicitInitKind,
- *Field, Member)) {
+ E = ClassDecl->field_end(); Field != E; ++Field)
+ if (CollectFieldInitializer(Info, *Field, *Field))
HadError = true;
- continue;
- }
-
- // If the member doesn't need to be initialized, it will be null.
- if (Member)
- AllToInit.push_back(Member);
- }
- NumInitializers = AllToInit.size();
+ NumInitializers = Info.AllToInit.size();
if (NumInitializers > 0) {
Constructor->setNumBaseOrMemberInitializers(NumInitializers);
CXXBaseOrMemberInitializer **baseOrMemberInitializers =
new (Context) CXXBaseOrMemberInitializer*[NumInitializers];
- memcpy(baseOrMemberInitializers, AllToInit.data(),
+ memcpy(baseOrMemberInitializers, Info.AllToInit.data(),
NumInitializers * sizeof(CXXBaseOrMemberInitializer*));
Constructor->setBaseOrMemberInitializers(baseOrMemberInitializers);
Modified: cfe/trunk/test/CodeGenCXX/anonymous-union-member-initializer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/anonymous-union-member-initializer.cpp?rev=104292&r1=104291&r2=104292&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/anonymous-union-member-initializer.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/anonymous-union-member-initializer.cpp Thu May 20 18:23:51 2010
@@ -34,3 +34,21 @@
// CHECK: ret void
}
}
+
+namespace test2 {
+ struct A {
+ struct {
+ union {
+ int b;
+ };
+ };
+
+ A();
+ };
+
+ A::A() : b(10) { }
+ // CHECK: define void @_ZN5test21AC2Ev(
+ // CHECK-NOT: }
+ // CHECK: store i32 10
+ // CHECK: }
+}
More information about the cfe-commits
mailing list