diff options
Diffstat (limited to 'lib/Sema/SemaTemplateDeduction.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 84 |
1 files changed, 51 insertions, 33 deletions
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 6f676ad7c55de..ae8157e70a603 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/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, @@ -3952,6 +3968,8 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) { } QualType Deduced = BuildDecltypeType(Init, Init->getLocStart(), false); + if (Deduced.isNull()) + return DAR_FailedAlreadyDiagnosed; // FIXME: Support a non-canonical deduced type for 'auto'. Deduced = Context.getCanonicalType(Deduced); Result = SubstituteAutoTransform(*this, Deduced).Apply(Type); |