https://github.com/cor3ntin created https://github.com/llvm/llvm-project/pull/135993
Reverts llvm/llvm-project#133426 This is failing on some bots https://lab.llvm.org/buildbot/#/builders/163/builds/17265 >From 2586e26ebaaf967c441651a736b740bc2113ecc1 Mon Sep 17 00:00:00 2001 From: cor3ntin <corentinja...@gmail.com> Date: Wed, 16 Apr 2025 19:39:15 +0200 Subject: [PATCH] =?UTF-8?q?Revert=20"[Clang][RFC]=20Bypass=20TAD=20during?= =?UTF-8?q?=20overload=20resolution=20if=20a=20perfect=20match=E2=80=A6"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit facc57fc25d0f05f5834fed421662dbad3ec5b50. --- clang/docs/ReleaseNotes.rst | 6 - clang/include/clang/Sema/Overload.h | 224 +------- clang/lib/Sema/SemaCodeComplete.cpp | 6 +- clang/lib/Sema/SemaInit.cpp | 15 +- clang/lib/Sema/SemaOverload.cpp | 522 ++++-------------- clang/lib/Sema/SemaTemplateDeduction.cpp | 4 +- .../constrant-satisfaction-conversions.cpp | 8 +- clang/test/SemaCUDA/function-overload.cu | 3 + .../SemaCXX/implicit-member-functions.cpp | 21 +- ...overload-resolution-deferred-templates.cpp | 185 ------- .../instantiate-function-params.cpp | 7 +- .../Templight/templight-empty-entries-fix.cpp | 126 +++-- 12 files changed, 217 insertions(+), 910 deletions(-) delete mode 100644 clang/test/SemaCXX/overload-resolution-deferred-templates.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index acbc9c5a6fac9..0891fd058bb57 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -96,12 +96,6 @@ C++ Language Changes asm((std::string_view("nop")) ::: (std::string_view("memory"))); } -- Clang now implements the changes to overload resolution proposed by section 1 and 2 of - `P3606 <https://wg21.link/P3606R0>`_. If a non-template candidate exists in an overload set that is - a perfect match (all conversion sequences are identity conversions) template candiates are not instantiated. - Diagnostics that would have resulted from the instantiation of these template candidates are no longer - produced. This aligns Clang closer to the behavior of GCC, and fixes (#GH62096), (#GH74581), and (#GH74581). - C++2c Feature Support ^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index 813811af06e89..6e08762dcc6d7 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -407,24 +407,6 @@ class Sema; Third == ICK_Identity; } - /// A conversion sequence is perfect if it is an identity conversion and - /// the type of the source is the same as the type of the target. - bool isPerfect(const ASTContext &C) const { - if (!isIdentityConversion()) - return false; - // If we are not performing a reference binding, we can skip comparing - // the types, which has a noticeable performance impact. - if (!ReferenceBinding) { - assert(First || C.hasSameUnqualifiedType(getFromType(), getToType(2))); - return true; - } - if (!C.hasSameType(getFromType(), getToType(2))) - return false; - if (BindsToRvalue && IsLvalueReference) - return false; - return true; - } - ImplicitConversionRank getRank() const; NarrowingKind getNarrowingKind(ASTContext &Context, const Expr *Converted, @@ -761,12 +743,6 @@ class Sema; Standard.setAllToTypes(T); } - /// A conversion sequence is perfect if it is an identity conversion and - /// the type of the source is the same as the type of the target. - bool isPerfect(const ASTContext &C) const { - return isStandard() && Standard.isPerfect(C); - } - // True iff this is a conversion sequence from an initializer list to an // array or std::initializer. bool hasInitializerListContainerType() const { @@ -1003,20 +979,6 @@ class Sema; return false; } - // An overload is a perfect match if the conversion - // sequences for each argument are perfect. - bool isPerfectMatch(const ASTContext &Ctx) const { - if (!Viable) - return false; - for (const auto &C : Conversions) { - if (!C.isInitialized() || !C.isPerfect(Ctx)) - return false; - } - if (isa_and_nonnull<CXXConversionDecl>(Function)) - return FinalConversion.isPerfect(Ctx); - return true; - } - bool TryToFixBadConversion(unsigned Idx, Sema &S) { bool CanFix = Fix.tryToFixConversion( Conversions[Idx].Bad.FromExpr, @@ -1053,65 +1015,6 @@ class Sema; RewriteKind(CRK_None) {} }; - struct DeferredTemplateOverloadCandidate { - - // intrusive linked list support for allocateDeferredCandidate - DeferredTemplateOverloadCandidate *Next = nullptr; - - enum Kind { Function, Method, Conversion }; - - LLVM_PREFERRED_TYPE(Kind) - unsigned Kind : 2; - LLVM_PREFERRED_TYPE(bool) - unsigned AllowObjCConversionOnExplicit : 1; - LLVM_PREFERRED_TYPE(bool) - unsigned AllowResultConversion : 1; - LLVM_PREFERRED_TYPE(bool) - unsigned AllowExplicit : 1; - LLVM_PREFERRED_TYPE(bool) - unsigned SuppressUserConversions : 1; - LLVM_PREFERRED_TYPE(bool) - unsigned PartialOverloading : 1; - LLVM_PREFERRED_TYPE(bool) - unsigned AggregateCandidateDeduction : 1; - }; - - struct DeferredFunctionTemplateOverloadCandidate - : public DeferredTemplateOverloadCandidate { - FunctionTemplateDecl *FunctionTemplate; - DeclAccessPair FoundDecl; - ArrayRef<Expr *> Args; - CallExpr::ADLCallKind IsADLCandidate; - OverloadCandidateParamOrder PO; - }; - static_assert(std::is_trivially_destructible_v< - DeferredFunctionTemplateOverloadCandidate>); - - struct DeferredMethodTemplateOverloadCandidate - : public DeferredTemplateOverloadCandidate { - FunctionTemplateDecl *FunctionTemplate; - DeclAccessPair FoundDecl; - ArrayRef<Expr *> Args; - CXXRecordDecl *ActingContext; - Expr::Classification ObjectClassification; - QualType ObjectType; - OverloadCandidateParamOrder PO; - }; - static_assert(std::is_trivially_destructible_v< - DeferredMethodTemplateOverloadCandidate>); - - struct DeferredConversionTemplateOverloadCandidate - : public DeferredTemplateOverloadCandidate { - FunctionTemplateDecl *FunctionTemplate; - DeclAccessPair FoundDecl; - CXXRecordDecl *ActingContext; - Expr *From; - QualType ToType; - }; - - static_assert(std::is_trivially_destructible_v< - DeferredConversionTemplateOverloadCandidate>); - /// OverloadCandidateSet - A set of overload candidates, used in C++ /// overload resolution (C++ 13.3). class OverloadCandidateSet { @@ -1140,11 +1043,6 @@ class Sema; /// C++ [over.match.call.general] /// Resolve a call through the address of an overload set. CSK_AddressOfOverloadSet, - - /// When doing overload resolution during code completion, - /// we want to show all viable candidates, including otherwise - /// deferred template candidates. - CSK_CodeCompletion, }; /// Information about operator rewrites to consider when adding operator @@ -1219,15 +1117,7 @@ class Sema; SmallVector<OverloadCandidate, 16> Candidates; llvm::SmallPtrSet<uintptr_t, 16> Functions; - DeferredTemplateOverloadCandidate *FirstDeferredCandidate = nullptr; - unsigned DeferredCandidatesCount : 8 * sizeof(unsigned) - 2; - LLVM_PREFERRED_TYPE(bool) - unsigned HasDeferredTemplateConstructors : 1; - LLVM_PREFERRED_TYPE(bool) - unsigned ResolutionByPerfectCandidateIsDisabled : 1; - - // Allocator for ConversionSequenceLists and deferred candidate args. - // We store the first few of these + // Allocator for ConversionSequenceLists. We store the first few of these // inline to avoid allocation for small sets. llvm::BumpPtrAllocator SlabAllocator; @@ -1235,11 +1125,8 @@ class Sema; CandidateSetKind Kind; OperatorRewriteInfo RewriteInfo; - /// Small storage size for ImplicitConversionSequences - /// and the persisted arguments of deferred candidates. constexpr static unsigned NumInlineBytes = - 32 * sizeof(ImplicitConversionSequence); - + 24 * sizeof(ImplicitConversionSequence); unsigned NumInlineBytesUsed = 0; alignas(void *) char InlineSpace[NumInlineBytes]; @@ -1250,13 +1137,15 @@ class Sema; /// from the slab allocator. /// FIXME: It would probably be nice to have a SmallBumpPtrAllocator /// instead. + /// FIXME: Now that this only allocates ImplicitConversionSequences, do we + /// want to un-generalize this? template <typename T> T *slabAllocate(unsigned N) { // It's simpler if this doesn't need to consider alignment. static_assert(alignof(T) == alignof(void *), "Only works for pointer-aligned types."); - static_assert(std::is_trivially_destructible_v<T> || - (std::is_same_v<ImplicitConversionSequence, T>), + static_assert(std::is_trivial<T>::value || + std::is_same<ImplicitConversionSequence, T>::value, "Add destruction logic to OverloadCandidateSet::clear()."); unsigned NBytes = sizeof(T) * N; @@ -1270,34 +1159,12 @@ class Sema; return reinterpret_cast<T *>(FreeSpaceStart); } - // Because the size of OverloadCandidateSet has a noticeable impact on - // performance, we store each deferred template candidate in the slab - // allocator such that deferred candidates are ultimately a singly-linked - // intrusive linked list. This ends up being much more efficient than a - // SmallVector that is empty in the common case. - template <typename T> T *allocateDeferredCandidate() { - T *C = slabAllocate<T>(1); - if (!FirstDeferredCandidate) - FirstDeferredCandidate = C; - else { - auto *F = FirstDeferredCandidate; - while (F->Next) - F = F->Next; - F->Next = C; - } - DeferredCandidatesCount++; - return C; - } - void destroyCandidates(); public: OverloadCandidateSet(SourceLocation Loc, CandidateSetKind CSK, OperatorRewriteInfo RewriteInfo = {}) - : FirstDeferredCandidate(nullptr), DeferredCandidatesCount(0), - HasDeferredTemplateConstructors(false), - ResolutionByPerfectCandidateIsDisabled(false), Loc(Loc), Kind(CSK), - RewriteInfo(RewriteInfo) {} + : Loc(Loc), Kind(CSK), RewriteInfo(RewriteInfo) {} OverloadCandidateSet(const OverloadCandidateSet &) = delete; OverloadCandidateSet &operator=(const OverloadCandidateSet &) = delete; ~OverloadCandidateSet() { destroyCandidates(); } @@ -1309,9 +1176,6 @@ class Sema; /// Whether diagnostics should be deferred. bool shouldDeferDiags(Sema &S, ArrayRef<Expr *> Args, SourceLocation OpLoc); - // Whether the resolution of template candidates should be deferred - bool shouldDeferTemplateArgumentDeduction(const LangOptions &Opts) const; - /// Determine when this overload candidate will be new to the /// overload set. bool isNewCandidate(Decl *F, OverloadCandidateParamOrder PO = @@ -1335,10 +1199,8 @@ class Sema; iterator begin() { return Candidates.begin(); } iterator end() { return Candidates.end(); } - size_t size() const { return Candidates.size() + DeferredCandidatesCount; } - bool empty() const { - return Candidates.empty() && DeferredCandidatesCount == 0; - } + size_t size() const { return Candidates.size(); } + bool empty() const { return Candidates.empty(); } /// Allocate storage for conversion sequences for NumConversions /// conversions. @@ -1354,24 +1216,6 @@ class Sema; return ConversionSequenceList(Conversions, NumConversions); } - /// Provide storage for any Expr* arg that must be preserved - /// until deferred template candidates are deduced. - /// Typically this should be used for reversed operator arguments - /// and any time the argument array is transformed while adding - /// a template candidate. - llvm::MutableArrayRef<Expr *> getPersistentArgsArray(unsigned N) { - Expr **Exprs = slabAllocate<Expr *>(N); - return llvm::MutableArrayRef<Expr *>(Exprs, N); - } - - template <typename... T> - llvm::MutableArrayRef<Expr *> getPersistentArgsArray(T *...Exprs) { - llvm::MutableArrayRef<Expr *> Arr = - getPersistentArgsArray(sizeof...(Exprs)); - llvm::copy(std::initializer_list<Expr *>{Exprs...}, Arr.data()); - return Arr; - } - /// Add a new candidate with NumConversions conversion sequence slots /// to the overload set. OverloadCandidate &addCandidate(unsigned NumConversions = 0, @@ -1387,32 +1231,6 @@ class Sema; return C; } - void AddDeferredTemplateCandidate( - FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, - ArrayRef<Expr *> Args, bool SuppressUserConversions, - bool PartialOverloading, bool AllowExplicit, - CallExpr::ADLCallKind IsADLCandidate, OverloadCandidateParamOrder PO, - bool AggregateCandidateDeduction); - - void AddDeferredMethodTemplateCandidate( - FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl, - CXXRecordDecl *ActingContext, QualType ObjectType, - Expr::Classification ObjectClassification, ArrayRef<Expr *> Args, - bool SuppressUserConversions, bool PartialOverloading, - OverloadCandidateParamOrder PO); - - void AddDeferredConversionTemplateCandidate( - FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, - CXXRecordDecl *ActingContext, Expr *From, QualType ToType, - bool AllowObjCConversionOnExplicit, bool AllowExplicit, - bool AllowResultConversion); - - void InjectNonDeducedTemplateCandidates(Sema &S); - - void DisableResolutionByPerfectCandidate() { - ResolutionByPerfectCandidateIsDisabled = true; - } - /// Find the best viable function on this overload set, if it exists. OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc, OverloadCandidateSet::iterator& Best); @@ -1445,15 +1263,6 @@ class Sema; DestAS = AS; } - private: - OverloadingResult ResultForBestCandidate(const iterator &Best); - void CudaExcludeWrongSideCandidates( - Sema &S, SmallVectorImpl<OverloadCandidate *> &Candidates); - OverloadingResult - BestViableFunctionImpl(Sema &S, SourceLocation Loc, - OverloadCandidateSet::iterator &Best); - void PerfectViableFunction(Sema &S, SourceLocation Loc, - OverloadCandidateSet::iterator &Best); }; bool isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1, @@ -1502,21 +1311,6 @@ class Sema; // parameter. bool shouldEnforceArgLimit(bool PartialOverloading, FunctionDecl *Function); - inline bool OverloadCandidateSet::shouldDeferTemplateArgumentDeduction( - const LangOptions &Opts) const { - return - // For user defined conversion we need to check against different - // combination of CV qualifiers and look at any explicit specifier, so - // always deduce template candidates. - Kind != CSK_InitByUserDefinedConversion - // When doing code completion, we want to see all the - // viable candidates. - && Kind != CSK_CodeCompletion - // CUDA may prefer template candidates even when a non-candidate - // is a perfect match - && !Opts.CUDA; - } - } // namespace clang #endif // LLVM_CLANG_SEMA_OVERLOAD_H diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 45405d4709e14..f6ec4cb0f069e 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -6354,8 +6354,7 @@ SemaCodeCompletion::ProduceCallSignatureHelp(Expr *Fn, ArrayRef<Expr *> Args, Expr *NakedFn = Fn->IgnoreParenCasts(); // Build an overload candidate set based on the functions we find. SourceLocation Loc = Fn->getExprLoc(); - OverloadCandidateSet CandidateSet(Loc, - OverloadCandidateSet::CSK_CodeCompletion); + OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) { SemaRef.AddOverloadedCallCandidates(ULE, ArgsWithoutDependentTypes, @@ -6558,8 +6557,7 @@ QualType SemaCodeCompletion::ProduceConstructorSignatureHelp( // FIXME: Provide support for variadic template constructors. if (CRD) { - OverloadCandidateSet CandidateSet(Loc, - OverloadCandidateSet::CSK_CodeCompletion); + OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); for (NamedDecl *C : SemaRef.LookupConstructors(CRD)) { if (auto *FD = dyn_cast<FunctionDecl>(C)) { // FIXME: we can't yet provide correct signature help for initializer diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 82489847b589b..a1e4bb4321d53 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -10029,19 +10029,12 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( // When [...] the constructor [...] is a candidate by // - [over.match.copy] (in all cases) if (TD) { - - // As template candidates are not deduced immediately, - // persist the array in the overload set. - MutableArrayRef<Expr *> TmpInits = - Candidates.getPersistentArgsArray(Inits.size()); - - for (auto [I, E] : llvm::enumerate(Inits)) { + SmallVector<Expr *, 8> TmpInits; + for (Expr *E : Inits) if (auto *DI = dyn_cast<DesignatedInitExpr>(E)) - TmpInits[I] = DI->getInit(); + TmpInits.push_back(DI->getInit()); else - TmpInits[I] = E; - } - + TmpInits.push_back(E); AddTemplateOverloadCandidate( TD, FoundDecl, /*ExplicitArgs=*/nullptr, TmpInits, Candidates, /*SuppressUserConversions=*/false, diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index deef01c946feb..55634aa75ae25 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1123,10 +1123,6 @@ void OverloadCandidateSet::clear(CandidateSetKind CSK) { Candidates.clear(); Functions.clear(); Kind = CSK; - FirstDeferredCandidate = nullptr; - DeferredCandidatesCount = 0; - HasDeferredTemplateConstructors = false; - ResolutionByPerfectCandidateIsDisabled = false; } namespace { @@ -7799,14 +7795,15 @@ void Sema::AddMethodCandidate( } } -static void AddMethodTemplateCandidateImmediately( - Sema &S, OverloadCandidateSet &CandidateSet, +void Sema::AddMethodTemplateCandidate( FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType, Expr::Classification ObjectClassification, ArrayRef<Expr *> Args, - bool SuppressUserConversions, bool PartialOverloading, - OverloadCandidateParamOrder PO) { + OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, + bool PartialOverloading, OverloadCandidateParamOrder PO) { + if (!CandidateSet.isNewCandidate(MethodTmpl, PO)) + return; // C++ [over.match.funcs]p7: // In each case where a candidate is a function template, candidate @@ -7820,12 +7817,12 @@ static void AddMethodTemplateCandidateImmediately( TemplateDeductionInfo Info(CandidateSet.getLocation()); FunctionDecl *Specialization = nullptr; ConversionSequenceList Conversions; - if (TemplateDeductionResult Result = S.DeduceTemplateArguments( + if (TemplateDeductionResult Result = DeduceTemplateArguments( MethodTmpl, ExplicitTemplateArgs, Args, Specialization, Info, PartialOverloading, /*AggregateDeductionCandidate=*/false, /*PartialOrdering=*/false, ObjectType, ObjectClassification, [&](ArrayRef<QualType> ParamTypes) { - return S.CheckNonDependentConversions( + return CheckNonDependentConversions( MethodTmpl, ParamTypes, Args, CandidateSet, Conversions, SuppressUserConversions, ActingContext, ObjectType, ObjectClassification, PO); @@ -7847,8 +7844,8 @@ static void AddMethodTemplateCandidateImmediately( Candidate.FailureKind = ovl_fail_bad_conversion; else { Candidate.FailureKind = ovl_fail_bad_deduction; - Candidate.DeductionFailure = - MakeDeductionFailureInfo(S.Context, Result, Info); + Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, + Info); } return; } @@ -7858,34 +7855,10 @@ static void AddMethodTemplateCandidateImmediately( assert(Specialization && "Missing member function template specialization?"); assert(isa<CXXMethodDecl>(Specialization) && "Specialization is not a member function?"); - S.AddMethodCandidate( - cast<CXXMethodDecl>(Specialization), FoundDecl, ActingContext, ObjectType, - ObjectClassification, Args, CandidateSet, SuppressUserConversions, - PartialOverloading, Conversions, PO, Info.hasStrictPackMatch()); -} - -void Sema::AddMethodTemplateCandidate( - FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl, - CXXRecordDecl *ActingContext, - TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType, - Expr::Classification ObjectClassification, ArrayRef<Expr *> Args, - OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, - bool PartialOverloading, OverloadCandidateParamOrder PO) { - if (!CandidateSet.isNewCandidate(MethodTmpl, PO)) - return; - - if (ExplicitTemplateArgs || - !CandidateSet.shouldDeferTemplateArgumentDeduction(getLangOpts())) { - AddMethodTemplateCandidateImmediately( - *this, CandidateSet, MethodTmpl, FoundDecl, ActingContext, - ExplicitTemplateArgs, ObjectType, ObjectClassification, Args, - SuppressUserConversions, PartialOverloading, PO); - return; - } - - CandidateSet.AddDeferredMethodTemplateCandidate( - MethodTmpl, FoundDecl, ActingContext, ObjectType, ObjectClassification, - Args, SuppressUserConversions, PartialOverloading, PO); + AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl, + ActingContext, ObjectType, ObjectClassification, Args, + CandidateSet, SuppressUserConversions, PartialOverloading, + Conversions, PO, Info.hasStrictPackMatch()); } /// Determine whether a given function template has a simple explicit specifier @@ -7894,18 +7867,14 @@ static bool isNonDependentlyExplicit(FunctionTemplateDecl *FTD) { return ExplicitSpecifier::getFromDecl(FTD->getTemplatedDecl()).isExplicit(); } -static bool hasDependentExplicit(FunctionTemplateDecl *FTD) { - return ExplicitSpecifier::getFromDecl(FTD->getTemplatedDecl()).getKind() == - ExplicitSpecKind::Unresolved; -} - -static void AddTemplateOverloadCandidateImmediately( - Sema &S, OverloadCandidateSet &CandidateSet, +void Sema::AddTemplateOverloadCandidate( FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, - bool SuppressUserConversions, bool PartialOverloading, bool AllowExplicit, - Sema::ADLCallKind IsADLCandidate, OverloadCandidateParamOrder PO, - bool AggregateCandidateDeduction) { + OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, + bool PartialOverloading, bool AllowExplicit, ADLCallKind IsADLCandidate, + OverloadCandidateParamOrder PO, bool AggregateCandidateDeduction) { + if (!CandidateSet.isNewCandidate(FunctionTemplate, PO)) + return; // If the function template has a non-dependent explicit specification, // exclude it now if appropriate; we are not permitted to perform deduction @@ -7932,14 +7901,14 @@ static void AddTemplateOverloadCandidateImmediately( FunctionTemplate->getTemplateDepth()); FunctionDecl *Specialization = nullptr; ConversionSequenceList Conversions; - if (TemplateDeductionResult Result = S.DeduceTemplateArguments( + if (TemplateDeductionResult Result = DeduceTemplateArguments( FunctionTemplate, ExplicitTemplateArgs, Args, Specialization, Info, PartialOverloading, AggregateCandidateDeduction, /*PartialOrdering=*/false, /*ObjectType=*/QualType(), /*ObjectClassification=*/Expr::Classification(), [&](ArrayRef<QualType> ParamTypes) { - return S.CheckNonDependentConversions( + return CheckNonDependentConversions( FunctionTemplate, ParamTypes, Args, CandidateSet, Conversions, SuppressUserConversions, nullptr, QualType(), {}, PO); }); @@ -7963,8 +7932,8 @@ static void AddTemplateOverloadCandidateImmediately( Candidate.FailureKind = ovl_fail_bad_conversion; else { Candidate.FailureKind = ovl_fail_bad_deduction; - Candidate.DeductionFailure = - MakeDeductionFailureInfo(S.Context, Result, Info); + Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, + Info); } return; } @@ -7972,7 +7941,7 @@ static void AddTemplateOverloadCandidateImmediately( // Add the function template specialization produced by template argument // deduction as a candidate. assert(Specialization && "Missing function template specialization?"); - S.AddOverloadCandidate( + AddOverloadCandidate( Specialization, FoundDecl, Args, CandidateSet, SuppressUserConversions, PartialOverloading, AllowExplicit, /*AllowExplicitConversions=*/false, IsADLCandidate, Conversions, PO, @@ -7980,38 +7949,6 @@ static void AddTemplateOverloadCandidateImmediately( Info.hasStrictPackMatch()); } -void Sema::AddTemplateOverloadCandidate( - FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, - TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, - OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, - bool PartialOverloading, bool AllowExplicit, ADLCallKind IsADLCandidate, - OverloadCandidateParamOrder PO, bool AggregateCandidateDeduction) { - if (!CandidateSet.isNewCandidate(FunctionTemplate, PO)) - return; - - bool DependentExplicitSpecifier = hasDependentExplicit(FunctionTemplate); - - if (ExplicitTemplateArgs || - !CandidateSet.shouldDeferTemplateArgumentDeduction(getLangOpts()) || - (isa<CXXConstructorDecl>(FunctionTemplate->getTemplatedDecl()) && - DependentExplicitSpecifier)) { - - AddTemplateOverloadCandidateImmediately( - *this, CandidateSet, FunctionTemplate, FoundDecl, ExplicitTemplateArgs, - Args, SuppressUserConversions, PartialOverloading, AllowExplicit, - IsADLCandidate, PO, AggregateCandidateDeduction); - - if (DependentExplicitSpecifier) - CandidateSet.DisableResolutionByPerfectCandidate(); - return; - } - - CandidateSet.AddDeferredTemplateCandidate( - FunctionTemplate, FoundDecl, Args, SuppressUserConversions, - PartialOverloading, AllowExplicit, IsADLCandidate, PO, - AggregateCandidateDeduction); -} - bool Sema::CheckNonDependentConversions( FunctionTemplateDecl *FunctionTemplate, ArrayRef<QualType> ParamTypes, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, @@ -8327,12 +8264,16 @@ void Sema::AddConversionCandidate( } } -static void AddTemplateConversionCandidateImmediately( - Sema &S, OverloadCandidateSet &CandidateSet, +void Sema::AddTemplateConversionCandidate( FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, - CXXRecordDecl *ActingContext, Expr *From, QualType ToType, - bool AllowObjCConversionOnExplicit, bool AllowExplicit, - bool AllowResultConversion) { + CXXRecordDecl *ActingDC, Expr *From, QualType ToType, + OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit, + bool AllowExplicit, bool AllowResultConversion) { + assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) && + "Only conversion function templates permitted here"); + + if (!CandidateSet.isNewCandidate(FunctionTemplate)) + return; // If the function template has a non-dependent explicit specification, // exclude it now if appropriate; we are not permitted to perform deduction @@ -8347,11 +8288,11 @@ static void AddTemplateConversionCandidateImmediately( } QualType ObjectType = From->getType(); - Expr::Classification ObjectClassification = From->Classify(S.Context); + Expr::Classification ObjectClassification = From->Classify(getASTContext()); TemplateDeductionInfo Info(CandidateSet.getLocation()); CXXConversionDecl *Specialization = nullptr; - if (TemplateDeductionResult Result = S.DeduceTemplateArguments( + if (TemplateDeductionResult Result = DeduceTemplateArguments( FunctionTemplate, ObjectType, ObjectClassification, ToType, Specialization, Info); Result != TemplateDeductionResult::Success) { @@ -8361,47 +8302,18 @@ static void AddTemplateConversionCandidateImmediately( Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_deduction; Candidate.ExplicitCallArguments = 1; - Candidate.DeductionFailure = - MakeDeductionFailureInfo(S.Context, Result, Info); + Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, + Info); return; } // Add the conversion function template specialization produced by // template argument deduction as a candidate. assert(Specialization && "Missing function template specialization?"); - S.AddConversionCandidate(Specialization, FoundDecl, ActingContext, From, - ToType, CandidateSet, AllowObjCConversionOnExplicit, - AllowExplicit, AllowResultConversion, - Info.hasStrictPackMatch()); -} - -void Sema::AddTemplateConversionCandidate( - FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, - CXXRecordDecl *ActingDC, Expr *From, QualType ToType, - OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit, - bool AllowExplicit, bool AllowResultConversion) { - assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) && - "Only conversion function templates permitted here"); - - if (!CandidateSet.isNewCandidate(FunctionTemplate)) - return; - - if (!CandidateSet.shouldDeferTemplateArgumentDeduction(getLangOpts()) || - CandidateSet.getKind() == - OverloadCandidateSet::CSK_InitByUserDefinedConversion || - CandidateSet.getKind() == OverloadCandidateSet::CSK_InitByConstructor) { - AddTemplateConversionCandidateImmediately( - *this, CandidateSet, FunctionTemplate, FoundDecl, ActingDC, From, - ToType, AllowObjCConversionOnExplicit, AllowExplicit, - AllowResultConversion); - - CandidateSet.DisableResolutionByPerfectCandidate(); - return; - } - - CandidateSet.AddDeferredConversionTemplateCandidate( - FunctionTemplate, FoundDecl, ActingDC, From, ToType, - AllowObjCConversionOnExplicit, AllowExplicit, AllowResultConversion); + AddConversionCandidate(Specialization, FoundDecl, ActingDC, From, ToType, + CandidateSet, AllowObjCConversionOnExplicit, + AllowExplicit, AllowResultConversion, + Info.hasStrictPackMatch()); } void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, @@ -8551,17 +8463,11 @@ void Sema::AddNonMemberOperatorCandidates( if (FunTmpl) { AddTemplateOverloadCandidate(FunTmpl, F.getPair(), ExplicitTemplateArgs, FunctionArgs, CandidateSet); - if (CandidateSet.getRewriteInfo().shouldAddReversed(*this, Args, FD)) { - - // As template candidates are not deduced immediately, - // persist the array in the overload set. - ArrayRef<Expr *> Reversed = CandidateSet.getPersistentArgsArray( - FunctionArgs[1], FunctionArgs[0]); - AddTemplateOverloadCandidate(FunTmpl, F.getPair(), ExplicitTemplateArgs, - Reversed, CandidateSet, false, false, true, - ADLCallKind::NotADL, - OverloadCandidateParamOrder::Reversed); - } + if (CandidateSet.getRewriteInfo().shouldAddReversed(*this, Args, FD)) + AddTemplateOverloadCandidate( + FunTmpl, F.getPair(), ExplicitTemplateArgs, + {FunctionArgs[1], FunctionArgs[0]}, CandidateSet, false, false, + true, ADLCallKind::NotADL, OverloadCandidateParamOrder::Reversed); } else { if (ExplicitTemplateArgs) continue; @@ -10293,8 +10199,6 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, // FIXME: Pass in the explicit template arguments? ArgumentDependentLookup(Name, Loc, Args, Fns); - ArrayRef<Expr *> ReversedArgs; - // Erase all of the candidates we already knew about. for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), CandEnd = CandidateSet.end(); @@ -10334,15 +10238,9 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, /*AllowExplicit=*/true, ADLCallKind::UsesADL); if (CandidateSet.getRewriteInfo().shouldAddReversed( *this, Args, FTD->getTemplatedDecl())) { - - // As template candidates are not deduced immediately, - // persist the array in the overload set. - if (ReversedArgs.empty()) - ReversedArgs = CandidateSet.getPersistentArgsArray(Args[1], Args[0]); - AddTemplateOverloadCandidate( - FTD, FoundDecl, ExplicitTemplateArgs, ReversedArgs, CandidateSet, - /*SuppressUserConversions=*/false, PartialOverloading, + FTD, FoundDecl, ExplicitTemplateArgs, {Args[1], Args[0]}, + CandidateSet, /*SuppressUserConversions=*/false, PartialOverloading, /*AllowExplicit=*/true, ADLCallKind::UsesADL, OverloadCandidateParamOrder::Reversed); } @@ -11015,147 +10913,23 @@ bool OverloadCandidate::NotValidBecauseConstraintExprHasError() const { ->Satisfaction.ContainsErrors; } -void OverloadCandidateSet::AddDeferredTemplateCandidate( - FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, - ArrayRef<Expr *> Args, bool SuppressUserConversions, - bool PartialOverloading, bool AllowExplicit, - CallExpr::ADLCallKind IsADLCandidate, OverloadCandidateParamOrder PO, - bool AggregateCandidateDeduction) { - - auto *C = - allocateDeferredCandidate<DeferredFunctionTemplateOverloadCandidate>(); - - C = new (C) DeferredFunctionTemplateOverloadCandidate{ - {nullptr, DeferredFunctionTemplateOverloadCandidate::Function, - /*AllowObjCConversionOnExplicit=*/false, - /*AllowResultConversion=*/false, AllowExplicit, SuppressUserConversions, - PartialOverloading, AggregateCandidateDeduction}, - FunctionTemplate, - FoundDecl, - Args, - IsADLCandidate, - PO}; - - HasDeferredTemplateConstructors |= - isa<CXXConstructorDecl>(FunctionTemplate->getTemplatedDecl()); -} - -void OverloadCandidateSet::AddDeferredMethodTemplateCandidate( - FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl, - CXXRecordDecl *ActingContext, QualType ObjectType, - Expr::Classification ObjectClassification, ArrayRef<Expr *> Args, - bool SuppressUserConversions, bool PartialOverloading, - OverloadCandidateParamOrder PO) { - - assert(!isa<CXXConstructorDecl>(MethodTmpl->getTemplatedDecl())); - - auto *C = - allocateDeferredCandidate<DeferredMethodTemplateOverloadCandidate>(); - - C = new (C) DeferredMethodTemplateOverloadCandidate{ - {nullptr, DeferredFunctionTemplateOverloadCandidate::Method, - /*AllowObjCConversionOnExplicit=*/false, - /*AllowResultConversion=*/false, - /*AllowExplicit=*/false, SuppressUserConversions, PartialOverloading, - /*AggregateCandidateDeduction=*/false}, - MethodTmpl, - FoundDecl, - Args, - ActingContext, - ObjectClassification, - ObjectType, - PO}; -} - -void OverloadCandidateSet::AddDeferredConversionTemplateCandidate( - FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, - CXXRecordDecl *ActingContext, Expr *From, QualType ToType, - bool AllowObjCConversionOnExplicit, bool AllowExplicit, - bool AllowResultConversion) { - - auto *C = - allocateDeferredCandidate<DeferredConversionTemplateOverloadCandidate>(); - - C = new (C) DeferredConversionTemplateOverloadCandidate{ - {nullptr, DeferredFunctionTemplateOverloadCandidate::Conversion, - AllowObjCConversionOnExplicit, AllowResultConversion, - /*AllowExplicit=*/false, - /*SuppressUserConversions=*/false, - /*PartialOverloading*/ false, - /*AggregateCandidateDeduction=*/false}, - FunctionTemplate, - FoundDecl, - ActingContext, - From, - ToType}; -} - -static void -AddTemplateOverloadCandidate(Sema &S, OverloadCandidateSet &CandidateSet, - DeferredMethodTemplateOverloadCandidate &C) { - - AddMethodTemplateCandidateImmediately( - S, CandidateSet, C.FunctionTemplate, C.FoundDecl, C.ActingContext, - /*ExplicitTemplateArgs=*/nullptr, C.ObjectType, C.ObjectClassification, - C.Args, C.SuppressUserConversions, C.PartialOverloading, C.PO); -} - -static void -AddTemplateOverloadCandidate(Sema &S, OverloadCandidateSet &CandidateSet, - DeferredFunctionTemplateOverloadCandidate &C) { - AddTemplateOverloadCandidateImmediately( - S, CandidateSet, C.FunctionTemplate, C.FoundDecl, - /*ExplicitTemplateArgs=*/nullptr, C.Args, C.SuppressUserConversions, - C.PartialOverloading, C.AllowExplicit, C.IsADLCandidate, C.PO, - C.AggregateCandidateDeduction); -} - -static void -AddTemplateOverloadCandidate(Sema &S, OverloadCandidateSet &CandidateSet, - DeferredConversionTemplateOverloadCandidate &C) { - return AddTemplateConversionCandidateImmediately( - S, CandidateSet, C.FunctionTemplate, C.FoundDecl, C.ActingContext, C.From, - C.ToType, C.AllowObjCConversionOnExplicit, C.AllowExplicit, - C.AllowResultConversion); -} - -void OverloadCandidateSet::InjectNonDeducedTemplateCandidates(Sema &S) { - Candidates.reserve(Candidates.size() + DeferredCandidatesCount); - DeferredTemplateOverloadCandidate *Cand = FirstDeferredCandidate; - while (Cand) { - switch (Cand->Kind) { - case DeferredTemplateOverloadCandidate::Function: - AddTemplateOverloadCandidate( - S, *this, - *static_cast<DeferredFunctionTemplateOverloadCandidate *>(Cand)); - break; - case DeferredTemplateOverloadCandidate::Method: - AddTemplateOverloadCandidate( - S, *this, - *static_cast<DeferredMethodTemplateOverloadCandidate *>(Cand)); - break; - case DeferredTemplateOverloadCandidate::Conversion: - AddTemplateOverloadCandidate( - S, *this, - *static_cast<DeferredConversionTemplateOverloadCandidate *>(Cand)); - break; - } - Cand = Cand->Next; - } - FirstDeferredCandidate = nullptr; - DeferredCandidatesCount = 0; -} - +/// Computes the best viable function (C++ 13.3.3) +/// within an overload candidate set. +/// +/// \param Loc The location of the function name (or operator symbol) for +/// which overload resolution occurs. +/// +/// \param Best If overload resolution was successful or found a deleted +/// function, \p Best points to the candidate function found. +/// +/// \returns The result of overload resolution. OverloadingResult -OverloadCandidateSet::ResultForBestCandidate(const iterator &Best) { - Best->Best = true; - if (Best->Function && Best->Function->isDeleted()) - return OR_Deleted; - return OR_Success; -} +OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc, + iterator &Best) { + llvm::SmallVector<OverloadCandidate *, 16> Candidates; + std::transform(begin(), end(), std::back_inserter(Candidates), + [](OverloadCandidate &Cand) { return &Cand; }); -void OverloadCandidateSet::CudaExcludeWrongSideCandidates( - Sema &S, SmallVectorImpl<OverloadCandidate *> &Candidates) { // [CUDA] HD->H or HD->D calls are technically not allowed by CUDA but // are accepted by both clang and NVCC. However, during a particular // compilation mode only one call variant is viable. We need to @@ -11167,112 +10941,27 @@ void OverloadCandidateSet::CudaExcludeWrongSideCandidates( // -fgpu-exclude-wrong-side-overloads is off. When // -fgpu-exclude-wrong-side-overloads is on, all candidates are compared // uniformly in isBetterOverloadCandidate. - if (!S.getLangOpts().CUDA || S.getLangOpts().GPUExcludeWrongSideOverloads) - return; - const FunctionDecl *Caller = S.getCurFunctionDecl(/*AllowLambda=*/true); - - bool ContainsSameSideCandidate = - llvm::any_of(Candidates, [&](const OverloadCandidate *Cand) { - // Check viable function only. + if (S.getLangOpts().CUDA && !S.getLangOpts().GPUExcludeWrongSideOverloads) { + const FunctionDecl *Caller = S.getCurFunctionDecl(/*AllowLambda=*/true); + bool ContainsSameSideCandidate = + llvm::any_of(Candidates, [&](OverloadCandidate *Cand) { + // Check viable function only. + return Cand->Viable && Cand->Function && + S.CUDA().IdentifyPreference(Caller, Cand->Function) == + SemaCUDA::CFP_SameSide; + }); + if (ContainsSameSideCandidate) { + auto IsWrongSideCandidate = [&](OverloadCandidate *Cand) { + // Check viable function only to avoid unnecessary data copying/moving. return Cand->Viable && Cand->Function && S.CUDA().IdentifyPreference(Caller, Cand->Function) == - SemaCUDA::CFP_SameSide; - }); - - if (!ContainsSameSideCandidate) - return; - - auto IsWrongSideCandidate = [&](const OverloadCandidate *Cand) { - // Check viable function only to avoid unnecessary data copying/moving. - return Cand->Viable && Cand->Function && - S.CUDA().IdentifyPreference(Caller, Cand->Function) == - SemaCUDA::CFP_WrongSide; - }; - llvm::erase_if(Candidates, IsWrongSideCandidate); -} - -/// Computes the best viable function (C++ 13.3.3) -/// within an overload candidate set. -/// -/// \param Loc The location of the function name (or operator symbol) for -/// which overload resolution occurs. -/// -/// \param Best If overload resolution was successful or found a deleted -/// function, \p Best points to the candidate function found. -/// -/// \returns The result of overload resolution. -OverloadingResult OverloadCandidateSet::BestViableFunction(Sema &S, - SourceLocation Loc, - iterator &Best) { - - assert(shouldDeferTemplateArgumentDeduction(S.getLangOpts()) || - DeferredCandidatesCount == 0 && - "Unexpected deferred template candidates"); - - bool TwoPhaseResolution = - DeferredCandidatesCount != 0 && !ResolutionByPerfectCandidateIsDisabled; - - if (TwoPhaseResolution) { - - PerfectViableFunction(S, Loc, Best); - if (Best != end()) - return ResultForBestCandidate(Best); - } - - InjectNonDeducedTemplateCandidates(S); - return BestViableFunctionImpl(S, Loc, Best); -} - -void OverloadCandidateSet::PerfectViableFunction( - Sema &S, SourceLocation Loc, OverloadCandidateSet::iterator &Best) { - - Best = end(); - for (auto It = begin(); It != end(); ++It) { - - if (!It->isPerfectMatch(S.getASTContext())) - continue; - - // We found a suitable conversion function - // but if there is a template constructor in the target class - // we might prefer that instead. - if (HasDeferredTemplateConstructors && - isa_and_nonnull<CXXConversionDecl>(It->Function)) { - Best = end(); - break; - } - - if (Best == end()) { - Best = It; - continue; - } - if (Best->Function && It->Function) { - FunctionDecl *D = - S.getMoreConstrainedFunction(Best->Function, It->Function); - if (D == nullptr) { - Best = end(); - break; - } - if (D == It->Function) - Best = It; - continue; + SemaCUDA::CFP_WrongSide; + }; + llvm::erase_if(Candidates, IsWrongSideCandidate); } - // ambiguous - Best = end(); - break; } -} - -OverloadingResult OverloadCandidateSet::BestViableFunctionImpl( - Sema &S, SourceLocation Loc, OverloadCandidateSet::iterator &Best) { - - llvm::SmallVector<OverloadCandidate *, 16> Candidates; - Candidates.reserve(this->Candidates.size()); - std::transform(begin(), end(), std::back_inserter(Candidates), - [](OverloadCandidate &Cand) { return &Cand; }); - - if (S.getLangOpts().CUDA) - CudaExcludeWrongSideCandidates(S, Candidates); + // Find the best viable function. Best = end(); for (auto *Cand : Candidates) { Cand->Best = false; @@ -11294,8 +10983,9 @@ OverloadingResult OverloadCandidateSet::BestViableFunctionImpl( if (Best == end()) return OR_No_Viable_Function; - llvm::SmallVector<OverloadCandidate *, 4> PendingBest; llvm::SmallVector<const NamedDecl *, 4> EquivalentCands; + + llvm::SmallVector<OverloadCandidate*, 4> PendingBest; PendingBest.push_back(&*Best); Best->Best = true; @@ -11318,15 +11008,25 @@ OverloadingResult OverloadCandidateSet::BestViableFunctionImpl( } } + // If we found more than one best candidate, this is ambiguous. if (Best == end()) return OR_Ambiguous; - OverloadingResult R = ResultForBestCandidate(Best); + // Best is the best viable function. + if (Best->Function && Best->Function->isDeleted()) + return OR_Deleted; + + if (auto *M = dyn_cast_or_null<CXXMethodDecl>(Best->Function); + Kind == CSK_AddressOfOverloadSet && M && + M->isImplicitObjectMemberFunction()) { + return OR_No_Viable_Function; + } if (!EquivalentCands.empty()) S.diagnoseEquivalentInternalLinkageDeclarations(Loc, Best->Function, EquivalentCands); - return R; + + return OR_Success; } namespace { @@ -13033,9 +12733,6 @@ SmallVector<OverloadCandidate *, 32> OverloadCandidateSet::CompleteCandidates( Sema &S, OverloadCandidateDisplayKind OCD, ArrayRef<Expr *> Args, SourceLocation OpLoc, llvm::function_ref<bool(OverloadCandidate &)> Filter) { - - InjectNonDeducedTemplateCandidates(S); - // Sort the candidates by viability and position. Sorting directly would // be prohibitive, so we make a set of pointers and sort those. SmallVector<OverloadCandidate*, 32> Cands; @@ -14657,12 +14354,10 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, Expr *ExecConfig, bool AllowTypoCorrection, bool CalleesAddressIsTaken) { - - OverloadCandidateSet::CandidateSetKind CSK = - CalleesAddressIsTaken ? OverloadCandidateSet::CSK_AddressOfOverloadSet - : OverloadCandidateSet::CSK_Normal; - - OverloadCandidateSet CandidateSet(Fn->getExprLoc(), CSK); + OverloadCandidateSet CandidateSet( + Fn->getExprLoc(), CalleesAddressIsTaken + ? OverloadCandidateSet::CSK_AddressOfOverloadSet + : OverloadCandidateSet::CSK_Normal); ExprResult result; if (buildOverloadedCallSet(S, Fn, ULE, Args, LParenLoc, &CandidateSet, @@ -14678,17 +14373,6 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, OverloadingResult OverloadResult = CandidateSet.BestViableFunction(*this, Fn->getBeginLoc(), Best); - // [C++23][over.call.func] - // if overload resolution selects a non-static member function, - // the call is ill-formed; - if (CSK == OverloadCandidateSet::CSK_AddressOfOverloadSet && - Best != CandidateSet.end()) { - if (auto *M = dyn_cast_or_null<CXXMethodDecl>(Best->Function); - M && M->isImplicitObjectMemberFunction()) { - OverloadResult = OR_No_Viable_Function; - } - } - // Model the case with a call to a templated function whose definition // encloses the call and whose return type contains a placeholder type as if // the UnresolvedLookupExpr was type-dependent. @@ -15024,24 +14708,18 @@ void Sema::LookupOverloadedBinOp(OverloadCandidateSet &CandidateSet, // rewritten candidates using these functions if necessary. AddNonMemberOperatorCandidates(Fns, Args, CandidateSet); - // As template candidates are not deduced immediately, - // persist the array in the overload set. - ArrayRef<Expr *> ReversedArgs; - if (CandidateSet.getRewriteInfo().allowsReversed(Op) || - CandidateSet.getRewriteInfo().allowsReversed(ExtraOp)) - ReversedArgs = CandidateSet.getPersistentArgsArray(Args[1], Args[0]); - // Add operator candidates that are member functions. AddMemberOperatorCandidates(Op, OpLoc, Args, CandidateSet); if (CandidateSet.getRewriteInfo().allowsReversed(Op)) - AddMemberOperatorCandidates(Op, OpLoc, ReversedArgs, CandidateSet, + AddMemberOperatorCandidates(Op, OpLoc, {Args[1], Args[0]}, CandidateSet, OverloadCandidateParamOrder::Reversed); // In C++20, also add any rewritten member candidates. if (ExtraOp) { AddMemberOperatorCandidates(ExtraOp, OpLoc, Args, CandidateSet); if (CandidateSet.getRewriteInfo().allowsReversed(ExtraOp)) - AddMemberOperatorCandidates(ExtraOp, OpLoc, ReversedArgs, CandidateSet, + AddMemberOperatorCandidates(ExtraOp, OpLoc, {Args[1], Args[0]}, + CandidateSet, OverloadCandidateParamOrder::Reversed); } diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 0ecdbb3ffb89f..772962ac653f7 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -6142,9 +6142,9 @@ FunctionDecl *Sema::getMoreConstrainedFunction(FunctionDecl *FD1, assert(!FD1->getDescribedTemplate() && !FD2->getDescribedTemplate() && "not for function templates"); assert(!FD1->isFunctionTemplateSpecialization() || - (isa<CXXConversionDecl, CXXConstructorDecl>(FD1))); + isa<CXXConversionDecl>(FD1)); assert(!FD2->isFunctionTemplateSpecialization() || - (isa<CXXConversionDecl, CXXConstructorDecl>(FD2))); + isa<CXXConversionDecl>(FD2)); FunctionDecl *F1 = FD1; if (FunctionDecl *P = FD1->getTemplateInstantiationPattern(false)) diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp index 083e743818121..ba8e2dc372e98 100644 --- a/clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp +++ b/clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp @@ -14,7 +14,7 @@ template<typename T> struct S { // expected-note@#FINST{{in instantiation of function template specialization}} template<typename T> requires (S<T>{}) void f(T); -void f(long); +void f(int); // Ensure this applies to operator && as well. // expected-error@+3{{atomic constraint must be of type 'bool' (found 'S<int>')}} @@ -22,7 +22,7 @@ void f(long); // expected-note@#F2INST{{in instantiation of function template specialization}} template<typename T> requires (S<T>{} && true) void f2(T); -void f2(long); +void f2(int); template<typename T> requires requires { requires S<T>{}; @@ -36,12 +36,12 @@ template<typename T> requires requires { // } void f3(T); -void f3(long); +void f3(int); // Doesn't diagnose, since this is no longer a compound requirement. template<typename T> requires (bool(1 && 2)) void f4(T); -void f4(long); +void f4(int); void g() { f(0); // #FINST diff --git a/clang/test/SemaCUDA/function-overload.cu b/clang/test/SemaCUDA/function-overload.cu index 3d05839af7528..4710c81763adf 100644 --- a/clang/test/SemaCUDA/function-overload.cu +++ b/clang/test/SemaCUDA/function-overload.cu @@ -1,3 +1,6 @@ +// REQUIRES: x86-registered-target +// REQUIRES: nvptx-registered-target + // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-linux-gnu -fsyntax-only \ // RUN: -verify=host,hostdefer,devdefer,expected %s // RUN: %clang_cc1 -std=c++14 -triple nvptx64-nvidia-cuda -fsyntax-only \ diff --git a/clang/test/SemaCXX/implicit-member-functions.cpp b/clang/test/SemaCXX/implicit-member-functions.cpp index 8350eac5b88a0..1554b1af5d59a 100644 --- a/clang/test/SemaCXX/implicit-member-functions.cpp +++ b/clang/test/SemaCXX/implicit-member-functions.cpp @@ -54,24 +54,31 @@ namespace PR7594 { namespace Recursion { template<typename T> struct InvokeCopyConstructor { static const T &get(); - typedef decltype(T(get())) type; + typedef decltype(T(get())) type; // expected-error {{no matching conver}} }; struct B; struct A { + // expected-note@-1 {{while substituting deduced template arguments}} typedef B type; template<typename T, typename = typename InvokeCopyConstructor<typename T::type>::type> + // expected-note@-1 {{in instantiation of template class}} A(const T &); + // expected-note@-1 {{in instantiation of default argument}} }; - struct B { - B(); + struct B { // expected-note {{while declaring the implicit copy constructor for 'B'}} + // expected-note@-1 {{candidate constructor (the implicit move }} + B(); // expected-note {{candidate constructor not viable}} A a; }; // Triggering the declaration of B's copy constructor causes overload - // resolution to occur for A's copying constructor, which picks - // the implicit copy constructor of A. - // Because that copy constructor is always a perfect match the template - // candidate is not instantiated. + // resolution to occur for A's copying constructor, which instantiates + // InvokeCopyConstructor<B>, which triggers the declaration of B's copy + // constructor. Notionally, this happens when we get to the end of the + // definition of 'struct B', so there is no declared copy constructor yet. + // + // This behavior is g++-compatible, but isn't exactly right; the class is + // supposed to be incomplete when we implicitly declare its special members. B b = B(); diff --git a/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp b/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp deleted file mode 100644 index 877816ca013ec..0000000000000 --- a/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp +++ /dev/null @@ -1,185 +0,0 @@ -// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -fsyntax-only -verify -std=c++11 %s -// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -fsyntax-only -verify -std=c++20 %s -// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -fsyntax-only -verify -std=c++2c %s - -template <typename T> -struct Invalid { static_assert(false, "instantiated Invalid"); }; // #err-invalid - -template <typename T> -int f(T a, Invalid<T> = {}); // #note-f - -// sanity check -int e1 = f(0); -//expected-error@#err-invalid {{static assertion failed: instantiated Invalid}} -//expected-note@-2 {{in instantiation of default function argument expression for 'f<int>' required here}} -//expected-note@#note-f {{in instantiation of template class 'Invalid<int>' requested here}} -//expected-note@#note-f {{passing argument to parameter here}} - -int f(int); -int ok1 = f(0); -int e4 = f((const int&)(ok1)); - -int f(int, int = 0); -int ok2 = f(0, 0); - -int e2 = f(0L); -//expected-error@#err-invalid {{static assertion failed: instantiated Invalid}} -//expected-note@-2 {{in instantiation of default function argument expression for 'f<long>' required here}} -//expected-note@#note-f {{in instantiation of template class 'Invalid<long>' requested here}} -//expected-note@#note-f {{passing argument to parameter here}} - -int f(long); -int ok3 = f(0L); - -template <typename T> -struct Invalid2 { static_assert(false, "instantiated Invalid2"); }; // #err-qualifiers - -template <typename T> -int ref(T a, Invalid2<T> = {}); // expected-note 2{{here}} -int ref(int&); -int ref1 = ref(ok3); -int ref2 = ref((const int&)ok3); // expected-note {{here}} -//expected-error@#err-qualifiers {{static assertion failed: instantiated Invalid2}} - - -template <typename T> -int f_alias(T a, Invalid<T> = {}); -using Alias = int; -int f_alias(Alias); -int ok4 = f_alias(0); - -#if __cplusplus >= 202002 - -struct Copyable { - template <typename T> - requires __is_constructible(Copyable, T) - explicit Copyable(T op) noexcept; // #1 - Copyable(const Copyable&) noexcept = default; // #2 -}; -static_assert(__is_constructible(Copyable, const Copyable&)); - -struct ImplicitlyCopyable { - template <typename T> - requires __is_constructible(ImplicitlyCopyable, T) - explicit ImplicitlyCopyable(T op) = delete; // #1 -}; -static_assert(__is_constructible(ImplicitlyCopyable, const ImplicitlyCopyable&)); - - -struct Movable { - template <typename T> - requires __is_constructible(Movable, T) // #err-self-constraint-1 - explicit Movable(T op) noexcept; // #1 - Movable(Movable&&) noexcept = default; // #2 -}; -static_assert(__is_constructible(Movable, Movable&&)); -static_assert(__is_constructible(Movable, const Movable&)); -// expected-error@-1 {{static assertion failed due to requirement '__is_constructible(Movable, const Movable &)'}} - -static_assert(__is_constructible(Movable, int)); -// expected-error@-1{{static assertion failed due to requirement '__is_constructible(Movable, int)'}} \ -// expected-note@-1 2{{}} -// expected-error@#err-self-constraint-1{{satisfaction of constraint '__is_constructible(Movable, T)' depends on itself}} -// expected-note@#err-self-constraint-1 4{{}} - -template <typename T> -struct Members { - constexpr auto f(auto) { - static_assert(false, ""); - } - constexpr auto f(int) { return 1; } - constexpr auto f(int) requires true { return 2; } - - constexpr auto g(auto) { - static_assert(false, "instantiated member"); //#err-qualified-member - return 0; - } - constexpr auto g(int) & { return 1; } - - static constexpr auto s(auto) { - static_assert(false, ""); - } - static constexpr auto s(int) { - return 1; - } - static constexpr auto s(int) requires true { - return 2; - } -}; - -static_assert(Members<int[1]>{}.f(0) == 2); -static_assert(Members<int[2]>{}.g(0) == 0); -// expected-error@#err-qualified-member {{static assertion failed: instantiated member}} \ -// expected-note@-1{{in instantiation of function template specialization 'Members<int[2]>::g<int>' }} -Members<int[3]> m1; -static_assert(m1.g(0) == 1); -static_assert(Members<int[3]>{}.s(0) == 2); - - -namespace ConstructorInit{ -struct S { - template <typename T> - S(T&&) {} -}; -struct Test { - operator S() = delete; -}; - -static_assert(__is_constructible(S, Test)); -} - -namespace RefBinding { - -template <typename> struct remove_reference; -template <typename _Tp> struct remove_reference<_Tp &> { - using type = _Tp; -}; -template <typename _Tp> remove_reference<_Tp>::type move(_Tp &&); -template <typename _Head> struct _Head_base { - _Head_base(_Head &__h) : _M_head_impl(__h) {} - template <typename _UHead> _Head_base(_UHead &&); - _Head _M_head_impl; -}; - -template <typename _Elements> void forward_as_tuple(_Elements &&) { - _Head_base<_Elements &&>(_Elements{}); -} -struct StringRef { - void operator[](const StringRef __k) { forward_as_tuple((move)(__k)); } -}; - -} - -template <class> struct tuple {}; -struct BonkersBananas { - template <class T> operator T(); - template <class = void> explicit operator tuple<int>() = delete; -}; -static_assert(!__is_constructible(tuple<int>, BonkersBananas)); - -namespace GH62096 { -template <typename T> -struct Oops { - static_assert(sizeof(T) == 0); // #GH62096-err - static constexpr bool value = true; -}; - -template <class OPERATOR> -concept Operator = Oops<OPERATOR>::value; // #GH62096-note1 - -template <Operator OP> void f(OP op); // // #GH62096-note2 -void f(int); - -void g(int n) { f(n); } // OK -void h(short n) { f(n); } -// expected-error@#GH62096-err {{static assertion failed due to requirement 'sizeof(short) == 0'}} \ -// expected-note@-1{{in instantiation of function template specialization}} \ -// expected-note@-1{{while checking constraint satisfaction for template}} -// expected-note@#GH62096-note1{{in instantiation}} -// expected-note@#GH62096-note1{{while substituting template arguments into constraint expression here}} -// expected-note@#GH62096-note2{{while substituting template arguments into constraint expression here}} -// expected-note@#GH62096-note2{{while checking the satisfaction of concept}} -// expected-note@#GH62096-err {{expression evaluates}} -} - -#endif diff --git a/clang/test/SemaTemplate/instantiate-function-params.cpp b/clang/test/SemaTemplate/instantiate-function-params.cpp index eb2a7c5d4e8d6..7dd5595de58a3 100644 --- a/clang/test/SemaTemplate/instantiate-function-params.cpp +++ b/clang/test/SemaTemplate/instantiate-function-params.cpp @@ -6,12 +6,13 @@ template<typename T1> struct if_ { typedef if_c< static_cast<bool>(T1::value)> almost_type_; // expected-note 7{{in instantiation}} }; template <class Model, void (Model::*)()> struct wrap_constraints { }; -template <class Model> +template <class Model> inline char has_constraints_(Model* , // expected-note 3{{candidate template ignored}} - wrap_constraints<Model,&Model::constraints>* = 0); + wrap_constraints<Model,&Model::constraints>* = 0); // expected-note 4{{in instantiation}} + template <class Model> struct not_satisfied { static const bool value = sizeof( has_constraints_((Model*)0) == 1); // expected-error 3{{no matching function}} \ - // expected-note 4{{in instantiation}} + // expected-note 4{{while substituting deduced template arguments into function template 'has_constraints_' [with }} }; template <class ModelFn> struct requirement_; template <void(*)()> struct instantiate { diff --git a/clang/test/Templight/templight-empty-entries-fix.cpp b/clang/test/Templight/templight-empty-entries-fix.cpp index 7f34b10134929..d13b748068efe 100644 --- a/clang/test/Templight/templight-empty-entries-fix.cpp +++ b/clang/test/Templight/templight-empty-entries-fix.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -templight-dump -Wno-unused-value %s 2>&1 | FileCheck %s -void a(long) { +void a() { [] {}; } @@ -17,14 +17,14 @@ void a(long) { // CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:4:3'$}} // CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:4:3'$}} -template <int = 0> void a(long) { a(0); } +template <int = 0> void a() { a(); } // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+a$}} // CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}} // CHECK: {{^event:[ ]+Begin$}} // CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:20:25'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:20:35'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:20:31'$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+unnamed template non-type parameter 0 of a$}} // CHECK: {{^kind:[ ]+DefaultTemplateArgumentInstantiation$}} @@ -42,29 +42,29 @@ template <int = 0> void a(long) { a(0); } // CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}} // CHECK: {{^event:[ ]+End$}} // CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:20:25'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:20:35'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:20:31'$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+'a<0>'$}} // CHECK: {{^kind:[ ]+TemplateInstantiation$}} // CHECK: {{^event:[ ]+Begin$}} // CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:20:25'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:20:35'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:20:31'$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+'a<0>'$}} // CHECK: {{^kind:[ ]+TemplateInstantiation$}} // CHECK: {{^event:[ ]+End$}} // CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:20:25'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:20:35'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:20:31'$}} template <int> struct b { typedef int c; }; -template <bool d = true, class = typename b<d>::c> void a(long) { a(0); } +template <bool d = true, class = typename b<d>::c> void a() { a(); } // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+a$}} // CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}} // CHECK: {{^event:[ ]+Begin$}} // CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:60:57'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:67'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+d$}} // CHECK: {{^kind:[ ]+DefaultTemplateArgumentInstantiation$}} @@ -130,25 +130,25 @@ template <bool d = true, class = typename b<d>::c> void a(long) { a(0); } // CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}} // CHECK: {{^event:[ ]+End$}} // CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:60:57'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:67'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+'a<true, int>'$}} // CHECK: {{^kind:[ ]+TemplateInstantiation$}} // CHECK: {{^event:[ ]+Begin$}} // CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:60:57'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:67'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+'a<true, int>'$}} // CHECK: {{^kind:[ ]+TemplateInstantiation$}} // CHECK: {{^event:[ ]+End$}} // CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:60:57'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:67'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+a$}} // CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}} // CHECK: {{^event:[ ]+Begin$}} // CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:20:25'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:67'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+unnamed template non-type parameter 0 of a$}} // CHECK: {{^kind:[ ]+DefaultTemplateArgumentInstantiation$}} @@ -166,10 +166,34 @@ template <bool d = true, class = typename b<d>::c> void a(long) { a(0); } // CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}} // CHECK: {{^event:[ ]+End$}} // CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:20:25'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:67'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}} template <bool = true> void d(int = 0) { d(); } +// CHECK-LABEL: {{^---$}} +// CHECK: {{^name:[ ]+a$}} +// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}} +// CHECK: {{^event:[ ]+Begin$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:60:57'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}} +// CHECK-LABEL: {{^---$}} +// CHECK: {{^name:[ ]+a$}} +// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}} +// CHECK: {{^event:[ ]+End$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:60:57'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}} +// CHECK-LABEL: {{^---$}} +// CHECK: {{^name:[ ]+a$}} +// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}} +// CHECK: {{^event:[ ]+Begin$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:20:25'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}} +// CHECK-LABEL: {{^---$}} +// CHECK: {{^name:[ ]+a$}} +// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}} +// CHECK: {{^event:[ ]+End$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:20:25'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+d$}} // CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}} @@ -225,41 +249,41 @@ void e() { } // CHECK-LABEL: {{^---$}} -// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}} +// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:247:3\)'$}} // CHECK: {{^kind:[ ]+Memoization$}} // CHECK: {{^event:[ ]+Begin$}} -// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:224:5'$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:248:5'$}} // CHECK-LABEL: {{^---$}} -// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}} +// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:247:3\)'$}} // CHECK: {{^kind:[ ]+Memoization$}} // CHECK: {{^event:[ ]+End$}} -// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:224:5'$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:248:5'$}} // CHECK-LABEL: {{^---$}} -// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}} +// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:247:3\)'$}} // CHECK: {{^kind:[ ]+Memoization$}} // CHECK: {{^event:[ ]+Begin$}} -// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:224:5'$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:248:5'$}} // CHECK-LABEL: {{^---$}} -// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}} +// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:247:3\)'$}} // CHECK: {{^kind:[ ]+Memoization$}} // CHECK: {{^event:[ ]+End$}} -// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:224:5'$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:248:5'$}} // CHECK-LABEL: {{^---$}} -// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}} +// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:247:3\)'$}} // CHECK: {{^kind:[ ]+Memoization$}} // CHECK: {{^event:[ ]+Begin$}} -// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}} // CHECK-LABEL: {{^---$}} -// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}} +// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:247:3\)'$}} // CHECK: {{^kind:[ ]+Memoization$}} // CHECK: {{^event:[ ]+End$}} -// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}} template <template<typename> class> @@ -275,71 +299,71 @@ void foo() { // CHECK: {{^name:[ ]+d$}} // CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}} // CHECK: {{^event:[ ]+Begin$}} -// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:290:6'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+unnamed template template parameter 0 of d$}} // CHECK: {{^kind:[ ]+PriorTemplateArgumentSubstitution$}} // CHECK: {{^event:[ ]+Begin$}} -// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:265:35'$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:289:35'$}} // CHECK: {{^poi:[ ]+''$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+unnamed template template parameter 0 of d$}} // CHECK: {{^kind:[ ]+PriorTemplateArgumentSubstitution$}} // CHECK: {{^event:[ ]+End$}} -// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:265:35'$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:289:35'$}} // CHECK: {{^poi:[ ]+''$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+unnamed template template parameter 0 of d$}} // CHECK: {{^kind:[ ]+PartialOrderingTTP$}} // CHECK: {{^event:[ ]+Begin$}} -// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:265:35'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:5'$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:289:35'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:5'$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+unnamed template template parameter 0 of d$}} // CHECK: {{^kind:[ ]+PartialOrderingTTP$}} // CHECK: {{^event:[ ]+End$}} -// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:265:35'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:5'$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:289:35'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:5'$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+d$}} // CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}} // CHECK: {{^event:[ ]+End$}} -// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:290:6'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+d$}} // CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}} // CHECK: {{^event:[ ]+Begin$}} -// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:290:6'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+d$}} // CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}} // CHECK: {{^event:[ ]+End$}} -// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:290:6'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+'d<C>'$}} // CHECK: {{^kind:[ ]+TemplateInstantiation$}} // CHECK: {{^event:[ ]+Begin$}} -// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:290:6'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+'d<C>'$}} // CHECK: {{^kind:[ ]+TemplateInstantiation$}} // CHECK: {{^event:[ ]+End$}} -// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}} +// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:290:6'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+d$}} // CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}} // CHECK: {{^event:[ ]+Begin$}} // CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:171:29'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}} // CHECK-LABEL: {{^---$}} // CHECK: {{^name:[ ]+d$}} // CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}} // CHECK: {{^event:[ ]+End$}} // CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:171:29'$}} -// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}} +// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits