[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