From 6b98b2e5f33ce2dcdb7fa385f7e21672d49f1a69 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 2 Mar 2010 07:38:39 +0000 Subject: [PATCH] Unify initializer-instantiation code for variable declarations and base/member initializers. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97560 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaTemplateInstantiateDecl.cpp | 178 ++++++++++++----------- 1 file changed, 93 insertions(+), 85 deletions(-) diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 549f87b2ca..3a6b4cb3cc 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -202,6 +202,72 @@ static bool InstantiateInitializationArguments(Sema &SemaRef, return false; } +/// \brief Instantiate an initializer, breaking it into separate +/// initialization arguments. +/// +/// \param S The semantic analysis object. +/// +/// \param Init The initializer to instantiate. +/// +/// \param TemplateArgs Template arguments to be substituted into the +/// initializer. +/// +/// \param NewArgs Will be filled in with the instantiation arguments. +/// +/// \returns true if an error occurred, false otherwise +static bool InstantiateInitializer(Sema &S, Expr *Init, + const MultiLevelTemplateArgumentList &TemplateArgs, + SourceLocation &LParenLoc, + llvm::SmallVector &CommaLocs, + ASTOwningVector<&ActionBase::DeleteExpr> &NewArgs, + SourceLocation &RParenLoc) { + NewArgs.clear(); + LParenLoc = SourceLocation(); + RParenLoc = SourceLocation(); + + if (!Init) + return false; + + if (CXXExprWithTemporaries *ExprTemp = dyn_cast(Init)) + Init = ExprTemp->getSubExpr(); + + while (CXXBindTemporaryExpr *Binder = dyn_cast(Init)) + Init = Binder->getSubExpr(); + + if (ImplicitCastExpr *ICE = dyn_cast(Init)) + Init = ICE->getSubExprAsWritten(); + + if (ParenListExpr *ParenList = dyn_cast(Init)) { + LParenLoc = ParenList->getLParenLoc(); + RParenLoc = ParenList->getRParenLoc(); + return InstantiateInitializationArguments(S, ParenList->getExprs(), + ParenList->getNumExprs(), + TemplateArgs, CommaLocs, + NewArgs); + } + + if (CXXConstructExpr *Construct = dyn_cast(Init)) { + if (InstantiateInitializationArguments(S, + Construct->getArgs(), + Construct->getNumArgs(), + TemplateArgs, + CommaLocs, NewArgs)) + return true; + + // FIXME: Fake locations! + LParenLoc = S.PP.getLocForEndOfToken(Init->getLocStart()); + RParenLoc = CommaLocs.empty()? LParenLoc : CommaLocs.back(); + return false; + } + + Sema::OwningExprResult Result = S.SubstExpr(Init, TemplateArgs); + if (Result.isInvalid()) + return true; + + NewArgs.push_back(Result.takeAs()); + return false; +} + Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { // Do substitution on the type of the declaration TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(), @@ -259,77 +325,33 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { else SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); - // Extract the initializer, skipping through any temporary-binding - // expressions and look at the subexpression as it was written. - Expr *DInit = D->getInit(); - if (CXXExprWithTemporaries *ExprTemp - = dyn_cast(DInit)) - DInit = ExprTemp->getSubExpr(); - while (CXXBindTemporaryExpr *Binder = dyn_cast(DInit)) - DInit = Binder->getSubExpr(); - if (ImplicitCastExpr *ICE = dyn_cast(DInit)) - DInit = ICE->getSubExprAsWritten(); - - if (ParenListExpr *PLE = dyn_cast(DInit)) { - // The initializer is a parenthesized list of expressions that is - // type-dependent. Instantiate each of the expressions; we'll be - // performing direct initialization with them. - llvm::SmallVector CommaLocs; - ASTOwningVector<&ActionBase::DeleteExpr> InitArgs(SemaRef); - if (!InstantiateInitializationArguments(SemaRef, - PLE->getExprs(), - PLE->getNumExprs(), - TemplateArgs, - CommaLocs, InitArgs)) { + // Instantiate the initializer. + SourceLocation LParenLoc, RParenLoc; + llvm::SmallVector CommaLocs; + ASTOwningVector<&ActionBase::DeleteExpr> InitArgs(SemaRef); + if (!InstantiateInitializer(SemaRef, D->getInit(), TemplateArgs, LParenLoc, + CommaLocs, InitArgs, RParenLoc)) { + // Attach the initializer to the declaration. + if (D->hasCXXDirectInitializer()) { // Add the direct initializer to the declaration. SemaRef.AddCXXDirectInitializerToDecl(Sema::DeclPtrTy::make(Var), - PLE->getLParenLoc(), + LParenLoc, move_arg(InitArgs), CommaLocs.data(), - PLE->getRParenLoc()); + RParenLoc); + } else if (InitArgs.size() == 1) { + Expr *Init = (Expr*)(InitArgs.take()[0]); + SemaRef.AddInitializerToDecl(Sema::DeclPtrTy::make(Var), + SemaRef.Owned(Init), + false); + } else { + assert(InitArgs.size() == 0); + SemaRef.ActOnUninitializedDecl(Sema::DeclPtrTy::make(Var), false); } - } else if (CXXConstructExpr *Construct =dyn_cast(DInit)) { - // The initializer resolved to a constructor. Instantiate the constructor - // arguments. - llvm::SmallVector CommaLocs; - ASTOwningVector<&ActionBase::DeleteExpr> InitArgs(SemaRef); - - if (!InstantiateInitializationArguments(SemaRef, - Construct->getArgs(), - Construct->getNumArgs(), - TemplateArgs, - CommaLocs, InitArgs)) { - if (D->hasCXXDirectInitializer()) { - SourceLocation FakeLParenLoc = - SemaRef.PP.getLocForEndOfToken(D->getLocation()); - SourceLocation FakeRParenLoc = CommaLocs.empty()? FakeLParenLoc - : CommaLocs.back(); - SemaRef.AddCXXDirectInitializerToDecl(Sema::DeclPtrTy::make(Var), - FakeLParenLoc, - move_arg(InitArgs), - CommaLocs.data(), - FakeRParenLoc); - } else if (InitArgs.size() == 1) { - Expr *Init = (Expr*)(InitArgs.take()[0]); - SemaRef.AddInitializerToDecl(Sema::DeclPtrTy::make(Var), - SemaRef.Owned(Init), - false); - } else { - assert(InitArgs.size() == 0); - SemaRef.ActOnUninitializedDecl(Sema::DeclPtrTy::make(Var), false); - } - } } else { - OwningExprResult Init - = SemaRef.SubstExpr(D->getInit(), TemplateArgs); - - // FIXME: Not happy about invalidating decls just because of a bad - // initializer, unless it affects the type. - if (Init.isInvalid()) - Var->setInvalidDecl(); - else - SemaRef.AddInitializerToDecl(Sema::DeclPtrTy::make(Var), move(Init), - D->hasCXXDirectInitializer()); + // FIXME: Not too happy about invalidating the declaration + // because of a bogus initializer. + Var->setInvalidDecl(); } SemaRef.PopExpressionEvaluationContext(); @@ -1888,29 +1910,15 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, Inits != InitsEnd; ++Inits) { CXXBaseOrMemberInitializer *Init = *Inits; + SourceLocation LParenLoc, RParenLoc; ASTOwningVector<&ActionBase::DeleteExpr> NewArgs(*this); llvm::SmallVector CommaLocs; - // Instantiate all the arguments. - Expr *InitE = Init->getInit(); - if (!InitE) { - // Nothing to instantiate; - } else if (ParenListExpr *ParenList = dyn_cast(InitE)) { - if (InstantiateInitializationArguments(*this, ParenList->getExprs(), - ParenList->getNumExprs(), - TemplateArgs, CommaLocs, - NewArgs)) { - AnyErrors = true; - continue; - } - } else { - OwningExprResult InitArg = SubstExpr(InitE, TemplateArgs); - if (InitArg.isInvalid()) { - AnyErrors = true; - continue; - } - - NewArgs.push_back(InitArg.release()); + // Instantiate the initializer. + if (InstantiateInitializer(*this, Init->getInit(), TemplateArgs, + LParenLoc, CommaLocs, NewArgs, RParenLoc)) { + AnyErrors = true; + continue; } MemInitResult NewInit; -- 2.40.0