Skip to content

Commit d2380e6

Browse files
committed
fix(parse): allow (to omit) semicolon after _unnamed-declaration_
1 parent 05ce45a commit d2380e6

6 files changed

+96
-11
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
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+
return :i32 = 0;
12+
}
13+
14+
x :== :i32 = 0;
15+
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: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
2+
#define CPP2_IMPORT_STD Yes
3+
4+
//=== Cpp2 type declarations ====================================================
5+
6+
7+
#include "cpp2util.h"
8+
9+
#line 1 "pure2-bugfix-for-unbraced-function-expression.cpp2"
10+
class t;
11+
#line 2 "pure2-bugfix-for-unbraced-function-expression.cpp2"
12+
13+
14+
//=== Cpp2 type definitions and function declarations ===========================
15+
16+
#line 1 "pure2-bugfix-for-unbraced-function-expression.cpp2"
17+
class t {
18+
#line 2 "pure2-bugfix-for-unbraced-function-expression.cpp2"
19+
public: auto operator[](auto const& f) const& -> void;
20+
public: t() = default;
21+
public: t(t const&) = delete; /* No 'that' constructor, suppress copy */
22+
public: auto operator=(t const&) -> void = delete;
23+
24+
#line 3 "pure2-bugfix-for-unbraced-function-expression.cpp2"
25+
};
26+
27+
[[nodiscard]] auto main() -> int;
28+
29+
#line 14 "pure2-bugfix-for-unbraced-function-expression.cpp2"
30+
auto inline constexpr x = cpp2::i32{0};
31+
extern cpp2::i32 y;
32+
33+
//=== Cpp2 function definitions =================================================
34+
35+
#line 1 "pure2-bugfix-for-unbraced-function-expression.cpp2"
36+
37+
#line 2 "pure2-bugfix-for-unbraced-function-expression.cpp2"
38+
auto t::operator[](auto const& f) const& -> void{}
39+
40+
#line 5 "pure2-bugfix-for-unbraced-function-expression.cpp2"
41+
[[nodiscard]] auto main() -> int{
42+
{
43+
auto const& x = t();
44+
#line 6 "pure2-bugfix-for-unbraced-function-expression.cpp2"
45+
{CPP2_ASSERT_IN_BOUNDS(x, []() mutable -> auto { return 0; }); }
46+
}
47+
{
48+
auto const& x = t();
49+
#line 7 "pure2-bugfix-for-unbraced-function-expression.cpp2"
50+
{CPP2_ASSERT_IN_BOUNDS(x, []() mutable -> auto { return 0; }); }
51+
}
52+
53+
#line 9 "pure2-bugfix-for-unbraced-function-expression.cpp2"
54+
cpp2::Default.expects(!((cpp2::is<int>([]() mutable -> void { 0; }))), "");
55+
56+
return cpp2::i32{0};
57+
}
58+
59+
#line 15 "pure2-bugfix-for-unbraced-function-expression.cpp2"
60+
cpp2::i32 y {0};
61+
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
@@ -5480,6 +5480,7 @@ class parser
54805480
!decl->has_name()
54815481
&& "ICE: declaration should have been unnamed"
54825482
);
5483+
54835484
if (auto obj = std::get_if<declaration_node::an_object>(&decl->type)) {
54845485
if ((*obj)->is_wildcard()) {
54855486
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)");
@@ -5504,24 +5505,30 @@ class parser
55045505
next();
55055506
return {};
55065507
}
5507-
if (
5508-
peek(-1) && peek(-1)->type() != lexeme::RightBrace // it is short function syntax
5509-
&& curr().type() != lexeme::LeftParen // not imediatelly called
5510-
&& curr().type() != lexeme::RightParen // not as a last argument to function
5511-
&& curr().type() != lexeme::Comma // not as first or in-the-middle, function argument
5512-
) {
5513-
// this is a fix for a short function syntax that should have double semicolon used
5514-
// (check comment in expression_statement(bool semicolon_required))
5515-
// We simulate double semicolon by moving back to single semicolon.
5516-
next(-1);
5517-
}
55185508
}
55195509
else {
55205510
error("(temporary alpha limitation) an unnamed declaration at expression scope must be a function or an object");
55215511
next();
55225512
return {};
55235513
}
55245514

5515+
if (
5516+
peek(-1) && peek(-1)->type() != lexeme::RightBrace // it is not a braced function expression
5517+
&& curr().type() != lexeme::LeftParen // not imediatelly called
5518+
&& curr().type() != lexeme::RightParen // not as a last argument to function
5519+
&& curr().type() != lexeme::Comma // not as first or in-the-middle, function argument
5520+
&& curr().type() != lexeme::Greater // not as the last argument to template
5521+
&& curr().type() != lexeme::RightBracket // not as the last index argument
5522+
&& curr() != "is" // not as the argument to is
5523+
&& curr() != "as" // not as the argument to as
5524+
&& curr() != "do" // not as `for`'s `next`.
5525+
) {
5526+
// this is a fix for a short function syntax that should have double semicolon used
5527+
// (check comment in expression_statement(bool semicolon_required))
5528+
// We simulate double semicolon by moving back to single semicolon.
5529+
next(-1);
5530+
}
5531+
55255532
n->expr = std::move(decl);
55265533
return n;
55275534
}

0 commit comments

Comments
 (0)