mizvekov updated this revision to Diff 352667.
mizvekov added a comment.

Instead of excluding function pointers from the overload set, just implicitly 
delete
with new diagnostic in case we end up selecting it.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103855/new/

https://reviews.llvm.org/D103855

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/CXX/class/class.compare/class.spaceship/p2.cpp

Index: clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
+++ clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
@@ -159,7 +159,7 @@
 namespace PR48856 {
   struct A {
     auto operator<=>(const A &) const = default; // expected-warning {{implicitly deleted}}
-    void (*x)();                                 // expected-note {{because there is no viable three-way comparison function for member 'x'}}
+    void (*x)();                                 // expected-note {{does not support relational comparisons}}
   };
 
   struct B {
@@ -197,8 +197,7 @@
     operator fp() const;
   };
   struct b3 {
-    auto operator<=>(b3 const &) const = default; // expected-error {{cannot be deduced because three-way comparison for member 'f' would compare as builtin type 'void (*)()' which is not currently supported}}
-    // expected-warning@-1 {{implicitly deleted}}
-    a3 f;
+    auto operator<=>(b3 const &) const = default; // expected-warning {{implicitly deleted}}
+    a3 f; // expected-note {{would compare member 'f' as 'void (*)()', which does not support relational comparisons}}
   };
 }
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -7749,16 +7749,11 @@
 
     if (Args[0]->getType()->isOverloadableType())
       S.LookupOverloadedBinOp(CandidateSet, OO, Fns, Args);
-    else if (OO == OO_EqualEqual ||
-             !Args[0]->getType()->isFunctionPointerType()) {
+    else
       // FIXME: We determine whether this is a valid expression by checking to
       // see if there's a viable builtin operator candidate for it. That isn't
       // really what the rules ask us to do, but should give the right results.
-      //
-      // Note that the builtin operator for relational comparisons on function
-      // pointers is the only known case which cannot be used.
       S.AddBuiltinOperatorCandidates(OO, FD->getLocation(), Args, CandidateSet);
-    }
 
     Result R;
 
@@ -7802,11 +7797,14 @@
           return Result::deleted();
       }
 
-      // C++2a [class.compare.default]p3 [P2002R0]:
-      //   A defaulted comparison function is constexpr-compatible if [...]
-      //   no overlod resolution performed [...] results in a non-constexpr
-      //   function.
+      bool NeedsDeducing =
+          OO == OO_Spaceship && FD->getReturnType()->isUndeducedAutoType();
+
       if (FunctionDecl *BestFD = Best->Function) {
+        // C++2a [class.compare.default]p3 [P2002R0]:
+        //   A defaulted comparison function is constexpr-compatible if
+        //   [...] no overlod resolution performed [...] results in a
+        //   non-constexpr function.
         assert(!BestFD->isDeleted() && "wrong overload resolution result");
         // If it's not constexpr, explain why not.
         if (Diagnose == ExplainConstexpr && !BestFD->isConstexpr()) {
@@ -7819,10 +7817,8 @@
           return Result::deleted();
         }
         R.Constexpr &= BestFD->isConstexpr();
-      }
 
-      if (OO == OO_Spaceship && FD->getReturnType()->isUndeducedAutoType()) {
-        if (auto *BestFD = Best->Function) {
+        if (NeedsDeducing) {
           // If any callee has an undeduced return type, deduce it now.
           // FIXME: It's not clear how a failure here should be handled. For
           // now, we produce an eager diagnostic, because that is forward
@@ -7848,10 +7844,9 @@
             }
             return Result::deleted();
           }
-          if (auto *Info = S.Context.CompCategories.lookupInfoForType(
-              BestFD->getCallResultType())) {
-            R.Category = Info->Kind;
-          } else {
+          auto *Info = S.Context.CompCategories.lookupInfoForType(
+              BestFD->getCallResultType());
+          if (!Info) {
             if (Diagnose == ExplainDeleted) {
               S.Diag(Subobj.Loc, diag::note_defaulted_comparison_cannot_deduce)
                   << Subobj.Kind << Subobj.Decl
@@ -7862,12 +7857,25 @@
             }
             return Result::deleted();
           }
-        } else {
-          QualType T = Best->BuiltinParamTypes[0];
-          assert(T == Best->BuiltinParamTypes[1] &&
-                 "builtin comparison for different types?");
-          assert(Best->BuiltinParamTypes[2].isNull() &&
-                 "invalid builtin comparison");
+          R.Category = Info->Kind;
+        }
+      } else {
+        QualType T = Best->BuiltinParamTypes[0];
+        assert(T == Best->BuiltinParamTypes[1] &&
+               "builtin comparison for different types?");
+        assert(Best->BuiltinParamTypes[2].isNull() &&
+               "invalid builtin comparison");
+
+        // The builtin operator for relational comparisons on function
+        // pointers is the only known case which cannot be used.
+        if (OO != OO_EqualEqual && T->isFunctionPointerType()) {
+          if (Diagnose == ExplainDeleted)
+            S.Diag(Subobj.Loc, diag::note_defaulted_comparison_selected_invalid)
+                << Subobj.Kind << Subobj.Decl << T;
+          return Result::deleted();
+        }
+
+        if (NeedsDeducing) {
           Optional<ComparisonCategoryType> Cat =
               getComparisonCategoryForBuiltinCmp(T);
           if (!Cat) {
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9143,6 +9143,9 @@
   "%select{|member|base class}0 %1 declared here">;
 def note_defaulted_comparison_cannot_deduce_callee : Note<
   "selected 'operator<=>' for %select{|member|base class}0 %1 declared here">;
+def note_defaulted_comparison_selected_invalid : Note<
+  "would compare %select{|member|base class}0 %1 "
+  "as %2, which does not support relational comparisons">;
 def err_defaulted_comparison_cannot_deduce_unsupported_builtin_type : Error<
   "return type of defaulted 'operator<=>' cannot be deduced because "
   "three-way comparison for %select{|member|base class}0 %1 "
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D103855: ... Matheus Izvekov via Phabricator via cfe-commits

Reply via email to