[clang] b9941de - Fix a rejects-valid with consteval on overloaded operators

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 14 11:47:42 PDT 2021


Author: Aaron Ballman
Date: 2021-10-14T14:47:29-04:00
New Revision: b9941de0bfac4bad93e11dff26396e34a53e3891

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

LOG: Fix a rejects-valid with consteval on overloaded operators

It seems that Clang 11 regressed functionality that was working in
Clang 10 regarding calling a few overloaded operators in an immediate
context. Specifically, we were not checking for immediate invocations
of array subscripting and the arrow operators, but we properly handle
the other overloaded operators.

This fixes the two problematic operators and adds some test coverage to
show they're equivalent to calling the operator directly.

This addresses PR50779.

Added: 
    

Modified: 
    clang/lib/Sema/SemaOverload.cpp
    clang/test/SemaCXX/cxx2a-consteval.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 044e3c4b254ad..d93fd9df0093e 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -14161,7 +14161,8 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
                               Method->getType()->castAs<FunctionProtoType>()))
           return ExprError();
 
-        return MaybeBindToTemporary(TheCall);
+        return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall),
+                                           FnDecl);
       } else {
         // We matched a built-in operator. Convert the arguments, then
         // break out so that we will build the appropriate built-in
@@ -14916,7 +14917,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
                         Method->getType()->castAs<FunctionProtoType>()))
     return ExprError();
 
-  return MaybeBindToTemporary(TheCall);
+  return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), Method);
 }
 
 /// BuildLiteralOperatorCall - Build a UserDefinedLiteral by creating a call to

diff  --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp
index 04c8898aa5bad..c1e713a5b6b79 100644
--- a/clang/test/SemaCXX/cxx2a-consteval.cpp
+++ b/clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -612,3 +612,34 @@ using T = decltype(g(f()));
 static_assert(is_same<long, T>::value);
 
 } // namespace unevaluated
+
+namespace PR50779 {
+struct derp {
+  int b = 0;
+};
+
+constexpr derp d;
+
+struct test {
+  consteval int operator[](int i) const { return {}; }
+  consteval const derp * operator->() const { return &d; }
+  consteval int f() const { return 12; } // expected-note 2{{declared here}}
+};
+
+constexpr test a;
+
+// We previously rejected both of these overloaded operators as taking the
+// address of a consteval function outside of an immediate context, but we
+// accepted direct calls to the overloaded operator. Now we show that we accept
+// both forms.
+constexpr int s = a.operator[](1);
+constexpr int t = a[1];
+constexpr int u = a.operator->()->b;
+constexpr int v = a->b;
+// FIXME: I believe this case should work, but we currently reject.
+constexpr int w = (a.*&test::f)(); // expected-error {{cannot take address of consteval function 'f' outside of an immediate invocation}}
+constexpr int x = a.f();
+
+// Show that we reject when not in an immediate context.
+int w2 = (a.*&test::f)(); // expected-error {{cannot take address of consteval function 'f' outside of an immediate invocation}}
+}


        


More information about the cfe-commits mailing list