From 4b911e6536ed77524c3cef572cb0f6c8d9079e2e Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Thu, 15 Mar 2012 21:40:51 +0000 Subject: [PATCH] Support deducing template arguments from nested initializer lists. PR12119. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152848 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaTemplateDeduction.cpp | 40 +++++++++++++++++-- .../cxx0x-initializer-stdinitializerlist.cpp | 13 ++++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 9970005b69..bc6138d559 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -2905,6 +2905,40 @@ static bool hasDeducibleTemplateParameters(Sema &S, FunctionTemplateDecl *FunctionTemplate, QualType T); +/// \brief Perform template argument deduction by matching a parameter type +/// against a single expression, where the expression is an element of +/// an initializer list that was originally matched against the argument +/// type. +static Sema::TemplateDeductionResult +DeduceTemplateArgumentByListElement(Sema &S, + TemplateParameterList *TemplateParams, + QualType ParamType, Expr *Arg, + TemplateDeductionInfo &Info, + SmallVectorImpl &Deduced, + unsigned TDF) { + // Handle the case where an init list contains another init list as the + // element. + if (InitListExpr *ILE = dyn_cast(Arg)) { + QualType X; + if (!S.isStdInitializerList(ParamType.getNonReferenceType(), &X)) + return Sema::TDK_Success; // Just ignore this expression. + + // Recurse down into the init list. + for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) { + if (Sema::TemplateDeductionResult Result = + DeduceTemplateArgumentByListElement(S, TemplateParams, X, + ILE->getInit(i), + Info, Deduced, TDF)) + return Result; + } + return Sema::TDK_Success; + } + + // For all other cases, just match by type. + return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType, + Arg->getType(), Info, Deduced, TDF); +} + /// \brief Perform template argument deduction from a function call /// (C++ [temp.deduct.call]). /// @@ -3025,9 +3059,9 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) { if (TemplateDeductionResult Result = - DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, X, - ILE->getInit(i)->getType(), - Info, Deduced, TDF)) + DeduceTemplateArgumentByListElement(*this, TemplateParams, X, + ILE->getInit(i), + Info, Deduced, TDF)) return Result; } // Don't track the argument type, since an initializer list has none. diff --git a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp index 23b51515f9..0e0e8f254b 100644 --- a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -137,3 +137,16 @@ struct haslist1 { haslist1::haslist1() : il{1, 2, 3} // expected-warning{{at the end of the constructor}} {} + +namespace PR12119 { + // Deduction with nested initializer lists. + template void f(std::initializer_list); + template void g(std::initializer_list>); + + void foo() { + f({0, {1}}); + g({{0, 1}, {2, 3}}); + std::initializer_list il = {1, 2}; + g({il, {2, 3}}); + } +} -- 2.40.0