r291074 - Factor out more common logic in template argument deduction from function call arguments.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 4 20:08:31 PST 2017


Author: rsmith
Date: Wed Jan  4 22:08:31 2017
New Revision: 291074

URL: http://llvm.org/viewvc/llvm-project?rev=291074&view=rev
Log:
Factor out more common logic in template argument deduction from function call arguments.

No functionality change intended.

Modified:
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=291074&r1=291073&r2=291074&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Wed Jan  4 22:08:31 2017
@@ -3197,19 +3197,20 @@ static bool
 hasDeducibleTemplateParameters(Sema &S, FunctionTemplateDecl *FunctionTemplate,
                                QualType T);
 
-static Sema::TemplateDeductionResult DeduceTemplateArgumentByListElement(
+static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument(
     Sema &S, TemplateParameterList *TemplateParams, QualType ParamType,
     Expr *Arg, TemplateDeductionInfo &Info,
-    SmallVectorImpl<DeducedTemplateArgument> &Deduced, unsigned TDF);
+    SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+    SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs,
+    Optional<unsigned> ArgIdx, unsigned TDF);
 
 /// \brief Attempt template argument deduction from an initializer list
 ///        deemed to be an argument in a function call.
-static Sema::TemplateDeductionResult
-DeduceFromInitializerList(Sema &S, TemplateParameterList *TemplateParams,
-                          QualType AdjustedParamType, InitListExpr *ILE,
-                          TemplateDeductionInfo &Info,
-                          SmallVectorImpl<DeducedTemplateArgument> &Deduced,
-                          unsigned TDF) {
+static Sema::TemplateDeductionResult DeduceFromInitializerList(
+    Sema &S, TemplateParameterList *TemplateParams, QualType AdjustedParamType,
+    InitListExpr *ILE, TemplateDeductionInfo &Info,
+    SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+    SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs, unsigned TDF) {
   // C++ [temp.deduct.call]p1: (CWG 1591)
   //   If removing references and cv-qualifiers from P gives
   //   std::initializer_list<P0> or P0[N] for some P0 and N and the argument is
@@ -3217,8 +3218,7 @@ DeduceFromInitializerList(Sema &S, Templ
   //   each element of the initializer list, taking P0 as a function template
   //   parameter type and the initializer element as its argument
   //
-  // FIXME: Remove references and cv-qualifiers here? Consider
-  //          std::initializer_list<std::initializer_list<T>&&>
+  // We've already removed references and cv-qualifiers here.
   QualType ElTy;
   auto *ArrTy = S.Context.getAsArrayType(AdjustedParamType);
   if (ArrTy)
@@ -3232,8 +3232,9 @@ DeduceFromInitializerList(Sema &S, Templ
   // Deduction only needs to be done for dependent types.
   if (ElTy->isDependentType()) {
     for (Expr *E : ILE->inits()) {
-      if (auto Result = DeduceTemplateArgumentByListElement(
-              S, TemplateParams, ElTy, E, Info, Deduced, TDF))
+      if (auto Result = DeduceTemplateArgumentsFromCallArgument(
+              S, TemplateParams, ElTy, E, Info, Deduced, OriginalCallArgs, None,
+              TDF))
         return Result;
     }
   }
@@ -3259,30 +3260,39 @@ DeduceFromInitializerList(Sema &S, Templ
   return Sema::TDK_Success;
 }
 
-/// \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
-///        of type \c initializer_list\<ParamType\>.
-static Sema::TemplateDeductionResult
-DeduceTemplateArgumentByListElement(Sema &S,
-                                    TemplateParameterList *TemplateParams,
-                                    QualType ParamType, Expr *Arg,
-                                    TemplateDeductionInfo &Info,
-                              SmallVectorImpl<DeducedTemplateArgument> &Deduced,
-                                    unsigned TDF) {
-  // Handle the case where an init list contains another init list as the
-  // element.
-  if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg))
-    return DeduceFromInitializerList(S, TemplateParams,
-                                     ParamType.getNonReferenceType(), ILE, Info,
-                                     Deduced, TDF);
-
-  // For all other cases, just match by type.
+/// \brief Perform template argument deduction per [temp.deduct.call] for a
+///        single parameter / argument pair.
+static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument(
+    Sema &S, TemplateParameterList *TemplateParams, QualType ParamType,
+    Expr *Arg, TemplateDeductionInfo &Info,
+    SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+    SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs,
+    Optional<unsigned> ArgIdx, unsigned TDF) {
   QualType ArgType = Arg->getType();
+  QualType OrigParamType = ParamType;
+
+  //   If P is a reference type [...]
+  //   If P is a cv-qualified type [...]
   if (AdjustFunctionParmAndArgTypesForDeduction(S, TemplateParams, ParamType,
                                                 ArgType, Arg, TDF))
     return Sema::TDK_Success;
 
+  //   If [...] the argument is a non-empty initializer list [...]
+  if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg))
+    return DeduceFromInitializerList(S, TemplateParams, ParamType, ILE, Info,
+                                     Deduced, OriginalCallArgs, TDF);
+
+  //   [...] the deduction process attempts to find template argument values
+  //   that will make the deduced A identical to A
+  //
+  // Keep track of the argument type and corresponding parameter index,
+  // so we can check for compatibility between the deduced A and A.
+  //
+  // FIXME: We are supposed to perform this check for the P/A pairs we extract
+  // from the initializer list case too.
+  if (ArgIdx)
+    OriginalCallArgs.push_back(
+        Sema::OriginalCallArg(OrigParamType, *ArgIdx, ArgType));
   return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType,
                                             ArgType, Info, Deduced, TDF);
 }
@@ -3365,31 +3375,17 @@ Sema::TemplateDeductionResult Sema::Dedu
 
   // Deduce an argument of type ParamType from an expression with index ArgIdx.
   auto DeduceCallArgument = [&](QualType ParamType, unsigned ArgIdx) {
-    Expr *Arg = Args[ArgIdx];
-    QualType ArgType = Arg->getType();
-    QualType OrigParamType = ParamType;
-
-    unsigned TDF = 0;
-    if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams,
-                                                  ParamType, ArgType, Arg,
-                                                  TDF))
-      return Sema::TDK_Success;
-
-    // If we have nothing to deduce, we're done.
+    // C++ [demp.deduct.call]p1: (DR1391)
+    //   Template argument deduction is done by comparing each function template
+    //   parameter that contains template-parameters that participate in
+    //   template argument deduction ...
     if (!hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType))
       return Sema::TDK_Success;
 
-    // If the argument is an initializer list ...
-    if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg))
-      return DeduceFromInitializerList(*this, TemplateParams, ParamType, ILE,
-                                       Info, Deduced, TDF);
-
-    // Keep track of the argument type and corresponding parameter index,
-    // so we can check for compatibility between the deduced A and A.
-    OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx, ArgType));
-
-    return DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, ParamType,
-                                              ArgType, Info, Deduced, TDF);
+    //   ... with the type of the corresponding argument
+    return DeduceTemplateArgumentsFromCallArgument(
+        *this, TemplateParams, ParamType, Args[ArgIdx], Info, Deduced,
+        OriginalCallArgs, ArgIdx, /*TDF*/ 0);
   };
 
   // Deduce template arguments from the function parameters.
@@ -4055,8 +4051,6 @@ Sema::DeduceAutoType(TypeLoc Type, Expr
   // Deduce type of TemplParam in Func(Init)
   SmallVector<DeducedTemplateArgument, 1> Deduced;
   Deduced.resize(1);
-  QualType InitType = Init->getType();
-  unsigned TDF = 0;
 
   TemplateDeductionInfo Info(Loc, Depth);
 
@@ -4071,12 +4065,14 @@ Sema::DeduceAutoType(TypeLoc Type, Expr
     return DAR_Failed;
   };
 
+  SmallVector<OriginalCallArg, 4> OriginalCallArgs;
+
   InitListExpr *InitList = dyn_cast<InitListExpr>(Init);
   if (InitList) {
     for (unsigned i = 0, e = InitList->getNumInits(); i < e; ++i) {
-      if (DeduceTemplateArgumentByListElement(*this, TemplateParamsSt.get(),
-                                              TemplArg, InitList->getInit(i),
-                                              Info, Deduced, TDF))
+      if (DeduceTemplateArgumentsFromCallArgument(
+              *this, TemplateParamsSt.get(), TemplArg, InitList->getInit(i),
+              Info, Deduced, OriginalCallArgs, None, /*TDF*/0))
         return DeductionFailed();
     }
   } else {
@@ -4085,13 +4081,9 @@ Sema::DeduceAutoType(TypeLoc Type, Expr
       return DAR_FailedAlreadyDiagnosed;
     }
 
-    if (AdjustFunctionParmAndArgTypesForDeduction(
-            *this, TemplateParamsSt.get(), FuncParam, InitType, Init, TDF))
-      return DAR_Failed;
-
-    if (DeduceTemplateArgumentsByTypeMatch(*this, TemplateParamsSt.get(),
-                                           FuncParam, InitType, Info, Deduced,
-                                           TDF))
+    if (DeduceTemplateArgumentsFromCallArgument(
+            *this, TemplateParamsSt.get(), FuncParam, Init, Info, Deduced,
+            OriginalCallArgs, /*ArgIdx*/0, /*TDF*/0))
       return DeductionFailed();
   }
 
@@ -4113,12 +4105,11 @@ Sema::DeduceAutoType(TypeLoc Type, Expr
 
   // Check that the deduced argument type is compatible with the original
   // argument type per C++ [temp.deduct.call]p4.
-  if (!InitList && !Result.isNull() &&
-      CheckOriginalCallArgDeduction(*this,
-                                    Sema::OriginalCallArg(FuncParam,0,InitType),
-                                    Result)) {
-    Result = QualType();
-    return DeductionFailed();
+  for (const OriginalCallArg &OriginalArg : OriginalCallArgs) {
+    if (CheckOriginalCallArgDeduction(*this, OriginalArg, Result)) {
+      Result = QualType();
+      return DeductionFailed();
+    }
   }
 
   return DAR_Succeeded;




More information about the cfe-commits mailing list