[cfe-commits] r100180 - in /cfe/trunk: lib/Sema/SemaDeclCXX.cpp test/SemaTemplate/instantiate-member-initializers.cpp
Anders Carlsson
andersca at mac.com
Thu Apr 1 23:26:45 PDT 2010
Author: andersca
Date: Fri Apr 2 01:26:44 2010
New Revision: 100180
URL: http://llvm.org/viewvc/llvm-project?rev=100180&view=rev
Log:
If a constructor is a dependent context, just set the base and member initializers as they are written. Fixes a bug where we wouldn't show initialization order warnings when instantiating.
Modified:
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=100180&r1=100179&r2=100180&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Apr 2 01:26:44 2010
@@ -1430,6 +1430,21 @@
CXXBaseOrMemberInitializer **Initializers,
unsigned NumInitializers,
bool AnyErrors) {
+ if (Constructor->isDependentContext()) {
+ // Just store the initializers as written, they will be checked during
+ // instantiation.
+ if (NumInitializers > 0) {
+ Constructor->setNumBaseOrMemberInitializers(NumInitializers);
+ CXXBaseOrMemberInitializer **baseOrMemberInitializers =
+ new (Context) CXXBaseOrMemberInitializer*[NumInitializers];
+ memcpy(baseOrMemberInitializers, Initializers,
+ NumInitializers * sizeof(CXXBaseOrMemberInitializer*));
+ Constructor->setBaseOrMemberInitializers(baseOrMemberInitializers);
+ }
+
+ return false;
+ }
+
// We need to build the initializer AST according to order of construction
// and not what user specified in the Initializers list.
CXXRecordDecl *ClassDecl = Constructor->getParent()->getDefinition();
@@ -1438,127 +1453,82 @@
llvm::SmallVector<CXXBaseOrMemberInitializer*, 32> AllToInit;
llvm::DenseMap<const void *, CXXBaseOrMemberInitializer*> AllBaseFields;
- bool HasDependentBaseInit = false;
bool HadError = false;
for (unsigned i = 0; i < NumInitializers; i++) {
CXXBaseOrMemberInitializer *Member = Initializers[i];
- if (Member->isBaseInitializer()) {
- if (Member->getBaseClass()->isDependentType())
- HasDependentBaseInit = true;
+
+ if (Member->isBaseInitializer())
AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member;
- } else {
+ else
AllBaseFields[Member->getMember()] = Member;
- }
}
- if (HasDependentBaseInit) {
- // FIXME. This does not preserve the ordering of the initializers.
- // Try (with -Wreorder)
- // template<class X> struct A {};
- // template<class X> struct B : A<X> {
- // B() : x1(10), A<X>() {}
- // int x1;
- // };
- // B<int> x;
- // On seeing one dependent type, we should essentially exit this routine
- // while preserving user-declared initializer list. When this routine is
- // called during instantiatiation process, this routine will rebuild the
- // ordered initializer list correctly.
-
- // If we have a dependent base initialization, we can't determine the
- // association between initializers and bases; just dump the known
- // initializers into the list, and don't try to deal with other bases.
- for (unsigned i = 0; i < NumInitializers; i++) {
- CXXBaseOrMemberInitializer *Member = Initializers[i];
- if (Member->isBaseInitializer())
- AllToInit.push_back(Member);
- }
- } else {
- llvm::SmallVector<CXXBaseSpecifier *, 4> BasesToDefaultInit;
-
- // Push virtual bases before others.
- for (CXXRecordDecl::base_class_iterator VBase =
- ClassDecl->vbases_begin(),
- E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
- if (VBase->getType()->isDependentType())
- continue;
- if (CXXBaseOrMemberInitializer *Value
- = AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
- AllToInit.push_back(Value);
- } else if (!AnyErrors) {
- InitializedEntity InitEntity
- = InitializedEntity::InitializeBase(Context, VBase);
- InitializationKind InitKind
- = InitializationKind::CreateDefault(Constructor->getLocation());
- InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);
- OwningExprResult BaseInit = InitSeq.Perform(*this, InitEntity, InitKind,
- MultiExprArg(*this, 0, 0));
- BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit));
- if (BaseInit.isInvalid()) {
- HadError = true;
- continue;
- }
+ llvm::SmallVector<CXXBaseSpecifier *, 4> BasesToDefaultInit;
- // Don't attach synthesized base initializers in a dependent
- // context; they'll be checked again at template instantiation
- // time.
- if (CurContext->isDependentContext())
- continue;
-
- CXXBaseOrMemberInitializer *CXXBaseInit =
- new (Context) CXXBaseOrMemberInitializer(Context,
- Context.getTrivialTypeSourceInfo(VBase->getType(),
- SourceLocation()),
- SourceLocation(),
- BaseInit.takeAs<Expr>(),
- SourceLocation());
- AllToInit.push_back(CXXBaseInit);
- }
- }
+ // Push virtual bases before others.
+ for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
+ E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
- 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.
- if (Base->isVirtual())
- continue;
- // Skip dependent types.
- if (Base->getType()->isDependentType())
+ if (CXXBaseOrMemberInitializer *Value
+ = AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
+ AllToInit.push_back(Value);
+ } else if (!AnyErrors) {
+ InitializedEntity InitEntity
+ = InitializedEntity::InitializeBase(Context, VBase);
+ InitializationKind InitKind
+ = InitializationKind::CreateDefault(Constructor->getLocation());
+ InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);
+ OwningExprResult BaseInit = InitSeq.Perform(*this, InitEntity, InitKind,
+ MultiExprArg(*this, 0, 0));
+ BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit));
+ if (BaseInit.isInvalid()) {
+ HadError = true;
continue;
- if (CXXBaseOrMemberInitializer *Value
- = AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) {
- AllToInit.push_back(Value);
}
- else if (!AnyErrors) {
- InitializedEntity InitEntity
- = InitializedEntity::InitializeBase(Context, Base);
- InitializationKind InitKind
- = InitializationKind::CreateDefault(Constructor->getLocation());
- InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);
- OwningExprResult BaseInit = InitSeq.Perform(*this, InitEntity, InitKind,
- MultiExprArg(*this, 0, 0));
- BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit));
- if (BaseInit.isInvalid()) {
- HadError = true;
- continue;
- }
- // Don't attach synthesized base initializers in a dependent
- // context; they'll be regenerated at template instantiation
- // time.
- if (CurContext->isDependentContext())
- continue;
-
- CXXBaseOrMemberInitializer *CXXBaseInit =
- new (Context) CXXBaseOrMemberInitializer(Context,
- Context.getTrivialTypeSourceInfo(Base->getType(),
- SourceLocation()),
- SourceLocation(),
- BaseInit.takeAs<Expr>(),
- SourceLocation());
- AllToInit.push_back(CXXBaseInit);
+ CXXBaseOrMemberInitializer *CXXBaseInit =
+ new (Context) CXXBaseOrMemberInitializer(Context,
+ Context.getTrivialTypeSourceInfo(VBase->getType(),
+ SourceLocation()),
+ SourceLocation(),
+ BaseInit.takeAs<Expr>(),
+ SourceLocation());
+ AllToInit.push_back(CXXBaseInit);
+ }
+ }
+
+ 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.
+ if (Base->isVirtual())
+ continue;
+
+ if (CXXBaseOrMemberInitializer *Value
+ = AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) {
+ AllToInit.push_back(Value);
+ } else if (!AnyErrors) {
+ InitializedEntity InitEntity
+ = InitializedEntity::InitializeBase(Context, Base);
+ InitializationKind InitKind
+ = InitializationKind::CreateDefault(Constructor->getLocation());
+ InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);
+ OwningExprResult BaseInit = InitSeq.Perform(*this, InitEntity, InitKind,
+ MultiExprArg(*this, 0, 0));
+ BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit));
+ if (BaseInit.isInvalid()) {
+ HadError = true;
+ continue;
}
+
+ CXXBaseOrMemberInitializer *CXXBaseInit =
+ new (Context) CXXBaseOrMemberInitializer(Context,
+ Context.getTrivialTypeSourceInfo(Base->getType(),
+ SourceLocation()),
+ SourceLocation(),
+ BaseInit.takeAs<Expr>(),
+ SourceLocation());
+ AllToInit.push_back(CXXBaseInit);
}
}
Modified: cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp?rev=100180&r1=100179&r2=100180&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp Fri Apr 2 01:26:44 2010
@@ -10,14 +10,14 @@
A<void*> a1; // expected-note{{in instantiation of member function 'A<void *>::A' requested here}}
template<typename T> struct B {
- // FIXME: This should warn about initialization order
- B() : b(1), a(2) { }
+ B() : b(1), // expected-warning {{member 'b' will be initialized after}}
+ a(2) { } // expected-note {{field a}}
int a;
int b;
};
-B<int> b0;
+B<int> b0; // expected-note {{in instantiation of member function 'B<int>::B' requested here}}
template <class T> struct AA { AA(int); };
template <class T> class BB : public AA<T> {
More information about the cfe-commits
mailing list