diff --git a/regression-tests/pure2-bugfix-for-unbraced-function-expression.cpp2 b/regression-tests/pure2-bugfix-for-unbraced-function-expression.cpp2 new file mode 100644 index 0000000000..fd7b5e8690 --- /dev/null +++ b/regression-tests/pure2-bugfix-for-unbraced-function-expression.cpp2 @@ -0,0 +1,18 @@ +t: type = { + operator[]: (this, f) = { } +} + +main: () -> int = { + (x := t()) { x[:() -> _ = 0]; } + (x := t()) { x[:() -> _ = 0;]; } + + [[assert: !(:() = 0; is int) ]] + + _ = :i32 = 0; + [[assert: true]] + + return :i32 = 0; +} + +x :== :i32 = 0; +y: i32 = 0; diff --git a/regression-tests/test-results/gcc-13/pure2-bugfix-for-unbraced-function-expression.cpp.execution b/regression-tests/test-results/gcc-13/pure2-bugfix-for-unbraced-function-expression.cpp.execution new file mode 100644 index 0000000000..e69de29bb2 diff --git a/regression-tests/test-results/gcc-13/pure2-bugfix-for-unbraced-function-expression.cpp.output b/regression-tests/test-results/gcc-13/pure2-bugfix-for-unbraced-function-expression.cpp.output new file mode 100644 index 0000000000..e69de29bb2 diff --git a/regression-tests/test-results/pure2-bugfix-for-unbraced-function-expression.cpp b/regression-tests/test-results/pure2-bugfix-for-unbraced-function-expression.cpp new file mode 100644 index 0000000000..b90a98097e --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-unbraced-function-expression.cpp @@ -0,0 +1,60 @@ + +#define CPP2_IMPORT_STD Yes + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + +class t; + + +//=== Cpp2 type definitions and function declarations =========================== + +class t { + public: auto operator[](auto const& f) const& -> void; + + public: t() = default; + public: t(t const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(t const&) -> void = delete; +#line 3 "pure2-bugfix-for-unbraced-function-expression.cpp2" +}; + +[[nodiscard]] auto main() -> int; + + +#line 17 "pure2-bugfix-for-unbraced-function-expression.cpp2" +auto inline constexpr x = cpp2::i32{0}; +extern cpp2::i32 y; + +//=== Cpp2 function definitions ================================================= + + +#line 2 "pure2-bugfix-for-unbraced-function-expression.cpp2" + auto t::operator[](auto const& f) const& -> void{} + +#line 5 "pure2-bugfix-for-unbraced-function-expression.cpp2" +[[nodiscard]] auto main() -> int{ +{ +auto const& x = t(); +#line 6 "pure2-bugfix-for-unbraced-function-expression.cpp2" + {cpp2::assert_in_bounds(x, []() -> auto { return 0; }); } +} +{ +auto const& x = t(); +#line 7 "pure2-bugfix-for-unbraced-function-expression.cpp2" + {cpp2::assert_in_bounds(x, []() -> auto { return 0; }); } +} + +#line 9 "pure2-bugfix-for-unbraced-function-expression.cpp2" + cpp2::Default.expects(!((cpp2::is([]() -> void { 0; }))), ""); + + static_cast(cpp2::i32{0}); + cpp2::Default.expects(true, ""); + + return cpp2::i32{0}; +} + +#line 18 "pure2-bugfix-for-unbraced-function-expression.cpp2" +cpp2::i32 y {0}; + diff --git a/regression-tests/test-results/pure2-bugfix-for-unbraced-function-expression.cpp2.output b/regression-tests/test-results/pure2-bugfix-for-unbraced-function-expression.cpp2.output new file mode 100644 index 0000000000..5fb1a9712f --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-unbraced-function-expression.cpp2.output @@ -0,0 +1,2 @@ +pure2-bugfix-for-unbraced-function-expression.cpp2... ok (all Cpp2, passes safety checks) + diff --git a/source/parse.h b/source/parse.h index bedb265b65..18bec79276 100644 --- a/source/parse.h +++ b/source/parse.h @@ -5335,6 +5335,7 @@ class parser !decl->has_name() && "ICE: declaration should have been unnamed" ); + if (auto obj = std::get_if(&decl->type)) { if ((*obj)->is_wildcard()) { 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,17 +5360,6 @@ class parser next(); return {}; } - if ( - peek(-1) && peek(-1)->type() != lexeme::RightBrace // it is short function syntax - && curr().type() != lexeme::LeftParen // not imediatelly called - && curr().type() != lexeme::RightParen // not as a last argument to function - && curr().type() != lexeme::Comma // not as first or in-the-middle, function argument - ) { - // this is a fix for a short function syntax that should have double semicolon used - // (check comment in expression_statement(bool semicolon_required)) - // We simulate double semicolon by moving back to single semicolon. - next(-1); - } } else { error("(temporary alpha limitation) an unnamed declaration at expression scope must be a function or an object"); @@ -5377,6 +5367,23 @@ class parser return {}; } + if ( + peek(-1) && peek(-1)->type() != lexeme::RightBrace // it is not a braced function expression + && curr().type() != lexeme::LeftParen // not imediatelly called + && curr().type() != lexeme::RightParen // not as a last argument to function + && curr().type() != lexeme::Comma // not as first or in-the-middle, function argument + && curr().type() != lexeme::Greater // not as the last argument to template + && curr().type() != lexeme::RightBracket // not as the last index argument + && curr() != "is" // not as the argument to is + && curr() != "as" // not as the argument to as + && curr() != "do" // not as `for`'s `next`. + ) { + // this is a fix for a short function syntax that should have double semicolon used + // (check comment in expression_statement(bool semicolon_required)) + // We simulate double semicolon by moving back to single semicolon. + next(-1); + } + n->expr = std::move(decl); return n; }