summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp2586
1 files changed, 1861 insertions, 725 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
index 5c77ed6..bd0a618 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -12,6 +12,7 @@
#include "clang/Sema/Sema.h"
#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/SemaDiagnostic.h" // FIXME: temporary!
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
#include "clang/AST/ASTContext.h"
@@ -20,6 +21,8 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "llvm/ADT/BitVector.h"
+#include "TreeTransform.h"
#include <algorithm>
namespace clang {
@@ -47,7 +50,10 @@ namespace clang {
/// \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
+ TDF_SkipNonDependent = 0x08,
+ /// \brief Whether we are performing template argument deduction for
+ /// parameters and arguments in a top-level template argument
+ TDF_TopLevelParameterTypeList = 0x10
};
}
@@ -57,9 +63,9 @@ using namespace clang;
/// necessary to compare their values regardless of underlying type.
static bool hasSameExtendedValue(llvm::APSInt X, llvm::APSInt Y) {
if (Y.getBitWidth() > X.getBitWidth())
- X.extend(Y.getBitWidth());
+ X = X.extend(Y.getBitWidth());
else if (Y.getBitWidth() < X.getBitWidth())
- Y.extend(X.getBitWidth());
+ Y = Y.extend(X.getBitWidth());
// If there is a signedness mismatch, correct it.
if (X.isSigned() != Y.isSigned()) {
@@ -78,9 +84,54 @@ static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateArgument &Param,
- const TemplateArgument &Arg,
+ TemplateArgument Arg,
TemplateDeductionInfo &Info,
- llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced);
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced);
+
+/// \brief Whether template argument deduction for two reference parameters
+/// resulted in the argument type, parameter type, or neither type being more
+/// qualified than the other.
+enum DeductionQualifierComparison {
+ NeitherMoreQualified = 0,
+ ParamMoreQualified,
+ ArgMoreQualified
+};
+
+/// \brief Stores the result of comparing two reference parameters while
+/// performing template argument deduction for partial ordering of function
+/// templates.
+struct RefParamPartialOrderingComparison {
+ /// \brief Whether the parameter type is an rvalue reference type.
+ bool ParamIsRvalueRef;
+ /// \brief Whether the argument type is an rvalue reference type.
+ bool ArgIsRvalueRef;
+
+ /// \brief Whether the parameter or argument (or neither) is more qualified.
+ DeductionQualifierComparison Qualifiers;
+};
+
+
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+ TemplateParameterList *TemplateParams,
+ QualType Param,
+ QualType Arg,
+ TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ unsigned TDF,
+ bool PartialOrdering = false,
+ llvm::SmallVectorImpl<RefParamPartialOrderingComparison> *
+ RefParamComparisons = 0);
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+ TemplateParameterList *TemplateParams,
+ const TemplateArgument *Params, unsigned NumParams,
+ const TemplateArgument *Args, unsigned NumArgs,
+ TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ bool NumberOfArgumentsMustMatch = true);
/// \brief If the given expression is of a form that permits the deduction
/// of a non-type template parameter, return the declaration of that
@@ -95,6 +146,141 @@ static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) {
return 0;
}
+/// \brief Determine whether two declaration pointers refer to the same
+/// declaration.
+static bool isSameDeclaration(Decl *X, Decl *Y) {
+ if (!X || !Y)
+ return !X && !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();
+}
+
+/// \brief Verify that the given, deduced template arguments are compatible.
+///
+/// \returns The deduced template argument, or a NULL template argument if
+/// the deduced template arguments were incompatible.
+static DeducedTemplateArgument
+checkDeducedTemplateArguments(ASTContext &Context,
+ const DeducedTemplateArgument &X,
+ const DeducedTemplateArgument &Y) {
+ // We have no deduction for one or both of the arguments; they're compatible.
+ 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 two template type arguments have the same type, they're compatible.
+ if (Y.getKind() == TemplateArgument::Type &&
+ Context.hasSameType(X.getAsType(), Y.getAsType()))
+ return X;
+
+ return DeducedTemplateArgument();
+
+ case TemplateArgument::Integral:
+ // If we deduced a constant in one case and either a dependent expression or
+ // declaration in another case, keep the integral constant.
+ // If both are integral constants with the same value, keep that value.
+ 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());
+
+ // All other combinations are incompatible.
+ return DeducedTemplateArgument();
+
+ case TemplateArgument::Template:
+ if (Y.getKind() == TemplateArgument::Template &&
+ Context.hasSameTemplateName(X.getAsTemplate(), Y.getAsTemplate()))
+ return X;
+
+ // All other combinations are incompatible.
+ return DeducedTemplateArgument();
+
+ case TemplateArgument::TemplateExpansion:
+ if (Y.getKind() == TemplateArgument::TemplateExpansion &&
+ Context.hasSameTemplateName(X.getAsTemplateOrTemplatePattern(),
+ Y.getAsTemplateOrTemplatePattern()))
+ return X;
+
+ // All other combinations are incompatible.
+ return DeducedTemplateArgument();
+
+ case TemplateArgument::Expression:
+ // If we deduced a dependent expression in one case and either an integral
+ // constant or a declaration in another case, keep the integral constant
+ // or declaration.
+ if (Y.getKind() == TemplateArgument::Integral ||
+ Y.getKind() == TemplateArgument::Declaration)
+ return DeducedTemplateArgument(Y, X.wasDeducedFromArrayBound() &&
+ Y.wasDeducedFromArrayBound());
+
+ if (Y.getKind() == TemplateArgument::Expression) {
+ // Compare the expressions for equality
+ llvm::FoldingSetNodeID ID1, ID2;
+ X.getAsExpr()->Profile(ID1, Context, true);
+ Y.getAsExpr()->Profile(ID2, Context, true);
+ if (ID1 == ID2)
+ return X;
+ }
+
+ // All other combinations are incompatible.
+ return DeducedTemplateArgument();
+
+ case TemplateArgument::Declaration:
+ // If we deduced a declaration and a dependent expression, keep the
+ // declaration.
+ if (Y.getKind() == TemplateArgument::Expression)
+ return X;
+
+ // If we deduced a declaration and an integral constant, keep the
+ // integral constant.
+ if (Y.getKind() == TemplateArgument::Integral)
+ return Y;
+
+ // If we deduced two declarations, make sure they they refer to the
+ // same declaration.
+ if (Y.getKind() == TemplateArgument::Declaration &&
+ isSameDeclaration(X.getAsDecl(), Y.getAsDecl()))
+ return X;
+
+ // All other combinations are incompatible.
+ 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;
+ }
+
+ return DeducedTemplateArgument();
+}
+
/// \brief Deduce the value of the given non-type template parameter
/// from the given constant.
static Sema::TemplateDeductionResult
@@ -107,31 +293,18 @@ DeduceNonTypeTemplateArgument(Sema &S,
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument with depth > 0");
- if (Deduced[NTTP->getIndex()].isNull()) {
- Deduced[NTTP->getIndex()] = DeducedTemplateArgument(Value, ValueType,
- DeducedFromArrayBound);
- return Sema::TDK_Success;
- }
-
- if (Deduced[NTTP->getIndex()].getKind() != TemplateArgument::Integral) {
+ DeducedTemplateArgument NewDeduced(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 = TemplateArgument(Value, ValueType);
- return Sema::TDK_Inconsistent;
- }
-
- // Extent the smaller of the two values.
- llvm::APSInt PrevValue = *Deduced[NTTP->getIndex()].getAsIntegral();
- if (!hasSameExtendedValue(PrevValue, Value)) {
- Info.Param = NTTP;
- Info.FirstArg = Deduced[NTTP->getIndex()];
- Info.SecondArg = TemplateArgument(Value, ValueType);
+ Info.SecondArg = NewDeduced;
return Sema::TDK_Inconsistent;
}
- if (!DeducedFromArrayBound)
- Deduced[NTTP->getIndex()].setDeducedFromArrayBound(false);
-
+ Deduced[NTTP->getIndex()] = Result;
return Sema::TDK_Success;
}
@@ -150,30 +323,19 @@ DeduceNonTypeTemplateArgument(Sema &S,
assert((Value->isTypeDependent() || Value->isValueDependent()) &&
"Expression template argument must be type- or value-dependent.");
- if (Deduced[NTTP->getIndex()].isNull()) {
- Deduced[NTTP->getIndex()] = TemplateArgument(Value->Retain());
- 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
- // dependent expression gives us the constant value.
- return Sema::TDK_Success;
- }
+ DeducedTemplateArgument NewDeduced(Value);
+ DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
+ Deduced[NTTP->getIndex()],
+ NewDeduced);
- if (Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Expression) {
- // Compare the expressions for equality
- llvm::FoldingSetNodeID ID1, ID2;
- Deduced[NTTP->getIndex()].getAsExpr()->Profile(ID1, S.Context, true);
- Value->Profile(ID2, S.Context, true);
- if (ID1 == ID2)
- return Sema::TDK_Success;
-
- // FIXME: Fill in argument mismatch information
- return Sema::TDK_NonDeducedMismatch;
+ 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;
}
@@ -189,28 +351,19 @@ DeduceNonTypeTemplateArgument(Sema &S,
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument with depth > 0");
-
- if (Deduced[NTTP->getIndex()].isNull()) {
- Deduced[NTTP->getIndex()] = TemplateArgument(D->getCanonicalDecl());
- return Sema::TDK_Success;
- }
-
- if (Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Expression) {
- // Okay, we deduced a declaration in one case and a dependent expression
- // in another case.
- return Sema::TDK_Success;
- }
-
- if (Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Declaration) {
- // Compare the declarations for equality
- if (Deduced[NTTP->getIndex()].getAsDecl()->getCanonicalDecl() ==
- D->getCanonicalDecl())
- return Sema::TDK_Success;
-
- // FIXME: Fill in argument mismatch information
- return Sema::TDK_NonDeducedMismatch;
+
+ DeducedTemplateArgument NewDeduced(D? D->getCanonicalDecl() : 0);
+ 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;
}
@@ -227,33 +380,28 @@ DeduceTemplateArguments(Sema &S,
// so there is nothing that we can deduce.
return Sema::TDK_Success;
}
-
+
if (TemplateTemplateParmDecl *TempParam
= dyn_cast<TemplateTemplateParmDecl>(ParamDecl)) {
- // Bind the template template parameter to the given template name.
- TemplateArgument &ExistingArg = Deduced[TempParam->getIndex()];
- if (ExistingArg.isNull()) {
- // This is the first deduction for this template template parameter.
- ExistingArg = TemplateArgument(S.Context.getCanonicalTemplateName(Arg));
- return Sema::TDK_Success;
+ 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;
}
-
- // Verify that the previous binding matches this deduction.
- assert(ExistingArg.getKind() == TemplateArgument::Template);
- if (S.Context.hasSameTemplateName(ExistingArg.getAsTemplate(), Arg))
- return Sema::TDK_Success;
-
- // Inconsistent deduction.
- Info.Param = TempParam;
- Info.FirstArg = ExistingArg;
- Info.SecondArg = TemplateArgument(Arg);
- return Sema::TDK_Inconsistent;
+
+ Deduced[TempParam->getIndex()] = Result;
+ return Sema::TDK_Success;
}
-
+
// Verify that the two template names are equivalent.
if (S.Context.hasSameTemplateName(Param, Arg))
return Sema::TDK_Success;
-
+
// Mismatch of non-dependent template parameter to argument.
Info.FirstArg = TemplateArgument(Param);
Info.SecondArg = TemplateArgument(Arg);
@@ -300,17 +448,13 @@ DeduceTemplateArguments(Sema &S,
// Perform template argument deduction on each template
- // argument.
- unsigned NumArgs = std::min(SpecArg->getNumArgs(), Param->getNumArgs());
- for (unsigned I = 0; I != NumArgs; ++I)
- if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(S, TemplateParams,
- Param->getArg(I),
- SpecArg->getArg(I),
- Info, Deduced))
- return Result;
-
- return Sema::TDK_Success;
+ // argument. Ignore any missing/extra arguments, since they could be
+ // filled in by default arguments.
+ return DeduceTemplateArguments(S, TemplateParams,
+ Param->getArgs(), Param->getNumArgs(),
+ SpecArg->getArgs(), SpecArg->getNumArgs(),
+ Info, Deduced,
+ /*NumberOfArgumentsMustMatch=*/false);
}
// If the argument type is a class template specialization, we
@@ -334,20 +478,12 @@ DeduceTemplateArguments(Sema &S,
Info, Deduced))
return Result;
- 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(S, TemplateParams,
- Param->getArg(I),
- ArgArgs.get(I),
- Info, Deduced))
- return Result;
-
- return Sema::TDK_Success;
+ // Perform template argument deduction for the template arguments.
+ return DeduceTemplateArguments(S, TemplateParams,
+ Param->getArgs(), Param->getNumArgs(),
+ SpecArg->getTemplateArgs().data(),
+ SpecArg->getTemplateArgs().size(),
+ Info, Deduced);
}
/// \brief Determines whether the given type is an opaque type that
@@ -359,6 +495,7 @@ static bool IsPossiblyOpaquelyQualifiedType(QualType T) {
case Type::DependentName:
case Type::Decltype:
case Type::UnresolvedUsing:
+ case Type::TemplateTypeParm:
return true;
case Type::ConstantArray:
@@ -373,6 +510,296 @@ static bool IsPossiblyOpaquelyQualifiedType(QualType T) {
}
}
+/// \brief Retrieve the depth and index of a template parameter.
+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());
+}
+
+/// \brief Retrieve the depth and index of an unexpanded parameter pack.
+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 *>());
+}
+
+/// \brief Helper function to build a TemplateParameter when we don't
+/// know its type statically.
+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));
+}
+
+/// \brief Prepare to perform template argument deduction for all of the
+/// arguments in a set of argument packs.
+static void PrepareArgumentPackDeduction(Sema &S,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ const llvm::SmallVectorImpl<unsigned> &PackIndices,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &SavedPacks,
+ llvm::SmallVectorImpl<
+ llvm::SmallVector<DeducedTemplateArgument, 4> > &NewlyDeducedPacks) {
+ // Save the deduced template arguments for each parameter pack expanded
+ // by this pack expansion, then clear out the deduction.
+ for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
+ // Save the previously-deduced argument pack, then clear it out so that we
+ // can deduce a new argument pack.
+ SavedPacks[I] = Deduced[PackIndices[I]];
+ Deduced[PackIndices[I]] = TemplateArgument();
+
+ // If the template arugment pack was explicitly specified, add that to
+ // the set of deduced arguments.
+ 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);
+ }
+ }
+}
+
+/// \brief Finish template argument deduction for a set of argument packs,
+/// producing the argument packs and checking for consistency with prior
+/// deductions.
+static Sema::TemplateDeductionResult
+FinishArgumentPackDeduction(Sema &S,
+ TemplateParameterList *TemplateParams,
+ bool HasAnyArguments,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ const llvm::SmallVectorImpl<unsigned> &PackIndices,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &SavedPacks,
+ llvm::SmallVectorImpl<
+ llvm::SmallVector<DeducedTemplateArgument, 4> > &NewlyDeducedPacks,
+ TemplateDeductionInfo &Info) {
+ // Build argument packs for each of the parameter packs expanded by this
+ // pack expansion.
+ for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
+ if (HasAnyArguments && NewlyDeducedPacks[I].empty()) {
+ // We were not able to deduce anything for this parameter pack,
+ // so just restore the saved argument pack.
+ Deduced[PackIndices[I]] = SavedPacks[I];
+ continue;
+ }
+
+ DeducedTemplateArgument NewPack;
+
+ if (NewlyDeducedPacks[I].empty()) {
+ // If we deduced an empty argument pack, create it now.
+ NewPack = DeducedTemplateArgument(TemplateArgument(0, 0));
+ } 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;
+}
+
+/// \brief Deduce the template arguments by comparing the list of parameter
+/// types to the list of argument types, as in the parameter-type-lists of
+/// function types (C++ [temp.deduct.type]p10).
+///
+/// \param S The semantic analysis object within which we are deducing
+///
+/// \param TemplateParams The template parameters that we are deducing
+///
+/// \param Params The list of parameter types
+///
+/// \param NumParams The number of types in \c Params
+///
+/// \param Args The list of argument types
+///
+/// \param NumArgs The number of types in \c Args
+///
+/// \param Info information about the template argument deduction itself
+///
+/// \param Deduced the deduced template arguments
+///
+/// \param TDF bitwise OR of the TemplateDeductionFlags bits that describe
+/// how template argument deduction is performed.
+///
+/// \param PartialOrdering If true, we are performing template argument
+/// deduction for during partial ordering for a call
+/// (C++0x [temp.deduct.partial]).
+///
+/// \param RefParamComparisons If we're performing template argument deduction
+/// in the context of partial ordering, the set of qualifier comparisons.
+///
+/// \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(Sema &S,
+ TemplateParameterList *TemplateParams,
+ const QualType *Params, unsigned NumParams,
+ const QualType *Args, unsigned NumArgs,
+ TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ unsigned TDF,
+ bool PartialOrdering = false,
+ llvm::SmallVectorImpl<RefParamPartialOrderingComparison> *
+ RefParamComparisons = 0) {
+ // Fast-path check to see if we have too many/too few arguments.
+ if (NumParams != NumArgs &&
+ !(NumParams && isa<PackExpansionType>(Params[NumParams - 1])) &&
+ !(NumArgs && isa<PackExpansionType>(Args[NumArgs - 1])))
+ return Sema::TDK_NonDeducedMismatch;
+
+ // C++0x [temp.deduct.type]p10:
+ // Similarly, if P has a form that contains (T), then each parameter type
+ // Pi of the respective parameter-type- list of P is compared with the
+ // corresponding parameter type Ai of the corresponding parameter-type-list
+ // of A. [...]
+ unsigned ArgIdx = 0, ParamIdx = 0;
+ for (; ParamIdx != NumParams; ++ParamIdx) {
+ // Check argument types.
+ const PackExpansionType *Expansion
+ = dyn_cast<PackExpansionType>(Params[ParamIdx]);
+ if (!Expansion) {
+ // Simple case: compare the parameter and argument types at this point.
+
+ // Make sure we have an argument.
+ if (ArgIdx >= NumArgs)
+ return Sema::TDK_NonDeducedMismatch;
+
+ if (isa<PackExpansionType>(Args[ArgIdx])) {
+ // C++0x [temp.deduct.type]p22:
+ // If the original function parameter associated with A is a function
+ // parameter pack and the function parameter associated with P is not
+ // a function parameter pack, then template argument deduction fails.
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(S, TemplateParams,
+ Params[ParamIdx],
+ Args[ArgIdx],
+ Info, Deduced, TDF,
+ PartialOrdering,
+ RefParamComparisons))
+ return Result;
+
+ ++ArgIdx;
+ continue;
+ }
+
+ // C++0x [temp.deduct.type]p5:
+ // The non-deduced contexts are:
+ // - A function parameter pack that does not occur at the end of the
+ // parameter-declaration-clause.
+ if (ParamIdx + 1 < NumParams)
+ return Sema::TDK_Success;
+
+ // C++0x [temp.deduct.type]p10:
+ // If the parameter-declaration corresponding to Pi is a function
+ // parameter pack, then the type of its declarator- id is compared with
+ // each remaining parameter type in the parameter-type-list of A. Each
+ // comparison deduces template arguments for subsequent positions in the
+ // template parameter packs expanded by the function parameter pack.
+
+ // Compute the set of template parameter indices that correspond to
+ // parameter packs expanded by the pack expansion.
+ llvm::SmallVector<unsigned, 2> PackIndices;
+ QualType Pattern = Expansion->getPattern();
+ {
+ llvm::BitVector SawIndices(TemplateParams->size());
+ llvm::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?");
+
+ // Keep track of the deduced template arguments for each parameter pack
+ // expanded by this pack expansion (the outer index) and for each
+ // template argument (the inner SmallVectors).
+ llvm::SmallVector<llvm::SmallVector<DeducedTemplateArgument, 4>, 2>
+ NewlyDeducedPacks(PackIndices.size());
+ llvm::SmallVector<DeducedTemplateArgument, 2>
+ SavedPacks(PackIndices.size());
+ PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks,
+ NewlyDeducedPacks);
+
+ bool HasAnyArguments = false;
+ for (; ArgIdx < NumArgs; ++ArgIdx) {
+ HasAnyArguments = true;
+
+ // Deduce template arguments from the pattern.
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(S, TemplateParams, Pattern, Args[ArgIdx],
+ Info, Deduced, TDF, PartialOrdering,
+ RefParamComparisons))
+ return Result;
+
+ // Capture the deduced template arguments for each parameter pack expanded
+ // by this pack expansion, add them to the list of arguments we've deduced
+ // for that pack, then clear out the deduced argument.
+ 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();
+ }
+ }
+ }
+
+ // Build argument packs for each of the parameter packs expanded by this
+ // pack expansion.
+ if (Sema::TemplateDeductionResult Result
+ = FinishArgumentPackDeduction(S, TemplateParams, HasAnyArguments,
+ Deduced, PackIndices, SavedPacks,
+ NewlyDeducedPacks, Info))
+ return Result;
+ }
+
+ // Make sure we don't have any extra arguments.
+ if (ArgIdx < NumArgs)
+ return Sema::TDK_NonDeducedMismatch;
+
+ return Sema::TDK_Success;
+}
+
/// \brief Deduce the template arguments by comparing the parameter type and
/// the argument type (C++ [temp.deduct.type]).
///
@@ -391,6 +818,12 @@ static bool IsPossiblyOpaquelyQualifiedType(QualType T) {
/// \param TDF bitwise OR of the TemplateDeductionFlags bits that describe
/// how template argument deduction is performed.
///
+/// \param PartialOrdering Whether we're performing template argument deduction
+/// in the context of partial ordering (C++0x [temp.deduct.partial]).
+///
+/// \param RefParamComparisons If we're performing template argument deduction
+/// in the context of partial ordering, the set of qualifier comparisons.
+///
/// \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.
@@ -400,31 +833,105 @@ DeduceTemplateArguments(Sema &S,
QualType ParamIn, QualType ArgIn,
TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- unsigned TDF) {
+ unsigned TDF,
+ bool PartialOrdering,
+ llvm::SmallVectorImpl<RefParamPartialOrderingComparison> *RefParamComparisons) {
// We only want to look at the canonical types, since typedefs and
// sugar are not part of template argument deduction.
QualType Param = S.Context.getCanonicalType(ParamIn);
QualType Arg = S.Context.getCanonicalType(ArgIn);
- // 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
- // transformed A.
- if (TDF & TDF_ParamWithReferenceType) {
- Qualifiers Quals;
- QualType UnqualParam = S.Context.getUnqualifiedArrayType(Param, Quals);
- Quals.setCVRQualifiers(Quals.getCVRQualifiers() &
- Arg.getCVRQualifiersThroughArrayTypes());
- Param = S.Context.getQualifiedType(UnqualParam, Quals);
+ // If the argument type is a pack expansion, look at its pattern.
+ // This isn't explicitly called out
+ if (const PackExpansionType *ArgExpansion
+ = dyn_cast<PackExpansionType>(Arg))
+ Arg = ArgExpansion->getPattern();
+
+ if (PartialOrdering) {
+ // 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.
+ const ReferenceType *ParamRef = Param->getAs<ReferenceType>();
+ if (ParamRef)
+ Param = ParamRef->getPointeeType();
+
+ // - If A is a reference type, A is replaced by the type referred to.
+ const ReferenceType *ArgRef = Arg->getAs<ReferenceType>();
+ if (ArgRef)
+ Arg = ArgRef->getPointeeType();
+
+ if (RefParamComparisons && 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.
+ RefParamPartialOrderingComparison Comparison;
+ Comparison.ParamIsRvalueRef = ParamRef->getAs<RValueReferenceType>();
+ Comparison.ArgIsRvalueRef = ArgRef->getAs<RValueReferenceType>();
+ Comparison.Qualifiers = NeitherMoreQualified;
+ if (Param.isMoreQualifiedThan(Arg))
+ Comparison.Qualifiers = ParamMoreQualified;
+ else if (Arg.isMoreQualifiedThan(Param))
+ Comparison.Qualifiers = ArgMoreQualified;
+ RefParamComparisons->push_back(Comparison);
+ }
+
+ // 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();
+ } else {
+ // 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
+ // transformed A.
+ 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()) {
+ // C++0x [temp.deduct.type]p10:
+ // If P and A are function types that originated from deduction when
+ // taking the address of a function template (14.8.2.2) or when deducing
+ // template arguments from a function declaration (14.8.2.6) and Pi and
+ // Ai are parameters of the top-level parameter-type-list of P and A,
+ // respectively, Pi is adjusted if it is an rvalue reference to a
+ // cv-unqualified template parameter and Ai is an lvalue reference, in
+ // which case the type of Pi is changed to be the template parameter
+ // type (i.e., T&& is changed to simply T). [ Note: As a result, when
+ // Pi is T&& and Ai is X&, the adjusted Pi will be T, causing T to be
+ // deduced as X&. - end note ]
+ 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 the parameter type is not dependent, there is nothing to deduce.
if (!Param->isDependentType()) {
- if (!(TDF & TDF_SkipNonDependent) && Param != Arg) {
-
+ if (!(TDF & TDF_SkipNonDependent) && Param != Arg)
return Sema::TDK_NonDeducedMismatch;
- }
-
+
return Sema::TDK_Success;
}
@@ -464,27 +971,24 @@ DeduceTemplateArguments(Sema &S,
assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0");
assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function");
QualType DeducedType = Arg;
- DeducedType.removeCVRQualifiers(Param.getCVRQualifiers());
+
+ // local manipulation is okay because it's canonical
+ DeducedType.removeLocalCVRQualifiers(Param.getCVRQualifiers());
if (RecanonicalizeArg)
DeducedType = S.Context.getCanonicalType(DeducedType);
- if (Deduced[Index].isNull())
- Deduced[Index] = TemplateArgument(DeducedType);
- else {
- // 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
- // explicitly specified, template argument deduction fails.
- if (Deduced[Index].getAsType() != DeducedType) {
- Info.Param
- = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
- Info.FirstArg = Deduced[Index];
- Info.SecondArg = TemplateArgument(Arg);
- return Sema::TDK_Inconsistent;
- }
+ 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;
}
@@ -492,6 +996,13 @@ DeduceTemplateArguments(Sema &S,
Info.FirstArg = TemplateArgument(ParamIn);
Info.SecondArg = TemplateArgument(ArgIn);
+ // If the parameter is an already-substituted template parameter
+ // pack, do nothing: we don't know which of its arguments to look
+ // at, so we have to wait until all of the parameter packs in this
+ // expansion have arguments.
+ if (isa<SubstTemplateTypeParmPackType>(Param))
+ return Sema::TDK_Success;
+
// Check the cv-qualifiers on the parameter and argument types.
if (!(TDF & TDF_IgnoreQualifiers)) {
if (TDF & TDF_ParamWithReferenceType) {
@@ -615,16 +1126,17 @@ DeduceTemplateArguments(Sema &S,
if (const ConstantArrayType *ConstantArrayArg
= dyn_cast<ConstantArrayType>(ArrayArg)) {
llvm::APSInt Size(ConstantArrayArg->getSize());
- return DeduceNonTypeTemplateArgument(S, NTTP, Size,
+ return DeduceNonTypeTemplateArgument(S, NTTP, Size,
S.Context.getSizeType(),
/*ArrayBound=*/true,
Info, Deduced);
}
if (const DependentSizedArrayType *DependentArrayArg
= dyn_cast<DependentSizedArrayType>(ArrayArg))
- return DeduceNonTypeTemplateArgument(S, NTTP,
- DependentArrayArg->getSizeExpr(),
- Info, Deduced);
+ if (DependentArrayArg->getSizeExpr())
+ return DeduceNonTypeTemplateArgument(S, NTTP,
+ DependentArrayArg->getSizeExpr(),
+ Info, Deduced);
// Incomplete type does not match a dependently-sized array type
return Sema::TDK_NonDeducedMismatch;
@@ -634,6 +1146,7 @@ DeduceTemplateArguments(Sema &S,
// T(*)()
// T(*)(T)
case Type::FunctionProto: {
+ unsigned SubTDF = TDF & TDF_TopLevelParameterTypeList;
const FunctionProtoType *FunctionProtoArg =
dyn_cast<FunctionProtoType>(Arg);
if (!FunctionProtoArg)
@@ -642,14 +1155,11 @@ DeduceTemplateArguments(Sema &S,
const FunctionProtoType *FunctionProtoParam =
cast<FunctionProtoType>(Param);
- if (FunctionProtoParam->getTypeQuals() !=
- FunctionProtoArg->getTypeQuals())
- return Sema::TDK_NonDeducedMismatch;
-
- if (FunctionProtoParam->getNumArgs() != FunctionProtoArg->getNumArgs())
- return Sema::TDK_NonDeducedMismatch;
-
- if (FunctionProtoParam->isVariadic() != FunctionProtoArg->isVariadic())
+ if (FunctionProtoParam->getTypeQuals()
+ != FunctionProtoArg->getTypeQuals() ||
+ FunctionProtoParam->getRefQualifier()
+ != FunctionProtoArg->getRefQualifier() ||
+ FunctionProtoParam->isVariadic() != FunctionProtoArg->isVariadic())
return Sema::TDK_NonDeducedMismatch;
// Check return types.
@@ -660,17 +1170,12 @@ DeduceTemplateArguments(Sema &S,
Info, Deduced, 0))
return Result;
- for (unsigned I = 0, N = FunctionProtoParam->getNumArgs(); I != N; ++I) {
- // Check argument types.
- if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(S, TemplateParams,
- FunctionProtoParam->getArgType(I),
- FunctionProtoArg->getArgType(I),
- Info, Deduced, 0))
- return Result;
- }
-
- return Sema::TDK_Success;
+ return DeduceTemplateArguments(S, TemplateParams,
+ FunctionProtoParam->arg_type_begin(),
+ FunctionProtoParam->getNumArgs(),
+ FunctionProtoArg->arg_type_begin(),
+ FunctionProtoArg->getNumArgs(),
+ Info, Deduced, SubTDF);
}
case Type::InjectedClassName: {
@@ -721,6 +1226,8 @@ DeduceTemplateArguments(Sema &S,
llvm::SmallVector<const RecordType *, 8> ToVisit;
ToVisit.push_back(RecordT);
bool Successful = false;
+ llvm::SmallVectorImpl<DeducedTemplateArgument> DeducedOrig(0);
+ DeducedOrig = Deduced;
while (!ToVisit.empty()) {
// Retrieve the next class in the inheritance hierarchy.
const RecordType *NextT = ToVisit.back();
@@ -738,9 +1245,14 @@ DeduceTemplateArguments(Sema &S,
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)
+ // note that we had some success. Otherwise, ignore any deductions
+ // from this base class.
+ if (BaseResult == Sema::TDK_Success) {
Successful = true;
+ DeducedOrig = Deduced;
+ }
+ else
+ Deduced = DeducedOrig;
}
// Visit base classes
@@ -828,9 +1340,15 @@ static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateArgument &Param,
- const TemplateArgument &Arg,
+ TemplateArgument Arg,
TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ // If the template argument is a pack expansion, perform template argument
+ // deduction against the pattern of that expansion. This only occurs during
+ // partial ordering.
+ if (Arg.isPackExpansion())
+ Arg = Arg.getPackExpansionPattern();
+
switch (Param.getKind()) {
case TemplateArgument::Null:
assert(false && "Null template argument in parameter list");
@@ -843,22 +1361,26 @@ DeduceTemplateArguments(Sema &S,
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
-
+
case TemplateArgument::Template:
if (Arg.getKind() == TemplateArgument::Template)
- return DeduceTemplateArguments(S, TemplateParams,
+ 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");
+ break;
+
case TemplateArgument::Declaration:
if (Arg.getKind() == TemplateArgument::Declaration &&
Param.getAsDecl()->getCanonicalDecl() ==
Arg.getAsDecl()->getCanonicalDecl())
return Sema::TDK_Success;
-
+
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
@@ -898,7 +1420,7 @@ DeduceTemplateArguments(Sema &S,
if (Arg.getKind() == TemplateArgument::Declaration)
return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsDecl(),
Info, Deduced);
-
+
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
@@ -908,31 +1430,209 @@ DeduceTemplateArguments(Sema &S,
return Sema::TDK_Success;
}
case TemplateArgument::Pack:
- assert(0 && "FIXME: Implement!");
- break;
+ llvm_unreachable("Argument packs should be expanded by the caller!");
}
return Sema::TDK_Success;
}
+/// \brief Determine whether there is a template argument to be used for
+/// deduction.
+///
+/// This routine "expands" argument packs in-place, overriding its input
+/// parameters so that \c Args[ArgIdx] will be the available template argument.
+///
+/// \returns true if there is another template argument (which will be at
+/// \c Args[ArgIdx]), false otherwise.
+static bool hasTemplateArgumentForDeduction(const TemplateArgument *&Args,
+ unsigned &ArgIdx,
+ unsigned &NumArgs) {
+ if (ArgIdx == NumArgs)
+ 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;
+}
+
+/// \brief Determine whether the given set of template arguments has a pack
+/// expansion that is not the last template argument.
+static bool hasPackExpansionBeforeEnd(const TemplateArgument *Args,
+ unsigned NumArgs) {
+ unsigned ArgIdx = 0;
+ while (ArgIdx < NumArgs) {
+ const TemplateArgument &Arg = Args[ArgIdx];
+
+ // Unwrap argument packs.
+ if (Args[ArgIdx].getKind() == TemplateArgument::Pack) {
+ Args = Arg.pack_begin();
+ NumArgs = Arg.pack_size();
+ ArgIdx = 0;
+ continue;
+ }
+
+ ++ArgIdx;
+ if (ArgIdx == NumArgs)
+ return false;
+
+ if (Arg.isPackExpansion())
+ return true;
+ }
+
+ return false;
+}
+
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
- const TemplateArgumentList &ParamList,
- const TemplateArgumentList &ArgList,
+ const TemplateArgument *Params, unsigned NumParams,
+ const TemplateArgument *Args, unsigned NumArgs,
TemplateDeductionInfo &Info,
- llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
- assert(ParamList.size() == ArgList.size());
- for (unsigned I = 0, N = ParamList.size(); I != N; ++I) {
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ bool NumberOfArgumentsMustMatch) {
+ // C++0x [temp.deduct.type]p9:
+ // If the template argument list of P contains a pack expansion that is not
+ // the last template argument, the entire template argument list is a
+ // non-deduced context.
+ if (hasPackExpansionBeforeEnd(Params, NumParams))
+ return Sema::TDK_Success;
+
+ // C++0x [temp.deduct.type]p9:
+ // If P has a form that contains <T> or <i>, then each argument Pi of the
+ // respective template argument list P is compared with the corresponding
+ // argument Ai of the corresponding template argument list of A.
+ unsigned ArgIdx = 0, ParamIdx = 0;
+ for (; hasTemplateArgumentForDeduction(Params, ParamIdx, NumParams);
+ ++ParamIdx) {
+ if (!Params[ParamIdx].isPackExpansion()) {
+ // The simple case: deduce template arguments by matching Pi and Ai.
+
+ // Check whether we have enough arguments.
+ if (!hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs))
+ return NumberOfArgumentsMustMatch? Sema::TDK_NonDeducedMismatch
+ : Sema::TDK_Success;
+
+ if (Args[ArgIdx].isPackExpansion()) {
+ // FIXME: We follow the logic of C++0x [temp.deduct.type]p22 here,
+ // but applied to pack expansions that are template arguments.
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
+ // Perform deduction for this Pi/Ai pair.
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(S, TemplateParams,
+ Params[ParamIdx], Args[ArgIdx],
+ Info, Deduced))
+ return Result;
+
+ // Move to the next argument.
+ ++ArgIdx;
+ continue;
+ }
+
+ // The parameter is a pack expansion.
+
+ // C++0x [temp.deduct.type]p9:
+ // If Pi is a pack expansion, then the pattern of Pi is compared with
+ // each remaining argument in the template argument list of A. Each
+ // comparison deduces template arguments for subsequent positions in the
+ // template parameter packs expanded by Pi.
+ TemplateArgument Pattern = Params[ParamIdx].getPackExpansionPattern();
+
+ // Compute the set of template parameter indices that correspond to
+ // parameter packs expanded by the pack expansion.
+ llvm::SmallVector<unsigned, 2> PackIndices;
+ {
+ llvm::BitVector SawIndices(TemplateParams->size());
+ llvm::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?");
+
+ // FIXME: If there are no remaining arguments, we can bail out early
+ // and set any deduced parameter packs to an empty argument pack.
+ // The latter part of this is a (minor) correctness issue.
+
+ // Save the deduced template arguments for each parameter pack expanded
+ // by this pack expansion, then clear out the deduction.
+ llvm::SmallVector<DeducedTemplateArgument, 2>
+ SavedPacks(PackIndices.size());
+ llvm::SmallVector<llvm::SmallVector<DeducedTemplateArgument, 4>, 2>
+ NewlyDeducedPacks(PackIndices.size());
+ PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks,
+ NewlyDeducedPacks);
+
+ // Keep track of the deduced template arguments for each parameter pack
+ // expanded by this pack expansion (the outer index) and for each
+ // template argument (the inner SmallVectors).
+ bool HasAnyArguments = false;
+ while (hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs)) {
+ HasAnyArguments = true;
+
+ // Deduce template arguments from the pattern.
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(S, TemplateParams, Pattern, Args[ArgIdx],
+ Info, Deduced))
+ return Result;
+
+ // Capture the deduced template arguments for each parameter pack expanded
+ // by this pack expansion, add them to the list of arguments we've deduced
+ // for that pack, then clear out the deduced argument.
+ 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;
+ }
+
+ // Build argument packs for each of the parameter packs expanded by this
+ // pack expansion.
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(S, TemplateParams,
- ParamList[I], ArgList[I],
- Info, Deduced))
+ = FinishArgumentPackDeduction(S, TemplateParams, HasAnyArguments,
+ Deduced, PackIndices, SavedPacks,
+ NewlyDeducedPacks, Info))
return Result;
}
+
+ // If there is an argument remaining, then we had too many arguments.
+ 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,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ return DeduceTemplateArguments(S, TemplateParams,
+ ParamList.data(), ParamList.size(),
+ ArgList.data(), ArgList.size(),
+ Info, Deduced);
+}
+
/// \brief Determine whether two template arguments are the same.
static bool isSameTemplateArg(ASTContext &Context,
const TemplateArgument &X,
@@ -954,18 +1654,19 @@ static bool isSameTemplateArg(ASTContext &Context,
Y.getAsDecl()->getCanonicalDecl();
case TemplateArgument::Template:
- return Context.getCanonicalTemplateName(X.getAsTemplate())
- .getAsVoidPointer() ==
- Context.getCanonicalTemplateName(Y.getAsTemplate())
- .getAsVoidPointer();
-
+ 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);
+ Y.getAsExpr()->Profile(YID, Context, true);
return XID == YID;
}
@@ -986,51 +1687,192 @@ static bool isSameTemplateArg(ASTContext &Context,
return false;
}
-/// \brief Helper function to build a TemplateParameter when we don't
-/// know its type statically.
-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);
+/// \brief Allocate a TemplateArgumentLoc where all locations have
+/// been initialized to the given location.
+///
+/// \param S The semantic analysis object.
+///
+/// \param The template argument we are producing template argument
+/// location information for.
+///
+/// \param NTTPType For a declaration template argument, the type of
+/// the non-type template parameter that corresponds to this template
+/// argument.
+///
+/// \param Loc The source location to use for the resulting template
+/// argument.
+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");
+ break;
- return TemplateParameter(cast<TemplateTemplateParmDecl>(D));
+ 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::Integral: {
+ Expr *E
+ = S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).takeAs<Expr>();
+ return TemplateArgumentLoc(TemplateArgument(E), E);
+ }
+
+ case TemplateArgument::Template:
+ return TemplateArgumentLoc(Arg, SourceRange(), Loc);
+
+ case TemplateArgument::TemplateExpansion:
+ return TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc);
+
+ case TemplateArgument::Expression:
+ return TemplateArgumentLoc(Arg, Arg.getAsExpr());
+
+ case TemplateArgument::Pack:
+ return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo());
+ }
+
+ return TemplateArgumentLoc();
+}
+
+
+/// \brief Convert the given deduced template argument and add it to the set of
+/// fully-converted template arguments.
+static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
+ DeducedTemplateArgument Arg,
+ NamedDecl *Template,
+ QualType NTTPType,
+ unsigned ArgumentPackIndex,
+ TemplateDeductionInfo &Info,
+ bool InFunctionTemplate,
+ llvm::SmallVectorImpl<TemplateArgument> &Output) {
+ if (Arg.getKind() == TemplateArgument::Pack) {
+ // This is a template argument pack, so check each of its arguments against
+ // the template parameter.
+ llvm::SmallVector<TemplateArgument, 2> PackedArgsBuilder;
+ for (TemplateArgument::pack_iterator PA = Arg.pack_begin(),
+ PAEnd = Arg.pack_end();
+ PA != PAEnd; ++PA) {
+ // When converting the deduced template argument, append it to the
+ // general output list. We need to do this so that the template argument
+ // checking logic has all of the prior template arguments available.
+ DeducedTemplateArgument InnerArg(*PA);
+ InnerArg.setDeducedFromArrayBound(Arg.wasDeducedFromArrayBound());
+ if (ConvertDeducedTemplateArgument(S, Param, InnerArg, Template,
+ NTTPType, PackedArgsBuilder.size(),
+ Info, InFunctionTemplate, Output))
+ return true;
+
+ // Move the converted template argument into our argument pack.
+ PackedArgsBuilder.push_back(Output.back());
+ Output.pop_back();
+ }
+
+ // Create the resulting argument pack.
+ Output.push_back(TemplateArgument::CreatePackCopy(S.Context,
+ PackedArgsBuilder.data(),
+ PackedArgsBuilder.size()));
+ return false;
+ }
+
+ // Convert the deduced template argument into a template
+ // argument that we can check, almost as if the user had written
+ // the template argument explicitly.
+ TemplateArgumentLoc ArgLoc = getTrivialTemplateArgumentLoc(S, Arg, NTTPType,
+ Info.getLocation());
+
+ // Check the template argument, converting it as necessary.
+ 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);
}
/// Complete template argument deduction for a class template partial
/// specialization.
static Sema::TemplateDeductionResult
-FinishTemplateArgumentDeduction(Sema &S,
+FinishTemplateArgumentDeduction(Sema &S,
ClassTemplatePartialSpecializationDecl *Partial,
const TemplateArgumentList &TemplateArgs,
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
TemplateDeductionInfo &Info) {
// Trap errors.
Sema::SFINAETrap Trap(S);
-
+
Sema::ContextRAII SavedContext(S, Partial);
// C++ [temp.deduct.type]p2:
// [...] or if any template argument remains neither deduced nor
// explicitly specified, template argument deduction fails.
- TemplateArgumentListBuilder Builder(Partial->getTemplateParameters(),
- Deduced.size());
- for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
+ llvm::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()) {
- Decl *Param
- = const_cast<NamedDecl *>(
- Partial->getTemplateParameters()->getParam(I));
Info.Param = makeTemplateParameter(Param);
return Sema::TDK_Incomplete;
}
-
- Builder.Append(Deduced[I]);
+
+ // We have deduced this argument, so it still needs to be
+ // checked and converted.
+
+ // First, for a non-type template parameter type that is
+ // initialized by a declaration, we need the type of the
+ // corresponding non-type template parameter.
+ QualType NTTPType;
+ if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+ NTTPType = NTTP->getType();
+ if (NTTPType->isDependentType()) {
+ TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+ Builder.data(), Builder.size());
+ NTTPType = S.SubstType(NTTPType,
+ MultiLevelTemplateArgumentList(TemplateArgs),
+ NTTP->getLocation(),
+ NTTP->getDeclName());
+ if (NTTPType.isNull()) {
+ Info.Param = makeTemplateParameter(Param);
+ // FIXME: These template arguments are temporary. Free them!
+ Info.reset(TemplateArgumentList::CreateCopy(S.Context,
+ Builder.data(),
+ Builder.size()));
+ return Sema::TDK_SubstitutionFailure;
+ }
+ }
+ }
+
+ if (ConvertDeducedTemplateArgument(S, Param, Deduced[I],
+ Partial, NTTPType, 0, Info, false,
+ Builder)) {
+ Info.Param = makeTemplateParameter(Param);
+ // FIXME: These template arguments are temporary. Free them!
+ Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder.data(),
+ Builder.size()));
+ return Sema::TDK_SubstitutionFailure;
+ }
}
-
+
// Form the template argument list from the deduced template arguments.
TemplateArgumentList *DeducedArgumentList
- = new (S.Context) TemplateArgumentList(S.Context, Builder,
- /*TakeArgs=*/true);
+ = TemplateArgumentList::CreateCopy(S.Context, Builder.data(),
+ Builder.size());
+
Info.reset(DeducedArgumentList);
// Substitute the deduced template arguments into the template
@@ -1038,60 +1880,40 @@ FinishTemplateArgumentDeduction(Sema &S,
// verify that the instantiated template arguments are both valid
// and are equivalent to the template arguments originally provided
// to the class template.
- // FIXME: Do we have to correct the types of deduced non-type template
- // arguments (in particular, integral non-type template arguments?).
LocalInstantiationScope InstScope(S);
ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate();
const TemplateArgumentLoc *PartialTemplateArgs
= Partial->getTemplateArgsAsWritten();
- unsigned N = Partial->getNumTemplateArgsAsWritten();
// Note that we don't provide the langle and rangle locations.
TemplateArgumentListInfo InstArgs;
- for (unsigned I = 0; I != N; ++I) {
- Decl *Param = const_cast<NamedDecl *>(
- ClassTemplate->getTemplateParameters()->getParam(I));
- TemplateArgumentLoc InstArg;
- if (S.Subst(PartialTemplateArgs[I], InstArg,
- MultiLevelTemplateArgumentList(*DeducedArgumentList))) {
- Info.Param = makeTemplateParameter(Param);
- Info.FirstArg = PartialTemplateArgs[I].getArgument();
- return Sema::TDK_SubstitutionFailure;
- }
- InstArgs.addArgument(InstArg);
- }
+ 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;
- TemplateArgumentListBuilder ConvertedInstArgs(
- ClassTemplate->getTemplateParameters(), N);
+ Decl *Param
+ = const_cast<NamedDecl *>(
+ Partial->getTemplateParameters()->getParam(ParamIdx));
+ Info.Param = makeTemplateParameter(Param);
+ Info.FirstArg = PartialTemplateArgs[ArgIdx].getArgument();
+ return Sema::TDK_SubstitutionFailure;
+ }
+ llvm::SmallVector<TemplateArgument, 4> ConvertedInstArgs;
if (S.CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(),
- InstArgs, false, ConvertedInstArgs))
+ InstArgs, false, ConvertedInstArgs))
return Sema::TDK_SubstitutionFailure;
-
- for (unsigned I = 0, E = ConvertedInstArgs.flatSize(); I != E; ++I) {
- TemplateArgument InstArg = ConvertedInstArgs.getFlatArguments()[I];
-
- Decl *Param = const_cast<NamedDecl *>(
- ClassTemplate->getTemplateParameters()->getParam(I));
-
- if (InstArg.getKind() == TemplateArgument::Expression) {
- // 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
- = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
- if (S.CheckTemplateArgument(NTTP, NTTP->getType(), InstExpr, InstArg)) {
- Info.Param = makeTemplateParameter(Param);
- Info.FirstArg = Partial->getTemplateArgs()[I];
- 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(Param);
+ Info.Param = makeTemplateParameter(TemplateParams->getParam(I));
Info.FirstArg = TemplateArgs[I];
Info.SecondArg = InstArg;
return Sema::TDK_NonDeducedMismatch;
@@ -1127,14 +1949,14 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
return Result;
InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial,
- Deduced.data(), Deduced.size());
+ Deduced.data(), Deduced.size(), Info);
if (Inst)
return TDK_InstantiationDepth;
if (Trap.hasErrorOccurred())
return Sema::TDK_SubstitutionFailure;
-
- return ::FinishTemplateArgumentDeduction(*this, Partial, TemplateArgs,
+
+ return ::FinishTemplateArgumentDeduction(*this, Partial, TemplateArgs,
Deduced, Info);
}
@@ -1206,26 +2028,24 @@ Sema::SubstituteExplicitTemplateArguments(
// 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,
- ExplicitTemplateArgs.size());
+ llvm::SmallVector<TemplateArgument, 4> Builder;
// 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);
+ ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution,
+ Info);
if (Inst)
return TDK_InstantiationDepth;
- ContextRAII SavedContext(*this, FunctionTemplate->getTemplatedDecl());
-
if (CheckTemplateArgumentList(FunctionTemplate,
SourceLocation(),
ExplicitTemplateArgs,
true,
Builder) || Trap.hasErrorOccurred()) {
- unsigned Index = Builder.structuredSize();
+ unsigned Index = Builder.size();
if (Index >= TemplateParams->size())
Index = TemplateParams->size() - 1;
Info.Param = makeTemplateParameter(TemplateParams->getParam(Index));
@@ -1235,25 +2055,38 @@ Sema::SubstituteExplicitTemplateArguments(
// Form the template argument list from the explicitly-specified
// template arguments.
TemplateArgumentList *ExplicitArgumentList
- = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
+ = TemplateArgumentList::CreateCopy(Context, Builder.data(), Builder.size());
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;
+ // Template argument deduction and the final substitution should be
+ // done in the context of the templated declaration. Explicit
+ // argument substitution, on the other hand, needs to happen in the
+ // calling context.
+ ContextRAII SavedContext(*this, FunctionTemplate->getTemplatedDecl());
- ParamTypes.push_back(ParamType);
+ // If we deduced template arguments for a template parameter pack,
+ // note that the template argument pack is partially substituted and record
+ // the explicit template arguments. They'll be used as part of deduction
+ // for this template parameter pack.
+ 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;
+ }
}
+ // Instantiate the types of each of the function parameters given the
+ // explicitly-specified template arguments.
+ if (SubstParmTypes(Function->getLocation(),
+ Function->param_begin(), Function->getNumParams(),
+ MultiLevelTemplateArgumentList(*ExplicitArgumentList),
+ ParamTypes))
+ return TDK_SubstitutionFailure;
+
// If the caller wants a full function type back, instantiate the return
// type and form that function type.
if (FunctionType) {
@@ -1274,6 +2107,7 @@ Sema::SubstituteExplicitTemplateArguments(
ParamTypes.data(), ParamTypes.size(),
Proto->isVariadic(),
Proto->getTypeQuals(),
+ Proto->getRefQualifier(),
Function->getLocation(),
Function->getDeclName(),
Proto->getExtInfo());
@@ -1287,67 +2121,20 @@ Sema::SubstituteExplicitTemplateArguments(
// 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.
+ // Take all of the explicitly-specified arguments and put them into
+ // the set of deduced template arguments. Explicitly-specified
+ // parameter packs, however, will be set to NULL since the deduction
+ // mechanisms handle explicitly-specified argument packs directly.
Deduced.reserve(TemplateParams->size());
- for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I)
- Deduced.push_back(ExplicitArgumentList->get(I));
-
- return TDK_Success;
-}
-
-/// \brief Allocate a TemplateArgumentLoc where all locations have
-/// been initialized to the given location.
-///
-/// \param S The semantic analysis object.
-///
-/// \param The template argument we are producing template argument
-/// location information for.
-///
-/// \param NTTPType For a declaration template argument, the type of
-/// the non-type template parameter that corresponds to this template
-/// argument.
-///
-/// \param Loc The source location to use for the resulting template
-/// argument.
-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");
- break;
-
- 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::Integral: {
- Expr *E
- = S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).takeAs<Expr>();
- return TemplateArgumentLoc(TemplateArgument(E), E);
- }
-
- case TemplateArgument::Template:
- return TemplateArgumentLoc(Arg, SourceRange(), Loc);
-
- case TemplateArgument::Expression:
- return TemplateArgumentLoc(Arg, Arg.getAsExpr());
-
- case TemplateArgument::Pack:
- llvm_unreachable("Template parameter packs are not yet supported");
+ 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 TemplateArgumentLoc();
+ return TDK_Success;
}
/// \brief Finish template argument deduction for a function template,
@@ -1370,7 +2157,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
// actual function declaration.
InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
FunctionTemplate, Deduced.data(), Deduced.size(),
- ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution);
+ ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
+ Info);
if (Inst)
return TDK_InstantiationDepth;
@@ -1379,18 +2167,16 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
// 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) {
- NamedDecl *Param = FunctionTemplate->getTemplateParameters()->getParam(I);
+ llvm::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 ||
- Deduced[I].getKind() == TemplateArgument::Type) {
+ if (I < NumExplicitlySpecified) {
// We have already fully type-checked and converted this
- // argument (because it was explicitly-specified) or no
- // additional checking is necessary (because it's a template
- // type parameter). Just record the presence of this
- // parameter.
- Builder.Append(Deduced[I]);
+ // argument, because it was explicitly-specified. Just record the
+ // presence of this argument.
+ Builder.push_back(Deduced[I]);
continue;
}
@@ -1401,55 +2187,61 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
// initialized by a declaration, we need the type of the
// corresponding non-type template parameter.
QualType NTTPType;
- if (NonTypeTemplateParmDecl *NTTP
- = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
- if (Deduced[I].getKind() == TemplateArgument::Declaration) {
- NTTPType = NTTP->getType();
- if (NTTPType->isDependentType()) {
- TemplateArgumentList TemplateArgs(Context, Builder,
- /*TakeArgs=*/false);
- NTTPType = SubstType(NTTPType,
- MultiLevelTemplateArgumentList(TemplateArgs),
- NTTP->getLocation(),
- NTTP->getDeclName());
- if (NTTPType.isNull()) {
- Info.Param = makeTemplateParameter(Param);
- Info.reset(new (Context) TemplateArgumentList(Context, Builder,
- /*TakeArgs=*/true));
- return TDK_SubstitutionFailure;
- }
+ 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);
+ // FIXME: These template arguments are temporary. Free them!
+ Info.reset(TemplateArgumentList::CreateCopy(Context,
+ Builder.data(),
+ Builder.size()));
+ return TDK_SubstitutionFailure;
}
}
}
- // Convert the deduced template argument into a template
- // argument that we can check, almost as if the user had written
- // the template argument explicitly.
- TemplateArgumentLoc Arg = getTrivialTemplateArgumentLoc(*this,
- Deduced[I],
- NTTPType,
- SourceLocation());
-
- // Check the template argument, converting it as necessary.
- if (CheckTemplateArgument(Param, Arg,
- FunctionTemplate,
- FunctionTemplate->getLocation(),
- FunctionTemplate->getSourceRange().getEnd(),
- Builder,
- Deduced[I].wasDeducedFromArrayBound()
- ? CTAK_DeducedFromArrayBound
- : CTAK_Deduced)) {
- Info.Param = makeTemplateParameter(
- const_cast<NamedDecl *>(TemplateParams->getParam(I)));
- Info.reset(new (Context) TemplateArgumentList(Context, Builder,
- /*TakeArgs=*/true));
+ if (ConvertDeducedTemplateArgument(*this, Param, Deduced[I],
+ FunctionTemplate, NTTPType, 0, Info,
+ true, Builder)) {
+ Info.Param = makeTemplateParameter(Param);
+ // FIXME: These template arguments are temporary. Free them!
+ Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(),
+ Builder.size()));
return TDK_SubstitutionFailure;
}
continue;
}
- // Substitute into the default template argument, if available.
+ // C++0x [temp.arg.explicit]p3:
+ // A trailing template parameter pack (14.5.3) not otherwise deduced will
+ // be deduced to an empty sequence of template arguments.
+ // FIXME: Where did the word "trailing" come from?
+ if (Param->isTemplateParameterPack()) {
+ // We may have had explicitly-specified template arguments for this
+ // template parameter pack. If so, our empty deduction extends the
+ // explicitly-specified set (C++0x [temp.arg.explicit]p9).
+ const TemplateArgument *ExplicitArgs;
+ unsigned NumExplicitArgs;
+ if (CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs,
+ &NumExplicitArgs)
+ == Param)
+ Builder.push_back(TemplateArgument(ExplicitArgs, NumExplicitArgs));
+ else
+ Builder.push_back(TemplateArgument(0, 0));
+
+ continue;
+ }
+
+ // Substitute into the default template argument, if available.
TemplateArgumentLoc DefArg
= SubstDefaultTemplateArgumentIfAvailable(FunctionTemplate,
FunctionTemplate->getLocation(),
@@ -1463,18 +2255,19 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
const_cast<NamedDecl *>(TemplateParams->getParam(I)));
return TDK_Incomplete;
}
-
+
// Check whether we can actually use the default argument.
if (CheckTemplateArgument(Param, DefArg,
FunctionTemplate,
FunctionTemplate->getLocation(),
FunctionTemplate->getSourceRange().getEnd(),
- Builder,
+ 0, Builder,
CTAK_Deduced)) {
Info.Param = makeTemplateParameter(
const_cast<NamedDecl *>(TemplateParams->getParam(I)));
- Info.reset(new (Context) TemplateArgumentList(Context, Builder,
- /*TakeArgs=*/true));
+ // FIXME: These template arguments are temporary. Free them!
+ Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(),
+ Builder.size()));
return TDK_SubstitutionFailure;
}
@@ -1483,7 +2276,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
// Form the template argument list from the deduced template arguments.
TemplateArgumentList *DeducedArgumentList
- = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
+ = TemplateArgumentList::CreateCopy(Context, Builder.data(), Builder.size());
Info.reset(DeducedArgumentList);
// Substitute the deduced template arguments into the function template
@@ -1497,9 +2290,9 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
if (!Specialization)
return TDK_SubstitutionFailure;
- assert(Specialization->getPrimaryTemplate()->getCanonicalDecl() ==
+ assert(Specialization->getPrimaryTemplate()->getCanonicalDecl() ==
FunctionTemplate->getCanonicalDecl());
-
+
// If the template argument list is owned by the function template
// specialization, release it.
if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList &&
@@ -1514,6 +2307,18 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
return TDK_SubstitutionFailure;
}
+ // If we suppressed any diagnostics while performing template argument
+ // deduction, and if we haven't already instantiated this declaration,
+ // keep track of these diagnostics. They'll be emitted if this specialization
+ // is actually used.
+ if (Info.diag_begin() != Info.diag_end()) {
+ llvm::DenseMap<Decl *, llvm::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;
}
@@ -1544,7 +2349,7 @@ static QualType
ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
Expr *Arg, QualType ParamType,
bool ParamWasReference) {
-
+
OverloadExpr::FindResult R = OverloadExpr::find(Arg);
OverloadExpr *Ovl = R.Expression;
@@ -1592,10 +2397,10 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
if (ArgType.isNull()) continue;
// Function-to-pointer conversion.
- if (!ParamWasReference && ParamType->isPointerType() &&
+ if (!ParamWasReference && ParamType->isPointerType() &&
ArgType->isFunctionType())
ArgType = S.Context.getPointerType(ArgType);
-
+
// - If the argument is an overload set (not containing function
// templates), trial argument deduction is attempted using each
// of the members of the set. If deduction succeeds for only one
@@ -1608,7 +2413,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
// Type deduction is done independently for each P/A pair, and
// the deduced template argument values are then combined.
// So we do not reject deductions which were made elsewhere.
- llvm::SmallVector<DeducedTemplateArgument, 8>
+ llvm::SmallVector<DeducedTemplateArgument, 8>
Deduced(TemplateParams->size());
TemplateDeductionInfo Info(S.Context, Ovl->getNameLoc());
Sema::TemplateDeductionResult Result
@@ -1623,6 +2428,113 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
return Match;
}
+/// \brief Perform the adjustments to the parameter and argument types
+/// described in C++ [temp.deduct.call].
+///
+/// \returns true if the caller should not attempt to perform any template
+/// argument deduction based on this P/A pair.
+static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
+ TemplateParameterList *TemplateParams,
+ QualType &ParamType,
+ QualType &ArgType,
+ Expr *Arg,
+ unsigned &TDF) {
+ // 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.
+ if (ParamType.getCVRQualifiers())
+ ParamType = ParamType.getLocalUnqualifiedType();
+ const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>();
+ if (ParamRefType) {
+ QualType PointeeType = ParamRefType->getPointeeType();
+
+ // [C++0x] If P is an rvalue reference to a cv-unqualified
+ // template parameter and the argument is an lvalue, the type
+ // "lvalue reference to A" is used in place of A for type
+ // deduction.
+ if (isa<RValueReferenceType>(ParamType)) {
+ if (!PointeeType.getQualifiers() &&
+ isa<TemplateTypeParmType>(PointeeType) &&
+ Arg->Classify(S.Context).isLValue())
+ ArgType = S.Context.getLValueReferenceType(ArgType);
+ }
+
+ // [...] If P is a reference type, the type referred to by P is used
+ // for type deduction.
+ ParamType = PointeeType;
+ }
+
+ // Overload sets usually make this parameter an undeduced
+ // context, but there are sometimes special circumstances.
+ if (ArgType == S.Context.OverloadTy) {
+ ArgType = ResolveOverloadForDeduction(S, TemplateParams,
+ Arg, ParamType,
+ ParamRefType != 0);
+ if (ArgType.isNull())
+ return true;
+ }
+
+ if (ParamRefType) {
+ // C++0x [temp.deduct.call]p3:
+ // [...] 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 (ParamRefType->isRValueReferenceType() &&
+ ParamRefType->getAs<TemplateTypeParmType>() &&
+ Arg->isLValue())
+ ArgType = S.Context.getLValueReferenceType(ArgType);
+ } else {
+ // C++ [temp.deduct.call]p2:
+ // If P is not a reference type:
+ // - 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 = S.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
+ // of A for type deduction; otherwise,
+ else if (ArgType->isFunctionType())
+ ArgType = S.Context.getPointerType(ArgType);
+ else {
+ // - If A is a cv-qualified type, the top level cv-qualifiers of A's
+ // type are ignored for type deduction.
+ if (ArgType.getCVRQualifiers())
+ ArgType = ArgType.getUnqualifiedType();
+ }
+ }
+
+ // 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). [...]
+ 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 (ParamRefType)
+ 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
+ // conversion (4.4).
+ if (ArgType->isPointerType() || ArgType->isMemberPointerType() ||
+ ArgType->isObjCObjectPointerType())
+ TDF |= TDF_IgnoreQualifiers;
+ // - 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) &&
+ isSimpleTemplateIdType(
+ ParamType->getAs<PointerType>()->getPointeeType())))
+ TDF |= TDF_DerivedClass;
+
+ return false;
+}
+
/// \brief Perform template argument deduction from a function call
/// (C++ [temp.deduct.call]).
///
@@ -1639,7 +2551,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
/// \param Name the name of the function being called. This is only significant
/// when the function template is a conversion function template, in which
/// case this routine will also perform template argument deduction based on
-/// the function to which
+/// the function to which
///
/// \param Specialization if template argument deduction was successful,
/// this will be set to the function template specialization produced by
@@ -1667,10 +2579,12 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
else if (NumArgs > Function->getNumParams()) {
const FunctionProtoType *Proto
= Function->getType()->getAs<FunctionProtoType>();
- if (!Proto->isVariadic())
+ if (Proto->isTemplateVariadic())
+ /* Do nothing */;
+ else if (Proto->isVariadic())
+ CheckArgs = Function->getNumParams();
+ else
return TDK_TooManyArguments;
-
- CheckArgs = Function->getNumParams();
}
// The types of the parameters from which we will perform template argument
@@ -1695,105 +2609,126 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
NumExplicitlySpecified = Deduced.size();
} else {
// Just fill in the parameter types from the function declaration.
- for (unsigned I = 0; I != CheckArgs; ++I)
+ for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I)
ParamTypes.push_back(Function->getParamDecl(I)->getType());
}
// Deduce template arguments from the function parameters.
Deduced.resize(TemplateParams->size());
- for (unsigned I = 0; I != CheckArgs; ++I) {
- QualType ParamType = ParamTypes[I];
- QualType ArgType = Args[I]->getType();
+ unsigned ArgIdx = 0;
+ for (unsigned ParamIdx = 0, NumParams = ParamTypes.size();
+ ParamIdx != NumParams; ++ParamIdx) {
+ QualType ParamType = ParamTypes[ParamIdx];
+
+ const PackExpansionType *ParamExpansion
+ = dyn_cast<PackExpansionType>(ParamType);
+ if (!ParamExpansion) {
+ // Simple case: matching a function parameter to a function argument.
+ if (ArgIdx >= CheckArgs)
+ break;
- // 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.
- if (ParamType.getCVRQualifiers())
- ParamType = ParamType.getLocalUnqualifiedType();
- const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>();
- if (ParamRefType) {
- // [...] If P is a reference type, the type referred to by P is used
- // for type deduction.
- ParamType = ParamRefType->getPointeeType();
- }
-
- // Overload sets usually make this parameter an undeduced
- // context, but there are sometimes special circumstances.
- if (ArgType == Context.OverloadTy) {
- ArgType = ResolveOverloadForDeduction(*this, TemplateParams,
- Args[I], ParamType,
- ParamRefType != 0);
- if (ArgType.isNull())
+ Expr *Arg = Args[ArgIdx++];
+ QualType ArgType = Arg->getType();
+ unsigned TDF = 0;
+ if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams,
+ ParamType, ArgType, Arg,
+ TDF))
continue;
+
+ if (TemplateDeductionResult Result
+ = ::DeduceTemplateArguments(*this, TemplateParams,
+ ParamType, ArgType, Info, Deduced,
+ TDF))
+ return Result;
+
+ // FIXME: we need to check that the deduced A is the same as A,
+ // modulo the various allowed differences.
+ continue;
}
- if (ParamRefType) {
- // C++0x [temp.deduct.call]p3:
- // [...] 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 (ParamRefType->isRValueReferenceType() &&
- ParamRefType->getAs<TemplateTypeParmType>() &&
- Args[I]->isLvalue(Context) == Expr::LV_Valid)
- ArgType = Context.getLValueReferenceType(ArgType);
- } else {
- // C++ [temp.deduct.call]p2:
- // If P is not a reference type:
- // - 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
- // of A for type deduction; otherwise,
- else if (ArgType->isFunctionType())
- ArgType = Context.getPointerType(ArgType);
- else {
- // - If A is a cv-qualified type, the top level cv-qualifiers of A’s
- // type are ignored for type deduction.
- QualType CanonArgType = Context.getCanonicalType(ArgType);
- if (ArgType.getCVRQualifiers())
- ArgType = ArgType.getUnqualifiedType();
+ // C++0x [temp.deduct.call]p1:
+ // For a function parameter pack that occurs at the end of the
+ // parameter-declaration-list, the type A of each remaining argument of
+ // the call is compared with the type P of the declarator-id of the
+ // function parameter pack. Each comparison deduces template arguments
+ // for subsequent positions in the template parameter packs expanded by
+ // the function parameter pack. For a function parameter pack that does
+ // not occur at the end of the parameter-declaration-list, the type of
+ // the parameter pack is a non-deduced context.
+ if (ParamIdx + 1 < NumParams)
+ break;
+
+ QualType ParamPattern = ParamExpansion->getPattern();
+ llvm::SmallVector<unsigned, 2> PackIndices;
+ {
+ llvm::BitVector SawIndices(TemplateParams->size());
+ llvm::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?");
+
+ // Keep track of the deduced template arguments for each parameter pack
+ // expanded by this pack expansion (the outer index) and for each
+ // template argument (the inner SmallVectors).
+ llvm::SmallVector<llvm::SmallVector<DeducedTemplateArgument, 4>, 2>
+ NewlyDeducedPacks(PackIndices.size());
+ llvm::SmallVector<DeducedTemplateArgument, 2>
+ SavedPacks(PackIndices.size());
+ PrepareArgumentPackDeduction(*this, Deduced, PackIndices, SavedPacks,
+ NewlyDeducedPacks);
+ bool HasAnyArguments = false;
+ for (; ArgIdx < NumArgs; ++ArgIdx) {
+ HasAnyArguments = true;
+
+ ParamType = ParamPattern;
+ Expr *Arg = Args[ArgIdx];
+ QualType ArgType = Arg->getType();
+ unsigned TDF = 0;
+ if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams,
+ ParamType, ArgType, Arg,
+ TDF)) {
+ // We can't actually perform any deduction for this argument, so stop
+ // deduction at this point.
+ ++ArgIdx;
+ break;
+ }
- // 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 = 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 (ParamRefType)
- 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
- // conversion (4.4).
- if (ArgType->isPointerType() || ArgType->isMemberPointerType() ||
- ArgType->isObjCObjectPointerType())
- TDF |= TDF_IgnoreQualifiers;
- // - 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) &&
- isSimpleTemplateIdType(
- ParamType->getAs<PointerType>()->getPointeeType())))
- TDF |= TDF_DerivedClass;
+ if (TemplateDeductionResult Result
+ = ::DeduceTemplateArguments(*this, TemplateParams,
+ ParamType, ArgType, Info, Deduced,
+ TDF))
+ return Result;
- if (TemplateDeductionResult Result
- = ::DeduceTemplateArguments(*this, TemplateParams,
- ParamType, ArgType, Info, Deduced,
- TDF))
+ // Capture the deduced template arguments for each parameter pack expanded
+ // by this pack expansion, add them to the list of arguments we've deduced
+ // for that pack, then clear out the deduced argument.
+ 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();
+ }
+ }
+ }
+
+ // Build argument packs for each of the parameter packs expanded by this
+ // pack expansion.
+ if (Sema::TemplateDeductionResult Result
+ = FinishArgumentPackDeduction(*this, TemplateParams, HasAnyArguments,
+ Deduced, PackIndices, SavedPacks,
+ NewlyDeducedPacks, Info))
return Result;
- // FIXME: we need to check that the deduced A is the same as A,
- // modulo the various allowed differences.
+ // After we've matching against a parameter pack, we're done.
+ break;
}
return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
@@ -1808,7 +2743,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
/// \param FunctionTemplate the function template for which we are performing
/// template argument deduction.
///
-/// \param ExplicitTemplateArguments the explicitly-specified template
+/// \param ExplicitTemplateArguments the explicitly-specified template
/// arguments.
///
/// \param ArgFunctionType the function type that will be used as the
@@ -1862,13 +2797,23 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
if (TemplateDeductionResult Result
= ::DeduceTemplateArguments(*this, TemplateParams,
FunctionType, ArgFunctionType, Info,
- Deduced, 0))
+ Deduced, TDF_TopLevelParameterTypeList))
return Result;
}
-
- return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
- NumExplicitlySpecified,
- Specialization, Info);
+
+ if (TemplateDeductionResult Result
+ = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
+ NumExplicitlySpecified,
+ Specialization, Info))
+ return Result;
+
+ // If the requested function type does not match the actual type of the
+ // specialization, template argument deduction fails.
+ if (!ArgFunctionType.isNull() &&
+ !Context.hasSameType(ArgFunctionType, Specialization->getType()))
+ return TDK_NonDeducedMismatch;
+
+ return TDK_Success;
}
/// \brief Deduce template arguments for a templated conversion
@@ -1915,12 +2860,12 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
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.
+ // 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
+ // If A is a cv-qualified type, the top level cv-qualifiers of A's
// type are ignored for type deduction.
A = A.getUnqualifiedType();
}
@@ -1950,7 +2895,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
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
+ // type that can be converted to A via a qualification
// conversion.
//
// (C++0x [temp.deduct.conv]p6 clarifies that this only happens when
@@ -1971,7 +2916,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
LocalInstantiationScope InstScope(*this);
FunctionDecl *Spec = 0;
TemplateDeductionResult Result
- = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, 0, Spec,
+ = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, 0, Spec,
Info);
Specialization = cast_or_null<CXXConversionDecl>(Spec);
return Result;
@@ -1983,7 +2928,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
/// \param FunctionTemplate the function template for which we are performing
/// template argument deduction.
///
-/// \param ExplicitTemplateArguments the explicitly-specified template
+/// \param ExplicitTemplateArguments the explicitly-specified template
/// arguments.
///
/// \param Specialization if template argument deduction was successful,
@@ -2003,88 +2948,93 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
QualType(), Specialization, Info);
}
-/// \brief Stores the result of comparing the qualifiers of two types.
-enum DeductionQualifierComparison {
- NeitherMoreQualified = 0,
- ParamMoreQualified,
- ArgMoreQualified
-};
+namespace {
+ /// Substitute the 'auto' type specifier within a type for a given replacement
+ /// type.
+ 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 we're building the type pattern to deduce against, don't wrap the
+ // substituted type in an AutoType. Certain template deduction rules
+ // apply only when a template type parameter appears directly (and not if
+ // the parameter is found through desugaring). For instance:
+ // auto &&lref = lvalue;
+ // must transform into "rvalue reference to T" not "rvalue reference to
+ // auto type deduced as T" in order for [temp.deduct.call]p3 to apply.
+ if (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;
+ }
+ }
+ };
+}
-/// \brief Deduce the template arguments during partial ordering by comparing
-/// the parameter type and the argument type (C++0x [temp.deduct.partial]).
-///
-/// \param S the semantic analysis object within which we are deducing
+/// \brief Deduce the type for an auto type-specifier (C++0x [dcl.spec.auto]p6)
///
-/// \param TemplateParams the template parameters that we are deducing
-///
-/// \param ParamIn the parameter type
-///
-/// \param ArgIn the argument type
+/// \param Type the type pattern using the auto type-specifier.
///
-/// \param Info information about the template argument deduction itself
+/// \param Init the initializer for the variable whose type is to be deduced.
///
-/// \param Deduced the deduced template arguments
+/// \param Result if type deduction was successful, this will be set to the
+/// deduced type. This may still contain undeduced autos if the type is
+/// dependent.
///
-/// \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(Sema &S,
- TemplateParameterList *TemplateParams,
- QualType ParamIn, QualType ArgIn,
- TemplateDeductionInfo &Info,
- llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- llvm::SmallVectorImpl<DeductionQualifierComparison> *QualifierComparisons) {
- CanQualType Param = S.Context.getCanonicalType(ParamIn);
- CanQualType Arg = S.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.isNull())
- 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.isNull())
- Arg = ArgRef->getPointeeType();
-
- if (QualifierComparisons && !ParamRef.isNull() && !ArgRef.isNull()) {
- // 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(S, TemplateParams, Param, Arg, Info,
- Deduced, TDF_None);
+/// \returns true if deduction succeeded, false if it failed.
+bool
+Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) {
+ if (Init->isTypeDependent()) {
+ Result = Type;
+ return true;
+ }
+
+ SourceLocation Loc = Init->getExprLoc();
+
+ LocalInstantiationScope InstScope(*this);
+
+ // Build template<class TemplParam> void Func(FuncParam);
+ NamedDecl *TemplParam
+ = TemplateTypeParmDecl::Create(Context, 0, Loc, 0, 0, 0, false, false);
+ TemplateParameterList *TemplateParams
+ = TemplateParameterList::Create(Context, Loc, Loc, &TemplParam, 1, Loc);
+
+ QualType TemplArg = Context.getTemplateTypeParmType(0, 0, false);
+ QualType FuncParam =
+ SubstituteAutoTransform(*this, TemplArg).TransformType(Type);
+
+ // Deduce type of TemplParam in Func(Init)
+ llvm::SmallVector<DeducedTemplateArgument, 1> Deduced;
+ Deduced.resize(1);
+ QualType InitType = Init->getType();
+ unsigned TDF = 0;
+ if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams,
+ FuncParam, InitType, Init,
+ TDF))
+ return false;
+
+ TemplateDeductionInfo Info(Context, Loc);
+ if (::DeduceTemplateArguments(*this, TemplateParams,
+ FuncParam, InitType, Info, Deduced,
+ TDF))
+ return false;
+
+ QualType DeducedType = Deduced[0].getAsType();
+ if (DeducedType.isNull())
+ return false;
+
+ Result = SubstituteAutoTransform(*this, DeducedType).TransformType(Type);
+ return true;
}
static void
@@ -2092,7 +3042,31 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
bool OnlyDeduced,
unsigned Level,
llvm::SmallVectorImpl<bool> &Deduced);
-
+
+/// \brief If this is a non-static member function,
+static void MaybeAddImplicitObjectParameterType(ASTContext &Context,
+ CXXMethodDecl *Method,
+ llvm::SmallVectorImpl<QualType> &ArgTypes) {
+ if (Method->isStatic())
+ return;
+
+ // C++ [over.match.funcs]p4:
+ //
+ // For non-static member functions, the type of the implicit
+ // object parameter is
+ // - "lvalue reference to cv X" for functions declared without a
+ // ref-qualifier or with the & ref-qualifier
+ // - "rvalue reference to cv X" for functions declared with the
+ // && ref-qualifier
+ //
+ // FIXME: We don't have ref-qualifiers yet, so we don't do that part.
+ QualType ArgTy = Context.getTypeDeclType(Method->getParent());
+ ArgTy = Context.getQualifiedType(ArgTy,
+ Qualifiers::fromCVRMask(Method->getTypeQualifiers()));
+ ArgTy = Context.getLValueReferenceType(ArgTy);
+ ArgTypes.push_back(ArgTy);
+}
+
/// \brief Determine whether the function template \p FT1 is at least as
/// specialized as \p FT2.
static bool isAtLeastAsSpecializedAs(Sema &S,
@@ -2100,12 +3074,13 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
FunctionTemplateDecl *FT1,
FunctionTemplateDecl *FT2,
TemplatePartialOrderingContext TPOC,
- llvm::SmallVectorImpl<DeductionQualifierComparison> *QualifierComparisons) {
+ unsigned NumCallArguments,
+ llvm::SmallVectorImpl<RefParamPartialOrderingComparison> *RefParamComparisons) {
FunctionDecl *FD1 = FT1->getTemplatedDecl();
- FunctionDecl *FD2 = FT2->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<DeducedTemplateArgument, 4> Deduced;
@@ -2115,55 +3090,89 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
// The types used to determine the ordering depend on the context in which
// the partial ordering is done:
TemplateDeductionInfo Info(S.Context, Loc);
+ CXXMethodDecl *Method1 = 0;
+ CXXMethodDecl *Method2 = 0;
+ bool IsNonStatic2 = false;
+ bool IsNonStatic1 = false;
+ unsigned Skip2 = 0;
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,
- TemplateParams,
- Proto2->getArgType(I),
- Proto1->getArgType(I),
- Info,
- Deduced,
- QualifierComparisons))
+ Method1 = dyn_cast<CXXMethodDecl>(FD1);
+ Method2 = dyn_cast<CXXMethodDecl>(FD2);
+ IsNonStatic1 = Method1 && !Method1->isStatic();
+ IsNonStatic2 = Method2 && !Method2->isStatic();
+
+ // C++0x [temp.func.order]p3:
+ // [...] If only one of the function templates is a non-static
+ // member, that function template is considered to have a new
+ // first parameter inserted in its function parameter list. The
+ // new parameter is of type "reference to cv A," where cv are
+ // the cv-qualifiers of the function template (if any) and A is
+ // the class of which the function template is a member.
+ //
+ // C++98/03 doesn't have this provision, so instead we drop the
+ // first argument of the free function or static member, which
+ // seems to match existing practice.
+ llvm::SmallVector<QualType, 4> Args1;
+ unsigned Skip1 = !S.getLangOptions().CPlusPlus0x &&
+ IsNonStatic2 && !IsNonStatic1;
+ if (S.getLangOptions().CPlusPlus0x && IsNonStatic1 && !IsNonStatic2)
+ MaybeAddImplicitObjectParameterType(S.Context, Method1, Args1);
+ Args1.insert(Args1.end(),
+ Proto1->arg_type_begin() + Skip1, Proto1->arg_type_end());
+
+ llvm::SmallVector<QualType, 4> Args2;
+ Skip2 = !S.getLangOptions().CPlusPlus0x &&
+ IsNonStatic1 && !IsNonStatic2;
+ if (S.getLangOptions().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1)
+ MaybeAddImplicitObjectParameterType(S.Context, Method2, Args2);
+ Args2.insert(Args2.end(),
+ Proto2->arg_type_begin() + Skip2, Proto2->arg_type_end());
+
+ // C++ [temp.func.order]p5:
+ // The presence of unused ellipsis and default arguments has no effect on
+ // the partial ordering of function templates.
+ if (Args1.size() > NumCallArguments)
+ Args1.resize(NumCallArguments);
+ if (Args2.size() > NumCallArguments)
+ Args2.resize(NumCallArguments);
+ if (DeduceTemplateArguments(S, TemplateParams, Args2.data(), Args2.size(),
+ Args1.data(), Args1.size(), Info, Deduced,
+ TDF_None, /*PartialOrdering=*/true,
+ RefParamComparisons))
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,
- TemplateParams,
- Proto2->getResultType(),
- Proto1->getResultType(),
- Info,
- Deduced,
- QualifierComparisons))
+ if (DeduceTemplateArguments(S, TemplateParams, Proto2->getResultType(),
+ Proto1->getResultType(), Info, Deduced,
+ TDF_None, /*PartialOrdering=*/true,
+ RefParamComparisons))
return false;
break;
-
+
case TPOC_Other:
- // - In other contexts (14.6.6.2) the function template’s function type
+ // - In other contexts (14.6.6.2) the function template's function type
// is used.
- if (DeduceTemplateArgumentsDuringPartialOrdering(S,
- TemplateParams,
- FD2->getType(),
- FD1->getType(),
- Info,
- Deduced,
- QualifierComparisons))
+ // FIXME: Don't we actually want to perform the adjustments on the parameter
+ // types?
+ if (DeduceTemplateArguments(S, TemplateParams, FD2->getType(),
+ FD1->getType(), Info, Deduced, TDF_None,
+ /*PartialOrdering=*/true, RefParamComparisons))
return false;
break;
}
-
+
// 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
+ // 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();
@@ -2172,7 +3181,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
break;
if (ArgIdx == NumArgs) {
- // All template arguments were deduced. FT1 is at least as specialized
+ // All template arguments were deduced. FT1 is at least as specialized
// as FT2.
return true;
}
@@ -2182,37 +3191,62 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
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,
+ unsigned NumParams = std::min(NumCallArguments,
+ std::min(Proto1->getNumArgs(),
+ Proto2->getNumArgs()));
+ if (S.getLangOptions().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1)
+ ::MarkUsedTemplateParameters(S, Method2->getThisType(S.Context), false,
+ TemplateParams->getDepth(), UsedParameters);
+ for (unsigned I = Skip2; I < NumParams; ++I)
+ ::MarkUsedTemplateParameters(S, Proto2->getArgType(I), false,
TemplateParams->getDepth(),
UsedParameters);
break;
}
-
+
case TPOC_Conversion:
- ::MarkUsedTemplateParameters(S, Proto2->getResultType(), false,
+ ::MarkUsedTemplateParameters(S, Proto2->getResultType(), false,
TemplateParams->getDepth(),
UsedParameters);
break;
-
+
case TPOC_Other:
- ::MarkUsedTemplateParameters(S, FD2->getType(), false,
+ ::MarkUsedTemplateParameters(S, FD2->getType(), false,
TemplateParams->getDepth(),
UsedParameters);
break;
}
-
+
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;
-
+
+ return true;
+}
+
+/// \brief Determine whether this a function template whose parameter-type-list
+/// ends with a function parameter pack.
+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;
+
+ // Make sure that no previous parameter is a parameter pack.
+ while (--NumParams > 0) {
+ if (Function->getParamDecl(NumParams - 1)->isParameterPack())
+ return false;
+ }
+
return true;
}
-
-
+
/// \brief Returns the more specialized function template according
/// to the rules of function template partial ordering (C++ [temp.func.order]).
///
@@ -2223,77 +3257,113 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
/// \param TPOC the context in which we are performing partial ordering of
/// function templates.
///
+/// \param NumCallArguments The number of arguments in a call, used only
+/// when \c TPOC is \c TPOC_Call.
+///
/// \returns the more specialized function template. If neither
/// template is more specialized, returns NULL.
FunctionTemplateDecl *
Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
FunctionTemplateDecl *FT2,
SourceLocation Loc,
- TemplatePartialOrderingContext TPOC) {
- llvm::SmallVector<DeductionQualifierComparison, 4> QualifierComparisons;
- bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC, 0);
- bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC,
- &QualifierComparisons);
-
+ TemplatePartialOrderingContext TPOC,
+ unsigned NumCallArguments) {
+ llvm::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) // 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
+ // 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
+ // 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) {
+ for (unsigned I = 0, N = RefParamComparisons.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;
+ // types are identical after the transformations above) and both P and A
+ // were reference types (before being replaced with the type referred to
+ // above):
+
+ // -- if the type from the argument template was an lvalue reference
+ // and the type from the parameter template was not, the argument
+ // type is considered to be more specialized than the other;
+ // otherwise,
+ 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;
}
+
+ // -- if the type from the argument template is more cv-qualified than
+ // the type from the parameter template (as described above), the
+ // argument type is considered to be more specialized than the
+ // other; otherwise,
+ 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;
+ }
+
+ // -- neither type is more specialized than the other.
}
-
+
assert(!(Better1 && Better2) && "Should have broken out in the loop above");
if (Better1)
return FT1;
else if (Better2)
return FT2;
- else
- return 0;
+
+ // FIXME: This mimics what GCC implements, but doesn't match up with the
+ // proposed resolution for core issue 692. This area needs to be sorted out,
+ // but for now we attempt to maintain compatibility.
+ bool Variadic1 = isVariadicFunctionTemplate(FT1);
+ bool Variadic2 = isVariadicFunctionTemplate(FT2);
+ if (Variadic1 != Variadic2)
+ return Variadic1? FT2 : FT1;
+
+ return 0;
}
/// \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();
}
@@ -2309,7 +3379,10 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
/// \param TPOC the partial ordering context to use to compare the function
/// template specializations.
///
-/// \param Loc the location where the ambiguity or no-specializations
+/// \param NumCallArguments The number of arguments in a call, used only
+/// when \c TPOC is \c TPOC_Call.
+///
+/// \param Loc the location where the ambiguity or no-specializations
/// diagnostic should occur.
///
/// \param NoneDiag partial diagnostic used to diagnose cases where there are
@@ -2323,35 +3396,38 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
/// 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,
+/// \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
+/// \returns the most specialized function template specialization, if
/// found. Otherwise, returns SpecEnd.
///
-/// \todo FIXME: Consider passing in the "also-ran" candidates that failed
+/// \todo FIXME: Consider passing in the "also-ran" candidates that failed
/// template argument deduction.
UnresolvedSetIterator
Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin,
- UnresolvedSetIterator SpecEnd,
+ UnresolvedSetIterator SpecEnd,
TemplatePartialOrderingContext TPOC,
+ unsigned NumCallArguments,
SourceLocation Loc,
const PartialDiagnostic &NoneDiag,
const PartialDiagnostic &AmbigDiag,
- const PartialDiagnostic &CandidateDiag) {
+ const PartialDiagnostic &CandidateDiag,
+ bool Complain) {
if (SpecBegin == SpecEnd) {
- Diag(Loc, NoneDiag);
+ if (Complain)
+ Diag(Loc, NoneDiag);
return SpecEnd;
}
-
- if (SpecBegin + 1 == SpecEnd)
+
+ if (SpecBegin + 1 == SpecEnd)
return SpecBegin;
-
+
// Find the function template that is better than all of the templates it
// has been compared to.
UnresolvedSetIterator Best = SpecBegin;
- FunctionTemplateDecl *BestTemplate
+ FunctionTemplateDecl *BestTemplate
= cast<FunctionDecl>(*Best)->getPrimaryTemplate();
assert(BestTemplate && "Not a function template specialization?");
for (UnresolvedSetIterator I = SpecBegin + 1; I != SpecEnd; ++I) {
@@ -2359,13 +3435,13 @@ Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin,
= cast<FunctionDecl>(*I)->getPrimaryTemplate();
assert(Challenger && "Not a function template specialization?");
if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
- Loc, TPOC),
+ Loc, TPOC, NumCallArguments),
Challenger)) {
Best = I;
BestTemplate = Challenger;
}
}
-
+
// Make sure that the "best" function template is more specialized than all
// of the others.
bool Ambiguous = false;
@@ -2373,29 +3449,31 @@ Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin,
FunctionTemplateDecl *Challenger
= cast<FunctionDecl>(*I)->getPrimaryTemplate();
if (I != Best &&
- !isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
- Loc, TPOC),
+ !isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
+ Loc, TPOC, NumCallArguments),
BestTemplate)) {
Ambiguous = true;
break;
}
}
-
+
if (!Ambiguous) {
// We found an answer. Return it.
return Best;
}
-
+
// Diagnose the ambiguity.
- Diag(Loc, AmbigDiag);
-
+ if (Complain)
+ Diag(Loc, AmbigDiag);
+
+ if (Complain)
// FIXME: Can we order the candidates in some sane way?
- for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I)
- Diag((*I)->getLocation(), CandidateDiag)
- << getTemplateArgumentBindingsText(
- cast<FunctionDecl>(*I)->getPrimaryTemplate()->getTemplateParameters(),
+ for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I)
+ Diag((*I)->getLocation(), CandidateDiag)
+ << getTemplateArgumentBindingsText(
+ cast<FunctionDecl>(*I)->getPrimaryTemplate()->getTemplateParameters(),
*cast<FunctionDecl>(*I)->getTemplateSpecializationArgs());
-
+
return SpecEnd;
}
@@ -2416,17 +3494,17 @@ Sema::getMoreSpecializedPartialSpecialization(
SourceLocation Loc) {
// 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
+ // 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
+ // 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
+ // 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
@@ -2443,39 +3521,39 @@ Sema::getMoreSpecializedPartialSpecialization(
QualType PT1 = PS1->getInjectedSpecializationType();
QualType PT2 = PS2->getInjectedSpecializationType();
-
+
// Determine whether PS1 is at least as specialized as PS2
Deduced.resize(PS2->getTemplateParameters()->size());
- bool Better1 = !DeduceTemplateArgumentsDuringPartialOrdering(*this,
- PS2->getTemplateParameters(),
- PT2,
- PT1,
- Info,
- Deduced,
- 0);
- if (Better1)
- Better1 = !::FinishTemplateArgumentDeduction(*this, PS2,
- PS1->getTemplateArgs(),
+ bool Better1 = !::DeduceTemplateArguments(*this, PS2->getTemplateParameters(),
+ PT2, PT1, Info, Deduced, TDF_None,
+ /*PartialOrdering=*/true,
+ /*RefParamComparisons=*/0);
+ if (Better1) {
+ InstantiatingTemplate Inst(*this, PS2->getLocation(), PS2,
+ Deduced.data(), Deduced.size(), Info);
+ Better1 = !::FinishTemplateArgumentDeduction(*this, PS2,
+ PS1->getTemplateArgs(),
Deduced, Info);
-
+ }
+
// Determine whether PS2 is at least as specialized as PS1
Deduced.clear();
Deduced.resize(PS1->getTemplateParameters()->size());
- bool Better2 = !DeduceTemplateArgumentsDuringPartialOrdering(*this,
- PS1->getTemplateParameters(),
- PT1,
- PT2,
- Info,
- Deduced,
- 0);
- if (Better2)
- Better2 = !::FinishTemplateArgumentDeduction(*this, PS1,
- PS2->getTemplateArgs(),
+ bool Better2 = !::DeduceTemplateArguments(*this, PS1->getTemplateParameters(),
+ PT1, PT2, Info, Deduced, TDF_None,
+ /*PartialOrdering=*/true,
+ /*RefParamComparisons=*/0);
+ if (Better2) {
+ InstantiatingTemplate Inst(*this, PS1->getLocation(), PS1,
+ Deduced.data(), Deduced.size(), Info);
+ Better2 = !::FinishTemplateArgumentDeduction(*this, PS1,
+ PS2->getTemplateArgs(),
Deduced, Info);
-
+ }
+
if (Better1 == Better2)
return 0;
-
+
return Better1? PS1 : PS2;
}
@@ -2494,7 +3572,15 @@ MarkUsedTemplateParameters(Sema &SemaRef,
bool OnlyDeduced,
unsigned Depth,
llvm::SmallVectorImpl<bool> &Used) {
- // FIXME: if !OnlyDeduced, we have to walk the whole subexpression to
+ // We can deduce from a pack expansion.
+ if (const PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(E))
+ E = Expansion->getPattern();
+
+ // Skip through any implicit casts we added while type-checking.
+ while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
+ E = ICE->getSubExpr();
+
+ // 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 (!DRE)
@@ -2519,13 +3605,13 @@ MarkUsedTemplateParameters(Sema &SemaRef,
llvm::SmallVectorImpl<bool> &Used) {
if (!NNS)
return;
-
+
MarkUsedTemplateParameters(SemaRef, NNS->getPrefix(), OnlyDeduced, Depth,
Used);
- MarkUsedTemplateParameters(SemaRef, QualType(NNS->getAsType(), 0),
+ MarkUsedTemplateParameters(SemaRef, QualType(NNS->getAsType(), 0),
OnlyDeduced, Depth, Used);
}
-
+
/// \brief Mark the template parameters that are used by the given
/// template name.
static void
@@ -2542,12 +3628,12 @@ MarkUsedTemplateParameters(Sema &SemaRef,
}
return;
}
-
+
if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName())
- MarkUsedTemplateParameters(SemaRef, QTN->getQualifier(), OnlyDeduced,
+ MarkUsedTemplateParameters(SemaRef, QTN->getQualifier(), OnlyDeduced,
Depth, Used);
if (DependentTemplateName *DTN = Name.getAsDependentTemplateName())
- MarkUsedTemplateParameters(SemaRef, DTN->getQualifier(), OnlyDeduced,
+ MarkUsedTemplateParameters(SemaRef, DTN->getQualifier(), OnlyDeduced,
Depth, Used);
}
@@ -2560,7 +3646,7 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
llvm::SmallVectorImpl<bool> &Used) {
if (T.isNull())
return;
-
+
// Non-dependent types have nothing deducible
if (!T->isDependentType())
return;
@@ -2626,7 +3712,7 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
= cast<DependentSizedExtVectorType>(T);
MarkUsedTemplateParameters(SemaRef, VecType->getElementType(), OnlyDeduced,
Depth, Used);
- MarkUsedTemplateParameters(SemaRef, VecType->getSizeExpr(), OnlyDeduced,
+ MarkUsedTemplateParameters(SemaRef, VecType->getSizeExpr(), OnlyDeduced,
Depth, Used);
break;
}
@@ -2648,6 +3734,17 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
break;
}
+ case Type::SubstTemplateTypeParmPack: {
+ const SubstTemplateTypeParmPackType *Subst
+ = cast<SubstTemplateTypeParmPackType>(T);
+ MarkUsedTemplateParameters(SemaRef,
+ QualType(Subst->getReplacedParameter(), 0),
+ OnlyDeduced, Depth, Used);
+ MarkUsedTemplateParameters(SemaRef, Subst->getArgumentPack(),
+ OnlyDeduced, Depth, Used);
+ break;
+ }
+
case Type::InjectedClassName:
T = cast<InjectedClassNameType>(T)->getInjectedSpecializationType();
// fall through
@@ -2657,6 +3754,15 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
= cast<TemplateSpecializationType>(T);
MarkUsedTemplateParameters(SemaRef, Spec->getTemplateName(), OnlyDeduced,
Depth, Used);
+
+ // C++0x [temp.deduct.type]p9:
+ // If the template argument list of P contains a pack expansion that is not
+ // the last template argument, the entire template argument list is a
+ // non-deduced context.
+ if (OnlyDeduced &&
+ hasPackExpansionBeforeEnd(Spec->getArgs(), Spec->getNumArgs()))
+ break;
+
for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Depth,
Used);
@@ -2665,7 +3771,7 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
case Type::Complex:
if (!OnlyDeduced)
- MarkUsedTemplateParameters(SemaRef,
+ MarkUsedTemplateParameters(SemaRef,
cast<ComplexType>(T)->getElementType(),
OnlyDeduced, Depth, Used);
break;
@@ -2683,6 +3789,15 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
if (!OnlyDeduced)
MarkUsedTemplateParameters(SemaRef, Spec->getQualifier(),
OnlyDeduced, Depth, Used);
+
+ // C++0x [temp.deduct.type]p9:
+ // If the template argument list of P contains a pack expansion that is not
+ // the last template argument, the entire template argument list is a
+ // non-deduced context.
+ if (OnlyDeduced &&
+ hasPackExpansionBeforeEnd(Spec->getArgs(), Spec->getNumArgs()))
+ break;
+
for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Depth,
Used);
@@ -2710,6 +3825,17 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
OnlyDeduced, Depth, Used);
break;
+ case Type::PackExpansion:
+ MarkUsedTemplateParameters(SemaRef,
+ cast<PackExpansionType>(T)->getPattern(),
+ OnlyDeduced, Depth, Used);
+ break;
+
+ case Type::Auto:
+ MarkUsedTemplateParameters(SemaRef,
+ cast<AutoType>(T)->getDeducedType(),
+ OnlyDeduced, Depth, Used);
+
// None of these types have any template parameters in them.
case Type::Builtin:
case Type::VariableArray:
@@ -2749,15 +3875,17 @@ MarkUsedTemplateParameters(Sema &SemaRef,
break;
case TemplateArgument::Template:
- MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsTemplate(),
+ case TemplateArgument::TemplateExpansion:
+ MarkUsedTemplateParameters(SemaRef,
+ TemplateArg.getAsTemplateOrTemplatePattern(),
OnlyDeduced, Depth, Used);
break;
case TemplateArgument::Expression:
- MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsExpr(), OnlyDeduced,
+ MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsExpr(), OnlyDeduced,
Depth, Used);
break;
-
+
case TemplateArgument::Pack:
for (TemplateArgument::pack_iterator P = TemplateArg.pack_begin(),
PEnd = TemplateArg.pack_end();
@@ -2780,21 +3908,29 @@ void
Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
bool OnlyDeduced, unsigned Depth,
llvm::SmallVectorImpl<bool> &Used) {
+ // C++0x [temp.deduct.type]p9:
+ // If the template argument list of P contains a pack expansion that is not
+ // the last template argument, the entire template argument list is a
+ // non-deduced context.
+ if (OnlyDeduced &&
+ hasPackExpansionBeforeEnd(TemplateArgs.data(), TemplateArgs.size()))
+ return;
+
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
- ::MarkUsedTemplateParameters(*this, TemplateArgs[I], OnlyDeduced,
+ ::MarkUsedTemplateParameters(*this, TemplateArgs[I], OnlyDeduced,
Depth, Used);
}
/// \brief Marks all of the template parameters that will be deduced by a
/// call to the given function template.
-void
+void
Sema::MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate,
llvm::SmallVectorImpl<bool> &Deduced) {
- TemplateParameterList *TemplateParams
+ 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(),
OpenPOWER on IntegriCloud