From a3bfc5dd821a0d1c891176cc41a17deebb44f0f7 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 3 Feb 2016 20:15:01 +0000 Subject: [PATCH] Refactor conversion of deduced template arguments to reduce repetition. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@259687 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaTemplateDeduction.cpp | 152 ++++++++++------------------- 1 file changed, 49 insertions(+), 103 deletions(-) diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 71faafc6bc..2dc4fdb320 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -2060,11 +2060,46 @@ static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param, DeducedTemplateArgument Arg, NamedDecl *Template, - QualType NTTPType, - unsigned ArgumentPackIndex, TemplateDeductionInfo &Info, bool InFunctionTemplate, SmallVectorImpl &Output) { + // First, for a non-type template parameter type that is + // initialized by a declaration, we need the type of the + // corresponding non-type template parameter. + QualType NTTPType; + if (NonTypeTemplateParmDecl *NTTP = + dyn_cast(Param)) { + NTTPType = NTTP->getType(); + if (NTTPType->isDependentType()) { + TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, + Output.data(), Output.size()); + NTTPType = S.SubstType(NTTPType, + MultiLevelTemplateArgumentList(TemplateArgs), + NTTP->getLocation(), + NTTP->getDeclName()); + if (NTTPType.isNull()) + return true; + } + } + + auto ConvertArg = [&](DeducedTemplateArgument Arg, + unsigned ArgumentPackIndex) { + // Convert the deduced template argument into a template + // argument that we can check, almost as if the user had written + // the template argument explicitly. + TemplateArgumentLoc ArgLoc = + getTrivialTemplateArgumentLoc(S, Arg, NTTPType, Info.getLocation()); + + // Check the template argument, converting it as necessary. + return S.CheckTemplateArgument( + Param, ArgLoc, Template, Template->getLocation(), + Template->getSourceRange().getEnd(), ArgumentPackIndex, Output, + InFunctionTemplate + ? (Arg.wasDeducedFromArrayBound() ? Sema::CTAK_DeducedFromArrayBound + : Sema::CTAK_Deduced) + : Sema::CTAK_Specified); + }; + if (Arg.getKind() == TemplateArgument::Pack) { // This is a template argument pack, so check each of its arguments against // the template parameter. @@ -2075,39 +2110,25 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param, // checking logic has all of the prior template arguments available. DeducedTemplateArgument InnerArg(P); InnerArg.setDeducedFromArrayBound(Arg.wasDeducedFromArrayBound()); - if (ConvertDeducedTemplateArgument(S, Param, InnerArg, Template, - NTTPType, PackedArgsBuilder.size(), - Info, InFunctionTemplate, Output)) + assert(InnerArg.getKind() != TemplateArgument::Pack && + "deduced nested pack"); + if (ConvertArg(InnerArg, PackedArgsBuilder.size())) return true; // Move the converted template argument into our argument pack. PackedArgsBuilder.push_back(Output.pop_back_val()); } + // FIXME: If the pack is empty and this is a template template parameter, + // we still need to substitute into the parameter itself. + // Create the resulting argument pack. Output.push_back( TemplateArgument::CreatePackCopy(S.Context, PackedArgsBuilder)); return false; } - // Convert the deduced template argument into a template - // argument that we can check, almost as if the user had written - // the template argument explicitly. - TemplateArgumentLoc ArgLoc = getTrivialTemplateArgumentLoc(S, Arg, NTTPType, - Info.getLocation()); - - // Check the template argument, converting it as necessary. - return S.CheckTemplateArgument(Param, ArgLoc, - Template, - Template->getLocation(), - Template->getSourceRange().getEnd(), - ArgumentPackIndex, - Output, - InFunctionTemplate - ? (Arg.wasDeducedFromArrayBound() - ? Sema::CTAK_DeducedFromArrayBound - : Sema::CTAK_Deduced) - : Sema::CTAK_Specified); + return ConvertArg(Arg, 0); } /// Complete template argument deduction for a class template partial @@ -2138,34 +2159,8 @@ FinishTemplateArgumentDeduction(Sema &S, // We have deduced this argument, so it still needs to be // checked and converted. - - // First, for a non-type template parameter type that is - // initialized by a declaration, we need the type of the - // corresponding non-type template parameter. - QualType NTTPType; - if (NonTypeTemplateParmDecl *NTTP - = dyn_cast(Param)) { - NTTPType = NTTP->getType(); - if (NTTPType->isDependentType()) { - TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, - Builder.data(), Builder.size()); - NTTPType = S.SubstType(NTTPType, - MultiLevelTemplateArgumentList(TemplateArgs), - NTTP->getLocation(), - NTTP->getDeclName()); - if (NTTPType.isNull()) { - Info.Param = makeTemplateParameter(Param); - // FIXME: These template arguments are temporary. Free them! - Info.reset(TemplateArgumentList::CreateCopy(S.Context, - Builder.data(), - Builder.size())); - return Sema::TDK_SubstitutionFailure; - } - } - } - if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], - Partial, NTTPType, 0, Info, false, + Partial, Info, false, Builder)) { Info.Param = makeTemplateParameter(Param); // FIXME: These template arguments are temporary. Free them! @@ -2306,32 +2301,8 @@ static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction( // We have deduced this argument, so it still needs to be // checked and converted. - - // First, for a non-type template parameter type that is - // initialized by a declaration, we need the type of the - // corresponding non-type template parameter. - QualType NTTPType; - if (NonTypeTemplateParmDecl *NTTP = - dyn_cast(Param)) { - NTTPType = NTTP->getType(); - if (NTTPType->isDependentType()) { - TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, - Builder.data(), Builder.size()); - NTTPType = - S.SubstType(NTTPType, MultiLevelTemplateArgumentList(TemplateArgs), - NTTP->getLocation(), NTTP->getDeclName()); - if (NTTPType.isNull()) { - Info.Param = makeTemplateParameter(Param); - // FIXME: These template arguments are temporary. Free them! - Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder.data(), - Builder.size())); - return Sema::TDK_SubstitutionFailure; - } - } - } - - if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], Partial, NTTPType, - 0, Info, false, Builder)) { + if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], Partial, + Info, false, Builder)) { Info.Param = makeTemplateParameter(Param); // FIXME: These template arguments are temporary. Free them! Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder.data(), @@ -2804,36 +2775,11 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, } continue; } + // We have deduced this argument, so it still needs to be // checked and converted. - - // First, for a non-type template parameter type that is - // initialized by a declaration, we need the type of the - // corresponding non-type template parameter. - QualType NTTPType; - if (NonTypeTemplateParmDecl *NTTP - = dyn_cast(Param)) { - NTTPType = NTTP->getType(); - if (NTTPType->isDependentType()) { - TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, - Builder.data(), Builder.size()); - NTTPType = SubstType(NTTPType, - MultiLevelTemplateArgumentList(TemplateArgs), - NTTP->getLocation(), - NTTP->getDeclName()); - if (NTTPType.isNull()) { - Info.Param = makeTemplateParameter(Param); - // FIXME: These template arguments are temporary. Free them! - Info.reset(TemplateArgumentList::CreateCopy(Context, - Builder.data(), - Builder.size())); - return TDK_SubstitutionFailure; - } - } - } - if (ConvertDeducedTemplateArgument(*this, Param, Deduced[I], - FunctionTemplate, NTTPType, 0, Info, + FunctionTemplate, Info, true, Builder)) { Info.Param = makeTemplateParameter(Param); // FIXME: These template arguments are temporary. Free them! -- 2.40.0