]> granicus.if.org Git - clang/commitdiff
Consolidate and unify initializer list deduction
authorHubert Tong <hubert.reinterpretcast@gmail.com>
Thu, 25 Jun 2015 00:25:49 +0000 (00:25 +0000)
committerHubert Tong <hubert.reinterpretcast@gmail.com>
Thu, 25 Jun 2015 00:25:49 +0000 (00:25 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@240612 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplateDeduction.cpp
test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp

index 6f676ad7c55de987a8d97385d601d4d8443a0f0a..02e59af558b23fb32268ad290dfd6af213aa3317 100644 (file)
@@ -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,
index a78f022e84c92f982e71c966bfd652c6f03a2a28..9456dd713aa84948d975703c0dd6abc39f6fd594 100644 (file)
@@ -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'}}); }
+}