Skip to content

Commit b716dcb

Browse files
committed
fix(parse): recognize parameter named after contextual keyword
1 parent 454bd3c commit b716dcb

9 files changed

+82
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
f: (virtual) = { }
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+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
c++ (GCC) 13.1.1 20230429
2+
Copyright (C) 2023 Free Software Foundation, Inc.
3+
This is free software; see the source for copying conditions. There is NO
4+
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5+

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+
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+
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

+19
Original file line numberDiff line numberDiff line change
@@ -5413,6 +5413,7 @@ class parser
54135413

54145414
// Handle optional this-specifier
54155415
//
5416+
auto this_specifier_pos = pos; // For backtracking if it's to be an identifier.
54165417
if (curr() == "implicit") {
54175418
n->mod = parameter_declaration_node::modifier::implicit;
54185419
next();
@@ -5432,6 +5433,7 @@ class parser
54325433

54335434
// Handle optional parameter-direction
54345435
//
5436+
auto parameter_direction_pos = pos; // For backtracking if it's to be an identifier.
54355437
if (auto dir = to_passing_style(curr());
54365438
dir != passing_style::invalid
54375439
)
@@ -5467,6 +5469,23 @@ class parser
54675469
next();
54685470
}
54695471

5472+
// Before the main declaration
5473+
// If we're not at an identifier, backtrack to a parsed one.
5474+
if (curr().type() != lexeme::Identifier && curr().type() != lexeme::Keyword) {
5475+
if (pos != parameter_direction_pos)
5476+
{
5477+
n->pass = passing_style::in;
5478+
pos = parameter_direction_pos;
5479+
}
5480+
else if (pos != this_specifier_pos)
5481+
{
5482+
auto mod = std::exchange(n->mod, parameter_declaration_node::modifier::none);
5483+
pos = this_specifier_pos;
5484+
if (mod == parameter_declaration_node::modifier::virtual_) {
5485+
error("invalid parameter identifier");
5486+
}
5487+
}
5488+
}
54705489
// Now the main declaration
54715490
//
54725491
if (!(n->declaration = declaration(false, true, is_template))) {

0 commit comments

Comments
 (0)