Author: Richard Smith Date: 2020-07-09T17:24:19-07:00 New Revision: 7462793be771712092de4c31fef1b04ac365ccea
URL: https://github.com/llvm/llvm-project/commit/7462793be771712092de4c31fef1b04ac365ccea DIFF: https://github.com/llvm/llvm-project/commit/7462793be771712092de4c31fef1b04ac365ccea.diff LOG: Move default argument instantiation to SemaTemplateInstantiateDecl.cpp. No functionality change intended. Added: Modified: clang/include/clang/Sema/Sema.h clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaTemplateInstantiateDecl.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 7535849144d0..c3bebea0cccb 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9101,6 +9101,8 @@ class Sema final { TemplateArgumentListInfo &Result, const MultiLevelTemplateArgumentList &TemplateArgs); + bool InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD, + ParmVarDecl *Param); void InstantiateExceptionSpec(SourceLocation PointOfInstantiation, FunctionDecl *Function); bool CheckInstantiatedFunctionTemplateConstraints( diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 0a7604d9f399..24b9c6777be1 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -5575,83 +5575,9 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, return true; } - if (Param->hasUninstantiatedDefaultArg()) { - Expr *UninstExpr = Param->getUninstantiatedDefaultArg(); - - EnterExpressionEvaluationContext EvalContext( - *this, ExpressionEvaluationContext::PotentiallyEvaluated, Param); - - // Instantiate the expression. - // - // FIXME: Pass in a correct Pattern argument, otherwise - // getTemplateInstantiationArgs uses the lexical context of FD, e.g. - // - // template<typename T> - // struct A { - // static int FooImpl(); - // - // template<typename Tp> - // // bug: default argument A<T>::FooImpl() is evaluated with 2-level - // // template argument list [[T], [Tp]], should be [[Tp]]. - // friend A<Tp> Foo(int a); - // }; - // - // template<typename T> - // A<T> Foo(int a = A<T>::FooImpl()); - MultiLevelTemplateArgumentList MutiLevelArgList - = getTemplateInstantiationArgs(FD, nullptr, /*RelativeToPrimary=*/true); - - InstantiatingTemplate Inst(*this, CallLoc, Param, - MutiLevelArgList.getInnermost()); - if (Inst.isInvalid()) - return true; - if (Inst.isAlreadyInstantiating()) { - Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD; - Param->setInvalidDecl(); - return true; - } - - ExprResult Result; - { - // C++ [dcl.fct.default]p5: - // The names in the [default argument] expression are bound, and - // the semantic constraints are checked, at the point where the - // default argument expression appears. - ContextRAII SavedContext(*this, FD); - LocalInstantiationScope Local(*this); - runWithSufficientStackSpace(CallLoc, [&] { - Result = SubstInitializer(UninstExpr, MutiLevelArgList, - /*DirectInit*/false); - }); - } - if (Result.isInvalid()) - return true; - - // Check the expression as an initializer for the parameter. - InitializedEntity Entity - = InitializedEntity::InitializeParameter(Context, Param); - InitializationKind Kind = InitializationKind::CreateCopy( - Param->getLocation(), - /*FIXME:EqualLoc*/ UninstExpr->getBeginLoc()); - Expr *ResultE = Result.getAs<Expr>(); - - InitializationSequence InitSeq(*this, Entity, Kind, ResultE); - Result = InitSeq.Perform(*this, Entity, Kind, ResultE); - if (Result.isInvalid()) - return true; - - Result = - ActOnFinishFullExpr(Result.getAs<Expr>(), Param->getOuterLocStart(), - /*DiscardedValue*/ false); - if (Result.isInvalid()) - return true; - - // Remember the instantiated default argument. - Param->setDefaultArg(Result.getAs<Expr>()); - if (ASTMutationListener *L = getASTMutationListener()) { - L->DefaultArgumentInstantiated(Param); - } - } + if (Param->hasUninstantiatedDefaultArg() && + InstantiateDefaultArgument(CallLoc, FD, Param)) + return true; assert(Param->hasInit() && "default argument but no initializer?"); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 444fb209e932..1098a9aa782c 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4227,6 +4227,87 @@ static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function, return false; } +bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD, + ParmVarDecl *Param) { + assert(Param->hasUninstantiatedDefaultArg()); + Expr *UninstExpr = Param->getUninstantiatedDefaultArg(); + + EnterExpressionEvaluationContext EvalContext( + *this, ExpressionEvaluationContext::PotentiallyEvaluated, Param); + + // Instantiate the expression. + // + // FIXME: Pass in a correct Pattern argument, otherwise + // getTemplateInstantiationArgs uses the lexical context of FD, e.g. + // + // template<typename T> + // struct A { + // static int FooImpl(); + // + // template<typename Tp> + // // bug: default argument A<T>::FooImpl() is evaluated with 2-level + // // template argument list [[T], [Tp]], should be [[Tp]]. + // friend A<Tp> Foo(int a); + // }; + // + // template<typename T> + // A<T> Foo(int a = A<T>::FooImpl()); + MultiLevelTemplateArgumentList TemplateArgs + = getTemplateInstantiationArgs(FD, nullptr, /*RelativeToPrimary=*/true); + + InstantiatingTemplate Inst(*this, CallLoc, Param, + TemplateArgs.getInnermost()); + if (Inst.isInvalid()) + return true; + if (Inst.isAlreadyInstantiating()) { + Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD; + Param->setInvalidDecl(); + return true; + } + + ExprResult Result; + { + // C++ [dcl.fct.default]p5: + // The names in the [default argument] expression are bound, and + // the semantic constraints are checked, at the point where the + // default argument expression appears. + ContextRAII SavedContext(*this, FD); + LocalInstantiationScope Local(*this); + runWithSufficientStackSpace(CallLoc, [&] { + Result = SubstInitializer(UninstExpr, TemplateArgs, + /*DirectInit*/false); + }); + } + if (Result.isInvalid()) + return true; + + // Check the expression as an initializer for the parameter. + InitializedEntity Entity + = InitializedEntity::InitializeParameter(Context, Param); + InitializationKind Kind = InitializationKind::CreateCopy( + Param->getLocation(), + /*FIXME:EqualLoc*/ UninstExpr->getBeginLoc()); + Expr *ResultE = Result.getAs<Expr>(); + + InitializationSequence InitSeq(*this, Entity, Kind, ResultE); + Result = InitSeq.Perform(*this, Entity, Kind, ResultE); + if (Result.isInvalid()) + return true; + + Result = + ActOnFinishFullExpr(Result.getAs<Expr>(), Param->getOuterLocStart(), + /*DiscardedValue*/ false); + if (Result.isInvalid()) + return true; + + // Remember the instantiated default argument. + Param->setDefaultArg(Result.getAs<Expr>()); + if (ASTMutationListener *L = getASTMutationListener()) + L->DefaultArgumentInstantiated(Param); + + return false; +} + void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, FunctionDecl *Decl) { const FunctionProtoType *Proto = Decl->getType()->castAs<FunctionProtoType>(); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits