Skip to content

Commit 36c5a9e

Browse files
committed
Make forward parameters of concrete type accept convertible/derived arguments
A `forward` parameter with a concrete type used to require an exact match, but can now accept arguments of convertible/derived types. The previous commit's change to `@struct` requires this change, so that code like this continues to work after the previous commit: data: @struct type = { name: std::string; city: std::string; } x: data = ( "Henry", "Memphis" ); // ok, uses conversions Added `@struct<noforward>` option to allow using `@struct` with GCC 10, which doesn't support `forward` parameters. And use that in cppfront's own sources, just so cppfront itself continues building under GCC10. (Someday we'll drop GCC 10 as a supported compiler, but for now it's still doing pretty well except for the won't-backport `requires`-clause bug...) Note that allowing the generated forwarding reference to bind to arguments of derived types was also suggested by @brevzin of @jumptrading in https://wg21.link/p2481 -- thanks Barry, for the Cpp2 suggestion and for the ISO C++ 'forward' parameter proposal paper! More examples: Base: @polymorphic_base type = { } // a Base type Derived: type = { this: Base; } // a Base-derived type b: Base = (); d: Derived = (); s: std::string = (); f:(forward _: Base ) = { } // forward a Base object g:(forward _: std::string) = { } // forward a std::string object main: () = { f( b ); // ok, b is-a Base f( d ); // ok, d is-a Base f( s ); // ERROR, s is-not-a Base g( s ); // ok, s is-a std::string g( "xyzzy" ); // ok, "xyzzy" is-convertible-to std::string g( b ); // ERROR, b is-not-a std::string }
1 parent 1590ea3 commit 36c5a9e

21 files changed

+522
-537
lines changed

include/cpp2regex.h2

+4-4
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ bview : <CharT> type == std::basic_string_view<CharT>;
4040

4141
// Structure for storing group information.
4242
//
43-
match_group: @struct <Iter> type =
43+
match_group: @struct<noforward> <Iter> type =
4444
{
4545
start: Iter = ();
4646
end: Iter = ();
@@ -50,7 +50,7 @@ match_group: @struct <Iter> type =
5050

5151
// Return value for every matcher.
5252
//
53-
match_return: @struct <Iter> type =
53+
match_return: @struct<noforward> <Iter> type =
5454
{
5555
matched: bool = false;
5656
pos: Iter = ();
@@ -119,15 +119,15 @@ match_context: <CharT, Iter, max_groups: int> type =
119119

120120
// End function that returns a valid match.
121121
//
122-
true_end_func: @struct type =
122+
true_end_func: @struct<noforward> type =
123123
{
124124
operator(): (in this, cur, inout ctx) ctx..pass(cur);
125125
}
126126

127127

128128
// Empty group reset function.
129129
//
130-
no_reset: @struct type =
130+
no_reset: @struct<noforward> type =
131131
{
132132
operator(): (this, inout _:) = {}
133133
}

regression-tests/test-results/clang-12-c++20/pure2-last-use.cpp.output

+18-30
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,18 @@ pure2-last-use.cpp2:273:30: note: to match this '<'
1010
pure2-last-use.cpp2:344:16: error: no template named 'move_only_function' in namespace 'std'
1111
public: std::move_only_function<int()> b;
1212
~~~~~^
13-
pure2-last-use.cpp2:348:94: error: no member named 'move_only_function' in namespace 'std'
14-
CPP2_REQUIRES_ (std::is_same_v<std::unique_ptr<int>, CPP2_TYPEOF(a_)> && std::is_same_v<std::move_only_function<int()>, CPP2_TYPEOF(b_)> && std::is_same_v<std::add_lvalue_reference_t<int>, CPP2_TYPEOF(c_)>) ;
15-
~~~~~^
13+
pure2-last-use.cpp2:348:161: error: no member named 'move_only_function' in namespace 'std'
14+
CPP2_REQUIRES_ (std::is_convertible_v<CPP2_TYPEOF(a_), std::add_const_t<std::unique_ptr<int>>&> && std::is_convertible_v<CPP2_TYPEOF(b_), std::add_const_t<std::move_only_function<int()>>&> && std::is_convertible_v<CPP2_TYPEOF(c_), std::add_const_t<std::add_lvalue_reference_t<int>>&>) ;
15+
~~~~~^
1616
../../../include/cpp2util.h:10008:43: note: expanded from macro 'CPP2_REQUIRES_'
1717
#define CPP2_REQUIRES_(...) requires (__VA_ARGS__)
1818
^~~~~~~~~~~
19+
pure2-last-use.cpp2:348:188: error: expected expression
20+
CPP2_REQUIRES_ (std::is_convertible_v<CPP2_TYPEOF(a_), std::add_const_t<std::unique_ptr<int>>&> && std::is_convertible_v<CPP2_TYPEOF(b_), std::add_const_t<std::move_only_function<int()>>&> && std::is_convertible_v<CPP2_TYPEOF(c_), std::add_const_t<std::add_lvalue_reference_t<int>>&>) ;
21+
^
22+
pure2-last-use.cpp2:348:193: error: use of address-of-label extension outside of a function body
23+
CPP2_REQUIRES_ (std::is_convertible_v<CPP2_TYPEOF(a_), std::add_const_t<std::unique_ptr<int>>&> && std::is_convertible_v<CPP2_TYPEOF(b_), std::add_const_t<std::move_only_function<int()>>&> && std::is_convertible_v<CPP2_TYPEOF(c_), std::add_const_t<std::add_lvalue_reference_t<int>>&>) ;
24+
^
1925
pure2-last-use.cpp2:773:69: error: no template named 'move_only_function' in namespace 'std'
2026
auto issue_888_1([[maybe_unused]] std::string unnamed_param_1, std::move_only_function<int([[maybe_unused]] cpp2::impl::in<int> unnamed_param_1)> size) -> void;
2127
~~~~~^
@@ -43,9 +49,15 @@ class issue_857_4 {
4349
pure2-last-use.cpp2:905:1: note: still within definition of 'issue_857_4' here
4450
namespace captures {
4551
^
46-
pure2-last-use.cpp2:279:178: error: no member named 'move_only_function' in namespace 'std'
47-
requires (std::is_same_v<std::add_pointer_t<int()>, CPP2_TYPEOF(f_)> && std::is_same_v<std::add_pointer_t<int(cpp2::impl::in<int> in_)>, CPP2_TYPEOF(g_)> && std::is_same_v<std::move_only_function<int()>, CPP2_TYPEOF(mf_)> && std::is_same_v<std::move_only_function<int(cpp2::impl::in<int> in_)>, CPP2_TYPEOF(mg_)>)
48-
~~~~~^
52+
pure2-last-use.cpp2:279:272: error: no member named 'move_only_function' in namespace 'std'
53+
requires (std::is_convertible_v<CPP2_TYPEOF(f_), std::add_const_t<std::add_pointer_t<int()>>&> && std::is_convertible_v<CPP2_TYPEOF(g_), std::add_const_t<std::add_pointer_t<int(cpp2::impl::in<int> in_)>>&> && std::is_convertible_v<CPP2_TYPEOF(mf_), std::add_const_t<std::move_only_function<int()>>&> && std::is_convertible_v<CPP2_TYPEOF(mg_), std::add_const_t<std::move_only_function<int(cpp2::impl::in<int> in_)>>&>)
54+
~~~~~^
55+
pure2-last-use.cpp2:279:299: error: expected expression
56+
requires (std::is_convertible_v<CPP2_TYPEOF(f_), std::add_const_t<std::add_pointer_t<int()>>&> && std::is_convertible_v<CPP2_TYPEOF(g_), std::add_const_t<std::add_pointer_t<int(cpp2::impl::in<int> in_)>>&> && std::is_convertible_v<CPP2_TYPEOF(mf_), std::add_const_t<std::move_only_function<int()>>&> && std::is_convertible_v<CPP2_TYPEOF(mg_), std::add_const_t<std::move_only_function<int(cpp2::impl::in<int> in_)>>&>)
57+
^
58+
pure2-last-use.cpp2:279:304: error: use of address-of-label extension outside of a function body
59+
requires (std::is_convertible_v<CPP2_TYPEOF(f_), std::add_const_t<std::add_pointer_t<int()>>&> && std::is_convertible_v<CPP2_TYPEOF(g_), std::add_const_t<std::add_pointer_t<int(cpp2::impl::in<int> in_)>>&> && std::is_convertible_v<CPP2_TYPEOF(mf_), std::add_const_t<std::move_only_function<int()>>&> && std::is_convertible_v<CPP2_TYPEOF(mg_), std::add_const_t<std::move_only_function<int(cpp2::impl::in<int> in_)>>&>)
60+
^
4961
pure2-last-use.cpp2:278:14: error: out-of-line definition of 'issue_857_4' does not match any declaration in 'issue_857_4'
5062
issue_857_4::issue_857_4(auto&& f_, auto&& g_, auto&& mf_, auto&& mg_)
5163
^~~~~~~~~~~
@@ -58,29 +70,5 @@ pure2-last-use.cpp2:282:272: error: member initializer 'mf' does not name a non-
5870
pure2-last-use.cpp2:283:272: error: member initializer 'mg' does not name a non-static data member or base class
5971
, mg{ CPP2_FORWARD(mg_) }{}
6072
^~~~~~~~~~~~~~~~~~~~~~~
61-
pure2-last-use.cpp2:332:8: error: incomplete type 'issue_857_5' named in nested name specifier
62-
auto issue_857_5::f() && -> void { f_copy(std::move(cpp2::move(*this).a)); }
63-
^~~~~~~~~~~~~
64-
pure2-last-use.cpp2:331:7: note: forward declaration of 'issue_857_5'
65-
class issue_857_5;
66-
^
67-
pure2-last-use.cpp2:334:3: error: incomplete type 'issue_857_5' named in nested name specifier
68-
issue_857_5::issue_857_5(auto&& a_)
69-
^~~~~~~~~~~~~
70-
pure2-last-use.cpp2:331:7: note: forward declaration of 'issue_857_5'
71-
class issue_857_5;
72-
^
73-
pure2-last-use.cpp2:334:3: error: incomplete type 'issue_857_5' named in nested name specifier
74-
issue_857_5::issue_857_5(auto&& a_)
75-
^~~~~~~~~~~~~
76-
pure2-last-use.cpp2:331:7: note: forward declaration of 'issue_857_5'
77-
class issue_857_5;
78-
^
79-
pure2-last-use.cpp2:338:6: error: incomplete type 'issue_857_5' named in nested name specifier
80-
auto issue_857_5::operator=(auto&& a_) -> issue_857_5&
81-
^~~~~~~~~~~~~
82-
pure2-last-use.cpp2:331:7: note: forward declaration of 'issue_857_5'
83-
class issue_857_5;
84-
^
8573
fatal error: too many errors emitted, stopping now [-ferror-limit=]
8674
20 errors generated.

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:46: error: expect
66
In file included from pure2-bugfix-for-requires-clause-in-forward-declaration.cpp:7:
77
../../../include/cpp2util.h:10005: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.
88
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:4:1: note: in expansion of macro ‘CPP2_REQUIRES_’
9-
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:3: error: no declaration matches ‘element::element(auto:98&&) requires is_same_v<std::__cxx11::string, typename std::remove_cv<typename std::remove_reference<decltype(element::__ct ::n)>::type>::type>’
9+
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:3: error: no declaration matches ‘element::element(auto:98&&) requires is_convertible_v<typename std::remove_cv<typename std::remove_reference<decltype(element::__ct ::n)>::type>::type, const std::__cxx11::add_const_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&>’
1010
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:5:11: note: candidates are: ‘element::element(const element&)’
1111
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:20: note: ‘template<class auto:96> element::element(auto:96&&)’
1212
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:1:7: note: ‘class element’ defined here
1313
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:5:78: error: expected unqualified-id before ‘{’ token
14-
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:8: error: no declaration matches ‘element& element::operator=(auto:99&&) requires is_same_v<std::__cxx11::string, typename std::remove_cv<typename std::remove_reference<decltype(element::operator=::n)>::type>::type>’
14+
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:8: error: no declaration matches ‘element& element::operator=(auto:99&&) requires is_convertible_v<typename std::remove_cv<typename std::remove_reference<decltype(element::operator=::n)>::type>::type, const std::__cxx11::add_const_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&>’
1515
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:6:16: note: candidates are: ‘void element::operator=(const element&)’
1616
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:16: note: ‘template<class auto:97> element& element::operator=(auto:97&&)’
1717
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:1:7: note: ‘class element’ defined here

regression-tests/test-results/gcc-10-c++20/pure2-bugfix-for-ufcs-arguments.cpp.output

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ pure2-bugfix-for-ufcs-arguments.cpp2:74:39: error: expected ‘;’ at end of me
66
In file included from pure2-bugfix-for-ufcs-arguments.cpp:7:
77
../../../include/cpp2util.h:10005: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.
88
pure2-bugfix-for-ufcs-arguments.cpp2:75:1: note: in expansion of macro ‘CPP2_REQUIRES_’
9-
pure2-bugfix-for-ufcs-arguments.cpp2:72:3: error: no declaration matches ‘B::B(auto:116&&) requires is_same_v<A, typename std::remove_cv<typename std::remove_reference<decltype(B::__ct ::m_)>::type>::type>’
9+
pure2-bugfix-for-ufcs-arguments.cpp2:72:3: error: no declaration matches ‘B::B(auto:116&&) requires is_convertible_v<typename std::remove_cv<typename std::remove_reference<decltype(B::__ct ::m_)>::type>::type, const add_const_t<A>&>’
1010
pure2-bugfix-for-ufcs-arguments.cpp2:68:7: note: candidates are: ‘constexpr B::B(B&&)’
1111
pure2-bugfix-for-ufcs-arguments.cpp2:68:7: note: ‘constexpr B::B(const B&)’
1212
pure2-bugfix-for-ufcs-arguments.cpp2:71:11: note: ‘template<class auto:104> B::B(auto:104&&)’
1313
pure2-bugfix-for-ufcs-arguments.cpp2:68:7: note: ‘class B’ defined here
1414
pure2-bugfix-for-ufcs-arguments.cpp2:74:81: error: expected unqualified-id before ‘{’ token
15-
pure2-bugfix-for-ufcs-arguments.cpp2:76:6: error: no declaration matches ‘B& B::operator=(auto:117&&) requires is_same_v<A, typename std::remove_cv<typename std::remove_reference<decltype(B::operator=::m_)>::type>::type>’
15+
pure2-bugfix-for-ufcs-arguments.cpp2:76:6: error: no declaration matches ‘B& B::operator=(auto:117&&) requires is_convertible_v<typename std::remove_cv<typename std::remove_reference<decltype(B::operator=::m_)>::type>::type, const add_const_t<A>&>’
1616
pure2-bugfix-for-ufcs-arguments.cpp2:68:7: note: candidates are: ‘constexpr B& B::operator=(B&&)’
1717
pure2-bugfix-for-ufcs-arguments.cpp2:68:7: note: ‘constexpr B& B::operator=(const B&)’
1818
pure2-bugfix-for-ufcs-arguments.cpp2:74:14: note: ‘template<class auto:105> B& B::operator=(auto:105&&)’

0 commit comments

Comments
 (0)