diff options
author | Hubert Tong <hubert.reinterpretcast@gmail.com> | 2015-06-25 00:25:49 +0000 |
---|---|---|
committer | Hubert Tong <hubert.reinterpretcast@gmail.com> | 2015-06-25 00:25:49 +0000 |
commit | 3280b3307f67d5b7406c6d8d3b451ddd0aad8832 (patch) | |
tree | ba5570fffdfc28db96bab791ae5864b7f11a0171 | |
parent | ec3cb573f522cf6748eae8afa5b33f9b65c33d6e (diff) | |
download | bcm5719-llvm-3280b3307f67d5b7406c6d8d3b451ddd0aad8832.tar.gz bcm5719-llvm-3280b3307f67d5b7406c6d8d3b451ddd0aad8832.zip |
Consolidate and unify initializer list deduction
Summary:
This patch reduces duplication in the template argument deduction code
for handling deduction from initializer lists in a function call. This
extends the fix for PR12119 to also apply to the case where the
corresponding parameter is a trailing parameter pack.
Test Plan:
A test for deduction from nested initializer lists where the
corresponding parameter is a trailing parameter pack is added in
`clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp`.
Reviewers: fraggamuffin, rsmith
Reviewed By: rsmith
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D10681
llvm-svn: 240612
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 82 | ||||
-rw-r--r-- | clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp | 7 |
2 files changed, 56 insertions, 33 deletions
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 6f676ad7c55..02e59af558b 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3190,6 +3190,40 @@ static bool hasDeducibleTemplateParameters(Sema &S, FunctionTemplateDecl *FunctionTemplate, QualType T); +static Sema::TemplateDeductionResult DeduceTemplateArgumentByListElement( + Sema &S, TemplateParameterList *TemplateParams, QualType ParamType, + Expr *Arg, TemplateDeductionInfo &Info, + SmallVectorImpl<DeducedTemplateArgument> &Deduced, unsigned TDF); + +/// \brief Attempt template argument deduction from an initializer list +/// deemed to be an argument in a function call. +static bool +DeduceFromInitializerList(Sema &S, TemplateParameterList *TemplateParams, + QualType AdjustedParamType, InitListExpr *ILE, + TemplateDeductionInfo &Info, + SmallVectorImpl<DeducedTemplateArgument> &Deduced, + unsigned TDF, Sema::TemplateDeductionResult &Result) { + // If the argument is an initializer list then the parameter is an undeduced + // context, unless the parameter type is (reference to cv) + // std::initializer_list<P'>, in which case deduction is done for each element + // of the initializer list as-if it were an argument in a function call, and + // the result is the deduced type if it's the same for all elements. + QualType X; + if (!S.isStdInitializerList(AdjustedParamType, &X)) + return false; + + Result = Sema::TDK_Success; + + // Recurse down into the init list. + for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) { + if ((Result = DeduceTemplateArgumentByListElement( + S, TemplateParams, X, ILE->getInit(i), Info, Deduced, TDF))) + return true; + } + + return true; +} + /// \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 a parameter @@ -3204,19 +3238,13 @@ DeduceTemplateArgumentByListElement(Sema &S, // Handle the case where an init list contains another init list as the // element. if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) { - QualType X; - if (!S.isStdInitializerList(ParamType.getNonReferenceType(), &X)) + Sema::TemplateDeductionResult Result; + if (!DeduceFromInitializerList(S, TemplateParams, + ParamType.getNonReferenceType(), ILE, Info, + Deduced, TDF, Result)) 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; + return Result; } // For all other cases, just match by type. @@ -3335,22 +3363,14 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( // If the argument is an initializer list ... if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) { - // ... then the parameter is an undeduced context, unless the parameter - // type is (reference to cv) std::initializer_list<P'>, in which case - // deduction is done for each element of the initializer list, and the - // result is the deduced type if it's the same for all elements. - QualType X; + TemplateDeductionResult Result; // Removing references was already done. - if (!isStdInitializerList(ParamType, &X)) + if (!DeduceFromInitializerList(*this, TemplateParams, ParamType, ILE, + Info, Deduced, TDF, Result)) continue; - for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) { - if (TemplateDeductionResult Result = - DeduceTemplateArgumentByListElement(*this, TemplateParams, X, - ILE->getInit(i), - Info, Deduced, TDF)) - return Result; - } + if (Result) + return Result; // Don't track the argument type, since an initializer list has none. continue; } @@ -3406,19 +3426,15 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( // As above, initializer lists need special handling. if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) { - QualType X; - if (!isStdInitializerList(ParamType, &X)) { + TemplateDeductionResult Result; + if (!DeduceFromInitializerList(*this, TemplateParams, ParamType, ILE, + Info, Deduced, TDF, Result)) { ++ArgIdx; break; } - for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) { - if (TemplateDeductionResult Result = - DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, X, - ILE->getInit(i)->getType(), - Info, Deduced, TDF)) - return Result; - } + if (Result) + return Result; } else { // Keep track of the argument type and corresponding argument index, diff --git a/clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp index a78f022e84c..9456dd713aa 100644 --- a/clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -275,3 +275,10 @@ namespace TemporaryInitListSourceRange_PR22367 { {0} ); } + +namespace ParameterPackNestedInitializerLists_PR23904c3 { + template <typename ...T> + void f(std::initializer_list<std::initializer_list<T>> ...tt); + + void foo() { f({{0}}, {{'\0'}}); } +} |