diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaTemplateDeduction.cpp')
| -rw-r--r-- | contrib/llvm-project/clang/lib/Sema/SemaTemplateDeduction.cpp | 440 |
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. /// |
