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