From c5573a81a83c4173c92c7e91b01371b7223d88c4 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Sat, 29 Aug 2009 22:22:07 +0000 Subject: [PATCH] Make instantiating initializers for classes with a dependent base type work correctly. The change in lib/AST/DeclCXX.cpp is mostly a large reindentation; I couldn't figure out a good way to avoid it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80446 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/DeclCXX.cpp | 113 ++++++++++-------- lib/Sema/SemaTemplateInstantiateDecl.cpp | 6 +- .../instantiate-member-initializers.cpp | 6 + 3 files changed, 73 insertions(+), 52 deletions(-) diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 3717126ec8..1da4c4e209 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -595,66 +595,81 @@ CXXConstructorDecl::setBaseOrMemberInitializers( CXXRecordDecl *ClassDecl = cast(getDeclContext()); llvm::SmallVector AllToInit; llvm::DenseMap AllBaseFields; + bool HasDependentBaseInit = false; for (unsigned i = 0; i < NumInitializers; i++) { CXXBaseOrMemberInitializer *Member = Initializers[i]; - if (Member->isBaseInitializer()) + if (Member->isBaseInitializer()) { + if (Member->getBaseClass()->isDependentType()) + HasDependentBaseInit = true; AllBaseFields[Member->getBaseClass()->getAs()] = Member; - else + } else { AllBaseFields[Member->getMember()] = Member; + } } + + if (HasDependentBaseInit) { + // 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 { + // 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())) + AllToInit.push_back(Value); + else { + CXXRecordDecl *VBaseDecl = + cast(VBase->getType()->getAs()->getDecl()); + assert(VBaseDecl && "setBaseOrMemberInitializers - VBaseDecl null"); + if (!VBaseDecl->getDefaultConstructor(C)) + Bases.push_back(VBase); + CXXBaseOrMemberInitializer *Member = + new (C) CXXBaseOrMemberInitializer(VBase->getType(), 0, 0, + VBaseDecl->getDefaultConstructor(C), + SourceLocation(), + SourceLocation()); + AllToInit.push_back(Member); + } + } - // 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())) - AllToInit.push_back(Value); - else { - CXXRecordDecl *VBaseDecl = - cast(VBase->getType()->getAs()->getDecl()); - assert(VBaseDecl && "setBaseOrMemberInitializers - VBaseDecl null"); - if (!VBaseDecl->getDefaultConstructor(C)) - Bases.push_back(VBase); - CXXBaseOrMemberInitializer *Member = - new (C) CXXBaseOrMemberInitializer(VBase->getType(), 0, 0, - VBaseDecl->getDefaultConstructor(C), + 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()) + continue; + if (CXXBaseOrMemberInitializer *Value = + AllBaseFields.lookup(Base->getType()->getAs())) + AllToInit.push_back(Value); + else { + CXXRecordDecl *BaseDecl = + cast(Base->getType()->getAs()->getDecl()); + assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null"); + if (!BaseDecl->getDefaultConstructor(C)) + Bases.push_back(Base); + CXXBaseOrMemberInitializer *Member = + new (C) CXXBaseOrMemberInitializer(Base->getType(), 0, 0, + BaseDecl->getDefaultConstructor(C), SourceLocation(), SourceLocation()); - AllToInit.push_back(Member); - } - } - - 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()) - continue; - if (CXXBaseOrMemberInitializer *Value = - AllBaseFields.lookup(Base->getType()->getAs())) - AllToInit.push_back(Value); - else { - CXXRecordDecl *BaseDecl = - cast(Base->getType()->getAs()->getDecl()); - assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null"); - if (!BaseDecl->getDefaultConstructor(C)) - Bases.push_back(Base); - CXXBaseOrMemberInitializer *Member = - new (C) CXXBaseOrMemberInitializer(Base->getType(), 0, 0, - BaseDecl->getDefaultConstructor(C), - SourceLocation(), - SourceLocation()); - AllToInit.push_back(Member); + AllToInit.push_back(Member); + } } } - + // non-static data members. for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), E = ClassDecl->field_end(); Field != E; ++Field) { diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 5978dae311..9785fb2653 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1134,9 +1134,9 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, MemInitResult NewInit; if (Init->isBaseInitializer()) { - // FIXME: Type needs to be instantiated. - QualType BaseType = - Context.getCanonicalType(QualType(Init->getBaseClass(), 0)); + QualType BaseType(Init->getBaseClass(), 0); + BaseType = SubstType(BaseType, TemplateArgs, Init->getSourceLocation(), + New->getDeclName()); NewInit = BuildBaseInitializer(BaseType, (Expr **)NewArgs.data(), diff --git a/test/SemaTemplate/instantiate-member-initializers.cpp b/test/SemaTemplate/instantiate-member-initializers.cpp index 66f4d37d01..6fc70429a9 100644 --- a/test/SemaTemplate/instantiate-member-initializers.cpp +++ b/test/SemaTemplate/instantiate-member-initializers.cpp @@ -18,3 +18,9 @@ template struct B { }; B b0; + +template struct AA { AA(int); }; +template class BB : public AA { + BB() : AA(1) {} +}; +BB x; -- 2.50.1