[c++20] Fix handling of operator rewrites naming consteval operator<=>.
authorRichard Smith <richard@metafoo.co.uk>
Tue, 30 Jun 2020 02:02:47 +0000 (19:02 -0700)
committerRichard Smith <richard@metafoo.co.uk>
Tue, 30 Jun 2020 02:02:47 +0000 (19:02 -0700)
clang/lib/Sema/SemaOverload.cpp
clang/test/SemaCXX/cxx2a-consteval.cpp

index 038b814..d68be85 100644 (file)
@@ -13506,6 +13506,10 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
         if (R.isInvalid())
           return ExprError();
 
+        R = CheckForImmediateInvocation(R, FnDecl);
+        if (R.isInvalid())
+          return ExprError();
+
         // For a rewritten candidate, we've already reversed the arguments
         // if needed. Perform the rest of the rewrite now.
         if ((Best->RewriteKind & CRK_DifferentOperator) ||
@@ -13541,7 +13545,7 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
         if (Best->RewriteKind != CRK_None)
           R = new (Context) CXXRewrittenBinaryOperator(R.get(), IsReversed);
 
-        return CheckForImmediateInvocation(R, FnDecl);
+        return R;
       } else {
         // We matched a built-in operator. Convert the arguments, then
         // break out so that we will build the appropriate built-in
index 0a6d137..3231107 100644 (file)
@@ -476,6 +476,25 @@ namespace override {
   }
 }
 
+namespace operator_rewrite {
+  struct A {
+    friend consteval int operator<=>(const A&, const A&) { return 0; }
+  };
+  const bool k = A() < A();
+  static_assert(!k);
+
+  A a;
+  bool k2 = A() < a; // OK, does not access 'a'.
+
+  struct B {
+    friend consteval int operator<=>(const B &l, const B &r) { return r.n - l.n; } // expected-note {{read of }}
+    int n;
+  };
+  static_assert(B() >= B());
+  B b; // expected-note {{here}}
+  bool k3 = B() < b; // expected-error-re {{call to consteval function '{{.*}}::operator<=>' is not a constant expression}} expected-note {{in call}}
+}
+
 struct A {
   int(*ptr)();
   consteval A(int(*p)() = nullptr) : ptr(p) {}