diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2009-08-29 22:22:07 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2009-08-29 22:22:07 +0000 |
commit | c5573a81a83c4173c92c7e91b01371b7223d88c4 (patch) | |
tree | d6f8b9c885e5d0ecc575581f0b9e6cfaf2577b0b | |
parent | e3a97db45ac46adf963115d0266cfd3e6bc2dce8 (diff) |
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
-rw-r--r-- | lib/AST/DeclCXX.cpp | 113 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 6 | ||||
-rw-r--r-- | test/SemaTemplate/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<CXXRecordDecl>(getDeclContext()); llvm::SmallVector<CXXBaseOrMemberInitializer*, 32> AllToInit; llvm::DenseMap<const void *, CXXBaseOrMemberInitializer*> 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<RecordType>()] = 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<RecordType>())) + AllToInit.push_back(Value); + else { + CXXRecordDecl *VBaseDecl = + cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->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<RecordType>())) - AllToInit.push_back(Value); - else { - CXXRecordDecl *VBaseDecl = - cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->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<RecordType>())) + AllToInit.push_back(Value); + else { + CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->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<RecordType>())) - AllToInit.push_back(Value); - else { - CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->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<typename T> struct B { }; B<int> b0; + +template <class T> struct AA { AA(int); }; +template <class T> class BB : public AA<T> { + BB() : AA<T>(1) {} +}; +BB<int> x; |