Skip to content

Commit 1764f0c

Browse files
committed
Emit requires clause for variable template, closes hsutter#607
And update GCC 10 diagnostic
1 parent ce8f8bc commit 1764f0c

19 files changed

+82
-59
lines changed

include/cpp2util.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1755,10 +1755,10 @@ using cpp2::cpp2_new;
17551755
// See commit 5a0d77f8e297902c0b9712c5aafb6208cfa4c139.
17561756
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ == 10
17571757
#define CPP2_REQUIRES(...) /* empty */
1758-
#define CPP2_REQUIRES_MEMFN(...) static_assert(false, "GCC 11 or higher is required to support type-scope functions that have a 'requires' clause. This includes a 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)', which relies on being able to add a 'requires' clause - in that case, use 'forward s: _' instead if you need the result to compile with GCC 10.")
1758+
#define CPP2_REQUIRES_(...) static_assert(false, "GCC 11 or higher is required to support variables and type-scope functions that have a 'requires' clause. This includes a type-scope 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)', which relies on being able to add a 'requires' clause - in that case, use 'forward s: _' instead if you need the result to compile with GCC 10.")
17591759
#else
17601760
#define CPP2_REQUIRES(...) requires (__VA_ARGS__)
1761-
#define CPP2_REQUIRES_MEMFN(...) requires (__VA_ARGS__)
1761+
#define CPP2_REQUIRES_(...) requires (__VA_ARGS__)
17621762
#endif
17631763

17641764
#endif

regression-tests/pure2-requires-clauses.cpp2

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ f: <T: type, U: type>
1515
return a * b;
1616
}
1717

18+
v: <T> const T requires std::same_as<T, i32> = 0;
19+
1820
main: () = {
1921
x: X<int,int> = ();
2022
std::cout << f<int,int>(2,5);

regression-tests/test-results/clang-12/pure2-bugfix-for-non-local-initialization.cpp.execution

Whitespace-only changes.

regression-tests/test-results/clang-12/pure2-bugfix-for-non-local-initialization.cpp.output

Whitespace-only changes.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
true
22
false
3-
./test.exe
3+
"test.exe"

regression-tests/test-results/gcc-10/pure2-bugfix-for-non-local-initialization.cpp.execution

Whitespace-only changes.

regression-tests/test-results/gcc-10/pure2-bugfix-for-non-local-initialization.cpp.output

Whitespace-only changes.

regression-tests/test-results/gcc-10/pure2-bugfix-for-requires-clause-in-forward-declaration.cpp.output

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:36: error: expected ‘;’ at end of member declaration
22
In file included from pure2-bugfix-for-requires-clause-in-forward-declaration.cpp:7:
3-
../../../include/cpp2util.h:1758:52: error: static assertion failed: GCC 11 or higher is required to support type-scope functions that have a 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)' - if you must use GCC 10, use 'forward s: _' instead
4-
1758 | #define CPP2_REQUIRES_MEMFN(...) static_assert(false, "GCC 11 or higher is required to support type-scope functions that have a 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)' - if you must use GCC 10, use 'forward s: _' instead")
5-
| ^~~~~
6-
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:4:1: note: in expansion of macro ‘CPP2_REQUIRES_MEMFN
3+
../../../include/cpp2util.h:1758:47: error: static assertion failed: GCC 11 or higher is required to support variables and type-scope functions that have a 'requires' clause. This includes a type-scope 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)', which relies on being able to add a 'requires' clause - in that case, use 'forward s: _' instead if you need the result to compile with GCC 10.
4+
1758 | #define CPP2_REQUIRES_(...) static_assert(false, "GCC 11 or higher is required to support variables and type-scope functions that have a 'requires' clause. This includes a type-scope 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)', which relies on being able to add a 'requires' clause - in that case, use 'forward s: _' instead if you need the result to compile with GCC 10.")
5+
| ^~~~~
6+
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:4:1: note: in expansion of macro ‘CPP2_REQUIRES_
77
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:46: error: expected ‘;’ at end of member declaration
88
In file included from pure2-bugfix-for-requires-clause-in-forward-declaration.cpp:7:
9-
../../../include/cpp2util.h:1758:52: error: static assertion failed: GCC 11 or higher is required to support type-scope functions that have a 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)' - if you must use GCC 10, use 'forward s: _' instead
10-
1758 | #define CPP2_REQUIRES_MEMFN(...) static_assert(false, "GCC 11 or higher is required to support type-scope functions that have a 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)' - if you must use GCC 10, use 'forward s: _' instead")
11-
| ^~~~~
12-
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:4:1: note: in expansion of macro ‘CPP2_REQUIRES_MEMFN
9+
../../../include/cpp2util.h:1758:47: error: static assertion failed: GCC 11 or higher is required to support variables and type-scope functions that have a 'requires' clause. This includes a type-scope 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)', which relies on being able to add a 'requires' clause - in that case, use 'forward s: _' instead if you need the result to compile with GCC 10.
10+
1758 | #define CPP2_REQUIRES_(...) static_assert(false, "GCC 11 or higher is required to support variables and type-scope functions that have a 'requires' clause. This includes a type-scope 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)', which relies on being able to add a 'requires' clause - in that case, use 'forward s: _' instead if you need the result to compile with GCC 10.")
11+
| ^~~~~
12+
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:4:1: note: in expansion of macro ‘CPP2_REQUIRES_
1313
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:3: error: no declaration matches ‘element::element(auto:80&&) requires is_same_v<typename std::remove_cv<typename std::remove_reference<decltype(element::__ct ::n)>::type>::type, std::__cxx11::string>’
1414
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:5:11: note: candidates are: ‘element::element(const element&)’
1515
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:20: note: ‘template<class auto:78> element::element(auto:78&&)’
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
In file included from pure2-requires-clauses.cpp:7:
2+
../../../include/cpp2util.h:1758:33: error: expected unqualified-id before ‘static_assert’
3+
1758 | #define CPP2_REQUIRES_(...) static_assert(false, "GCC 11 or higher is required to support variables and type-scope functions that have a 'requires' clause. This includes a type-scope 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)', which relies on being able to add a 'requires' clause - in that case, use 'forward s: _' instead if you need the result to compile with GCC 10.")
4+
| ^~~~~~~~~~~~~
5+
pure2-requires-clauses.cpp2:19:1: note: in expansion of macro ‘CPP2_REQUIRES_’

regression-tests/test-results/gcc-13/pure2-bugfix-for-non-local-initialization.cpp.execution

Whitespace-only changes.

regression-tests/test-results/gcc-13/pure2-bugfix-for-non-local-initialization.cpp.output

Whitespace-only changes.

regression-tests/test-results/msvc-2022/pure2-bugfix-for-non-local-initialization.cpp.execution

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pure2-bugfix-for-non-local-initialization.cpp

regression-tests/test-results/pure2-bugfix-for-non-local-initialization.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ auto main() -> int;
2626

2727
#line 5 "pure2-bugfix-for-non-local-initialization.cpp2"
2828
auto main() -> int{
29-
cpp2::Testing.expects(cpp2::assert_in_bounds(t::value, 0)==17, "");
30-
cpp2::Testing.expects(cpp2::assert_in_bounds(t::value, 1)==29, "");
29+
cpp2::Testing.expects(cpp2::assert_in_bounds(t::value, 0) == 17, "");
30+
cpp2::Testing.expects(cpp2::assert_in_bounds(t::value, 1) == 29, "");
3131
}
3232

regression-tests/test-results/pure2-bugfix-for-requires-clause-in-forward-declaration.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ class element;
1616
class element {
1717
private: std::string name;
1818
public: explicit element(auto&& n)
19-
CPP2_REQUIRES_MEMFN (std::is_same_v<CPP2_TYPEOF(n), std::string>)
19+
CPP2_REQUIRES_ (std::is_same_v<CPP2_TYPEOF(n), std::string>)
2020
#line 3 "pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2"
2121
;
2222
#line 3 "pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2"
2323
public: auto operator=(auto&& n) -> element&
24-
CPP2_REQUIRES_MEMFN (std::is_same_v<CPP2_TYPEOF(n), std::string>)
24+
CPP2_REQUIRES_ (std::is_same_v<CPP2_TYPEOF(n), std::string>)
2525
#line 3 "pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2"
2626
;
2727

regression-tests/test-results/pure2-requires-clauses.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ CPP2_REQUIRES (std::is_same_v<T,int> && std::is_same_v<U,int> && std::is_same_v<
3737

3838

3939
#line 18 "pure2-requires-clauses.cpp2"
40+
template<typename T>
41+
CPP2_REQUIRES_ (std::same_as<T,cpp2::i32>)
42+
#line 18 "pure2-requires-clauses.cpp2"
43+
extern T const v;
44+
4045
auto main() -> int;
4146

4247

@@ -56,6 +61,11 @@ requires (std::is_same_v<T,int> && std::is_same_v<U,int> && std::is_same_v<CPP2_
5661
return CPP2_FORWARD(a) * CPP2_FORWARD(b);
5762
}
5863

64+
template<typename T>
65+
requires (std::same_as<T,cpp2::i32>)
66+
#line 18 "pure2-requires-clauses.cpp2"
67+
T const v {0};
68+
5969
auto main() -> int{
6070
X<int,int> x {};
6171
std::cout << f<int,int>(2, 5);

regression-tests/test-results/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
cppfront compiler v0.2.1 Build 8829:1248
2+
cppfront compiler v0.2.1 Build 8831:1555
33
Copyright(c) Herb Sutter All rights reserved
44

55
SPDX-License-Identifier: CC-BY-NC-ND-4.0

source/build.info

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"8829:1248"
1+
"8831:1555"

source/cppfront.cpp

Lines changed: 47 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5317,6 +5317,51 @@ class cppfront
53175317
}
53185318
}
53195319

5320+
5321+
// Helper for declarations that can have requires-clauses
5322+
auto const emit_requires_clause = [&]() {
5323+
if (
5324+
n.requires_clause_expression
5325+
|| !function_requires_conditions.empty()
5326+
)
5327+
{
5328+
printer.print_extra("\n");
5329+
printer.ignore_alignment( true, n.position().colno + 4 );
5330+
if (printer.get_phase() == printer.phase1_type_defs_func_decls) {
5331+
// Workaround GCC 10 not supporting requires in forward declarations in some cases.
5332+
// See commit 5a0d77f8e297902c0b9712c5aafb6208cfa4c139.
5333+
if (n.is_object() || n.parent_is_type()) {
5334+
printer.print_extra("CPP2_REQUIRES_ (");
5335+
}
5336+
else {
5337+
printer.print_extra("CPP2_REQUIRES (");
5338+
}
5339+
}
5340+
else {
5341+
printer.print_extra("requires (");
5342+
}
5343+
5344+
if (n.requires_clause_expression) {
5345+
emit(*n.requires_clause_expression);
5346+
if (!function_requires_conditions.empty()) {
5347+
printer.print_extra(" && ");
5348+
}
5349+
}
5350+
5351+
if (!function_requires_conditions.empty()) {
5352+
printer.print_extra(function_requires_conditions.front());
5353+
for (auto it = std::cbegin(function_requires_conditions)+1; it != std::cend(function_requires_conditions); ++it) {
5354+
printer.print_extra(" && " + *it);
5355+
}
5356+
}
5357+
5358+
printer.print_extra(")");
5359+
function_requires_conditions = {};
5360+
printer.ignore_alignment( false );
5361+
}
5362+
};
5363+
5364+
53205365
// Namespace
53215366
if (n.is_namespace())
53225367
{
@@ -5626,48 +5671,6 @@ class cppfront
56265671
}
56275672
}
56285673

5629-
auto const emit_requires_clause = [&]() {
5630-
if (
5631-
n.requires_clause_expression
5632-
|| !function_requires_conditions.empty()
5633-
)
5634-
{
5635-
printer.print_extra("\n");
5636-
printer.ignore_alignment( true, n.position().colno + 4 );
5637-
if (printer.get_phase() == printer.phase1_type_defs_func_decls) {
5638-
// Workaround GCC 10 not supporting requires in forward declarations in some cases.
5639-
// See commit 5a0d77f8e297902c0b9712c5aafb6208cfa4c139.
5640-
if (n.parent_is_type()) {
5641-
printer.print_extra("CPP2_REQUIRES_MEMFN (");
5642-
}
5643-
else {
5644-
printer.print_extra("CPP2_REQUIRES (");
5645-
}
5646-
}
5647-
else {
5648-
printer.print_extra("requires (");
5649-
}
5650-
5651-
if (n.requires_clause_expression) {
5652-
emit(*n.requires_clause_expression);
5653-
if (!function_requires_conditions.empty()) {
5654-
printer.print_extra(" && ");
5655-
}
5656-
}
5657-
5658-
if (!function_requires_conditions.empty()) {
5659-
printer.print_extra(function_requires_conditions.front());
5660-
for (auto it = std::cbegin(function_requires_conditions)+1; it != std::cend(function_requires_conditions); ++it) {
5661-
printer.print_extra(" && " + *it);
5662-
}
5663-
}
5664-
5665-
printer.print_extra(")");
5666-
function_requires_conditions = {};
5667-
printer.ignore_alignment( false );
5668-
}
5669-
};
5670-
56715674
// If we're only emitting declarations, end the function declaration
56725675
if (printer.get_phase() == printer.phase1_type_defs_func_decls)
56735676
{
@@ -5841,6 +5844,8 @@ class cppfront
58415844
return;
58425845
}
58435846

5847+
emit_requires_clause();
5848+
58445849
if (
58455850
printer.get_phase() != printer.phase2_func_defs
58465851
&& n.parent_is_namespace()

0 commit comments

Comments
 (0)