summaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Sema/SemaTemplateDeduction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaTemplateDeduction.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaTemplateDeduction.cpp440
1 files changed, 357 insertions, 83 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm-project/clang/lib/Sema/SemaTemplateDeduction.cpp
index b55a232d26c2..6b865a601f9d 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -24,6 +24,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
@@ -642,6 +643,10 @@ static TemplateParameter makeTemplateParameter(Decl *D) {
/// If \p Param is an expanded parameter pack, get the number of expansions.
static Optional<unsigned> getExpandedPackSize(NamedDecl *Param) {
+ if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
+ if (TTP->isExpandedParameterPack())
+ return TTP->getNumExpansionParameters();
+
if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param))
if (NTTP->isExpandedParameterPack())
return NTTP->getNumExpansionTypes();
@@ -719,38 +724,48 @@ private:
// Compute the set of template parameter indices that correspond to
// parameter packs expanded by the pack expansion.
llvm::SmallBitVector SawIndices(TemplateParams->size());
+ llvm::SmallVector<TemplateArgument, 4> ExtraDeductions;
auto AddPack = [&](unsigned Index) {
if (SawIndices[Index])
return;
SawIndices[Index] = true;
addPack(Index);
+
+ // Deducing a parameter pack that is a pack expansion also constrains the
+ // packs appearing in that parameter to have the same deduced arity. Also,
+ // in C++17 onwards, deducing a non-type template parameter deduces its
+ // type, so we need to collect the pending deduced values for those packs.
+ if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(
+ TemplateParams->getParam(Index))) {
+ if (auto *Expansion = dyn_cast<PackExpansionType>(NTTP->getType()))
+ ExtraDeductions.push_back(Expansion->getPattern());
+ }
+ // FIXME: Also collect the unexpanded packs in any type and template
+ // parameter packs that are pack expansions.
};
- // 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);
- }
+ auto Collect = [&](TemplateArgument 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);
+ }
+ };
+
+ // Look for unexpanded packs in the pattern.
+ Collect(Pattern);
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);
+ // Also look for unexpanded packs that are indirectly deduced by deducing
+ // the sizes of the packs in this pattern.
+ while (!ExtraDeductions.empty())
+ Collect(ExtraDeductions.pop_back_val());
return NumNamedPacks;
}
@@ -859,34 +874,31 @@ public:
/// Finish template argument deduction for a set of argument packs,
/// producing the argument packs and checking for consistency with prior
/// deductions.
- Sema::TemplateDeductionResult
- finish(bool TreatNoDeductionsAsNonDeduced = true) {
+ Sema::TemplateDeductionResult finish() {
// 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);
+ // Always make sure the size of this pack is correct, even if we didn't
+ // deduce any values for it.
+ //
+ // FIXME: This isn't required by the normative wording, but substitution
+ // and post-substitution checking will always fail if the arity of any
+ // pack is not equal to the number of elements we processed. (Either that
+ // or something else has gone *very* wrong.) We're permitted to skip any
+ // hard errors from those follow-on steps by the intent (but not the
+ // wording) of C++ [temp.inst]p8:
+ //
+ // If the function selected by overload resolution can be determined
+ // without instantiating a class template definition, it is unspecified
+ // whether that instantiation actually takes place
+ Pack.New.resize(PackElements);
// Build or find a new value for this pack.
DeducedTemplateArgument NewPack;
- if (PackElements && Pack.New.empty()) {
- if (Pack.DeferredDeduction.isNull()) {
- // We were not able to deduce anything for this parameter pack
- // (because it only appeared in non-deduced contexts), so just
- // restore the saved argument pack.
- continue;
- }
-
- NewPack = Pack.DeferredDeduction;
- Pack.DeferredDeduction = TemplateArgument();
- } else if (Pack.New.empty()) {
+ if (Pack.New.empty()) {
// If we deduced an empty argument pack, create it now.
NewPack = DeducedTemplateArgument(TemplateArgument::getEmptyPack());
} else {
@@ -1486,7 +1498,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
#define NON_CANONICAL_TYPE(Class, Base) \
case Type::Class: llvm_unreachable("deducing non-canonical type: " #Class);
#define TYPE(Class, Base)
-#include "clang/AST/TypeNodes.def"
+#include "clang/AST/TypeNodes.inc"
case Type::TemplateTypeParm:
case Type::SubstTemplateTypeParmPack:
@@ -2476,7 +2488,7 @@ Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion: {
NestedNameSpecifierLocBuilder Builder;
- TemplateName Template = Arg.getAsTemplate();
+ TemplateName Template = Arg.getAsTemplateOrTemplatePattern();
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
else if (QualifiedTemplateName *QTN =
@@ -2501,6 +2513,13 @@ Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
llvm_unreachable("Invalid TemplateArgument Kind!");
}
+TemplateArgumentLoc
+Sema::getIdentityTemplateArgumentLoc(NamedDecl *TemplateParm,
+ SourceLocation Location) {
+ return getTrivialTemplateArgumentLoc(
+ Context.getInjectedTemplateArg(TemplateParm), QualType(), Location);
+}
+
/// Convert the given deduced template argument and add it to the set of
/// fully-converted template arguments.
static bool
@@ -2611,8 +2630,8 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments(
// 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))
+ if (auto Result =
+ PackDeductionScope(S, TemplateParams, Deduced, Info, I).finish())
return Result;
}
@@ -2709,6 +2728,23 @@ struct IsPartialSpecialization<VarTemplatePartialSpecializationDecl> {
static constexpr bool value = true;
};
+template<typename TemplateDeclT>
+static Sema::TemplateDeductionResult
+CheckDeducedArgumentConstraints(Sema& S, TemplateDeclT *Template,
+ ArrayRef<TemplateArgument> DeducedArgs,
+ TemplateDeductionInfo& Info) {
+ llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
+ Template->getAssociatedConstraints(AssociatedConstraints);
+ if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints,
+ DeducedArgs, Info.getLocation(),
+ Info.AssociatedConstraintsSatisfaction) ||
+ !Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
+ Info.reset(TemplateArgumentList::CreateCopy(S.Context, DeducedArgs));
+ return Sema::TDK_ConstraintsNotSatisfied;
+ }
+ return Sema::TDK_Success;
+}
+
/// Complete template argument deduction for a partial specialization.
template <typename T>
static typename std::enable_if<IsPartialSpecialization<T>::value,
@@ -2767,10 +2803,14 @@ FinishTemplateArgumentDeduction(
return Sema::TDK_SubstitutionFailure;
}
+ bool ConstraintsNotSatisfied;
SmallVector<TemplateArgument, 4> ConvertedInstArgs;
if (S.CheckTemplateArgumentList(Template, Partial->getLocation(), InstArgs,
- false, ConvertedInstArgs))
- return Sema::TDK_SubstitutionFailure;
+ false, ConvertedInstArgs,
+ /*UpdateArgsWithConversions=*/true,
+ &ConstraintsNotSatisfied))
+ return ConstraintsNotSatisfied ? Sema::TDK_ConstraintsNotSatisfied :
+ Sema::TDK_SubstitutionFailure;
TemplateParameterList *TemplateParams = Template->getTemplateParameters();
for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {
@@ -2786,6 +2826,9 @@ FinishTemplateArgumentDeduction(
if (Trap.hasErrorOccurred())
return Sema::TDK_SubstitutionFailure;
+ if (auto Result = CheckDeducedArgumentConstraints(S, Partial, Builder, Info))
+ return Result;
+
return Sema::TDK_Success;
}
@@ -2828,10 +2871,13 @@ static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
if (Trap.hasErrorOccurred())
return Sema::TDK_SubstitutionFailure;
+ if (auto Result = CheckDeducedArgumentConstraints(S, Template, Builder,
+ Info))
+ return Result;
+
return Sema::TDK_Success;
}
-
/// Perform template argument deduction to determine whether
/// the given template arguments match the given class template
/// partial specialization per C++ [temp.class.spec.match].
@@ -3093,6 +3139,13 @@ Sema::SubstituteExplicitTemplateArguments(
Function->getTypeSpecStartLoc(), Function->getDeclName());
if (ResultType.isNull() || Trap.hasErrorOccurred())
return TDK_SubstitutionFailure;
+ // CUDA: Kernel function must have 'void' return type.
+ if (getLangOpts().CUDA)
+ if (Function->hasAttr<CUDAGlobalAttr>() && !ResultType->isVoidType()) {
+ Diag(Function->getLocation(), diag::err_kern_type_not_void_return)
+ << Function->getType() << Function->getSourceRange();
+ return TDK_SubstitutionFailure;
+ }
}
// Instantiate the types of each of the function parameters given the
@@ -3378,6 +3431,26 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
return TDK_SubstitutionFailure;
}
+ // C++2a [temp.deduct]p5
+ // [...] When all template arguments have been deduced [...] all uses of
+ // template parameters [...] are replaced with the corresponding deduced
+ // or default argument values.
+ // [...] If the function template has associated constraints
+ // ([temp.constr.decl]), those constraints are checked for satisfaction
+ // ([temp.constr.constr]). If the constraints are not satisfied, type
+ // deduction fails.
+ if (!PartialOverloading ||
+ (Builder.size() == FunctionTemplate->getTemplateParameters()->size())) {
+ if (CheckInstantiatedFunctionTemplateConstraints(Info.getLocation(),
+ Specialization, Builder, Info.AssociatedConstraintsSatisfaction))
+ return TDK_MiscellaneousDeductionFailure;
+
+ if (!Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
+ Info.reset(TemplateArgumentList::CreateCopy(Context, Builder));
+ return TDK_ConstraintsNotSatisfied;
+ }
+ }
+
if (OriginalCallArgs) {
// C++ [temp.deduct.call]p4:
// In general, the deduction process attempts to find template argument
@@ -3498,7 +3571,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
DeclAccessPair DAP;
if (FunctionDecl *Viable =
- S.resolveAddressOfOnlyViableOverloadCandidate(Arg, DAP))
+ S.resolveAddressOfSingleOverloadCandidate(Arg, DAP))
return GetTypeOfFunction(S, R, Viable);
return {};
@@ -3702,6 +3775,12 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList(
return Sema::TDK_Success;
}
+ // Resolving a core issue: a braced-init-list containing any designators is
+ // a non-deduced context.
+ for (Expr *E : ILE->inits())
+ if (isa<DesignatedInitExpr>(E))
+ return Sema::TDK_Success;
+
// Deduction only needs to be done for dependent types.
if (ElTy->isDependentType()) {
for (Expr *E : ILE->inits()) {
@@ -3813,8 +3892,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
if (Args.size() < Function->getMinRequiredArguments() && !PartialOverloading)
return TDK_TooFewArguments;
else if (TooManyArguments(NumParams, Args.size(), PartialOverloading)) {
- const FunctionProtoType *Proto
- = Function->getType()->getAs<FunctionProtoType>();
+ const auto *Proto = Function->getType()->castAs<FunctionProtoType>();
if (Proto->isTemplateVariadic())
/* Do nothing */;
else if (!Proto->isVariadic())
@@ -3952,11 +4030,8 @@ QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
if (ArgFunctionType.isNull())
return ArgFunctionType;
- const FunctionProtoType *FunctionTypeP =
- FunctionType->castAs<FunctionProtoType>();
- const FunctionProtoType *ArgFunctionTypeP =
- ArgFunctionType->getAs<FunctionProtoType>();
-
+ const auto *FunctionTypeP = FunctionType->castAs<FunctionProtoType>();
+ const auto *ArgFunctionTypeP = ArgFunctionType->castAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = ArgFunctionTypeP->getExtProtoInfo();
bool Rebuild = false;
@@ -4325,9 +4400,10 @@ namespace {
QualType Result = SemaRef.Context.getAutoType(
Replacement, TL.getTypePtr()->getKeyword(), Replacement.isNull(),
- ReplacementIsPack);
+ ReplacementIsPack, TL.getTypePtr()->getTypeConstraintConcept(),
+ TL.getTypePtr()->getTypeConstraintArguments());
auto NewTL = TLB.push<AutoTypeLoc>(Result);
- NewTL.setNameLoc(TL.getNameLoc());
+ NewTL.copy(TL);
return Result;
}
@@ -4362,9 +4438,10 @@ namespace {
Sema::DeduceAutoResult
Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init, QualType &Result,
- Optional<unsigned> DependentDeductionDepth) {
+ Optional<unsigned> DependentDeductionDepth,
+ bool IgnoreConstraints) {
return DeduceAutoType(Type->getTypeLoc(), Init, Result,
- DependentDeductionDepth);
+ DependentDeductionDepth, IgnoreConstraints);
}
/// Attempt to produce an informative diagostic explaining why auto deduction
@@ -4392,6 +4469,49 @@ static bool diagnoseAutoDeductionFailure(Sema &S,
}
}
+static Sema::DeduceAutoResult
+CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type,
+ AutoTypeLoc TypeLoc, QualType Deduced) {
+ ConstraintSatisfaction Satisfaction;
+ ConceptDecl *Concept = Type.getTypeConstraintConcept();
+ TemplateArgumentListInfo TemplateArgs(TypeLoc.getLAngleLoc(),
+ TypeLoc.getRAngleLoc());
+ TemplateArgs.addArgument(
+ TemplateArgumentLoc(TemplateArgument(Deduced),
+ S.Context.getTrivialTypeSourceInfo(
+ Deduced, TypeLoc.getNameLoc())));
+ for (unsigned I = 0, C = TypeLoc.getNumArgs(); I != C; ++I)
+ TemplateArgs.addArgument(TypeLoc.getArgLoc(I));
+
+ llvm::SmallVector<TemplateArgument, 4> Converted;
+ if (S.CheckTemplateArgumentList(Concept, SourceLocation(), TemplateArgs,
+ /*PartialTemplateArgs=*/false, Converted))
+ return Sema::DAR_FailedAlreadyDiagnosed;
+ if (S.CheckConstraintSatisfaction(Concept, {Concept->getConstraintExpr()},
+ Converted, TypeLoc.getLocalSourceRange(),
+ Satisfaction))
+ return Sema::DAR_FailedAlreadyDiagnosed;
+ if (!Satisfaction.IsSatisfied) {
+ std::string Buf;
+ llvm::raw_string_ostream OS(Buf);
+ OS << "'" << Concept->getName();
+ if (TypeLoc.hasExplicitTemplateArgs()) {
+ OS << "<";
+ for (const auto &Arg : Type.getTypeConstraintArguments())
+ Arg.print(S.getPrintingPolicy(), OS);
+ OS << ">";
+ }
+ OS << "'";
+ OS.flush();
+ S.Diag(TypeLoc.getConceptNameLoc(),
+ diag::err_placeholder_constraints_not_satisfied)
+ << Deduced << Buf << TypeLoc.getLocalSourceRange();
+ S.DiagnoseUnsatisfiedConstraint(Satisfaction);
+ return Sema::DAR_FailedAlreadyDiagnosed;
+ }
+ return Sema::DAR_Succeeded;
+}
+
/// 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
@@ -4406,9 +4526,12 @@ static bool diagnoseAutoDeductionFailure(Sema &S,
/// dependent cases. This is necessary for template partial ordering with
/// 'auto' template parameters. The value specified is the template
/// parameter depth at which we should perform 'auto' deduction.
+/// \param IgnoreConstraints Set if we should not fail if the deduced type does
+/// not satisfy the type-constraint in the auto type.
Sema::DeduceAutoResult
Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
- Optional<unsigned> DependentDeductionDepth) {
+ Optional<unsigned> DependentDeductionDepth,
+ bool IgnoreConstraints) {
if (Init->getType()->isNonOverloadPlaceholderType()) {
ExprResult NonPlaceholder = CheckPlaceholderExpr(Init);
if (NonPlaceholder.isInvalid())
@@ -4420,7 +4543,8 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
/*.IsPack = */ (bool)Type.getAs<PackExpansionTypeLoc>()};
if (!DependentDeductionDepth &&
- (Type.getType()->isDependentType() || Init->isTypeDependent())) {
+ (Type.getType()->isDependentType() || Init->isTypeDependent() ||
+ Init->containsUnexpandedParameterPack())) {
Result = SubstituteDeducedTypeTransform(*this, DependentResult).Apply(Type);
assert(!Result.isNull() && "substituting DependentTy can't fail");
return DAR_Succeeded;
@@ -4448,6 +4572,14 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
return DAR_FailedAlreadyDiagnosed;
// FIXME: Support a non-canonical deduced type for 'auto'.
Deduced = Context.getCanonicalType(Deduced);
+ if (AT->isConstrained() && !IgnoreConstraints) {
+ auto ConstraintsResult =
+ CheckDeducedPlaceholderConstraints(*this, *AT,
+ Type.getContainedAutoTypeLoc(),
+ Deduced);
+ if (ConstraintsResult != DAR_Succeeded)
+ return ConstraintsResult;
+ }
Result = SubstituteDeducedTypeTransform(*this, Deduced).Apply(Type);
if (Result.isNull())
return DAR_FailedAlreadyDiagnosed;
@@ -4466,11 +4598,12 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
// Build template<class TemplParam> void Func(FuncParam);
TemplateTypeParmDecl *TemplParam = TemplateTypeParmDecl::Create(
- Context, nullptr, SourceLocation(), Loc, Depth, 0, nullptr, false, false);
+ Context, nullptr, SourceLocation(), Loc, Depth, 0, nullptr, false, false,
+ false);
QualType TemplArg = QualType(TemplParam->getTypeForDecl(), 0);
NamedDecl *TemplParamPtr = TemplParam;
FixedSizeTemplateParameterListStorage<1, false> TemplateParamsSt(
- Loc, Loc, TemplParamPtr, Loc, nullptr);
+ Context, Loc, Loc, TemplParamPtr, Loc, nullptr);
QualType FuncParam =
SubstituteDeducedTypeTransform(*this, TemplArg, /*UseTypeSugar*/false)
@@ -4509,6 +4642,12 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
if (!Type.getType().getNonReferenceType()->getAs<AutoType>())
return DAR_Failed;
+ // Resolving a core issue: a braced-init-list containing any designators is
+ // a non-deduced context.
+ for (Expr *E : InitList->inits())
+ if (isa<DesignatedInitExpr>(E))
+ return DAR_Failed;
+
SourceRange DeducedFromInitRange;
for (unsigned i = 0, e = InitList->getNumInits(); i < e; ++i) {
Expr *Init = InitList->getInit(i);
@@ -4548,6 +4687,17 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
return DAR_FailedAlreadyDiagnosed;
}
+ if (const auto *AT = Type.getType()->getAs<AutoType>()) {
+ if (AT->isConstrained() && !IgnoreConstraints) {
+ auto ConstraintsResult =
+ CheckDeducedPlaceholderConstraints(*this, *AT,
+ Type.getContainedAutoTypeLoc(),
+ DeducedType);
+ if (ConstraintsResult != DAR_Succeeded)
+ return ConstraintsResult;
+ }
+ }
+
Result = SubstituteDeducedTypeTransform(*this, DeducedType).Apply(Type);
if (Result.isNull())
return DAR_FailedAlreadyDiagnosed;
@@ -4632,8 +4782,11 @@ bool Sema::DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
// 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->getReturnType()->isUndeducedType()) {
+ runWithSufficientStackSpace(Loc, [&] {
+ InstantiateFunctionDefinition(Loc, CallOp);
+ });
+ }
}
if (CallOp->isInvalidDecl())
@@ -4654,8 +4807,11 @@ bool Sema::DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
return false;
}
- if (FD->getTemplateInstantiationPattern())
- InstantiateFunctionDefinition(Loc, FD);
+ if (FD->getTemplateInstantiationPattern()) {
+ runWithSufficientStackSpace(Loc, [&] {
+ InstantiateFunctionDefinition(Loc, FD);
+ });
+ }
bool StillUndeduced = FD->getReturnType()->isUndeducedType();
if (StillUndeduced && Diagnose && !FD->isInvalidDecl()) {
@@ -4884,6 +5040,21 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
TemplatePartialOrderingContext TPOC,
unsigned NumCallArguments1,
unsigned NumCallArguments2) {
+
+ auto JudgeByConstraints = [&] () -> FunctionTemplateDecl * {
+ llvm::SmallVector<const Expr *, 3> AC1, AC2;
+ FT1->getAssociatedConstraints(AC1);
+ FT2->getAssociatedConstraints(AC2);
+ bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+ if (IsAtLeastAsConstrained(FT1, AC1, FT2, AC2, AtLeastAsConstrained1))
+ return nullptr;
+ if (IsAtLeastAsConstrained(FT2, AC2, FT1, AC1, AtLeastAsConstrained2))
+ return nullptr;
+ if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+ return nullptr;
+ return AtLeastAsConstrained1 ? FT1 : FT2;
+ };
+
bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC,
NumCallArguments1);
bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC,
@@ -4893,7 +5064,7 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
return Better1 ? FT1 : FT2;
if (!Better1 && !Better2) // Neither is better than the other
- return nullptr;
+ return JudgeByConstraints();
// 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,
@@ -4903,7 +5074,7 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
if (Variadic1 != Variadic2)
return Variadic1? FT2 : FT1;
- return nullptr;
+ return JudgeByConstraints();
}
/// Determine if the two templates are equivalent.
@@ -5098,8 +5269,21 @@ Sema::getMoreSpecializedPartialSpecialization(
bool Better1 = isAtLeastAsSpecializedAs(*this, PT1, PT2, PS2, Info);
bool Better2 = isAtLeastAsSpecializedAs(*this, PT2, PT1, PS1, Info);
- if (Better1 == Better2)
- return nullptr;
+ if (!Better1 && !Better2)
+ return nullptr;
+ if (Better1 && Better2) {
+ llvm::SmallVector<const Expr *, 3> AC1, AC2;
+ PS1->getAssociatedConstraints(AC1);
+ PS2->getAssociatedConstraints(AC2);
+ bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+ if (IsAtLeastAsConstrained(PS1, AC1, PS2, AC2, AtLeastAsConstrained1))
+ return nullptr;
+ if (IsAtLeastAsConstrained(PS2, AC2, PS1, AC1, AtLeastAsConstrained2))
+ return nullptr;
+ if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+ return nullptr;
+ return AtLeastAsConstrained1 ? PS1 : PS2;
+ }
return Better1 ? PS1 : PS2;
}
@@ -5111,11 +5295,22 @@ bool Sema::isMoreSpecializedThanPrimary(
QualType PartialT = Spec->getInjectedSpecializationType();
if (!isAtLeastAsSpecializedAs(*this, PartialT, PrimaryT, Primary, Info))
return false;
- if (isAtLeastAsSpecializedAs(*this, PrimaryT, PartialT, Spec, Info)) {
- Info.clearSFINAEDiagnostic();
+ if (!isAtLeastAsSpecializedAs(*this, PrimaryT, PartialT, Spec, Info))
+ return true;
+ Info.clearSFINAEDiagnostic();
+ llvm::SmallVector<const Expr *, 3> PrimaryAC, SpecAC;
+ Primary->getAssociatedConstraints(PrimaryAC);
+ Spec->getAssociatedConstraints(SpecAC);
+ bool AtLeastAsConstrainedPrimary, AtLeastAsConstrainedSpec;
+ if (IsAtLeastAsConstrained(Spec, SpecAC, Primary, PrimaryAC,
+ AtLeastAsConstrainedSpec))
return false;
- }
- return true;
+ if (!AtLeastAsConstrainedSpec)
+ return false;
+ if (IsAtLeastAsConstrained(Primary, PrimaryAC, Spec, SpecAC,
+ AtLeastAsConstrainedPrimary))
+ return false;
+ return !AtLeastAsConstrainedPrimary;
}
VarTemplatePartialSpecializationDecl *
@@ -5138,8 +5333,21 @@ Sema::getMoreSpecializedPartialSpecialization(
bool Better1 = isAtLeastAsSpecializedAs(*this, PT1, PT2, PS2, Info);
bool Better2 = isAtLeastAsSpecializedAs(*this, PT2, PT1, PS1, Info);
- if (Better1 == Better2)
+ if (!Better1 && !Better2)
return nullptr;
+ if (Better1 && Better2) {
+ llvm::SmallVector<const Expr *, 3> AC1, AC2;
+ PS1->getAssociatedConstraints(AC1);
+ PS2->getAssociatedConstraints(AC2);
+ bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+ if (IsAtLeastAsConstrained(PS1, AC1, PS2, AC2, AtLeastAsConstrained1))
+ return nullptr;
+ if (IsAtLeastAsConstrained(PS2, AC2, PS1, AC1, AtLeastAsConstrained2))
+ return nullptr;
+ if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+ return nullptr;
+ return AtLeastAsConstrained1 ? PS1 : PS2;
+ }
return Better1 ? PS1 : PS2;
}
@@ -5159,13 +5367,25 @@ bool Sema::isMoreSpecializedThanPrimary(
CanonTemplate, PrimaryArgs);
QualType PartialT = Context.getTemplateSpecializationType(
CanonTemplate, Spec->getTemplateArgs().asArray());
+
if (!isAtLeastAsSpecializedAs(*this, PartialT, PrimaryT, Primary, Info))
return false;
- if (isAtLeastAsSpecializedAs(*this, PrimaryT, PartialT, Spec, Info)) {
- Info.clearSFINAEDiagnostic();
+ if (!isAtLeastAsSpecializedAs(*this, PrimaryT, PartialT, Spec, Info))
+ return true;
+ Info.clearSFINAEDiagnostic();
+ llvm::SmallVector<const Expr *, 3> PrimaryAC, SpecAC;
+ Primary->getAssociatedConstraints(PrimaryAC);
+ Spec->getAssociatedConstraints(SpecAC);
+ bool AtLeastAsConstrainedPrimary, AtLeastAsConstrainedSpec;
+ if (IsAtLeastAsConstrained(Spec, SpecAC, Primary, PrimaryAC,
+ AtLeastAsConstrainedSpec))
+ return false;
+ if (!AtLeastAsConstrainedSpec)
return false;
- }
- return true;
+ if (IsAtLeastAsConstrained(Primary, PrimaryAC, Spec, SpecAC,
+ AtLeastAsConstrainedPrimary))
+ return false;
+ return !AtLeastAsConstrainedPrimary;
}
bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
@@ -5199,7 +5419,8 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
SFINAETrap Trap(*this);
Context.getInjectedTemplateArgs(P, PArgs);
- TemplateArgumentListInfo PArgList(P->getLAngleLoc(), P->getRAngleLoc());
+ TemplateArgumentListInfo PArgList(P->getLAngleLoc(),
+ P->getRAngleLoc());
for (unsigned I = 0, N = P->size(); I != N; ++I) {
// Unwrap packs that getInjectedTemplateArgs wrapped around pack
// expansions, to form an "as written" argument list.
@@ -5231,6 +5452,41 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
return isAtLeastAsSpecializedAs(*this, PType, AType, AArg, Info);
}
+namespace {
+struct MarkUsedTemplateParameterVisitor :
+ RecursiveASTVisitor<MarkUsedTemplateParameterVisitor> {
+ llvm::SmallBitVector &Used;
+ unsigned Depth;
+
+ MarkUsedTemplateParameterVisitor(llvm::SmallBitVector &Used,
+ unsigned Depth)
+ : Used(Used), Depth(Depth) { }
+
+ bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
+ if (T->getDepth() == Depth)
+ Used[T->getIndex()] = true;
+ return true;
+ }
+
+ bool TraverseTemplateName(TemplateName Template) {
+ if (auto *TTP =
+ dyn_cast<TemplateTemplateParmDecl>(Template.getAsTemplateDecl()))
+ if (TTP->getDepth() == Depth)
+ Used[TTP->getIndex()] = true;
+ RecursiveASTVisitor<MarkUsedTemplateParameterVisitor>::
+ TraverseTemplateName(Template);
+ return true;
+ }
+
+ bool VisitDeclRefExpr(DeclRefExpr *E) {
+ if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(E->getDecl()))
+ if (NTTP->getDepth() == Depth)
+ Used[NTTP->getIndex()] = true;
+ return true;
+ }
+};
+}
+
/// Mark the template parameters that are used by the given
/// expression.
static void
@@ -5239,6 +5495,12 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
bool OnlyDeduced,
unsigned Depth,
llvm::SmallBitVector &Used) {
+ if (!OnlyDeduced) {
+ MarkUsedTemplateParameterVisitor(Used, Depth)
+ .TraverseStmt(const_cast<Expr *>(E));
+ return;
+ }
+
// We can deduce from a pack expansion.
if (const PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(E))
E = Expansion->getPattern();
@@ -5257,8 +5519,6 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
break;
}
- // 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)
return;
@@ -5590,7 +5850,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
#define ABSTRACT_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base)
#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
-#include "clang/AST/TypeNodes.def"
+#include "clang/AST/TypeNodes.inc"
break;
}
}
@@ -5638,6 +5898,20 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
}
}
+/// Mark which template parameters are used in a given expression.
+///
+/// \param E the expression from which template parameters will be deduced.
+///
+/// \param Used a bit vector whose elements will be set to \c true
+/// to indicate when the corresponding template parameter will be
+/// deduced.
+void
+Sema::MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced,
+ unsigned Depth,
+ llvm::SmallBitVector &Used) {
+ ::MarkUsedTemplateParameters(Context, E, OnlyDeduced, Depth, Used);
+}
+
/// Mark which template parameters can be deduced from a given
/// template argument list.
///