aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplateDeduction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaTemplateDeduction.cpp')
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp909
1 files changed, 513 insertions, 396 deletions
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index f8ee60251698..633b2837e1fe 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -1,60 +1,97 @@
-//===------- SemaTemplateDeduction.cpp - Template Argument Deduction ------===/
+//===- SemaTemplateDeduction.cpp - Template Argument Deduction ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
-//===----------------------------------------------------------------------===/
//
-// This file implements C++ template argument deduction.
+//===----------------------------------------------------------------------===//
//
-//===----------------------------------------------------------------------===/
+// This file implements C++ template argument deduction.
+//
+//===----------------------------------------------------------------------===//
#include "clang/Sema/TemplateDeduction.h"
#include "TreeTransform.h"
+#include "TypeLocBuilder.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
-#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclAccessPair.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
-#include "clang/AST/StmtVisitor.h"
-#include "clang/AST/TypeOrdering.h"
-#include "clang/Sema/DeclSpec.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/ExceptionSpecificationType.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Sema/Ownership.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/Template.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallBitVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
+#include <cassert>
+#include <tuple>
+#include <utility>
namespace clang {
- using namespace sema;
- /// \brief Various flags that control template argument deduction.
+
+ /// Various flags that control template argument deduction.
///
/// These flags can be bitwise-OR'd together.
enum TemplateDeductionFlags {
- /// \brief No template argument deduction flags, which indicates the
+ /// No template argument deduction flags, which indicates the
/// strictest results for template argument deduction (as used for, e.g.,
/// matching class template partial specializations).
TDF_None = 0,
- /// \brief Within template argument deduction from a function call, we are
+
+ /// Within template argument deduction from a function call, we are
/// matching with a parameter type for which the original parameter was
/// a reference.
TDF_ParamWithReferenceType = 0x1,
- /// \brief Within template argument deduction from a function call, we
+
+ /// Within template argument deduction from a function call, we
/// are matching in a case where we ignore cv-qualifiers.
TDF_IgnoreQualifiers = 0x02,
- /// \brief Within template argument deduction from a function call,
+
+ /// Within template argument deduction from a function call,
/// we are matching in a case where we can perform template argument
/// deduction from a template-id of a derived class of the argument type.
TDF_DerivedClass = 0x04,
- /// \brief Allow non-dependent types to differ, e.g., when performing
+
+ /// Allow non-dependent types to differ, e.g., when performing
/// template argument deduction from a function call where conversions
/// may apply.
TDF_SkipNonDependent = 0x08,
- /// \brief Whether we are performing template argument deduction for
+
+ /// Whether we are performing template argument deduction for
/// parameters and arguments in a top-level template argument
TDF_TopLevelParameterTypeList = 0x10,
- /// \brief Within template argument deduction from overload resolution per
+
+ /// Within template argument deduction from overload resolution per
/// C++ [over.over] allow matching function types that are compatible in
/// terms of noreturn and default calling convention adjustments, or
/// similarly matching a declared template specialization against a
@@ -62,12 +99,18 @@ namespace clang {
/// deduction where the parameter is a function type that can be converted
/// to the argument type.
TDF_AllowCompatibleFunctionType = 0x20,
+
+ /// Within template argument deduction for a conversion function, we are
+ /// matching with an argument type for which the original argument was
+ /// a reference.
+ TDF_ArgWithReferenceType = 0x40,
};
}
using namespace clang;
+using namespace sema;
-/// \brief Compare two APSInts, extending and switching the sign as
+/// Compare two APSInts, extending and switching the sign as
/// necessary to compare their values regardless of underlying type.
static bool hasSameExtendedValue(llvm::APSInt X, llvm::APSInt Y) {
if (Y.getBitWidth() > X.getBitWidth())
@@ -125,14 +168,14 @@ static void MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
bool OnlyDeduced, unsigned Level,
llvm::SmallBitVector &Deduced);
-/// \brief If the given expression is of a form that permits the deduction
+/// If the given expression is of a form that permits the deduction
/// of a non-type template parameter, return the declaration of that
/// non-type template parameter.
static NonTypeTemplateParmDecl *
getDeducedParameterFromExpr(TemplateDeductionInfo &Info, Expr *E) {
// If we are within an alias template, the expression may have undergone
// any number of parameter substitutions already.
- while (1) {
+ while (true) {
if (ImplicitCastExpr *IC = dyn_cast<ImplicitCastExpr>(E))
E = IC->getSubExpr();
else if (SubstNonTypeTemplateParmExpr *Subst =
@@ -150,7 +193,7 @@ getDeducedParameterFromExpr(TemplateDeductionInfo &Info, Expr *E) {
return nullptr;
}
-/// \brief Determine whether two declaration pointers refer to the same
+/// Determine whether two declaration pointers refer to the same
/// declaration.
static bool isSameDeclaration(Decl *X, Decl *Y) {
if (NamedDecl *NX = dyn_cast<NamedDecl>(X))
@@ -161,7 +204,7 @@ static bool isSameDeclaration(Decl *X, Decl *Y) {
return X->getCanonicalDecl() == Y->getCanonicalDecl();
}
-/// \brief Verify that the given, deduced template arguments are compatible.
+/// 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.
@@ -270,7 +313,7 @@ checkDeducedTemplateArguments(ASTContext &Context,
return Y;
}
- // If we deduced two declarations, make sure they they refer to the
+ // If we deduced two declarations, make sure that they refer to the
// same declaration.
if (Y.getKind() == TemplateArgument::Declaration &&
isSameDeclaration(X.getAsDecl(), Y.getAsDecl()))
@@ -297,7 +340,7 @@ checkDeducedTemplateArguments(ASTContext &Context,
// All other combinations are incompatible.
return DeducedTemplateArgument();
- case TemplateArgument::Pack:
+ case TemplateArgument::Pack: {
if (Y.getKind() != TemplateArgument::Pack ||
X.pack_size() != Y.pack_size())
return DeducedTemplateArgument();
@@ -319,11 +362,12 @@ checkDeducedTemplateArguments(ASTContext &Context,
TemplateArgument::CreatePackCopy(Context, NewPack),
X.wasDeducedFromArrayBound() && Y.wasDeducedFromArrayBound());
}
+ }
llvm_unreachable("Invalid TemplateArgument Kind!");
}
-/// \brief Deduce the value of the given non-type template parameter
+/// Deduce the value of the given non-type template parameter
/// as the given deduced template argument. All non-type template parameter
/// deduction is funneled through here.
static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
@@ -371,7 +415,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
/*ArrayBound=*/NewDeduced.wasDeducedFromArrayBound());
}
-/// \brief Deduce the value of the given non-type template parameter
+/// Deduce the value of the given non-type template parameter
/// from the given integral constant.
static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
Sema &S, TemplateParameterList *TemplateParams,
@@ -385,7 +429,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
ValueType, Info, Deduced);
}
-/// \brief Deduce the value of the given non-type template parameter
+/// Deduce the value of the given non-type template parameter
/// from the given null pointer template argument type.
static Sema::TemplateDeductionResult DeduceNullPtrTemplateArgument(
Sema &S, TemplateParameterList *TemplateParams,
@@ -402,7 +446,7 @@ static Sema::TemplateDeductionResult DeduceNullPtrTemplateArgument(
Value->getType(), Info, Deduced);
}
-/// \brief Deduce the value of the given non-type template parameter
+/// Deduce the value of the given non-type template parameter
/// from the given type- or value-dependent expression.
///
/// \returns true if deduction succeeded, false otherwise.
@@ -415,7 +459,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
Value->getType(), Info, Deduced);
}
-/// \brief Deduce the value of the given non-type template parameter
+/// Deduce the value of the given non-type template parameter
/// from the given declaration.
///
/// \returns true if deduction succeeded, false otherwise.
@@ -475,7 +519,7 @@ DeduceTemplateArguments(Sema &S,
return Sema::TDK_NonDeducedMismatch;
}
-/// \brief Deduce the template arguments by comparing the template parameter
+/// Deduce the template arguments by comparing the template parameter
/// type (which is a template-id) with the template argument type.
///
/// \param S the Sema
@@ -502,6 +546,10 @@ DeduceTemplateArguments(Sema &S,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
assert(Arg.isCanonical() && "Argument type must be canonical");
+ // Treat an injected-class-name as its underlying template-id.
+ if (auto *Injected = dyn_cast<InjectedClassNameType>(Arg))
+ Arg = Injected->getInjectedSpecializationType();
+
// Check whether the template argument is a dependent template-id.
if (const TemplateSpecializationType *SpecArg
= dyn_cast<TemplateSpecializationType>(Arg)) {
@@ -556,7 +604,7 @@ DeduceTemplateArguments(Sema &S,
Deduced, /*NumberOfArgumentsMustMatch=*/true);
}
-/// \brief Determines whether the given type is an opaque type that
+/// Determines whether the given type is an opaque type that
/// might be more qualified when instantiated.
static bool IsPossiblyOpaquelyQualifiedType(QualType T) {
switch (T->getTypeClass()) {
@@ -580,30 +628,7 @@ 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
+/// 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))
@@ -614,10 +639,21 @@ static TemplateParameter makeTemplateParameter(Decl *D) {
return TemplateParameter(cast<TemplateTemplateParmDecl>(D));
}
+/// If \p Param is an expanded parameter pack, get the number of expansions.
+static Optional<unsigned> getExpandedPackSize(NamedDecl *Param) {
+ if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param))
+ if (NTTP->isExpandedParameterPack())
+ return NTTP->getNumExpansionTypes();
+
+ if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Param))
+ if (TTP->isExpandedParameterPack())
+ return TTP->getNumExpansionTemplateParameters();
+
+ return None;
+}
+
/// A pack that we're currently deducing.
struct clang::DeducedPack {
- DeducedPack(unsigned Index) : Index(Index), Outer(nullptr) {}
-
// The index of the pack.
unsigned Index;
@@ -632,17 +668,93 @@ struct clang::DeducedPack {
SmallVector<DeducedTemplateArgument, 4> New;
// The outer deduction for this pack, if any.
- DeducedPack *Outer;
+ DeducedPack *Outer = nullptr;
+
+ DeducedPack(unsigned Index) : Index(Index) {}
};
namespace {
+
/// A scope in which we're performing pack deduction.
class PackDeductionScope {
public:
+ /// Prepare to deduce the packs named within Pattern.
PackDeductionScope(Sema &S, TemplateParameterList *TemplateParams,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
TemplateDeductionInfo &Info, TemplateArgument Pattern)
: S(S), TemplateParams(TemplateParams), Deduced(Deduced), Info(Info) {
+ unsigned NumNamedPacks = addPacks(Pattern);
+ finishConstruction(NumNamedPacks);
+ }
+
+ /// Prepare to directly deduce arguments of the parameter with index \p Index.
+ PackDeductionScope(Sema &S, TemplateParameterList *TemplateParams,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ TemplateDeductionInfo &Info, unsigned Index)
+ : S(S), TemplateParams(TemplateParams), Deduced(Deduced), Info(Info) {
+ addPack(Index);
+ finishConstruction(1);
+ }
+
+private:
+ void addPack(unsigned Index) {
+ // Save the deduced template argument for the parameter pack expanded
+ // by this pack expansion, then clear out the deduction.
+ DeducedPack Pack(Index);
+ Pack.Saved = Deduced[Index];
+ Deduced[Index] = TemplateArgument();
+
+ // FIXME: What if we encounter multiple packs with different numbers of
+ // pre-expanded expansions? (This should already have been diagnosed
+ // during substitution.)
+ if (Optional<unsigned> ExpandedPackExpansions =
+ getExpandedPackSize(TemplateParams->getParam(Index)))
+ FixedNumExpansions = ExpandedPackExpansions;
+
+ Packs.push_back(Pack);
+ }
+
+ unsigned addPacks(TemplateArgument Pattern) {
+ // Compute the set of template parameter indices that correspond to
+ // parameter packs expanded by the pack expansion.
+ llvm::SmallBitVector SawIndices(TemplateParams->size());
+
+ auto AddPack = [&](unsigned Index) {
+ if (SawIndices[Index])
+ return;
+ SawIndices[Index] = true;
+ addPack(Index);
+ };
+
+ // First look for unexpanded packs in the pattern.
+ SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+ for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
+ unsigned Depth, Index;
+ std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
+ if (Depth == Info.getDeducedDepth())
+ AddPack(Index);
+ }
+ assert(!Packs.empty() && "Pack expansion without unexpanded packs?");
+
+ unsigned NumNamedPacks = Packs.size();
+
+ // We can also have deduced template parameters that do not actually
+ // appear in the pattern, but can be deduced by it (the type of a non-type
+ // template parameter pack, in particular). These won't have prevented us
+ // from partially expanding the pack.
+ llvm::SmallBitVector Used(TemplateParams->size());
+ MarkUsedTemplateParameters(S.Context, Pattern, /*OnlyDeduced*/true,
+ Info.getDeducedDepth(), Used);
+ for (int Index = Used.find_first(); Index != -1;
+ Index = Used.find_next(Index))
+ if (TemplateParams->getParam(Index)->isParameterPack())
+ AddPack(Index);
+
+ return NumNamedPacks;
+ }
+
+ void finishConstruction(unsigned NumNamedPacks) {
// Dig out the partially-substituted pack, if there is one.
const TemplateArgument *PartialPackArgs = nullptr;
unsigned NumPartialPackArgs = 0;
@@ -652,60 +764,29 @@ public:
&PartialPackArgs, &NumPartialPackArgs))
PartialPackDepthIndex = getDepthAndIndex(Partial);
- // Compute the set of template parameter indices that correspond to
- // parameter packs expanded by the pack expansion.
- {
- llvm::SmallBitVector SawIndices(TemplateParams->size());
-
- auto AddPack = [&](unsigned Index) {
- if (SawIndices[Index])
- return;
- SawIndices[Index] = true;
-
- // Save the deduced template argument for the parameter pack expanded
- // by this pack expansion, then clear out the deduction.
- DeducedPack Pack(Index);
- Pack.Saved = Deduced[Index];
- Deduced[Index] = TemplateArgument();
-
- Packs.push_back(Pack);
- };
-
- // First look for unexpanded packs in the pattern.
- SmallVector<UnexpandedParameterPack, 2> Unexpanded;
- S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
- for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
- unsigned Depth, Index;
- std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
- if (Depth == Info.getDeducedDepth())
- AddPack(Index);
+ // This pack expansion will have been partially or fully expanded if
+ // it only names explicitly-specified parameter packs (including the
+ // partially-substituted one, if any).
+ bool IsExpanded = true;
+ for (unsigned I = 0; I != NumNamedPacks; ++I) {
+ if (Packs[I].Index >= Info.getNumExplicitArgs()) {
+ IsExpanded = false;
+ IsPartiallyExpanded = false;
+ break;
+ }
+ if (PartialPackDepthIndex ==
+ std::make_pair(Info.getDeducedDepth(), Packs[I].Index)) {
+ IsPartiallyExpanded = true;
}
- assert(!Packs.empty() && "Pack expansion without unexpanded packs?");
-
- // This pack expansion will have been partially expanded iff the only
- // unexpanded parameter pack within it is the partially-substituted pack.
- IsPartiallyExpanded =
- Packs.size() == 1 &&
- PartialPackDepthIndex ==
- std::make_pair(Info.getDeducedDepth(), Packs.front().Index);
-
- // Skip over the pack elements that were expanded into separate arguments.
- if (IsPartiallyExpanded)
- PackElements += NumPartialPackArgs;
-
- // We can also have deduced template parameters that do not actually
- // appear in the pattern, but can be deduced by it (the type of a non-type
- // template parameter pack, in particular). These won't have prevented us
- // from partially expanding the pack.
- llvm::SmallBitVector Used(TemplateParams->size());
- MarkUsedTemplateParameters(S.Context, Pattern, /*OnlyDeduced*/true,
- Info.getDeducedDepth(), Used);
- for (int Index = Used.find_first(); Index != -1;
- Index = Used.find_next(Index))
- if (TemplateParams->getParam(Index)->isParameterPack())
- AddPack(Index);
}
+ // Skip over the pack elements that were expanded into separate arguments.
+ // If we partially expanded, this is the number of partial arguments.
+ if (IsPartiallyExpanded)
+ PackElements += NumPartialPackArgs;
+ else if (IsExpanded)
+ PackElements += *FixedNumExpansions;
+
for (auto &Pack : Packs) {
if (Info.PendingDeducedPacks.size() > Pack.Index)
Pack.Outer = Info.PendingDeducedPacks[Pack.Index];
@@ -724,12 +805,13 @@ public:
// FIXME: If we could represent a "depth i, index j, pack elem k"
// parameter, we could substitute the partially-substituted pack
// everywhere and avoid this.
- if (Pack.New.size() > PackElements)
+ if (!IsPartiallyExpanded)
Deduced[Pack.Index] = Pack.New[PackElements];
}
}
}
+public:
~PackDeductionScope() {
for (auto &Pack : Packs)
Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
@@ -739,6 +821,18 @@ public:
/// sequence of (prior) function parameters / template arguments.
bool isPartiallyExpanded() { return IsPartiallyExpanded; }
+ /// Determine whether this pack expansion scope has a known, fixed arity.
+ /// This happens if it involves a pack from an outer template that has
+ /// (notionally) already been expanded.
+ bool hasFixedArity() { return FixedNumExpansions.hasValue(); }
+
+ /// Determine whether the next element of the argument is still part of this
+ /// pack. This is the case unless the pack is already expanded to a fixed
+ /// length.
+ bool hasNextElement() {
+ return !FixedNumExpansions || *FixedNumExpansions > PackElements;
+ }
+
/// Move to deducing the next element in each pack that is being deduced.
void nextPackElement() {
// Capture the deduced template arguments for each parameter pack expanded
@@ -761,16 +855,24 @@ public:
++PackElements;
}
- /// \brief Finish template argument deduction for a set of argument packs,
+ /// Finish template argument deduction for a set of argument packs,
/// producing the argument packs and checking for consistency with prior
/// deductions.
- Sema::TemplateDeductionResult finish() {
+ Sema::TemplateDeductionResult
+ finish(bool TreatNoDeductionsAsNonDeduced = true) {
// Build argument packs for each of the parameter packs expanded by this
// pack expansion.
for (auto &Pack : Packs) {
// Put back the old value for this pack.
Deduced[Pack.Index] = Pack.Saved;
+ // If we are deducing the size of this pack even if we didn't deduce any
+ // values for it, then make sure we build a pack of the right size.
+ // FIXME: Should we always deduce the size, even if the pack appears in
+ // a non-deduced context?
+ if (!TreatNoDeductionsAsNonDeduced)
+ Pack.New.resize(PackElements);
+
// Build or find a new value for this pack.
DeducedTemplateArgument NewPack;
if (PackElements && Pack.New.empty()) {
@@ -826,14 +928,24 @@ public:
Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
}
+ NamedDecl *Param = TemplateParams->getParam(Pack.Index);
if (Result.isNull()) {
- Info.Param =
- makeTemplateParameter(TemplateParams->getParam(Pack.Index));
+ Info.Param = makeTemplateParameter(Param);
Info.FirstArg = OldPack;
Info.SecondArg = NewPack;
return Sema::TDK_Inconsistent;
}
+ // If we have a pre-expanded pack and we didn't deduce enough elements
+ // for it, fail deduction.
+ if (Optional<unsigned> Expansions = getExpandedPackSize(Param)) {
+ if (*Expansions != PackElements) {
+ Info.Param = makeTemplateParameter(Param);
+ Info.FirstArg = Result;
+ return Sema::TDK_IncompletePack;
+ }
+ }
+
*Loc = Result;
}
@@ -847,12 +959,15 @@ private:
TemplateDeductionInfo &Info;
unsigned PackElements = 0;
bool IsPartiallyExpanded = false;
+ /// The number of expansions, if we have a fully-expanded pack in this scope.
+ Optional<unsigned> FixedNumExpansions;
SmallVector<DeducedPack, 2> Packs;
};
+
} // namespace
-/// \brief Deduce the template arguments by comparing the list of parameter
+/// 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).
///
@@ -891,12 +1006,6 @@ DeduceTemplateArguments(Sema &S,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned TDF,
bool PartialOrdering = false) {
- // 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_MiscellaneousDeductionFailure;
-
// 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
@@ -933,13 +1042,6 @@ DeduceTemplateArguments(Sema &S,
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
@@ -950,15 +1052,43 @@ DeduceTemplateArguments(Sema &S,
QualType Pattern = Expansion->getPattern();
PackDeductionScope PackScope(S, TemplateParams, Deduced, Info, Pattern);
- for (; ArgIdx < NumArgs; ++ArgIdx) {
- // Deduce template arguments from the pattern.
- if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern,
- Args[ArgIdx], Info, Deduced,
- TDF, PartialOrdering))
- return Result;
+ // A pack scope with fixed arity is not really a pack any more, so is not
+ // a non-deduced context.
+ if (ParamIdx + 1 == NumParams || PackScope.hasFixedArity()) {
+ for (; ArgIdx < NumArgs && PackScope.hasNextElement(); ++ArgIdx) {
+ // Deduce template arguments from the pattern.
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern,
+ Args[ArgIdx], Info, Deduced,
+ TDF, PartialOrdering))
+ return Result;
- PackScope.nextPackElement();
+ PackScope.nextPackElement();
+ }
+ } else {
+ // 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.
+ //
+ // FIXME: There is no wording to say what we should do in this case. We
+ // choose to resolve this by applying the same rule that is applied for a
+ // function call: that is, deduce all contained packs to their
+ // explicitly-specified values (or to <> if there is no such value).
+ //
+ // This is seemingly-arbitrarily different from the case of a template-id
+ // with a non-trailing pack-expansion in its arguments, which renders the
+ // entire template-argument-list a non-deduced context.
+
+ // If the parameter type contains an explicitly-specified pack that we
+ // could not expand, skip the number of parameters notionally created
+ // by the expansion.
+ Optional<unsigned> NumExpansions = Expansion->getNumExpansions();
+ if (NumExpansions && !PackScope.isPartiallyExpanded()) {
+ for (unsigned I = 0; I != *NumExpansions && ArgIdx < NumArgs;
+ ++I, ++ArgIdx)
+ PackScope.nextPackElement();
+ }
}
// Build argument packs for each of the parameter packs expanded by this
@@ -974,8 +1104,10 @@ DeduceTemplateArguments(Sema &S,
return Sema::TDK_Success;
}
-/// \brief Determine whether the parameter has qualifiers that are either
-/// inconsistent with or a superset of the argument's qualifiers.
+/// Determine whether the parameter has qualifiers that the argument
+/// lacks. Put another way, determine whether there is no way to add
+/// a deduced set of qualifiers to the ParamType that would result in
+/// its qualifiers matching those of the ArgType.
static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType,
QualType ArgType) {
Qualifiers ParamQs = ParamType.getQualifiers();
@@ -999,13 +1131,11 @@ static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType,
ParamQs.hasObjCLifetime())
return true;
- // CVR qualifier superset.
- return (ParamQs.getCVRQualifiers() != ArgQs.getCVRQualifiers()) &&
- ((ParamQs.getCVRQualifiers() | ArgQs.getCVRQualifiers())
- == ParamQs.getCVRQualifiers());
+ // CVR qualifiers inconsistent or a superset.
+ return (ParamQs.getCVRQualifiers() & ~ArgQs.getCVRQualifiers()) != 0;
}
-/// \brief Compare types for equality with respect to possibly compatible
+/// Compare types for equality with respect to possibly compatible
/// function types (noreturn adjustment, implicit calling conventions). If any
/// of parameter and argument is not a function, just perform type comparison.
///
@@ -1057,7 +1187,7 @@ static bool isForwardingReference(QualType Param, unsigned FirstInnerIndex) {
return false;
}
-/// \brief Deduce the template arguments by comparing the parameter type and
+/// Deduce the template arguments by comparing the parameter type and
/// the argument type (C++ [temp.deduct.type]).
///
/// \param S the semantic analysis object within which we are deducing
@@ -1228,6 +1358,12 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return Sema::TDK_Underqualified;
}
+ // Do not match a function type with a cv-qualified type.
+ // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1584
+ if (Arg->isFunctionType() && Param.hasQualifiers()) {
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
assert(TemplateTypeParm->getDepth() == Info.getDeducedDepth() &&
"saw template type parameter with wrong depth");
assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function");
@@ -1303,6 +1439,18 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
if (TDF & TDF_ParamWithReferenceType) {
if (hasInconsistentOrSupersetQualifiersOf(Param, Arg))
return Sema::TDK_NonDeducedMismatch;
+ } else if (TDF & TDF_ArgWithReferenceType) {
+ // C++ [temp.deduct.conv]p4:
+ // If the original A is a reference type, A can be more cv-qualified
+ // than the deduced A
+ if (!Arg.getQualifiers().compatiblyIncludes(Param.getQualifiers()))
+ return Sema::TDK_NonDeducedMismatch;
+
+ // Strip out all extra qualifiers from the argument to figure out the
+ // type we're converting to, prior to the qualification conversion.
+ Qualifiers Quals;
+ Arg = S.Context.getUnqualifiedArrayType(Arg, Quals);
+ Arg = S.Context.getQualifiedType(Arg, Param.getQualifiers());
} else if (!IsPossiblyOpaquelyQualifiedType(Param)) {
if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
return Sema::TDK_NonDeducedMismatch;
@@ -1353,7 +1501,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
case Type::Enum:
case Type::ObjCObject:
case Type::ObjCInterface:
- case Type::ObjCObjectPointer: {
+ case Type::ObjCObjectPointer:
if (TDF & TDF_SkipNonDependent)
return Sema::TDK_Success;
@@ -1363,7 +1511,6 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
}
return Param == Arg? Sema::TDK_Success : Sema::TDK_NonDeducedMismatch;
- }
// _Complex T [placeholder extension]
case Type::Complex:
@@ -1557,7 +1704,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
"saw non-type template parameter with wrong depth");
llvm::APSInt Noexcept(1);
- switch (FunctionProtoArg->canThrow(S.Context)) {
+ switch (FunctionProtoArg->canThrow()) {
case CT_Cannot:
Noexcept = 1;
LLVM_FALLTHROUGH;
@@ -1578,11 +1725,14 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
}
}
// FIXME: Detect non-deduced exception specification mismatches?
+ //
+ // Careful about [temp.deduct.call] and [temp.deduct.conv], which allow
+ // top-level differences in noexcept-specifications.
return Sema::TDK_Success;
}
- case Type::InjectedClassName: {
+ case Type::InjectedClassName:
// Treat a template's injected-class-name as if the template
// specialization type had been used.
Param = cast<InjectedClassNameType>(Param)
@@ -1590,7 +1740,6 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
assert(isa<TemplateSpecializationType>(Param) &&
"injected class name is not a template specialization type");
LLVM_FALLTHROUGH;
- }
// template-name<T> (where template-name refers to a class template)
// template-name<i>
@@ -1788,6 +1937,54 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return Sema::TDK_NonDeducedMismatch;
}
+ case Type::DependentVector: {
+ const auto *VectorParam = cast<DependentVectorType>(Param);
+
+ if (const auto *VectorArg = dyn_cast<VectorType>(Arg)) {
+ // Perform deduction on the element types.
+ if (Sema::TemplateDeductionResult Result =
+ DeduceTemplateArgumentsByTypeMatch(
+ S, TemplateParams, VectorParam->getElementType(),
+ VectorArg->getElementType(), Info, Deduced, TDF))
+ return Result;
+
+ // Perform deduction on the vector size, if we can.
+ NonTypeTemplateParmDecl *NTTP =
+ getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr());
+ if (!NTTP)
+ return Sema::TDK_Success;
+
+ llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false);
+ ArgSize = VectorArg->getNumElements();
+ // Note that we use the "array bound" rules here; just like in that
+ // case, we don't have any particular type for the vector size, but
+ // we can provide one if necessary.
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, ArgSize,
+ S.Context.UnsignedIntTy, true,
+ Info, Deduced);
+ }
+
+ if (const auto *VectorArg = dyn_cast<DependentVectorType>(Arg)) {
+ // Perform deduction on the element types.
+ if (Sema::TemplateDeductionResult Result =
+ DeduceTemplateArgumentsByTypeMatch(
+ S, TemplateParams, VectorParam->getElementType(),
+ VectorArg->getElementType(), Info, Deduced, TDF))
+ return Result;
+
+ // Perform deduction on the vector size, if we can.
+ NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(
+ Info, VectorParam->getSizeExpr());
+ if (!NTTP)
+ return Sema::TDK_Success;
+
+ return DeduceNonTypeTemplateArgument(
+ S, TemplateParams, NTTP, VectorArg->getSizeExpr(), Info, Deduced);
+ }
+
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
// (clang extension)
//
// T __attribute__(((ext_vector_type(N))))
@@ -1992,7 +2189,7 @@ DeduceTemplateArguments(Sema &S,
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
- case TemplateArgument::Expression: {
+ case TemplateArgument::Expression:
if (NonTypeTemplateParmDecl *NTTP
= getDeducedParameterFromExpr(Info, Param.getAsExpr())) {
if (Arg.getKind() == TemplateArgument::Integral)
@@ -2021,7 +2218,7 @@ DeduceTemplateArguments(Sema &S,
// Can't deduce anything, but that's okay.
return Sema::TDK_Success;
- }
+
case TemplateArgument::Pack:
llvm_unreachable("Argument packs should be expanded by the caller!");
}
@@ -2029,7 +2226,7 @@ DeduceTemplateArguments(Sema &S,
llvm_unreachable("Invalid TemplateArgument Kind!");
}
-/// \brief Determine whether there is a template argument to be used for
+/// Determine whether there is a template argument to be used for
/// deduction.
///
/// This routine "expands" argument packs in-place, overriding its input
@@ -2052,7 +2249,7 @@ static bool hasTemplateArgumentForDeduction(ArrayRef<TemplateArgument> &Args,
return ArgIdx < Args.size();
}
-/// \brief Determine whether the given set of template arguments has a pack
+/// Determine whether the given set of template arguments has a pack
/// expansion that is not the last template argument.
static bool hasPackExpansionBeforeEnd(ArrayRef<TemplateArgument> Args) {
bool FoundPackExpansion = false;
@@ -2063,6 +2260,8 @@ static bool hasPackExpansionBeforeEnd(ArrayRef<TemplateArgument> Args) {
if (A.getKind() == TemplateArgument::Pack)
return hasPackExpansionBeforeEnd(A.pack_elements());
+ // FIXME: If this is a fixed-arity pack expansion from an outer level of
+ // templates, it should not be treated as a pack expansion.
if (A.isPackExpansion())
FoundPackExpansion = true;
}
@@ -2126,17 +2325,15 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
// template parameter packs expanded by Pi.
TemplateArgument Pattern = Params[ParamIdx].getPackExpansionPattern();
- // 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.
-
// Prepare to deduce the packs within the pattern.
PackDeductionScope PackScope(S, TemplateParams, Deduced, Info, Pattern);
// 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).
- for (; hasTemplateArgumentForDeduction(Args, ArgIdx); ++ArgIdx) {
+ for (; hasTemplateArgumentForDeduction(Args, ArgIdx) &&
+ PackScope.hasNextElement();
+ ++ArgIdx) {
// Deduce template arguments from the pattern.
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArguments(S, TemplateParams, Pattern, Args[ArgIdx],
@@ -2167,7 +2364,7 @@ DeduceTemplateArguments(Sema &S,
/*NumberOfArgumentsMustMatch*/false);
}
-/// \brief Determine whether two template arguments are the same.
+/// Determine whether two template arguments are the same.
static bool isSameTemplateArg(ASTContext &Context,
TemplateArgument X,
const TemplateArgument &Y,
@@ -2228,7 +2425,7 @@ static bool isSameTemplateArg(ASTContext &Context,
llvm_unreachable("Invalid TemplateArgument Kind!");
}
-/// \brief Allocate a TemplateArgumentLoc where all locations have
+/// Allocate a TemplateArgumentLoc where all locations have
/// been initialized to the given location.
///
/// \param Arg The template argument we are producing template argument
@@ -2303,8 +2500,7 @@ Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
llvm_unreachable("Invalid TemplateArgument Kind!");
}
-
-/// \brief Convert the given deduced template argument and add it to the set of
+/// Convert the given deduced template argument and add it to the set of
/// fully-converted template arguments.
static bool
ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
@@ -2409,6 +2605,16 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments(
for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
NamedDecl *Param = TemplateParams->getParam(I);
+ // 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 (Deduced[I].isNull() && Param->isTemplateParameterPack()) {
+ if (auto Result = PackDeductionScope(S, TemplateParams, Deduced, Info, I)
+ .finish(/*TreatNoDeductionsAsNonDeduced*/false))
+ return Result;
+ }
+
if (!Deduced[I].isNull()) {
if (I < NumAlreadyConverted) {
// We may have had explicitly-specified template arguments for a
@@ -2443,40 +2649,6 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments(
continue;
}
- // C++0x [temp.arg.explicit]p3:
- // A trailing template parameter pack (14.5.3) not otherwise deduced will
- // be deduced to an empty sequence of template arguments.
- // FIXME: Where did the word "trailing" come from?
- if (Param->isTemplateParameterPack()) {
- // We may have had explicitly-specified template arguments for this
- // template parameter pack. If so, our empty deduction extends the
- // explicitly-specified set (C++0x [temp.arg.explicit]p9).
- const TemplateArgument *ExplicitArgs;
- unsigned NumExplicitArgs;
- if (CurrentInstantiationScope &&
- CurrentInstantiationScope->getPartiallySubstitutedPack(
- &ExplicitArgs, &NumExplicitArgs) == Param) {
- Builder.push_back(TemplateArgument(
- llvm::makeArrayRef(ExplicitArgs, NumExplicitArgs)));
-
- // Forget the partially-substituted pack; its substitution is now
- // complete.
- CurrentInstantiationScope->ResetPartiallySubstitutedPack();
- } else {
- // Go through the motions of checking the empty argument pack against
- // the parameter pack.
- DeducedTemplateArgument DeducedPack(TemplateArgument::getEmptyPack());
- if (ConvertDeducedTemplateArgument(S, Param, DeducedPack, Template,
- Info, IsDeduced, Builder)) {
- Info.Param = makeTemplateParameter(Param);
- // FIXME: These template arguments are temporary. Free them!
- Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
- return Sema::TDK_SubstitutionFailure;
- }
- }
- continue;
- }
-
// Substitute into the default template argument, if available.
bool HasDefaultArg = false;
TemplateDecl *TD = dyn_cast<TemplateDecl>(Template);
@@ -2659,7 +2831,7 @@ static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
}
-/// \brief Perform template argument deduction to determine whether
+/// Perform template argument deduction to determine whether
/// the given template arguments match the given class template
/// partial specialization per C++ [temp.class.spec.match].
Sema::TemplateDeductionResult
@@ -2702,7 +2874,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
*this, Partial, /*PartialOrdering=*/false, TemplateArgs, Deduced, Info);
}
-/// \brief Perform template argument deduction to determine whether
+/// Perform template argument deduction to determine whether
/// the given template arguments match the given variable template
/// partial specialization per C++ [temp.class.spec.match].
Sema::TemplateDeductionResult
@@ -2743,7 +2915,7 @@ Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
*this, Partial, /*PartialOrdering=*/false, TemplateArgs, Deduced, Info);
}
-/// \brief Determine whether the given type T is a simple-template-id type.
+/// Determine whether the given type T is a simple-template-id type.
static bool isSimpleTemplateIdType(QualType T) {
if (const TemplateSpecializationType *Spec
= T->getAs<TemplateSpecializationType>())
@@ -2763,7 +2935,7 @@ static bool isSimpleTemplateIdType(QualType T) {
return false;
}
-/// \brief Substitute the explicitly-provided template arguments into the
+/// Substitute the explicitly-provided template arguments into the
/// given function template according to C++ [temp.arg.explicit].
///
/// \param FunctionTemplate the function template into which the explicit
@@ -2837,7 +3009,7 @@ Sema::SubstituteExplicitTemplateArguments(
Trap.hasErrorOccurred()) {
unsigned Index = Builder.size();
if (Index >= TemplateParams->size())
- Index = TemplateParams->size() - 1;
+ return TDK_SubstitutionFailure;
Info.Param = makeTemplateParameter(TemplateParams->getParam(Index));
return TDK_InvalidExplicitArguments;
}
@@ -2846,7 +3018,7 @@ Sema::SubstituteExplicitTemplateArguments(
// template arguments.
TemplateArgumentList *ExplicitArgumentList
= TemplateArgumentList::CreateCopy(Context, Builder);
- Info.reset(ExplicitArgumentList);
+ Info.setExplicitArgs(ExplicitArgumentList);
// Template argument deduction and the final substitution should be
// done in the context of the templated declaration. Explicit
@@ -2858,14 +3030,19 @@ Sema::SubstituteExplicitTemplateArguments(
// 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];
+ unsigned PartiallySubstitutedPackIndex = -1u;
+ if (!Builder.empty()) {
+ const TemplateArgument &Arg = Builder.back();
if (Arg.getKind() == TemplateArgument::Pack) {
- CurrentInstantiationScope->SetPartiallySubstitutedPack(
- TemplateParams->getParam(I),
- Arg.pack_begin(),
- Arg.pack_size());
- break;
+ auto *Param = TemplateParams->getParam(Builder.size() - 1);
+ // If this is a fully-saturated fixed-size pack, it should be
+ // fully-substituted, not partially-substituted.
+ Optional<unsigned> Expansions = getExpandedPackSize(Param);
+ if (!Expansions || Arg.pack_size() < *Expansions) {
+ PartiallySubstitutedPackIndex = Builder.size() - 1;
+ CurrentInstantiationScope->SetPartiallySubstitutedPack(
+ Param, Arg.pack_begin(), Arg.pack_size());
+ }
}
}
@@ -2955,13 +3132,13 @@ Sema::SubstituteExplicitTemplateArguments(
// 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. Explicitly-specified
- // parameter packs, however, will be set to NULL since the deduction
- // mechanisms handle explicitly-specified argument packs directly.
+ // the set of deduced template arguments. The partially-substituted
+ // parameter pack, however, will be set to NULL since the deduction
+ // mechanism handles the partially-substituted argument pack directly.
Deduced.reserve(TemplateParams->size());
for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I) {
const TemplateArgument &Arg = ExplicitArgumentList->get(I);
- if (Arg.getKind() == TemplateArgument::Pack)
+ if (I == PartiallySubstitutedPackIndex)
Deduced.push_back(DeducedTemplateArgument());
else
Deduced.push_back(Arg);
@@ -2970,7 +3147,7 @@ Sema::SubstituteExplicitTemplateArguments(
return TDK_Success;
}
-/// \brief Check whether the deduced argument type for a call to a function
+/// Check whether the deduced argument type for a call to a function
/// template matches the actual argument type per C++ [temp.deduct.call]p4.
static Sema::TemplateDeductionResult
CheckOriginalCallArgDeduction(Sema &S, TemplateDeductionInfo &Info,
@@ -3080,7 +3257,7 @@ CheckOriginalCallArgDeduction(Sema &S, TemplateDeductionInfo &Info,
return Sema::TDK_Success;
if (A->isRecordType() && isSimpleTemplateIdType(OriginalParamType) &&
- S.IsDerivedFrom(SourceLocation(), A, DeducedA))
+ S.IsDerivedFrom(Info.getLocation(), A, DeducedA))
return Sema::TDK_Success;
return Failed();
@@ -3116,7 +3293,7 @@ static unsigned getPackIndexForParam(Sema &S,
llvm_unreachable("parameter index would not be produced from template");
}
-/// \brief Finish template argument deduction for a function template,
+/// Finish template argument deduction for a function template,
/// checking the deduced template arguments for completeness and forming
/// the function template specialization.
///
@@ -3267,13 +3444,14 @@ static QualType GetTypeOfFunction(Sema &S, const OverloadExpr::FindResult &R,
// We may need to deduce the return type of the function now.
if (S.getLangOpts().CPlusPlus14 && Fn->getReturnType()->isUndeducedType() &&
S.DeduceReturnType(Fn, R.Expression->getExprLoc(), /*Diagnose*/ false))
- return QualType();
+ return {};
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn))
if (Method->isInstance()) {
// An instance method that's referenced in a form that doesn't
// look like a member pointer is just invalid.
- if (!R.HasFormOfMemberPointer) return QualType();
+ if (!R.HasFormOfMemberPointer)
+ return {};
return S.Context.getMemberPointerType(Fn->getType(),
S.Context.getTypeDeclType(Method->getParent()).getTypePtr());
@@ -3322,7 +3500,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
S.resolveAddressOfOnlyViableOverloadCandidate(Arg, DAP))
return GetTypeOfFunction(S, R, Viable);
- return QualType();
+ return {};
}
// Gather the explicit template arguments, if any.
@@ -3339,7 +3517,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
// function templates, the parameter is treated as a
// non-deduced context.
if (!Ovl->hasExplicitTemplateArgs())
- return QualType();
+ return {};
// Otherwise, see if we can resolve a function type
FunctionDecl *Specialization = nullptr;
@@ -3379,14 +3557,15 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
= DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType,
ArgType, Info, Deduced, TDF);
if (Result) continue;
- if (!Match.isNull()) return QualType();
+ if (!Match.isNull())
+ return {};
Match = ArgType;
}
return Match;
}
-/// \brief Perform the adjustments to the parameter and argument types
+/// 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
@@ -3493,7 +3672,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument(
SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs,
bool DecomposedParam, unsigned ArgIdx, unsigned TDF);
-/// \brief Attempt template argument deduction from an initializer list
+/// Attempt template argument deduction from an initializer list
/// deemed to be an argument in a function call.
static Sema::TemplateDeductionResult DeduceFromInitializerList(
Sema &S, TemplateParameterList *TemplateParams, QualType AdjustedParamType,
@@ -3554,7 +3733,7 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList(
return Sema::TDK_Success;
}
-/// \brief Perform template argument deduction per [temp.deduct.call] for a
+/// Perform template argument deduction per [temp.deduct.call] for a
/// single parameter / argument pair.
static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument(
Sema &S, TemplateParameterList *TemplateParams, unsigned FirstInnerIndex,
@@ -3587,7 +3766,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument(
ArgType, Info, Deduced, TDF);
}
-/// \brief Perform template argument deduction from a function call
+/// Perform template argument deduction from a function call
/// (C++ [temp.deduct.call]).
///
/// \param FunctionTemplate the function template for which we are performing
@@ -3725,8 +3904,9 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
// the length of the explicitly-specified pack if it's expanded by the
// parameter pack and 0 otherwise, and we treat each deduction as a
// non-deduced context.
- if (ParamIdx + 1 == NumParamTypes) {
- for (; ArgIdx < Args.size(); PackScope.nextPackElement(), ++ArgIdx) {
+ if (ParamIdx + 1 == NumParamTypes || PackScope.hasFixedArity()) {
+ for (; ArgIdx < Args.size() && PackScope.hasNextElement();
+ PackScope.nextPackElement(), ++ArgIdx) {
ParamTypesForArgChecking.push_back(ParamPattern);
if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx))
return Result;
@@ -3753,10 +3933,16 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
return Result;
}
+ // Capture the context in which the function call is made. This is the context
+ // that is needed when the accessibility of template arguments is checked.
+ DeclContext *CallingCtx = CurContext;
+
return FinishTemplateArgumentDeduction(
FunctionTemplate, Deduced, NumExplicitlySpecified, Specialization, Info,
- &OriginalCallArgs, PartialOverloading,
- [&]() { return CheckNonDependent(ParamTypesForArgChecking); });
+ &OriginalCallArgs, PartialOverloading, [&, CallingCtx]() {
+ ContextRAII SavedContext(*this, CallingCtx);
+ return CheckNonDependent(ParamTypesForArgChecking);
+ });
}
QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
@@ -3798,7 +3984,7 @@ QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
ArgFunctionTypeP->getParamTypes(), EPI);
}
-/// \brief Deduce template arguments when taking the address of a function
+/// Deduce template arguments when taking the address of a function
/// template (C++ [temp.deduct.funcaddr]) or matching a specialization to
/// a template.
///
@@ -3940,118 +4126,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
return TDK_Success;
}
-/// \brief Given a function declaration (e.g. a generic lambda conversion
-/// function) that contains an 'auto' in its result type, substitute it
-/// with TypeToReplaceAutoWith. Be careful to pass in the type you want
-/// to replace 'auto' with and not the actual result type you want
-/// to set the function to.
-static inline void
-SubstAutoWithinFunctionReturnType(FunctionDecl *F,
- QualType TypeToReplaceAutoWith, Sema &S) {
- assert(!TypeToReplaceAutoWith->getContainedAutoType());
- QualType AutoResultType = F->getReturnType();
- assert(AutoResultType->getContainedAutoType());
- QualType DeducedResultType = S.SubstAutoType(AutoResultType,
- TypeToReplaceAutoWith);
- S.Context.adjustDeducedFunctionResultType(F, DeducedResultType);
-}
-
-/// \brief Given a specialized conversion operator of a generic lambda
-/// create the corresponding specializations of the call operator and
-/// the static-invoker. If the return type of the call operator is auto,
-/// deduce its return type and check if that matches the
-/// return type of the destination function ptr.
-
-static inline Sema::TemplateDeductionResult
-SpecializeCorrespondingLambdaCallOperatorAndInvoker(
- CXXConversionDecl *ConversionSpecialized,
- SmallVectorImpl<DeducedTemplateArgument> &DeducedArguments,
- QualType ReturnTypeOfDestFunctionPtr,
- TemplateDeductionInfo &TDInfo,
- Sema &S) {
-
- CXXRecordDecl *LambdaClass = ConversionSpecialized->getParent();
- assert(LambdaClass && LambdaClass->isGenericLambda());
-
- CXXMethodDecl *CallOpGeneric = LambdaClass->getLambdaCallOperator();
- QualType CallOpResultType = CallOpGeneric->getReturnType();
- const bool GenericLambdaCallOperatorHasDeducedReturnType =
- CallOpResultType->getContainedAutoType();
-
- FunctionTemplateDecl *CallOpTemplate =
- CallOpGeneric->getDescribedFunctionTemplate();
-
- FunctionDecl *CallOpSpecialized = nullptr;
- // Use the deduced arguments of the conversion function, to specialize our
- // generic lambda's call operator.
- if (Sema::TemplateDeductionResult Result
- = S.FinishTemplateArgumentDeduction(CallOpTemplate,
- DeducedArguments,
- 0, CallOpSpecialized, TDInfo))
- return Result;
-
- // If we need to deduce the return type, do so (instantiates the callop).
- if (GenericLambdaCallOperatorHasDeducedReturnType &&
- CallOpSpecialized->getReturnType()->isUndeducedType())
- S.DeduceReturnType(CallOpSpecialized,
- CallOpSpecialized->getPointOfInstantiation(),
- /*Diagnose*/ true);
-
- // Check to see if the return type of the destination ptr-to-function
- // matches the return type of the call operator.
- if (!S.Context.hasSameType(CallOpSpecialized->getReturnType(),
- ReturnTypeOfDestFunctionPtr))
- return Sema::TDK_NonDeducedMismatch;
- // Since we have succeeded in matching the source and destination
- // ptr-to-functions (now including return type), and have successfully
- // specialized our corresponding call operator, we are ready to
- // specialize the static invoker with the deduced arguments of our
- // ptr-to-function.
- FunctionDecl *InvokerSpecialized = nullptr;
- FunctionTemplateDecl *InvokerTemplate = LambdaClass->
- getLambdaStaticInvoker()->getDescribedFunctionTemplate();
-
-#ifndef NDEBUG
- Sema::TemplateDeductionResult LLVM_ATTRIBUTE_UNUSED Result =
-#endif
- S.FinishTemplateArgumentDeduction(InvokerTemplate, DeducedArguments, 0,
- InvokerSpecialized, TDInfo);
- assert(Result == Sema::TDK_Success &&
- "If the call operator succeeded so should the invoker!");
- // Set the result type to match the corresponding call operator
- // specialization's result type.
- if (GenericLambdaCallOperatorHasDeducedReturnType &&
- InvokerSpecialized->getReturnType()->isUndeducedType()) {
- // Be sure to get the type to replace 'auto' with and not
- // the full result type of the call op specialization
- // to substitute into the 'auto' of the invoker and conversion
- // function.
- // For e.g.
- // int* (*fp)(int*) = [](auto* a) -> auto* { return a; };
- // We don't want to subst 'int*' into 'auto' to get int**.
-
- QualType TypeToReplaceAutoWith = CallOpSpecialized->getReturnType()
- ->getContainedAutoType()
- ->getDeducedType();
- SubstAutoWithinFunctionReturnType(InvokerSpecialized,
- TypeToReplaceAutoWith, S);
- SubstAutoWithinFunctionReturnType(ConversionSpecialized,
- TypeToReplaceAutoWith, S);
- }
-
- // Ensure that static invoker doesn't have a const qualifier.
- // FIXME: When creating the InvokerTemplate in SemaLambda.cpp
- // do not use the CallOperator's TypeSourceInfo which allows
- // the const qualifier to leak through.
- const FunctionProtoType *InvokerFPT = InvokerSpecialized->
- getType().getTypePtr()->castAs<FunctionProtoType>();
- FunctionProtoType::ExtProtoInfo EPI = InvokerFPT->getExtProtoInfo();
- EPI.TypeQuals = 0;
- InvokerSpecialized->setType(S.Context.getFunctionType(
- InvokerFPT->getReturnType(), InvokerFPT->getParamTypes(), EPI));
- return Sema::TDK_Success;
-}
-/// \brief Deduce template arguments for a templated conversion
+/// Deduce template arguments for a templated conversion
/// function (C++ [temp.deduct.conv]) and, if successful, produce a
/// conversion function template specialization.
Sema::TemplateDeductionResult
@@ -4080,12 +4155,20 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
// C++0x [temp.deduct.conv]p4:
// [...] If A is a reference type, the type referred to by A is used
// for type deduction.
- if (const ReferenceType *ARef = A->getAs<ReferenceType>())
- A = ARef->getPointeeType().getUnqualifiedType();
+ if (const ReferenceType *ARef = A->getAs<ReferenceType>()) {
+ A = ARef->getPointeeType();
+ // We work around a defect in the standard here: cv-qualifiers are also
+ // removed from P and A in this case, unless P was a reference type. This
+ // seems to mostly match what other compilers are doing.
+ if (!FromType->getAs<ReferenceType>()) {
+ A = A.getUnqualifiedType();
+ P = P.getUnqualifiedType();
+ }
+
// C++ [temp.deduct.conv]p3:
//
// If A is not a reference type:
- else {
+ } else {
assert(!A->isReferenceType() && "Reference types were handled above");
// - If P is an array type, the pointer type produced by the
@@ -4134,7 +4217,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
// cv-qualified than the deduced A (i.e., the type referred to
// by the reference)
if (ToType->isReferenceType())
- TDF |= TDF_ParamWithReferenceType;
+ TDF |= TDF_ArgWithReferenceType;
// - The deduced A can be another pointer or pointer to member
// type that can be converted to A via a qualification
// conversion.
@@ -4158,39 +4241,10 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
= FinishTemplateArgumentDeduction(ConversionTemplate, Deduced, 0,
ConversionSpecialized, Info);
Specialization = cast_or_null<CXXConversionDecl>(ConversionSpecialized);
-
- // If the conversion operator is being invoked on a lambda closure to convert
- // to a ptr-to-function, use the deduced arguments from the conversion
- // function to specialize the corresponding call operator.
- // e.g., int (*fp)(int) = [](auto a) { return a; };
- if (Result == TDK_Success && isLambdaConversionOperator(ConversionGeneric)) {
-
- // Get the return type of the destination ptr-to-function we are converting
- // to. This is necessary for matching the lambda call operator's return
- // type to that of the destination ptr-to-function's return type.
- assert(A->isPointerType() &&
- "Can only convert from lambda to ptr-to-function");
- const FunctionType *ToFunType =
- A->getPointeeType().getTypePtr()->getAs<FunctionType>();
- const QualType DestFunctionPtrReturnType = ToFunType->getReturnType();
-
- // Create the corresponding specializations of the call operator and
- // the static-invoker; and if the return type is auto,
- // deduce the return type and check if it matches the
- // DestFunctionPtrReturnType.
- // For instance:
- // auto L = [](auto a) { return f(a); };
- // int (*fp)(int) = L;
- // char (*fp2)(int) = L; <-- Not OK.
-
- Result = SpecializeCorrespondingLambdaCallOperatorAndInvoker(
- Specialization, Deduced, DestFunctionPtrReturnType,
- Info, *this);
- }
return Result;
}
-/// \brief Deduce template arguments for a function template when there is
+/// Deduce template arguments for a function template when there is
/// nothing to deduce against (C++0x [temp.arg.explicit]p3).
///
/// \param FunctionTemplate the function template for which we are performing
@@ -4225,12 +4279,14 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
}
namespace {
+
/// Substitute the 'auto' specifier or deduced template specialization type
/// specifier within a type for a given replacement type.
class SubstituteDeducedTypeTransform :
public TreeTransform<SubstituteDeducedTypeTransform> {
QualType Replacement;
bool UseTypeSugar;
+
public:
SubstituteDeducedTypeTransform(Sema &SemaRef, QualType Replacement,
bool UseTypeSugar = true)
@@ -4292,7 +4348,8 @@ namespace {
return TransformType(TLB, TL);
}
};
-}
+
+} // namespace
Sema::DeduceAutoResult
Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init, QualType &Result,
@@ -4326,7 +4383,7 @@ static bool diagnoseAutoDeductionFailure(Sema &S,
}
}
-/// \brief Deduce the type for an auto type-specifier (C++11 [dcl.spec.auto]p6)
+/// Deduce the type for an auto type-specifier (C++11 [dcl.spec.auto]p6)
///
/// Note that this is done even if the initializer is dependent. (This is
/// necessary to support partial ordering of templates using 'auto'.)
@@ -4536,6 +4593,43 @@ bool Sema::DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
bool Diagnose) {
assert(FD->getReturnType()->isUndeducedType());
+ // For a lambda's conversion operator, deduce any 'auto' or 'decltype(auto)'
+ // within the return type from the call operator's type.
+ if (isLambdaConversionOperator(FD)) {
+ CXXRecordDecl *Lambda = cast<CXXMethodDecl>(FD)->getParent();
+ FunctionDecl *CallOp = Lambda->getLambdaCallOperator();
+
+ // For a generic lambda, instantiate the call operator if needed.
+ if (auto *Args = FD->getTemplateSpecializationArgs()) {
+ CallOp = InstantiateFunctionDeclaration(
+ CallOp->getDescribedFunctionTemplate(), Args, Loc);
+ if (!CallOp || CallOp->isInvalidDecl())
+ return true;
+
+ // We might need to deduce the return type by instantiating the definition
+ // of the operator() function.
+ if (CallOp->getReturnType()->isUndeducedType())
+ InstantiateFunctionDefinition(Loc, CallOp);
+ }
+
+ if (CallOp->isInvalidDecl())
+ return true;
+ assert(!CallOp->getReturnType()->isUndeducedType() &&
+ "failed to deduce lambda return type");
+
+ // Build the new return type from scratch.
+ QualType RetType = getLambdaConversionFunctionResultType(
+ CallOp->getType()->castAs<FunctionProtoType>());
+ if (FD->getReturnType()->getAs<PointerType>())
+ RetType = Context.getPointerType(RetType);
+ else {
+ assert(FD->getReturnType()->getAs<BlockPointerType>());
+ RetType = Context.getBlockPointerType(RetType);
+ }
+ Context.adjustDeducedFunctionResultType(FD, RetType);
+ return false;
+ }
+
if (FD->getTemplateInstantiationPattern())
InstantiateFunctionDefinition(Loc, FD);
@@ -4548,7 +4642,7 @@ bool Sema::DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
return StillUndeduced;
}
-/// \brief If this is a non-static member function,
+/// If this is a non-static member function,
static void
AddImplicitObjectParameterType(ASTContext &Context,
CXXMethodDecl *Method,
@@ -4570,7 +4664,7 @@ AddImplicitObjectParameterType(ASTContext &Context,
ArgTypes.push_back(ArgTy);
}
-/// \brief Determine whether the function template \p FT1 is at least as
+/// Determine whether the function template \p FT1 is at least as
/// specialized as \p FT2.
static bool isAtLeastAsSpecializedAs(Sema &S,
SourceLocation Loc,
@@ -4721,7 +4815,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
return true;
}
-/// \brief Determine whether this a function template whose parameter-type-list
+/// 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();
@@ -4742,7 +4836,7 @@ static bool isVariadicFunctionTemplate(FunctionTemplateDecl *FunTmpl) {
return true;
}
-/// \brief Returns the more specialized function template according
+/// Returns the more specialized function template according
/// to the rules of function template partial ordering (C++ [temp.func.order]).
///
/// \param FT1 the first function template
@@ -4789,7 +4883,7 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
return nullptr;
}
-/// \brief Determine if the two templates are equivalent.
+/// Determine if the two templates are equivalent.
static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
if (T1 == T2)
return true;
@@ -4800,7 +4894,7 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
return T1->getCanonicalDecl() == T2->getCanonicalDecl();
}
-/// \brief Retrieve the most specialized of the given function template
+/// Retrieve the most specialized of the given function template
/// specializations.
///
/// \param SpecBegin the start iterator of the function template
@@ -4959,7 +5053,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, QualType T1, QualType T2,
return true;
}
-/// \brief Returns the more specialized class template partial specialization
+/// Returns the more specialized class template partial specialization
/// according to the rules of partial ordering of class template partial
/// specializations (C++ [temp.class.order]).
///
@@ -5114,7 +5208,7 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
return isAtLeastAsSpecializedAs(*this, PType, AType, AArg, Info);
}
-/// \brief Mark the template parameters that are used by the given
+/// Mark the template parameters that are used by the given
/// expression.
static void
MarkUsedTemplateParameters(ASTContext &Ctx,
@@ -5128,7 +5222,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
// Skip through any implicit casts we added while type-checking, and any
// substitutions performed by template alias expansion.
- while (1) {
+ while (true) {
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
E = ICE->getSubExpr();
else if (const SubstNonTypeTemplateParmExpr *Subst =
@@ -5158,7 +5252,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
MarkUsedTemplateParameters(Ctx, NTTP->getType(), OnlyDeduced, Depth, Used);
}
-/// \brief Mark the template parameters that are used by the given
+/// Mark the template parameters that are used by the given
/// nested name specifier.
static void
MarkUsedTemplateParameters(ASTContext &Ctx,
@@ -5175,7 +5269,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
OnlyDeduced, Depth, Used);
}
-/// \brief Mark the template parameters that are used by the given
+/// Mark the template parameters that are used by the given
/// template name.
static void
MarkUsedTemplateParameters(ASTContext &Ctx,
@@ -5200,7 +5294,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
Depth, Used);
}
-/// \brief Mark the template parameters that are used by the given
+/// Mark the template parameters that are used by the given
/// type.
static void
MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
@@ -5271,6 +5365,14 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
OnlyDeduced, Depth, Used);
break;
+ case Type::DependentVector: {
+ const auto *VecType = cast<DependentVectorType>(T);
+ MarkUsedTemplateParameters(Ctx, VecType->getElementType(), OnlyDeduced,
+ Depth, Used);
+ MarkUsedTemplateParameters(Ctx, VecType->getSizeExpr(), OnlyDeduced, Depth,
+ Used);
+ break;
+ }
case Type::DependentSizedExtVector: {
const DependentSizedExtVectorType *VecType
= cast<DependentSizedExtVectorType>(T);
@@ -5296,9 +5398,24 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
MarkUsedTemplateParameters(Ctx, Proto->getReturnType(), OnlyDeduced, Depth,
Used);
- for (unsigned I = 0, N = Proto->getNumParams(); I != N; ++I)
- MarkUsedTemplateParameters(Ctx, Proto->getParamType(I), OnlyDeduced,
- Depth, Used);
+ for (unsigned I = 0, N = Proto->getNumParams(); I != N; ++I) {
+ // C++17 [temp.deduct.type]p5:
+ // The non-deduced contexts are: [...]
+ // -- A function parameter pack that does not occur at the end of the
+ // parameter-declaration-list.
+ if (!OnlyDeduced || I + 1 == N ||
+ !Proto->getParamType(I)->getAs<PackExpansionType>()) {
+ MarkUsedTemplateParameters(Ctx, Proto->getParamType(I), OnlyDeduced,
+ Depth, Used);
+ } else {
+ // FIXME: C++17 [temp.deduct.call]p1:
+ // When a function parameter pack appears in a non-deduced context,
+ // the type of that pack is never deduced.
+ //
+ // We should also track a set of "never deduced" parameters, and
+ // subtract that from the list of deduced parameters after marking.
+ }
+ }
if (auto *E = Proto->getNoexceptExpr())
MarkUsedTemplateParameters(Ctx, E, OnlyDeduced, Depth, Used);
break;
@@ -5453,7 +5570,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
}
}
-/// \brief Mark the template parameters that are used by this
+/// Mark the template parameters that are used by this
/// template argument.
static void
MarkUsedTemplateParameters(ASTContext &Ctx,
@@ -5496,7 +5613,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
}
}
-/// \brief Mark which template parameters can be deduced from a given
+/// Mark which template parameters can be deduced from a given
/// template argument list.
///
/// \param TemplateArgs the template argument list from which template
@@ -5522,7 +5639,7 @@ Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
Depth, Used);
}
-/// \brief Marks all of the template parameters that will be deduced by a
+/// Marks all of the template parameters that will be deduced by a
/// call to the given function template.
void Sema::MarkDeducedTemplateParameters(
ASTContext &Ctx, const FunctionTemplateDecl *FunctionTemplate,