diff options
author | Anders Carlsson <andersca@mac.com> | 2009-08-29 05:16:22 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-08-29 05:16:22 +0000 |
commit | 090253155017b7eec031bbd7bf07824a448e1d7a (patch) | |
tree | 858c03d91ef08ca9191d7a90996955430ed5f892 /lib/Sema/SemaTemplateInstantiateDecl.cpp | |
parent | eab975dce83fcf6a7fa8fc9379944d4b1aaf1a00 (diff) |
Instantiate member and base initializers. Patch by Anders Johnsen! (tweaked slightly by me)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80422 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 78 |
1 files changed, 76 insertions, 2 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index e2ebd09954..ba5c786366 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -992,9 +992,18 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, DeclContext *PreviousContext = CurContext; CurContext = Function; + MultiLevelTemplateArgumentList TemplateArgs = + getTemplateInstantiationArgs(Function); + + // If this is a constructor, instantiate the member initializers. + if (const CXXConstructorDecl *Ctor = + dyn_cast<CXXConstructorDecl>(PatternDecl)) { + InstantiateMemInitializers(cast<CXXConstructorDecl>(Function), Ctor, + TemplateArgs); + } + // Instantiate the function body. - OwningStmtResult Body - = SubstStmt(Pattern, getTemplateInstantiationArgs(Function)); + OwningStmtResult Body = SubstStmt(Pattern, TemplateArgs); ActOnFinishFunctionBody(DeclPtrTy::make(Function), move(Body), /*IsInstantiation=*/true); @@ -1092,6 +1101,71 @@ void Sema::InstantiateStaticDataMemberDefinition( } } +void +Sema::InstantiateMemInitializers(CXXConstructorDecl *New, + const CXXConstructorDecl *Tmpl, + const MultiLevelTemplateArgumentList &TemplateArgs) { + + llvm::SmallVector<MemInitTy*, 4> NewInits; + + // Instantiate all the initializers. + for (CXXConstructorDecl::init_const_iterator Inits = Tmpl->init_begin(), + InitsEnd = Tmpl->init_end(); Inits != InitsEnd; ++Inits) { + CXXBaseOrMemberInitializer *Init = *Inits; + + ASTOwningVector<&ActionBase::DeleteExpr> NewArgs(*this); + + // Instantiate all the arguments. + for (ExprIterator Args = Init->arg_begin(), ArgsEnd = Init->arg_end(); + Args != ArgsEnd; ++Args) { + OwningExprResult NewArg = SubstExpr(*Args, TemplateArgs); + + if (NewArg.isInvalid()) + New->setInvalidDecl(); + else + NewArgs.push_back(NewArg.takeAs<Expr>()); + } + + MemInitResult NewInit; + + if (Init->isBaseInitializer()) { + // FIXME: Type needs to be instantiated. + QualType BaseType = + Context.getCanonicalType(QualType(Init->getBaseClass(), 0)); + + NewInit = BuildBaseInitializer(BaseType, + (Expr **)NewArgs.data(), + NewArgs.size(), + Init->getSourceLocation(), + Init->getRParenLoc(), + New->getParent()); + } else if (Init->isMemberInitializer()) { + FieldDecl *Member = + cast<FieldDecl>(FindInstantiatedDecl(Init->getMember())); + + NewInit = BuildMemberInitializer(Member, (Expr **)NewArgs.data(), + NewArgs.size(), + Init->getSourceLocation(), + Init->getRParenLoc()); + } + + if (NewInit.isInvalid()) + New->setInvalidDecl(); + else { + // FIXME: It would be nice if ASTOwningVector had a release function. + NewArgs.take(); + + NewInits.push_back((MemInitTy *)NewInit.get()); + } + } + + // Assign all the initializers to the new constructor. + ActOnMemInitializers(DeclPtrTy::make(New), + /*FIXME: ColonLoc */ + SourceLocation(), + NewInits.data(), NewInits.size()); +} + static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) { if (D->getKind() != Other->getKind()) return false; |