Index: clang/include/clang/Sema/Template.h =================================================================== --- clang/include/clang/Sema/Template.h +++ clang/include/clang/Sema/Template.h @@ -412,6 +412,13 @@ NamedDecl * getPartiallySubstitutedPack(const TemplateArgument **ExplicitArgs = nullptr, unsigned *NumExplicitArgs = nullptr) const; + + /// Introduce the instantiated function parameters into the local + /// instantiation scope, and set the parameter names to those used + /// in the template. + bool addInstantiatedParameters( + FunctionDecl *Function, const FunctionDecl *PatternDecl, + const MultiLevelTemplateArgumentList &TemplateArgs); }; class TemplateDeclInstantiator Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -4811,11 +4811,11 @@ // // template // A Foo(int a = A::FooImpl()); - MultiLevelTemplateArgumentList MutiLevelArgList + MultiLevelTemplateArgumentList MultiLevelArgList = getTemplateInstantiationArgs(FD, nullptr, /*RelativeToPrimary=*/true); InstantiatingTemplate Inst(*this, CallLoc, Param, - MutiLevelArgList.getInnermost()); + MultiLevelArgList.getInnermost()); if (Inst.isInvalid()) return true; if (Inst.isAlreadyInstantiating()) { @@ -4832,7 +4832,13 @@ // default argument expression appears. ContextRAII SavedContext(*this, FD); LocalInstantiationScope Local(*this); - Result = SubstInitializer(UninstExpr, MutiLevelArgList, + + const FunctionDecl *PatternDecl = FD->getTemplateInstantiationPattern(); + if (!PatternDecl) + PatternDecl = FD; + + Local.addInstantiatedParameters(FD, PatternDecl, MultiLevelArgList); + Result = SubstInitializer(UninstExpr, MultiLevelArgList, /*DirectInit*/false); } if (Result.isInvalid()) Index: clang/lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiate.cpp +++ clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -3063,3 +3063,64 @@ return nullptr; } + +bool LocalInstantiationScope::addInstantiatedParameters( + FunctionDecl *Function, const FunctionDecl *PatternDecl, + const MultiLevelTemplateArgumentList &TemplateArgs) { + unsigned FParamIdx = 0; + for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) { + const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I); + if (!PatternParam->isParameterPack()) { + // Simple case: not a parameter pack. + assert(FParamIdx < Function->getNumParams()); + ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); + FunctionParam->setDeclName(PatternParam->getDeclName()); + // If the parameter's type is not dependent, update it to match the type + // in the pattern. They can differ in top-level cv-qualifiers, and we want + // the pattern's type here. If the type is dependent, they can't differ, + // per core issue 1668. Substitute into the type from the pattern, in case + // it's instantiation-dependent. + // FIXME: Updating the type to work around this is at best fragile. + if (!PatternDecl->getType()->isDependentType()) { + QualType T = SemaRef.SubstType(PatternParam->getType(), TemplateArgs, + FunctionParam->getLocation(), + FunctionParam->getDeclName()); + if (T.isNull()) + return true; + FunctionParam->setType(T); + } + + InstantiatedLocal(PatternParam, FunctionParam); + ++FParamIdx; + continue; + } + + // Expand the parameter pack. + MakeInstantiatedLocalArgPack(PatternParam); + Optional NumArgumentsInExpansion = + SemaRef.getNumArgumentsInExpansion(PatternParam->getType(), + TemplateArgs); + if (NumArgumentsInExpansion) { + QualType PatternType = + PatternParam->getType()->castAs()->getPattern(); + for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) { + ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); + FunctionParam->setDeclName(PatternParam->getDeclName()); + if (!PatternDecl->getType()->isDependentType()) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, Arg); + QualType T = SemaRef.SubstType(PatternType, TemplateArgs, + FunctionParam->getLocation(), + FunctionParam->getDeclName()); + if (T.isNull()) + return true; + FunctionParam->setType(T); + } + + InstantiatedLocalPackArg(PatternParam, FunctionParam); + ++FParamIdx; + } + } + } + + return false; +} Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3823,70 +3823,6 @@ return NewTInfo; } -/// Introduce the instantiated function parameters into the local -/// instantiation scope, and set the parameter names to those used -/// in the template. -static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function, - const FunctionDecl *PatternDecl, - LocalInstantiationScope &Scope, - const MultiLevelTemplateArgumentList &TemplateArgs) { - unsigned FParamIdx = 0; - for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) { - const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I); - if (!PatternParam->isParameterPack()) { - // Simple case: not a parameter pack. - assert(FParamIdx < Function->getNumParams()); - ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); - FunctionParam->setDeclName(PatternParam->getDeclName()); - // If the parameter's type is not dependent, update it to match the type - // in the pattern. They can differ in top-level cv-qualifiers, and we want - // the pattern's type here. If the type is dependent, they can't differ, - // per core issue 1668. Substitute into the type from the pattern, in case - // it's instantiation-dependent. - // FIXME: Updating the type to work around this is at best fragile. - if (!PatternDecl->getType()->isDependentType()) { - QualType T = S.SubstType(PatternParam->getType(), TemplateArgs, - FunctionParam->getLocation(), - FunctionParam->getDeclName()); - if (T.isNull()) - return true; - FunctionParam->setType(T); - } - - Scope.InstantiatedLocal(PatternParam, FunctionParam); - ++FParamIdx; - continue; - } - - // Expand the parameter pack. - Scope.MakeInstantiatedLocalArgPack(PatternParam); - Optional NumArgumentsInExpansion - = S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs); - if (NumArgumentsInExpansion) { - QualType PatternType = - PatternParam->getType()->castAs()->getPattern(); - for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) { - ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); - FunctionParam->setDeclName(PatternParam->getDeclName()); - if (!PatternDecl->getType()->isDependentType()) { - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, Arg); - QualType T = S.SubstType(PatternType, TemplateArgs, - FunctionParam->getLocation(), - FunctionParam->getDeclName()); - if (T.isNull()) - return true; - FunctionParam->setType(T); - } - - Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam); - ++FParamIdx; - } - } - } - - return false; -} - void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, FunctionDecl *Decl) { const FunctionProtoType *Proto = Decl->getType()->castAs(); @@ -3918,8 +3854,7 @@ getTemplateInstantiationArgs(Decl, nullptr, /*RelativeToPrimary*/true); FunctionDecl *Template = Proto->getExceptionSpecTemplate(); - if (addInstantiatedParametersToScope(*this, Decl, Template, Scope, - TemplateArgs)) { + if (Scope.addInstantiatedParameters(Decl, Template, TemplateArgs)) { UpdateExceptionSpec(Decl, EST_None); return; } @@ -4270,8 +4205,7 @@ // PushDeclContext because we don't have a scope. Sema::ContextRAII savedContext(*this, Function); - if (addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope, - TemplateArgs)) + if (Scope.addInstantiatedParameters(Function, PatternDecl, TemplateArgs)) return; StmtResult Body; Index: clang/test/SemaTemplate/default-arguments-cxx0x.cpp =================================================================== --- clang/test/SemaTemplate/default-arguments-cxx0x.cpp +++ clang/test/SemaTemplate/default-arguments-cxx0x.cpp @@ -114,3 +114,33 @@ S _a{}; }; } + +// Failure to resolve the decltype part during instantiation caused an +// assertion failure +namespace PR28500 { +namespace original { +template +void bar(T t = [](decltype(t) i) { return 0; }(0)) {} +void foo() { + bar(); +} +} // namespace original + +namespace cast { +template +void bar(T t = decltype(t)(0)) {} +void foo() { + bar(); + bar(); +} +} // namespace cast + +namespace value { +template +void bar(T t = decltype(t)()) {} +void foo() { + bar(); + bar(); +} +} // namespace value +} // namespace PR28500