diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 3717126ec8ef..1da4c4e2091b 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/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); + 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); - } - } - + // non-static data members. for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), E = ClassDecl->field_end(); Field != E; ++Field) { diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 5978dae311e3..9785fb2653e7 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/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/clang/test/SemaTemplate/instantiate-member-initializers.cpp b/clang/test/SemaTemplate/instantiate-member-initializers.cpp index 66f4d37d015a..6fc70429a9d3 100644 --- a/clang/test/SemaTemplate/instantiate-member-initializers.cpp +++ b/clang/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;