SemaTemplateDeduction.cpp [plain text]
#include "clang/Sema/Sema.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "llvm/ADT/SmallBitVector.h"
#include "TreeTransform.h"
#include <algorithm>
namespace clang {
using namespace sema;
enum TemplateDeductionFlags {
TDF_None = 0,
TDF_ParamWithReferenceType = 0x1,
TDF_IgnoreQualifiers = 0x02,
TDF_DerivedClass = 0x04,
TDF_SkipNonDependent = 0x08,
TDF_TopLevelParameterTypeList = 0x10
};
}
using namespace clang;
static bool hasSameExtendedValue(llvm::APSInt X, llvm::APSInt Y) {
if (Y.getBitWidth() > X.getBitWidth())
X = X.extend(Y.getBitWidth());
else if (Y.getBitWidth() < X.getBitWidth())
Y = Y.extend(X.getBitWidth());
if (X.isSigned() != Y.isSigned()) {
if ((Y.isSigned() && Y.isNegative()) || (X.isSigned() && X.isNegative()))
return false;
Y.setIsSigned(true);
X.setIsSigned(true);
}
return X == Y;
}
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateArgument &Param,
TemplateArgument Arg,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced);
enum DeductionQualifierComparison {
NeitherMoreQualified = 0,
ParamMoreQualified,
ArgMoreQualified
};
struct RefParamPartialOrderingComparison {
bool ParamIsRvalueRef;
bool ArgIsRvalueRef;
DeductionQualifierComparison Qualifiers;
};
static Sema::TemplateDeductionResult
DeduceTemplateArgumentsByTypeMatch(Sema &S,
TemplateParameterList *TemplateParams,
QualType Param,
QualType Arg,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &
Deduced,
unsigned TDF,
bool PartialOrdering = false,
SmallVectorImpl<RefParamPartialOrderingComparison> *
RefParamComparisons = 0);
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateArgument *Params, unsigned NumParams,
const TemplateArgument *Args, unsigned NumArgs,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
bool NumberOfArgumentsMustMatch = true);
static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) {
while (1) {
if (ImplicitCastExpr *IC = dyn_cast<ImplicitCastExpr>(E))
E = IC->getSubExpr();
else if (SubstNonTypeTemplateParmExpr *Subst =
dyn_cast<SubstNonTypeTemplateParmExpr>(E))
E = Subst->getReplacement();
else
break;
}
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
return dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
return 0;
}
static bool isSameDeclaration(Decl *X, Decl *Y) {
if (NamedDecl *NX = dyn_cast<NamedDecl>(X))
X = NX->getUnderlyingDecl();
if (NamedDecl *NY = dyn_cast<NamedDecl>(Y))
Y = NY->getUnderlyingDecl();
return X->getCanonicalDecl() == Y->getCanonicalDecl();
}
static DeducedTemplateArgument
checkDeducedTemplateArguments(ASTContext &Context,
const DeducedTemplateArgument &X,
const DeducedTemplateArgument &Y) {
if (X.isNull())
return Y;
if (Y.isNull())
return X;
switch (X.getKind()) {
case TemplateArgument::Null:
llvm_unreachable("Non-deduced template arguments handled above");
case TemplateArgument::Type:
if (Y.getKind() == TemplateArgument::Type &&
Context.hasSameType(X.getAsType(), Y.getAsType()))
return X;
return DeducedTemplateArgument();
case TemplateArgument::Integral:
if (Y.getKind() == TemplateArgument::Expression ||
Y.getKind() == TemplateArgument::Declaration ||
(Y.getKind() == TemplateArgument::Integral &&
hasSameExtendedValue(X.getAsIntegral(), Y.getAsIntegral())))
return DeducedTemplateArgument(X,
X.wasDeducedFromArrayBound() &&
Y.wasDeducedFromArrayBound());
return DeducedTemplateArgument();
case TemplateArgument::Template:
if (Y.getKind() == TemplateArgument::Template &&
Context.hasSameTemplateName(X.getAsTemplate(), Y.getAsTemplate()))
return X;
return DeducedTemplateArgument();
case TemplateArgument::TemplateExpansion:
if (Y.getKind() == TemplateArgument::TemplateExpansion &&
Context.hasSameTemplateName(X.getAsTemplateOrTemplatePattern(),
Y.getAsTemplateOrTemplatePattern()))
return X;
return DeducedTemplateArgument();
case TemplateArgument::Expression:
if (Y.getKind() == TemplateArgument::Integral ||
Y.getKind() == TemplateArgument::Declaration)
return DeducedTemplateArgument(Y, X.wasDeducedFromArrayBound() &&
Y.wasDeducedFromArrayBound());
if (Y.getKind() == TemplateArgument::Expression) {
llvm::FoldingSetNodeID ID1, ID2;
X.getAsExpr()->Profile(ID1, Context, true);
Y.getAsExpr()->Profile(ID2, Context, true);
if (ID1 == ID2)
return X;
}
return DeducedTemplateArgument();
case TemplateArgument::Declaration:
if (Y.getKind() == TemplateArgument::Expression)
return X;
if (Y.getKind() == TemplateArgument::Integral)
return Y;
if (Y.getKind() == TemplateArgument::Declaration &&
isSameDeclaration(X.getAsDecl(), Y.getAsDecl()) &&
X.isDeclForReferenceParam() == Y.isDeclForReferenceParam())
return X;
return DeducedTemplateArgument();
case TemplateArgument::NullPtr:
if (Y.getKind() == TemplateArgument::Expression)
return X;
if (Y.getKind() == TemplateArgument::Integral)
return Y;
if (Y.getKind() == TemplateArgument::NullPtr &&
Context.hasSameType(X.getNullPtrType(), Y.getNullPtrType()))
return X;
return DeducedTemplateArgument();
case TemplateArgument::Pack:
if (Y.getKind() != TemplateArgument::Pack ||
X.pack_size() != Y.pack_size())
return DeducedTemplateArgument();
for (TemplateArgument::pack_iterator XA = X.pack_begin(),
XAEnd = X.pack_end(),
YA = Y.pack_begin();
XA != XAEnd; ++XA, ++YA) {
if (checkDeducedTemplateArguments(Context,
DeducedTemplateArgument(*XA, X.wasDeducedFromArrayBound()),
DeducedTemplateArgument(*YA, Y.wasDeducedFromArrayBound()))
.isNull())
return DeducedTemplateArgument();
}
return X;
}
llvm_unreachable("Invalid TemplateArgument Kind!");
}
static Sema::TemplateDeductionResult
DeduceNonTypeTemplateArgument(Sema &S,
NonTypeTemplateParmDecl *NTTP,
llvm::APSInt Value, QualType ValueType,
bool DeducedFromArrayBound,
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);
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,
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,
NonTypeTemplateParmDecl *NTTP,
ValueDecl *D,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument with depth > 0");
D = D ? cast<ValueDecl>(D->getCanonicalDecl()) : 0;
TemplateArgument New(D, NTTP->getType()->isReferenceType());
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;
}
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
TemplateName Param,
TemplateName Arg,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
TemplateDecl *ParamDecl = Param.getAsTemplateDecl();
if (!ParamDecl) {
return Sema::TDK_Success;
}
if (TemplateTemplateParmDecl *TempParam
= dyn_cast<TemplateTemplateParmDecl>(ParamDecl)) {
DeducedTemplateArgument NewDeduced(S.Context.getCanonicalTemplateName(Arg));
DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
Deduced[TempParam->getIndex()],
NewDeduced);
if (Result.isNull()) {
Info.Param = TempParam;
Info.FirstArg = Deduced[TempParam->getIndex()];
Info.SecondArg = NewDeduced;
return Sema::TDK_Inconsistent;
}
Deduced[TempParam->getIndex()] = Result;
return Sema::TDK_Success;
}
if (S.Context.hasSameTemplateName(Param, Arg))
return Sema::TDK_Success;
Info.FirstArg = TemplateArgument(Param);
Info.SecondArg = TemplateArgument(Arg);
return Sema::TDK_NonDeducedMismatch;
}
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateSpecializationType *Param,
QualType Arg,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
assert(Arg.isCanonical() && "Argument type must be canonical");
if (const TemplateSpecializationType *SpecArg
= dyn_cast<TemplateSpecializationType>(Arg)) {
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArguments(S, TemplateParams,
Param->getTemplateName(),
SpecArg->getTemplateName(),
Info, Deduced))
return Result;
return DeduceTemplateArguments(S, TemplateParams,
Param->getArgs(), Param->getNumArgs(),
SpecArg->getArgs(), SpecArg->getNumArgs(),
Info, Deduced,
false);
}
const RecordType *RecordArg = dyn_cast<RecordType>(Arg);
if (!RecordArg)
return Sema::TDK_NonDeducedMismatch;
ClassTemplateSpecializationDecl *SpecArg
= dyn_cast<ClassTemplateSpecializationDecl>(RecordArg->getDecl());
if (!SpecArg)
return Sema::TDK_NonDeducedMismatch;
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArguments(S,
TemplateParams,
Param->getTemplateName(),
TemplateName(SpecArg->getSpecializedTemplate()),
Info, Deduced))
return Result;
return DeduceTemplateArguments(S, TemplateParams,
Param->getArgs(), Param->getNumArgs(),
SpecArg->getTemplateArgs().data(),
SpecArg->getTemplateArgs().size(),
Info, Deduced);
}
static bool IsPossiblyOpaquelyQualifiedType(QualType T) {
switch (T->getTypeClass()) {
case Type::TypeOfExpr:
case Type::TypeOf:
case Type::DependentName:
case Type::Decltype:
case Type::UnresolvedUsing:
case Type::TemplateTypeParm:
return true;
case Type::ConstantArray:
case Type::IncompleteArray:
case Type::VariableArray:
case Type::DependentSizedArray:
return IsPossiblyOpaquelyQualifiedType(
cast<ArrayType>(T)->getElementType());
default:
return false;
}
}
static std::pair<unsigned, unsigned>
getDepthAndIndex(NamedDecl *ND) {
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
return std::make_pair(TTP->getDepth(), TTP->getIndex());
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
return std::make_pair(TTP->getDepth(), TTP->getIndex());
}
static std::pair<unsigned, unsigned>
getDepthAndIndex(UnexpandedParameterPack UPP) {
if (const TemplateTypeParmType *TTP
= UPP.first.dyn_cast<const TemplateTypeParmType *>())
return std::make_pair(TTP->getDepth(), TTP->getIndex());
return getDepthAndIndex(UPP.first.get<NamedDecl *>());
}
static TemplateParameter makeTemplateParameter(Decl *D) {
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(D))
return TemplateParameter(TTP);
else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D))
return TemplateParameter(NTTP);
return TemplateParameter(cast<TemplateTemplateParmDecl>(D));
}
static void PrepareArgumentPackDeduction(Sema &S,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
ArrayRef<unsigned> PackIndices,
SmallVectorImpl<DeducedTemplateArgument> &SavedPacks,
SmallVectorImpl<
SmallVector<DeducedTemplateArgument, 4> > &NewlyDeducedPacks) {
for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
SavedPacks[I] = Deduced[PackIndices[I]];
Deduced[PackIndices[I]] = TemplateArgument();
if (!S.CurrentInstantiationScope)
continue;
const TemplateArgument *ExplicitArgs;
unsigned NumExplicitArgs;
if (NamedDecl *PartiallySubstitutedPack
= S.CurrentInstantiationScope->getPartiallySubstitutedPack(
&ExplicitArgs,
&NumExplicitArgs)) {
if (getDepthAndIndex(PartiallySubstitutedPack).second == PackIndices[I])
NewlyDeducedPacks[I].append(ExplicitArgs,
ExplicitArgs + NumExplicitArgs);
}
}
}
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) {
for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
if (HasAnyArguments && NewlyDeducedPacks[I].empty()) {
Deduced[PackIndices[I]] = SavedPacks[I];
continue;
}
DeducedTemplateArgument NewPack;
if (NewlyDeducedPacks[I].empty()) {
NewPack = DeducedTemplateArgument(TemplateArgument::getEmptyPack());
} else {
TemplateArgument *ArgumentPack
= new (S.Context) TemplateArgument [NewlyDeducedPacks[I].size()];
std::copy(NewlyDeducedPacks[I].begin(), NewlyDeducedPacks[I].end(),
ArgumentPack);
NewPack
= DeducedTemplateArgument(TemplateArgument(ArgumentPack,
NewlyDeducedPacks[I].size()),
NewlyDeducedPacks[I][0].wasDeducedFromArrayBound());
}
DeducedTemplateArgument Result
= checkDeducedTemplateArguments(S.Context, SavedPacks[I], NewPack);
if (Result.isNull()) {
Info.Param
= makeTemplateParameter(TemplateParams->getParam(PackIndices[I]));
Info.FirstArg = SavedPacks[I];
Info.SecondArg = NewPack;
return Sema::TDK_Inconsistent;
}
Deduced[PackIndices[I]] = Result;
}
return Sema::TDK_Success;
}
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const QualType *Params, unsigned NumParams,
const QualType *Args, unsigned NumArgs,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned TDF,
bool PartialOrdering = false,
SmallVectorImpl<RefParamPartialOrderingComparison> *
RefParamComparisons = 0) {
if (NumParams != NumArgs &&
!(NumParams && isa<PackExpansionType>(Params[NumParams - 1])) &&
!(NumArgs && isa<PackExpansionType>(Args[NumArgs - 1])))
return Sema::TDK_NonDeducedMismatch;
unsigned ArgIdx = 0, ParamIdx = 0;
for (; ParamIdx != NumParams; ++ParamIdx) {
const PackExpansionType *Expansion
= dyn_cast<PackExpansionType>(Params[ParamIdx]);
if (!Expansion) {
if (ArgIdx >= NumArgs)
return Sema::TDK_NonDeducedMismatch;
if (isa<PackExpansionType>(Args[ArgIdx])) {
return Sema::TDK_NonDeducedMismatch;
}
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
Params[ParamIdx], Args[ArgIdx],
Info, Deduced, TDF,
PartialOrdering,
RefParamComparisons))
return Result;
++ArgIdx;
continue;
}
if (ParamIdx + 1 < NumParams)
return Sema::TDK_Success;
SmallVector<unsigned, 2> PackIndices;
QualType Pattern = Expansion->getPattern();
{
llvm::SmallBitVector SawIndices(TemplateParams->size());
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
unsigned Depth, Index;
llvm::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
if (Depth == 0 && !SawIndices[Index]) {
SawIndices[Index] = true;
PackIndices.push_back(Index);
}
}
}
assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2>
NewlyDeducedPacks(PackIndices.size());
SmallVector<DeducedTemplateArgument, 2>
SavedPacks(PackIndices.size());
PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks,
NewlyDeducedPacks);
bool HasAnyArguments = false;
for (; ArgIdx < NumArgs; ++ArgIdx) {
HasAnyArguments = true;
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern,
Args[ArgIdx], Info, Deduced,
TDF, PartialOrdering,
RefParamComparisons))
return Result;
for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
DeducedTemplateArgument &DeducedArg = Deduced[PackIndices[I]];
if (!DeducedArg.isNull()) {
NewlyDeducedPacks[I].push_back(DeducedArg);
DeducedArg = DeducedTemplateArgument();
}
}
}
if (Sema::TemplateDeductionResult Result
= FinishArgumentPackDeduction(S, TemplateParams, HasAnyArguments,
Deduced, PackIndices, SavedPacks,
NewlyDeducedPacks, Info))
return Result;
}
if (ArgIdx < NumArgs)
return Sema::TDK_NonDeducedMismatch;
return Sema::TDK_Success;
}
static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType,
QualType ArgType) {
Qualifiers ParamQs = ParamType.getQualifiers();
Qualifiers ArgQs = ArgType.getQualifiers();
if (ParamQs == ArgQs)
return false;
if (ParamQs.getObjCGCAttr() != ArgQs.getObjCGCAttr() &&
ParamQs.hasObjCGCAttr())
return true;
if (ParamQs.getAddressSpace() != ArgQs.getAddressSpace() &&
ParamQs.hasAddressSpace())
return true;
if (ParamQs.getObjCLifetime() != ArgQs.getObjCLifetime() &&
ParamQs.hasObjCLifetime())
return true;
return (ParamQs.getCVRQualifiers() != ArgQs.getCVRQualifiers()) &&
((ParamQs.getCVRQualifiers() | ArgQs.getCVRQualifiers())
== ParamQs.getCVRQualifiers());
}
static Sema::TemplateDeductionResult
DeduceTemplateArgumentsByTypeMatch(Sema &S,
TemplateParameterList *TemplateParams,
QualType ParamIn, QualType ArgIn,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned TDF,
bool PartialOrdering,
SmallVectorImpl<RefParamPartialOrderingComparison> *
RefParamComparisons) {
QualType Param = S.Context.getCanonicalType(ParamIn);
QualType Arg = S.Context.getCanonicalType(ArgIn);
if (const PackExpansionType *ArgExpansion
= dyn_cast<PackExpansionType>(Arg))
Arg = ArgExpansion->getPattern();
if (PartialOrdering) {
const ReferenceType *ParamRef = Param->getAs<ReferenceType>();
if (ParamRef)
Param = ParamRef->getPointeeType();
const ReferenceType *ArgRef = Arg->getAs<ReferenceType>();
if (ArgRef)
Arg = ArgRef->getPointeeType();
if (RefParamComparisons && ParamRef && ArgRef) {
RefParamPartialOrderingComparison Comparison;
Comparison.ParamIsRvalueRef = ParamRef->getAs<RValueReferenceType>();
Comparison.ArgIsRvalueRef = ArgRef->getAs<RValueReferenceType>();
Comparison.Qualifiers = NeitherMoreQualified;
Qualifiers ParamQuals = Param.getQualifiers();
Qualifiers ArgQuals = Arg.getQualifiers();
if (ParamQuals.isStrictSupersetOf(ArgQuals))
Comparison.Qualifiers = ParamMoreQualified;
else if (ArgQuals.isStrictSupersetOf(ParamQuals))
Comparison.Qualifiers = ArgMoreQualified;
RefParamComparisons->push_back(Comparison);
}
Param = Param.getUnqualifiedType();
Arg = Arg.getUnqualifiedType();
} else {
if (TDF & TDF_ParamWithReferenceType) {
Qualifiers Quals;
QualType UnqualParam = S.Context.getUnqualifiedArrayType(Param, Quals);
Quals.setCVRQualifiers(Quals.getCVRQualifiers() &
Arg.getCVRQualifiers());
Param = S.Context.getQualifiedType(UnqualParam, Quals);
}
if ((TDF & TDF_TopLevelParameterTypeList) && !Param->isFunctionType()) {
TDF &= ~TDF_TopLevelParameterTypeList;
if (const RValueReferenceType *ParamRef
= Param->getAs<RValueReferenceType>()) {
if (isa<TemplateTypeParmType>(ParamRef->getPointeeType()) &&
!ParamRef->getPointeeType().getQualifiers())
if (Arg->isLValueReferenceType())
Param = ParamRef->getPointeeType();
}
}
}
if (const TemplateTypeParmType *TemplateTypeParm
= Param->getAs<TemplateTypeParmType>()) {
if (Arg->isPlaceholderType())
return Sema::TDK_Success;
unsigned Index = TemplateTypeParm->getIndex();
bool RecanonicalizeArg = false;
if (isa<ArrayType>(Arg)) {
Qualifiers Quals;
Arg = S.Context.getUnqualifiedArrayType(Arg, Quals);
if (Quals) {
Arg = S.Context.getQualifiedType(Arg, Quals);
RecanonicalizeArg = true;
}
}
if (!(TDF & TDF_IgnoreQualifiers) &&
hasInconsistentOrSupersetQualifiersOf(Param, Arg)) {
Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
Info.FirstArg = TemplateArgument(Param);
Info.SecondArg = TemplateArgument(Arg);
return Sema::TDK_Underqualified;
}
assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0");
assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function");
QualType DeducedType = Arg;
Qualifiers DeducedQs = DeducedType.getQualifiers();
Qualifiers ParamQs = Param.getQualifiers();
DeducedQs.removeCVRQualifiers(ParamQs.getCVRQualifiers());
if (ParamQs.hasObjCGCAttr())
DeducedQs.removeObjCGCAttr();
if (ParamQs.hasAddressSpace())
DeducedQs.removeAddressSpace();
if (ParamQs.hasObjCLifetime())
DeducedQs.removeObjCLifetime();
if (ParamQs.hasObjCLifetime() && !DeducedType->isObjCLifetimeType() &&
!DeducedType->isDependentType()) {
Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
Info.FirstArg = TemplateArgument(Param);
Info.SecondArg = TemplateArgument(Arg);
return Sema::TDK_Underqualified;
}
if (S.getLangOpts().ObjCAutoRefCount &&
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 Result = checkDeducedTemplateArguments(S.Context,
Deduced[Index],
NewDeduced);
if (Result.isNull()) {
Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
Info.FirstArg = Deduced[Index];
Info.SecondArg = NewDeduced;
return Sema::TDK_Inconsistent;
}
Deduced[Index] = Result;
return Sema::TDK_Success;
}
Info.FirstArg = TemplateArgument(ParamIn);
Info.SecondArg = TemplateArgument(ArgIn);
if (isa<SubstTemplateTypeParmPackType>(Param))
return Sema::TDK_Success;
if (!(TDF & TDF_IgnoreQualifiers)) {
if (TDF & TDF_ParamWithReferenceType) {
if (hasInconsistentOrSupersetQualifiersOf(Param, Arg))
return Sema::TDK_NonDeducedMismatch;
} else if (!IsPossiblyOpaquelyQualifiedType(Param)) {
if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
return Sema::TDK_NonDeducedMismatch;
}
if (!Param->isDependentType()) {
if (!(TDF & TDF_SkipNonDependent) && Param != Arg)
return Sema::TDK_NonDeducedMismatch;
return Sema::TDK_Success;
}
} else if (!Param->isDependentType() &&
Param.getUnqualifiedType() == Arg.getUnqualifiedType()) {
return Sema::TDK_Success;
}
switch (Param->getTypeClass()) {
#define NON_CANONICAL_TYPE(Class, Base) \
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");
case Type::Builtin:
case Type::VariableArray:
case Type::Vector:
case Type::FunctionNoProto:
case Type::Record:
case Type::Enum:
case Type::ObjCObject:
case Type::ObjCInterface:
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;
}
case Type::Complex:
if (const ComplexType *ComplexArg = Arg->getAs<ComplexType>())
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
cast<ComplexType>(Param)->getElementType(),
ComplexArg->getElementType(),
Info, Deduced, TDF);
return Sema::TDK_NonDeducedMismatch;
case Type::Atomic:
if (const AtomicType *AtomicArg = Arg->getAs<AtomicType>())
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
cast<AtomicType>(Param)->getValueType(),
AtomicArg->getValueType(),
Info, Deduced, TDF);
return Sema::TDK_NonDeducedMismatch;
case Type::Pointer: {
QualType PointeeType;
if (const PointerType *PointerArg = Arg->getAs<PointerType>()) {
PointeeType = PointerArg->getPointeeType();
} else if (const ObjCObjectPointerType *PointerArg
= Arg->getAs<ObjCObjectPointerType>()) {
PointeeType = PointerArg->getPointeeType();
} else {
return Sema::TDK_NonDeducedMismatch;
}
unsigned SubTDF = TDF & (TDF_IgnoreQualifiers | TDF_DerivedClass);
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
cast<PointerType>(Param)->getPointeeType(),
PointeeType,
Info, Deduced, SubTDF);
}
case Type::LValueReference: {
const LValueReferenceType *ReferenceArg = Arg->getAs<LValueReferenceType>();
if (!ReferenceArg)
return Sema::TDK_NonDeducedMismatch;
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
cast<LValueReferenceType>(Param)->getPointeeType(),
ReferenceArg->getPointeeType(), Info, Deduced, 0);
}
case Type::RValueReference: {
const RValueReferenceType *ReferenceArg = Arg->getAs<RValueReferenceType>();
if (!ReferenceArg)
return Sema::TDK_NonDeducedMismatch;
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
cast<RValueReferenceType>(Param)->getPointeeType(),
ReferenceArg->getPointeeType(),
Info, Deduced, 0);
}
case Type::IncompleteArray: {
const IncompleteArrayType *IncompleteArrayArg =
S.Context.getAsIncompleteArrayType(Arg);
if (!IncompleteArrayArg)
return Sema::TDK_NonDeducedMismatch;
unsigned SubTDF = TDF & TDF_IgnoreQualifiers;
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
S.Context.getAsIncompleteArrayType(Param)->getElementType(),
IncompleteArrayArg->getElementType(),
Info, Deduced, SubTDF);
}
case Type::ConstantArray: {
const ConstantArrayType *ConstantArrayArg =
S.Context.getAsConstantArrayType(Arg);
if (!ConstantArrayArg)
return Sema::TDK_NonDeducedMismatch;
const ConstantArrayType *ConstantArrayParm =
S.Context.getAsConstantArrayType(Param);
if (ConstantArrayArg->getSize() != ConstantArrayParm->getSize())
return Sema::TDK_NonDeducedMismatch;
unsigned SubTDF = TDF & TDF_IgnoreQualifiers;
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
ConstantArrayParm->getElementType(),
ConstantArrayArg->getElementType(),
Info, Deduced, SubTDF);
}
case Type::DependentSizedArray: {
const ArrayType *ArrayArg = S.Context.getAsArrayType(Arg);
if (!ArrayArg)
return Sema::TDK_NonDeducedMismatch;
unsigned SubTDF = TDF & TDF_IgnoreQualifiers;
const DependentSizedArrayType *DependentArrayParm
= S.Context.getAsDependentSizedArrayType(Param);
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
DependentArrayParm->getElementType(),
ArrayArg->getElementType(),
Info, Deduced, SubTDF))
return Result;
NonTypeTemplateParmDecl *NTTP
= getDeducedParameterFromExpr(DependentArrayParm->getSizeExpr());
if (!NTTP)
return Sema::TDK_Success;
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument at depth > 0");
if (const ConstantArrayType *ConstantArrayArg
= dyn_cast<ConstantArrayType>(ArrayArg)) {
llvm::APSInt Size(ConstantArrayArg->getSize());
return DeduceNonTypeTemplateArgument(S, NTTP, Size,
S.Context.getSizeType(),
true,
Info, Deduced);
}
if (const DependentSizedArrayType *DependentArrayArg
= dyn_cast<DependentSizedArrayType>(ArrayArg))
if (DependentArrayArg->getSizeExpr())
return DeduceNonTypeTemplateArgument(S, NTTP,
DependentArrayArg->getSizeExpr(),
Info, Deduced);
return Sema::TDK_NonDeducedMismatch;
}
case Type::FunctionProto: {
unsigned SubTDF = TDF & TDF_TopLevelParameterTypeList;
const FunctionProtoType *FunctionProtoArg =
dyn_cast<FunctionProtoType>(Arg);
if (!FunctionProtoArg)
return Sema::TDK_NonDeducedMismatch;
const FunctionProtoType *FunctionProtoParam =
cast<FunctionProtoType>(Param);
if (FunctionProtoParam->getTypeQuals()
!= FunctionProtoArg->getTypeQuals() ||
FunctionProtoParam->getRefQualifier()
!= FunctionProtoArg->getRefQualifier() ||
FunctionProtoParam->isVariadic() != FunctionProtoArg->isVariadic())
return Sema::TDK_NonDeducedMismatch;
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
FunctionProtoParam->getResultType(),
FunctionProtoArg->getResultType(),
Info, Deduced, 0))
return Result;
return DeduceTemplateArguments(S, TemplateParams,
FunctionProtoParam->arg_type_begin(),
FunctionProtoParam->getNumArgs(),
FunctionProtoArg->arg_type_begin(),
FunctionProtoArg->getNumArgs(),
Info, Deduced, SubTDF);
}
case Type::InjectedClassName: {
Param = cast<InjectedClassNameType>(Param)
->getInjectedSpecializationType();
assert(isa<TemplateSpecializationType>(Param) &&
"injected class name is not a template specialization type");
}
case Type::TemplateSpecialization: {
const TemplateSpecializationType *SpecParam
= cast<TemplateSpecializationType>(Param);
Sema::TemplateDeductionResult Result
= DeduceTemplateArguments(S, TemplateParams, SpecParam, Arg,
Info, Deduced);
if (Result && (TDF & TDF_DerivedClass)) {
if (const RecordType *RecordT = Arg->getAs<RecordType>()) {
if (S.RequireCompleteType(Info.getLocation(), Arg, 0))
return Result;
llvm::SmallPtrSet<const RecordType *, 8> Visited;
SmallVector<const RecordType *, 8> ToVisit;
ToVisit.push_back(RecordT);
bool Successful = false;
SmallVector<DeducedTemplateArgument, 8> DeducedOrig(Deduced.begin(),
Deduced.end());
while (!ToVisit.empty()) {
const RecordType *NextT = ToVisit.back();
ToVisit.pop_back();
if (!Visited.insert(NextT))
continue;
if (NextT != RecordT) {
Sema::TemplateDeductionResult BaseResult
= DeduceTemplateArguments(S, TemplateParams, SpecParam,
QualType(NextT, 0), Info, Deduced);
if (BaseResult == Sema::TDK_Success) {
Successful = true;
DeducedOrig.clear();
DeducedOrig.append(Deduced.begin(), Deduced.end());
}
else
Deduced = DeducedOrig;
}
CXXRecordDecl *Next = cast<CXXRecordDecl>(NextT->getDecl());
for (CXXRecordDecl::base_class_iterator Base = Next->bases_begin(),
BaseEnd = Next->bases_end();
Base != BaseEnd; ++Base) {
assert(Base->getType()->isRecordType() &&
"Base class that isn't a record?");
ToVisit.push_back(Base->getType()->getAs<RecordType>());
}
}
if (Successful)
return Sema::TDK_Success;
}
}
return Result;
}
case Type::MemberPointer: {
const MemberPointerType *MemPtrParam = cast<MemberPointerType>(Param);
const MemberPointerType *MemPtrArg = dyn_cast<MemberPointerType>(Arg);
if (!MemPtrArg)
return Sema::TDK_NonDeducedMismatch;
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
MemPtrParam->getPointeeType(),
MemPtrArg->getPointeeType(),
Info, Deduced,
TDF & TDF_IgnoreQualifiers))
return Result;
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
QualType(MemPtrParam->getClass(), 0),
QualType(MemPtrArg->getClass(), 0),
Info, Deduced,
TDF & TDF_IgnoreQualifiers);
}
case Type::BlockPointer: {
const BlockPointerType *BlockPtrParam = cast<BlockPointerType>(Param);
const BlockPointerType *BlockPtrArg = dyn_cast<BlockPointerType>(Arg);
if (!BlockPtrArg)
return Sema::TDK_NonDeducedMismatch;
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
BlockPtrParam->getPointeeType(),
BlockPtrArg->getPointeeType(),
Info, Deduced, 0);
}
case Type::ExtVector: {
const ExtVectorType *VectorParam = cast<ExtVectorType>(Param);
if (const ExtVectorType *VectorArg = dyn_cast<ExtVectorType>(Arg)) {
if (VectorParam->getNumElements() != VectorArg->getNumElements())
return Sema::TDK_NonDeducedMismatch;
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
VectorParam->getElementType(),
VectorArg->getElementType(),
Info, Deduced, TDF);
}
if (const DependentSizedExtVectorType *VectorArg
= dyn_cast<DependentSizedExtVectorType>(Arg)) {
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
VectorParam->getElementType(),
VectorArg->getElementType(),
Info, Deduced, TDF);
}
return Sema::TDK_NonDeducedMismatch;
}
case Type::DependentSizedExtVector: {
const DependentSizedExtVectorType *VectorParam
= cast<DependentSizedExtVectorType>(Param);
if (const ExtVectorType *VectorArg = dyn_cast<ExtVectorType>(Arg)) {
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
VectorParam->getElementType(),
VectorArg->getElementType(),
Info, Deduced, TDF))
return Result;
NonTypeTemplateParmDecl *NTTP
= getDeducedParameterFromExpr(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);
}
if (const DependentSizedExtVectorType *VectorArg
= dyn_cast<DependentSizedExtVectorType>(Arg)) {
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
VectorParam->getElementType(),
VectorArg->getElementType(),
Info, Deduced, TDF))
return Result;
NonTypeTemplateParmDecl *NTTP
= getDeducedParameterFromExpr(VectorParam->getSizeExpr());
if (!NTTP)
return Sema::TDK_Success;
return DeduceNonTypeTemplateArgument(S, NTTP, VectorArg->getSizeExpr(),
Info, Deduced);
}
return Sema::TDK_NonDeducedMismatch;
}
case Type::TypeOfExpr:
case Type::TypeOf:
case Type::DependentName:
case Type::UnresolvedUsing:
case Type::Decltype:
case Type::UnaryTransform:
case Type::Auto:
case Type::DependentTemplateSpecialization:
case Type::PackExpansion:
return Sema::TDK_Success;
}
llvm_unreachable("Invalid Type Class!");
}
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateArgument &Param,
TemplateArgument Arg,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
if (Arg.isPackExpansion())
Arg = Arg.getPackExpansionPattern();
switch (Param.getKind()) {
case TemplateArgument::Null:
llvm_unreachable("Null template argument in parameter list");
case TemplateArgument::Type:
if (Arg.getKind() == TemplateArgument::Type)
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
Param.getAsType(),
Arg.getAsType(),
Info, Deduced, 0);
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
case TemplateArgument::Template:
if (Arg.getKind() == TemplateArgument::Template)
return DeduceTemplateArguments(S, TemplateParams,
Param.getAsTemplate(),
Arg.getAsTemplate(), Info, Deduced);
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
case TemplateArgument::TemplateExpansion:
llvm_unreachable("caller should handle pack expansions");
case TemplateArgument::Declaration:
if (Arg.getKind() == TemplateArgument::Declaration &&
isSameDeclaration(Param.getAsDecl(), Arg.getAsDecl()) &&
Param.isDeclForReferenceParam() == Arg.isDeclForReferenceParam())
return Sema::TDK_Success;
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
case TemplateArgument::NullPtr:
if (Arg.getKind() == TemplateArgument::NullPtr &&
S.Context.hasSameType(Param.getNullPtrType(), Arg.getNullPtrType()))
return Sema::TDK_Success;
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
case TemplateArgument::Integral:
if (Arg.getKind() == TemplateArgument::Integral) {
if (hasSameExtendedValue(Param.getAsIntegral(), Arg.getAsIntegral()))
return Sema::TDK_Success;
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
}
if (Arg.getKind() == TemplateArgument::Expression) {
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
}
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
case TemplateArgument::Expression: {
if (NonTypeTemplateParmDecl *NTTP
= getDeducedParameterFromExpr(Param.getAsExpr())) {
if (Arg.getKind() == TemplateArgument::Integral)
return DeduceNonTypeTemplateArgument(S, NTTP,
Arg.getAsIntegral(),
Arg.getIntegralType(),
false,
Info, Deduced);
if (Arg.getKind() == TemplateArgument::Expression)
return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsExpr(),
Info, Deduced);
if (Arg.getKind() == TemplateArgument::Declaration)
return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsDecl(),
Info, Deduced);
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
}
return Sema::TDK_Success;
}
case TemplateArgument::Pack:
llvm_unreachable("Argument packs should be expanded by the caller!");
}
llvm_unreachable("Invalid TemplateArgument Kind!");
}
static bool hasTemplateArgumentForDeduction(const TemplateArgument *&Args,
unsigned &ArgIdx,
unsigned &NumArgs) {
if (ArgIdx == NumArgs)
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();
ArgIdx = 0;
return ArgIdx < NumArgs;
}
static bool hasPackExpansionBeforeEnd(const TemplateArgument *Args,
unsigned NumArgs) {
unsigned ArgIdx = 0;
while (ArgIdx < NumArgs) {
const TemplateArgument &Arg = Args[ArgIdx];
if (Args[ArgIdx].getKind() == TemplateArgument::Pack) {
Args = Arg.pack_begin();
NumArgs = Arg.pack_size();
ArgIdx = 0;
continue;
}
++ArgIdx;
if (ArgIdx == NumArgs)
return false;
if (Arg.isPackExpansion())
return true;
}
return false;
}
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateArgument *Params, unsigned NumParams,
const TemplateArgument *Args, unsigned NumArgs,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
bool NumberOfArgumentsMustMatch) {
if (hasPackExpansionBeforeEnd(Params, NumParams))
return Sema::TDK_Success;
unsigned ArgIdx = 0, ParamIdx = 0;
for (; hasTemplateArgumentForDeduction(Params, ParamIdx, NumParams);
++ParamIdx) {
if (!Params[ParamIdx].isPackExpansion()) {
if (!hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs))
return NumberOfArgumentsMustMatch? Sema::TDK_NonDeducedMismatch
: Sema::TDK_Success;
if (Args[ArgIdx].isPackExpansion()) {
return Sema::TDK_NonDeducedMismatch;
}
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArguments(S, TemplateParams,
Params[ParamIdx], Args[ArgIdx],
Info, Deduced))
return Result;
++ArgIdx;
continue;
}
TemplateArgument Pattern = Params[ParamIdx].getPackExpansionPattern();
SmallVector<unsigned, 2> PackIndices;
{
llvm::SmallBitVector SawIndices(TemplateParams->size());
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
unsigned Depth, Index;
llvm::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
if (Depth == 0 && !SawIndices[Index]) {
SawIndices[Index] = true;
PackIndices.push_back(Index);
}
}
}
assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
SmallVector<DeducedTemplateArgument, 2>
SavedPacks(PackIndices.size());
SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2>
NewlyDeducedPacks(PackIndices.size());
PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks,
NewlyDeducedPacks);
bool HasAnyArguments = false;
while (hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs)) {
HasAnyArguments = true;
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArguments(S, TemplateParams, Pattern, Args[ArgIdx],
Info, Deduced))
return Result;
for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
DeducedTemplateArgument &DeducedArg = Deduced[PackIndices[I]];
if (!DeducedArg.isNull()) {
NewlyDeducedPacks[I].push_back(DeducedArg);
DeducedArg = DeducedTemplateArgument();
}
}
++ArgIdx;
}
if (Sema::TemplateDeductionResult Result
= FinishArgumentPackDeduction(S, TemplateParams, HasAnyArguments,
Deduced, PackIndices, SavedPacks,
NewlyDeducedPacks, Info))
return Result;
}
if (NumberOfArgumentsMustMatch &&
hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs))
return Sema::TDK_NonDeducedMismatch;
return Sema::TDK_Success;
}
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateArgumentList &ParamList,
const TemplateArgumentList &ArgList,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
return DeduceTemplateArguments(S, TemplateParams,
ParamList.data(), ParamList.size(),
ArgList.data(), ArgList.size(),
Info, Deduced);
}
static bool isSameTemplateArg(ASTContext &Context,
const TemplateArgument &X,
const TemplateArgument &Y) {
if (X.getKind() != Y.getKind())
return false;
switch (X.getKind()) {
case TemplateArgument::Null:
llvm_unreachable("Comparing NULL template argument");
case TemplateArgument::Type:
return Context.getCanonicalType(X.getAsType()) ==
Context.getCanonicalType(Y.getAsType());
case TemplateArgument::Declaration:
return isSameDeclaration(X.getAsDecl(), Y.getAsDecl()) &&
X.isDeclForReferenceParam() == Y.isDeclForReferenceParam();
case TemplateArgument::NullPtr:
return Context.hasSameType(X.getNullPtrType(), Y.getNullPtrType());
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
return Context.getCanonicalTemplateName(
X.getAsTemplateOrTemplatePattern()).getAsVoidPointer() ==
Context.getCanonicalTemplateName(
Y.getAsTemplateOrTemplatePattern()).getAsVoidPointer();
case TemplateArgument::Integral:
return X.getAsIntegral() == Y.getAsIntegral();
case TemplateArgument::Expression: {
llvm::FoldingSetNodeID XID, YID;
X.getAsExpr()->Profile(XID, Context, true);
Y.getAsExpr()->Profile(YID, Context, true);
return XID == YID;
}
case TemplateArgument::Pack:
if (X.pack_size() != Y.pack_size())
return false;
for (TemplateArgument::pack_iterator XP = X.pack_begin(),
XPEnd = X.pack_end(),
YP = Y.pack_begin();
XP != XPEnd; ++XP, ++YP)
if (!isSameTemplateArg(Context, *XP, *YP))
return false;
return true;
}
llvm_unreachable("Invalid TemplateArgument Kind!");
}
static TemplateArgumentLoc
getTrivialTemplateArgumentLoc(Sema &S,
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));
case TemplateArgument::Declaration: {
Expr *E
= S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
.takeAs<Expr>();
return TemplateArgumentLoc(TemplateArgument(E), E);
}
case TemplateArgument::NullPtr: {
Expr *E
= S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
.takeAs<Expr>();
return TemplateArgumentLoc(TemplateArgument(NTTPType, true),
E);
}
case TemplateArgument::Integral: {
Expr *E
= S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).takeAs<Expr>();
return TemplateArgumentLoc(TemplateArgument(E), E);
}
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion: {
NestedNameSpecifierLocBuilder Builder;
TemplateName Template = Arg.getAsTemplate();
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
Builder.MakeTrivial(S.Context, DTN->getQualifier(), Loc);
else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
Builder.MakeTrivial(S.Context, QTN->getQualifier(), Loc);
if (Arg.getKind() == TemplateArgument::Template)
return TemplateArgumentLoc(Arg,
Builder.getWithLocInContext(S.Context),
Loc);
return TemplateArgumentLoc(Arg, Builder.getWithLocInContext(S.Context),
Loc, Loc);
}
case TemplateArgument::Expression:
return TemplateArgumentLoc(Arg, Arg.getAsExpr());
case TemplateArgument::Pack:
return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo());
}
llvm_unreachable("Invalid TemplateArgument Kind!");
}
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) {
SmallVector<TemplateArgument, 2> PackedArgsBuilder;
for (TemplateArgument::pack_iterator PA = Arg.pack_begin(),
PAEnd = Arg.pack_end();
PA != PAEnd; ++PA) {
DeducedTemplateArgument InnerArg(*PA);
InnerArg.setDeducedFromArrayBound(Arg.wasDeducedFromArrayBound());
if (ConvertDeducedTemplateArgument(S, Param, InnerArg, Template,
NTTPType, PackedArgsBuilder.size(),
Info, InFunctionTemplate, Output))
return true;
PackedArgsBuilder.push_back(Output.back());
Output.pop_back();
}
Output.push_back(TemplateArgument::CreatePackCopy(S.Context,
PackedArgsBuilder.data(),
PackedArgsBuilder.size()));
return false;
}
TemplateArgumentLoc ArgLoc = getTrivialTemplateArgumentLoc(S, Arg, NTTPType,
Info.getLocation());
return S.CheckTemplateArgument(Param, ArgLoc,
Template,
Template->getLocation(),
Template->getSourceRange().getEnd(),
ArgumentPackIndex,
Output,
InFunctionTemplate
? (Arg.wasDeducedFromArrayBound()
? Sema::CTAK_DeducedFromArrayBound
: Sema::CTAK_Deduced)
: Sema::CTAK_Specified);
}
static Sema::TemplateDeductionResult
FinishTemplateArgumentDeduction(Sema &S,
ClassTemplatePartialSpecializationDecl *Partial,
const TemplateArgumentList &TemplateArgs,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
TemplateDeductionInfo &Info) {
EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
Sema::SFINAETrap Trap(S);
Sema::ContextRAII SavedContext(S, Partial);
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;
}
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);
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);
Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder.data(),
Builder.size()));
return Sema::TDK_SubstitutionFailure;
}
}
TemplateArgumentList *DeducedArgumentList
= TemplateArgumentList::CreateCopy(S.Context, Builder.data(),
Builder.size());
Info.reset(DeducedArgumentList);
LocalInstantiationScope InstScope(S);
ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate();
const TemplateArgumentLoc *PartialTemplateArgs
= Partial->getTemplateArgsAsWritten();
TemplateArgumentListInfo InstArgs;
if (S.Subst(PartialTemplateArgs,
Partial->getNumTemplateArgsAsWritten(),
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(ClassTemplate, Partial->getLocation(),
InstArgs, false, ConvertedInstArgs))
return Sema::TDK_SubstitutionFailure;
TemplateParameterList *TemplateParams
= ClassTemplate->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;
}
Sema::TemplateDeductionResult
Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
const TemplateArgumentList &TemplateArgs,
TemplateDeductionInfo &Info) {
if (Partial->isInvalidDecl())
return TDK_Invalid;
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)
return TDK_InstantiationDepth;
if (Trap.hasErrorOccurred())
return Sema::TDK_SubstitutionFailure;
return ::FinishTemplateArgumentDeduction(*this, Partial, TemplateArgs,
Deduced, Info);
}
static bool isSimpleTemplateIdType(QualType T) {
if (const TemplateSpecializationType *Spec
= T->getAs<TemplateSpecializationType>())
return Spec->getTemplateName().getAsTemplateDecl() != 0;
return false;
}
Sema::TemplateDeductionResult
Sema::SubstituteExplicitTemplateArguments(
FunctionTemplateDecl *FunctionTemplate,
TemplateArgumentListInfo &ExplicitTemplateArgs,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
SmallVectorImpl<QualType> &ParamTypes,
QualType *FunctionType,
TemplateDeductionInfo &Info) {
FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
if (ExplicitTemplateArgs.size() == 0) {
for (FunctionDecl::param_iterator P = Function->param_begin(),
PEnd = Function->param_end();
P != PEnd;
++P)
ParamTypes.push_back((*P)->getType());
if (FunctionType)
*FunctionType = Function->getType();
return TDK_Success;
}
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
SFINAETrap Trap(*this);
SmallVector<TemplateArgument, 4> Builder;
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
FunctionTemplate, DeducedArgs,
ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution,
Info);
if (Inst)
return TDK_InstantiationDepth;
if (CheckTemplateArgumentList(FunctionTemplate,
SourceLocation(),
ExplicitTemplateArgs,
true,
Builder) || Trap.hasErrorOccurred()) {
unsigned Index = Builder.size();
if (Index >= TemplateParams->size())
Index = TemplateParams->size() - 1;
Info.Param = makeTemplateParameter(TemplateParams->getParam(Index));
return TDK_InvalidExplicitArguments;
}
TemplateArgumentList *ExplicitArgumentList
= TemplateArgumentList::CreateCopy(Context, Builder.data(), Builder.size());
Info.reset(ExplicitArgumentList);
ContextRAII SavedContext(*this, FunctionTemplate->getTemplatedDecl());
for (unsigned I = 0, N = Builder.size(); I != N; ++I) {
const TemplateArgument &Arg = Builder[I];
if (Arg.getKind() == TemplateArgument::Pack) {
CurrentInstantiationScope->SetPartiallySubstitutedPack(
TemplateParams->getParam(I),
Arg.pack_begin(),
Arg.pack_size());
break;
}
}
const FunctionProtoType *Proto
= Function->getType()->getAs<FunctionProtoType>();
assert(Proto && "Function template does not have a prototype?");
if (Proto->hasTrailingReturn()) {
if (SubstParmTypes(Function->getLocation(),
Function->param_begin(), Function->getNumParams(),
MultiLevelTemplateArgumentList(*ExplicitArgumentList),
ParamTypes))
return TDK_SubstitutionFailure;
}
QualType ResultType;
{
unsigned ThisTypeQuals = 0;
CXXRecordDecl *ThisContext = 0;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
ThisContext = Method->getParent();
ThisTypeQuals = Method->getTypeQualifiers();
}
CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals,
getLangOpts().CPlusPlus0x);
ResultType = SubstType(Proto->getResultType(),
MultiLevelTemplateArgumentList(*ExplicitArgumentList),
Function->getTypeSpecStartLoc(),
Function->getDeclName());
if (ResultType.isNull() || Trap.hasErrorOccurred())
return TDK_SubstitutionFailure;
}
if (!Proto->hasTrailingReturn() &&
SubstParmTypes(Function->getLocation(),
Function->param_begin(), Function->getNumParams(),
MultiLevelTemplateArgumentList(*ExplicitArgumentList),
ParamTypes))
return TDK_SubstitutionFailure;
if (FunctionType) {
*FunctionType = BuildFunctionType(ResultType,
ParamTypes.data(), ParamTypes.size(),
Proto->isVariadic(),
Proto->hasTrailingReturn(),
Proto->getTypeQuals(),
Proto->getRefQualifier(),
Function->getLocation(),
Function->getDeclName(),
Proto->getExtInfo());
if (FunctionType->isNull() || Trap.hasErrorOccurred())
return TDK_SubstitutionFailure;
}
Deduced.reserve(TemplateParams->size());
for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I) {
const TemplateArgument &Arg = ExplicitArgumentList->get(I);
if (Arg.getKind() == TemplateArgument::Pack)
Deduced.push_back(DeducedTemplateArgument());
else
Deduced.push_back(Arg);
}
return TDK_Success;
}
static bool
CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
QualType DeducedA) {
ASTContext &Context = S.Context;
QualType A = OriginalArg.OriginalArgType;
QualType OriginalParamType = OriginalArg.OriginalParamType;
if (Context.hasSameUnqualifiedType(A, DeducedA))
return false;
if (const ReferenceType *DeducedARef = DeducedA->getAs<ReferenceType>())
DeducedA = DeducedARef->getPointeeType();
if (const ReferenceType *ARef = A->getAs<ReferenceType>())
A = ARef->getPointeeType();
if (const ReferenceType *OriginalParamRef
= OriginalParamType->getAs<ReferenceType>()) {
OriginalParamType = OriginalParamRef->getPointeeType();
Qualifiers AQuals = A.getQualifiers();
Qualifiers DeducedAQuals = DeducedA.getQualifiers();
if (S.getLangOpts().ObjCAutoRefCount &&
DeducedAQuals.getObjCLifetime() == Qualifiers::OCL_Strong &&
AQuals.getObjCLifetime() == Qualifiers::OCL_None) {
AQuals.setObjCLifetime(Qualifiers::OCL_Strong);
}
if (AQuals == DeducedAQuals) {
} else if (!DeducedAQuals.compatiblyIncludes(AQuals)) {
return true;
} else {
A = Context.getQualifiedType(A.getUnqualifiedType(), DeducedAQuals);
}
}
bool ObjCLifetimeConversion = false;
QualType ResultTy;
if ((A->isAnyPointerType() || A->isMemberPointerType()) &&
(S.IsQualificationConversion(A, DeducedA, false,
ObjCLifetimeConversion) ||
S.IsNoReturnConversion(A, DeducedA, ResultTy)))
return false;
if (const PointerType *OriginalParamPtr
= OriginalParamType->getAs<PointerType>()) {
if (const PointerType *DeducedAPtr = DeducedA->getAs<PointerType>()) {
if (const PointerType *APtr = A->getAs<PointerType>()) {
if (A->getPointeeType()->isRecordType()) {
OriginalParamType = OriginalParamPtr->getPointeeType();
DeducedA = DeducedAPtr->getPointeeType();
A = APtr->getPointeeType();
}
}
}
}
if (Context.hasSameUnqualifiedType(A, DeducedA))
return false;
if (A->isRecordType() && isSimpleTemplateIdType(OriginalParamType) &&
S.IsDerivedFrom(A, DeducedA))
return false;
return true;
}
Sema::TemplateDeductionResult
Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned NumExplicitlySpecified,
FunctionDecl *&Specialization,
TemplateDeductionInfo &Info,
SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs) {
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
SFINAETrap Trap(*this);
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
FunctionTemplate, DeducedArgs,
ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
Info);
if (Inst)
return TDK_InstantiationDepth;
ContextRAII SavedContext(*this, FunctionTemplate->getTemplatedDecl());
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) {
Builder.push_back(Deduced[I]);
continue;
}
QualType NTTPType;
if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(Param)) {
NTTPType = NTTP->getType();
if (NTTPType->isDependentType()) {
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
Builder.data(), Builder.size());
NTTPType = SubstType(NTTPType,
MultiLevelTemplateArgumentList(TemplateArgs),
NTTP->getLocation(),
NTTP->getDeclName());
if (NTTPType.isNull()) {
Info.Param = makeTemplateParameter(Param);
Info.reset(TemplateArgumentList::CreateCopy(Context,
Builder.data(),
Builder.size()));
return TDK_SubstitutionFailure;
}
}
}
if (ConvertDeducedTemplateArgument(*this, Param, Deduced[I],
FunctionTemplate, NTTPType, 0, Info,
true, Builder)) {
Info.Param = makeTemplateParameter(Param);
Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(),
Builder.size()));
return TDK_SubstitutionFailure;
}
continue;
}
if (Param->isTemplateParameterPack()) {
const TemplateArgument *ExplicitArgs;
unsigned NumExplicitArgs;
if (CurrentInstantiationScope &&
CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs,
&NumExplicitArgs)
== Param)
Builder.push_back(TemplateArgument(ExplicitArgs, NumExplicitArgs));
else
Builder.push_back(TemplateArgument::getEmptyPack());
continue;
}
TemplateArgumentLoc DefArg
= SubstDefaultTemplateArgumentIfAvailable(FunctionTemplate,
FunctionTemplate->getLocation(),
FunctionTemplate->getSourceRange().getEnd(),
Param,
Builder);
if (DefArg.getArgument().isNull()) {
Info.Param = makeTemplateParameter(
const_cast<NamedDecl *>(TemplateParams->getParam(I)));
return TDK_Incomplete;
}
if (CheckTemplateArgument(Param, DefArg,
FunctionTemplate,
FunctionTemplate->getLocation(),
FunctionTemplate->getSourceRange().getEnd(),
0, Builder,
CTAK_Specified)) {
Info.Param = makeTemplateParameter(
const_cast<NamedDecl *>(TemplateParams->getParam(I)));
Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(),
Builder.size()));
return TDK_SubstitutionFailure;
}
}
TemplateArgumentList *DeducedArgumentList
= TemplateArgumentList::CreateCopy(Context, Builder.data(), Builder.size());
Info.reset(DeducedArgumentList);
DeclContext *Owner = FunctionTemplate->getDeclContext();
if (FunctionTemplate->getFriendObjectKind())
Owner = FunctionTemplate->getLexicalDeclContext();
Specialization = cast_or_null<FunctionDecl>(
SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner,
MultiLevelTemplateArgumentList(*DeducedArgumentList)));
if (!Specialization || Specialization->isInvalidDecl())
return TDK_SubstitutionFailure;
assert(Specialization->getPrimaryTemplate()->getCanonicalDecl() ==
FunctionTemplate->getCanonicalDecl());
if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList &&
!Trap.hasErrorOccurred())
Info.take();
if (Trap.hasErrorOccurred()) {
Specialization->setInvalidDecl(true);
return TDK_SubstitutionFailure;
}
if (OriginalCallArgs) {
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))
return Sema::TDK_SubstitutionFailure;
}
}
if (Info.diag_begin() != Info.diag_end()) {
llvm::DenseMap<Decl *, SmallVector<PartialDiagnosticAt, 1> >::iterator
Pos = SuppressedDiagnostics.find(Specialization->getCanonicalDecl());
if (Pos == SuppressedDiagnostics.end())
SuppressedDiagnostics[Specialization->getCanonicalDecl()]
.append(Info.diag_begin(), Info.diag_end());
}
return TDK_Success;
}
static QualType GetTypeOfFunction(ASTContext &Context,
const OverloadExpr::FindResult &R,
FunctionDecl *Fn) {
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn))
if (Method->isInstance()) {
if (!R.HasFormOfMemberPointer) return QualType();
return Context.getMemberPointerType(Fn->getType(),
Context.getTypeDeclType(Method->getParent()).getTypePtr());
}
if (!R.IsAddressOfOperand) return Fn->getType();
return Context.getPointerType(Fn->getType());
}
static QualType
ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
Expr *Arg, QualType ParamType,
bool ParamWasReference) {
OverloadExpr::FindResult R = OverloadExpr::find(Arg);
OverloadExpr *Ovl = R.Expression;
unsigned TDF = 0;
if (ParamWasReference)
TDF |= TDF_ParamWithReferenceType;
if (R.IsAddressOfOperand)
TDF |= TDF_IgnoreQualifiers;
if (!ParamType->isFunctionType() &&
!ParamType->isFunctionPointerType() &&
!ParamType->isMemberFunctionPointerType()) {
if (Ovl->hasExplicitTemplateArgs()) {
if (FunctionDecl *ExplicitSpec
= S.ResolveSingleFunctionTemplateSpecialization(Ovl))
return GetTypeOfFunction(S.Context, R, ExplicitSpec);
}
return QualType();
}
TemplateArgumentListInfo ExplicitTemplateArgs;
if (Ovl->hasExplicitTemplateArgs())
Ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
QualType Match;
for (UnresolvedSetIterator I = Ovl->decls_begin(),
E = Ovl->decls_end(); I != E; ++I) {
NamedDecl *D = (*I)->getUnderlyingDecl();
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) {
if (!Ovl->hasExplicitTemplateArgs())
return QualType();
FunctionDecl *Specialization = 0;
TemplateDeductionInfo Info(Ovl->getNameLoc());
if (S.DeduceTemplateArguments(FunTmpl, &ExplicitTemplateArgs,
Specialization, Info))
continue;
D = Specialization;
}
FunctionDecl *Fn = cast<FunctionDecl>(D);
QualType ArgType = GetTypeOfFunction(S.Context, R, Fn);
if (ArgType.isNull()) continue;
if (!ParamWasReference && ParamType->isPointerType() &&
ArgType->isFunctionType())
ArgType = S.Context.getPointerType(ArgType);
SmallVector<DeducedTemplateArgument, 8>
Deduced(TemplateParams->size());
TemplateDeductionInfo Info(Ovl->getNameLoc());
Sema::TemplateDeductionResult Result
= DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType,
ArgType, Info, Deduced, TDF);
if (Result) continue;
if (!Match.isNull()) return QualType();
Match = ArgType;
}
return Match;
}
static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
TemplateParameterList *TemplateParams,
QualType &ParamType,
QualType &ArgType,
Expr *Arg,
unsigned &TDF) {
if (ParamType.hasQualifiers())
ParamType = ParamType.getUnqualifiedType();
const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>();
if (ParamRefType) {
QualType PointeeType = ParamRefType->getPointeeType();
if (ArgType->isIncompleteArrayType() && !S.RequireCompleteExprType(Arg, 0))
ArgType = Arg->getType();
if (isa<RValueReferenceType>(ParamType)) {
if (!PointeeType.getQualifiers() &&
isa<TemplateTypeParmType>(PointeeType) &&
Arg->Classify(S.Context).isLValue() &&
Arg->getType() != S.Context.OverloadTy &&
Arg->getType() != S.Context.BoundMemberTy)
ArgType = S.Context.getLValueReferenceType(ArgType);
}
ParamType = PointeeType;
}
if (ArgType == S.Context.OverloadTy) {
ArgType = ResolveOverloadForDeduction(S, TemplateParams,
Arg, ParamType,
ParamRefType != 0);
if (ArgType.isNull())
return true;
}
if (ParamRefType) {
if (ParamRefType->isRValueReferenceType() &&
ParamRefType->getAs<TemplateTypeParmType>() &&
Arg->isLValue())
ArgType = S.Context.getLValueReferenceType(ArgType);
} else {
if (ArgType->isArrayType())
ArgType = S.Context.getArrayDecayedType(ArgType);
else if (ArgType->isFunctionType())
ArgType = S.Context.getPointerType(ArgType);
else {
ArgType = ArgType.getUnqualifiedType();
}
}
TDF = TDF_SkipNonDependent;
if (ParamRefType)
TDF |= TDF_ParamWithReferenceType;
if (ArgType->isPointerType() || ArgType->isMemberPointerType() ||
ArgType->isObjCObjectPointerType())
TDF |= TDF_IgnoreQualifiers;
if (isSimpleTemplateIdType(ParamType) ||
(isa<PointerType>(ParamType) &&
isSimpleTemplateIdType(
ParamType->getAs<PointerType>()->getPointeeType())))
TDF |= TDF_DerivedClass;
return false;
}
static bool hasDeducibleTemplateParameters(Sema &S,
FunctionTemplateDecl *FunctionTemplate,
QualType T);
static Sema::TemplateDeductionResult
DeduceTemplateArgumentByListElement(Sema &S,
TemplateParameterList *TemplateParams,
QualType ParamType, Expr *Arg,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned TDF) {
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) {
QualType X;
if (!S.isStdInitializerList(ParamType.getNonReferenceType(), &X))
return Sema::TDK_Success;
for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
if (Sema::TemplateDeductionResult Result =
DeduceTemplateArgumentByListElement(S, TemplateParams, X,
ILE->getInit(i),
Info, Deduced, TDF))
return Result;
}
return Sema::TDK_Success;
}
QualType ArgType = Arg->getType();
if (AdjustFunctionParmAndArgTypesForDeduction(S, TemplateParams, ParamType,
ArgType, Arg, TDF))
return Sema::TDK_FailedOverloadResolution;
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType,
ArgType, Info, Deduced, TDF);
}
Sema::TemplateDeductionResult
Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
TemplateArgumentListInfo *ExplicitTemplateArgs,
llvm::ArrayRef<Expr *> Args,
FunctionDecl *&Specialization,
TemplateDeductionInfo &Info) {
if (FunctionTemplate->isInvalidDecl())
return TDK_Invalid;
FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
unsigned CheckArgs = Args.size();
if (Args.size() < Function->getMinRequiredArguments())
return TDK_TooFewArguments;
else if (Args.size() > Function->getNumParams()) {
const FunctionProtoType *Proto
= Function->getType()->getAs<FunctionProtoType>();
if (Proto->isTemplateVariadic())
;
else if (Proto->isVariadic())
CheckArgs = Function->getNumParams();
else
return TDK_TooManyArguments;
}
LocalInstantiationScope InstScope(*this);
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
SmallVector<DeducedTemplateArgument, 4> Deduced;
SmallVector<QualType, 4> ParamTypes;
unsigned NumExplicitlySpecified = 0;
if (ExplicitTemplateArgs) {
TemplateDeductionResult Result =
SubstituteExplicitTemplateArguments(FunctionTemplate,
*ExplicitTemplateArgs,
Deduced,
ParamTypes,
0,
Info);
if (Result)
return Result;
NumExplicitlySpecified = Deduced.size();
} else {
for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I)
ParamTypes.push_back(Function->getParamDecl(I)->getType());
}
Deduced.resize(TemplateParams->size());
unsigned ArgIdx = 0;
SmallVector<OriginalCallArg, 4> OriginalCallArgs;
for (unsigned ParamIdx = 0, NumParams = ParamTypes.size();
ParamIdx != NumParams; ++ParamIdx) {
QualType OrigParamType = ParamTypes[ParamIdx];
QualType ParamType = OrigParamType;
const PackExpansionType *ParamExpansion
= dyn_cast<PackExpansionType>(ParamType);
if (!ParamExpansion) {
if (ArgIdx >= CheckArgs)
break;
Expr *Arg = Args[ArgIdx++];
QualType ArgType = Arg->getType();
unsigned TDF = 0;
if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams,
ParamType, ArgType, Arg,
TDF))
continue;
if (!hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType))
continue;
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) {
QualType X;
if (!isStdInitializerList(ParamType, &X))
continue;
for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
if (TemplateDeductionResult Result =
DeduceTemplateArgumentByListElement(*this, TemplateParams, X,
ILE->getInit(i),
Info, Deduced, TDF))
return Result;
}
continue;
}
OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx-1,
ArgType));
if (TemplateDeductionResult Result
= DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
ParamType, ArgType,
Info, Deduced, TDF))
return Result;
continue;
}
if (ParamIdx + 1 < NumParams)
break;
QualType ParamPattern = ParamExpansion->getPattern();
SmallVector<unsigned, 2> PackIndices;
{
llvm::SmallBitVector SawIndices(TemplateParams->size());
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
unsigned Depth, Index;
llvm::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
if (Depth == 0 && !SawIndices[Index]) {
SawIndices[Index] = true;
PackIndices.push_back(Index);
}
}
}
assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2>
NewlyDeducedPacks(PackIndices.size());
SmallVector<DeducedTemplateArgument, 2>
SavedPacks(PackIndices.size());
PrepareArgumentPackDeduction(*this, Deduced, PackIndices, SavedPacks,
NewlyDeducedPacks);
bool HasAnyArguments = false;
for (; ArgIdx < Args.size(); ++ArgIdx) {
HasAnyArguments = true;
QualType OrigParamType = ParamPattern;
ParamType = OrigParamType;
Expr *Arg = Args[ArgIdx];
QualType ArgType = Arg->getType();
unsigned TDF = 0;
if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams,
ParamType, ArgType, Arg,
TDF)) {
++ArgIdx;
break;
}
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) {
QualType X;
if (!isStdInitializerList(ParamType, &X)) {
++ArgIdx;
break;
}
for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
if (TemplateDeductionResult Result =
DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, X,
ILE->getInit(i)->getType(),
Info, Deduced, TDF))
return Result;
}
} else {
if (hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType))
OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx,
ArgType));
if (TemplateDeductionResult Result
= DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
ParamType, ArgType, Info,
Deduced, TDF))
return Result;
}
for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
DeducedTemplateArgument &DeducedArg = Deduced[PackIndices[I]];
if (!DeducedArg.isNull()) {
NewlyDeducedPacks[I].push_back(DeducedArg);
DeducedArg = DeducedTemplateArgument();
}
}
}
if (Sema::TemplateDeductionResult Result
= FinishArgumentPackDeduction(*this, TemplateParams, HasAnyArguments,
Deduced, PackIndices, SavedPacks,
NewlyDeducedPacks, Info))
return Result;
break;
}
return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
NumExplicitlySpecified,
Specialization, Info, &OriginalCallArgs);
}
Sema::TemplateDeductionResult
Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
TemplateArgumentListInfo *ExplicitTemplateArgs,
QualType ArgFunctionType,
FunctionDecl *&Specialization,
TemplateDeductionInfo &Info) {
if (FunctionTemplate->isInvalidDecl())
return TDK_Invalid;
FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
QualType FunctionType = Function->getType();
LocalInstantiationScope InstScope(*this);
SmallVector<DeducedTemplateArgument, 4> Deduced;
unsigned NumExplicitlySpecified = 0;
SmallVector<QualType, 4> ParamTypes;
if (ExplicitTemplateArgs) {
if (TemplateDeductionResult Result
= SubstituteExplicitTemplateArguments(FunctionTemplate,
*ExplicitTemplateArgs,
Deduced, ParamTypes,
&FunctionType, Info))
return Result;
NumExplicitlySpecified = Deduced.size();
}
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
SFINAETrap Trap(*this);
Deduced.resize(TemplateParams->size());
if (!ArgFunctionType.isNull()) {
if (TemplateDeductionResult Result
= DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
FunctionType, ArgFunctionType, Info,
Deduced, TDF_TopLevelParameterTypeList))
return Result;
}
if (TemplateDeductionResult Result
= FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
NumExplicitlySpecified,
Specialization, Info))
return Result;
if (!ArgFunctionType.isNull() &&
!Context.hasSameType(ArgFunctionType, Specialization->getType()))
return TDK_NonDeducedMismatch;
return TDK_Success;
}
Sema::TemplateDeductionResult
Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
QualType ToType,
CXXConversionDecl *&Specialization,
TemplateDeductionInfo &Info) {
if (FunctionTemplate->isInvalidDecl())
return TDK_Invalid;
CXXConversionDecl *Conv
= cast<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl());
QualType FromType = Conv->getConversionType();
QualType P = Context.getCanonicalType(FromType);
QualType A = Context.getCanonicalType(ToType);
if (const ReferenceType *PRef = P->getAs<ReferenceType>())
P = PRef->getPointeeType();
if (const ReferenceType *ARef = A->getAs<ReferenceType>())
A = ARef->getPointeeType().getUnqualifiedType();
else {
assert(!A->isReferenceType() && "Reference types were handled above");
if (P->isArrayType())
P = Context.getArrayDecayedType(P);
else if (P->isFunctionType())
P = Context.getPointerType(P);
else
P = P.getUnqualifiedType();
A = A.getUnqualifiedType();
}
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
SFINAETrap Trap(*this);
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
SmallVector<DeducedTemplateArgument, 4> Deduced;
Deduced.resize(TemplateParams->size());
unsigned TDF = 0;
if (ToType->isReferenceType())
TDF |= TDF_ParamWithReferenceType;
if ((P->isPointerType() && A->isPointerType()) ||
(P->isMemberPointerType() && A->isMemberPointerType()))
TDF |= TDF_IgnoreQualifiers;
if (TemplateDeductionResult Result
= DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
P, A, Info, Deduced, TDF))
return Result;
LocalInstantiationScope InstScope(*this);
FunctionDecl *Spec = 0;
TemplateDeductionResult Result
= FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, 0, Spec,
Info);
Specialization = cast_or_null<CXXConversionDecl>(Spec);
return Result;
}
Sema::TemplateDeductionResult
Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
TemplateArgumentListInfo *ExplicitTemplateArgs,
FunctionDecl *&Specialization,
TemplateDeductionInfo &Info) {
return DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
QualType(), Specialization, Info);
}
namespace {
class SubstituteAutoTransform :
public TreeTransform<SubstituteAutoTransform> {
QualType Replacement;
public:
SubstituteAutoTransform(Sema &SemaRef, QualType Replacement) :
TreeTransform<SubstituteAutoTransform>(SemaRef), Replacement(Replacement) {
}
QualType TransformAutoType(TypeLocBuilder &TLB, AutoTypeLoc TL) {
if (isa<TemplateTypeParmType>(Replacement)) {
QualType Result = Replacement;
TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
return Result;
} else {
QualType Result = RebuildAutoType(Replacement);
AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
return Result;
}
}
ExprResult TransformLambdaExpr(LambdaExpr *E) {
return E;
}
};
bool isDependentAutoType(QualType Ty) {
while (1) {
QualType Pointee = Ty->getPointeeType();
if (!Pointee.isNull()) {
Ty = Pointee;
} else if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()){
if (MPT->getClass()->isDependentType())
return true;
Ty = MPT->getPointeeType();
} else if (const FunctionProtoType *FPT = Ty->getAs<FunctionProtoType>()){
for (FunctionProtoType::arg_type_iterator I = FPT->arg_type_begin(),
E = FPT->arg_type_end();
I != E; ++I)
if ((*I)->isDependentType())
return true;
Ty = FPT->getResultType();
} else if (Ty->isDependentSizedArrayType()) {
return true;
} else if (const ArrayType *AT = Ty->getAsArrayTypeUnsafe()) {
Ty = AT->getElementType();
} else if (Ty->getAs<DependentSizedExtVectorType>()) {
return true;
} else if (const VectorType *VT = Ty->getAs<VectorType>()) {
Ty = VT->getElementType();
} else {
break;
}
}
assert(Ty->getAs<AutoType>() && "didn't find 'auto' in auto type");
return false;
}
}
Sema::DeduceAutoResult
Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init,
TypeSourceInfo *&Result) {
if (Init->getType()->isNonOverloadPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(Init);
if (result.isInvalid()) return DAR_FailedAlreadyDiagnosed;
Init = result.take();
}
if (Init->isTypeDependent() || isDependentAutoType(Type->getType())) {
Result = Type;
return DAR_Succeeded;
}
SourceLocation Loc = Init->getExprLoc();
LocalInstantiationScope InstScope(*this);
TemplateTypeParmDecl *TemplParam =
TemplateTypeParmDecl::Create(Context, 0, SourceLocation(), Loc, 0, 0, 0,
false, false);
QualType TemplArg = QualType(TemplParam->getTypeForDecl(), 0);
NamedDecl *TemplParamPtr = TemplParam;
FixedSizeTemplateParameterList<1> TemplateParams(Loc, Loc, &TemplParamPtr,
Loc);
TypeSourceInfo *FuncParamInfo =
SubstituteAutoTransform(*this, TemplArg).TransformType(Type);
assert(FuncParamInfo && "substituting template parameter for 'auto' failed");
QualType FuncParam = FuncParamInfo->getType();
SmallVector<DeducedTemplateArgument, 1> Deduced;
Deduced.resize(1);
QualType InitType = Init->getType();
unsigned TDF = 0;
TemplateDeductionInfo Info(Loc);
InitListExpr *InitList = dyn_cast<InitListExpr>(Init);
if (InitList) {
for (unsigned i = 0, e = InitList->getNumInits(); i < e; ++i) {
if (DeduceTemplateArgumentByListElement(*this, &TemplateParams,
TemplArg,
InitList->getInit(i),
Info, Deduced, TDF))
return DAR_Failed;
}
} else {
if (AdjustFunctionParmAndArgTypesForDeduction(*this, &TemplateParams,
FuncParam, InitType, Init,
TDF))
return DAR_Failed;
if (DeduceTemplateArgumentsByTypeMatch(*this, &TemplateParams, FuncParam,
InitType, Info, Deduced, TDF))
return DAR_Failed;
}
QualType DeducedType = Deduced[0].getAsType();
if (DeducedType.isNull())
return DAR_Failed;
if (InitList) {
DeducedType = BuildStdInitializerList(DeducedType, Loc);
if (DeducedType.isNull())
return DAR_FailedAlreadyDiagnosed;
}
Result = SubstituteAutoTransform(*this, DeducedType).TransformType(Type);
if (!InitList && Result &&
CheckOriginalCallArgDeduction(*this,
Sema::OriginalCallArg(FuncParam,0,InitType),
Result->getType())) {
Result = 0;
return DAR_Failed;
}
return DAR_Succeeded;
}
void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {
if (isa<InitListExpr>(Init))
Diag(VDecl->getLocation(),
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)
<< VDecl->getDeclName() << VDecl->getType() << Init->getType()
<< Init->getSourceRange();
}
static void
MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
bool OnlyDeduced,
unsigned Level,
llvm::SmallBitVector &Deduced);
static void AddImplicitObjectParameterType(ASTContext &Context,
CXXMethodDecl *Method,
SmallVectorImpl<QualType> &ArgTypes) {
QualType ArgTy = Context.getTypeDeclType(Method->getParent());
ArgTy = Context.getQualifiedType(ArgTy,
Qualifiers::fromCVRMask(Method->getTypeQualifiers()));
if (Method->getRefQualifier() == RQ_RValue)
ArgTy = Context.getRValueReferenceType(ArgTy);
else
ArgTy = Context.getLValueReferenceType(ArgTy);
ArgTypes.push_back(ArgTy);
}
static bool isAtLeastAsSpecializedAs(Sema &S,
SourceLocation Loc,
FunctionTemplateDecl *FT1,
FunctionTemplateDecl *FT2,
TemplatePartialOrderingContext TPOC,
unsigned NumCallArguments,
SmallVectorImpl<RefParamPartialOrderingComparison> *RefParamComparisons) {
FunctionDecl *FD1 = FT1->getTemplatedDecl();
FunctionDecl *FD2 = FT2->getTemplatedDecl();
const FunctionProtoType *Proto1 = FD1->getType()->getAs<FunctionProtoType>();
const FunctionProtoType *Proto2 = FD2->getType()->getAs<FunctionProtoType>();
assert(Proto1 && Proto2 && "Function templates must have prototypes");
TemplateParameterList *TemplateParams = FT2->getTemplateParameters();
SmallVector<DeducedTemplateArgument, 4> Deduced;
Deduced.resize(TemplateParams->size());
TemplateDeductionInfo Info(Loc);
CXXMethodDecl *Method1 = 0;
CXXMethodDecl *Method2 = 0;
bool IsNonStatic2 = false;
bool IsNonStatic1 = false;
unsigned Skip2 = 0;
switch (TPOC) {
case TPOC_Call: {
Method1 = dyn_cast<CXXMethodDecl>(FD1);
Method2 = dyn_cast<CXXMethodDecl>(FD2);
IsNonStatic1 = Method1 && !Method1->isStatic();
IsNonStatic2 = Method2 && !Method2->isStatic();
SmallVector<QualType, 4> Args1;
unsigned Skip1 = !S.getLangOpts().CPlusPlus0x && IsNonStatic2 && !Method1;
if (S.getLangOpts().CPlusPlus0x && IsNonStatic1 && !Method2)
AddImplicitObjectParameterType(S.Context, Method1, Args1);
Args1.insert(Args1.end(),
Proto1->arg_type_begin() + Skip1, Proto1->arg_type_end());
SmallVector<QualType, 4> Args2;
Skip2 = !S.getLangOpts().CPlusPlus0x && IsNonStatic1 && !Method2;
if (S.getLangOpts().CPlusPlus0x && IsNonStatic2 && !Method1)
AddImplicitObjectParameterType(S.Context, Method2, Args2);
Args2.insert(Args2.end(),
Proto2->arg_type_begin() + Skip2, Proto2->arg_type_end());
if (Args1.size() > NumCallArguments)
Args1.resize(NumCallArguments);
if (Args2.size() > NumCallArguments)
Args2.resize(NumCallArguments);
if (DeduceTemplateArguments(S, TemplateParams, Args2.data(), Args2.size(),
Args1.data(), Args1.size(), Info, Deduced,
TDF_None, true,
RefParamComparisons))
return false;
break;
}
case TPOC_Conversion:
if (DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
Proto2->getResultType(),
Proto1->getResultType(),
Info, Deduced, TDF_None,
true,
RefParamComparisons))
return false;
break;
case TPOC_Other:
if (DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
FD2->getType(), FD1->getType(),
Info, Deduced, TDF_None,
true,
RefParamComparisons))
return false;
break;
}
unsigned ArgIdx = 0, NumArgs = Deduced.size();
for (; ArgIdx != NumArgs; ++ArgIdx)
if (Deduced[ArgIdx].isNull())
break;
if (ArgIdx == NumArgs) {
return true;
}
llvm::SmallBitVector UsedParameters(TemplateParams->size());
switch (TPOC) {
case TPOC_Call: {
unsigned NumParams = std::min(NumCallArguments,
std::min(Proto1->getNumArgs(),
Proto2->getNumArgs()));
if (S.getLangOpts().CPlusPlus0x && 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,
TemplateParams->getDepth(),
UsedParameters);
break;
}
case TPOC_Conversion:
::MarkUsedTemplateParameters(S.Context, Proto2->getResultType(), false,
TemplateParams->getDepth(),
UsedParameters);
break;
case TPOC_Other:
::MarkUsedTemplateParameters(S.Context, FD2->getType(), false,
TemplateParams->getDepth(),
UsedParameters);
break;
}
for (; ArgIdx != NumArgs; ++ArgIdx)
if (Deduced[ArgIdx].isNull() && UsedParameters[ArgIdx])
return false;
return true;
}
static bool isVariadicFunctionTemplate(FunctionTemplateDecl *FunTmpl) {
FunctionDecl *Function = FunTmpl->getTemplatedDecl();
unsigned NumParams = Function->getNumParams();
if (NumParams == 0)
return false;
ParmVarDecl *Last = Function->getParamDecl(NumParams - 1);
if (!Last->isParameterPack())
return false;
while (--NumParams > 0) {
if (Function->getParamDecl(NumParams - 1)->isParameterPack())
return false;
}
return true;
}
FunctionTemplateDecl *
Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
FunctionTemplateDecl *FT2,
SourceLocation Loc,
TemplatePartialOrderingContext TPOC,
unsigned NumCallArguments) {
SmallVector<RefParamPartialOrderingComparison, 4> RefParamComparisons;
bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC,
NumCallArguments, 0);
bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC,
NumCallArguments,
&RefParamComparisons);
if (Better1 != Better2) return Better1? FT1 : FT2;
if (!Better1 && !Better2) return 0;
Better1 = false;
Better2 = false;
for (unsigned I = 0, N = RefParamComparisons.size(); I != N; ++I) {
if (!RefParamComparisons[I].ArgIsRvalueRef &&
RefParamComparisons[I].ParamIsRvalueRef) {
Better2 = true;
if (Better1)
return 0;
continue;
} else if (!RefParamComparisons[I].ParamIsRvalueRef &&
RefParamComparisons[I].ArgIsRvalueRef) {
Better1 = true;
if (Better2)
return 0;
continue;
}
switch (RefParamComparisons[I].Qualifiers) {
case NeitherMoreQualified:
break;
case ParamMoreQualified:
Better1 = true;
if (Better2)
return 0;
continue;
case ArgMoreQualified:
Better2 = true;
if (Better1)
return 0;
continue;
}
}
assert(!(Better1 && Better2) && "Should have broken out in the loop above");
if (Better1)
return FT1;
else if (Better2)
return FT2;
bool Variadic1 = isVariadicFunctionTemplate(FT1);
bool Variadic2 = isVariadicFunctionTemplate(FT2);
if (Variadic1 != Variadic2)
return Variadic1? FT2 : FT1;
return 0;
}
static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
if (T1 == T2)
return true;
if (!T1 || !T2)
return false;
return T1->getCanonicalDecl() == T2->getCanonicalDecl();
}
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) {
if (SpecBegin == SpecEnd) {
if (Complain)
Diag(Loc, NoneDiag);
return SpecEnd;
}
if (SpecBegin + 1 == SpecEnd)
return SpecBegin;
UnresolvedSetIterator Best = SpecBegin;
FunctionTemplateDecl *BestTemplate
= cast<FunctionDecl>(*Best)->getPrimaryTemplate();
assert(BestTemplate && "Not a function template specialization?");
for (UnresolvedSetIterator I = SpecBegin + 1; I != SpecEnd; ++I) {
FunctionTemplateDecl *Challenger
= cast<FunctionDecl>(*I)->getPrimaryTemplate();
assert(Challenger && "Not a function template specialization?");
if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
Loc, TPOC, NumCallArguments),
Challenger)) {
Best = I;
BestTemplate = Challenger;
}
}
bool Ambiguous = false;
for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I) {
FunctionTemplateDecl *Challenger
= cast<FunctionDecl>(*I)->getPrimaryTemplate();
if (I != Best &&
!isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
Loc, TPOC, NumCallArguments),
BestTemplate)) {
Ambiguous = true;
break;
}
}
if (!Ambiguous) {
return Best;
}
if (Complain)
Diag(Loc, AmbigDiag);
if (Complain)
for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I) {
PartialDiagnostic PD = CandidateDiag;
PD << getTemplateArgumentBindingsText(
cast<FunctionDecl>(*I)->getPrimaryTemplate()->getTemplateParameters(),
*cast<FunctionDecl>(*I)->getTemplateSpecializationArgs());
if (!TargetType.isNull())
HandleFunctionTypeMismatch(PD, cast<FunctionDecl>(*I)->getType(),
TargetType);
Diag((*I)->getLocation(), PD);
}
return SpecEnd;
}
ClassTemplatePartialSpecializationDecl *
Sema::getMoreSpecializedPartialSpecialization(
ClassTemplatePartialSpecializationDecl *PS1,
ClassTemplatePartialSpecializationDecl *PS2,
SourceLocation Loc) {
SmallVector<DeducedTemplateArgument, 4> Deduced;
TemplateDeductionInfo Info(Loc);
QualType PT1 = PS1->getInjectedSpecializationType();
QualType PT2 = PS2->getInjectedSpecializationType();
Deduced.resize(PS2->getTemplateParameters()->size());
bool Better1 = !DeduceTemplateArgumentsByTypeMatch(*this,
PS2->getTemplateParameters(),
PT2, PT1, Info, Deduced, TDF_None,
true,
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);
}
Deduced.clear();
Deduced.resize(PS1->getTemplateParameters()->size());
bool Better2 = !DeduceTemplateArgumentsByTypeMatch(*this,
PS1->getTemplateParameters(),
PT1, PT2, Info, Deduced, TDF_None,
true,
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;
}
static void
MarkUsedTemplateParameters(ASTContext &Ctx,
const TemplateArgument &TemplateArg,
bool OnlyDeduced,
unsigned Depth,
llvm::SmallBitVector &Used);
static void
MarkUsedTemplateParameters(ASTContext &Ctx,
const Expr *E,
bool OnlyDeduced,
unsigned Depth,
llvm::SmallBitVector &Used) {
if (const PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(E))
E = Expansion->getPattern();
while (1) {
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
E = ICE->getSubExpr();
else if (const SubstNonTypeTemplateParmExpr *Subst =
dyn_cast<SubstNonTypeTemplateParmExpr>(E))
E = Subst->getReplacement();
else
break;
}
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
if (!DRE)
return;
const NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
if (!NTTP)
return;
if (NTTP->getDepth() == Depth)
Used[NTTP->getIndex()] = true;
}
static void
MarkUsedTemplateParameters(ASTContext &Ctx,
NestedNameSpecifier *NNS,
bool OnlyDeduced,
unsigned Depth,
llvm::SmallBitVector &Used) {
if (!NNS)
return;
MarkUsedTemplateParameters(Ctx, NNS->getPrefix(), OnlyDeduced, Depth,
Used);
MarkUsedTemplateParameters(Ctx, QualType(NNS->getAsType(), 0),
OnlyDeduced, Depth, Used);
}
static void
MarkUsedTemplateParameters(ASTContext &Ctx,
TemplateName Name,
bool OnlyDeduced,
unsigned Depth,
llvm::SmallBitVector &Used) {
if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(Template)) {
if (TTP->getDepth() == Depth)
Used[TTP->getIndex()] = true;
}
return;
}
if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName())
MarkUsedTemplateParameters(Ctx, QTN->getQualifier(), OnlyDeduced,
Depth, Used);
if (DependentTemplateName *DTN = Name.getAsDependentTemplateName())
MarkUsedTemplateParameters(Ctx, DTN->getQualifier(), OnlyDeduced,
Depth, Used);
}
static void
MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
bool OnlyDeduced,
unsigned Depth,
llvm::SmallBitVector &Used) {
if (T.isNull())
return;
if (!T->isDependentType())
return;
T = Ctx.getCanonicalType(T);
switch (T->getTypeClass()) {
case Type::Pointer:
MarkUsedTemplateParameters(Ctx,
cast<PointerType>(T)->getPointeeType(),
OnlyDeduced,
Depth,
Used);
break;
case Type::BlockPointer:
MarkUsedTemplateParameters(Ctx,
cast<BlockPointerType>(T)->getPointeeType(),
OnlyDeduced,
Depth,
Used);
break;
case Type::LValueReference:
case Type::RValueReference:
MarkUsedTemplateParameters(Ctx,
cast<ReferenceType>(T)->getPointeeType(),
OnlyDeduced,
Depth,
Used);
break;
case Type::MemberPointer: {
const MemberPointerType *MemPtr = cast<MemberPointerType>(T.getTypePtr());
MarkUsedTemplateParameters(Ctx, MemPtr->getPointeeType(), OnlyDeduced,
Depth, Used);
MarkUsedTemplateParameters(Ctx, QualType(MemPtr->getClass(), 0),
OnlyDeduced, Depth, Used);
break;
}
case Type::DependentSizedArray:
MarkUsedTemplateParameters(Ctx,
cast<DependentSizedArrayType>(T)->getSizeExpr(),
OnlyDeduced, Depth, Used);
case Type::ConstantArray:
case Type::IncompleteArray:
MarkUsedTemplateParameters(Ctx,
cast<ArrayType>(T)->getElementType(),
OnlyDeduced, Depth, Used);
break;
case Type::Vector:
case Type::ExtVector:
MarkUsedTemplateParameters(Ctx,
cast<VectorType>(T)->getElementType(),
OnlyDeduced, Depth, Used);
break;
case Type::DependentSizedExtVector: {
const DependentSizedExtVectorType *VecType
= cast<DependentSizedExtVectorType>(T);
MarkUsedTemplateParameters(Ctx, VecType->getElementType(), OnlyDeduced,
Depth, Used);
MarkUsedTemplateParameters(Ctx, VecType->getSizeExpr(), OnlyDeduced,
Depth, Used);
break;
}
case Type::FunctionProto: {
const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
MarkUsedTemplateParameters(Ctx, Proto->getResultType(), OnlyDeduced,
Depth, Used);
for (unsigned I = 0, N = Proto->getNumArgs(); I != N; ++I)
MarkUsedTemplateParameters(Ctx, Proto->getArgType(I), OnlyDeduced,
Depth, Used);
break;
}
case Type::TemplateTypeParm: {
const TemplateTypeParmType *TTP = cast<TemplateTypeParmType>(T);
if (TTP->getDepth() == Depth)
Used[TTP->getIndex()] = true;
break;
}
case Type::SubstTemplateTypeParmPack: {
const SubstTemplateTypeParmPackType *Subst
= cast<SubstTemplateTypeParmPackType>(T);
MarkUsedTemplateParameters(Ctx,
QualType(Subst->getReplacedParameter(), 0),
OnlyDeduced, Depth, Used);
MarkUsedTemplateParameters(Ctx, Subst->getArgumentPack(),
OnlyDeduced, Depth, Used);
break;
}
case Type::InjectedClassName:
T = cast<InjectedClassNameType>(T)->getInjectedSpecializationType();
case Type::TemplateSpecialization: {
const TemplateSpecializationType *Spec
= cast<TemplateSpecializationType>(T);
MarkUsedTemplateParameters(Ctx, Spec->getTemplateName(), OnlyDeduced,
Depth, Used);
if (OnlyDeduced &&
hasPackExpansionBeforeEnd(Spec->getArgs(), Spec->getNumArgs()))
break;
for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
MarkUsedTemplateParameters(Ctx, Spec->getArg(I), OnlyDeduced, Depth,
Used);
break;
}
case Type::Complex:
if (!OnlyDeduced)
MarkUsedTemplateParameters(Ctx,
cast<ComplexType>(T)->getElementType(),
OnlyDeduced, Depth, Used);
break;
case Type::Atomic:
if (!OnlyDeduced)
MarkUsedTemplateParameters(Ctx,
cast<AtomicType>(T)->getValueType(),
OnlyDeduced, Depth, Used);
break;
case Type::DependentName:
if (!OnlyDeduced)
MarkUsedTemplateParameters(Ctx,
cast<DependentNameType>(T)->getQualifier(),
OnlyDeduced, Depth, Used);
break;
case Type::DependentTemplateSpecialization: {
const DependentTemplateSpecializationType *Spec
= cast<DependentTemplateSpecializationType>(T);
if (!OnlyDeduced)
MarkUsedTemplateParameters(Ctx, Spec->getQualifier(),
OnlyDeduced, Depth, Used);
if (OnlyDeduced &&
hasPackExpansionBeforeEnd(Spec->getArgs(), Spec->getNumArgs()))
break;
for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
MarkUsedTemplateParameters(Ctx, Spec->getArg(I), OnlyDeduced, Depth,
Used);
break;
}
case Type::TypeOf:
if (!OnlyDeduced)
MarkUsedTemplateParameters(Ctx,
cast<TypeOfType>(T)->getUnderlyingType(),
OnlyDeduced, Depth, Used);
break;
case Type::TypeOfExpr:
if (!OnlyDeduced)
MarkUsedTemplateParameters(Ctx,
cast<TypeOfExprType>(T)->getUnderlyingExpr(),
OnlyDeduced, Depth, Used);
break;
case Type::Decltype:
if (!OnlyDeduced)
MarkUsedTemplateParameters(Ctx,
cast<DecltypeType>(T)->getUnderlyingExpr(),
OnlyDeduced, Depth, Used);
break;
case Type::UnaryTransform:
if (!OnlyDeduced)
MarkUsedTemplateParameters(Ctx,
cast<UnaryTransformType>(T)->getUnderlyingType(),
OnlyDeduced, Depth, Used);
break;
case Type::PackExpansion:
MarkUsedTemplateParameters(Ctx,
cast<PackExpansionType>(T)->getPattern(),
OnlyDeduced, Depth, Used);
break;
case Type::Auto:
MarkUsedTemplateParameters(Ctx,
cast<AutoType>(T)->getDeducedType(),
OnlyDeduced, Depth, Used);
case Type::Builtin:
case Type::VariableArray:
case Type::FunctionNoProto:
case Type::Record:
case Type::Enum:
case Type::ObjCInterface:
case Type::ObjCObject:
case Type::ObjCObjectPointer:
case Type::UnresolvedUsing:
#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base)
#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
#include "clang/AST/TypeNodes.def"
break;
}
}
static void
MarkUsedTemplateParameters(ASTContext &Ctx,
const TemplateArgument &TemplateArg,
bool OnlyDeduced,
unsigned Depth,
llvm::SmallBitVector &Used) {
switch (TemplateArg.getKind()) {
case TemplateArgument::Null:
case TemplateArgument::Integral:
case TemplateArgument::Declaration:
break;
case TemplateArgument::NullPtr:
MarkUsedTemplateParameters(Ctx, TemplateArg.getNullPtrType(), OnlyDeduced,
Depth, Used);
break;
case TemplateArgument::Type:
MarkUsedTemplateParameters(Ctx, TemplateArg.getAsType(), OnlyDeduced,
Depth, Used);
break;
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
MarkUsedTemplateParameters(Ctx,
TemplateArg.getAsTemplateOrTemplatePattern(),
OnlyDeduced, Depth, Used);
break;
case TemplateArgument::Expression:
MarkUsedTemplateParameters(Ctx, TemplateArg.getAsExpr(), OnlyDeduced,
Depth, Used);
break;
case TemplateArgument::Pack:
for (TemplateArgument::pack_iterator P = TemplateArg.pack_begin(),
PEnd = TemplateArg.pack_end();
P != PEnd; ++P)
MarkUsedTemplateParameters(Ctx, *P, OnlyDeduced, Depth, Used);
break;
}
}
void
Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
bool OnlyDeduced, unsigned Depth,
llvm::SmallBitVector &Used) {
if (OnlyDeduced &&
hasPackExpansionBeforeEnd(TemplateArgs.data(), TemplateArgs.size()))
return;
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
::MarkUsedTemplateParameters(Context, TemplateArgs[I], OnlyDeduced,
Depth, Used);
}
void
Sema::MarkDeducedTemplateParameters(ASTContext &Ctx,
FunctionTemplateDecl *FunctionTemplate,
llvm::SmallBitVector &Deduced) {
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
Deduced.clear();
Deduced.resize(TemplateParams->size());
FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I)
::MarkUsedTemplateParameters(Ctx, Function->getParamDecl(I)->getType(),
true, TemplateParams->getDepth(), Deduced);
}
bool hasDeducibleTemplateParameters(Sema &S,
FunctionTemplateDecl *FunctionTemplate,
QualType T) {
if (!T->isDependentType())
return false;
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
llvm::SmallBitVector Deduced(TemplateParams->size());
::MarkUsedTemplateParameters(S.Context, T, true, TemplateParams->getDepth(),
Deduced);
return Deduced.any();
}