[clang] [Clang] Ensure compound requirements do not contain placeholder expressions (PR #162618)
Corentin Jabot via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 9 02:55:04 PDT 2025
https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/162618
>From 5b3e3d5b66bd45d9d08c274134bd49dbdb250fef Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Thu, 9 Oct 2025 11:06:10 +0200
Subject: [PATCH] [Clang] Ensure compound requirements do not contain
placeholder expressions
The name of an overloasd set is not a valid id expression.
Fixes #51246
Fixes #97753
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Parse/ParseExprCXX.cpp | 4 ++
.../AST/ByteCode/libcxx/deref-to-array.cpp | 2 +-
clang/test/SemaTemplate/concepts.cpp | 42 ++++++++++++++++---
4 files changed, 43 insertions(+), 6 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 9a0d69c6c1b0e..12c632ed0c24a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -455,6 +455,7 @@ Bug Fixes to C++ Support
- Fix a crash when attempting to deduce a deduction guide from a non deducible template template parameter. (#130604)
- Fix for clang incorrectly rejecting the default construction of a union with
nontrivial member when another member has an initializer. (#GH81774)
+- Diagnose unresolved overload sets in non-dependent compound requirements. (#GH51246) (#GH97753)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index a2c69578d5087..90191b0aeb666 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -3200,6 +3200,8 @@ ExprResult Parser::ParseRequiresExpression() {
BalancedDelimiterTracker ExprBraces(*this, tok::l_brace);
ExprBraces.consumeOpen();
ExprResult Expression = ParseExpression();
+ if (Expression.isUsable())
+ Expression = Actions.CheckPlaceholderExpr(Expression.get());
if (!Expression.isUsable()) {
ExprBraces.skipToEnd();
SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch);
@@ -3369,6 +3371,8 @@ ExprResult Parser::ParseRequiresExpression() {
// expression ';'
SourceLocation StartLoc = Tok.getLocation();
ExprResult Expression = ParseExpression();
+ if (Expression.isUsable())
+ Expression = Actions.CheckPlaceholderExpr(Expression.get());
if (!Expression.isUsable()) {
SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch);
break;
diff --git a/clang/test/AST/ByteCode/libcxx/deref-to-array.cpp b/clang/test/AST/ByteCode/libcxx/deref-to-array.cpp
index 2a527ab336a0d..7cfcd76b3965a 100644
--- a/clang/test/AST/ByteCode/libcxx/deref-to-array.cpp
+++ b/clang/test/AST/ByteCode/libcxx/deref-to-array.cpp
@@ -270,7 +270,7 @@ template <class _Op, class _Yp>
void __is_derived_from_view_interface();
template <class _Tp>
bool enable_view = derived_from<_Tp, int> ||
- requires { ranges::__is_derived_from_view_interface; };
+ requires { ranges::__is_derived_from_view_interface<_Tp, int>(); };
template <class>
concept range = requires { ranges::end; };
template <class _Tp>
diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp
index 3b7c138f83364..768af09afe9e2 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -1037,7 +1037,7 @@ void test() {
namespace GH66612 {
template<typename C>
- auto end(C c) ->int;
+ auto end(C c) ->int; // expected-note {{possible target for call}}
template <typename T>
concept Iterator = true;
@@ -1047,9 +1047,8 @@ namespace GH66612 {
{ end } -> Iterator; // #66612GH_END
};
- static_assert(Container<int>);// expected-error{{static assertion failed}}
- // expected-note at -1{{because 'int' does not satisfy 'Container'}}
- // expected-note@#66612GH_END{{because 'end' would be invalid: reference to overloaded function could not be resolved; did you mean to call it?}}
+ static_assert(Container<int>);
+ // expected-error@#66612GH_END{{reference to overloaded function could not be resolved; did you mean to call it?}}
}
namespace GH66938 {
@@ -1407,7 +1406,6 @@ static_assert(!std::is_constructible_v<span<4>, array<int, 3>>);
}
-
namespace GH162125 {
template<typename, int size>
concept true_int = (size, true);
@@ -1444,3 +1442,37 @@ struct s {
void(*test)(int) = &s<bool>::f<int>;
}
+namespace GH51246 {
+void f(); // expected-note {{possible target for call}}
+void f(int); // expected-note {{possible target for call}}
+void g();
+static_assert(requires { f; }); // expected-error {{reference to overloaded function could not be resolved}}
+static_assert(requires { g; });
+struct S {
+ void mf() {
+ static_assert(requires { mf(); });
+ static_assert(requires { mf; }); // expected-error {{reference to non-static member function must be called}}
+ static_assert(requires { S::mf; }); // expected-error {{reference to non-static member function must be called}}
+ }
+ void mf2(int); // expected-note 2{{possible target for call}}
+ void mf2() { // expected-note 2{{possible target for call}}
+ static_assert(requires { mf2; }); // expected-error {{reference to non-static member function must be called}}
+ static_assert(requires { S::mf2; }); // expected-error {{reference to non-static member function must be called}}
+ }
+};
+
+} // namespace GH51246
+
+
+namespace GH97753 {
+
+void f(); // expected-note {{possible target for call}}
+void f(int); // expected-note {{possible target for call}}
+
+template<typename T>
+concept C = sizeof(T) == 42;
+
+static_assert( requires {{ &f } -> C;} ); // expected-error {{reference to overloaded function could not be resolved;}}
+// expected-error at -1 {{static assertion failed due to requirement 'requires { { &f() } -> C; }'}}
+
+}
More information about the cfe-commits
mailing list