summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplateDeduction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaTemplateDeduction.cpp')
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp1669
1 files changed, 916 insertions, 753 deletions
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 5740bc712e861..0bc85a2f2635b 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -100,12 +100,13 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
SmallVectorImpl<DeducedTemplateArgument> &
Deduced,
unsigned TDF,
- bool PartialOrdering = false);
+ bool PartialOrdering = false,
+ bool DeducedFromArrayBound = false);
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
- const TemplateArgument *Params, unsigned NumParams,
- const TemplateArgument *Args, unsigned NumArgs,
+ ArrayRef<TemplateArgument> Params,
+ ArrayRef<TemplateArgument> Args,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
bool NumberOfArgumentsMustMatch);
@@ -113,7 +114,8 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
/// \brief If the given expression is of a form that permits the deduction
/// of a non-type template parameter, return the declaration of that
/// non-type template parameter.
-static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) {
+static NonTypeTemplateParmDecl *
+getDeducedParameterFromExpr(TemplateDeductionInfo &Info, Expr *E) {
// If we are within an alias template, the expression may have undergone
// any number of parameter substitutions already.
while (1) {
@@ -127,7 +129,9 @@ static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) {
}
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
- return dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
+ if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl()))
+ if (NTTP->getDepth() == Info.getDeducedDepth())
+ return NTTP;
return nullptr;
}
@@ -157,6 +161,20 @@ checkDeducedTemplateArguments(ASTContext &Context,
if (Y.isNull())
return X;
+ // If we have two non-type template argument values deduced for the same
+ // parameter, they must both match the type of the parameter, and thus must
+ // match each other's type. As we're only keeping one of them, we must check
+ // for that now. The exception is that if either was deduced from an array
+ // bound, the type is permitted to differ.
+ if (!X.wasDeducedFromArrayBound() && !Y.wasDeducedFromArrayBound()) {
+ QualType XType = X.getNonTypeTemplateArgumentType();
+ if (!XType.isNull()) {
+ QualType YType = Y.getNonTypeTemplateArgumentType();
+ if (YType.isNull() || !Context.hasSameType(XType, YType))
+ return DeducedTemplateArgument();
+ }
+ }
+
switch (X.getKind()) {
case TemplateArgument::Null:
llvm_unreachable("Non-deduced template arguments handled above");
@@ -167,6 +185,12 @@ checkDeducedTemplateArguments(ASTContext &Context,
Context.hasSameType(X.getAsType(), Y.getAsType()))
return X;
+ // If one of the two arguments was deduced from an array bound, the other
+ // supersedes it.
+ if (X.wasDeducedFromArrayBound() != Y.wasDeducedFromArrayBound())
+ return X.wasDeducedFromArrayBound() ? Y : X;
+
+ // The arguments are not compatible.
return DeducedTemplateArgument();
case TemplateArgument::Integral:
@@ -177,9 +201,7 @@ checkDeducedTemplateArguments(ASTContext &Context,
Y.getKind() == TemplateArgument::Declaration ||
(Y.getKind() == TemplateArgument::Integral &&
hasSameExtendedValue(X.getAsIntegral(), Y.getAsIntegral())))
- return DeducedTemplateArgument(X,
- X.wasDeducedFromArrayBound() &&
- Y.wasDeducedFromArrayBound());
+ return X.wasDeducedFromArrayBound() ? Y : X;
// All other combinations are incompatible.
return DeducedTemplateArgument();
@@ -201,37 +223,38 @@ checkDeducedTemplateArguments(ASTContext &Context,
// All other combinations are incompatible.
return DeducedTemplateArgument();
- case TemplateArgument::Expression:
- // If we deduced a dependent expression in one case and either an integral
- // constant or a declaration in another case, keep the integral constant
- // or declaration.
- if (Y.getKind() == TemplateArgument::Integral ||
- Y.getKind() == TemplateArgument::Declaration)
- return DeducedTemplateArgument(Y, X.wasDeducedFromArrayBound() &&
- Y.wasDeducedFromArrayBound());
-
- if (Y.getKind() == TemplateArgument::Expression) {
- // Compare the expressions for equality
- llvm::FoldingSetNodeID ID1, ID2;
- X.getAsExpr()->Profile(ID1, Context, true);
- Y.getAsExpr()->Profile(ID2, Context, true);
- if (ID1 == ID2)
- return X;
- }
+ case TemplateArgument::Expression: {
+ if (Y.getKind() != TemplateArgument::Expression)
+ return checkDeducedTemplateArguments(Context, Y, X);
- // All other combinations are incompatible.
+ // Compare the expressions for equality
+ llvm::FoldingSetNodeID ID1, ID2;
+ X.getAsExpr()->Profile(ID1, Context, true);
+ Y.getAsExpr()->Profile(ID2, Context, true);
+ if (ID1 == ID2)
+ return X.wasDeducedFromArrayBound() ? Y : X;
+
+ // Differing dependent expressions are incompatible.
return DeducedTemplateArgument();
+ }
case TemplateArgument::Declaration:
+ assert(!X.wasDeducedFromArrayBound());
+
// If we deduced a declaration and a dependent expression, keep the
// declaration.
if (Y.getKind() == TemplateArgument::Expression)
return X;
// If we deduced a declaration and an integral constant, keep the
- // integral constant.
- if (Y.getKind() == TemplateArgument::Integral)
+ // integral constant and whichever type did not come from an array
+ // bound.
+ if (Y.getKind() == TemplateArgument::Integral) {
+ if (Y.wasDeducedFromArrayBound())
+ return TemplateArgument(Context, Y.getAsIntegral(),
+ X.getParamTypeForDecl());
return Y;
+ }
// If we deduced two declarations, make sure they they refer to the
// same declaration.
@@ -253,9 +276,8 @@ checkDeducedTemplateArguments(ASTContext &Context,
if (Y.getKind() == TemplateArgument::Integral)
return Y;
- // If we deduced two null pointers, make sure they have the same type.
- if (Y.getKind() == TemplateArgument::NullPtr &&
- Context.hasSameType(X.getNullPtrType(), Y.getNullPtrType()))
+ // If we deduced two null pointers, they are the same.
+ if (Y.getKind() == TemplateArgument::NullPtr)
return X;
// All other combinations are incompatible.
@@ -285,19 +307,18 @@ checkDeducedTemplateArguments(ASTContext &Context,
}
/// \brief Deduce the value of the given non-type template parameter
-/// from the given constant.
+/// as the given deduced template argument. All non-type template parameter
+/// deduction is funneled through here.
static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
- Sema &S, NonTypeTemplateParmDecl *NTTP, const llvm::APSInt &Value,
- QualType ValueType, bool DeducedFromArrayBound, TemplateDeductionInfo &Info,
+ Sema &S, TemplateParameterList *TemplateParams,
+ NonTypeTemplateParmDecl *NTTP, const DeducedTemplateArgument &NewDeduced,
+ QualType ValueType, TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
- assert(NTTP->getDepth() == 0 &&
- "Cannot deduce non-type template argument with depth > 0");
-
- DeducedTemplateArgument NewDeduced(S.Context, Value, ValueType,
- DeducedFromArrayBound);
- DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
- Deduced[NTTP->getIndex()],
- NewDeduced);
+ assert(NTTP->getDepth() == Info.getDeducedDepth() &&
+ "deducing non-type template argument with wrong depth");
+
+ DeducedTemplateArgument Result = checkDeducedTemplateArguments(
+ S.Context, Deduced[NTTP->getIndex()], NewDeduced);
if (Result.isNull()) {
Info.Param = NTTP;
Info.FirstArg = Deduced[NTTP->getIndex()];
@@ -306,68 +327,77 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
}
Deduced[NTTP->getIndex()] = Result;
- return Sema::TDK_Success;
+ if (!S.getLangOpts().CPlusPlus1z)
+ return Sema::TDK_Success;
+
+ // FIXME: It's not clear how deduction of a parameter of reference
+ // type from an argument (of non-reference type) should be performed.
+ // For now, we just remove reference types from both sides and let
+ // the final check for matching types sort out the mess.
+ return DeduceTemplateArgumentsByTypeMatch(
+ S, TemplateParams, NTTP->getType().getNonReferenceType(),
+ ValueType.getNonReferenceType(), Info, Deduced, TDF_SkipNonDependent,
+ /*PartialOrdering=*/false,
+ /*ArrayBound=*/NewDeduced.wasDeducedFromArrayBound());
+}
+
+/// \brief Deduce the value of the given non-type template parameter
+/// from the given integral constant.
+static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
+ Sema &S, TemplateParameterList *TemplateParams,
+ NonTypeTemplateParmDecl *NTTP, const llvm::APSInt &Value,
+ QualType ValueType, bool DeducedFromArrayBound, TemplateDeductionInfo &Info,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ return DeduceNonTypeTemplateArgument(
+ S, TemplateParams, NTTP,
+ DeducedTemplateArgument(S.Context, Value, ValueType,
+ DeducedFromArrayBound),
+ ValueType, Info, Deduced);
+}
+
+/// \brief Deduce the value of the given non-type template parameter
+/// from the given null pointer template argument type.
+static Sema::TemplateDeductionResult DeduceNullPtrTemplateArgument(
+ Sema &S, TemplateParameterList *TemplateParams,
+ NonTypeTemplateParmDecl *NTTP, QualType NullPtrType,
+ TemplateDeductionInfo &Info,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ Expr *Value =
+ S.ImpCastExprToType(new (S.Context) CXXNullPtrLiteralExpr(
+ S.Context.NullPtrTy, NTTP->getLocation()),
+ NullPtrType, CK_NullToPointer)
+ .get();
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
+ DeducedTemplateArgument(Value),
+ Value->getType(), Info, Deduced);
}
/// \brief Deduce the value of the given non-type template parameter
/// from the given type- or value-dependent expression.
///
/// \returns true if deduction succeeded, false otherwise.
-static Sema::TemplateDeductionResult
-DeduceNonTypeTemplateArgument(Sema &S,
- NonTypeTemplateParmDecl *NTTP,
- Expr *Value,
- TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
- assert(NTTP->getDepth() == 0 &&
- "Cannot deduce non-type template argument with depth > 0");
- assert((Value->isTypeDependent() || Value->isValueDependent()) &&
- "Expression template argument must be type- or value-dependent.");
-
- DeducedTemplateArgument NewDeduced(Value);
- DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
- Deduced[NTTP->getIndex()],
- NewDeduced);
-
- if (Result.isNull()) {
- Info.Param = NTTP;
- Info.FirstArg = Deduced[NTTP->getIndex()];
- Info.SecondArg = NewDeduced;
- return Sema::TDK_Inconsistent;
- }
-
- Deduced[NTTP->getIndex()] = Result;
- return Sema::TDK_Success;
+static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
+ Sema &S, TemplateParameterList *TemplateParams,
+ NonTypeTemplateParmDecl *NTTP, Expr *Value, TemplateDeductionInfo &Info,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
+ DeducedTemplateArgument(Value),
+ Value->getType(), Info, Deduced);
}
/// \brief Deduce the value of the given non-type template parameter
/// from the given declaration.
///
/// \returns true if deduction succeeded, false otherwise.
-static Sema::TemplateDeductionResult
-DeduceNonTypeTemplateArgument(Sema &S,
- NonTypeTemplateParmDecl *NTTP,
- ValueDecl *D,
- TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
- assert(NTTP->getDepth() == 0 &&
- "Cannot deduce non-type template argument with depth > 0");
-
+static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
+ Sema &S, TemplateParameterList *TemplateParams,
+ NonTypeTemplateParmDecl *NTTP, ValueDecl *D, QualType T,
+ TemplateDeductionInfo &Info,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
D = D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
- TemplateArgument New(D, NTTP->getType());
- DeducedTemplateArgument NewDeduced(New);
- DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
- Deduced[NTTP->getIndex()],
- NewDeduced);
- if (Result.isNull()) {
- Info.Param = NTTP;
- Info.FirstArg = Deduced[NTTP->getIndex()];
- Info.SecondArg = NewDeduced;
- return Sema::TDK_Inconsistent;
- }
-
- Deduced[NTTP->getIndex()] = Result;
- return Sema::TDK_Success;
+ TemplateArgument New(D, T);
+ return DeduceNonTypeTemplateArgument(
+ S, TemplateParams, NTTP, DeducedTemplateArgument(New), T, Info, Deduced);
}
static Sema::TemplateDeductionResult
@@ -386,6 +416,10 @@ DeduceTemplateArguments(Sema &S,
if (TemplateTemplateParmDecl *TempParam
= dyn_cast<TemplateTemplateParmDecl>(ParamDecl)) {
+ // If we're not deducing at this depth, there's nothing to deduce.
+ if (TempParam->getDepth() != Info.getDeducedDepth())
+ return Sema::TDK_Success;
+
DeducedTemplateArgument NewDeduced(S.Context.getCanonicalTemplateName(Arg));
DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
Deduced[TempParam->getIndex()],
@@ -453,9 +487,9 @@ DeduceTemplateArguments(Sema &S,
// Perform template argument deduction on each template
// argument. Ignore any missing/extra arguments, since they could be
// filled in by default arguments.
- return DeduceTemplateArguments(S, TemplateParams, Param->getArgs(),
- Param->getNumArgs(), SpecArg->getArgs(),
- SpecArg->getNumArgs(), Info, Deduced,
+ return DeduceTemplateArguments(S, TemplateParams,
+ Param->template_arguments(),
+ SpecArg->template_arguments(), Info, Deduced,
/*NumberOfArgumentsMustMatch=*/false);
}
@@ -487,10 +521,9 @@ DeduceTemplateArguments(Sema &S,
return Result;
// Perform template argument deduction for the template arguments.
- return DeduceTemplateArguments(
- S, TemplateParams, Param->getArgs(), Param->getNumArgs(),
- SpecArg->getTemplateArgs().data(), SpecArg->getTemplateArgs().size(),
- Info, Deduced, /*NumberOfArgumentsMustMatch=*/true);
+ return DeduceTemplateArguments(S, TemplateParams, Param->template_arguments(),
+ SpecArg->getTemplateArgs().asArray(), Info,
+ Deduced, /*NumberOfArgumentsMustMatch=*/true);
}
/// \brief Determines whether the given type is an opaque type that
@@ -589,7 +622,7 @@ public:
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
unsigned Depth, Index;
std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
- if (Depth == 0 && !SawIndices[Index]) {
+ if (Depth == Info.getDeducedDepth() && !SawIndices[Index]) {
SawIndices[Index] = true;
// Save the deduced template argument for the parameter pack expanded
@@ -620,7 +653,8 @@ public:
S.CurrentInstantiationScope->getPartiallySubstitutedPack(
&ExplicitArgs, &NumExplicitArgs);
if (PartiallySubstitutedPack &&
- getDepthAndIndex(PartiallySubstitutedPack).second == Pack.Index)
+ getDepthAndIndex(PartiallySubstitutedPack) ==
+ std::make_pair(Info.getDeducedDepth(), Pack.Index))
Pack.New.append(ExplicitArgs, ExplicitArgs + NumExplicitArgs);
}
}
@@ -863,12 +897,12 @@ static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType,
if (ParamQs == ArgQs)
return false;
-
+
// Mismatched (but not missing) Objective-C GC attributes.
- if (ParamQs.getObjCGCAttr() != ArgQs.getObjCGCAttr() &&
+ if (ParamQs.getObjCGCAttr() != ArgQs.getObjCGCAttr() &&
ParamQs.hasObjCGCAttr())
return true;
-
+
// Mismatched (but not missing) address spaces.
if (ParamQs.getAddressSpace() != ArgQs.getAddressSpace() &&
ParamQs.hasAddressSpace())
@@ -878,7 +912,7 @@ static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType,
if (ParamQs.getObjCLifetime() != ArgQs.getObjCLifetime() &&
ParamQs.hasObjCLifetime())
return true;
-
+
// CVR qualifier superset.
return (ParamQs.getCVRQualifiers() != ArgQs.getCVRQualifiers()) &&
((ParamQs.getCVRQualifiers() | ArgQs.getCVRQualifiers())
@@ -901,9 +935,9 @@ bool Sema::isSameOrCompatibleFunctionType(CanQualType Param,
if (!ParamFunction || !ArgFunction)
return Param == Arg;
- // Noreturn adjustment.
+ // Noreturn and noexcept adjustment.
QualType AdjustedParam;
- if (IsNoReturnConversion(Param, Arg, AdjustedParam))
+ if (IsFunctionConversion(Param, Arg, AdjustedParam))
return Arg == Context.getCanonicalType(AdjustedParam);
// FIXME: Compatible calling conventions.
@@ -942,7 +976,8 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned TDF,
- bool PartialOrdering) {
+ bool PartialOrdering,
+ bool DeducedFromArrayBound) {
// We only want to look at the canonical types, since typedefs and
// sugar are not part of template argument deduction.
QualType Param = S.Context.getCanonicalType(ParamIn);
@@ -1057,10 +1092,12 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
// cv-list T
if (const TemplateTypeParmType *TemplateTypeParm
= Param->getAs<TemplateTypeParmType>()) {
- // Just skip any attempts to deduce from a placeholder type.
- if (Arg->isPlaceholderType())
+ // Just skip any attempts to deduce from a placeholder type or a parameter
+ // at a different depth.
+ if (Arg->isPlaceholderType() ||
+ Info.getDeducedDepth() != TemplateTypeParm->getDepth())
return Sema::TDK_Success;
-
+
unsigned Index = TemplateTypeParm->getIndex();
bool RecanonicalizeArg = false;
@@ -1085,7 +1122,8 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return Sema::TDK_Underqualified;
}
- assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0");
+ assert(TemplateTypeParm->getDepth() == Info.getDeducedDepth() &&
+ "saw template type parameter with wrong depth");
assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function");
QualType DeducedType = Arg;
@@ -1100,7 +1138,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
DeducedQs.removeAddressSpace();
if (ParamQs.hasObjCLifetime())
DeducedQs.removeObjCLifetime();
-
+
// Objective-C ARC:
// If template deduction would produce a lifetime qualifier on a type
// that is not a lifetime type, template argument deduction fails.
@@ -1109,9 +1147,9 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
Info.FirstArg = TemplateArgument(Param);
Info.SecondArg = TemplateArgument(Arg);
- return Sema::TDK_Underqualified;
+ return Sema::TDK_Underqualified;
}
-
+
// Objective-C ARC:
// If template deduction would produce an argument type with lifetime type
// but no lifetime qualifier, the __strong lifetime qualifier is inferred.
@@ -1119,14 +1157,14 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
DeducedType->isObjCLifetimeType() &&
!DeducedQs.hasObjCLifetime())
DeducedQs.setObjCLifetime(Qualifiers::OCL_Strong);
-
+
DeducedType = S.Context.getQualifiedType(DeducedType.getUnqualifiedType(),
DeducedQs);
-
+
if (RecanonicalizeArg)
DeducedType = S.Context.getCanonicalType(DeducedType);
- DeducedTemplateArgument NewDeduced(DeducedType);
+ DeducedTemplateArgument NewDeduced(DeducedType, DeducedFromArrayBound);
DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
Deduced[Index],
NewDeduced);
@@ -1163,7 +1201,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
return Sema::TDK_NonDeducedMismatch;
}
-
+
// If the parameter type is not dependent, there is nothing to deduce.
if (!Param->isDependentType()) {
if (!(TDF & TDF_SkipNonDependent)) {
@@ -1193,7 +1231,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
case Type::Class: llvm_unreachable("deducing non-canonical type: " #Class);
#define TYPE(Class, Base)
#include "clang/AST/TypeNodes.def"
-
+
case Type::TemplateTypeParm:
case Type::SubstTemplateTypeParmPack:
llvm_unreachable("Type nodes handled above");
@@ -1211,20 +1249,20 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
case Type::ObjCObjectPointer: {
if (TDF & TDF_SkipNonDependent)
return Sema::TDK_Success;
-
+
if (TDF & TDF_IgnoreQualifiers) {
Param = Param.getUnqualifiedType();
Arg = Arg.getUnqualifiedType();
}
-
+
return Param == Arg? Sema::TDK_Success : Sema::TDK_NonDeducedMismatch;
}
-
- // _Complex T [placeholder extension]
+
+ // _Complex T [placeholder extension]
case Type::Complex:
if (const ComplexType *ComplexArg = Arg->getAs<ComplexType>())
- return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
- cast<ComplexType>(Param)->getElementType(),
+ return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+ cast<ComplexType>(Param)->getElementType(),
ComplexArg->getElementType(),
Info, Deduced, TDF);
@@ -1337,18 +1375,18 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
// Determine the array bound is something we can deduce.
NonTypeTemplateParmDecl *NTTP
- = getDeducedParameterFromExpr(DependentArrayParm->getSizeExpr());
+ = getDeducedParameterFromExpr(Info, DependentArrayParm->getSizeExpr());
if (!NTTP)
return Sema::TDK_Success;
// We can perform template argument deduction for the given non-type
// template parameter.
- assert(NTTP->getDepth() == 0 &&
- "Cannot deduce non-type template argument at depth > 0");
+ assert(NTTP->getDepth() == Info.getDeducedDepth() &&
+ "saw non-type template parameter with wrong depth");
if (const ConstantArrayType *ConstantArrayArg
= dyn_cast<ConstantArrayType>(ArrayArg)) {
llvm::APSInt Size(ConstantArrayArg->getSize());
- return DeduceNonTypeTemplateArgument(S, NTTP, Size,
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, Size,
S.Context.getSizeType(),
/*ArrayBound=*/true,
Info, Deduced);
@@ -1356,7 +1394,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
if (const DependentSizedArrayType *DependentArrayArg
= dyn_cast<DependentSizedArrayType>(ArrayArg))
if (DependentArrayArg->getSizeExpr())
- return DeduceNonTypeTemplateArgument(S, NTTP,
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
DependentArrayArg->getSizeExpr(),
Info, Deduced);
@@ -1549,7 +1587,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
QualType(MemPtrParam->getClass(), 0),
QualType(MemPtrArg->getClass(), 0),
- Info, Deduced,
+ Info, Deduced,
TDF & TDF_IgnoreQualifiers);
}
@@ -1580,15 +1618,15 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
// Make sure that the vectors have the same number of elements.
if (VectorParam->getNumElements() != VectorArg->getNumElements())
return Sema::TDK_NonDeducedMismatch;
-
+
// Perform deduction on the element types.
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
VectorParam->getElementType(),
VectorArg->getElementType(),
Info, Deduced, TDF);
}
-
- if (const DependentSizedExtVectorType *VectorArg
+
+ if (const DependentSizedExtVectorType *VectorArg
= dyn_cast<DependentSizedExtVectorType>(Arg)) {
// We can't check the number of elements, since the argument has a
// dependent number of elements. This can only occur during partial
@@ -1600,10 +1638,10 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
VectorArg->getElementType(),
Info, Deduced, TDF);
}
-
+
return Sema::TDK_NonDeducedMismatch;
}
-
+
// (clang extension)
//
// T __attribute__(((ext_vector_type(N))))
@@ -1619,20 +1657,24 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
VectorArg->getElementType(),
Info, Deduced, TDF))
return Result;
-
+
// Perform deduction on the vector size, if we can.
NonTypeTemplateParmDecl *NTTP
- = getDeducedParameterFromExpr(VectorParam->getSizeExpr());
+ = getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr());
if (!NTTP)
return Sema::TDK_Success;
llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false);
ArgSize = VectorArg->getNumElements();
- return DeduceNonTypeTemplateArgument(S, NTTP, ArgSize, S.Context.IntTy,
- false, Info, Deduced);
+ // Note that we use the "array bound" rules here; just like in that
+ // case, we don't have any particular type for the vector size, but
+ // we can provide one if necessary.
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, ArgSize,
+ S.Context.IntTy, true, Info,
+ Deduced);
}
-
- if (const DependentSizedExtVectorType *VectorArg
+
+ if (const DependentSizedExtVectorType *VectorArg
= dyn_cast<DependentSizedExtVectorType>(Arg)) {
// Perform deduction on the element types.
if (Sema::TemplateDeductionResult Result
@@ -1641,20 +1683,21 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
VectorArg->getElementType(),
Info, Deduced, TDF))
return Result;
-
+
// Perform deduction on the vector size, if we can.
NonTypeTemplateParmDecl *NTTP
- = getDeducedParameterFromExpr(VectorParam->getSizeExpr());
+ = getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr());
if (!NTTP)
return Sema::TDK_Success;
-
- return DeduceNonTypeTemplateArgument(S, NTTP, VectorArg->getSizeExpr(),
+
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
+ VectorArg->getSizeExpr(),
Info, Deduced);
}
-
+
return Sema::TDK_NonDeducedMismatch;
}
-
+
case Type::TypeOfExpr:
case Type::TypeOf:
case Type::DependentName:
@@ -1751,18 +1794,24 @@ DeduceTemplateArguments(Sema &S,
case TemplateArgument::Expression: {
if (NonTypeTemplateParmDecl *NTTP
- = getDeducedParameterFromExpr(Param.getAsExpr())) {
+ = getDeducedParameterFromExpr(Info, Param.getAsExpr())) {
if (Arg.getKind() == TemplateArgument::Integral)
- return DeduceNonTypeTemplateArgument(S, NTTP,
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
Arg.getAsIntegral(),
Arg.getIntegralType(),
/*ArrayBound=*/false,
Info, Deduced);
- if (Arg.getKind() == TemplateArgument::Expression)
- return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsExpr(),
+ if (Arg.getKind() == TemplateArgument::NullPtr)
+ return DeduceNullPtrTemplateArgument(S, TemplateParams, NTTP,
+ Arg.getNullPtrType(),
Info, Deduced);
+ if (Arg.getKind() == TemplateArgument::Expression)
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
+ Arg.getAsExpr(), Info, Deduced);
if (Arg.getKind() == TemplateArgument::Declaration)
- return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsDecl(),
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
+ Arg.getAsDecl(),
+ Arg.getParamTypeForDecl(),
Info, Deduced);
Info.FirstArg = Param;
@@ -1788,45 +1837,34 @@ DeduceTemplateArguments(Sema &S,
///
/// \returns true if there is another template argument (which will be at
/// \c Args[ArgIdx]), false otherwise.
-static bool hasTemplateArgumentForDeduction(const TemplateArgument *&Args,
- unsigned &ArgIdx,
- unsigned &NumArgs) {
- if (ArgIdx == NumArgs)
+static bool hasTemplateArgumentForDeduction(ArrayRef<TemplateArgument> &Args,
+ unsigned &ArgIdx) {
+ if (ArgIdx == Args.size())
return false;
const TemplateArgument &Arg = Args[ArgIdx];
if (Arg.getKind() != TemplateArgument::Pack)
return true;
- assert(ArgIdx == NumArgs - 1 && "Pack not at the end of argument list?");
- Args = Arg.pack_begin();
- NumArgs = Arg.pack_size();
+ assert(ArgIdx == Args.size() - 1 && "Pack not at the end of argument list?");
+ Args = Arg.pack_elements();
ArgIdx = 0;
- return ArgIdx < NumArgs;
+ return ArgIdx < Args.size();
}
/// \brief Determine whether the given set of template arguments has a pack
/// expansion that is not the last template argument.
-static bool hasPackExpansionBeforeEnd(const TemplateArgument *Args,
- unsigned NumArgs) {
- unsigned ArgIdx = 0;
- while (ArgIdx < NumArgs) {
- const TemplateArgument &Arg = Args[ArgIdx];
-
- // Unwrap argument packs.
- if (Args[ArgIdx].getKind() == TemplateArgument::Pack) {
- Args = Arg.pack_begin();
- NumArgs = Arg.pack_size();
- ArgIdx = 0;
- continue;
- }
+static bool hasPackExpansionBeforeEnd(ArrayRef<TemplateArgument> Args) {
+ bool FoundPackExpansion = false;
+ for (const auto &A : Args) {
+ if (FoundPackExpansion)
+ return true;
- ++ArgIdx;
- if (ArgIdx == NumArgs)
- return false;
+ if (A.getKind() == TemplateArgument::Pack)
+ return hasPackExpansionBeforeEnd(A.pack_elements());
- if (Arg.isPackExpansion())
- return true;
+ if (A.isPackExpansion())
+ FoundPackExpansion = true;
}
return false;
@@ -1834,8 +1872,8 @@ static bool hasPackExpansionBeforeEnd(const TemplateArgument *Args,
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
- const TemplateArgument *Params, unsigned NumParams,
- const TemplateArgument *Args, unsigned NumArgs,
+ ArrayRef<TemplateArgument> Params,
+ ArrayRef<TemplateArgument> Args,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
bool NumberOfArgumentsMustMatch) {
@@ -1843,7 +1881,7 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
// If the template argument list of P contains a pack expansion that is not
// the last template argument, the entire template argument list is a
// non-deduced context.
- if (hasPackExpansionBeforeEnd(Params, NumParams))
+ if (hasPackExpansionBeforeEnd(Params))
return Sema::TDK_Success;
// C++0x [temp.deduct.type]p9:
@@ -1851,21 +1889,20 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
// respective template argument list P is compared with the corresponding
// argument Ai of the corresponding template argument list of A.
unsigned ArgIdx = 0, ParamIdx = 0;
- for (; hasTemplateArgumentForDeduction(Params, ParamIdx, NumParams);
- ++ParamIdx) {
+ for (; hasTemplateArgumentForDeduction(Params, ParamIdx); ++ParamIdx) {
if (!Params[ParamIdx].isPackExpansion()) {
// The simple case: deduce template arguments by matching Pi and Ai.
// Check whether we have enough arguments.
- if (!hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs))
+ if (!hasTemplateArgumentForDeduction(Args, ArgIdx))
return NumberOfArgumentsMustMatch ? Sema::TDK_TooFewArguments
: Sema::TDK_Success;
- if (Args[ArgIdx].isPackExpansion()) {
- // FIXME: We follow the logic of C++0x [temp.deduct.type]p22 here,
- // but applied to pack expansions that are template arguments.
+ // C++1z [temp.deduct.type]p9:
+ // During partial ordering, if Ai was originally a pack expansion [and]
+ // Pi is not a pack expansion, template argument deduction fails.
+ if (Args[ArgIdx].isPackExpansion())
return Sema::TDK_MiscellaneousDeductionFailure;
- }
// Perform deduction for this Pi/Ai pair.
if (Sema::TemplateDeductionResult Result
@@ -1899,7 +1936,7 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
// expanded by this pack expansion (the outer index) and for each
// template argument (the inner SmallVectors).
bool HasAnyArguments = false;
- for (; hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs); ++ArgIdx) {
+ for (; hasTemplateArgumentForDeduction(Args, ArgIdx); ++ArgIdx) {
HasAnyArguments = true;
// Deduce template arguments from the pattern.
@@ -1927,16 +1964,21 @@ DeduceTemplateArguments(Sema &S,
const TemplateArgumentList &ArgList,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
- return DeduceTemplateArguments(S, TemplateParams,
- ParamList.data(), ParamList.size(),
- ArgList.data(), ArgList.size(),
- Info, Deduced, false);
+ return DeduceTemplateArguments(S, TemplateParams, ParamList.asArray(),
+ ArgList.asArray(), Info, Deduced,
+ /*NumberOfArgumentsMustMatch*/false);
}
/// \brief Determine whether two template arguments are the same.
static bool isSameTemplateArg(ASTContext &Context,
- const TemplateArgument &X,
- const TemplateArgument &Y) {
+ TemplateArgument X,
+ const TemplateArgument &Y,
+ bool PackExpansionMatchesPack = false) {
+ // If we're checking deduced arguments (X) against original arguments (Y),
+ // we will have flattened packs to non-expansions in X.
+ if (PackExpansionMatchesPack && X.isPackExpansion() && !Y.isPackExpansion())
+ X = X.getPackExpansionPattern();
+
if (X.getKind() != Y.getKind())
return false;
@@ -1962,7 +2004,7 @@ static bool isSameTemplateArg(ASTContext &Context,
Y.getAsTemplateOrTemplatePattern()).getAsVoidPointer();
case TemplateArgument::Integral:
- return X.getAsIntegral() == Y.getAsIntegral();
+ return hasSameExtendedValue(X.getAsIntegral(), Y.getAsIntegral());
case TemplateArgument::Expression: {
llvm::FoldingSetNodeID XID, YID;
@@ -1979,7 +2021,7 @@ static bool isSameTemplateArg(ASTContext &Context,
XPEnd = X.pack_end(),
YP = Y.pack_begin();
XP != XPEnd; ++XP, ++YP)
- if (!isSameTemplateArg(Context, *XP, *YP))
+ if (!isSameTemplateArg(Context, *XP, *YP, PackExpansionMatchesPack))
return false;
return true;
@@ -1991,48 +2033,47 @@ static bool isSameTemplateArg(ASTContext &Context,
/// \brief Allocate a TemplateArgumentLoc where all locations have
/// been initialized to the given location.
///
-/// \param S The semantic analysis object.
-///
/// \param Arg The template argument we are producing template argument
/// location information for.
///
/// \param NTTPType For a declaration template argument, the type of
/// the non-type template parameter that corresponds to this template
-/// argument.
+/// argument. Can be null if no type sugar is available to add to the
+/// type from the template argument.
///
/// \param Loc The source location to use for the resulting template
/// argument.
-static TemplateArgumentLoc
-getTrivialTemplateArgumentLoc(Sema &S,
- const TemplateArgument &Arg,
- QualType NTTPType,
- SourceLocation Loc) {
+TemplateArgumentLoc
+Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
+ QualType NTTPType, SourceLocation Loc) {
switch (Arg.getKind()) {
case TemplateArgument::Null:
llvm_unreachable("Can't get a NULL template argument here");
case TemplateArgument::Type:
- return TemplateArgumentLoc(Arg,
- S.Context.getTrivialTypeSourceInfo(Arg.getAsType(), Loc));
+ return TemplateArgumentLoc(
+ Arg, Context.getTrivialTypeSourceInfo(Arg.getAsType(), Loc));
case TemplateArgument::Declaration: {
- Expr *E
- = S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
- .getAs<Expr>();
+ if (NTTPType.isNull())
+ NTTPType = Arg.getParamTypeForDecl();
+ Expr *E = BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
+ .getAs<Expr>();
return TemplateArgumentLoc(TemplateArgument(E), E);
}
case TemplateArgument::NullPtr: {
- Expr *E
- = S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
- .getAs<Expr>();
+ if (NTTPType.isNull())
+ NTTPType = Arg.getNullPtrType();
+ Expr *E = BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
+ .getAs<Expr>();
return TemplateArgumentLoc(TemplateArgument(NTTPType, /*isNullPtr*/true),
E);
}
case TemplateArgument::Integral: {
- Expr *E
- = S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).getAs<Expr>();
+ Expr *E =
+ BuildExpressionFromIntegralTemplateArgument(Arg, Loc).getAs<Expr>();
return TemplateArgumentLoc(TemplateArgument(E), E);
}
@@ -2041,18 +2082,16 @@ getTrivialTemplateArgumentLoc(Sema &S,
NestedNameSpecifierLocBuilder Builder;
TemplateName Template = Arg.getAsTemplate();
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
- Builder.MakeTrivial(S.Context, DTN->getQualifier(), Loc);
+ Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
else if (QualifiedTemplateName *QTN =
Template.getAsQualifiedTemplateName())
- Builder.MakeTrivial(S.Context, QTN->getQualifier(), Loc);
-
+ Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
+
if (Arg.getKind() == TemplateArgument::Template)
- return TemplateArgumentLoc(Arg,
- Builder.getWithLocInContext(S.Context),
+ return TemplateArgumentLoc(Arg, Builder.getWithLocInContext(Context),
Loc);
-
-
- return TemplateArgumentLoc(Arg, Builder.getWithLocInContext(S.Context),
+
+ return TemplateArgumentLoc(Arg, Builder.getWithLocInContext(Context),
Loc, Loc);
}
@@ -2074,39 +2113,21 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
DeducedTemplateArgument Arg,
NamedDecl *Template,
TemplateDeductionInfo &Info,
- bool InFunctionTemplate,
+ bool IsDeduced,
SmallVectorImpl<TemplateArgument> &Output) {
- // First, for a non-type template parameter type that is
- // initialized by a declaration, we need the type of the
- // corresponding non-type template parameter.
- QualType NTTPType;
- if (NonTypeTemplateParmDecl *NTTP =
- dyn_cast<NonTypeTemplateParmDecl>(Param)) {
- NTTPType = NTTP->getType();
- if (NTTPType->isDependentType()) {
- TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Output);
- NTTPType = S.SubstType(NTTPType,
- MultiLevelTemplateArgumentList(TemplateArgs),
- NTTP->getLocation(),
- NTTP->getDeclName());
- if (NTTPType.isNull())
- return true;
- }
- }
-
auto ConvertArg = [&](DeducedTemplateArgument Arg,
unsigned ArgumentPackIndex) {
// Convert the deduced template argument into a template
// argument that we can check, almost as if the user had written
// the template argument explicitly.
TemplateArgumentLoc ArgLoc =
- getTrivialTemplateArgumentLoc(S, Arg, NTTPType, Info.getLocation());
+ S.getTrivialTemplateArgumentLoc(Arg, QualType(), Info.getLocation());
// Check the template argument, converting it as necessary.
return S.CheckTemplateArgument(
Param, ArgLoc, Template, Template->getLocation(),
Template->getSourceRange().getEnd(), ArgumentPackIndex, Output,
- InFunctionTemplate
+ IsDeduced
? (Arg.wasDeducedFromArrayBound() ? Sema::CTAK_DeducedFromArrayBound
: Sema::CTAK_Deduced)
: Sema::CTAK_Specified);
@@ -2132,22 +2153,28 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
}
// If the pack is empty, we still need to substitute into the parameter
- // itself, in case that substitution fails. For non-type parameters, we did
- // this above. For type parameters, no substitution is ever required.
- auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Param);
- if (TTP && PackedArgsBuilder.empty()) {
- // Set up a template instantiation context.
+ // itself, in case that substitution fails.
+ if (PackedArgsBuilder.empty()) {
LocalInstantiationScope Scope(S);
- Sema::InstantiatingTemplate Inst(S, Template->getLocation(), Template,
- TTP, Output,
- Template->getSourceRange());
- if (Inst.isInvalid())
- return true;
-
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Output);
- if (!S.SubstDecl(TTP, S.CurContext,
- MultiLevelTemplateArgumentList(TemplateArgs)))
- return true;
+ MultiLevelTemplateArgumentList Args(TemplateArgs);
+
+ if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+ Sema::InstantiatingTemplate Inst(S, Template->getLocation(), Template,
+ NTTP, Output,
+ Template->getSourceRange());
+ if (Inst.isInvalid() ||
+ S.SubstType(NTTP->getType(), Args, NTTP->getLocation(),
+ NTTP->getDeclName()).isNull())
+ return true;
+ } else if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Param)) {
+ Sema::InstantiatingTemplate Inst(S, Template->getLocation(), Template,
+ TTP, Output,
+ Template->getSourceRange());
+ if (Inst.isInvalid() || !S.SubstDecl(TTP, S.CurContext, Args))
+ return true;
+ }
+ // For type parameters, no substitution is ever required.
}
// Create the resulting argument pack.
@@ -2159,44 +2186,169 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
return ConvertArg(Arg, 0);
}
-/// Complete template argument deduction for a class template partial
-/// specialization.
-static Sema::TemplateDeductionResult
-FinishTemplateArgumentDeduction(Sema &S,
- ClassTemplatePartialSpecializationDecl *Partial,
- const TemplateArgumentList &TemplateArgs,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- TemplateDeductionInfo &Info) {
- // Unevaluated SFINAE context.
- EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
- Sema::SFINAETrap Trap(S);
+// FIXME: This should not be a template, but
+// ClassTemplatePartialSpecializationDecl sadly does not derive from
+// TemplateDecl.
+template<typename TemplateDeclT>
+static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments(
+ Sema &S, TemplateDeclT *Template, bool IsDeduced,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ TemplateDeductionInfo &Info, SmallVectorImpl<TemplateArgument> &Builder,
+ LocalInstantiationScope *CurrentInstantiationScope = nullptr,
+ unsigned NumAlreadyConverted = 0, bool PartialOverloading = false) {
+ TemplateParameterList *TemplateParams = Template->getTemplateParameters();
- Sema::ContextRAII SavedContext(S, Partial);
+ for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
+ NamedDecl *Param = TemplateParams->getParam(I);
- // C++ [temp.deduct.type]p2:
- // [...] or if any template argument remains neither deduced nor
- // explicitly specified, template argument deduction fails.
- SmallVector<TemplateArgument, 4> Builder;
- TemplateParameterList *PartialParams = Partial->getTemplateParameters();
- for (unsigned I = 0, N = PartialParams->size(); I != N; ++I) {
- NamedDecl *Param = PartialParams->getParam(I);
- if (Deduced[I].isNull()) {
- Info.Param = makeTemplateParameter(Param);
+ if (!Deduced[I].isNull()) {
+ if (I < NumAlreadyConverted) {
+ // We have already fully type-checked and converted this
+ // argument, because it was explicitly-specified. Just record the
+ // presence of this argument.
+ Builder.push_back(Deduced[I]);
+ // We may have had explicitly-specified template arguments for a
+ // template parameter pack (that may or may not have been extended
+ // via additional deduced arguments).
+ if (Param->isParameterPack() && CurrentInstantiationScope) {
+ if (CurrentInstantiationScope->getPartiallySubstitutedPack() ==
+ Param) {
+ // Forget the partially-substituted pack; its substitution is now
+ // complete.
+ CurrentInstantiationScope->ResetPartiallySubstitutedPack();
+ }
+ }
+ continue;
+ }
+
+ // We have deduced this argument, so it still needs to be
+ // checked and converted.
+ if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], Template, Info,
+ IsDeduced, Builder)) {
+ Info.Param = makeTemplateParameter(Param);
+ // FIXME: These template arguments are temporary. Free them!
+ Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
+ return Sema::TDK_SubstitutionFailure;
+ }
+
+ continue;
+ }
+
+ // C++0x [temp.arg.explicit]p3:
+ // A trailing template parameter pack (14.5.3) not otherwise deduced will
+ // be deduced to an empty sequence of template arguments.
+ // FIXME: Where did the word "trailing" come from?
+ if (Param->isTemplateParameterPack()) {
+ // We may have had explicitly-specified template arguments for this
+ // template parameter pack. If so, our empty deduction extends the
+ // explicitly-specified set (C++0x [temp.arg.explicit]p9).
+ const TemplateArgument *ExplicitArgs;
+ unsigned NumExplicitArgs;
+ if (CurrentInstantiationScope &&
+ CurrentInstantiationScope->getPartiallySubstitutedPack(
+ &ExplicitArgs, &NumExplicitArgs) == Param) {
+ Builder.push_back(TemplateArgument(
+ llvm::makeArrayRef(ExplicitArgs, NumExplicitArgs)));
+
+ // Forget the partially-substituted pack; its substitution is now
+ // complete.
+ CurrentInstantiationScope->ResetPartiallySubstitutedPack();
+ } else {
+ // Go through the motions of checking the empty argument pack against
+ // the parameter pack.
+ DeducedTemplateArgument DeducedPack(TemplateArgument::getEmptyPack());
+ if (ConvertDeducedTemplateArgument(S, Param, DeducedPack, Template,
+ Info, IsDeduced, Builder)) {
+ Info.Param = makeTemplateParameter(Param);
+ // FIXME: These template arguments are temporary. Free them!
+ Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
+ return Sema::TDK_SubstitutionFailure;
+ }
+ }
+ continue;
+ }
+
+ // Substitute into the default template argument, if available.
+ bool HasDefaultArg = false;
+ TemplateDecl *TD = dyn_cast<TemplateDecl>(Template);
+ if (!TD) {
+ assert(isa<ClassTemplatePartialSpecializationDecl>(Template));
return Sema::TDK_Incomplete;
}
- // We have deduced this argument, so it still needs to be
- // checked and converted.
- if (ConvertDeducedTemplateArgument(S, Param, Deduced[I],
- Partial, Info, false,
- Builder)) {
- Info.Param = makeTemplateParameter(Param);
+ TemplateArgumentLoc DefArg = S.SubstDefaultTemplateArgumentIfAvailable(
+ TD, TD->getLocation(), TD->getSourceRange().getEnd(), Param, Builder,
+ HasDefaultArg);
+
+ // If there was no default argument, deduction is incomplete.
+ if (DefArg.getArgument().isNull()) {
+ Info.Param = makeTemplateParameter(
+ const_cast<NamedDecl *>(TemplateParams->getParam(I)));
+ Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
+ if (PartialOverloading) break;
+
+ return HasDefaultArg ? Sema::TDK_SubstitutionFailure
+ : Sema::TDK_Incomplete;
+ }
+
+ // Check whether we can actually use the default argument.
+ if (S.CheckTemplateArgument(Param, DefArg, TD, TD->getLocation(),
+ TD->getSourceRange().getEnd(), 0, Builder,
+ Sema::CTAK_Specified)) {
+ Info.Param = makeTemplateParameter(
+ const_cast<NamedDecl *>(TemplateParams->getParam(I)));
// FIXME: These template arguments are temporary. Free them!
Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
return Sema::TDK_SubstitutionFailure;
}
+
+ // If we get here, we successfully used the default template argument.
}
+ return Sema::TDK_Success;
+}
+
+DeclContext *getAsDeclContextOrEnclosing(Decl *D) {
+ if (auto *DC = dyn_cast<DeclContext>(D))
+ return DC;
+ return D->getDeclContext();
+}
+
+template<typename T> struct IsPartialSpecialization {
+ static constexpr bool value = false;
+};
+template<>
+struct IsPartialSpecialization<ClassTemplatePartialSpecializationDecl> {
+ static constexpr bool value = true;
+};
+template<>
+struct IsPartialSpecialization<VarTemplatePartialSpecializationDecl> {
+ static constexpr bool value = true;
+};
+
+/// Complete template argument deduction for a partial specialization.
+template <typename T>
+static typename std::enable_if<IsPartialSpecialization<T>::value,
+ Sema::TemplateDeductionResult>::type
+FinishTemplateArgumentDeduction(
+ Sema &S, T *Partial, bool IsPartialOrdering,
+ const TemplateArgumentList &TemplateArgs,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ TemplateDeductionInfo &Info) {
+ // Unevaluated SFINAE context.
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
+ Sema::SFINAETrap Trap(S);
+
+ Sema::ContextRAII SavedContext(S, getAsDeclContextOrEnclosing(Partial));
+
+ // C++ [temp.deduct.type]p2:
+ // [...] or if any template argument remains neither deduced nor
+ // explicitly specified, template argument deduction fails.
+ SmallVector<TemplateArgument, 4> Builder;
+ if (auto Result = ConvertDeducedTemplateArguments(
+ S, Partial, IsPartialOrdering, Deduced, Info, Builder))
+ return Result;
+
// Form the template argument list from the deduced template arguments.
TemplateArgumentList *DeducedArgumentList
= TemplateArgumentList::CreateCopy(S.Context, Builder);
@@ -2209,11 +2361,11 @@ FinishTemplateArgumentDeduction(Sema &S,
// and are equivalent to the template arguments originally provided
// to the class template.
LocalInstantiationScope InstScope(S);
- ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate();
- const ASTTemplateArgumentListInfo *PartialTemplArgInfo
- = Partial->getTemplateArgsAsWritten();
- const TemplateArgumentLoc *PartialTemplateArgs
- = PartialTemplArgInfo->getTemplateArgs();
+ auto *Template = Partial->getSpecializedTemplate();
+ const ASTTemplateArgumentListInfo *PartialTemplArgInfo =
+ Partial->getTemplateArgsAsWritten();
+ const TemplateArgumentLoc *PartialTemplateArgs =
+ PartialTemplArgInfo->getTemplateArgs();
TemplateArgumentListInfo InstArgs(PartialTemplArgInfo->LAngleLoc,
PartialTemplArgInfo->RAngleLoc);
@@ -2224,21 +2376,19 @@ FinishTemplateArgumentDeduction(Sema &S,
if (ParamIdx >= Partial->getTemplateParameters()->size())
ParamIdx = Partial->getTemplateParameters()->size() - 1;
- Decl *Param
- = const_cast<NamedDecl *>(
- Partial->getTemplateParameters()->getParam(ParamIdx));
+ Decl *Param = const_cast<NamedDecl *>(
+ Partial->getTemplateParameters()->getParam(ParamIdx));
Info.Param = makeTemplateParameter(Param);
Info.FirstArg = PartialTemplateArgs[ArgIdx].getArgument();
return Sema::TDK_SubstitutionFailure;
}
SmallVector<TemplateArgument, 4> ConvertedInstArgs;
- if (S.CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(),
- InstArgs, false, ConvertedInstArgs))
+ if (S.CheckTemplateArgumentList(Template, Partial->getLocation(), InstArgs,
+ false, ConvertedInstArgs))
return Sema::TDK_SubstitutionFailure;
- TemplateParameterList *TemplateParams
- = ClassTemplate->getTemplateParameters();
+ TemplateParameterList *TemplateParams = Template->getTemplateParameters();
for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {
TemplateArgument InstArg = ConvertedInstArgs.data()[I];
if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg)) {
@@ -2255,6 +2405,48 @@ FinishTemplateArgumentDeduction(Sema &S,
return Sema::TDK_Success;
}
+/// Complete template argument deduction for a class or variable template,
+/// when partial ordering against a partial specialization.
+// FIXME: Factor out duplication with partial specialization version above.
+Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
+ Sema &S, TemplateDecl *Template, bool PartialOrdering,
+ const TemplateArgumentList &TemplateArgs,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ TemplateDeductionInfo &Info) {
+ // Unevaluated SFINAE context.
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
+ Sema::SFINAETrap Trap(S);
+
+ Sema::ContextRAII SavedContext(S, getAsDeclContextOrEnclosing(Template));
+
+ // C++ [temp.deduct.type]p2:
+ // [...] or if any template argument remains neither deduced nor
+ // explicitly specified, template argument deduction fails.
+ SmallVector<TemplateArgument, 4> Builder;
+ if (auto Result = ConvertDeducedTemplateArguments(
+ S, Template, /*IsDeduced*/PartialOrdering, Deduced, Info, Builder))
+ return Result;
+
+ // Check that we produced the correct argument list.
+ TemplateParameterList *TemplateParams = Template->getTemplateParameters();
+ for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {
+ TemplateArgument InstArg = Builder[I];
+ if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg,
+ /*PackExpansionMatchesPack*/true)) {
+ Info.Param = makeTemplateParameter(TemplateParams->getParam(I));
+ Info.FirstArg = TemplateArgs[I];
+ Info.SecondArg = InstArg;
+ return Sema::TDK_NonDeducedMismatch;
+ }
+ }
+
+ if (Trap.hasErrorOccurred())
+ return Sema::TDK_SubstitutionFailure;
+
+ return Sema::TDK_Success;
+}
+
+
/// \brief Perform template argument deduction to determine whether
/// the given template arguments match the given class template
/// partial specialization per C++ [temp.class.spec.match].
@@ -2293,112 +2485,13 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
if (Trap.hasErrorOccurred())
return Sema::TDK_SubstitutionFailure;
- return ::FinishTemplateArgumentDeduction(*this, Partial, TemplateArgs,
- Deduced, Info);
-}
-
-/// Complete template argument deduction for a variable template partial
-/// specialization.
-/// TODO: Unify with ClassTemplatePartialSpecializationDecl version?
-/// May require unifying ClassTemplate(Partial)SpecializationDecl and
-/// VarTemplate(Partial)SpecializationDecl with a new data
-/// structure Template(Partial)SpecializationDecl, and
-/// using Template(Partial)SpecializationDecl as input type.
-static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
- Sema &S, VarTemplatePartialSpecializationDecl *Partial,
- const TemplateArgumentList &TemplateArgs,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- TemplateDeductionInfo &Info) {
- // Unevaluated SFINAE context.
- EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
- Sema::SFINAETrap Trap(S);
-
- // C++ [temp.deduct.type]p2:
- // [...] or if any template argument remains neither deduced nor
- // explicitly specified, template argument deduction fails.
- SmallVector<TemplateArgument, 4> Builder;
- TemplateParameterList *PartialParams = Partial->getTemplateParameters();
- for (unsigned I = 0, N = PartialParams->size(); I != N; ++I) {
- NamedDecl *Param = PartialParams->getParam(I);
- if (Deduced[I].isNull()) {
- Info.Param = makeTemplateParameter(Param);
- return Sema::TDK_Incomplete;
- }
-
- // We have deduced this argument, so it still needs to be
- // checked and converted.
- if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], Partial,
- Info, false, Builder)) {
- Info.Param = makeTemplateParameter(Param);
- // FIXME: These template arguments are temporary. Free them!
- Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
- return Sema::TDK_SubstitutionFailure;
- }
- }
-
- // Form the template argument list from the deduced template arguments.
- TemplateArgumentList *DeducedArgumentList = TemplateArgumentList::CreateCopy(
- S.Context, Builder);
-
- Info.reset(DeducedArgumentList);
-
- // Substitute the deduced template arguments into the template
- // arguments of the class template partial specialization, and
- // verify that the instantiated template arguments are both valid
- // and are equivalent to the template arguments originally provided
- // to the class template.
- LocalInstantiationScope InstScope(S);
- VarTemplateDecl *VarTemplate = Partial->getSpecializedTemplate();
- const ASTTemplateArgumentListInfo *PartialTemplArgInfo
- = Partial->getTemplateArgsAsWritten();
- const TemplateArgumentLoc *PartialTemplateArgs
- = PartialTemplArgInfo->getTemplateArgs();
-
- TemplateArgumentListInfo InstArgs(PartialTemplArgInfo->LAngleLoc,
- PartialTemplArgInfo->RAngleLoc);
-
- if (S.Subst(PartialTemplateArgs, PartialTemplArgInfo->NumTemplateArgs,
- InstArgs, MultiLevelTemplateArgumentList(*DeducedArgumentList))) {
- unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx;
- if (ParamIdx >= Partial->getTemplateParameters()->size())
- ParamIdx = Partial->getTemplateParameters()->size() - 1;
-
- Decl *Param = const_cast<NamedDecl *>(
- Partial->getTemplateParameters()->getParam(ParamIdx));
- Info.Param = makeTemplateParameter(Param);
- Info.FirstArg = PartialTemplateArgs[ArgIdx].getArgument();
- return Sema::TDK_SubstitutionFailure;
- }
- SmallVector<TemplateArgument, 4> ConvertedInstArgs;
- if (S.CheckTemplateArgumentList(VarTemplate, Partial->getLocation(), InstArgs,
- false, ConvertedInstArgs))
- return Sema::TDK_SubstitutionFailure;
-
- TemplateParameterList *TemplateParams = VarTemplate->getTemplateParameters();
- for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {
- TemplateArgument InstArg = ConvertedInstArgs.data()[I];
- if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg)) {
- Info.Param = makeTemplateParameter(TemplateParams->getParam(I));
- Info.FirstArg = TemplateArgs[I];
- Info.SecondArg = InstArg;
- return Sema::TDK_NonDeducedMismatch;
- }
- }
-
- if (Trap.hasErrorOccurred())
- return Sema::TDK_SubstitutionFailure;
-
- return Sema::TDK_Success;
+ return ::FinishTemplateArgumentDeduction(
+ *this, Partial, /*PartialOrdering=*/false, TemplateArgs, Deduced, Info);
}
/// \brief Perform template argument deduction to determine whether
/// the given template arguments match the given variable template
/// partial specialization per C++ [temp.class.spec.match].
-/// TODO: Unify with ClassTemplatePartialSpecializationDecl version?
-/// May require unifying ClassTemplate(Partial)SpecializationDecl and
-/// VarTemplate(Partial)SpecializationDecl with a new data
-/// structure Template(Partial)SpecializationDecl, and
-/// using Template(Partial)SpecializationDecl as input type.
Sema::TemplateDeductionResult
Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
const TemplateArgumentList &TemplateArgs,
@@ -2432,8 +2525,8 @@ Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
if (Trap.hasErrorOccurred())
return Sema::TDK_SubstitutionFailure;
- return ::FinishTemplateArgumentDeduction(*this, Partial, TemplateArgs,
- Deduced, Info);
+ return ::FinishTemplateArgumentDeduction(
+ *this, Partial, /*PartialOrdering=*/false, TemplateArgs, Deduced, Info);
}
/// \brief Determine whether the given type T is a simple-template-id type.
@@ -2573,15 +2666,15 @@ Sema::SubstituteExplicitTemplateArguments(
ParamTypes, /*params*/ nullptr, ExtParamInfos))
return TDK_SubstitutionFailure;
}
-
+
// Instantiate the return type.
QualType ResultType;
{
// C++11 [expr.prim.general]p3:
- // If a declaration declares a member function or member function
- // template of a class X, the expression this is a prvalue of type
+ // If a declaration declares a member function or member function
+ // template of a class X, the expression this is a prvalue of type
// "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
- // and the end of the function-definition, member-declarator, or
+ // and the end of the function-definition, member-declarator, or
// declarator.
unsigned ThisTypeQuals = 0;
CXXRecordDecl *ThisContext = nullptr;
@@ -2589,7 +2682,7 @@ Sema::SubstituteExplicitTemplateArguments(
ThisContext = Method->getParent();
ThisTypeQuals = Method->getTypeQualifiers();
}
-
+
CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals,
getLangOpts().CPlusPlus11);
@@ -2645,35 +2738,42 @@ Sema::SubstituteExplicitTemplateArguments(
/// \brief Check whether the deduced argument type for a call to a function
/// template matches the actual argument type per C++ [temp.deduct.call]p4.
-static bool
-CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
+static bool
+CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
QualType DeducedA) {
ASTContext &Context = S.Context;
-
+
QualType A = OriginalArg.OriginalArgType;
QualType OriginalParamType = OriginalArg.OriginalParamType;
-
+
// Check for type equality (top-level cv-qualifiers are ignored).
if (Context.hasSameUnqualifiedType(A, DeducedA))
return false;
-
+
// Strip off references on the argument types; they aren't needed for
// the following checks.
if (const ReferenceType *DeducedARef = DeducedA->getAs<ReferenceType>())
DeducedA = DeducedARef->getPointeeType();
if (const ReferenceType *ARef = A->getAs<ReferenceType>())
A = ARef->getPointeeType();
-
+
// C++ [temp.deduct.call]p4:
// [...] However, there are three cases that allow a difference:
- // - If the original P is a reference type, the deduced A (i.e., the
- // type referred to by the reference) can be more cv-qualified than
+ // - If the original P is a reference type, the deduced A (i.e., the
+ // type referred to by the reference) can be more cv-qualified than
// the transformed A.
if (const ReferenceType *OriginalParamRef
= OriginalParamType->getAs<ReferenceType>()) {
// We don't want to keep the reference around any more.
OriginalParamType = OriginalParamRef->getPointeeType();
-
+
+ // FIXME: Resolve core issue (no number yet): if the original P is a
+ // reference type and the transformed A is function type "noexcept F",
+ // the deduced A can be F.
+ QualType Tmp;
+ if (A->isFunctionType() && S.IsFunctionConversion(A, DeducedA, Tmp))
+ return false;
+
Qualifiers AQuals = A.getQualifiers();
Qualifiers DeducedAQuals = DeducedA.getQualifiers();
@@ -2693,34 +2793,32 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
// Qualifiers match; there's nothing to do.
} else if (!DeducedAQuals.compatiblyIncludes(AQuals)) {
return true;
- } else {
+ } else {
// Qualifiers are compatible, so have the argument type adopt the
// deduced argument type's qualifiers as if we had performed the
// qualification conversion.
A = Context.getQualifiedType(A.getUnqualifiedType(), DeducedAQuals);
}
}
-
- // - The transformed A can be another pointer or pointer to member
- // type that can be converted to the deduced A via a qualification
- // conversion.
+
+ // - The transformed A can be another pointer or pointer to member
+ // type that can be converted to the deduced A via a function pointer
+ // conversion and/or a qualification conversion.
//
- // Also allow conversions which merely strip [[noreturn]] from function types
- // (recursively) as an extension.
- // FIXME: Currently, this doesn't play nicely with qualification conversions.
+ // Also allow conversions which merely strip __attribute__((noreturn)) from
+ // function types (recursively).
bool ObjCLifetimeConversion = false;
QualType ResultTy;
if ((A->isAnyPointerType() || A->isMemberPointerType()) &&
(S.IsQualificationConversion(A, DeducedA, false,
ObjCLifetimeConversion) ||
- S.IsNoReturnConversion(A, DeducedA, ResultTy)))
+ S.IsFunctionConversion(A, DeducedA, ResultTy)))
return false;
-
-
- // - If P is a class and P has the form simple-template-id, then the
+
+ // - If P is a class and P has the form simple-template-id, then the
// transformed A can be a derived class of the deduced A. [...]
- // [...] Likewise, if P is a pointer to a class of the form
- // simple-template-id, the transformed A can be a pointer to a
+ // [...] Likewise, if P is a pointer to a class of the form
+ // simple-template-id, the transformed A can be a pointer to a
// derived class pointed to by the deduced A.
if (const PointerType *OriginalParamPtr
= OriginalParamType->getAs<PointerType>()) {
@@ -2734,14 +2832,14 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
}
}
}
-
+
if (Context.hasSameUnqualifiedType(A, DeducedA))
return false;
-
+
if (A->isRecordType() && isSimpleTemplateIdType(OriginalParamType) &&
S.IsDerivedFrom(SourceLocation(), A, DeducedA))
return false;
-
+
return true;
}
@@ -2759,9 +2857,6 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
TemplateDeductionInfo &Info,
SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs,
bool PartialOverloading) {
- TemplateParameterList *TemplateParams
- = FunctionTemplate->getTemplateParameters();
-
// Unevaluated SFINAE context.
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
SFINAETrap Trap(*this);
@@ -2782,114 +2877,11 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
// [...] or if any template argument remains neither deduced nor
// explicitly specified, template argument deduction fails.
SmallVector<TemplateArgument, 4> Builder;
- for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
- NamedDecl *Param = TemplateParams->getParam(I);
-
- if (!Deduced[I].isNull()) {
- if (I < NumExplicitlySpecified) {
- // We have already fully type-checked and converted this
- // argument, because it was explicitly-specified. Just record the
- // presence of this argument.
- Builder.push_back(Deduced[I]);
- // We may have had explicitly-specified template arguments for a
- // template parameter pack (that may or may not have been extended
- // via additional deduced arguments).
- if (Param->isParameterPack() && CurrentInstantiationScope) {
- if (CurrentInstantiationScope->getPartiallySubstitutedPack() ==
- Param) {
- // Forget the partially-substituted pack; its substitution is now
- // complete.
- CurrentInstantiationScope->ResetPartiallySubstitutedPack();
- }
- }
- continue;
- }
-
- // We have deduced this argument, so it still needs to be
- // checked and converted.
- if (ConvertDeducedTemplateArgument(*this, Param, Deduced[I],
- FunctionTemplate, Info,
- true, Builder)) {
- Info.Param = makeTemplateParameter(Param);
- // FIXME: These template arguments are temporary. Free them!
- Info.reset(TemplateArgumentList::CreateCopy(Context, Builder));
- return TDK_SubstitutionFailure;
- }
-
- continue;
- }
-
- // C++0x [temp.arg.explicit]p3:
- // A trailing template parameter pack (14.5.3) not otherwise deduced will
- // be deduced to an empty sequence of template arguments.
- // FIXME: Where did the word "trailing" come from?
- if (Param->isTemplateParameterPack()) {
- // We may have had explicitly-specified template arguments for this
- // template parameter pack. If so, our empty deduction extends the
- // explicitly-specified set (C++0x [temp.arg.explicit]p9).
- const TemplateArgument *ExplicitArgs;
- unsigned NumExplicitArgs;
- if (CurrentInstantiationScope &&
- CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs,
- &NumExplicitArgs)
- == Param) {
- Builder.push_back(TemplateArgument(
- llvm::makeArrayRef(ExplicitArgs, NumExplicitArgs)));
-
- // Forget the partially-substituted pack; its substitution is now
- // complete.
- CurrentInstantiationScope->ResetPartiallySubstitutedPack();
- } else {
- // Go through the motions of checking the empty argument pack against
- // the parameter pack.
- DeducedTemplateArgument DeducedPack(TemplateArgument::getEmptyPack());
- if (ConvertDeducedTemplateArgument(*this, Param, DeducedPack,
- FunctionTemplate, Info, true,
- Builder)) {
- Info.Param = makeTemplateParameter(Param);
- // FIXME: These template arguments are temporary. Free them!
- Info.reset(TemplateArgumentList::CreateCopy(Context, Builder));
- return TDK_SubstitutionFailure;
- }
- }
- continue;
- }
-
- // Substitute into the default template argument, if available.
- bool HasDefaultArg = false;
- TemplateArgumentLoc DefArg
- = SubstDefaultTemplateArgumentIfAvailable(FunctionTemplate,
- FunctionTemplate->getLocation(),
- FunctionTemplate->getSourceRange().getEnd(),
- Param,
- Builder, HasDefaultArg);
-
- // If there was no default argument, deduction is incomplete.
- if (DefArg.getArgument().isNull()) {
- Info.Param = makeTemplateParameter(
- const_cast<NamedDecl *>(TemplateParams->getParam(I)));
- Info.reset(TemplateArgumentList::CreateCopy(Context, Builder));
- if (PartialOverloading) break;
-
- return HasDefaultArg ? TDK_SubstitutionFailure : TDK_Incomplete;
- }
-
- // Check whether we can actually use the default argument.
- if (CheckTemplateArgument(Param, DefArg,
- FunctionTemplate,
- FunctionTemplate->getLocation(),
- FunctionTemplate->getSourceRange().getEnd(),
- 0, Builder,
- CTAK_Specified)) {
- Info.Param = makeTemplateParameter(
- const_cast<NamedDecl *>(TemplateParams->getParam(I)));
- // FIXME: These template arguments are temporary. Free them!
- Info.reset(TemplateArgumentList::CreateCopy(Context, Builder));
- return TDK_SubstitutionFailure;
- }
-
- // If we get here, we successfully used the default template argument.
- }
+ if (auto Result = ConvertDeducedTemplateArguments(
+ *this, FunctionTemplate, /*IsDeduced*/true, Deduced, Info, Builder,
+ CurrentInstantiationScope, NumExplicitlySpecified,
+ PartialOverloading))
+ return Result;
// Form the template argument list from the deduced template arguments.
TemplateArgumentList *DeducedArgumentList
@@ -2927,15 +2919,15 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
if (OriginalCallArgs) {
// C++ [temp.deduct.call]p4:
// In general, the deduction process attempts to find template argument
- // values that will make the deduced A identical to A (after the type A
+ // values that will make the deduced A identical to A (after the type A
// is transformed as described above). [...]
for (unsigned I = 0, N = OriginalCallArgs->size(); I != N; ++I) {
OriginalCallArg OriginalArg = (*OriginalCallArgs)[I];
unsigned ParamIdx = OriginalArg.ArgIdx;
-
+
if (ParamIdx >= Specialization->getNumParams())
continue;
-
+
QualType DeducedA = Specialization->getParamDecl(ParamIdx)->getType();
if (CheckOriginalCallArgDeduction(*this, OriginalArg, DeducedA)) {
Info.FirstArg = TemplateArgument(DeducedA);
@@ -2945,7 +2937,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
}
}
}
-
+
// If we suppressed any diagnostics while performing template argument
// deduction, and if we haven't already instantiated this declaration,
// keep track of these diagnostics. They'll be emitted if this specialization
@@ -3025,7 +3017,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
return QualType();
}
-
+
// Gather the explicit template arguments, if any.
TemplateArgumentListInfo ExplicitTemplateArgs;
if (Ovl->hasExplicitTemplateArgs())
@@ -3041,14 +3033,14 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
// non-deduced context.
if (!Ovl->hasExplicitTemplateArgs())
return QualType();
-
- // Otherwise, see if we can resolve a function type
+
+ // Otherwise, see if we can resolve a function type
FunctionDecl *Specialization = nullptr;
TemplateDeductionInfo Info(Ovl->getNameLoc());
if (S.DeduceTemplateArguments(FunTmpl, &ExplicitTemplateArgs,
Specialization, Info))
continue;
-
+
D = Specialization;
}
@@ -3250,16 +3242,13 @@ DeduceFromInitializerList(Sema &S, TemplateParameterList *TemplateParams,
S.Context.getAsDependentSizedArrayType(AdjustedParamType);
// Determine the array bound is something we can deduce.
if (NonTypeTemplateParmDecl *NTTP =
- getDeducedParameterFromExpr(ArrTy->getSizeExpr())) {
+ getDeducedParameterFromExpr(Info, ArrTy->getSizeExpr())) {
// We can perform template argument deduction for the given non-type
// template parameter.
- assert(NTTP->getDepth() == 0 &&
- "Cannot deduce non-type template argument at depth > 0");
llvm::APInt Size(S.Context.getIntWidth(NTTP->getType()),
ILE->getNumInits());
-
Result = DeduceNonTypeTemplateArgument(
- S, NTTP, llvm::APSInt(Size), NTTP->getType(),
+ S, TemplateParams, NTTP, llvm::APSInt(Size), NTTP->getType(),
/*ArrayBound=*/true, Info, Deduced);
}
}
@@ -3291,7 +3280,7 @@ DeduceTemplateArgumentByListElement(Sema &S,
// For all other cases, just match by type.
QualType ArgType = Arg->getType();
- if (AdjustFunctionParmAndArgTypesForDeduction(S, TemplateParams, ParamType,
+ if (AdjustFunctionParmAndArgTypesForDeduction(S, TemplateParams, ParamType,
ArgType, Arg, TDF)) {
Info.Expression = Arg;
return Sema::TDK_FailedOverloadResolution;
@@ -3382,7 +3371,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
ParamIdx != NumParamTypes; ++ParamIdx) {
QualType OrigParamType = ParamTypes[ParamIdx];
QualType ParamType = OrigParamType;
-
+
const PackExpansionType *ParamExpansion
= dyn_cast<PackExpansionType>(ParamType);
if (!ParamExpansion) {
@@ -3392,7 +3381,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
Expr *Arg = Args[ArgIdx++];
QualType ArgType = Arg->getType();
-
+
unsigned TDF = 0;
if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams,
ParamType, ArgType, Arg,
@@ -3419,7 +3408,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
// 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-1,
+ OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx-1,
ArgType));
if (TemplateDeductionResult Result
@@ -3482,7 +3471,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
// Keep track of the argument type and corresponding argument index,
// so we can check for compatibility between the deduced A and A.
if (hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType))
- OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx,
+ OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx,
ArgType));
if (TemplateDeductionResult Result
@@ -3511,25 +3500,42 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
}
QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
- QualType FunctionType) {
+ QualType FunctionType,
+ bool AdjustExceptionSpec) {
if (ArgFunctionType.isNull())
return ArgFunctionType;
const FunctionProtoType *FunctionTypeP =
FunctionType->castAs<FunctionProtoType>();
- CallingConv CC = FunctionTypeP->getCallConv();
- bool NoReturn = FunctionTypeP->getNoReturnAttr();
const FunctionProtoType *ArgFunctionTypeP =
ArgFunctionType->getAs<FunctionProtoType>();
- if (ArgFunctionTypeP->getCallConv() == CC &&
- ArgFunctionTypeP->getNoReturnAttr() == NoReturn)
+
+ FunctionProtoType::ExtProtoInfo EPI = ArgFunctionTypeP->getExtProtoInfo();
+ bool Rebuild = false;
+
+ CallingConv CC = FunctionTypeP->getCallConv();
+ if (EPI.ExtInfo.getCC() != CC) {
+ EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC);
+ Rebuild = true;
+ }
+
+ bool NoReturn = FunctionTypeP->getNoReturnAttr();
+ if (EPI.ExtInfo.getNoReturn() != NoReturn) {
+ EPI.ExtInfo = EPI.ExtInfo.withNoReturn(NoReturn);
+ Rebuild = true;
+ }
+
+ if (AdjustExceptionSpec && (FunctionTypeP->hasExceptionSpec() ||
+ ArgFunctionTypeP->hasExceptionSpec())) {
+ EPI.ExceptionSpec = FunctionTypeP->getExtProtoInfo().ExceptionSpec;
+ Rebuild = true;
+ }
+
+ if (!Rebuild)
return ArgFunctionType;
- FunctionType::ExtInfo EI = ArgFunctionTypeP->getExtInfo().withCallingConv(CC);
- EI = EI.withNoReturn(NoReturn);
- ArgFunctionTypeP =
- cast<FunctionProtoType>(Context.adjustFunctionType(ArgFunctionTypeP, EI));
- return QualType(ArgFunctionTypeP, 0);
+ return Context.getFunctionType(ArgFunctionTypeP->getReturnType(),
+ ArgFunctionTypeP->getParamTypes(), EPI);
}
/// \brief Deduce template arguments when taking the address of a function
@@ -3554,14 +3560,17 @@ QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
/// \param Info the argument will be updated to provide additional information
/// about template argument deduction.
///
+/// \param IsAddressOfFunction If \c true, we are deducing as part of taking
+/// the address of a function template per [temp.deduct.funcaddr] and
+/// [over.over]. If \c false, we are looking up a function template
+/// specialization based on its signature, per [temp.deduct.decl].
+///
/// \returns the result of template argument deduction.
-Sema::TemplateDeductionResult
-Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
- TemplateArgumentListInfo *ExplicitTemplateArgs,
- QualType ArgFunctionType,
- FunctionDecl *&Specialization,
- TemplateDeductionInfo &Info,
- bool InOverloadResolution) {
+Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
+ FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ArgFunctionType,
+ FunctionDecl *&Specialization, TemplateDeductionInfo &Info,
+ bool IsAddressOfFunction) {
if (FunctionTemplate->isInvalidDecl())
return TDK_Invalid;
@@ -3569,8 +3578,13 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
QualType FunctionType = Function->getType();
- if (!InOverloadResolution)
- ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, FunctionType);
+
+ // When taking the address of a function, we require convertibility of
+ // the resulting function type. Otherwise, we allow arbitrary mismatches
+ // of calling convention, noreturn, and noexcept.
+ if (!IsAddressOfFunction)
+ ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, FunctionType,
+ /*AdjustExceptionSpec*/true);
// Substitute any explicit template arguments.
LocalInstantiationScope InstScope(*this);
@@ -3595,9 +3609,11 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
Deduced.resize(TemplateParams->size());
// If the function has a deduced return type, substitute it for a dependent
- // type so that we treat it as a non-deduced context in what follows.
+ // type so that we treat it as a non-deduced context in what follows. If we
+ // are looking up by signature, the signature type should also have a deduced
+ // return type, which we instead expect to exactly match.
bool HasDeducedReturnType = false;
- if (getLangOpts().CPlusPlus14 && InOverloadResolution &&
+ if (getLangOpts().CPlusPlus14 && IsAddressOfFunction &&
Function->getReturnType()->getContainedAutoType()) {
FunctionType = SubstAutoType(FunctionType, Context.DependentTy);
HasDeducedReturnType = true;
@@ -3605,7 +3621,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
if (!ArgFunctionType.isNull()) {
unsigned TDF = TDF_TopLevelParameterTypeList;
- if (InOverloadResolution) TDF |= TDF_InOverloadResolution;
+ if (IsAddressOfFunction)
+ TDF |= TDF_InOverloadResolution;
// Deduce template arguments from the function type.
if (TemplateDeductionResult Result
= DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
@@ -3627,86 +3644,106 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
DeduceReturnType(Specialization, Info.getLocation(), false))
return TDK_MiscellaneousDeductionFailure;
+ // If the function has a dependent exception specification, resolve it now,
+ // so we can check that the exception specification matches.
+ auto *SpecializationFPT =
+ Specialization->getType()->castAs<FunctionProtoType>();
+ if (getLangOpts().CPlusPlus1z &&
+ isUnresolvedExceptionSpec(SpecializationFPT->getExceptionSpecType()) &&
+ !ResolveExceptionSpec(Info.getLocation(), SpecializationFPT))
+ return TDK_MiscellaneousDeductionFailure;
+
+ // Adjust the exception specification of the argument again to match the
+ // substituted and resolved type we just formed. (Calling convention and
+ // noreturn can't be dependent, so we don't actually need this for them
+ // right now.)
+ QualType SpecializationType = Specialization->getType();
+ if (!IsAddressOfFunction)
+ ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, SpecializationType,
+ /*AdjustExceptionSpec*/true);
+
// If the requested function type does not match the actual type of the
// specialization with respect to arguments of compatible pointer to function
// types, template argument deduction fails.
if (!ArgFunctionType.isNull()) {
- if (InOverloadResolution && !isSameOrCompatibleFunctionType(
- Context.getCanonicalType(Specialization->getType()),
- Context.getCanonicalType(ArgFunctionType)))
+ if (IsAddressOfFunction &&
+ !isSameOrCompatibleFunctionType(
+ Context.getCanonicalType(SpecializationType),
+ Context.getCanonicalType(ArgFunctionType)))
return TDK_MiscellaneousDeductionFailure;
- else if(!InOverloadResolution &&
- !Context.hasSameType(Specialization->getType(), ArgFunctionType))
+
+ if (!IsAddressOfFunction &&
+ !Context.hasSameType(SpecializationType, ArgFunctionType))
return TDK_MiscellaneousDeductionFailure;
}
return TDK_Success;
}
-/// \brief Given a function declaration (e.g. a generic lambda conversion
-/// function) that contains an 'auto' in its result type, substitute it
+/// \brief Given a function declaration (e.g. a generic lambda conversion
+/// function) that contains an 'auto' in its result type, substitute it
/// with TypeToReplaceAutoWith. Be careful to pass in the type you want
/// to replace 'auto' with and not the actual result type you want
/// to set the function to.
-static inline void
-SubstAutoWithinFunctionReturnType(FunctionDecl *F,
+static inline void
+SubstAutoWithinFunctionReturnType(FunctionDecl *F,
QualType TypeToReplaceAutoWith, Sema &S) {
assert(!TypeToReplaceAutoWith->getContainedAutoType());
QualType AutoResultType = F->getReturnType();
- assert(AutoResultType->getContainedAutoType());
- QualType DeducedResultType = S.SubstAutoType(AutoResultType,
+ assert(AutoResultType->getContainedAutoType());
+ QualType DeducedResultType = S.SubstAutoType(AutoResultType,
TypeToReplaceAutoWith);
S.Context.adjustDeducedFunctionResultType(F, DeducedResultType);
}
-/// \brief Given a specialized conversion operator of a generic lambda
-/// create the corresponding specializations of the call operator and
-/// the static-invoker. If the return type of the call operator is auto,
-/// deduce its return type and check if that matches the
+/// \brief Given a specialized conversion operator of a generic lambda
+/// create the corresponding specializations of the call operator and
+/// the static-invoker. If the return type of the call operator is auto,
+/// deduce its return type and check if that matches the
/// return type of the destination function ptr.
-static inline Sema::TemplateDeductionResult
+static inline Sema::TemplateDeductionResult
SpecializeCorrespondingLambdaCallOperatorAndInvoker(
CXXConversionDecl *ConversionSpecialized,
SmallVectorImpl<DeducedTemplateArgument> &DeducedArguments,
QualType ReturnTypeOfDestFunctionPtr,
TemplateDeductionInfo &TDInfo,
Sema &S) {
-
+
CXXRecordDecl *LambdaClass = ConversionSpecialized->getParent();
- assert(LambdaClass && LambdaClass->isGenericLambda());
-
+ assert(LambdaClass && LambdaClass->isGenericLambda());
+
CXXMethodDecl *CallOpGeneric = LambdaClass->getLambdaCallOperator();
QualType CallOpResultType = CallOpGeneric->getReturnType();
- const bool GenericLambdaCallOperatorHasDeducedReturnType =
+ const bool GenericLambdaCallOperatorHasDeducedReturnType =
CallOpResultType->getContainedAutoType();
-
- FunctionTemplateDecl *CallOpTemplate =
+
+ FunctionTemplateDecl *CallOpTemplate =
CallOpGeneric->getDescribedFunctionTemplate();
FunctionDecl *CallOpSpecialized = nullptr;
- // Use the deduced arguments of the conversion function, to specialize our
+ // Use the deduced arguments of the conversion function, to specialize our
// generic lambda's call operator.
if (Sema::TemplateDeductionResult Result
- = S.FinishTemplateArgumentDeduction(CallOpTemplate,
- DeducedArguments,
+ = S.FinishTemplateArgumentDeduction(CallOpTemplate,
+ DeducedArguments,
0, CallOpSpecialized, TDInfo))
return Result;
-
+
// If we need to deduce the return type, do so (instantiates the callop).
if (GenericLambdaCallOperatorHasDeducedReturnType &&
CallOpSpecialized->getReturnType()->isUndeducedType())
- S.DeduceReturnType(CallOpSpecialized,
+ S.DeduceReturnType(CallOpSpecialized,
CallOpSpecialized->getPointOfInstantiation(),
/*Diagnose*/ true);
-
+
// Check to see if the return type of the destination ptr-to-function
// matches the return type of the call operator.
if (!S.Context.hasSameType(CallOpSpecialized->getReturnType(),
ReturnTypeOfDestFunctionPtr))
return Sema::TDK_NonDeducedMismatch;
// Since we have succeeded in matching the source and destination
- // ptr-to-functions (now including return type), and have successfully
+ // ptr-to-functions (now including return type), and have successfully
// specialized our corresponding call operator, we are ready to
// specialize the static invoker with the deduced arguments of our
// ptr-to-function.
@@ -3717,16 +3754,16 @@ SpecializeCorrespondingLambdaCallOperatorAndInvoker(
#ifndef NDEBUG
Sema::TemplateDeductionResult LLVM_ATTRIBUTE_UNUSED Result =
#endif
- S.FinishTemplateArgumentDeduction(InvokerTemplate, DeducedArguments, 0,
+ S.FinishTemplateArgumentDeduction(InvokerTemplate, DeducedArguments, 0,
InvokerSpecialized, TDInfo);
- assert(Result == Sema::TDK_Success &&
+ assert(Result == Sema::TDK_Success &&
"If the call operator succeeded so should the invoker!");
// Set the result type to match the corresponding call operator
// specialization's result type.
if (GenericLambdaCallOperatorHasDeducedReturnType &&
InvokerSpecialized->getReturnType()->isUndeducedType()) {
// Be sure to get the type to replace 'auto' with and not
- // the full result type of the call op specialization
+ // the full result type of the call op specialization
// to substitute into the 'auto' of the invoker and conversion
// function.
// For e.g.
@@ -3738,14 +3775,14 @@ SpecializeCorrespondingLambdaCallOperatorAndInvoker(
->getDeducedType();
SubstAutoWithinFunctionReturnType(InvokerSpecialized,
TypeToReplaceAutoWith, S);
- SubstAutoWithinFunctionReturnType(ConversionSpecialized,
+ SubstAutoWithinFunctionReturnType(ConversionSpecialized,
TypeToReplaceAutoWith, S);
}
-
+
// Ensure that static invoker doesn't have a const qualifier.
- // FIXME: When creating the InvokerTemplate in SemaLambda.cpp
+ // FIXME: When creating the InvokerTemplate in SemaLambda.cpp
// do not use the CallOperator's TypeSourceInfo which allows
- // the const qualifier to leak through.
+ // the const qualifier to leak through.
const FunctionProtoType *InvokerFPT = InvokerSpecialized->
getType().getTypePtr()->castAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = InvokerFPT->getExtProtoInfo();
@@ -3857,7 +3894,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
// Finish template argument deduction.
FunctionDecl *ConversionSpecialized = nullptr;
TemplateDeductionResult Result
- = FinishTemplateArgumentDeduction(ConversionTemplate, Deduced, 0,
+ = FinishTemplateArgumentDeduction(ConversionTemplate, Deduced, 0,
ConversionSpecialized, Info);
Specialization = cast_or_null<CXXConversionDecl>(ConversionSpecialized);
@@ -3866,19 +3903,19 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
// function to specialize the corresponding call operator.
// e.g., int (*fp)(int) = [](auto a) { return a; };
if (Result == TDK_Success && isLambdaConversionOperator(ConversionGeneric)) {
-
+
// Get the return type of the destination ptr-to-function we are converting
- // to. This is necessary for matching the lambda call operator's return
+ // to. This is necessary for matching the lambda call operator's return
// type to that of the destination ptr-to-function's return type.
- assert(A->isPointerType() &&
+ assert(A->isPointerType() &&
"Can only convert from lambda to ptr-to-function");
- const FunctionType *ToFunType =
+ const FunctionType *ToFunType =
A->getPointeeType().getTypePtr()->getAs<FunctionType>();
const QualType DestFunctionPtrReturnType = ToFunType->getReturnType();
- // Create the corresponding specializations of the call operator and
- // the static-invoker; and if the return type is auto,
- // deduce the return type and check if it matches the
+ // Create the corresponding specializations of the call operator and
+ // the static-invoker; and if the return type is auto,
+ // deduce the return type and check if it matches the
// DestFunctionPtrReturnType.
// For instance:
// auto L = [](auto a) { return f(a); };
@@ -3886,7 +3923,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
// char (*fp2)(int) = L; <-- Not OK.
Result = SpecializeCorrespondingLambdaCallOperatorAndInvoker(
- Specialization, Deduced, DestFunctionPtrReturnType,
+ Specialization, Deduced, DestFunctionPtrReturnType,
Info, *this);
}
return Result;
@@ -3908,16 +3945,22 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
/// \param Info the argument will be updated to provide additional information
/// about template argument deduction.
///
+/// \param IsAddressOfFunction If \c true, we are deducing as part of taking
+/// the address of a function template in a context where we do not have a
+/// target type, per [over.over]. If \c false, we are looking up a function
+/// template specialization based on its signature, which only happens when
+/// deducing a function parameter type from an argument that is a template-id
+/// naming a function template specialization.
+///
/// \returns the result of template argument deduction.
-Sema::TemplateDeductionResult
-Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
- TemplateArgumentListInfo *ExplicitTemplateArgs,
- FunctionDecl *&Specialization,
- TemplateDeductionInfo &Info,
- bool InOverloadResolution) {
+Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
+ FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
+ FunctionDecl *&Specialization, TemplateDeductionInfo &Info,
+ bool IsAddressOfFunction) {
return DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
QualType(), Specialization, Info,
- InOverloadResolution);
+ IsAddressOfFunction);
}
namespace {
@@ -3926,10 +3969,12 @@ namespace {
class SubstituteAutoTransform :
public TreeTransform<SubstituteAutoTransform> {
QualType Replacement;
+ bool UseAutoSugar;
public:
- SubstituteAutoTransform(Sema &SemaRef, QualType Replacement)
+ SubstituteAutoTransform(Sema &SemaRef, QualType Replacement,
+ bool UseAutoSugar = true)
: TreeTransform<SubstituteAutoTransform>(SemaRef),
- Replacement(Replacement) {}
+ Replacement(Replacement), UseAutoSugar(UseAutoSugar) {}
QualType TransformAutoType(TypeLocBuilder &TLB, AutoTypeLoc TL) {
// If we're building the type pattern to deduce against, don't wrap the
@@ -3939,19 +3984,17 @@ namespace {
// auto &&lref = lvalue;
// must transform into "rvalue reference to T" not "rvalue reference to
// auto type deduced as T" in order for [temp.deduct.call]p3 to apply.
- if (!Replacement.isNull() && isa<TemplateTypeParmType>(Replacement)) {
+ if (!UseAutoSugar) {
+ assert(isa<TemplateTypeParmType>(Replacement) &&
+ "unexpected unsugared replacement kind");
QualType Result = Replacement;
TemplateTypeParmTypeLoc NewTL =
TLB.push<TemplateTypeParmTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
return Result;
} else {
- bool Dependent =
- !Replacement.isNull() && Replacement->isDependentType();
- QualType Result =
- SemaRef.Context.getAutoType(Dependent ? QualType() : Replacement,
- TL.getTypePtr()->getKeyword(),
- Dependent);
+ QualType Result = SemaRef.Context.getAutoType(
+ Replacement, TL.getTypePtr()->getKeyword(), Replacement.isNull());
AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
return Result;
@@ -3974,18 +4017,29 @@ namespace {
}
Sema::DeduceAutoResult
-Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init, QualType &Result) {
- return DeduceAutoType(Type->getTypeLoc(), Init, Result);
+Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init, QualType &Result,
+ Optional<unsigned> DependentDeductionDepth) {
+ return DeduceAutoType(Type->getTypeLoc(), Init, Result,
+ DependentDeductionDepth);
}
/// \brief Deduce the type for an auto type-specifier (C++11 [dcl.spec.auto]p6)
///
+/// Note that this is done even if the initializer is dependent. (This is
+/// necessary to support partial ordering of templates using 'auto'.)
+/// A dependent type will be produced when deducing from a dependent type.
+///
/// \param Type the type pattern using the auto type-specifier.
/// \param Init the initializer for the variable whose type is to be deduced.
/// \param Result if type deduction was successful, this will be set to the
/// deduced type.
+/// \param DependentDeductionDepth Set if we should permit deduction in
+/// dependent cases. This is necessary for template partial ordering with
+/// 'auto' template parameters. The value specified is the template
+/// parameter depth at which we should perform 'auto' deduction.
Sema::DeduceAutoResult
-Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
+Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
+ Optional<unsigned> DependentDeductionDepth) {
if (Init->getType()->isNonOverloadPlaceholderType()) {
ExprResult NonPlaceholder = CheckPlaceholderExpr(Init);
if (NonPlaceholder.isInvalid())
@@ -3993,12 +4047,16 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
Init = NonPlaceholder.get();
}
- if (Init->isTypeDependent() || Type.getType()->isDependentType()) {
- Result = SubstituteAutoTransform(*this, Context.DependentTy).Apply(Type);
+ if (!DependentDeductionDepth &&
+ (Type.getType()->isDependentType() || Init->isTypeDependent())) {
+ Result = SubstituteAutoTransform(*this, QualType()).Apply(Type);
assert(!Result.isNull() && "substituting DependentTy can't fail");
return DAR_Succeeded;
}
+ // Find the depth of template parameter to synthesize.
+ unsigned Depth = DependentDeductionDepth.getValueOr(0);
+
// If this is a 'decltype(auto)' specifier, do the decltype dance.
// Since 'decltype(auto)' can only occur at the top of the type, we
// don't need to go digging for it.
@@ -4031,15 +4089,16 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
LocalInstantiationScope InstScope(*this);
// Build template<class TemplParam> void Func(FuncParam);
- TemplateTypeParmDecl *TemplParam =
- TemplateTypeParmDecl::Create(Context, nullptr, SourceLocation(), Loc, 0, 0,
- nullptr, false, false);
+ TemplateTypeParmDecl *TemplParam = TemplateTypeParmDecl::Create(
+ Context, nullptr, SourceLocation(), Loc, Depth, 0, nullptr, false, false);
QualType TemplArg = QualType(TemplParam->getTypeForDecl(), 0);
NamedDecl *TemplParamPtr = TemplParam;
- FixedSizeTemplateParameterListStorage<1> TemplateParamsSt(
- Loc, Loc, TemplParamPtr, Loc);
+ FixedSizeTemplateParameterListStorage<1, false> TemplateParamsSt(
+ Loc, Loc, TemplParamPtr, Loc, nullptr);
- QualType FuncParam = SubstituteAutoTransform(*this, TemplArg).Apply(Type);
+ QualType FuncParam =
+ SubstituteAutoTransform(*this, TemplArg, /*UseAutoSugar*/false)
+ .Apply(Type);
assert(!FuncParam.isNull() &&
"substituting template parameter for 'auto' failed");
@@ -4049,7 +4108,18 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
QualType InitType = Init->getType();
unsigned TDF = 0;
- TemplateDeductionInfo Info(Loc);
+ TemplateDeductionInfo Info(Loc, Depth);
+
+ // If deduction failed, don't diagnose if the initializer is dependent; it
+ // might acquire a matching type in the instantiation.
+ auto DeductionFailed = [&]() -> DeduceAutoResult {
+ if (Init->isTypeDependent()) {
+ Result = SubstituteAutoTransform(*this, QualType()).Apply(Type);
+ assert(!Result.isNull() && "substituting DependentTy can't fail");
+ return DAR_Succeeded;
+ }
+ return DAR_Failed;
+ };
InitListExpr *InitList = dyn_cast<InitListExpr>(Init);
if (InitList) {
@@ -4057,7 +4127,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
if (DeduceTemplateArgumentByListElement(*this, TemplateParamsSt.get(),
TemplArg, InitList->getInit(i),
Info, Deduced, TDF))
- return DAR_Failed;
+ return DeductionFailed();
}
} else {
if (!getLangOpts().CPlusPlus && Init->refersToBitField()) {
@@ -4072,11 +4142,12 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
if (DeduceTemplateArgumentsByTypeMatch(*this, TemplateParamsSt.get(),
FuncParam, InitType, Info, Deduced,
TDF))
- return DAR_Failed;
+ return DeductionFailed();
}
+ // Could be null if somehow 'auto' appears in a non-deduced context.
if (Deduced[0].getKind() != TemplateArgument::Type)
- return DAR_Failed;
+ return DeductionFailed();
QualType DeducedType = Deduced[0].getAsType();
@@ -4088,7 +4159,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
Result = SubstituteAutoTransform(*this, DeducedType).Apply(Type);
if (Result.isNull())
- return DAR_FailedAlreadyDiagnosed;
+ return DAR_FailedAlreadyDiagnosed;
// Check that the deduced argument type is compatible with the original
// argument type per C++ [temp.deduct.call]p4.
@@ -4097,22 +4168,26 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
Sema::OriginalCallArg(FuncParam,0,InitType),
Result)) {
Result = QualType();
- return DAR_Failed;
+ return DeductionFailed();
}
return DAR_Succeeded;
}
-QualType Sema::SubstAutoType(QualType TypeWithAuto,
+QualType Sema::SubstAutoType(QualType TypeWithAuto,
QualType TypeToReplaceAuto) {
- return SubstituteAutoTransform(*this, TypeToReplaceAuto).
- TransformType(TypeWithAuto);
+ if (TypeToReplaceAuto->isDependentType())
+ TypeToReplaceAuto = QualType();
+ return SubstituteAutoTransform(*this, TypeToReplaceAuto)
+ .TransformType(TypeWithAuto);
}
-TypeSourceInfo* Sema::SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
+TypeSourceInfo* Sema::SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
QualType TypeToReplaceAuto) {
- return SubstituteAutoTransform(*this, TypeToReplaceAuto).
- TransformType(TypeWithAuto);
+ if (TypeToReplaceAuto->isDependentType())
+ TypeToReplaceAuto = QualType();
+ return SubstituteAutoTransform(*this, TypeToReplaceAuto)
+ .TransformType(TypeWithAuto);
}
void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {
@@ -4284,6 +4359,10 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
if (Deduced[ArgIdx].isNull())
break;
+ // FIXME: We fail to implement [temp.deduct.type]p1 along this path. We need
+ // to substitute the deduced arguments back into the template and check that
+ // we get the right type.
+
if (ArgIdx == NumArgs) {
// All template arguments were deduced. FT1 is at least as specialized
// as FT2.
@@ -4487,12 +4566,12 @@ UnresolvedSetIterator Sema::getMostSpecialized(
// FIXME: Can we order the candidates in some sane way?
for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I) {
PartialDiagnostic PD = CandidateDiag;
- PD << getTemplateArgumentBindingsText(
- cast<FunctionDecl>(*I)->getPrimaryTemplate()->getTemplateParameters(),
- *cast<FunctionDecl>(*I)->getTemplateSpecializationArgs());
+ const auto *FD = cast<FunctionDecl>(*I);
+ PD << FD << getTemplateArgumentBindingsText(
+ FD->getPrimaryTemplate()->getTemplateParameters(),
+ *FD->getTemplateSpecializationArgs());
if (!TargetType.isNull())
- HandleFunctionTypeMismatch(PD, cast<FunctionDecl>(*I)->getType(),
- TargetType);
+ HandleFunctionTypeMismatch(PD, FD->getType(), TargetType);
Diag((*I)->getLocation(), PD);
}
}
@@ -4500,21 +4579,17 @@ UnresolvedSetIterator Sema::getMostSpecialized(
return SpecEnd;
}
-/// \brief Returns the more specialized class template partial specialization
-/// according to the rules of partial ordering of class template partial
-/// specializations (C++ [temp.class.order]).
-///
-/// \param PS1 the first class template partial specialization
+/// Determine whether one partial specialization, P1, is at least as
+/// specialized than another, P2.
///
-/// \param PS2 the second class template partial specialization
-///
-/// \returns the more specialized class template partial specialization. If
-/// neither partial specialization is more specialized, returns NULL.
-ClassTemplatePartialSpecializationDecl *
-Sema::getMoreSpecializedPartialSpecialization(
- ClassTemplatePartialSpecializationDecl *PS1,
- ClassTemplatePartialSpecializationDecl *PS2,
- SourceLocation Loc) {
+/// \tparam TemplateLikeDecl The kind of P2, which must be a
+/// TemplateDecl or {Class,Var}TemplatePartialSpecializationDecl.
+/// \param T1 The injected-class-name of P1 (faked for a variable template).
+/// \param T2 The injected-class-name of P2 (faked for a variable template).
+template<typename TemplateLikeDecl>
+static bool isAtLeastAsSpecializedAs(Sema &S, QualType T1, QualType T2,
+ TemplateLikeDecl *P2,
+ TemplateDeductionInfo &Info) {
// C++ [temp.class.order]p1:
// For two class template partial specializations, the first is at least as
// specialized as the second if, given the following rewrite to two
@@ -4540,37 +4615,50 @@ Sema::getMoreSpecializedPartialSpecialization(
// template partial specialization's template arguments, for
// example.
SmallVector<DeducedTemplateArgument, 4> Deduced;
- TemplateDeductionInfo Info(Loc);
+ // Determine whether P1 is at least as specialized as P2.
+ Deduced.resize(P2->getTemplateParameters()->size());
+ if (DeduceTemplateArgumentsByTypeMatch(S, P2->getTemplateParameters(),
+ T2, T1, Info, Deduced, TDF_None,
+ /*PartialOrdering=*/true))
+ return false;
+
+ SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
+ Deduced.end());
+ Sema::InstantiatingTemplate Inst(S, Info.getLocation(), P2, DeducedArgs,
+ Info);
+ auto *TST1 = T1->castAs<TemplateSpecializationType>();
+ if (FinishTemplateArgumentDeduction(
+ S, P2, /*PartialOrdering=*/true,
+ TemplateArgumentList(TemplateArgumentList::OnStack,
+ TST1->template_arguments()),
+ Deduced, Info))
+ return false;
+
+ return true;
+}
+
+/// \brief Returns the more specialized class template partial specialization
+/// according to the rules of partial ordering of class template partial
+/// specializations (C++ [temp.class.order]).
+///
+/// \param PS1 the first class template partial specialization
+///
+/// \param PS2 the second class template partial specialization
+///
+/// \returns the more specialized class template partial specialization. If
+/// neither partial specialization is more specialized, returns NULL.
+ClassTemplatePartialSpecializationDecl *
+Sema::getMoreSpecializedPartialSpecialization(
+ ClassTemplatePartialSpecializationDecl *PS1,
+ ClassTemplatePartialSpecializationDecl *PS2,
+ SourceLocation Loc) {
QualType PT1 = PS1->getInjectedSpecializationType();
QualType PT2 = PS2->getInjectedSpecializationType();
- // Determine whether PS1 is at least as specialized as PS2
- Deduced.resize(PS2->getTemplateParameters()->size());
- bool Better1 = !DeduceTemplateArgumentsByTypeMatch(*this,
- PS2->getTemplateParameters(),
- PT2, PT1, Info, Deduced, TDF_None,
- /*PartialOrdering=*/true);
- if (Better1) {
- SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end());
- InstantiatingTemplate Inst(*this, Loc, PS2, DeducedArgs, Info);
- Better1 = !::FinishTemplateArgumentDeduction(
- *this, PS2, PS1->getTemplateArgs(), Deduced, Info);
- }
-
- // Determine whether PS2 is at least as specialized as PS1
- Deduced.clear();
- Deduced.resize(PS1->getTemplateParameters()->size());
- bool Better2 = !DeduceTemplateArgumentsByTypeMatch(
- *this, PS1->getTemplateParameters(), PT1, PT2, Info, Deduced, TDF_None,
- /*PartialOrdering=*/true);
- if (Better2) {
- SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
- Deduced.end());
- InstantiatingTemplate Inst(*this, Loc, PS1, DeducedArgs, Info);
- Better2 = !::FinishTemplateArgumentDeduction(
- *this, PS1, PS2->getTemplateArgs(), Deduced, Info);
- }
+ TemplateDeductionInfo Info(Loc);
+ bool Better1 = isAtLeastAsSpecializedAs(*this, PT1, PT2, PS2, Info);
+ bool Better2 = isAtLeastAsSpecializedAs(*this, PT2, PT1, PS1, Info);
if (Better1 == Better2)
return nullptr;
@@ -4578,18 +4666,26 @@ Sema::getMoreSpecializedPartialSpecialization(
return Better1 ? PS1 : PS2;
}
-/// TODO: Unify with ClassTemplatePartialSpecializationDecl version?
-/// May require unifying ClassTemplate(Partial)SpecializationDecl and
-/// VarTemplate(Partial)SpecializationDecl with a new data
-/// structure Template(Partial)SpecializationDecl, and
-/// using Template(Partial)SpecializationDecl as input type.
+bool Sema::isMoreSpecializedThanPrimary(
+ ClassTemplatePartialSpecializationDecl *Spec, TemplateDeductionInfo &Info) {
+ ClassTemplateDecl *Primary = Spec->getSpecializedTemplate();
+ QualType PrimaryT = Primary->getInjectedClassNameSpecialization();
+ QualType PartialT = Spec->getInjectedSpecializationType();
+ if (!isAtLeastAsSpecializedAs(*this, PartialT, PrimaryT, Primary, Info))
+ return false;
+ if (isAtLeastAsSpecializedAs(*this, PrimaryT, PartialT, Spec, Info)) {
+ Info.clearSFINAEDiagnostic();
+ return false;
+ }
+ return true;
+}
+
VarTemplatePartialSpecializationDecl *
Sema::getMoreSpecializedPartialSpecialization(
VarTemplatePartialSpecializationDecl *PS1,
VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc) {
- SmallVector<DeducedTemplateArgument, 4> Deduced;
- TemplateDeductionInfo Info(Loc);
-
+ // Pretend the variable template specializations are class template
+ // specializations and form a fake injected class name type for comparison.
assert(PS1->getSpecializedTemplate() == PS2->getSpecializedTemplate() &&
"the partial specializations being compared should specialize"
" the same template.");
@@ -4600,39 +4696,101 @@ Sema::getMoreSpecializedPartialSpecialization(
QualType PT2 = Context.getTemplateSpecializationType(
CanonTemplate, PS2->getTemplateArgs().asArray());
- // Determine whether PS1 is at least as specialized as PS2
- Deduced.resize(PS2->getTemplateParameters()->size());
- bool Better1 = !DeduceTemplateArgumentsByTypeMatch(
- *this, PS2->getTemplateParameters(), PT2, PT1, Info, Deduced, TDF_None,
- /*PartialOrdering=*/true);
- if (Better1) {
- SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
- Deduced.end());
- InstantiatingTemplate Inst(*this, Loc, PS2, DeducedArgs, Info);
- Better1 = !::FinishTemplateArgumentDeduction(*this, PS2,
- PS1->getTemplateArgs(),
- Deduced, Info);
+ TemplateDeductionInfo Info(Loc);
+ bool Better1 = isAtLeastAsSpecializedAs(*this, PT1, PT2, PS2, Info);
+ bool Better2 = isAtLeastAsSpecializedAs(*this, PT2, PT1, PS1, Info);
+
+ if (Better1 == Better2)
+ return nullptr;
+
+ return Better1 ? PS1 : PS2;
+}
+
+bool Sema::isMoreSpecializedThanPrimary(
+ VarTemplatePartialSpecializationDecl *Spec, TemplateDeductionInfo &Info) {
+ TemplateDecl *Primary = Spec->getSpecializedTemplate();
+ // FIXME: Cache the injected template arguments rather than recomputing
+ // them for each partial specialization.
+ SmallVector<TemplateArgument, 8> PrimaryArgs;
+ Context.getInjectedTemplateArgs(Primary->getTemplateParameters(),
+ PrimaryArgs);
+
+ TemplateName CanonTemplate =
+ Context.getCanonicalTemplateName(TemplateName(Primary));
+ QualType PrimaryT = Context.getTemplateSpecializationType(
+ CanonTemplate, PrimaryArgs);
+ QualType PartialT = Context.getTemplateSpecializationType(
+ CanonTemplate, Spec->getTemplateArgs().asArray());
+ if (!isAtLeastAsSpecializedAs(*this, PartialT, PrimaryT, Primary, Info))
+ return false;
+ if (isAtLeastAsSpecializedAs(*this, PrimaryT, PartialT, Spec, Info)) {
+ Info.clearSFINAEDiagnostic();
+ return false;
}
+ return true;
+}
- // Determine whether PS2 is at least as specialized as PS1
- Deduced.clear();
- Deduced.resize(PS1->getTemplateParameters()->size());
- bool Better2 = !DeduceTemplateArgumentsByTypeMatch(*this,
- PS1->getTemplateParameters(),
- PT1, PT2, Info, Deduced, TDF_None,
- /*PartialOrdering=*/true);
- if (Better2) {
- SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end());
- InstantiatingTemplate Inst(*this, Loc, PS1, DeducedArgs, Info);
- Better2 = !::FinishTemplateArgumentDeduction(*this, PS1,
- PS2->getTemplateArgs(),
- Deduced, Info);
+bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
+ TemplateParameterList *P, TemplateDecl *AArg, SourceLocation Loc) {
+ // C++1z [temp.arg.template]p4: (DR 150)
+ // A template template-parameter P is at least as specialized as a
+ // template template-argument A if, given the following rewrite to two
+ // function templates...
+
+ // Rather than synthesize function templates, we merely perform the
+ // equivalent partial ordering by performing deduction directly on
+ // the template parameter lists of the template template parameters.
+ //
+ // Given an invented class template X with the template parameter list of
+ // A (including default arguments):
+ TemplateName X = Context.getCanonicalTemplateName(TemplateName(AArg));
+ TemplateParameterList *A = AArg->getTemplateParameters();
+
+ // - Each function template has a single function parameter whose type is
+ // a specialization of X with template arguments corresponding to the
+ // template parameters from the respective function template
+ SmallVector<TemplateArgument, 8> AArgs;
+ Context.getInjectedTemplateArgs(A, AArgs);
+
+ // Check P's arguments against A's parameter list. This will fill in default
+ // template arguments as needed. AArgs are already correct by construction.
+ // We can't just use CheckTemplateIdType because that will expand alias
+ // templates.
+ SmallVector<TemplateArgument, 4> PArgs;
+ {
+ SFINAETrap Trap(*this);
+
+ Context.getInjectedTemplateArgs(P, PArgs);
+ TemplateArgumentListInfo PArgList(P->getLAngleLoc(), P->getRAngleLoc());
+ for (unsigned I = 0, N = P->size(); I != N; ++I) {
+ // Unwrap packs that getInjectedTemplateArgs wrapped around pack
+ // expansions, to form an "as written" argument list.
+ TemplateArgument Arg = PArgs[I];
+ if (Arg.getKind() == TemplateArgument::Pack) {
+ assert(Arg.pack_size() == 1 && Arg.pack_begin()->isPackExpansion());
+ Arg = *Arg.pack_begin();
+ }
+ PArgList.addArgument(getTrivialTemplateArgumentLoc(
+ Arg, QualType(), P->getParam(I)->getLocation()));
+ }
+ PArgs.clear();
+
+ // C++1z [temp.arg.template]p3:
+ // If the rewrite produces an invalid type, then P is not at least as
+ // specialized as A.
+ if (CheckTemplateArgumentList(AArg, Loc, PArgList, false, PArgs) ||
+ Trap.hasErrorOccurred())
+ return false;
}
- if (Better1 == Better2)
- return nullptr;
+ QualType AType = Context.getTemplateSpecializationType(X, AArgs);
+ QualType PType = Context.getTemplateSpecializationType(X, PArgs);
- return Better1? PS1 : PS2;
+ // ... the function template corresponding to P is at least as specialized
+ // as the function template corresponding to A according to the partial
+ // ordering rules for function templates.
+ TemplateDeductionInfo Info(Loc, A->getDepth());
+ return isAtLeastAsSpecializedAs(*this, PType, AType, AArg, Info);
}
static void
@@ -4679,6 +4837,11 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
if (NTTP->getDepth() == Depth)
Used[NTTP->getIndex()] = true;
+
+ // In C++1z mode, additional arguments may be deduced from the type of a
+ // non-type argument.
+ if (Ctx.getLangOpts().CPlusPlus1z)
+ MarkUsedTemplateParameters(Ctx, NTTP->getType(), OnlyDeduced, Depth, Used);
}
/// \brief Mark the template parameters that are used by the given
@@ -4846,7 +5009,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
// not the last template argument, the entire template argument list is a
// non-deduced context.
if (OnlyDeduced &&
- hasPackExpansionBeforeEnd(Spec->getArgs(), Spec->getNumArgs()))
+ hasPackExpansionBeforeEnd(Spec->template_arguments()))
break;
for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
@@ -4925,7 +5088,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
case Type::UnaryTransform:
if (!OnlyDeduced)
MarkUsedTemplateParameters(Ctx,
- cast<UnaryTransformType>(T)->getUnderlyingType(),
+ cast<UnaryTransformType>(T)->getUnderlyingType(),
OnlyDeduced, Depth, Used);
break;
@@ -5021,7 +5184,7 @@ Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
// the last template argument, the entire template argument list is a
// non-deduced context.
if (OnlyDeduced &&
- hasPackExpansionBeforeEnd(TemplateArgs.data(), TemplateArgs.size()))
+ hasPackExpansionBeforeEnd(TemplateArgs.asArray()))
return;
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
@@ -5054,7 +5217,7 @@ bool hasDeducibleTemplateParameters(Sema &S,
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
llvm::SmallBitVector Deduced(TemplateParams->size());
- ::MarkUsedTemplateParameters(S.Context, T, true, TemplateParams->getDepth(),
+ ::MarkUsedTemplateParameters(S.Context, T, true, TemplateParams->getDepth(),
Deduced);
return Deduced.any();