Skip to content

Commit f9d9dee

Browse files
committed
fix(parse): recognize parameter named after contextual keyword
1 parent 52a2798 commit f9d9dee

8 files changed

+77
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
f: (virtual) = { }
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
t: type = {
2+
f: (in) -> _ = in;
3+
}
4+
g: (final) -> _ = final.first;
5+
h: (out, x) -> _ = out(x);
6+
main: () = {
7+
[[assert: t::f(0) == 0]]
8+
[[assert: g(std::make_pair(1, 2)) == 1]]
9+
[[assert: h(:(y) -> _ = y, 3) == 3]]
10+
}

regression-tests/test-results/gcc-13/pure2-bugfix-for-parameter-named-after-contextual-keyword.cpp.execution

Whitespace-only changes.

regression-tests/test-results/gcc-13/pure2-bugfix-for-parameter-named-after-contextual-keyword.cpp.output

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pure2-bugfix-for-parameter-named-after-contextual-keyword-error.cpp2...
2+
pure2-bugfix-for-parameter-named-after-contextual-keyword-error.cpp2(1,5): error: invalid parameter identifier (at 'virtual')
3+
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
2+
#define CPP2_USE_MODULES Yes
3+
4+
//=== Cpp2 type declarations ====================================================
5+
6+
7+
#include "cpp2util.h"
8+
9+
#line 1 "pure2-bugfix-for-parameter-named-after-contextual-keyword.cpp2"
10+
class t;
11+
12+
13+
//=== Cpp2 type definitions and function declarations ===========================
14+
15+
#line 1 "pure2-bugfix-for-parameter-named-after-contextual-keyword.cpp2"
16+
class t {
17+
public: [[nodiscard]] static auto f(auto const& in) -> auto;
18+
19+
public: t() = default;
20+
public: t(t const&) = delete; /* No 'that' constructor, suppress copy */
21+
public: auto operator=(t const&) -> void = delete;
22+
#line 3 "pure2-bugfix-for-parameter-named-after-contextual-keyword.cpp2"
23+
};
24+
[[nodiscard]] auto g(auto const& final) -> auto;
25+
[[nodiscard]] auto h(auto const& out, auto const& x) -> auto;
26+
auto main() -> int;
27+
28+
29+
//=== Cpp2 function definitions =================================================
30+
31+
32+
#line 2 "pure2-bugfix-for-parameter-named-after-contextual-keyword.cpp2"
33+
[[nodiscard]] auto t::f(auto const& in) -> auto { return in; }
34+
35+
[[nodiscard]] auto g(auto const& final) -> auto { return final.first; }
36+
[[nodiscard]] auto h(auto const& out, auto const& x) -> auto { return out(x); }
37+
auto main() -> int{
38+
cpp2::Default.expects(t::f(0)==0, "");
39+
cpp2::Default.expects(g(std::make_pair(1, 2))==1, "");
40+
cpp2::Default.expects(h([](auto const& y) -> auto { return y; }, 3)==3, "");
41+
}
42+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pure2-bugfix-for-parameter-named-after-contextual-keyword.cpp2... ok (all Cpp2, passes safety checks)
2+

source/parse.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5787,6 +5787,7 @@ class parser
57875787

57885788
// Handle optional this-specifier
57895789
//
5790+
auto this_specifier_pos = pos; // For backtracking if it's to be an identifier.
57905791
if (curr() == "implicit") {
57915792
n->mod = parameter_declaration_node::modifier::implicit;
57925793
next();
@@ -5806,6 +5807,7 @@ class parser
58065807

58075808
// Handle optional parameter-direction
58085809
//
5810+
auto parameter_direction_pos = pos; // For backtracking if it's to be an identifier.
58095811
if (auto dir = to_passing_style(curr());
58105812
dir != passing_style::invalid
58115813
)
@@ -5841,6 +5843,23 @@ class parser
58415843
next();
58425844
}
58435845

5846+
// Before the main declaration
5847+
// If we're not at an identifier, backtrack to a parsed one.
5848+
if (curr().type() != lexeme::Identifier && curr().type() != lexeme::Keyword) {
5849+
if (pos != parameter_direction_pos)
5850+
{
5851+
n->pass = passing_style::in;
5852+
pos = parameter_direction_pos;
5853+
}
5854+
else if (pos != this_specifier_pos)
5855+
{
5856+
auto mod = std::exchange(n->mod, parameter_declaration_node::modifier::none);
5857+
pos = this_specifier_pos;
5858+
if (mod == parameter_declaration_node::modifier::virtual_) {
5859+
error("invalid parameter identifier");
5860+
}
5861+
}
5862+
}
58445863
// Now the main declaration
58455864
//
58465865
if (!(n->declaration = declaration(false, true, is_template))) {

0 commit comments

Comments
 (0)