[llvm-branch-commits] [clang] fdedf39 - PR44723: Trigger return type deduction for operator<=>s whose return

Richard Smith via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Jan 31 13:09:03 PST 2020


Author: Richard Smith
Date: 2020-01-31T13:08:25-08:00
New Revision: fdedf39c46f526afb1c07b0ca91a7c5bc1e43b8f

URL: https://github.com/llvm/llvm-project/commit/fdedf39c46f526afb1c07b0ca91a7c5bc1e43b8f
DIFF: https://github.com/llvm/llvm-project/commit/fdedf39c46f526afb1c07b0ca91a7c5bc1e43b8f.diff

LOG: PR44723: Trigger return type deduction for operator<=>s whose return
types are needed to compute the return type of a defaulted operator<=>.

This raises the question of what to do if return type deduction fails.
The standard doesn't say, and implementations vary, so for now reject
that case eagerly to keep our options open.

(cherry picked from commit 42d4a55f227a1cc78ab8071062d869abe88655d9)

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b7b8c5f17c41..5608e2064b25 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8392,6 +8392,12 @@ def note_defaulted_comparison_cannot_deduce : Note<
   "return type of defaulted 'operator<=>' cannot be deduced because "
   "return type %2 of three-way comparison for %select{|member|base class}0 %1 "
   "is not a standard comparison category type">;
+def err_defaulted_comparison_cannot_deduce_undeduced_auto : Error<
+  "return type of defaulted 'operator<=>' cannot be deduced because "
+  "three-way comparison for %select{|member|base class}0 %1 "
+  "has a deduced return type and is not yet defined">;
+def note_defaulted_comparison_cannot_deduce_undeduced_auto : Note<
+  "%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 err_incorrect_defaulted_comparison_constexpr : Error<

diff  --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 9fa5691983a1..19403e050850 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7438,6 +7438,31 @@ class DefaultedComparisonAnalyzer
 
       if (OO == OO_Spaceship && FD->getReturnType()->isUndeducedAutoType()) {
         if (auto *BestFD = Best->Function) {
+          // 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
+          // compatible with most (all?) other reasonable options.
+          if (BestFD->getReturnType()->isUndeducedType() &&
+              S.DeduceReturnType(BestFD, FD->getLocation(),
+                                 /*Diagnose=*/false)) {
+            // Don't produce a duplicate error when asked to explain why the
+            // comparison is deleted: we diagnosed that when initially checking
+            // the defaulted operator.
+            if (Diagnose == NoDiagnostics) {
+              S.Diag(
+                  FD->getLocation(),
+                  diag::err_defaulted_comparison_cannot_deduce_undeduced_auto)
+                  << Subobj.Kind << Subobj.Decl;
+              S.Diag(
+                  Subobj.Loc,
+                  diag::note_defaulted_comparison_cannot_deduce_undeduced_auto)
+                  << Subobj.Kind << Subobj.Decl;
+              S.Diag(BestFD->getLocation(),
+                     diag::note_defaulted_comparison_cannot_deduce_callee)
+                  << Subobj.Kind << Subobj.Decl;
+            }
+            return Result::deleted();
+          }
           if (auto *Info = S.Context.CompCategories.lookupInfoForType(
               BestFD->getCallResultType())) {
             R.Category = Info->Kind;

diff  --git a/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp b/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
index a912384ccf76..dae31e925ba1 100644
--- a/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
+++ b/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
@@ -97,6 +97,39 @@ namespace Deduction {
 
   // Check that the above mechanism works.
   template void f<std::strong_ordering, weak>(); // expected-note {{instantiation of}}
+
+  std::strong_ordering x = A<strong>() <=> A<strong>();
+}
+
+namespace PR44723 {
+  // Make sure we trigger return type deduction for a callee 'operator<=>'
+  // before inspecting its return type.
+  template<int> struct a {
+    friend constexpr auto operator<=>(a const &lhs, a const &rhs) {
+      return std::strong_ordering::equal;
+    }
+  };
+  struct b {
+    friend constexpr auto operator<=>(b const &, b const &) = default;
+    a<0> m_value;
+  };
+  std::strong_ordering cmp_b = b() <=> b();
+
+  struct c {
+    auto operator<=>(const c&) const&; // expected-note {{selected 'operator<=>' for base class 'c' declared here}}
+  };
+  struct d : c { // expected-note {{base class 'c' declared here}}
+    friend auto operator<=>(const d&, const d&) = default; // #d
+    // expected-error@#d {{return type of defaulted 'operator<=>' cannot be deduced because three-way comparison for base class 'c' has a deduced return type and is not yet defined}}
+    // expected-warning@#d {{implicitly deleted}}
+  };
+  auto c::operator<=>(const c&) const& { // #c
+    return std::strong_ordering::equal;
+  }
+  // expected-error at +1 {{overload resolution selected deleted operator '<=>'}}
+  std::strong_ordering cmp_d = d() <=> d();
+  // expected-note@#c 2{{candidate}}
+  // expected-note@#d {{candidate function has been implicitly deleted}}
 }
 
 namespace BadDeducedType {


        


More information about the llvm-branch-commits mailing list