summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaTemplateDeduction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaTemplateDeduction.cpp')
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp1857
1 files changed, 1428 insertions, 429 deletions
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 5a0578f..b981389 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/Parse/DeclSpec.h"
#include "llvm/Support/Compiler.h"
+#include <algorithm>
namespace clang {
/// \brief Various flags that control template argument deduction.
@@ -38,14 +39,18 @@ namespace clang {
/// \brief Within template argument deduction from a function call,
/// we are matching in a case where we can perform template argument
/// deduction from a template-id of a derived class of the argument type.
- TDF_DerivedClass = 0x04
+ TDF_DerivedClass = 0x04,
+ /// \brief Allow non-dependent types to differ, e.g., when performing
+ /// template argument deduction from a function call where conversions
+ /// may apply.
+ TDF_SkipNonDependent = 0x08
};
}
using namespace clang;
static Sema::TemplateDeductionResult
-DeduceTemplateArguments(ASTContext &Context,
+DeduceTemplateArguments(ASTContext &Context,
TemplateParameterList *TemplateParams,
const TemplateArgument &Param,
const TemplateArgument &Arg,
@@ -58,27 +63,27 @@ DeduceTemplateArguments(ASTContext &Context,
static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) {
if (ImplicitCastExpr *IC = dyn_cast<ImplicitCastExpr>(E))
E = IC->getSubExpr();
-
+
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
return dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
-
+
return 0;
}
-/// \brief Deduce the value of the given non-type template parameter
+/// \brief Deduce the value of the given non-type template parameter
/// from the given constant.
static Sema::TemplateDeductionResult
-DeduceNonTypeTemplateArgument(ASTContext &Context,
- NonTypeTemplateParmDecl *NTTP,
+DeduceNonTypeTemplateArgument(ASTContext &Context,
+ NonTypeTemplateParmDecl *NTTP,
llvm::APSInt Value,
Sema::TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
- assert(NTTP->getDepth() == 0 &&
+ assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument with depth > 0");
-
+
if (Deduced[NTTP->getIndex()].isNull()) {
QualType T = NTTP->getType();
-
+
// FIXME: Make sure we didn't overflow our data type!
unsigned AllowedBits = Context.getTypeSize(T);
if (Value.getBitWidth() != AllowedBits)
@@ -88,10 +93,10 @@ DeduceNonTypeTemplateArgument(ASTContext &Context,
Deduced[NTTP->getIndex()] = TemplateArgument(SourceLocation(), Value, T);
return Sema::TDK_Success;
}
-
+
assert(Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Integral);
-
- // If the template argument was previously deduced to a negative value,
+
+ // If the template argument was previously deduced to a negative value,
// then our deduction fails.
const llvm::APSInt *PrevValuePtr = Deduced[NTTP->getIndex()].getAsIntegral();
if (PrevValuePtr->isNegative()) {
@@ -117,36 +122,47 @@ DeduceNonTypeTemplateArgument(ASTContext &Context,
return Sema::TDK_Success;
}
-/// \brief Deduce the value of the given non-type template parameter
+/// \brief Deduce the value of the given non-type template parameter
/// from the given type- or value-dependent expression.
///
/// \returns true if deduction succeeded, false otherwise.
static Sema::TemplateDeductionResult
-DeduceNonTypeTemplateArgument(ASTContext &Context,
+DeduceNonTypeTemplateArgument(ASTContext &Context,
NonTypeTemplateParmDecl *NTTP,
Expr *Value,
Sema::TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
- assert(NTTP->getDepth() == 0 &&
+ 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.");
-
+
if (Deduced[NTTP->getIndex()].isNull()) {
// FIXME: Clone the Value?
Deduced[NTTP->getIndex()] = TemplateArgument(Value);
return Sema::TDK_Success;
}
-
+
if (Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Integral) {
- // Okay, we deduced a constant in one case and a dependent expression
- // in another case. FIXME: Later, we will check that instantiating the
+ // Okay, we deduced a constant in one case and a dependent expression
+ // in another case. FIXME: Later, we will check that instantiating the
// dependent expression gives us the constant value.
return Sema::TDK_Success;
}
-
- // FIXME: Compare the expressions for equality!
+
+ if (Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Expression) {
+ // Compare the expressions for equality
+ llvm::FoldingSetNodeID ID1, ID2;
+ Deduced[NTTP->getIndex()].getAsExpr()->Profile(ID1, Context, true);
+ Value->Profile(ID2, Context, true);
+ if (ID1 == ID2)
+ return Sema::TDK_Success;
+
+ // FIXME: Fill in argument mismatch information
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
return Sema::TDK_Success;
}
@@ -164,14 +180,14 @@ DeduceTemplateArguments(ASTContext &Context,
TemplateDecl *ParamDecl = Param.getAsTemplateDecl();
TemplateDecl *ArgDecl = Arg.getAsTemplateDecl();
-
+
if (!ParamDecl || !ArgDecl) {
// FIXME: fill in Info.Param/Info.FirstArg
return Sema::TDK_Inconsistent;
}
- ParamDecl = cast<TemplateDecl>(Context.getCanonicalDecl(ParamDecl));
- ArgDecl = cast<TemplateDecl>(Context.getCanonicalDecl(ArgDecl));
+ ParamDecl = cast<TemplateDecl>(ParamDecl->getCanonicalDecl());
+ ArgDecl = cast<TemplateDecl>(ArgDecl->getCanonicalDecl());
if (ParamDecl != ArgDecl) {
// FIXME: fill in Info.Param/Info.FirstArg
return Sema::TDK_Inconsistent;
@@ -180,6 +196,161 @@ DeduceTemplateArguments(ASTContext &Context,
return Sema::TDK_Success;
}
+/// \brief Deduce the template arguments by comparing the template parameter
+/// type (which is a template-id) with the template argument type.
+///
+/// \param Context the AST context in which this deduction occurs.
+///
+/// \param TemplateParams the template parameters that we are deducing
+///
+/// \param Param the parameter type
+///
+/// \param Arg the argument type
+///
+/// \param Info information about the template argument deduction itself
+///
+/// \param Deduced the deduced template arguments
+///
+/// \returns the result of template argument deduction so far. Note that a
+/// "success" result means that template argument deduction has not yet failed,
+/// but it may still fail, later, for other reasons.
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(ASTContext &Context,
+ TemplateParameterList *TemplateParams,
+ const TemplateSpecializationType *Param,
+ QualType Arg,
+ Sema::TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
+ assert(Arg->isCanonical() && "Argument type must be canonical");
+
+ // Check whether the template argument is a dependent template-id.
+ // FIXME: This is untested code; it can be tested when we implement
+ // partial ordering of class template partial specializations.
+ if (const TemplateSpecializationType *SpecArg
+ = dyn_cast<TemplateSpecializationType>(Arg)) {
+ // Perform template argument deduction for the template name.
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(Context,
+ Param->getTemplateName(),
+ SpecArg->getTemplateName(),
+ Info, Deduced))
+ return Result;
+
+ unsigned NumArgs = Param->getNumArgs();
+
+ // FIXME: When one of the template-names refers to a
+ // declaration with default template arguments, do we need to
+ // fill in those default template arguments here? Most likely,
+ // the answer is "yes", but I don't see any references. This
+ // issue may be resolved elsewhere, because we may want to
+ // instantiate default template arguments when we actually write
+ // the template-id.
+ if (SpecArg->getNumArgs() != NumArgs)
+ return Sema::TDK_NonDeducedMismatch;
+
+ // Perform template argument deduction on each template
+ // argument.
+ for (unsigned I = 0; I != NumArgs; ++I)
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(Context, TemplateParams,
+ Param->getArg(I),
+ SpecArg->getArg(I),
+ Info, Deduced))
+ return Result;
+
+ return Sema::TDK_Success;
+ }
+
+ // If the argument type is a class template specialization, we
+ // perform template argument deduction using its template
+ // arguments.
+ 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;
+
+ // Perform template argument deduction for the template name.
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(Context,
+ Param->getTemplateName(),
+ TemplateName(SpecArg->getSpecializedTemplate()),
+ Info, Deduced))
+ return Result;
+
+ // FIXME: Can the # of arguments in the parameter and the argument
+ // differ due to default arguments?
+ unsigned NumArgs = Param->getNumArgs();
+ const TemplateArgumentList &ArgArgs = SpecArg->getTemplateArgs();
+ if (NumArgs != ArgArgs.size())
+ return Sema::TDK_NonDeducedMismatch;
+
+ for (unsigned I = 0; I != NumArgs; ++I)
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(Context, TemplateParams,
+ Param->getArg(I),
+ ArgArgs.get(I),
+ Info, Deduced))
+ return Result;
+
+ return Sema::TDK_Success;
+}
+
+/// \brief Returns a completely-unqualified array type, capturing the
+/// qualifiers in Quals.
+///
+/// \param Context the AST context in which the array type was built.
+///
+/// \param T a canonical type that may be an array type.
+///
+/// \param Quals will receive the full set of qualifiers that were
+/// applied to the element type of the array.
+///
+/// \returns if \p T is an array type, the completely unqualified array type
+/// that corresponds to T. Otherwise, returns T.
+static QualType getUnqualifiedArrayType(ASTContext &Context, QualType T,
+ Qualifiers &Quals) {
+ assert(T->isCanonical() && "Only operates on canonical types");
+ if (!isa<ArrayType>(T)) {
+ Quals = T.getQualifiers();
+ return T.getUnqualifiedType();
+ }
+
+ assert(!T.hasQualifiers() && "canonical array type has qualifiers!");
+
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T)) {
+ QualType Elt = getUnqualifiedArrayType(Context, CAT->getElementType(),
+ Quals);
+ if (Elt == CAT->getElementType())
+ return T;
+
+ return Context.getConstantArrayType(Elt, CAT->getSize(),
+ CAT->getSizeModifier(), 0);
+ }
+
+ if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(T)) {
+ QualType Elt = getUnqualifiedArrayType(Context, IAT->getElementType(),
+ Quals);
+ if (Elt == IAT->getElementType())
+ return T;
+
+ return Context.getIncompleteArrayType(Elt, IAT->getSizeModifier(), 0);
+ }
+
+ const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(T);
+ QualType Elt = getUnqualifiedArrayType(Context, DSAT->getElementType(),
+ Quals);
+ if (Elt == DSAT->getElementType())
+ return T;
+
+ return Context.getDependentSizedArrayType(Elt, DSAT->getSizeExpr()->Retain(),
+ DSAT->getSizeModifier(), 0,
+ SourceRange());
+}
+
/// \brief Deduce the template arguments by comparing the parameter type and
/// the argument type (C++ [temp.deduct.type]).
///
@@ -196,13 +367,13 @@ DeduceTemplateArguments(ASTContext &Context,
/// \param Deduced the deduced template arguments
///
/// \param TDF bitwise OR of the TemplateDeductionFlags bits that describe
-/// how template argument deduction is performed.
+/// how template argument deduction is performed.
///
/// \returns the result of template argument deduction so far. Note that a
/// "success" result means that template argument deduction has not yet failed,
/// but it may still fail, later, for other reasons.
static Sema::TemplateDeductionResult
-DeduceTemplateArguments(ASTContext &Context,
+DeduceTemplateArguments(ASTContext &Context,
TemplateParameterList *TemplateParams,
QualType ParamIn, QualType ArgIn,
Sema::TemplateDeductionInfo &Info,
@@ -215,28 +386,47 @@ DeduceTemplateArguments(ASTContext &Context,
// C++0x [temp.deduct.call]p4 bullet 1:
// - If the original P is a reference type, the deduced A (i.e., the type
- // referred to by the reference) can be more cv-qualified than the
+ // referred to by the reference) can be more cv-qualified than the
// transformed A.
if (TDF & TDF_ParamWithReferenceType) {
- unsigned ExtraQualsOnParam
- = Param.getCVRQualifiers() & ~Arg.getCVRQualifiers();
- Param.setCVRQualifiers(Param.getCVRQualifiers() & ~ExtraQualsOnParam);
+ Qualifiers Quals = Param.getQualifiers();
+ Quals.setCVRQualifiers(Quals.getCVRQualifiers() & Arg.getCVRQualifiers());
+ Param = Context.getQualifiedType(Param.getUnqualifiedType(), Quals);
}
-
+
// If the parameter type is not dependent, there is nothing to deduce.
- if (!Param->isDependentType())
+ if (!Param->isDependentType()) {
+ if (!(TDF & TDF_SkipNonDependent) && Param != Arg) {
+
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
return Sema::TDK_Success;
+ }
// C++ [temp.deduct.type]p9:
- // A template type argument T, a template template argument TT or a
- // template non-type argument i can be deduced if P and A have one of
+ // A template type argument T, a template template argument TT or a
+ // template non-type argument i can be deduced if P and A have one of
// the following forms:
//
// T
// cv-list T
- if (const TemplateTypeParmType *TemplateTypeParm
- = Param->getAsTemplateTypeParmType()) {
+ if (const TemplateTypeParmType *TemplateTypeParm
+ = Param->getAs<TemplateTypeParmType>()) {
unsigned Index = TemplateTypeParm->getIndex();
+ bool RecanonicalizeArg = false;
+
+ // If the argument type is an array type, move the qualifiers up to the
+ // top level, so they can be matched with the qualifiers on the parameter.
+ // FIXME: address spaces, ObjC GC qualifiers
+ if (isa<ArrayType>(Arg)) {
+ Qualifiers Quals;
+ Arg = getUnqualifiedArrayType(Context, Arg, Quals);
+ if (Quals) {
+ Arg = Context.getQualifiedType(Arg, Quals);
+ RecanonicalizeArg = true;
+ }
+ }
// The argument type can not be less qualified than the parameter
// type.
@@ -248,21 +438,23 @@ DeduceTemplateArguments(ASTContext &Context,
}
assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0");
-
- unsigned Quals = Arg.getCVRQualifiers() & ~Param.getCVRQualifiers();
- QualType DeducedType = Arg.getQualifiedType(Quals);
+
+ QualType DeducedType = Arg;
+ DeducedType.removeCVRQualifiers(Param.getCVRQualifiers());
+ if (RecanonicalizeArg)
+ DeducedType = Context.getCanonicalType(DeducedType);
if (Deduced[Index].isNull())
Deduced[Index] = TemplateArgument(SourceLocation(), DeducedType);
else {
- // C++ [temp.deduct.type]p2:
+ // C++ [temp.deduct.type]p2:
// [...] If type deduction cannot be done for any P/A pair, or if for
- // any pair the deduction leads to more than one possible set of
- // deduced values, or if different pairs yield different deduced
- // values, or if any template argument remains neither deduced nor
+ // any pair the deduction leads to more than one possible set of
+ // deduced values, or if different pairs yield different deduced
+ // values, or if any template argument remains neither deduced nor
// explicitly specified, template argument deduction fails.
if (Deduced[Index].getAsType() != DeducedType) {
- Info.Param
+ Info.Param
= cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
Info.FirstArg = Deduced[Index];
Info.SecondArg = TemplateArgument(SourceLocation(), Arg);
@@ -283,7 +475,7 @@ DeduceTemplateArguments(ASTContext &Context,
return Sema::TDK_NonDeducedMismatch;
} else {
if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
- return Sema::TDK_NonDeducedMismatch;
+ return Sema::TDK_NonDeducedMismatch;
}
}
@@ -291,26 +483,26 @@ DeduceTemplateArguments(ASTContext &Context,
// No deduction possible for these types
case Type::Builtin:
return Sema::TDK_NonDeducedMismatch;
-
+
// T *
case Type::Pointer: {
- const PointerType *PointerArg = Arg->getAsPointerType();
+ const PointerType *PointerArg = Arg->getAs<PointerType>();
if (!PointerArg)
return Sema::TDK_NonDeducedMismatch;
-
+
unsigned SubTDF = TDF & (TDF_IgnoreQualifiers | TDF_DerivedClass);
return DeduceTemplateArguments(Context, TemplateParams,
cast<PointerType>(Param)->getPointeeType(),
PointerArg->getPointeeType(),
Info, Deduced, SubTDF);
}
-
+
// T &
case Type::LValueReference: {
- const LValueReferenceType *ReferenceArg = Arg->getAsLValueReferenceType();
+ const LValueReferenceType *ReferenceArg = Arg->getAs<LValueReferenceType>();
if (!ReferenceArg)
return Sema::TDK_NonDeducedMismatch;
-
+
return DeduceTemplateArguments(Context, TemplateParams,
cast<LValueReferenceType>(Param)->getPointeeType(),
ReferenceArg->getPointeeType(),
@@ -319,23 +511,23 @@ DeduceTemplateArguments(ASTContext &Context,
// T && [C++0x]
case Type::RValueReference: {
- const RValueReferenceType *ReferenceArg = Arg->getAsRValueReferenceType();
+ const RValueReferenceType *ReferenceArg = Arg->getAs<RValueReferenceType>();
if (!ReferenceArg)
return Sema::TDK_NonDeducedMismatch;
-
+
return DeduceTemplateArguments(Context, TemplateParams,
cast<RValueReferenceType>(Param)->getPointeeType(),
ReferenceArg->getPointeeType(),
Info, Deduced, 0);
}
-
+
// T [] (implied, but not stated explicitly)
case Type::IncompleteArray: {
- const IncompleteArrayType *IncompleteArrayArg =
+ const IncompleteArrayType *IncompleteArrayArg =
Context.getAsIncompleteArrayType(Arg);
if (!IncompleteArrayArg)
return Sema::TDK_NonDeducedMismatch;
-
+
return DeduceTemplateArguments(Context, TemplateParams,
Context.getAsIncompleteArrayType(Param)->getElementType(),
IncompleteArrayArg->getElementType(),
@@ -344,16 +536,16 @@ DeduceTemplateArguments(ASTContext &Context,
// T [integer-constant]
case Type::ConstantArray: {
- const ConstantArrayType *ConstantArrayArg =
+ const ConstantArrayType *ConstantArrayArg =
Context.getAsConstantArrayType(Arg);
if (!ConstantArrayArg)
return Sema::TDK_NonDeducedMismatch;
-
- const ConstantArrayType *ConstantArrayParm =
+
+ const ConstantArrayType *ConstantArrayParm =
Context.getAsConstantArrayType(Param);
if (ConstantArrayArg->getSize() != ConstantArrayParm->getSize())
return Sema::TDK_NonDeducedMismatch;
-
+
return DeduceTemplateArguments(Context, TemplateParams,
ConstantArrayParm->getElementType(),
ConstantArrayArg->getElementType(),
@@ -365,7 +557,7 @@ DeduceTemplateArguments(ASTContext &Context,
const ArrayType *ArrayArg = dyn_cast<ArrayType>(Arg);
if (!ArrayArg)
return Sema::TDK_NonDeducedMismatch;
-
+
// Check the element type of the arrays
const DependentSizedArrayType *DependentArrayParm
= cast<DependentSizedArrayType>(Param);
@@ -375,18 +567,18 @@ DeduceTemplateArguments(ASTContext &Context,
ArrayArg->getElementType(),
Info, Deduced, 0))
return Result;
-
+
// Determine the array bound is something we can deduce.
- NonTypeTemplateParmDecl *NTTP
+ NonTypeTemplateParmDecl *NTTP
= getDeducedParameterFromExpr(DependentArrayParm->getSizeExpr());
if (!NTTP)
return Sema::TDK_Success;
-
- // We can perform template argument deduction for the given non-type
+
+ // We can perform template argument deduction for the given non-type
// template parameter.
- assert(NTTP->getDepth() == 0 &&
+ assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument at depth > 0");
- if (const ConstantArrayType *ConstantArrayArg
+ if (const ConstantArrayType *ConstantArrayArg
= dyn_cast<ConstantArrayType>(ArrayArg)) {
llvm::APSInt Size(ConstantArrayArg->getSize());
return DeduceNonTypeTemplateArgument(Context, NTTP, Size,
@@ -397,30 +589,30 @@ DeduceTemplateArguments(ASTContext &Context,
return DeduceNonTypeTemplateArgument(Context, NTTP,
DependentArrayArg->getSizeExpr(),
Info, Deduced);
-
+
// Incomplete type does not match a dependently-sized array type
return Sema::TDK_NonDeducedMismatch;
}
-
- // type(*)(T)
- // T(*)()
- // T(*)(T)
+
+ // type(*)(T)
+ // T(*)()
+ // T(*)(T)
case Type::FunctionProto: {
- const FunctionProtoType *FunctionProtoArg =
+ const FunctionProtoType *FunctionProtoArg =
dyn_cast<FunctionProtoType>(Arg);
if (!FunctionProtoArg)
return Sema::TDK_NonDeducedMismatch;
-
- const FunctionProtoType *FunctionProtoParam =
+
+ const FunctionProtoType *FunctionProtoParam =
cast<FunctionProtoType>(Param);
- if (FunctionProtoParam->getTypeQuals() !=
+ if (FunctionProtoParam->getTypeQuals() !=
FunctionProtoArg->getTypeQuals())
return Sema::TDK_NonDeducedMismatch;
-
+
if (FunctionProtoParam->getNumArgs() != FunctionProtoArg->getNumArgs())
return Sema::TDK_NonDeducedMismatch;
-
+
if (FunctionProtoParam->isVariadic() != FunctionProtoArg->isVariadic())
return Sema::TDK_NonDeducedMismatch;
@@ -431,7 +623,7 @@ DeduceTemplateArguments(ASTContext &Context,
FunctionProtoArg->getResultType(),
Info, Deduced, 0))
return Result;
-
+
for (unsigned I = 0, N = FunctionProtoParam->getNumArgs(); I != N; ++I) {
// Check argument types.
if (Sema::TemplateDeductionResult Result
@@ -441,10 +633,10 @@ DeduceTemplateArguments(ASTContext &Context,
Info, Deduced, 0))
return Result;
}
-
+
return Sema::TDK_Success;
}
-
+
// template-name<T> (where template-name refers to a class template)
// template-name<i>
// TT<T> (TODO)
@@ -454,83 +646,69 @@ DeduceTemplateArguments(ASTContext &Context,
const TemplateSpecializationType *SpecParam
= cast<TemplateSpecializationType>(Param);
- // Check whether the template argument is a dependent template-id.
- // FIXME: This is untested code; it can be tested when we implement
- // partial ordering of class template partial specializations.
- if (const TemplateSpecializationType *SpecArg
- = dyn_cast<TemplateSpecializationType>(Arg)) {
- // Perform template argument deduction for the template name.
- if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context,
- SpecParam->getTemplateName(),
- SpecArg->getTemplateName(),
- Info, Deduced))
- return Result;
-
- unsigned NumArgs = SpecParam->getNumArgs();
-
- // FIXME: When one of the template-names refers to a
- // declaration with default template arguments, do we need to
- // fill in those default template arguments here? Most likely,
- // the answer is "yes", but I don't see any references. This
- // issue may be resolved elsewhere, because we may want to
- // instantiate default template arguments when
- if (SpecArg->getNumArgs() != NumArgs)
- return Sema::TDK_NonDeducedMismatch;
-
- // Perform template argument deduction on each template
- // argument.
- for (unsigned I = 0; I != NumArgs; ++I)
- if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams,
- SpecParam->getArg(I),
- SpecArg->getArg(I),
- Info, Deduced))
- return Result;
-
- return Sema::TDK_Success;
- }
-
- // If the argument type is a class template specialization, we
- // perform template argument deduction using its template
- // arguments.
- const RecordType *RecordArg = dyn_cast<RecordType>(Arg);
- if (!RecordArg)
- return Sema::TDK_NonDeducedMismatch;
-
- // FIXME: Check TDF_DerivedClass here. When this flag is set, we need
- // to troll through the base classes of the argument and try matching
- // all of them. Failure to match does not mean that there is a problem,
- // of course.
-
- ClassTemplateSpecializationDecl *SpecArg
- = dyn_cast<ClassTemplateSpecializationDecl>(RecordArg->getDecl());
- if (!SpecArg)
- return Sema::TDK_NonDeducedMismatch;
-
- // Perform template argument deduction for the template name.
- if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context,
- SpecParam->getTemplateName(),
- TemplateName(SpecArg->getSpecializedTemplate()),
- Info, Deduced))
- return Result;
+ // Try to deduce template arguments from the template-id.
+ Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(Context, TemplateParams, SpecParam, Arg,
+ Info, Deduced);
+
+ if (Result && (TDF & TDF_DerivedClass)) {
+ // C++ [temp.deduct.call]p3b3:
+ // If P is a class, and P has the form template-id, then A can be a
+ // derived class of the deduced A. Likewise, if P is a pointer to a
+ // class of the form template-id, A can be a pointer to a derived
+ // class pointed to by the deduced A.
+ //
+ // More importantly:
+ // These alternatives are considered only if type deduction would
+ // otherwise fail.
+ if (const RecordType *RecordT = dyn_cast<RecordType>(Arg)) {
+ // Use data recursion to crawl through the list of base classes.
+ // Visited contains the set of nodes we have already visited, while
+ // ToVisit is our stack of records that we still need to visit.
+ llvm::SmallPtrSet<const RecordType *, 8> Visited;
+ llvm::SmallVector<const RecordType *, 8> ToVisit;
+ ToVisit.push_back(RecordT);
+ bool Successful = false;
+ while (!ToVisit.empty()) {
+ // Retrieve the next class in the inheritance hierarchy.
+ const RecordType *NextT = ToVisit.back();
+ ToVisit.pop_back();
+
+ // If we have already seen this type, skip it.
+ if (!Visited.insert(NextT))
+ continue;
+
+ // If this is a base class, try to perform template argument
+ // deduction from it.
+ if (NextT != RecordT) {
+ Sema::TemplateDeductionResult BaseResult
+ = DeduceTemplateArguments(Context, TemplateParams, SpecParam,
+ QualType(NextT, 0), Info, Deduced);
+
+ // If template argument deduction for this base was successful,
+ // note that we had some success.
+ if (BaseResult == Sema::TDK_Success)
+ Successful = true;
+ }
+
+ // Visit base classes
+ 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;
+ }
- // FIXME: Can the # of arguments in the parameter and the argument differ?
- unsigned NumArgs = SpecParam->getNumArgs();
- const TemplateArgumentList &ArgArgs = SpecArg->getTemplateArgs();
- if (NumArgs != ArgArgs.size())
- return Sema::TDK_NonDeducedMismatch;
+ }
- for (unsigned I = 0; I != NumArgs; ++I)
- if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams,
- SpecParam->getArg(I),
- ArgArgs.get(I),
- Info, Deduced))
- return Result;
-
- return Sema::TDK_Success;
+ return Result;
}
// T type::*
@@ -564,16 +742,16 @@ DeduceTemplateArguments(ASTContext &Context,
// (clang extension)
//
- // type(^)(T)
- // T(^)()
- // T(^)(T)
+ // type(^)(T)
+ // T(^)()
+ // T(^)(T)
case Type::BlockPointer: {
const BlockPointerType *BlockPtrParam = cast<BlockPointerType>(Param);
const BlockPointerType *BlockPtrArg = dyn_cast<BlockPointerType>(Arg);
-
+
if (!BlockPtrArg)
return Sema::TDK_NonDeducedMismatch;
-
+
return DeduceTemplateArguments(Context, TemplateParams,
BlockPtrParam->getPointeeType(),
BlockPtrArg->getPointeeType(), Info,
@@ -595,7 +773,7 @@ DeduceTemplateArguments(ASTContext &Context,
}
static Sema::TemplateDeductionResult
-DeduceTemplateArguments(ASTContext &Context,
+DeduceTemplateArguments(ASTContext &Context,
TemplateParameterList *TemplateParams,
const TemplateArgument &Param,
const TemplateArgument &Arg,
@@ -605,8 +783,8 @@ DeduceTemplateArguments(ASTContext &Context,
case TemplateArgument::Null:
assert(false && "Null template argument in parameter list");
break;
-
- case TemplateArgument::Type:
+
+ case TemplateArgument::Type:
assert(Arg.getKind() == TemplateArgument::Type && "Type/value mismatch");
return DeduceTemplateArguments(Context, TemplateParams, Param.getAsType(),
Arg.getAsType(), Info, Deduced, 0);
@@ -617,7 +795,7 @@ DeduceTemplateArguments(ASTContext &Context,
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
-
+
case TemplateArgument::Integral:
if (Arg.getKind() == TemplateArgument::Integral) {
// FIXME: Zero extension + sign checking here?
@@ -639,25 +817,25 @@ DeduceTemplateArguments(ASTContext &Context,
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
-
+
case TemplateArgument::Expression: {
- if (NonTypeTemplateParmDecl *NTTP
+ if (NonTypeTemplateParmDecl *NTTP
= getDeducedParameterFromExpr(Param.getAsExpr())) {
if (Arg.getKind() == TemplateArgument::Integral)
// FIXME: Sign problems here
- return DeduceNonTypeTemplateArgument(Context, NTTP,
- *Arg.getAsIntegral(),
+ return DeduceNonTypeTemplateArgument(Context, NTTP,
+ *Arg.getAsIntegral(),
Info, Deduced);
if (Arg.getKind() == TemplateArgument::Expression)
return DeduceNonTypeTemplateArgument(Context, NTTP, Arg.getAsExpr(),
Info, Deduced);
-
+
assert(false && "Type/value mismatch");
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
}
-
+
// Can't deduce anything, but that's okay.
return Sema::TDK_Success;
}
@@ -665,11 +843,11 @@ DeduceTemplateArguments(ASTContext &Context,
assert(0 && "FIXME: Implement!");
break;
}
-
+
return Sema::TDK_Success;
}
-static Sema::TemplateDeductionResult
+static Sema::TemplateDeductionResult
DeduceTemplateArguments(ASTContext &Context,
TemplateParameterList *TemplateParams,
const TemplateArgumentList &ParamList,
@@ -680,7 +858,7 @@ DeduceTemplateArguments(ASTContext &Context,
for (unsigned I = 0, N = ParamList.size(); I != N; ++I) {
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArguments(Context, TemplateParams,
- ParamList[I], ArgList[I],
+ ParamList[I], ArgList[I],
Info, Deduced))
return Result;
}
@@ -688,41 +866,41 @@ DeduceTemplateArguments(ASTContext &Context,
}
/// \brief Determine whether two template arguments are the same.
-static bool isSameTemplateArg(ASTContext &Context,
+static bool isSameTemplateArg(ASTContext &Context,
const TemplateArgument &X,
const TemplateArgument &Y) {
if (X.getKind() != Y.getKind())
return false;
-
+
switch (X.getKind()) {
case TemplateArgument::Null:
assert(false && "Comparing NULL template argument");
break;
-
+
case TemplateArgument::Type:
return Context.getCanonicalType(X.getAsType()) ==
Context.getCanonicalType(Y.getAsType());
-
+
case TemplateArgument::Declaration:
- return Context.getCanonicalDecl(X.getAsDecl()) ==
- Context.getCanonicalDecl(Y.getAsDecl());
-
+ return X.getAsDecl()->getCanonicalDecl() ==
+ Y.getAsDecl()->getCanonicalDecl();
+
case TemplateArgument::Integral:
return *X.getAsIntegral() == *Y.getAsIntegral();
-
+
case TemplateArgument::Expression:
// FIXME: We assume that all expressions are distinct, but we should
// really check their canonical forms.
return false;
-
+
case TemplateArgument::Pack:
if (X.pack_size() != Y.pack_size())
return false;
-
- for (TemplateArgument::pack_iterator XP = X.pack_begin(),
- XPEnd = X.pack_end(),
+
+ for (TemplateArgument::pack_iterator XP = X.pack_begin(),
+ XPEnd = X.pack_end(),
YP = Y.pack_begin();
- XP != XPEnd; ++XP, ++YP)
+ XP != XPEnd; ++XP, ++YP)
if (!isSameTemplateArg(Context, *XP, *YP))
return false;
@@ -739,7 +917,7 @@ static TemplateParameter makeTemplateParameter(Decl *D) {
return TemplateParameter(TTP);
else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D))
return TemplateParameter(NTTP);
-
+
return TemplateParameter(cast<TemplateTemplateParmDecl>(D));
}
@@ -759,9 +937,9 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
llvm::SmallVector<TemplateArgument, 4> Deduced;
Deduced.resize(Partial->getTemplateParameters()->size());
if (TemplateDeductionResult Result
- = ::DeduceTemplateArguments(Context,
+ = ::DeduceTemplateArguments(Context,
Partial->getTemplateParameters(),
- Partial->getTemplateArgs(),
+ Partial->getTemplateArgs(),
TemplateArgs, Info, Deduced))
return Result;
@@ -777,11 +955,12 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
Deduced.size());
for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
if (Deduced[I].isNull()) {
- Decl *Param
- = const_cast<Decl *>(Partial->getTemplateParameters()->getParam(I));
+ Decl *Param
+ = const_cast<NamedDecl *>(
+ Partial->getTemplateParameters()->getParam(I));
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
Info.Param = TTP;
- else if (NonTypeTemplateParmDecl *NTTP
+ else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(Param))
Info.Param = NTTP;
else
@@ -793,7 +972,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
}
// Form the template argument list from the deduced template arguments.
- TemplateArgumentList *DeducedArgumentList
+ TemplateArgumentList *DeducedArgumentList
= new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
Info.reset(DeducedArgumentList);
@@ -801,44 +980,45 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
// arguments of the class template partial specialization, and
// verify that the instantiated template arguments are both valid
// and are equivalent to the template arguments originally provided
- // to the class template.
+ // to the class template.
ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate();
const TemplateArgumentList &PartialTemplateArgs = Partial->getTemplateArgs();
for (unsigned I = 0, N = PartialTemplateArgs.flat_size(); I != N; ++I) {
- Decl *Param = const_cast<Decl *>(
+ Decl *Param = const_cast<NamedDecl *>(
ClassTemplate->getTemplateParameters()->getParam(I));
- TemplateArgument InstArg = Instantiate(PartialTemplateArgs[I],
- *DeducedArgumentList);
+ TemplateArgument InstArg
+ = Subst(PartialTemplateArgs[I],
+ MultiLevelTemplateArgumentList(*DeducedArgumentList));
if (InstArg.isNull()) {
Info.Param = makeTemplateParameter(Param);
Info.FirstArg = PartialTemplateArgs[I];
- return TDK_SubstitutionFailure;
+ return TDK_SubstitutionFailure;
}
-
+
if (InstArg.getKind() == TemplateArgument::Expression) {
- // When the argument is an expression, check the expression result
+ // When the argument is an expression, check the expression result
// against the actual template parameter to get down to the canonical
// template argument.
Expr *InstExpr = InstArg.getAsExpr();
- if (NonTypeTemplateParmDecl *NTTP
+ if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(Param)) {
if (CheckTemplateArgument(NTTP, NTTP->getType(), InstExpr, InstArg)) {
Info.Param = makeTemplateParameter(Param);
Info.FirstArg = PartialTemplateArgs[I];
- return TDK_SubstitutionFailure;
+ return TDK_SubstitutionFailure;
}
- } else if (TemplateTemplateParmDecl *TTP
+ } else if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(Param)) {
// FIXME: template template arguments should really resolve to decls
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(InstExpr);
if (!DRE || CheckTemplateArgument(TTP, DRE)) {
Info.Param = makeTemplateParameter(Param);
Info.FirstArg = PartialTemplateArgs[I];
- return TDK_SubstitutionFailure;
+ return TDK_SubstitutionFailure;
}
}
}
-
+
if (!isSameTemplateArg(Context, TemplateArgs[I], InstArg)) {
Info.Param = makeTemplateParameter(Param);
Info.FirstArg = TemplateArgs[I];
@@ -855,27 +1035,244 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
/// \brief Determine whether the given type T is a simple-template-id type.
static bool isSimpleTemplateIdType(QualType T) {
- if (const TemplateSpecializationType *Spec
- = T->getAsTemplateSpecializationType())
+ if (const TemplateSpecializationType *Spec
+ = T->getAs<TemplateSpecializationType>())
return Spec->getTemplateName().getAsTemplateDecl() != 0;
-
+
return false;
}
-
+
+/// \brief Substitute the explicitly-provided template arguments into the
+/// given function template according to C++ [temp.arg.explicit].
+///
+/// \param FunctionTemplate the function template into which the explicit
+/// template arguments will be substituted.
+///
+/// \param ExplicitTemplateArguments the explicitly-specified template
+/// arguments.
+///
+/// \param NumExplicitTemplateArguments the number of explicitly-specified
+/// template arguments in @p ExplicitTemplateArguments. This value may be zero.
+///
+/// \param Deduced the deduced template arguments, which will be populated
+/// with the converted and checked explicit template arguments.
+///
+/// \param ParamTypes will be populated with the instantiated function
+/// parameters.
+///
+/// \param FunctionType if non-NULL, the result type of the function template
+/// will also be instantiated and the pointed-to value will be updated with
+/// the instantiated function type.
+///
+/// \param Info if substitution fails for any reason, this object will be
+/// populated with more information about the failure.
+///
+/// \returns TDK_Success if substitution was successful, or some failure
+/// condition.
+Sema::TemplateDeductionResult
+Sema::SubstituteExplicitTemplateArguments(
+ FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgument *ExplicitTemplateArgs,
+ unsigned NumExplicitTemplateArgs,
+ llvm::SmallVectorImpl<TemplateArgument> &Deduced,
+ llvm::SmallVectorImpl<QualType> &ParamTypes,
+ QualType *FunctionType,
+ TemplateDeductionInfo &Info) {
+ FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
+ TemplateParameterList *TemplateParams
+ = FunctionTemplate->getTemplateParameters();
+
+ if (NumExplicitTemplateArgs == 0) {
+ // No arguments to substitute; just copy over the parameter types and
+ // fill in the function type.
+ 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;
+ }
+
+ // Substitution of the explicit template arguments into a function template
+ /// is a SFINAE context. Trap any errors that might occur.
+ SFINAETrap Trap(*this);
+
+ // C++ [temp.arg.explicit]p3:
+ // Template arguments that are present shall be specified in the
+ // declaration order of their corresponding template-parameters. The
+ // template argument list shall not specify more template-arguments than
+ // there are corresponding template-parameters.
+ TemplateArgumentListBuilder Builder(TemplateParams,
+ NumExplicitTemplateArgs);
+
+ // Enter a new template instantiation context where we check the
+ // explicitly-specified template arguments against this function template,
+ // and then substitute them into the function parameter types.
+ InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
+ FunctionTemplate, Deduced.data(), Deduced.size(),
+ ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution);
+ if (Inst)
+ return TDK_InstantiationDepth;
+
+ if (CheckTemplateArgumentList(FunctionTemplate,
+ SourceLocation(), SourceLocation(),
+ ExplicitTemplateArgs,
+ NumExplicitTemplateArgs,
+ SourceLocation(),
+ true,
+ Builder) || Trap.hasErrorOccurred())
+ return TDK_InvalidExplicitArguments;
+
+ // Form the template argument list from the explicitly-specified
+ // template arguments.
+ TemplateArgumentList *ExplicitArgumentList
+ = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
+ Info.reset(ExplicitArgumentList);
+
+ // Instantiate the types of each of the function parameters given the
+ // explicitly-specified template arguments.
+ for (FunctionDecl::param_iterator P = Function->param_begin(),
+ PEnd = Function->param_end();
+ P != PEnd;
+ ++P) {
+ QualType ParamType
+ = SubstType((*P)->getType(),
+ MultiLevelTemplateArgumentList(*ExplicitArgumentList),
+ (*P)->getLocation(), (*P)->getDeclName());
+ if (ParamType.isNull() || Trap.hasErrorOccurred())
+ return TDK_SubstitutionFailure;
+
+ ParamTypes.push_back(ParamType);
+ }
+
+ // If the caller wants a full function type back, instantiate the return
+ // type and form that function type.
+ if (FunctionType) {
+ // FIXME: exception-specifications?
+ const FunctionProtoType *Proto
+ = Function->getType()->getAs<FunctionProtoType>();
+ assert(Proto && "Function template does not have a prototype?");
+
+ QualType ResultType
+ = SubstType(Proto->getResultType(),
+ MultiLevelTemplateArgumentList(*ExplicitArgumentList),
+ Function->getTypeSpecStartLoc(),
+ Function->getDeclName());
+ if (ResultType.isNull() || Trap.hasErrorOccurred())
+ return TDK_SubstitutionFailure;
+
+ *FunctionType = BuildFunctionType(ResultType,
+ ParamTypes.data(), ParamTypes.size(),
+ Proto->isVariadic(),
+ Proto->getTypeQuals(),
+ Function->getLocation(),
+ Function->getDeclName());
+ if (FunctionType->isNull() || Trap.hasErrorOccurred())
+ return TDK_SubstitutionFailure;
+ }
+
+ // C++ [temp.arg.explicit]p2:
+ // Trailing template arguments that can be deduced (14.8.2) may be
+ // omitted from the list of explicit template-arguments. If all of the
+ // template arguments can be deduced, they may all be omitted; in this
+ // case, the empty template argument list <> itself may also be omitted.
+ //
+ // Take all of the explicitly-specified arguments and put them into the
+ // set of deduced template arguments.
+ Deduced.reserve(TemplateParams->size());
+ for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I)
+ Deduced.push_back(ExplicitArgumentList->get(I));
+
+ return TDK_Success;
+}
+
+/// \brief Finish template argument deduction for a function template,
+/// checking the deduced template arguments for completeness and forming
+/// the function template specialization.
+Sema::TemplateDeductionResult
+Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
+ llvm::SmallVectorImpl<TemplateArgument> &Deduced,
+ FunctionDecl *&Specialization,
+ TemplateDeductionInfo &Info) {
+ TemplateParameterList *TemplateParams
+ = FunctionTemplate->getTemplateParameters();
+
+ // C++ [temp.deduct.type]p2:
+ // [...] or if any template argument remains neither deduced nor
+ // explicitly specified, template argument deduction fails.
+ TemplateArgumentListBuilder Builder(TemplateParams, Deduced.size());
+ for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
+ if (Deduced[I].isNull()) {
+ Info.Param = makeTemplateParameter(
+ const_cast<NamedDecl *>(TemplateParams->getParam(I)));
+ return TDK_Incomplete;
+ }
+
+ Builder.Append(Deduced[I]);
+ }
+
+ // Form the template argument list from the deduced template arguments.
+ TemplateArgumentList *DeducedArgumentList
+ = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
+ Info.reset(DeducedArgumentList);
+
+ // Template argument deduction for function templates in a SFINAE context.
+ // Trap any errors that might occur.
+ SFINAETrap Trap(*this);
+
+ // Enter a new template instantiation context while we instantiate the
+ // actual function declaration.
+ InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
+ FunctionTemplate, Deduced.data(), Deduced.size(),
+ ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution);
+ if (Inst)
+ return TDK_InstantiationDepth;
+
+ // Substitute the deduced template arguments into the function template
+ // declaration to produce the function template specialization.
+ Specialization = cast_or_null<FunctionDecl>(
+ SubstDecl(FunctionTemplate->getTemplatedDecl(),
+ FunctionTemplate->getDeclContext(),
+ MultiLevelTemplateArgumentList(*DeducedArgumentList)));
+ if (!Specialization)
+ return TDK_SubstitutionFailure;
+
+ assert(Specialization->getPrimaryTemplate()->getCanonicalDecl() ==
+ FunctionTemplate->getCanonicalDecl());
+
+ // If the template argument list is owned by the function template
+ // specialization, release it.
+ if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList)
+ Info.take();
+
+ // There may have been an error that did not prevent us from constructing a
+ // declaration. Mark the declaration invalid and return with a substitution
+ // failure.
+ if (Trap.hasErrorOccurred()) {
+ Specialization->setInvalidDecl(true);
+ return TDK_SubstitutionFailure;
+ }
+
+ return TDK_Success;
+}
+
/// \brief Perform template argument deduction from a function call
/// (C++ [temp.deduct.call]).
///
/// \param FunctionTemplate the function template for which we are performing
/// template argument deduction.
///
-/// \param HasExplicitTemplateArgs whether any template arguments were
+/// \param HasExplicitTemplateArgs whether any template arguments were
/// explicitly specified.
///
/// \param ExplicitTemplateArguments when @p HasExplicitTemplateArgs is true,
/// the explicitly-specified template arguments.
///
/// \param NumExplicitTemplateArguments when @p HasExplicitTemplateArgs is true,
-/// the number of explicitly-specified template arguments in
+/// the number of explicitly-specified template arguments in
/// @p ExplicitTemplateArguments. This value may be zero.
///
/// \param Args the function call arguments
@@ -883,7 +1280,7 @@ static bool isSimpleTemplateIdType(QualType T) {
/// \param NumArgs the number of arguments in Args
///
/// \param Specialization if template argument deduction was successful,
-/// this will be set to the function template specialization produced by
+/// this will be set to the function template specialization produced by
/// template argument deduction.
///
/// \param Info the argument will be updated to provide additional information
@@ -908,17 +1305,13 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
if (NumArgs < Function->getMinRequiredArguments())
return TDK_TooFewArguments;
else if (NumArgs > Function->getNumParams()) {
- const FunctionProtoType *Proto
- = Function->getType()->getAsFunctionProtoType();
+ const FunctionProtoType *Proto
+ = Function->getType()->getAs<FunctionProtoType>();
if (!Proto->isVariadic())
return TDK_TooManyArguments;
-
+
CheckArgs = Function->getNumParams();
}
-
- // Template argument deduction for function templates in a SFINAE context.
- // Trap any errors that might occur.
- SFINAETrap Trap(*this);
// The types of the parameters from which we will perform template argument
// deduction.
@@ -927,89 +1320,40 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
llvm::SmallVector<TemplateArgument, 4> Deduced;
llvm::SmallVector<QualType, 4> ParamTypes;
if (NumExplicitTemplateArgs) {
- // C++ [temp.arg.explicit]p3:
- // Template arguments that are present shall be specified in the
- // declaration order of their corresponding template-parameters. The
- // template argument list shall not specify more template-arguments than
- // there are corresponding template-parameters.
- TemplateArgumentListBuilder Builder(TemplateParams,
- NumExplicitTemplateArgs);
-
- // Enter a new template instantiation context where we check the
- // explicitly-specified template arguments against this function template,
- // and then substitute them into the function parameter types.
- InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
- FunctionTemplate, Deduced.data(), Deduced.size(),
- ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution);
- if (Inst)
- return TDK_InstantiationDepth;
-
- if (CheckTemplateArgumentList(FunctionTemplate,
- SourceLocation(), SourceLocation(),
- ExplicitTemplateArgs,
- NumExplicitTemplateArgs,
- SourceLocation(),
- true,
- Builder) || Trap.hasErrorOccurred())
- return TDK_InvalidExplicitArguments;
-
- // Form the template argument list from the explicitly-specified
- // template arguments.
- TemplateArgumentList *ExplicitArgumentList
- = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
- Info.reset(ExplicitArgumentList);
-
- // Instantiate the types of each of the function parameters given the
- // explicitly-specified template arguments.
- for (FunctionDecl::param_iterator P = Function->param_begin(),
- PEnd = Function->param_end();
- P != PEnd;
- ++P) {
- QualType ParamType = InstantiateType((*P)->getType(),
- *ExplicitArgumentList,
- (*P)->getLocation(),
- (*P)->getDeclName());
- if (ParamType.isNull() || Trap.hasErrorOccurred())
- return TDK_SubstitutionFailure;
-
- ParamTypes.push_back(ParamType);
- }
-
- // C++ [temp.arg.explicit]p2:
- // Trailing template arguments that can be deduced (14.8.2) may be
- // omitted from the list of explicit template- arguments. If all of the
- // template arguments can be deduced, they may all be omitted; in this
- // case, the empty template argument list <> itself may also be omitted.
- //
- // Take all of the explicitly-specified arguments and put them into the
- // set of deduced template arguments.
- Deduced.reserve(TemplateParams->size());
- for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I)
- Deduced.push_back(ExplicitArgumentList->get(I));
+ TemplateDeductionResult Result =
+ SubstituteExplicitTemplateArguments(FunctionTemplate,
+ ExplicitTemplateArgs,
+ NumExplicitTemplateArgs,
+ Deduced,
+ ParamTypes,
+ 0,
+ Info);
+ if (Result)
+ return Result;
} else {
// Just fill in the parameter types from the function declaration.
for (unsigned I = 0; I != CheckArgs; ++I)
ParamTypes.push_back(Function->getParamDecl(I)->getType());
}
-
+
// Deduce template arguments from the function parameters.
- Deduced.resize(TemplateParams->size());
+ Deduced.resize(TemplateParams->size());
for (unsigned I = 0; I != CheckArgs; ++I) {
QualType ParamType = ParamTypes[I];
QualType ArgType = Args[I]->getType();
-
+
// C++ [temp.deduct.call]p2:
// If P is not a reference type:
QualType CanonParamType = Context.getCanonicalType(ParamType);
bool ParamWasReference = isa<ReferenceType>(CanonParamType);
if (!ParamWasReference) {
- // - If A is an array type, the pointer type produced by the
- // array-to-pointer standard conversion (4.2) is used in place of
+ // - If A is an array type, the pointer type produced by the
+ // array-to-pointer standard conversion (4.2) is used in place of
// A for type deduction; otherwise,
if (ArgType->isArrayType())
ArgType = Context.getArrayDecayedType(ArgType);
- // - If A is a function type, the pointer type produced by the
- // function-to-pointer standard conversion (4.3) is used in place
+ // - If A is a function type, the pointer type produced by the
+ // function-to-pointer standard conversion (4.3) is used in place
// of A for type deduction; otherwise,
else if (ArgType->isFunctionType())
ArgType = Context.getPointerType(ArgType);
@@ -1021,252 +1365,884 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
ArgType = CanonArgType.getUnqualifiedType();
}
}
-
+
// C++0x [temp.deduct.call]p3:
// If P is a cv-qualified type, the top level cv-qualifiers of P’s type
- // are ignored for type deduction.
+ // are ignored for type deduction.
if (CanonParamType.getCVRQualifiers())
ParamType = CanonParamType.getUnqualifiedType();
- if (const ReferenceType *ParamRefType = ParamType->getAsReferenceType()) {
- // [...] If P is a reference type, the type referred to by P is used
- // for type deduction.
+ if (const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>()) {
+ // [...] If P is a reference type, the type referred to by P is used
+ // for type deduction.
ParamType = ParamRefType->getPointeeType();
-
- // [...] If P is of the form T&&, where T is a template parameter, and
- // the argument is an lvalue, the type A& is used in place of A for
+
+ // [...] If P is of the form T&&, where T is a template parameter, and
+ // the argument is an lvalue, the type A& is used in place of A for
// type deduction.
if (isa<RValueReferenceType>(ParamRefType) &&
- ParamRefType->getAsTemplateTypeParmType() &&
+ ParamRefType->getAs<TemplateTypeParmType>() &&
Args[I]->isLvalue(Context) == Expr::LV_Valid)
ArgType = Context.getLValueReferenceType(ArgType);
}
-
+
// C++0x [temp.deduct.call]p4:
// In general, the deduction process attempts to find template argument
// values that will make the deduced A identical to A (after the type A
// is transformed as described above). [...]
- unsigned TDF = 0;
-
+ unsigned TDF = TDF_SkipNonDependent;
+
// - If the original P is a reference type, the deduced A (i.e., the
// type referred to by the reference) can be more cv-qualified than
// the transformed A.
if (ParamWasReference)
TDF |= TDF_ParamWithReferenceType;
- // - The transformed A can be another pointer or pointer to member
- // type that can be converted to the deduced A via a qualification
+ // - The transformed A can be another pointer or pointer to member
+ // type that can be converted to the deduced A via a qualification
// conversion (4.4).
if (ArgType->isPointerType() || ArgType->isMemberPointerType())
TDF |= TDF_IgnoreQualifiers;
- // - If P is a class and P has the form simple-template-id, then the
+ // - If P is a class and P has the form simple-template-id, then the
// transformed A can be a derived class of the deduced A. Likewise,
// if P is a pointer to a class of the form simple-template-id, the
// transformed A can be a pointer to a derived class pointed to by
// the deduced A.
if (isSimpleTemplateIdType(ParamType) ||
- (isa<PointerType>(ParamType) &&
+ (isa<PointerType>(ParamType) &&
isSimpleTemplateIdType(
- ParamType->getAsPointerType()->getPointeeType())))
+ ParamType->getAs<PointerType>()->getPointeeType())))
TDF |= TDF_DerivedClass;
-
+
if (TemplateDeductionResult Result
= ::DeduceTemplateArguments(Context, TemplateParams,
ParamType, ArgType, Info, Deduced,
TDF))
return Result;
+
+ // FIXME: C++0x [temp.deduct.call] paragraphs 6-9 deal with function
+ // pointer parameters.
+
+ // FIXME: we need to check that the deduced A is the same as A,
+ // modulo the various allowed differences.
+ }
+
+ return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
+ Specialization, Info);
+}
+
+/// \brief Deduce template arguments when taking the address of a function
+/// template (C++ [temp.deduct.funcaddr]) or matching a
+///
+/// \param FunctionTemplate the function template for which we are performing
+/// template argument deduction.
+///
+/// \param HasExplicitTemplateArgs whether any template arguments were
+/// explicitly specified.
+///
+/// \param ExplicitTemplateArguments when @p HasExplicitTemplateArgs is true,
+/// the explicitly-specified template arguments.
+///
+/// \param NumExplicitTemplateArguments when @p HasExplicitTemplateArgs is true,
+/// the number of explicitly-specified template arguments in
+/// @p ExplicitTemplateArguments. This value may be zero.
+///
+/// \param ArgFunctionType the function type that will be used as the
+/// "argument" type (A) when performing template argument deduction from the
+/// function template's function type.
+///
+/// \param Specialization if template argument deduction was successful,
+/// this will be set to the function template specialization produced by
+/// template argument deduction.
+///
+/// \param Info the argument will be updated to provide additional information
+/// about template argument deduction.
+///
+/// \returns the result of template argument deduction.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ bool HasExplicitTemplateArgs,
+ const TemplateArgument *ExplicitTemplateArgs,
+ unsigned NumExplicitTemplateArgs,
+ QualType ArgFunctionType,
+ FunctionDecl *&Specialization,
+ TemplateDeductionInfo &Info) {
+ FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
+ TemplateParameterList *TemplateParams
+ = FunctionTemplate->getTemplateParameters();
+ QualType FunctionType = Function->getType();
+
+ // Substitute any explicit template arguments.
+ llvm::SmallVector<TemplateArgument, 4> Deduced;
+ llvm::SmallVector<QualType, 4> ParamTypes;
+ if (HasExplicitTemplateArgs) {
+ if (TemplateDeductionResult Result
+ = SubstituteExplicitTemplateArguments(FunctionTemplate,
+ ExplicitTemplateArgs,
+ NumExplicitTemplateArgs,
+ Deduced, ParamTypes,
+ &FunctionType, Info))
+ return Result;
+ }
+
+ // Template argument deduction for function templates in a SFINAE context.
+ // Trap any errors that might occur.
+ SFINAETrap Trap(*this);
+
+ // Deduce template arguments from the function type.
+ Deduced.resize(TemplateParams->size());
+ if (TemplateDeductionResult Result
+ = ::DeduceTemplateArguments(Context, TemplateParams,
+ FunctionType, ArgFunctionType, Info,
+ Deduced, 0))
+ return Result;
+
+ return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
+ Specialization, Info);
+}
+
+/// \brief Deduce template arguments for a templated conversion
+/// function (C++ [temp.deduct.conv]) and, if successful, produce a
+/// conversion function template specialization.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ QualType ToType,
+ CXXConversionDecl *&Specialization,
+ TemplateDeductionInfo &Info) {
+ CXXConversionDecl *Conv
+ = cast<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl());
+ QualType FromType = Conv->getConversionType();
+
+ // Canonicalize the types for deduction.
+ QualType P = Context.getCanonicalType(FromType);
+ QualType A = Context.getCanonicalType(ToType);
+
+ // C++0x [temp.deduct.conv]p3:
+ // If P is a reference type, the type referred to by P is used for
+ // type deduction.
+ if (const ReferenceType *PRef = P->getAs<ReferenceType>())
+ P = PRef->getPointeeType();
+
+ // C++0x [temp.deduct.conv]p3:
+ // If A is a reference type, the type referred to by A is used
+ // for type deduction.
+ if (const ReferenceType *ARef = A->getAs<ReferenceType>())
+ A = ARef->getPointeeType();
+ // C++ [temp.deduct.conv]p2:
+ //
+ // If A is not a reference type:
+ else {
+ assert(!A->isReferenceType() && "Reference types were handled above");
+
+ // - If P is an array type, the pointer type produced by the
+ // array-to-pointer standard conversion (4.2) is used in place
+ // of P for type deduction; otherwise,
+ if (P->isArrayType())
+ P = Context.getArrayDecayedType(P);
+ // - If P is a function type, the pointer type produced by the
+ // function-to-pointer standard conversion (4.3) is used in
+ // place of P for type deduction; otherwise,
+ else if (P->isFunctionType())
+ P = Context.getPointerType(P);
+ // - If P is a cv-qualified type, the top level cv-qualifiers of
+ // P’s type are ignored for type deduction.
+ else
+ P = P.getUnqualifiedType();
+
+ // C++0x [temp.deduct.conv]p3:
+ // If A is a cv-qualified type, the top level cv-qualifiers of A’s
+ // type are ignored for type deduction.
+ A = A.getUnqualifiedType();
+ }
+
+ // Template argument deduction for function templates in a SFINAE context.
+ // Trap any errors that might occur.
+ SFINAETrap Trap(*this);
+
+ // C++ [temp.deduct.conv]p1:
+ // Template argument deduction is done by comparing the return
+ // type of the template conversion function (call it P) with the
+ // type that is required as the result of the conversion (call it
+ // A) as described in 14.8.2.4.
+ TemplateParameterList *TemplateParams
+ = FunctionTemplate->getTemplateParameters();
+ llvm::SmallVector<TemplateArgument, 4> Deduced;
+ Deduced.resize(TemplateParams->size());
+
+ // C++0x [temp.deduct.conv]p4:
+ // In general, the deduction process attempts to find template
+ // argument values that will make the deduced A identical to
+ // A. However, there are two cases that allow a difference:
+ unsigned TDF = 0;
+ // - If the original A is a reference type, A can be more
+ // cv-qualified than the deduced A (i.e., the type referred to
+ // by the reference)
+ if (ToType->isReferenceType())
+ TDF |= TDF_ParamWithReferenceType;
+ // - The deduced A can be another pointer or pointer to member
+ // type that can be converted to A via a qualification
+ // conversion.
+ //
+ // (C++0x [temp.deduct.conv]p6 clarifies that this only happens when
+ // both P and A are pointers or member pointers. In this case, we
+ // just ignore cv-qualifiers completely).
+ if ((P->isPointerType() && A->isPointerType()) ||
+ (P->isMemberPointerType() && P->isMemberPointerType()))
+ TDF |= TDF_IgnoreQualifiers;
+ if (TemplateDeductionResult Result
+ = ::DeduceTemplateArguments(Context, TemplateParams,
+ P, A, Info, Deduced, TDF))
+ return Result;
+
+ // FIXME: we need to check that the deduced A is the same as A,
+ // modulo the various allowed differences.
+
+ // Finish template argument deduction.
+ FunctionDecl *Spec = 0;
+ TemplateDeductionResult Result
+ = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, Spec, Info);
+ Specialization = cast_or_null<CXXConversionDecl>(Spec);
+ return Result;
+}
+
+/// \brief Stores the result of comparing the qualifiers of two types.
+enum DeductionQualifierComparison {
+ NeitherMoreQualified = 0,
+ ParamMoreQualified,
+ ArgMoreQualified
+};
+
+/// \brief Deduce the template arguments during partial ordering by comparing
+/// the parameter type and the argument type (C++0x [temp.deduct.partial]).
+///
+/// \param Context the AST context in which this deduction occurs.
+///
+/// \param TemplateParams the template parameters that we are deducing
+///
+/// \param ParamIn the parameter type
+///
+/// \param ArgIn the argument type
+///
+/// \param Info information about the template argument deduction itself
+///
+/// \param Deduced the deduced template arguments
+///
+/// \returns the result of template argument deduction so far. Note that a
+/// "success" result means that template argument deduction has not yet failed,
+/// but it may still fail, later, for other reasons.
+static Sema::TemplateDeductionResult
+DeduceTemplateArgumentsDuringPartialOrdering(ASTContext &Context,
+ TemplateParameterList *TemplateParams,
+ QualType ParamIn, QualType ArgIn,
+ Sema::TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<TemplateArgument> &Deduced,
+ llvm::SmallVectorImpl<DeductionQualifierComparison> *QualifierComparisons) {
+ CanQualType Param = Context.getCanonicalType(ParamIn);
+ CanQualType Arg = Context.getCanonicalType(ArgIn);
+
+ // C++0x [temp.deduct.partial]p5:
+ // Before the partial ordering is done, certain transformations are
+ // performed on the types used for partial ordering:
+ // - If P is a reference type, P is replaced by the type referred to.
+ CanQual<ReferenceType> ParamRef = Param->getAs<ReferenceType>();
+ if (ParamRef)
+ Param = ParamRef->getPointeeType();
+
+ // - If A is a reference type, A is replaced by the type referred to.
+ CanQual<ReferenceType> ArgRef = Arg->getAs<ReferenceType>();
+ if (ArgRef)
+ Arg = ArgRef->getPointeeType();
+
+ if (QualifierComparisons && ParamRef && ArgRef) {
+ // C++0x [temp.deduct.partial]p6:
+ // If both P and A were reference types (before being replaced with the
+ // type referred to above), determine which of the two types (if any) is
+ // more cv-qualified than the other; otherwise the types are considered to
+ // be equally cv-qualified for partial ordering purposes. The result of this
+ // determination will be used below.
+ //
+ // We save this information for later, using it only when deduction
+ // succeeds in both directions.
+ DeductionQualifierComparison QualifierResult = NeitherMoreQualified;
+ if (Param.isMoreQualifiedThan(Arg))
+ QualifierResult = ParamMoreQualified;
+ else if (Arg.isMoreQualifiedThan(Param))
+ QualifierResult = ArgMoreQualified;
+ QualifierComparisons->push_back(QualifierResult);
+ }
+
+ // C++0x [temp.deduct.partial]p7:
+ // Remove any top-level cv-qualifiers:
+ // - If P is a cv-qualified type, P is replaced by the cv-unqualified
+ // version of P.
+ Param = Param.getUnqualifiedType();
+ // - If A is a cv-qualified type, A is replaced by the cv-unqualified
+ // version of A.
+ Arg = Arg.getUnqualifiedType();
+
+ // C++0x [temp.deduct.partial]p8:
+ // Using the resulting types P and A the deduction is then done as
+ // described in 14.9.2.5. If deduction succeeds for a given type, the type
+ // from the argument template is considered to be at least as specialized
+ // as the type from the parameter template.
+ return DeduceTemplateArguments(Context, TemplateParams, Param, Arg, Info,
+ Deduced, TDF_None);
+}
+
+static void
+MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
+ bool OnlyDeduced,
+ llvm::SmallVectorImpl<bool> &Deduced);
+
+/// \brief Determine whether the function template \p FT1 is at least as
+/// specialized as \p FT2.
+static bool isAtLeastAsSpecializedAs(Sema &S,
+ FunctionTemplateDecl *FT1,
+ FunctionTemplateDecl *FT2,
+ TemplatePartialOrderingContext TPOC,
+ llvm::SmallVectorImpl<DeductionQualifierComparison> *QualifierComparisons) {
+ 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();
+ llvm::SmallVector<TemplateArgument, 4> Deduced;
+ Deduced.resize(TemplateParams->size());
+
+ // C++0x [temp.deduct.partial]p3:
+ // The types used to determine the ordering depend on the context in which
+ // the partial ordering is done:
+ Sema::TemplateDeductionInfo Info(S.Context);
+ switch (TPOC) {
+ case TPOC_Call: {
+ // - In the context of a function call, the function parameter types are
+ // used.
+ unsigned NumParams = std::min(Proto1->getNumArgs(), Proto2->getNumArgs());
+ for (unsigned I = 0; I != NumParams; ++I)
+ if (DeduceTemplateArgumentsDuringPartialOrdering(S.Context,
+ TemplateParams,
+ Proto2->getArgType(I),
+ Proto1->getArgType(I),
+ Info,
+ Deduced,
+ QualifierComparisons))
+ return false;
+
+ break;
+ }
+
+ case TPOC_Conversion:
+ // - In the context of a call to a conversion operator, the return types
+ // of the conversion function templates are used.
+ if (DeduceTemplateArgumentsDuringPartialOrdering(S.Context,
+ TemplateParams,
+ Proto2->getResultType(),
+ Proto1->getResultType(),
+ Info,
+ Deduced,
+ QualifierComparisons))
+ return false;
+ break;
- // FIXME: C++ [temp.deduct.call] paragraphs 6-9 deal with function
- // pointer parameters.
+ case TPOC_Other:
+ // - In other contexts (14.6.6.2) the function template’s function type
+ // is used.
+ if (DeduceTemplateArgumentsDuringPartialOrdering(S.Context,
+ TemplateParams,
+ FD2->getType(),
+ FD1->getType(),
+ Info,
+ Deduced,
+ QualifierComparisons))
+ return false;
+ break;
}
- // C++ [temp.deduct.type]p2:
- // [...] or if any template argument remains neither deduced nor
- // explicitly specified, template argument deduction fails.
- TemplateArgumentListBuilder Builder(TemplateParams, Deduced.size());
- for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
- if (Deduced[I].isNull()) {
- Decl *Param
- = const_cast<Decl *>(TemplateParams->getParam(I));
- if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
- Info.Param = TTP;
- else if (NonTypeTemplateParmDecl *NTTP
- = dyn_cast<NonTypeTemplateParmDecl>(Param))
- Info.Param = NTTP;
- else
- Info.Param = cast<TemplateTemplateParmDecl>(Param);
- return TDK_Incomplete;
- }
+ // C++0x [temp.deduct.partial]p11:
+ // In most cases, all template parameters must have values in order for
+ // deduction to succeed, but for partial ordering purposes a template
+ // parameter may remain without a value provided it is not used in the
+ // types being used for partial ordering. [ Note: a template parameter used
+ // in a non-deduced context is considered used. -end note]
+ unsigned ArgIdx = 0, NumArgs = Deduced.size();
+ for (; ArgIdx != NumArgs; ++ArgIdx)
+ if (Deduced[ArgIdx].isNull())
+ break;
+
+ if (ArgIdx == NumArgs) {
+ // All template arguments were deduced. FT1 is at least as specialized
+ // as FT2.
+ return true;
+ }
+
+ // Figure out which template parameters were used.
+ llvm::SmallVector<bool, 4> UsedParameters;
+ UsedParameters.resize(TemplateParams->size());
+ switch (TPOC) {
+ case TPOC_Call: {
+ unsigned NumParams = std::min(Proto1->getNumArgs(), Proto2->getNumArgs());
+ for (unsigned I = 0; I != NumParams; ++I)
+ ::MarkUsedTemplateParameters(S, Proto2->getArgType(I), false,
+ UsedParameters);
+ break;
+ }
- Builder.Append(Deduced[I]);
+ case TPOC_Conversion:
+ ::MarkUsedTemplateParameters(S, Proto2->getResultType(), false,
+ UsedParameters);
+ break;
+
+ case TPOC_Other:
+ ::MarkUsedTemplateParameters(S, FD2->getType(), false, UsedParameters);
+ break;
}
- // Form the template argument list from the deduced template arguments.
- TemplateArgumentList *DeducedArgumentList
- = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
- Info.reset(DeducedArgumentList);
+ for (; ArgIdx != NumArgs; ++ArgIdx)
+ // If this argument had no value deduced but was used in one of the types
+ // used for partial ordering, then deduction fails.
+ if (Deduced[ArgIdx].isNull() && UsedParameters[ArgIdx])
+ return false;
- // Enter a new template instantiation context while we instantiate the
- // actual function declaration.
- InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
- FunctionTemplate, Deduced.data(), Deduced.size(),
- ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution);
- if (Inst)
- return TDK_InstantiationDepth;
-
- // Substitute the deduced template arguments into the function template
- // declaration to produce the function template specialization.
- Specialization = cast_or_null<FunctionDecl>(
- InstantiateDecl(FunctionTemplate->getTemplatedDecl(),
- FunctionTemplate->getDeclContext(),
- *DeducedArgumentList));
- if (!Specialization)
- return TDK_SubstitutionFailure;
+ return true;
+}
+
+
+/// \brief Returns the more specialized function template according
+/// to the rules of function template partial ordering (C++ [temp.func.order]).
+///
+/// \param FT1 the first function template
+///
+/// \param FT2 the second function template
+///
+/// \param TPOC the context in which we are performing partial ordering of
+/// function templates.
+///
+/// \returns the more specialized function template. If neither
+/// template is more specialized, returns NULL.
+FunctionTemplateDecl *
+Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
+ FunctionTemplateDecl *FT2,
+ TemplatePartialOrderingContext TPOC) {
+ llvm::SmallVector<DeductionQualifierComparison, 4> QualifierComparisons;
+ bool Better1 = isAtLeastAsSpecializedAs(*this, FT1, FT2, TPOC, 0);
+ bool Better2 = isAtLeastAsSpecializedAs(*this, FT2, FT1, TPOC,
+ &QualifierComparisons);
- // If the template argument list is owned by the function template
- // specialization, release it.
- if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList)
- Info.take();
+ if (Better1 != Better2) // We have a clear winner
+ return Better1? FT1 : FT2;
+
+ if (!Better1 && !Better2) // Neither is better than the other
+ return 0;
+
+
+ // C++0x [temp.deduct.partial]p10:
+ // If for each type being considered a given template is at least as
+ // specialized for all types and more specialized for some set of types and
+ // the other template is not more specialized for any types or is not at
+ // least as specialized for any types, then the given template is more
+ // specialized than the other template. Otherwise, neither template is more
+ // specialized than the other.
+ Better1 = false;
+ Better2 = false;
+ for (unsigned I = 0, N = QualifierComparisons.size(); I != N; ++I) {
+ // C++0x [temp.deduct.partial]p9:
+ // If, for a given type, deduction succeeds in both directions (i.e., the
+ // types are identical after the transformations above) and if the type
+ // from the argument template is more cv-qualified than the type from the
+ // parameter template (as described above) that type is considered to be
+ // more specialized than the other. If neither type is more cv-qualified
+ // than the other then neither type is more specialized than the other.
+ switch (QualifierComparisons[I]) {
+ case NeitherMoreQualified:
+ break;
+
+ case ParamMoreQualified:
+ Better1 = true;
+ if (Better2)
+ return 0;
+ break;
+
+ case ArgMoreQualified:
+ Better2 = true;
+ if (Better1)
+ return 0;
+ break;
+ }
+ }
+
+ assert(!(Better1 && Better2) && "Should have broken out in the loop above");
+ if (Better1)
+ return FT1;
+ else if (Better2)
+ return FT2;
+ else
+ return 0;
+}
- // There may have been an error that did not prevent us from constructing a
- // declaration. Mark the declaration invalid and return with a substitution
- // failure.
- if (Trap.hasErrorOccurred()) {
- Specialization->setInvalidDecl(true);
- return TDK_SubstitutionFailure;
+/// \brief Determine if the two templates are equivalent.
+static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
+ if (T1 == T2)
+ return true;
+
+ if (!T1 || !T2)
+ return false;
+
+ return T1->getCanonicalDecl() == T2->getCanonicalDecl();
+}
+
+/// \brief Retrieve the most specialized of the given function template
+/// specializations.
+///
+/// \param Specializations the set of function template specializations that
+/// we will be comparing.
+///
+/// \param NumSpecializations the number of function template specializations in
+/// \p Specializations
+///
+/// \param TPOC the partial ordering context to use to compare the function
+/// template specializations.
+///
+/// \param Loc the location where the ambiguity or no-specializations
+/// diagnostic should occur.
+///
+/// \param NoneDiag partial diagnostic used to diagnose cases where there are
+/// no matching candidates.
+///
+/// \param AmbigDiag partial diagnostic used to diagnose an ambiguity, if one
+/// occurs.
+///
+/// \param CandidateDiag partial diagnostic used for each function template
+/// specialization that is a candidate in the ambiguous ordering. One parameter
+/// in this diagnostic should be unbound, which will correspond to the string
+/// describing the template arguments for the function template specialization.
+///
+/// \param Index if non-NULL and the result of this function is non-nULL,
+/// receives the index corresponding to the resulting function template
+/// specialization.
+///
+/// \returns the most specialized function template specialization, if
+/// found. Otherwise, returns NULL.
+///
+/// \todo FIXME: Consider passing in the "also-ran" candidates that failed
+/// template argument deduction.
+FunctionDecl *Sema::getMostSpecialized(FunctionDecl **Specializations,
+ unsigned NumSpecializations,
+ TemplatePartialOrderingContext TPOC,
+ SourceLocation Loc,
+ const PartialDiagnostic &NoneDiag,
+ const PartialDiagnostic &AmbigDiag,
+ const PartialDiagnostic &CandidateDiag,
+ unsigned *Index) {
+ if (NumSpecializations == 0) {
+ Diag(Loc, NoneDiag);
+ return 0;
}
- return TDK_Success;
+ if (NumSpecializations == 1) {
+ if (Index)
+ *Index = 0;
+
+ return Specializations[0];
+ }
+
+
+ // Find the function template that is better than all of the templates it
+ // has been compared to.
+ unsigned Best = 0;
+ FunctionTemplateDecl *BestTemplate
+ = Specializations[Best]->getPrimaryTemplate();
+ assert(BestTemplate && "Not a function template specialization?");
+ for (unsigned I = 1; I != NumSpecializations; ++I) {
+ FunctionTemplateDecl *Challenger = Specializations[I]->getPrimaryTemplate();
+ assert(Challenger && "Not a function template specialization?");
+ if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
+ TPOC),
+ Challenger)) {
+ Best = I;
+ BestTemplate = Challenger;
+ }
+ }
+
+ // Make sure that the "best" function template is more specialized than all
+ // of the others.
+ bool Ambiguous = false;
+ for (unsigned I = 0; I != NumSpecializations; ++I) {
+ FunctionTemplateDecl *Challenger = Specializations[I]->getPrimaryTemplate();
+ if (I != Best &&
+ !isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
+ TPOC),
+ BestTemplate)) {
+ Ambiguous = true;
+ break;
+ }
+ }
+
+ if (!Ambiguous) {
+ // We found an answer. Return it.
+ if (Index)
+ *Index = Best;
+ return Specializations[Best];
+ }
+
+ // Diagnose the ambiguity.
+ Diag(Loc, AmbigDiag);
+
+ // FIXME: Can we order the candidates in some sane way?
+ for (unsigned I = 0; I != NumSpecializations; ++I)
+ Diag(Specializations[I]->getLocation(), CandidateDiag)
+ << getTemplateArgumentBindingsText(
+ Specializations[I]->getPrimaryTemplate()->getTemplateParameters(),
+ *Specializations[I]->getTemplateSpecializationArgs());
+
+ return 0;
+}
+
+/// \brief Returns the more specialized class template partial specialization
+/// according to the rules of partial ordering of class template partial
+/// specializations (C++ [temp.class.order]).
+///
+/// \param PS1 the first class template partial specialization
+///
+/// \param PS2 the second class template partial specialization
+///
+/// \returns the more specialized class template partial specialization. If
+/// neither partial specialization is more specialized, returns NULL.
+ClassTemplatePartialSpecializationDecl *
+Sema::getMoreSpecializedPartialSpecialization(
+ ClassTemplatePartialSpecializationDecl *PS1,
+ ClassTemplatePartialSpecializationDecl *PS2) {
+ // C++ [temp.class.order]p1:
+ // For two class template partial specializations, the first is at least as
+ // specialized as the second if, given the following rewrite to two
+ // function templates, the first function template is at least as
+ // specialized as the second according to the ordering rules for function
+ // templates (14.6.6.2):
+ // - the first function template has the same template parameters as the
+ // first partial specialization and has a single function parameter
+ // whose type is a class template specialization with the template
+ // arguments of the first partial specialization, and
+ // - the second function template has the same template parameters as the
+ // second partial specialization and has a single function parameter
+ // whose type is a class template specialization with the template
+ // arguments of the second partial specialization.
+ //
+ // Rather than synthesize function templates, we merely perform the
+ // equivalent partial ordering by performing deduction directly on the
+ // template arguments of the class template partial specializations. This
+ // computation is slightly simpler than the general problem of function
+ // template partial ordering, because class template partial specializations
+ // are more constrained. We know that every template parameter is deduc
+ llvm::SmallVector<TemplateArgument, 4> Deduced;
+ Sema::TemplateDeductionInfo Info(Context);
+
+ // Determine whether PS1 is at least as specialized as PS2
+ Deduced.resize(PS2->getTemplateParameters()->size());
+ bool Better1 = !DeduceTemplateArgumentsDuringPartialOrdering(Context,
+ PS2->getTemplateParameters(),
+ Context.getTypeDeclType(PS2),
+ Context.getTypeDeclType(PS1),
+ Info,
+ Deduced,
+ 0);
+
+ // Determine whether PS2 is at least as specialized as PS1
+ Deduced.resize(PS1->getTemplateParameters()->size());
+ bool Better2 = !DeduceTemplateArgumentsDuringPartialOrdering(Context,
+ PS1->getTemplateParameters(),
+ Context.getTypeDeclType(PS1),
+ Context.getTypeDeclType(PS2),
+ Info,
+ Deduced,
+ 0);
+
+ if (Better1 == Better2)
+ return 0;
+
+ return Better1? PS1 : PS2;
}
-static void
-MarkDeducedTemplateParameters(Sema &SemaRef,
- const TemplateArgument &TemplateArg,
- llvm::SmallVectorImpl<bool> &Deduced);
+static void
+MarkUsedTemplateParameters(Sema &SemaRef,
+ const TemplateArgument &TemplateArg,
+ bool OnlyDeduced,
+ llvm::SmallVectorImpl<bool> &Used);
-/// \brief Mark the template arguments that are deduced by the given
+/// \brief Mark the template parameters that are used by the given
/// expression.
-static void
-MarkDeducedTemplateParameters(const Expr *E,
- llvm::SmallVectorImpl<bool> &Deduced) {
+static void
+MarkUsedTemplateParameters(Sema &SemaRef,
+ const Expr *E,
+ bool OnlyDeduced,
+ llvm::SmallVectorImpl<bool> &Used) {
+ // FIXME: if !OnlyDeduced, we have to walk the whole subexpression to
+ // find other occurrences of template parameters.
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
if (!E)
return;
- const NonTypeTemplateParmDecl *NTTP
+ const NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
if (!NTTP)
return;
- Deduced[NTTP->getIndex()] = true;
+ Used[NTTP->getIndex()] = true;
+}
+
+/// \brief Mark the template parameters that are used by the given
+/// nested name specifier.
+static void
+MarkUsedTemplateParameters(Sema &SemaRef,
+ NestedNameSpecifier *NNS,
+ bool OnlyDeduced,
+ llvm::SmallVectorImpl<bool> &Used) {
+ if (!NNS)
+ return;
+
+ MarkUsedTemplateParameters(SemaRef, NNS->getPrefix(), OnlyDeduced, Used);
+ MarkUsedTemplateParameters(SemaRef, QualType(NNS->getAsType(), 0),
+ OnlyDeduced, Used);
+}
+
+/// \brief Mark the template parameters that are used by the given
+/// template name.
+static void
+MarkUsedTemplateParameters(Sema &SemaRef,
+ TemplateName Name,
+ bool OnlyDeduced,
+ llvm::SmallVectorImpl<bool> &Used) {
+ if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(Template))
+ Used[TTP->getIndex()] = true;
+ return;
+ }
+
+ if (DependentTemplateName *DTN = Name.getAsDependentTemplateName())
+ MarkUsedTemplateParameters(SemaRef, DTN->getQualifier(), OnlyDeduced, Used);
}
-/// \brief Mark the template parameters that are deduced by the given
+/// \brief Mark the template parameters that are used by the given
/// type.
-static void
-MarkDeducedTemplateParameters(Sema &SemaRef, QualType T,
- llvm::SmallVectorImpl<bool> &Deduced) {
+static void
+MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
+ bool OnlyDeduced,
+ llvm::SmallVectorImpl<bool> &Used) {
+ if (T.isNull())
+ return;
+
// Non-dependent types have nothing deducible
if (!T->isDependentType())
return;
T = SemaRef.Context.getCanonicalType(T);
switch (T->getTypeClass()) {
- case Type::ExtQual:
- MarkDeducedTemplateParameters(SemaRef,
- QualType(cast<ExtQualType>(T)->getBaseType(), 0),
- Deduced);
- break;
-
case Type::Pointer:
- MarkDeducedTemplateParameters(SemaRef,
- cast<PointerType>(T)->getPointeeType(),
- Deduced);
+ MarkUsedTemplateParameters(SemaRef,
+ cast<PointerType>(T)->getPointeeType(),
+ OnlyDeduced,
+ Used);
break;
case Type::BlockPointer:
- MarkDeducedTemplateParameters(SemaRef,
- cast<BlockPointerType>(T)->getPointeeType(),
- Deduced);
+ MarkUsedTemplateParameters(SemaRef,
+ cast<BlockPointerType>(T)->getPointeeType(),
+ OnlyDeduced,
+ Used);
break;
case Type::LValueReference:
case Type::RValueReference:
- MarkDeducedTemplateParameters(SemaRef,
- cast<ReferenceType>(T)->getPointeeType(),
- Deduced);
+ MarkUsedTemplateParameters(SemaRef,
+ cast<ReferenceType>(T)->getPointeeType(),
+ OnlyDeduced,
+ Used);
break;
case Type::MemberPointer: {
const MemberPointerType *MemPtr = cast<MemberPointerType>(T.getTypePtr());
- MarkDeducedTemplateParameters(SemaRef, MemPtr->getPointeeType(), Deduced);
- MarkDeducedTemplateParameters(SemaRef, QualType(MemPtr->getClass(), 0),
- Deduced);
+ MarkUsedTemplateParameters(SemaRef, MemPtr->getPointeeType(), OnlyDeduced,
+ Used);
+ MarkUsedTemplateParameters(SemaRef, QualType(MemPtr->getClass(), 0),
+ OnlyDeduced, Used);
break;
}
case Type::DependentSizedArray:
- MarkDeducedTemplateParameters(cast<DependentSizedArrayType>(T)->getSizeExpr(),
- Deduced);
+ MarkUsedTemplateParameters(SemaRef,
+ cast<DependentSizedArrayType>(T)->getSizeExpr(),
+ OnlyDeduced, Used);
// Fall through to check the element type
case Type::ConstantArray:
case Type::IncompleteArray:
- MarkDeducedTemplateParameters(SemaRef,
- cast<ArrayType>(T)->getElementType(),
- Deduced);
+ MarkUsedTemplateParameters(SemaRef,
+ cast<ArrayType>(T)->getElementType(),
+ OnlyDeduced, Used);
break;
case Type::Vector:
case Type::ExtVector:
- MarkDeducedTemplateParameters(SemaRef,
- cast<VectorType>(T)->getElementType(),
- Deduced);
+ MarkUsedTemplateParameters(SemaRef,
+ cast<VectorType>(T)->getElementType(),
+ OnlyDeduced, Used);
break;
case Type::DependentSizedExtVector: {
const DependentSizedExtVectorType *VecType
= cast<DependentSizedExtVectorType>(T);
- MarkDeducedTemplateParameters(SemaRef, VecType->getElementType(), Deduced);
- MarkDeducedTemplateParameters(VecType->getSizeExpr(), Deduced);
+ MarkUsedTemplateParameters(SemaRef, VecType->getElementType(), OnlyDeduced,
+ Used);
+ MarkUsedTemplateParameters(SemaRef, VecType->getSizeExpr(), OnlyDeduced,
+ Used);
break;
}
case Type::FunctionProto: {
const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
- MarkDeducedTemplateParameters(SemaRef, Proto->getResultType(), Deduced);
+ MarkUsedTemplateParameters(SemaRef, Proto->getResultType(), OnlyDeduced,
+ Used);
for (unsigned I = 0, N = Proto->getNumArgs(); I != N; ++I)
- MarkDeducedTemplateParameters(SemaRef, Proto->getArgType(I), Deduced);
+ MarkUsedTemplateParameters(SemaRef, Proto->getArgType(I), OnlyDeduced,
+ Used);
break;
}
case Type::TemplateTypeParm:
- Deduced[cast<TemplateTypeParmType>(T)->getIndex()] = true;
+ Used[cast<TemplateTypeParmType>(T)->getIndex()] = true;
break;
case Type::TemplateSpecialization: {
- const TemplateSpecializationType *Spec
+ const TemplateSpecializationType *Spec
= cast<TemplateSpecializationType>(T);
- if (TemplateDecl *Template = Spec->getTemplateName().getAsTemplateDecl())
- if (TemplateTemplateParmDecl *TTP
- = dyn_cast<TemplateTemplateParmDecl>(Template))
- Deduced[TTP->getIndex()] = true;
-
- for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
- MarkDeducedTemplateParameters(SemaRef, Spec->getArg(I), Deduced);
-
+ MarkUsedTemplateParameters(SemaRef, Spec->getTemplateName(), OnlyDeduced,
+ Used);
+ for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
+ MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Used);
break;
}
- // None of these types have any deducible parts.
+ case Type::Complex:
+ if (!OnlyDeduced)
+ MarkUsedTemplateParameters(SemaRef,
+ cast<ComplexType>(T)->getElementType(),
+ OnlyDeduced, Used);
+ break;
+
+ case Type::Typename:
+ if (!OnlyDeduced)
+ MarkUsedTemplateParameters(SemaRef,
+ cast<TypenameType>(T)->getQualifier(),
+ OnlyDeduced, Used);
+ break;
+
+ // None of these types have any template parameters in them.
case Type::Builtin:
case Type::FixedWidthInt:
- case Type::Complex:
case Type::VariableArray:
case Type::FunctionNoProto:
case Type::Record:
case Type::Enum:
- case Type::Typename:
case Type::ObjCInterface:
- case Type::ObjCQualifiedInterface:
case Type::ObjCObjectPointer:
#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
@@ -1277,32 +2253,39 @@ MarkDeducedTemplateParameters(Sema &SemaRef, QualType T,
}
}
-/// \brief Mark the template parameters that are deduced by this
+/// \brief Mark the template parameters that are used by this
/// template argument.
-static void
-MarkDeducedTemplateParameters(Sema &SemaRef,
- const TemplateArgument &TemplateArg,
- llvm::SmallVectorImpl<bool> &Deduced) {
+static void
+MarkUsedTemplateParameters(Sema &SemaRef,
+ const TemplateArgument &TemplateArg,
+ bool OnlyDeduced,
+ llvm::SmallVectorImpl<bool> &Used) {
switch (TemplateArg.getKind()) {
case TemplateArgument::Null:
case TemplateArgument::Integral:
break;
-
+
case TemplateArgument::Type:
- MarkDeducedTemplateParameters(SemaRef, TemplateArg.getAsType(), Deduced);
+ MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsType(), OnlyDeduced,
+ Used);
break;
case TemplateArgument::Declaration:
- if (TemplateTemplateParmDecl *TTP
+ if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(TemplateArg.getAsDecl()))
- Deduced[TTP->getIndex()] = true;
+ Used[TTP->getIndex()] = true;
break;
case TemplateArgument::Expression:
- MarkDeducedTemplateParameters(TemplateArg.getAsExpr(), Deduced);
+ MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsExpr(), OnlyDeduced,
+ Used);
break;
+
case TemplateArgument::Pack:
- assert(0 && "FIXME: Implement!");
+ for (TemplateArgument::pack_iterator P = TemplateArg.pack_begin(),
+ PEnd = TemplateArg.pack_end();
+ P != PEnd; ++P)
+ MarkUsedTemplateParameters(SemaRef, *P, OnlyDeduced, Used);
break;
}
}
@@ -1316,9 +2299,25 @@ MarkDeducedTemplateParameters(Sema &SemaRef,
/// \param Deduced a bit vector whose elements will be set to \c true
/// to indicate when the corresponding template parameter will be
/// deduced.
-void
-Sema::MarkDeducedTemplateParameters(const TemplateArgumentList &TemplateArgs,
- llvm::SmallVectorImpl<bool> &Deduced) {
+void
+Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
+ bool OnlyDeduced,
+ llvm::SmallVectorImpl<bool> &Used) {
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
- ::MarkDeducedTemplateParameters(*this, TemplateArgs[I], Deduced);
+ ::MarkUsedTemplateParameters(*this, TemplateArgs[I], OnlyDeduced, Used);
+}
+
+/// \brief Marks all of the template parameters that will be deduced by a
+/// call to the given function template.
+void Sema::MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate,
+ llvm::SmallVectorImpl<bool> &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(*this, Function->getParamDecl(I)->getType(),
+ true, Deduced);
}
OpenPOWER on IntegriCloud