llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Younan Zhang (zyn0217)

<details>
<summary>Changes</summary>

There is a wall-time improvement: 
https://llvm-compile-time-tracker.com/compare.php?from=678058af7da6a20593d8bb23076dc4773f9e55f1&amp;to=d5c04428be4b47526390e4bbcbb49e92bd9005dd&amp;stat=instructions%3Au

When overload resolution fails, we tried to build a RecoveryExpr which ended up 
performing duplicate overload resolutions, where the template argument 
deduction can be expensive.

This patch removes those 'known' invalid overload candidates before building 
RecoveryExpr.


---
Full diff: https://github.com/llvm/llvm-project/pull/222296.diff


1 Files Affected:

- (modified) clang/lib/Sema/SemaOverload.cpp (+42-22) 


``````````diff
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 106ddb90ed9dc..6cec8f9892c2c 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -14612,18 +14612,31 @@ static bool canBeDeclaredInNamespace(const 
DeclarationName &Name) {
 
 /// Attempt to recover from an ill-formed use of a non-dependent name in a
 /// template, where the non-dependent name was declared after the template
-/// was defined. This is common in code written for a compilers which do not
+/// was defined. This is common in code written for compilers which do not
 /// correctly implement two-stage name lookup.
 ///
 /// Returns true if a viable candidate was found and a diagnostic was issued.
 static bool DiagnoseTwoPhaseLookup(
     Sema &SemaRef, SourceLocation FnLoc, const CXXScopeSpec &SS,
     LookupResult &R, OverloadCandidateSet::CandidateSetKind CSK,
+    OverloadCandidateSet &KnownInvalidCandidateSet,
     TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
     CXXRecordDecl **FoundInClass = nullptr) {
   if (!SemaRef.inTemplateInstantiation() || !SS.isEmpty())
     return false;
 
+  llvm::SmallPtrSet<FunctionDecl *, 4> InvalidCandidates(
+      llvm::from_range,
+      llvm::make_filter_range(
+          llvm::map_range(
+              KnownInvalidCandidateSet,
+              [](const OverloadCandidate &Candidate) -> FunctionDecl * {
+                if (!Candidate.Viable)
+                  return Candidate.Function;
+                return nullptr;
+              }),
+          [](const FunctionDecl *FD) { return FD != nullptr; }));
+
   for (DeclContext *DC = SemaRef.CurContext; DC; DC = DC->getParent()) {
     if (DC->isTransparentContext())
       continue;
@@ -14634,8 +14647,13 @@ static bool DiagnoseTwoPhaseLookup(
       R.suppressDiagnostics();
 
       OverloadCandidateSet Candidates(FnLoc, CSK);
-      SemaRef.AddOverloadedCallCandidates(R, ExplicitTemplateArgs, Args,
-                                          Candidates);
+      for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+        if (InvalidCandidates.contains(I->getAsFunction()))
+          continue;
+        AddOverloadedCallCandidate(SemaRef, I.getPair(), ExplicitTemplateArgs,
+                                   Args, Candidates, false,
+                                   /*KnownValid=*/false);
+      }
 
       OverloadCandidateSet::iterator Best;
       OverloadingResult OR =
@@ -14726,14 +14744,15 @@ static bool DiagnoseTwoPhaseLookup(
 /// Returns true if a viable candidate was found and a diagnostic was issued.
 static bool
 DiagnoseTwoPhaseOperatorLookup(Sema &SemaRef, OverloadedOperatorKind Op,
-                               SourceLocation OpLoc,
-                               ArrayRef<Expr *> Args) {
+                               SourceLocation OpLoc, ArrayRef<Expr *> Args,
+                               OverloadCandidateSet &KnownInvalidCandidateSet) 
{
   DeclarationName OpName =
-    SemaRef.Context.DeclarationNames.getCXXOperatorName(Op);
+      SemaRef.Context.DeclarationNames.getCXXOperatorName(Op);
   LookupResult R(SemaRef, OpName, OpLoc, Sema::LookupOperatorName);
-  return DiagnoseTwoPhaseLookup(SemaRef, OpLoc, CXXScopeSpec(), R,
-                                OverloadCandidateSet::CSK_Operator,
-                                /*ExplicitTemplateArgs=*/nullptr, Args);
+  return DiagnoseTwoPhaseLookup(
+      SemaRef, OpLoc, CXXScopeSpec(), R, OverloadCandidateSet::CSK_Operator,
+      KnownInvalidCandidateSet,
+      /*ExplicitTemplateArgs=*/nullptr, Args, /*FoundInClass=*/nullptr);
 }
 
 namespace {
@@ -14760,11 +14779,10 @@ class BuildRecoveryCallExprRAII {
 ///    expected to diagnose as appropriate.
 static ExprResult
 BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
-                      UnresolvedLookupExpr *ULE,
-                      SourceLocation LParenLoc,
-                      MutableArrayRef<Expr *> Args,
-                      SourceLocation RParenLoc,
-                      bool EmptyLookup, bool AllowTypoCorrection) {
+                      UnresolvedLookupExpr *ULE, SourceLocation LParenLoc,
+                      MutableArrayRef<Expr *> Args, SourceLocation RParenLoc,
+                      OverloadCandidateSet &KnownInvalidCandidateSet,
+                      bool AllowTypoCorrection) {
   // Do not try to recover if it is already building a recovery call.
   // This stops infinite loops for template instantiations like
   //
@@ -14790,9 +14808,10 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr 
*Fn,
   CXXRecordDecl *FoundInClass = nullptr;
   if (DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R,
                              OverloadCandidateSet::CSK_Normal,
-                             ExplicitTemplateArgs, Args, &FoundInClass)) {
+                             KnownInvalidCandidateSet, ExplicitTemplateArgs,
+                             Args, &FoundInClass)) {
     // OK, diagnosed a two-phase lookup issue.
-  } else if (EmptyLookup) {
+  } else if (KnownInvalidCandidateSet.empty()) {
     // Try to recover from an empty lookup with typo correction.
     R.clear();
     NoTypoCorrectionCCC NoTypoValidator{};
@@ -15005,10 +15024,9 @@ static ExprResult FinishOverloadedCallExpr(Sema 
&SemaRef, Scope *S, Expr *Fn,
 
     // Try to recover by looking for viable functions which the user might
     // have meant to call.
-    ExprResult Recovery = BuildRecoveryCallExpr(SemaRef, S, Fn, ULE, LParenLoc,
-                                                Args, RParenLoc,
-                                                CandidateSet->empty(),
-                                                AllowTypoCorrection);
+    ExprResult Recovery =
+        BuildRecoveryCallExpr(SemaRef, S, Fn, ULE, LParenLoc, Args, RParenLoc,
+                              *CandidateSet, AllowTypoCorrection);
     if (Recovery.isInvalid() || Recovery.isUsable())
       return Recovery;
 
@@ -15410,7 +15428,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, 
UnaryOperatorKind Opc,
     // This is an erroneous use of an operator which can be overloaded by
     // a non-member function. Check for non-member operators which were
     // defined too late to be candidates.
-    if (DiagnoseTwoPhaseOperatorLookup(*this, Op, OpLoc, ArgsArray))
+    if (DiagnoseTwoPhaseOperatorLookup(*this, Op, OpLoc, ArgsArray,
+                                       CandidateSet))
       // FIXME: Recover by calling the found function.
       return ExprError();
 
@@ -15932,7 +15951,8 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation 
OpLoc,
         // This is an erroneous use of an operator which can be overloaded by
         // a non-member function. Check for non-member operators which were
         // defined too late to be candidates.
-        if (DiagnoseTwoPhaseOperatorLookup(*this, Op, OpLoc, Args))
+        if (DiagnoseTwoPhaseOperatorLookup(*this, Op, OpLoc, Args,
+                                           CandidateSet))
           // FIXME: Recover by calling the found function.
           return ExprError();
 

``````````

</details>


https://github.com/llvm/llvm-project/pull/222296
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to