llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: cor3ntin (cor3ntin) <details> <summary>Changes</summary> Reverts llvm/llvm-project#<!-- -->136018 Still some bots failing https://lab.llvm.org/buildbot/#/builders/52/builds/7643 --- Patch is 78.11 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/136113.diff 12 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (-6) - (modified) clang/include/clang/Sema/Overload.h (+10-222) - (modified) clang/lib/Sema/SemaCodeComplete.cpp (+2-4) - (modified) clang/lib/Sema/SemaInit.cpp (+5-13) - (modified) clang/lib/Sema/SemaOverload.cpp (+100-432) - (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+2-2) - (modified) clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp (+4-4) - (modified) clang/test/SemaCUDA/function-overload.cu (+3) - (modified) clang/test/SemaCXX/implicit-member-functions.cpp (+14-7) - (removed) clang/test/SemaCXX/overload-resolution-deferred-templates.cpp (-200) - (modified) clang/test/SemaTemplate/instantiate-function-params.cpp (+4-3) - (modified) clang/test/Templight/templight-empty-entries-fix.cpp (+75-51) ``````````diff diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index fc36962b317e8..4f640697e1817 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 candidates 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 e667147bfac7e..6e08762dcc6d7 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -407,26 +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) { - // The types might differ if there is an array-to-pointer conversion - // or lvalue-to-rvalue conversion. - 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, @@ -763,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 { @@ -965,10 +939,6 @@ class Sema; LLVM_PREFERRED_TYPE(CallExpr::ADLCallKind) unsigned IsADLCandidate : 1; - /// Whether FinalConversion has been set. - LLVM_PREFERRED_TYPE(bool) - unsigned HasFinalConversion : 1; - /// Whether this is a rewritten candidate, and if so, of what kind? LLVM_PREFERRED_TYPE(OverloadCandidateRewriteKind) unsigned RewriteKind : 2; @@ -1009,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 (HasFinalConversion) - return FinalConversion.isPerfect(Ctx); - return true; - } - bool TryToFixBadConversion(unsigned Idx, Sema &S) { bool CanFix = Fix.tryToFixConversion( Conversions[Idx].Bad.FromExpr, @@ -1056,67 +1012,8 @@ class Sema; : IsSurrogate(false), IgnoreObjectArgument(false), TookAddressOfOverload(false), StrictPackMatch(false), IsADLCandidate(llvm::to_underlying(CallExpr::NotADL)), - HasFinalConversion(false), 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; + RewriteKind(CRK_None) {} }; - 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). @@ -1146,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 @@ -1225,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; @@ -1241,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]; @@ -1256,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; @@ -1276,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(); } @@ -1315,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 = @@ -1341,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. @@ -1360,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, @@ -1393,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); @@ -1451,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, @@ -1508,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 9e802a175bb05..77d7f821f2011 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -5231,7 +5231,7 @@ static OverloadingResult TryRefInitWithConversionFunction( // Add the final conversion sequence, if necessary. if (NewRefRelationship == Sema::Ref_Incompatible) { - assert(Best->HasFinalConversion && !isa<CXXConstructorDecl>(Function) && + assert(!isa<CXXConstructorDecl>(Function) && "should not have conversion after constructor"); ImplicitConversionSequence ICS; @@ -6200,7 +6200,6 @@ static void TryUserDefinedConversion(Sema &S, // If the conversion following the call to the conversion function // is interesting, add it as a separate step. - assert(Best->HasFinalConversion); if (Best->FinalConversion.First || Best->FinalConversion.Second || Best->FinalConversion.Third) { ImplicitConversionSequence ICS; @@ -10030,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 b7a981e08ead9..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 { @@ -4079,9 +4075,6 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, } if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(Best->Function)) { - - assert(Best->HasFinalConversion); - // C++ [over.ics.user]p1: // // [...] If the user-defined conversion is specified by a @@ -5165,9 +5158,6 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, OverloadCandidateSet::iterator Best; switch (CandidateSet.BestViableFunction(S, DeclLoc, Best)) { case OR_Success: - - assert(Best->HasFinalConversion); - // C++ [over.ics.ref]p1: // // [...] If the parameter binds directly to the result of @@ -7805,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.fu... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/136113 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits