Skip to content

Commit cd07251

Browse files
cor3ntinsvkeerthy
authored andcommitted
[Clang] Ensure compound requirements do not contain placeholder expressions (#162618)
The name of an overload set is not a valid id expression. Fixes #51246
1 parent 49b7e77 commit cd07251

File tree

4 files changed

+43
-6
lines changed

4 files changed

+43
-6
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ Bug Fixes to C++ Support
460460
- Fix a crash when attempting to deduce a deduction guide from a non deducible template template parameter. (#130604)
461461
- Fix for clang incorrectly rejecting the default construction of a union with
462462
nontrivial member when another member has an initializer. (#GH81774)
463+
- Diagnose unresolved overload sets in non-dependent compound requirements. (#GH51246) (#GH97753)
463464

464465
Bug Fixes to AST Handling
465466
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Parse/ParseExprCXX.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3200,6 +3200,8 @@ ExprResult Parser::ParseRequiresExpression() {
32003200
BalancedDelimiterTracker ExprBraces(*this, tok::l_brace);
32013201
ExprBraces.consumeOpen();
32023202
ExprResult Expression = ParseExpression();
3203+
if (Expression.isUsable())
3204+
Expression = Actions.CheckPlaceholderExpr(Expression.get());
32033205
if (!Expression.isUsable()) {
32043206
ExprBraces.skipToEnd();
32053207
SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch);
@@ -3369,6 +3371,8 @@ ExprResult Parser::ParseRequiresExpression() {
33693371
// expression ';'
33703372
SourceLocation StartLoc = Tok.getLocation();
33713373
ExprResult Expression = ParseExpression();
3374+
if (Expression.isUsable())
3375+
Expression = Actions.CheckPlaceholderExpr(Expression.get());
33723376
if (!Expression.isUsable()) {
33733377
SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch);
33743378
break;

clang/test/AST/ByteCode/libcxx/deref-to-array.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ template <class _Op, class _Yp>
270270
void __is_derived_from_view_interface();
271271
template <class _Tp>
272272
bool enable_view = derived_from<_Tp, int> ||
273-
requires { ranges::__is_derived_from_view_interface; };
273+
requires { ranges::__is_derived_from_view_interface<_Tp, int>(); };
274274
template <class>
275275
concept range = requires { ranges::end; };
276276
template <class _Tp>

clang/test/SemaTemplate/concepts.cpp

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,7 +1037,7 @@ void test() {
10371037

10381038
namespace GH66612 {
10391039
template<typename C>
1040-
auto end(C c) ->int;
1040+
auto end(C c) ->int; // expected-note {{possible target for call}}
10411041

10421042
template <typename T>
10431043
concept Iterator = true;
@@ -1047,9 +1047,8 @@ namespace GH66612 {
10471047
{ end } -> Iterator; // #66612GH_END
10481048
};
10491049

1050-
static_assert(Container<int>);// expected-error{{static assertion failed}}
1051-
// expected-note@-1{{because 'int' does not satisfy 'Container'}}
1052-
// expected-note@#66612GH_END{{because 'end' would be invalid: reference to overloaded function could not be resolved; did you mean to call it?}}
1050+
static_assert(Container<int>);
1051+
// expected-error@#66612GH_END{{reference to overloaded function could not be resolved; did you mean to call it?}}
10531052
}
10541053

10551054
namespace GH66938 {
@@ -1407,7 +1406,6 @@ static_assert(!std::is_constructible_v<span<4>, array<int, 3>>);
14071406

14081407
}
14091408

1410-
14111409
namespace GH162125 {
14121410
template<typename, int size>
14131411
concept true_int = (size, true);
@@ -1444,3 +1442,37 @@ struct s {
14441442

14451443
void(*test)(int) = &s<bool>::f<int>;
14461444
}
1445+
namespace GH51246 {
1446+
void f(); // expected-note {{possible target for call}}
1447+
void f(int); // expected-note {{possible target for call}}
1448+
void g();
1449+
static_assert(requires { f; }); // expected-error {{reference to overloaded function could not be resolved}}
1450+
static_assert(requires { g; });
1451+
struct S {
1452+
void mf() {
1453+
static_assert(requires { mf(); });
1454+
static_assert(requires { mf; }); // expected-error {{reference to non-static member function must be called}}
1455+
static_assert(requires { S::mf; }); // expected-error {{reference to non-static member function must be called}}
1456+
}
1457+
void mf2(int); // expected-note 2{{possible target for call}}
1458+
void mf2() { // expected-note 2{{possible target for call}}
1459+
static_assert(requires { mf2; }); // expected-error {{reference to non-static member function must be called}}
1460+
static_assert(requires { S::mf2; }); // expected-error {{reference to non-static member function must be called}}
1461+
}
1462+
};
1463+
1464+
} // namespace GH51246
1465+
1466+
1467+
namespace GH97753 {
1468+
1469+
void f(); // expected-note {{possible target for call}}
1470+
void f(int); // expected-note {{possible target for call}}
1471+
1472+
template<typename T>
1473+
concept C = sizeof(T) == 42;
1474+
1475+
static_assert( requires {{ &f } -> C;} ); // expected-error {{reference to overloaded function could not be resolved;}}
1476+
// expected-error@-1 {{static assertion failed due to requirement 'requires { { &f() } -> C; }'}}
1477+
1478+
}

0 commit comments

Comments
 (0)