summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaTemplateDeduction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaTemplateDeduction.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp61
1 files changed, 43 insertions, 18 deletions
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index a9fd8fd40ce..93e796ee966 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -2912,14 +2912,13 @@ static unsigned getPackIndexForParam(Sema &S,
///
/// \param OriginalCallArgs If non-NULL, the original call arguments against
/// which the deduced argument types should be compared.
-Sema::TemplateDeductionResult
-Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- unsigned NumExplicitlySpecified,
- FunctionDecl *&Specialization,
- TemplateDeductionInfo &Info,
- SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs,
- bool PartialOverloading) {
+Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
+ FunctionTemplateDecl *FunctionTemplate,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ unsigned NumExplicitlySpecified, FunctionDecl *&Specialization,
+ TemplateDeductionInfo &Info,
+ SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs,
+ bool PartialOverloading, llvm::function_ref<bool()> CheckNonDependent) {
// Unevaluated SFINAE context.
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
SFINAETrap Trap(*this);
@@ -2946,6 +2945,18 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
PartialOverloading))
return Result;
+ // C++ [temp.deduct.call]p10: [DR1391]
+ // If deduction succeeds for all parameters that contain
+ // template-parameters that participate in template argument deduction,
+ // and all template arguments are explicitly specified, deduced, or
+ // obtained from default template arguments, remaining parameters are then
+ // compared with the corresponding arguments. For each remaining parameter
+ // P with a type that was non-dependent before substitution of any
+ // explicitly-specified template arguments, if the corresponding argument
+ // A cannot be implicitly converted to P, deduction fails.
+ if (CheckNonDependent())
+ return TDK_NonDependentConversionFailure;
+
// Form the template argument list from the deduced template arguments.
TemplateArgumentList *DeducedArgumentList
= TemplateArgumentList::CreateCopy(Context, Builder);
@@ -3392,12 +3403,19 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument(
/// \param Info the argument will be updated to provide additional information
/// about template argument deduction.
///
+/// \param CheckNonDependent A callback to invoke to check conversions for
+/// non-dependent parameters, between deduction and substitution, per DR1391.
+/// If this returns true, substitution will be skipped and we return
+/// TDK_NonDependentConversionFailure. The callback is passed the parameter
+/// types (after substituting explicit template arguments).
+///
/// \returns the result of template argument deduction.
Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
FunctionTemplateDecl *FunctionTemplate,
TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
FunctionDecl *&Specialization, TemplateDeductionInfo &Info,
- bool PartialOverloading) {
+ bool PartialOverloading,
+ llvm::function_ref<bool(ArrayRef<QualType>)> CheckNonDependent) {
if (FunctionTemplate->isInvalidDecl())
return TDK_Invalid;
@@ -3425,7 +3443,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
SmallVector<DeducedTemplateArgument, 4> Deduced;
- SmallVector<QualType, 4> ParamTypes;
+ SmallVector<QualType, 8> ParamTypes;
unsigned NumExplicitlySpecified = 0;
if (ExplicitTemplateArgs) {
TemplateDeductionResult Result =
@@ -3445,7 +3463,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
ParamTypes.push_back(Function->getParamDecl(I)->getType());
}
- SmallVector<OriginalCallArg, 4> OriginalCallArgs;
+ SmallVector<OriginalCallArg, 8> OriginalCallArgs;
// Deduce an argument of type ParamType from an expression with index ArgIdx.
auto DeduceCallArgument = [&](QualType ParamType, unsigned ArgIdx) {
@@ -3464,6 +3482,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
// Deduce template arguments from the function parameters.
Deduced.resize(TemplateParams->size());
+ SmallVector<QualType, 8> ParamTypesForArgChecking;
for (unsigned ParamIdx = 0, NumParamTypes = ParamTypes.size(), ArgIdx = 0;
ParamIdx != NumParamTypes; ++ParamIdx) {
QualType ParamType = ParamTypes[ParamIdx];
@@ -3475,6 +3494,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
if (ArgIdx >= Args.size())
break;
+ ParamTypesForArgChecking.push_back(ParamType);
if (auto Result = DeduceCallArgument(ParamType, ArgIdx++))
return Result;
@@ -3502,20 +3522,25 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
// parameter pack and 0 otherwise, and we treat each deduction as a
// non-deduced context.
if (ParamIdx + 1 == NumParamTypes) {
- for (; ArgIdx < Args.size(); PackScope.nextPackElement(), ++ArgIdx)
+ for (; ArgIdx < Args.size(); PackScope.nextPackElement(), ++ArgIdx) {
+ ParamTypesForArgChecking.push_back(ParamPattern);
if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx))
return Result;
+ }
} else {
// If the parameter type contains an explicitly-specified pack that we
// could not expand, skip the number of parameters notionally created
// by the expansion.
Optional<unsigned> NumExpansions = ParamExpansion->getNumExpansions();
- if (NumExpansions && !PackScope.isPartiallyExpanded())
+ if (NumExpansions && !PackScope.isPartiallyExpanded()) {
for (unsigned I = 0; I != *NumExpansions && ArgIdx < Args.size();
- ++I, ++ArgIdx)
+ ++I, ++ArgIdx) {
+ ParamTypesForArgChecking.push_back(ParamPattern);
// FIXME: Should we add OriginalCallArgs for these? What if the
// corresponding argument is a list?
PackScope.nextPackElement();
+ }
+ }
}
// Build argument packs for each of the parameter packs expanded by this
@@ -3524,10 +3549,10 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
return Result;
}
- return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
- NumExplicitlySpecified, Specialization,
- Info, &OriginalCallArgs,
- PartialOverloading);
+ return FinishTemplateArgumentDeduction(
+ FunctionTemplate, Deduced, NumExplicitlySpecified, Specialization, Info,
+ &OriginalCallArgs, PartialOverloading,
+ [&]() { return CheckNonDependent(ParamTypesForArgChecking); });
}
QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
OpenPOWER on IntegriCloud