summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp699
1 files changed, 547 insertions, 152 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
index 8efc7a0..8d66ff6 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -13,6 +13,7 @@
#include "clang/Sema/TemplateDeduction.h"
#include "TreeTransform.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTLambda.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
@@ -26,7 +27,6 @@
namespace clang {
using namespace sema;
-
/// \brief Various flags that control template argument deduction.
///
/// These flags can be bitwise-OR'd together.
@@ -89,7 +89,7 @@ DeduceTemplateArguments(Sema &S,
const TemplateArgument &Param,
TemplateArgument Arg,
TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced);
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced);
/// \brief Whether template argument deduction for two reference parameters
/// resulted in the argument type, parameter type, or neither type being more
@@ -375,10 +375,10 @@ DeduceNonTypeTemplateArgument(Sema &S,
/// \returns true if deduction succeeded, false otherwise.
static Sema::TemplateDeductionResult
DeduceNonTypeTemplateArgument(Sema &S,
- NonTypeTemplateParmDecl *NTTP,
- ValueDecl *D,
- TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ NonTypeTemplateParmDecl *NTTP,
+ ValueDecl *D,
+ TemplateDeductionInfo &Info,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument with depth > 0");
@@ -405,7 +405,7 @@ DeduceTemplateArguments(Sema &S,
TemplateName Param,
TemplateName Arg,
TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
TemplateDecl *ParamDecl = Param.getAsTemplateDecl();
if (!ParamDecl) {
// The parameter type is dependent and is not a template template parameter,
@@ -464,7 +464,7 @@ DeduceTemplateArguments(Sema &S,
const TemplateSpecializationType *Param,
QualType Arg,
TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
assert(Arg.isCanonical() && "Argument type must be canonical");
// Check whether the template argument is a dependent template-id.
@@ -575,20 +575,23 @@ getDepthAndIndex(UnexpandedParameterPack UPP) {
static TemplateParameter makeTemplateParameter(Decl *D) {
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(D))
return TemplateParameter(TTP);
- else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D))
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D))
return TemplateParameter(NTTP);
return TemplateParameter(cast<TemplateTemplateParmDecl>(D));
}
+typedef SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2>
+ NewlyDeducedPacksType;
+
/// \brief Prepare to perform template argument deduction for all of the
/// arguments in a set of argument packs.
-static void PrepareArgumentPackDeduction(Sema &S,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- ArrayRef<unsigned> PackIndices,
- SmallVectorImpl<DeducedTemplateArgument> &SavedPacks,
- SmallVectorImpl<
- SmallVector<DeducedTemplateArgument, 4> > &NewlyDeducedPacks) {
+static void
+PrepareArgumentPackDeduction(Sema &S,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ ArrayRef<unsigned> PackIndices,
+ SmallVectorImpl<DeducedTemplateArgument> &SavedPacks,
+ NewlyDeducedPacksType &NewlyDeducedPacks) {
// Save the deduced template arguments for each parameter pack expanded
// by this pack expansion, then clear out the deduction.
for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
@@ -620,14 +623,13 @@ static void PrepareArgumentPackDeduction(Sema &S,
/// deductions.
static Sema::TemplateDeductionResult
FinishArgumentPackDeduction(Sema &S,
- TemplateParameterList *TemplateParams,
- bool HasAnyArguments,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- ArrayRef<unsigned> PackIndices,
- SmallVectorImpl<DeducedTemplateArgument> &SavedPacks,
- SmallVectorImpl<
- SmallVector<DeducedTemplateArgument, 4> > &NewlyDeducedPacks,
- TemplateDeductionInfo &Info) {
+ TemplateParameterList *TemplateParams,
+ bool HasAnyArguments,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ ArrayRef<unsigned> PackIndices,
+ SmallVectorImpl<DeducedTemplateArgument> &SavedPacks,
+ NewlyDeducedPacksType &NewlyDeducedPacks,
+ TemplateDeductionInfo &Info) {
// Build argument packs for each of the parameter packs expanded by this
// pack expansion.
for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
@@ -709,7 +711,7 @@ DeduceTemplateArguments(Sema &S,
const QualType *Params, unsigned NumParams,
const QualType *Args, unsigned NumArgs,
TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned TDF,
bool PartialOrdering = false,
SmallVectorImpl<RefParamPartialOrderingComparison> *
@@ -793,8 +795,7 @@ DeduceTemplateArguments(Sema &S,
// Keep track of the deduced template arguments for each parameter pack
// expanded by this pack expansion (the outer index) and for each
// template argument (the inner SmallVectors).
- SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2>
- NewlyDeducedPacks(PackIndices.size());
+ NewlyDeducedPacksType NewlyDeducedPacks(PackIndices.size());
SmallVector<DeducedTemplateArgument, 2>
SavedPacks(PackIndices.size());
PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks,
@@ -1430,8 +1431,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
Deduced.end());
while (!ToVisit.empty()) {
// Retrieve the next class in the inheritance hierarchy.
- const RecordType *NextT = ToVisit.back();
- ToVisit.pop_back();
+ const RecordType *NextT = ToVisit.pop_back_val();
// If we have already seen this type, skip it.
if (!Visited.insert(NextT))
@@ -1635,7 +1635,7 @@ DeduceTemplateArguments(Sema &S,
const TemplateArgument &Param,
TemplateArgument Arg,
TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
// If the template argument is a pack expansion, perform template argument
// deduction against the pattern of that expansion. This only occurs during
// partial ordering.
@@ -1871,8 +1871,7 @@ DeduceTemplateArguments(Sema &S,
// by this pack expansion, then clear out the deduction.
SmallVector<DeducedTemplateArgument, 2>
SavedPacks(PackIndices.size());
- SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2>
- NewlyDeducedPacks(PackIndices.size());
+ NewlyDeducedPacksType NewlyDeducedPacks(PackIndices.size());
PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks,
NewlyDeducedPacks);
@@ -1921,7 +1920,7 @@ DeduceTemplateArguments(Sema &S,
const TemplateArgumentList &ParamList,
const TemplateArgumentList &ArgList,
TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
return DeduceTemplateArguments(S, TemplateParams,
ParamList.data(), ParamList.size(),
ArgList.data(), ArgList.size(),
@@ -2064,14 +2063,15 @@ getTrivialTemplateArgumentLoc(Sema &S,
/// \brief Convert the given deduced template argument and add it to the set of
/// fully-converted template arguments.
-static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
- DeducedTemplateArgument Arg,
- NamedDecl *Template,
- QualType NTTPType,
- unsigned ArgumentPackIndex,
- TemplateDeductionInfo &Info,
- bool InFunctionTemplate,
- SmallVectorImpl<TemplateArgument> &Output) {
+static bool
+ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
+ DeducedTemplateArgument Arg,
+ NamedDecl *Template,
+ QualType NTTPType,
+ unsigned ArgumentPackIndex,
+ TemplateDeductionInfo &Info,
+ bool InFunctionTemplate,
+ SmallVectorImpl<TemplateArgument> &Output) {
if (Arg.getKind() == TemplateArgument::Pack) {
// This is a template argument pack, so check each of its arguments against
// the template parameter.
@@ -2090,8 +2090,7 @@ static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
return true;
// Move the converted template argument into our argument pack.
- PackedArgsBuilder.push_back(Output.back());
- Output.pop_back();
+ PackedArgsBuilder.push_back(Output.pop_back_val());
}
// Create the resulting argument pack.
@@ -2200,14 +2199,15 @@ FinishTemplateArgumentDeduction(Sema &S,
// to the class template.
LocalInstantiationScope InstScope(S);
ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate();
- const TemplateArgumentLoc *PartialTemplateArgs
+ const ASTTemplateArgumentListInfo *PartialTemplArgInfo
= Partial->getTemplateArgsAsWritten();
+ const TemplateArgumentLoc *PartialTemplateArgs
+ = PartialTemplArgInfo->getTemplateArgs();
- // Note that we don't provide the langle and rangle locations.
- TemplateArgumentListInfo InstArgs;
+ TemplateArgumentListInfo InstArgs(PartialTemplArgInfo->LAngleLoc,
+ PartialTemplArgInfo->RAngleLoc);
- if (S.Subst(PartialTemplateArgs,
- Partial->getNumTemplateArgsAsWritten(),
+ if (S.Subst(PartialTemplateArgs, PartialTemplArgInfo->NumTemplateArgs,
InstArgs, MultiLevelTemplateArgumentList(*DeducedArgumentList))) {
unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx;
if (ParamIdx >= Partial->getTemplateParameters()->size())
@@ -2276,7 +2276,171 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial,
DeducedArgs, Info);
- if (Inst)
+ if (Inst.isInvalid())
+ return TDK_InstantiationDepth;
+
+ 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.
+
+ // 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,
+ Builder.data(), Builder.size());
+ NTTPType =
+ S.SubstType(NTTPType, MultiLevelTemplateArgumentList(TemplateArgs),
+ NTTP->getLocation(), NTTP->getDeclName());
+ if (NTTPType.isNull()) {
+ Info.Param = makeTemplateParameter(Param);
+ // FIXME: These template arguments are temporary. Free them!
+ Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder.data(),
+ Builder.size()));
+ return Sema::TDK_SubstitutionFailure;
+ }
+ }
+ }
+
+ if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], Partial, NTTPType,
+ 0, Info, false, Builder)) {
+ Info.Param = makeTemplateParameter(Param);
+ // FIXME: These template arguments are temporary. Free them!
+ Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder.data(),
+ Builder.size()));
+ return Sema::TDK_SubstitutionFailure;
+ }
+ }
+
+ // Form the template argument list from the deduced template arguments.
+ TemplateArgumentList *DeducedArgumentList = TemplateArgumentList::CreateCopy(
+ S.Context, Builder.data(), Builder.size());
+
+ 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;
+}
+
+/// \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,
+ TemplateDeductionInfo &Info) {
+ if (Partial->isInvalidDecl())
+ return TDK_Invalid;
+
+ // C++ [temp.class.spec.match]p2:
+ // A partial specialization matches a given actual template
+ // argument list if the template arguments of the partial
+ // specialization can be deduced from the actual template argument
+ // list (14.8.2).
+
+ // Unevaluated SFINAE context.
+ EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
+ SFINAETrap Trap(*this);
+
+ SmallVector<DeducedTemplateArgument, 4> Deduced;
+ Deduced.resize(Partial->getTemplateParameters()->size());
+ if (TemplateDeductionResult Result = ::DeduceTemplateArguments(
+ *this, Partial->getTemplateParameters(), Partial->getTemplateArgs(),
+ TemplateArgs, Info, Deduced))
+ return Result;
+
+ SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
+ InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial,
+ DeducedArgs, Info);
+ if (Inst.isInvalid())
return TDK_InstantiationDepth;
if (Trap.hasErrorOccurred())
@@ -2364,7 +2528,7 @@ Sema::SubstituteExplicitTemplateArguments(
FunctionTemplate, DeducedArgs,
ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution,
Info);
- if (Inst)
+ if (Inst.isInvalid())
return TDK_InstantiationDepth;
if (CheckTemplateArgumentList(FunctionTemplate,
@@ -2423,7 +2587,6 @@ Sema::SubstituteExplicitTemplateArguments(
}
// Instantiate the return type.
- // FIXME: exception-specifications?
QualType ResultType;
{
// C++11 [expr.prim.general]p3:
@@ -2524,13 +2687,16 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
Qualifiers AQuals = A.getQualifiers();
Qualifiers DeducedAQuals = DeducedA.getQualifiers();
- // Under Objective-C++ ARC, the deduced type may have implicitly been
- // given strong lifetime. If so, update the original qualifiers to
- // include this strong lifetime.
+ // Under Objective-C++ ARC, the deduced type may have implicitly
+ // been given strong or (when dealing with a const reference)
+ // unsafe_unretained lifetime. If so, update the original
+ // qualifiers to include this lifetime.
if (S.getLangOpts().ObjCAutoRefCount &&
- DeducedAQuals.getObjCLifetime() == Qualifiers::OCL_Strong &&
- AQuals.getObjCLifetime() == Qualifiers::OCL_None) {
- AQuals.setObjCLifetime(Qualifiers::OCL_Strong);
+ ((DeducedAQuals.getObjCLifetime() == Qualifiers::OCL_Strong &&
+ AQuals.getObjCLifetime() == Qualifiers::OCL_None) ||
+ (DeducedAQuals.hasConst() &&
+ DeducedAQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone))) {
+ AQuals.setObjCLifetime(DeducedAQuals.getObjCLifetime());
}
if (AQuals == DeducedAQuals) {
@@ -2551,7 +2717,7 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
//
// Also allow conversions which merely strip [[noreturn]] from function types
// (recursively) as an extension.
- // FIXME: Currently, this doesn't place nicely with qualfication conversions.
+ // FIXME: Currently, this doesn't play nicely with qualification conversions.
bool ObjCLifetimeConversion = false;
QualType ResultTy;
if ((A->isAnyPointerType() || A->isMemberPointerType()) &&
@@ -2616,7 +2782,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
FunctionTemplate, DeducedArgs,
ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
Info);
- if (Inst)
+ if (Inst.isInvalid())
return TDK_InstantiationDepth;
ContextRAII SavedContext(*this, FunctionTemplate->getTemplatedDecl());
@@ -2704,18 +2870,21 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
}
// Substitute into the default template argument, if available.
+ bool HasDefaultArg = false;
TemplateArgumentLoc DefArg
= SubstDefaultTemplateArgumentIfAvailable(FunctionTemplate,
FunctionTemplate->getLocation(),
FunctionTemplate->getSourceRange().getEnd(),
Param,
- Builder);
+ Builder, HasDefaultArg);
// If there was no default argument, deduction is incomplete.
if (DefArg.getArgument().isNull()) {
Info.Param = makeTemplateParameter(
const_cast<NamedDecl *>(TemplateParams->getParam(I)));
- return TDK_Incomplete;
+ Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(),
+ Builder.size()));
+ return HasDefaultArg ? TDK_SubstitutionFailure : TDK_Incomplete;
}
// Check whether we can actually use the default argument.
@@ -2792,7 +2961,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
// keep track of these diagnostics. They'll be emitted if this specialization
// is actually used.
if (Info.diag_begin() != Info.diag_end()) {
- llvm::DenseMap<Decl *, SmallVector<PartialDiagnosticAt, 1> >::iterator
+ SuppressedDiagnosticsMap::iterator
Pos = SuppressedDiagnostics.find(Specialization->getCanonicalDecl());
if (Pos == SuppressedDiagnostics.end())
SuppressedDiagnostics[Specialization->getCanonicalDecl()]
@@ -3099,12 +3268,10 @@ DeduceTemplateArgumentByListElement(Sema &S,
/// about template argument deduction.
///
/// \returns the result of template argument deduction.
-Sema::TemplateDeductionResult
-Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
- TemplateArgumentListInfo *ExplicitTemplateArgs,
- llvm::ArrayRef<Expr *> Args,
- FunctionDecl *&Specialization,
- TemplateDeductionInfo &Info) {
+Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
+ FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
+ FunctionDecl *&Specialization, TemplateDeductionInfo &Info) {
if (FunctionTemplate->isInvalidDecl())
return TDK_Invalid;
@@ -3251,8 +3418,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// Keep track of the deduced template arguments for each parameter pack
// expanded by this pack expansion (the outer index) and for each
// template argument (the inner SmallVectors).
- SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2>
- NewlyDeducedPacks(PackIndices.size());
+ NewlyDeducedPacksType NewlyDeducedPacks(PackIndices.size());
SmallVector<DeducedTemplateArgument, 2>
SavedPacks(PackIndices.size());
PrepareArgumentPackDeduction(*this, Deduced, PackIndices, SavedPacks,
@@ -3335,6 +3501,28 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
Specialization, Info, &OriginalCallArgs);
}
+QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
+ QualType FunctionType) {
+ 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)
+ return ArgFunctionType;
+
+ FunctionType::ExtInfo EI = ArgFunctionTypeP->getExtInfo().withCallingConv(CC);
+ EI = EI.withNoReturn(NoReturn);
+ ArgFunctionTypeP =
+ cast<FunctionProtoType>(Context.adjustFunctionType(ArgFunctionTypeP, EI));
+ return QualType(ArgFunctionTypeP, 0);
+}
+
/// \brief Deduce template arguments when taking the address of a function
/// template (C++ [temp.deduct.funcaddr]) or matching a specialization to
/// a template.
@@ -3372,6 +3560,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
QualType FunctionType = Function->getType();
+ if (!InOverloadResolution)
+ ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, FunctionType);
// Substitute any explicit template arguments.
LocalInstantiationScope InstScope(*this);
@@ -3397,11 +3587,11 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// 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.
- bool HasUndeducedReturnType = false;
+ bool HasDeducedReturnType = false;
if (getLangOpts().CPlusPlus1y && InOverloadResolution &&
- Function->getResultType()->isUndeducedType()) {
+ Function->getResultType()->getContainedAutoType()) {
FunctionType = SubstAutoType(FunctionType, Context.DependentTy);
- HasUndeducedReturnType = true;
+ HasDeducedReturnType = true;
}
if (!ArgFunctionType.isNull()) {
@@ -3423,7 +3613,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// If the function has a deduced return type, deduce it now, so we can check
// that the deduced function type matches the requested type.
- if (HasUndeducedReturnType &&
+ if (HasDeducedReturnType &&
Specialization->getResultType()->isUndeducedType() &&
DeduceReturnType(Specialization, Info.getLocation(), false))
return TDK_MiscellaneousDeductionFailure;
@@ -3444,20 +3634,130 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
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
+/// 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,
+ QualType TypeToReplaceAutoWith, Sema &S) {
+ assert(!TypeToReplaceAutoWith->getContainedAutoType());
+ QualType AutoResultType = F->getResultType();
+ 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
+/// return type of the destination function ptr.
+
+static inline Sema::TemplateDeductionResult
+SpecializeCorrespondingLambdaCallOperatorAndInvoker(
+ CXXConversionDecl *ConversionSpecialized,
+ SmallVectorImpl<DeducedTemplateArgument> &DeducedArguments,
+ QualType ReturnTypeOfDestFunctionPtr,
+ TemplateDeductionInfo &TDInfo,
+ Sema &S) {
+
+ CXXRecordDecl *LambdaClass = ConversionSpecialized->getParent();
+ assert(LambdaClass && LambdaClass->isGenericLambda());
+
+ CXXMethodDecl *CallOpGeneric = LambdaClass->getLambdaCallOperator();
+ QualType CallOpResultType = CallOpGeneric->getResultType();
+ const bool GenericLambdaCallOperatorHasDeducedReturnType =
+ CallOpResultType->getContainedAutoType();
+
+ FunctionTemplateDecl *CallOpTemplate =
+ CallOpGeneric->getDescribedFunctionTemplate();
+
+ FunctionDecl *CallOpSpecialized = 0;
+ // Use the deduced arguments of the conversion function, to specialize our
+ // generic lambda's call operator.
+ if (Sema::TemplateDeductionResult Result
+ = 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->getResultType()->isUndeducedType())
+ 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->getResultType(),
+ 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
+ // specialized our corresponding call operator, we are ready to
+ // specialize the static invoker with the deduced arguments of our
+ // ptr-to-function.
+ FunctionDecl *InvokerSpecialized = 0;
+ FunctionTemplateDecl *InvokerTemplate = LambdaClass->
+ getLambdaStaticInvoker()->getDescribedFunctionTemplate();
+
+ Sema::TemplateDeductionResult LLVM_ATTRIBUTE_UNUSED Result
+ = S.FinishTemplateArgumentDeduction(InvokerTemplate, DeducedArguments, 0,
+ InvokerSpecialized, TDInfo);
+ 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->getResultType()->isUndeducedType()) {
+ // Be sure to get the type to replace 'auto' with and not
+ // the full result type of the call op specialization
+ // to substitute into the 'auto' of the invoker and conversion
+ // function.
+ // For e.g.
+ // int* (*fp)(int*) = [](auto* a) -> auto* { return a; };
+ // We don't want to subst 'int*' into 'auto' to get int**.
+
+ QualType TypeToReplaceAutoWith =
+ CallOpSpecialized->getResultType()->
+ getContainedAutoType()->getDeducedType();
+ SubstAutoWithinFunctionReturnType(InvokerSpecialized,
+ TypeToReplaceAutoWith, S);
+ SubstAutoWithinFunctionReturnType(ConversionSpecialized,
+ TypeToReplaceAutoWith, S);
+ }
+
+ // Ensure that static invoker doesn't have a const qualifier.
+ // FIXME: When creating the InvokerTemplate in SemaLambda.cpp
+ // do not use the CallOperator's TypeSourceInfo which allows
+ // the const qualifier to leak through.
+ const FunctionProtoType *InvokerFPT = InvokerSpecialized->
+ getType().getTypePtr()->castAs<FunctionProtoType>();
+ FunctionProtoType::ExtProtoInfo EPI = InvokerFPT->getExtProtoInfo();
+ EPI.TypeQuals = 0;
+ InvokerSpecialized->setType(S.Context.getFunctionType(
+ InvokerFPT->getResultType(), InvokerFPT->getArgTypes(),EPI));
+ return Sema::TDK_Success;
+}
/// \brief Deduce template arguments for a templated conversion
/// function (C++ [temp.deduct.conv]) and, if successful, produce a
/// conversion function template specialization.
Sema::TemplateDeductionResult
-Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
QualType ToType,
CXXConversionDecl *&Specialization,
TemplateDeductionInfo &Info) {
- if (FunctionTemplate->isInvalidDecl())
+ if (ConversionTemplate->isInvalidDecl())
return TDK_Invalid;
- CXXConversionDecl *Conv
- = cast<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl());
- QualType FromType = Conv->getConversionType();
+ CXXConversionDecl *ConversionGeneric
+ = cast<CXXConversionDecl>(ConversionTemplate->getTemplatedDecl());
+
+ QualType FromType = ConversionGeneric->getConversionType();
// Canonicalize the types for deduction.
QualType P = Context.getCanonicalType(FromType);
@@ -3512,7 +3812,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// type that is required as the result of the conversion (call it
// A) as described in 14.8.2.4.
TemplateParameterList *TemplateParams
- = FunctionTemplate->getTemplateParameters();
+ = ConversionTemplate->getTemplateParameters();
SmallVector<DeducedTemplateArgument, 4> Deduced;
Deduced.resize(TemplateParams->size());
@@ -3541,13 +3841,43 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
P, A, Info, Deduced, TDF))
return Result;
- // Finish template argument deduction.
+ // Create an Instantiation Scope for finalizing the operator.
LocalInstantiationScope InstScope(*this);
- FunctionDecl *Spec = 0;
+ // Finish template argument deduction.
+ FunctionDecl *ConversionSpecialized = 0;
TemplateDeductionResult Result
- = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, 0, Spec,
- Info);
- Specialization = cast_or_null<CXXConversionDecl>(Spec);
+ = FinishTemplateArgumentDeduction(ConversionTemplate, Deduced, 0,
+ ConversionSpecialized, Info);
+ Specialization = cast_or_null<CXXConversionDecl>(ConversionSpecialized);
+
+ // If the conversion operator is being invoked on a lambda closure to convert
+ // to a ptr-to-function, use the deduced arguments from the conversion 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
+ // type to that of the destination ptr-to-function's return type.
+ assert(A->isPointerType() &&
+ "Can only convert from lambda to ptr-to-function");
+ const FunctionType *ToFunType =
+ A->getPointeeType().getTypePtr()->getAs<FunctionType>();
+ const QualType DestFunctionPtrReturnType = ToFunType->getResultType();
+
+ // 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); };
+ // int (*fp)(int) = L;
+ // char (*fp2)(int) = L; <-- Not OK.
+
+ Result = SpecializeCorrespondingLambdaCallOperatorAndInvoker(
+ Specialization, Deduced, DestFunctionPtrReturnType,
+ Info, *this);
+ }
return Result;
}
@@ -3750,17 +4080,29 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
return DAR_Succeeded;
}
-QualType Sema::SubstAutoType(QualType Type, QualType Deduced) {
- return SubstituteAutoTransform(*this, Deduced).TransformType(Type);
+QualType Sema::SubstAutoType(QualType TypeWithAuto,
+ QualType TypeToReplaceAuto) {
+ return SubstituteAutoTransform(*this, TypeToReplaceAuto).
+ TransformType(TypeWithAuto);
+}
+
+TypeSourceInfo* Sema::SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
+ QualType TypeToReplaceAuto) {
+ return SubstituteAutoTransform(*this, TypeToReplaceAuto).
+ TransformType(TypeWithAuto);
}
void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {
if (isa<InitListExpr>(Init))
Diag(VDecl->getLocation(),
- diag::err_auto_var_deduction_failure_from_init_list)
+ VDecl->isInitCapture()
+ ? diag::err_init_capture_deduction_failure_from_init_list
+ : diag::err_auto_var_deduction_failure_from_init_list)
<< VDecl->getDeclName() << VDecl->getType() << Init->getSourceRange();
else
- Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
+ Diag(VDecl->getLocation(),
+ VDecl->isInitCapture() ? diag::err_init_capture_deduction_failure
+ : diag::err_auto_var_deduction_failure)
<< VDecl->getDeclName() << VDecl->getType() << Init->getType()
<< Init->getSourceRange();
}
@@ -3788,9 +4130,10 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
llvm::SmallBitVector &Deduced);
/// \brief If this is a non-static member function,
-static void AddImplicitObjectParameterType(ASTContext &Context,
- CXXMethodDecl *Method,
- SmallVectorImpl<QualType> &ArgTypes) {
+static void
+AddImplicitObjectParameterType(ASTContext &Context,
+ CXXMethodDecl *Method,
+ SmallVectorImpl<QualType> &ArgTypes) {
// C++11 [temp.func.order]p3:
// [...] The new parameter is of type "reference to cv A," where cv are
// the cv-qualifiers of the function template (if any) and A is
@@ -3815,7 +4158,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
FunctionTemplateDecl *FT1,
FunctionTemplateDecl *FT2,
TemplatePartialOrderingContext TPOC,
- unsigned NumCallArguments,
+ unsigned NumCallArguments1,
SmallVectorImpl<RefParamPartialOrderingComparison> *RefParamComparisons) {
FunctionDecl *FD1 = FT1->getTemplatedDecl();
FunctionDecl *FD2 = FT2->getTemplatedDecl();
@@ -3831,19 +4174,13 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
// The types used to determine the ordering depend on the context in which
// the partial ordering is done:
TemplateDeductionInfo Info(Loc);
- CXXMethodDecl *Method1 = 0;
- CXXMethodDecl *Method2 = 0;
- bool IsNonStatic2 = false;
- bool IsNonStatic1 = false;
- unsigned Skip2 = 0;
+ SmallVector<QualType, 4> Args2;
switch (TPOC) {
case TPOC_Call: {
// - In the context of a function call, the function parameter types are
// used.
- Method1 = dyn_cast<CXXMethodDecl>(FD1);
- Method2 = dyn_cast<CXXMethodDecl>(FD2);
- IsNonStatic1 = Method1 && !Method1->isStatic();
- IsNonStatic2 = Method2 && !Method2->isStatic();
+ CXXMethodDecl *Method1 = dyn_cast<CXXMethodDecl>(FD1);
+ CXXMethodDecl *Method2 = dyn_cast<CXXMethodDecl>(FD2);
// C++11 [temp.func.order]p3:
// [...] If only one of the function templates is a non-static
@@ -3862,26 +4199,39 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
// first argument of the free function, which seems to match
// existing practice.
SmallVector<QualType, 4> Args1;
- unsigned Skip1 = !S.getLangOpts().CPlusPlus11 && IsNonStatic2 && !Method1;
- if (S.getLangOpts().CPlusPlus11 && IsNonStatic1 && !Method2)
- AddImplicitObjectParameterType(S.Context, Method1, Args1);
+
+ unsigned Skip1 = 0, Skip2 = 0;
+ unsigned NumComparedArguments = NumCallArguments1;
+
+ if (!Method2 && Method1 && !Method1->isStatic()) {
+ if (S.getLangOpts().CPlusPlus11) {
+ // Compare 'this' from Method1 against first parameter from Method2.
+ AddImplicitObjectParameterType(S.Context, Method1, Args1);
+ ++NumComparedArguments;
+ } else
+ // Ignore first parameter from Method2.
+ ++Skip2;
+ } else if (!Method1 && Method2 && !Method2->isStatic()) {
+ if (S.getLangOpts().CPlusPlus11)
+ // Compare 'this' from Method2 against first parameter from Method1.
+ AddImplicitObjectParameterType(S.Context, Method2, Args2);
+ else
+ // Ignore first parameter from Method1.
+ ++Skip1;
+ }
+
Args1.insert(Args1.end(),
Proto1->arg_type_begin() + Skip1, Proto1->arg_type_end());
-
- SmallVector<QualType, 4> Args2;
- Skip2 = !S.getLangOpts().CPlusPlus11 && IsNonStatic1 && !Method2;
- if (S.getLangOpts().CPlusPlus11 && IsNonStatic2 && !Method1)
- AddImplicitObjectParameterType(S.Context, Method2, Args2);
Args2.insert(Args2.end(),
Proto2->arg_type_begin() + Skip2, Proto2->arg_type_end());
// C++ [temp.func.order]p5:
// The presence of unused ellipsis and default arguments has no effect on
// the partial ordering of function templates.
- if (Args1.size() > NumCallArguments)
- Args1.resize(NumCallArguments);
- if (Args2.size() > NumCallArguments)
- Args2.resize(NumCallArguments);
+ if (Args1.size() > NumComparedArguments)
+ Args1.resize(NumComparedArguments);
+ if (Args2.size() > NumComparedArguments)
+ Args2.resize(NumComparedArguments);
if (DeduceTemplateArguments(S, TemplateParams, Args2.data(), Args2.size(),
Args1.data(), Args1.size(), Info, Deduced,
TDF_None, /*PartialOrdering=*/true,
@@ -3935,20 +4285,12 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
// Figure out which template parameters were used.
llvm::SmallBitVector UsedParameters(TemplateParams->size());
switch (TPOC) {
- case TPOC_Call: {
- unsigned NumParams = std::min(NumCallArguments,
- std::min(Proto1->getNumArgs(),
- Proto2->getNumArgs()));
- if (S.getLangOpts().CPlusPlus11 && IsNonStatic2 && !IsNonStatic1)
- ::MarkUsedTemplateParameters(S.Context, Method2->getThisType(S.Context),
- false,
- TemplateParams->getDepth(), UsedParameters);
- for (unsigned I = Skip2; I < NumParams; ++I)
- ::MarkUsedTemplateParameters(S.Context, Proto2->getArgType(I), false,
+ case TPOC_Call:
+ for (unsigned I = 0, N = Args2.size(); I != N; ++I)
+ ::MarkUsedTemplateParameters(S.Context, Args2[I], false,
TemplateParams->getDepth(),
UsedParameters);
break;
- }
case TPOC_Conversion:
::MarkUsedTemplateParameters(S.Context, Proto2->getResultType(), false,
@@ -4003,8 +4345,11 @@ static bool isVariadicFunctionTemplate(FunctionTemplateDecl *FunTmpl) {
/// \param TPOC the context in which we are performing partial ordering of
/// function templates.
///
-/// \param NumCallArguments The number of arguments in a call, used only
-/// when \c TPOC is \c TPOC_Call.
+/// \param NumCallArguments1 The number of arguments in the call to FT1, used
+/// only when \c TPOC is \c TPOC_Call.
+///
+/// \param NumCallArguments2 The number of arguments in the call to FT2, used
+/// only when \c TPOC is \c TPOC_Call.
///
/// \returns the more specialized function template. If neither
/// template is more specialized, returns NULL.
@@ -4013,12 +4358,13 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
FunctionTemplateDecl *FT2,
SourceLocation Loc,
TemplatePartialOrderingContext TPOC,
- unsigned NumCallArguments) {
+ unsigned NumCallArguments1,
+ unsigned NumCallArguments2) {
SmallVector<RefParamPartialOrderingComparison, 4> RefParamComparisons;
bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC,
- NumCallArguments, 0);
+ NumCallArguments1, 0);
bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC,
- NumCallArguments,
+ NumCallArguments2,
&RefParamComparisons);
if (Better1 != Better2) // We have a clear winner
@@ -4122,12 +4468,6 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
/// \param SpecEnd the end iterator of the function template
/// specializations, paired with \p SpecBegin.
///
-/// \param TPOC the partial ordering context to use to compare the function
-/// template specializations.
-///
-/// \param NumCallArguments The number of arguments in a call, used only
-/// when \c TPOC is \c TPOC_Call.
-///
/// \param Loc the location where the ambiguity or no-specializations
/// diagnostic should occur.
///
@@ -4144,23 +4484,17 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
///
/// \returns the most specialized function template specialization, if
/// found. Otherwise, returns SpecEnd.
-///
-/// \todo FIXME: Consider passing in the "also-ran" candidates that failed
-/// template argument deduction.
-UnresolvedSetIterator
-Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin,
- UnresolvedSetIterator SpecEnd,
- TemplatePartialOrderingContext TPOC,
- unsigned NumCallArguments,
- SourceLocation Loc,
- const PartialDiagnostic &NoneDiag,
- const PartialDiagnostic &AmbigDiag,
- const PartialDiagnostic &CandidateDiag,
- bool Complain,
- QualType TargetType) {
+UnresolvedSetIterator Sema::getMostSpecialized(
+ UnresolvedSetIterator SpecBegin, UnresolvedSetIterator SpecEnd,
+ TemplateSpecCandidateSet &FailedCandidates,
+ SourceLocation Loc, const PartialDiagnostic &NoneDiag,
+ const PartialDiagnostic &AmbigDiag, const PartialDiagnostic &CandidateDiag,
+ bool Complain, QualType TargetType) {
if (SpecBegin == SpecEnd) {
- if (Complain)
+ if (Complain) {
Diag(Loc, NoneDiag);
+ FailedCandidates.NoteCandidates(*this, Loc);
+ }
return SpecEnd;
}
@@ -4178,7 +4512,7 @@ Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin,
= cast<FunctionDecl>(*I)->getPrimaryTemplate();
assert(Challenger && "Not a function template specialization?");
if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
- Loc, TPOC, NumCallArguments),
+ Loc, TPOC_Other, 0, 0),
Challenger)) {
Best = I;
BestTemplate = Challenger;
@@ -4193,7 +4527,7 @@ Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin,
= cast<FunctionDecl>(*I)->getPrimaryTemplate();
if (I != Best &&
!isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
- Loc, TPOC, NumCallArguments),
+ Loc, TPOC_Other, 0, 0),
BestTemplate)) {
Ambiguous = true;
break;
@@ -4279,6 +4613,67 @@ Sema::getMoreSpecializedPartialSpecialization(
/*RefParamComparisons=*/0);
if (Better1) {
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end());
+ InstantiatingTemplate Inst(*this, PS2->getLocation(), 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,
+ /*RefParamComparisons=*/0);
+ if (Better2) {
+ SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
+ Deduced.end());
+ InstantiatingTemplate Inst(*this, PS1->getLocation(), PS1, DeducedArgs,
+ Info);
+ Better2 = !::FinishTemplateArgumentDeduction(
+ *this, PS1, PS2->getTemplateArgs(), Deduced, Info);
+ }
+
+ if (Better1 == Better2)
+ return 0;
+
+ 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.
+VarTemplatePartialSpecializationDecl *
+Sema::getMoreSpecializedPartialSpecialization(
+ VarTemplatePartialSpecializationDecl *PS1,
+ VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc) {
+ SmallVector<DeducedTemplateArgument, 4> Deduced;
+ TemplateDeductionInfo Info(Loc);
+
+ assert(PS1->getSpecializedTemplate() == PS1->getSpecializedTemplate() &&
+ "the partial specializations being compared should specialize"
+ " the same template.");
+ TemplateName Name(PS1->getSpecializedTemplate());
+ TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
+ QualType PT1 = Context.getTemplateSpecializationType(
+ CanonTemplate, PS1->getTemplateArgs().data(),
+ PS1->getTemplateArgs().size());
+ QualType PT2 = Context.getTemplateSpecializationType(
+ CanonTemplate, PS2->getTemplateArgs().data(),
+ PS2->getTemplateArgs().size());
+
+ // 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,
+ /*RefParamComparisons=*/0);
+ if (Better1) {
+ SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
+ Deduced.end());
InstantiatingTemplate Inst(*this, PS2->getLocation(), PS2,
DeducedArgs, Info);
Better1 = !::FinishTemplateArgumentDeduction(*this, PS2,
OpenPOWER on IntegriCloud