Skip to content

Commit 17caed1

Browse files
committed
feat: recognize requires expressions
1 parent ce824c5 commit 17caed1

File tree

6 files changed

+254
-157
lines changed

6 files changed

+254
-157
lines changed
Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
11
arithmetic: <T> concept = std::integral<T> || std::floating_point<T>;
2-
number: <T> concept = std::regular<T> && requires(c: T)
2+
number_difference_t: <T> type == std::type_identity_t<decltype(T() - T())>;
3+
number: <T> concept = std::regular<T> && requires(c: T)
34
{
4-
!requires std::input_or_output_iterator<T>;
5+
!requires(c*);
56
{c + c} throws is std::common_with<T>;
67
number_difference_t<T>;
78
(c - c);
89
{c - c} throws;
910
requires std::common_with<number_difference_t<T>, T>;
1011
};
11-
number_difference_t: <T> type == std::type_identity_t<T() - T()>;
1212
test_nonthrowing_requirements: <T> concept = requires(c: T)
1313
{
1414
{T()};
1515
{-T()} is std::same_as<T>;
1616
};
1717
main: () = {
18-
[[assert Testing: arithmetic<i32>]]
19-
[[assert Testing: arithmetic<float>]]
20-
[[assert Testing: number<i32>]]
21-
[[assert Testing: number<float>]]
22-
[[assert Testing: number<std::chrono::seconds>]]
23-
[[assert Testing: test_nonthrowing_requirements<i32>]]
18+
static_assert(arithmetic<i32>);
19+
static_assert(arithmetic<float>);
20+
static_assert(number<i32>);
21+
static_assert(number<float>);
22+
static_assert(number<std::chrono::seconds>);
23+
static_assert(!number<* i32>);
24+
static_assert(test_nonthrowing_requirements<i32>);
25+
static_assert(!test_nonthrowing_requirements<std::chrono::seconds>);
2426
}

regression-tests/test-results/clang-18/pure2-concept-definition.cpp.execution

Whitespace-only changes.

regression-tests/test-results/clang-18/pure2-concept-definition.cpp.output

Lines changed: 0 additions & 25 deletions
This file was deleted.

regression-tests/test-results/pure2-concept-definition.cpp

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,21 @@
1212

1313
#line 1 "pure2-concept-definition.cpp2"
1414
template<typename T> concept arithmetic = std::integral<T> || std::floating_point<T>;
15-
template<typename T> concept number = std::regular<T> && ;
16-
17-
#line 11 "pure2-concept-definition.cpp2"
18-
template<typename T> using number_difference_t = std::type_identity_t<T() - T()>;
19-
template<typename T> concept test_nonthrowing_requirements = ;
20-
21-
#line 17 "pure2-concept-definition.cpp2"
15+
template<typename T> using number_difference_t = std::type_identity_t<decltype(T() - T())>;
16+
template<typename T> concept number = std::regular<T> && requires(T const& c) {
17+
18+
requires !requires { (*cpp2::assert_not_null(c)); };
19+
{ c + c } -> std::common_with<T>;
20+
typename number_difference_t<T>;
21+
(c - c);
22+
{ c - c };
23+
requires std::common_with<number_difference_t<T>,T>;
24+
};
25+
template<typename T> concept test_nonthrowing_requirements = requires(T const& c) {
26+
27+
{ T() } noexcept;
28+
{ -T() } noexcept -> std::same_as<T>;
29+
};
2230
auto main() -> int;
2331

2432

@@ -27,11 +35,13 @@ auto main() -> int;
2735

2836
#line 17 "pure2-concept-definition.cpp2"
2937
auto main() -> int{
30-
cpp2::Testing.expects(arithmetic<cpp2::i32>, "");
31-
cpp2::Testing.expects(arithmetic<float>, "");
32-
cpp2::Testing.expects(number<cpp2::i32>, "");
33-
cpp2::Testing.expects(number<float>, "");
34-
cpp2::Testing.expects(number<std::chrono::seconds>, "");
35-
cpp2::Testing.expects(test_nonthrowing_requirements<cpp2::i32>, "");
38+
static_assert(arithmetic<cpp2::i32>);
39+
static_assert(arithmetic<float>);
40+
static_assert(number<cpp2::i32>);
41+
static_assert(number<float>);
42+
static_assert(number<std::chrono::seconds>);
43+
static_assert(!(number<cpp2::i32*>));
44+
static_assert(test_nonthrowing_requirements<cpp2::i32>);
45+
static_assert(!(test_nonthrowing_requirements<std::chrono::seconds>));
3646
}
3747

source/cppfront.cpp

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2029,6 +2029,101 @@ class cppfront
20292029
}
20302030

20312031

2032+
//-----------------------------------------------------------------------
2033+
//
2034+
struct type_requirement_tag {};
2035+
struct simple_requirement_tag {};
2036+
struct nested_requirement_tag {};
2037+
struct negative_requirement_tag {};
2038+
2039+
auto emit(
2040+
type_id_node const& n,
2041+
type_requirement_tag
2042+
)
2043+
-> void
2044+
{
2045+
printer.print_cpp2("typename ", n.position());
2046+
emit(n);
2047+
printer.print_cpp2(";", n.position());
2048+
}
2049+
2050+
auto emit(
2051+
expression_node const& n,
2052+
simple_requirement_tag
2053+
)
2054+
-> void
2055+
{
2056+
emit(n);
2057+
printer.print_cpp2(";", n.position());
2058+
}
2059+
2060+
auto emit(requires_expression_node::compound_requirement_node const& n)
2061+
-> void
2062+
{
2063+
assert(n.expression);
2064+
printer.print_cpp2("{ ", n.expression->position());
2065+
emit(*n.expression);
2066+
printer.print_cpp2(" }", n.expression->position());
2067+
if (!n.throws) {
2068+
printer.print_cpp2(" noexcept", n.expression->position());
2069+
}
2070+
if (n.type_constraint) {
2071+
printer.print_cpp2(" -> ", n.expression->position());
2072+
emit(*n.type_constraint);
2073+
}
2074+
printer.print_cpp2(";", n.expression->position());
2075+
}
2076+
2077+
auto emit(
2078+
logical_or_expression_node const& n,
2079+
nested_requirement_tag
2080+
)
2081+
-> void
2082+
{
2083+
printer.print_cpp2("requires ", n.position());
2084+
emit(n);
2085+
printer.print_cpp2(";", n.position());
2086+
}
2087+
2088+
auto emit(
2089+
requires_expression_node::requirement_node const& n,
2090+
negative_requirement_tag
2091+
)
2092+
-> void
2093+
{
2094+
printer.print_cpp2("requires ", n.position());
2095+
printer.print_cpp2("!requires { ", n.position());
2096+
emit(n);
2097+
printer.print_cpp2(" };", n.position());
2098+
}
2099+
2100+
auto emit(requires_expression_node::requirement_node const& n)
2101+
-> void
2102+
{
2103+
try_emit<requires_expression_node::requirement_node::type >(n.requirement, type_requirement_tag{});
2104+
try_emit<requires_expression_node::requirement_node::expression>(n.requirement, simple_requirement_tag{});
2105+
try_emit<requires_expression_node::requirement_node::compound >(n.requirement);
2106+
try_emit<requires_expression_node::requirement_node::nested >(n.requirement, nested_requirement_tag{});
2107+
try_emit<requires_expression_node::requirement_node::negative >(n.requirement, negative_requirement_tag{});
2108+
}
2109+
2110+
auto emit(requires_expression_node const& n)
2111+
-> void
2112+
{
2113+
assert(n.identifier);
2114+
emit(*n.identifier);
2115+
if (n.parameters) {
2116+
emit(*n.parameters);
2117+
}
2118+
printer.print_cpp2(" {", n.position());
2119+
for (auto const& x : n.requirements) {
2120+
assert(x);
2121+
emit(*x);
2122+
}
2123+
printer.print_cpp2("\n}", n.position(), true);
2124+
}
2125+
2126+
20322127
//-----------------------------------------------------------------------
20332128
//
20342129
auto emit(selection_statement_node const& n)
@@ -2480,6 +2575,7 @@ class cppfront
24802575
try_emit<primary_expression_node::expression_list>(n.expr);
24812576
try_emit<primary_expression_node::id_expression >(n.expr);
24822577
try_emit<primary_expression_node::inspect >(n.expr, true);
2578+
try_emit<primary_expression_node::requires_ >(n.expr);
24832579
try_emit<primary_expression_node::literal >(n.expr);
24842580

24852581
if (n.expr.index() == primary_expression_node::declaration)

0 commit comments

Comments
 (0)