From d53e16abd1dcaa2942d5183f48e7f63d0e75b35a Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 5 Jan 2011 20:52:18 +0000 Subject: [PATCH] When we're converting deduced template arguments to the type of the corresponding template parameter, make sure that prior converted template arguments are available for substitution. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122902 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaTemplateDeduction.cpp | 30 +++++++++++++++++-- .../temp.variadic/metafunctions.cpp | 27 +++++++++++++++++ 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 5837ebd8e5..f6dacc7cea 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -1402,12 +1402,19 @@ static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param, for (TemplateArgument::pack_iterator PA = Arg.pack_begin(), PAEnd = Arg.pack_end(); PA != PAEnd; ++PA) { + // When converting the deduced template argument, append it to the + // general output list. We need to do this so that the template argument + // checking logic has all of the prior template arguments available. DeducedTemplateArgument InnerArg(*PA); InnerArg.setDeducedFromArrayBound(Arg.wasDeducedFromArrayBound()); if (ConvertDeducedTemplateArgument(S, Param, InnerArg, Template, NTTPType, Info, - InFunctionTemplate, PackedArgsBuilder)) + InFunctionTemplate, Output)) return true; + + // Move the converted template argument into our argument pack. + PackedArgsBuilder.push_back(Output.back()); + Output.pop_back(); } // Create the resulting argument pack. @@ -1472,9 +1479,26 @@ FinishTemplateArgumentDeduction(Sema &S, // corresponding non-type template parameter. QualType NTTPType; if (NonTypeTemplateParmDecl *NTTP - = dyn_cast(Param)) + = 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, Info, false, Builder)) { diff --git a/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp b/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp index 75181081ad..5c0eb74875 100644 --- a/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp +++ b/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp @@ -118,6 +118,33 @@ namespace Math { } } +namespace ListMath { + template struct add; + + template + struct add { + static const T value = i + add::value; + }; + + template + struct add { + static const T value = T(); + }; + + template + struct List { + struct sum { + static const T value = add::value; + }; + }; + + template + struct ListI : public List { + }; + + int check0[ListI<1, 2, 3>::sum::value == 6? 1 : -1]; +} + namespace Indices { template struct build_indices_impl; -- 2.40.0