diff --git a/src/compiler/parse_expr.c b/src/compiler/parse_expr.c index fae520ed4..16086f13d 100644 --- a/src/compiler/parse_expr.c +++ b/src/compiler/parse_expr.c @@ -903,7 +903,7 @@ static Expr *parse_call_expr(ParseContext *c, Expr *left) int force_inline = -1; while (1) { - if (!parse_attribute(c, &attr)) return poisoned_expr; + if (!parse_attribute(c, &attr, true)) return poisoned_expr; if (!attr) break; AttributeType attr_type = attribute_by_name(attr->name); diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index 5fc576e0b..79f70d154 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -923,8 +923,9 @@ Decl *parse_var_decl(ParseContext *c) * attr_params ::= '(' attr_param (',' attr_param)* ')' * attr_param ::= const_expr | '&' '[' ']' || '[' ']' '='? */ -bool parse_attribute(ParseContext *c, Attr **attribute_ref) +bool parse_attribute(ParseContext *c, Attr **attribute_ref, bool expect_eos) { + SourceSpan start_span = c->prev_span; bool had_error; Path *path; if (!parse_path_prefix(c, &path)) return false; @@ -933,7 +934,15 @@ bool parse_attribute(ParseContext *c, Attr **attribute_ref) if (!tok_is(c, TOKEN_AT_IDENT) && !tok_is(c, TOKEN_AT_TYPE_IDENT)) { // Started a path? If so hard error - if (path) RETURN_SEMA_ERROR_HERE("Expected an attribute name."); + if (path) + { + if (expect_eos) + { + sema_error_at_after(start_span, "Expected a ';' here."); + return false; + } + RETURN_SEMA_ERROR_HERE("Expected an attribute name."); + } // Otherwise assume no attributes *attribute_ref = NULL; @@ -1033,7 +1042,7 @@ bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visib while (1) { Attr *attr; - if (!parse_attribute(c, &attr)) return false; + if (!parse_attribute(c, &attr, false)) return false; if (!attr) return true; Visibility parsed_visibility = -1; if (!attr->is_custom) diff --git a/src/compiler/parse_stmt.c b/src/compiler/parse_stmt.c index 9958870f5..13bf25105 100644 --- a/src/compiler/parse_stmt.c +++ b/src/compiler/parse_stmt.c @@ -1062,7 +1062,7 @@ static inline Ast *consume_eos(ParseContext *c, Ast *ast) { if (!try_consume(c, TOKEN_EOS)) { - sema_error_at_after(c->prev_span, "Expected ';'"); + sema_error_at_after(c->prev_span, "Expected a ';' here."); advance(c); return poisoned_ast; } diff --git a/src/compiler/parser_internal.h b/src/compiler/parser_internal.h index ac3a35561..e804205cb 100644 --- a/src/compiler/parser_internal.h +++ b/src/compiler/parser_internal.h @@ -47,7 +47,8 @@ Expr *parse_cond(ParseContext *c); Expr *parse_assert_expr(ParseContext *c); Ast* parse_compound_stmt(ParseContext *c); Ast *parse_short_body(ParseContext *c, TypeInfoId return_type, bool require_eos); -bool parse_attribute(ParseContext *c, Attr **attribute_ref); + +bool parse_attribute(ParseContext *c, Attr **attribute_ref, bool expect_eos); bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref); bool parse_switch_body(ParseContext *c, Ast ***cases, TokenType case_type, TokenType default_type); diff --git a/src/version.h b/src/version.h index d95154cb6..d52494b4f 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.4.511" \ No newline at end of file +#define COMPILER_VERSION "0.4.512" \ No newline at end of file diff --git a/test/test_suite/attributes/call_attribute_error_eos.c3 b/test/test_suite/attributes/call_attribute_error_eos.c3 new file mode 100644 index 000000000..4f610fde6 --- /dev/null +++ b/test/test_suite/attributes/call_attribute_error_eos.c3 @@ -0,0 +1,5 @@ +fn void main() +{ + call() // #error: ';' + rl::bar(); +} \ No newline at end of file