Skip to content

Commit d2b821c

Browse files
committed
fix(parse): allow (to omit) semicolon after _unnamed-declaration_
1 parent 083c8a0 commit d2b821c

6 files changed

+98
-11
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
t: type = {
2+
operator[]: (this, f) = { }
3+
}
4+
5+
main: () -> int = {
6+
(x := t()) { x[:() -> _ = 0]; }
7+
(x := t()) { x[:() -> _ = 0;]; }
8+
9+
[[assert: !(:() = 0; is int) ]]
10+
11+
_ = :i32 = 0;
12+
[[assert: true]]
13+
14+
return :i32 = 0;
15+
}
16+
17+
x :== :i32 = 0;
18+
y: i32 = 0;

regression-tests/test-results/gcc-13/pure2-bugfix-for-unbraced-function-expression.cpp.execution

Whitespace-only changes.

regression-tests/test-results/gcc-13/pure2-bugfix-for-unbraced-function-expression.cpp.output

Whitespace-only changes.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
2+
#define CPP2_IMPORT_STD Yes
3+
4+
//=== Cpp2 type declarations ====================================================
5+
6+
7+
#include "cpp2util.h"
8+
9+
class t;
10+
11+
12+
//=== Cpp2 type definitions and function declarations ===========================
13+
14+
class t {
15+
public: auto operator[](auto const& f) const& -> void;
16+
17+
public: t() = default;
18+
public: t(t const&) = delete; /* No 'that' constructor, suppress copy */
19+
public: auto operator=(t const&) -> void = delete;
20+
#line 3 "pure2-bugfix-for-unbraced-function-expression.cpp2"
21+
};
22+
23+
[[nodiscard]] auto main() -> int;
24+
25+
26+
#line 17 "pure2-bugfix-for-unbraced-function-expression.cpp2"
27+
auto inline constexpr x = cpp2::i32{0};
28+
extern cpp2::i32 y;
29+
30+
//=== Cpp2 function definitions =================================================
31+
32+
33+
#line 2 "pure2-bugfix-for-unbraced-function-expression.cpp2"
34+
auto t::operator[](auto const& f) const& -> void{}
35+
36+
#line 5 "pure2-bugfix-for-unbraced-function-expression.cpp2"
37+
[[nodiscard]] auto main() -> int{
38+
{
39+
auto const& x = t();
40+
#line 6 "pure2-bugfix-for-unbraced-function-expression.cpp2"
41+
{cpp2::assert_in_bounds(x, []() -> auto { return 0; }); }
42+
}
43+
{
44+
auto const& x = t();
45+
#line 7 "pure2-bugfix-for-unbraced-function-expression.cpp2"
46+
{cpp2::assert_in_bounds(x, []() -> auto { return 0; }); }
47+
}
48+
49+
#line 9 "pure2-bugfix-for-unbraced-function-expression.cpp2"
50+
cpp2::Default.expects(!((cpp2::is<int>([]() -> void { 0; }))), "");
51+
52+
static_cast<void>(cpp2::i32{0});
53+
cpp2::Default.expects(true, "");
54+
55+
return cpp2::i32{0};
56+
}
57+
58+
#line 18 "pure2-bugfix-for-unbraced-function-expression.cpp2"
59+
cpp2::i32 y {0};
60+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pure2-bugfix-for-unbraced-function-expression.cpp2... ok (all Cpp2, passes safety checks)
2+

source/parse.h

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5335,6 +5335,7 @@ class parser
53355335
!decl->has_name()
53365336
&& "ICE: declaration should have been unnamed"
53375337
);
5338+
53385339
if (auto obj = std::get_if<declaration_node::an_object>(&decl->type)) {
53395340
if ((*obj)->is_wildcard()) {
53405341
error("an unnamed object at expression scope currently cannot have a deduced type (the reason to create an unnamed object is typically to create a temporary of a named type)");
@@ -5359,24 +5360,30 @@ class parser
53595360
next();
53605361
return {};
53615362
}
5362-
if (
5363-
peek(-1) && peek(-1)->type() != lexeme::RightBrace // it is short function syntax
5364-
&& curr().type() != lexeme::LeftParen // not imediatelly called
5365-
&& curr().type() != lexeme::RightParen // not as a last argument to function
5366-
&& curr().type() != lexeme::Comma // not as first or in-the-middle, function argument
5367-
) {
5368-
// this is a fix for a short function syntax that should have double semicolon used
5369-
// (check comment in expression_statement(bool semicolon_required))
5370-
// We simulate double semicolon by moving back to single semicolon.
5371-
next(-1);
5372-
}
53735363
}
53745364
else {
53755365
error("(temporary alpha limitation) an unnamed declaration at expression scope must be a function or an object");
53765366
next();
53775367
return {};
53785368
}
53795369

5370+
if (
5371+
peek(-1) && peek(-1)->type() != lexeme::RightBrace // it is not a braced function expression
5372+
&& curr().type() != lexeme::LeftParen // not imediatelly called
5373+
&& curr().type() != lexeme::RightParen // not as a last argument to function
5374+
&& curr().type() != lexeme::Comma // not as first or in-the-middle, function argument
5375+
&& curr().type() != lexeme::Greater // not as the last argument to template
5376+
&& curr().type() != lexeme::RightBracket // not as the last index argument
5377+
&& curr() != "is" // not as the argument to is
5378+
&& curr() != "as" // not as the argument to as
5379+
&& curr() != "do" // not as `for`'s `next`.
5380+
) {
5381+
// this is a fix for a short function syntax that should have double semicolon used
5382+
// (check comment in expression_statement(bool semicolon_required))
5383+
// We simulate double semicolon by moving back to single semicolon.
5384+
next(-1);
5385+
}
5386+
53805387
n->expr = std::move(decl);
53815388
return n;
53825389
}

0 commit comments

Comments
 (0)