Incorrect parsing of call attributes #2144.

This commit is contained in:
Christoffer Lerno
2025-05-17 22:10:03 +02:00
parent 23897bc9a4
commit 082457c5fb
3 changed files with 28 additions and 10 deletions

View File

@@ -30,6 +30,7 @@
- Using a non-const as the end range for a bitstruct would trigger an assert. - Using a non-const as the end range for a bitstruct would trigger an assert.
- Incorrect parsing of ad hoc generic types, like `Foo{int}****` #2140. - Incorrect parsing of ad hoc generic types, like `Foo{int}****` #2140.
- $define did not correctly handle generic types #2140. - $define did not correctly handle generic types #2140.
- Incorrect parsing of call attributes #2144.
### Stdlib changes ### Stdlib changes
- Added `String.quick_ztr` and `String.is_zstr` - Added `String.quick_ztr` and `String.is_zstr`

View File

@@ -982,21 +982,19 @@ static Expr *parse_call_expr(ParseContext *c, Expr *left)
PRINT_ERROR_HERE("Expected a macro body here."); PRINT_ERROR_HERE("Expected a macro body here.");
return poisoned_expr; return poisoned_expr;
} }
Attr *attr;
int force_inline = -1; int force_inline = -1;
while (1) while (tok_is(c, TOKEN_AT_IDENT))
{ {
if (!parse_attribute(c, &attr, true)) return poisoned_expr; AttributeType attr_type = attribute_by_name(symstr(c));
if (!attr) break; advance(c);
AttributeType attr_type = attribute_by_name(attr->name);
int new_inline = attr_type == ATTRIBUTE_INLINE; int new_inline = attr_type == ATTRIBUTE_INLINE;
switch (attr_type) switch (attr_type)
{ {
case ATTRIBUTE_PURE: case ATTRIBUTE_PURE:
if (call->call_expr.attr_pure) if (call->call_expr.attr_pure)
{ {
RETURN_PRINT_ERROR_AT(poisoned_expr, attr, "Repeat of the same attribute is not allowed."); PRINT_ERROR_LAST("Repeat of the same attribute is not allowed.");
return poisoned_expr;
} }
call->call_expr.attr_pure = true; call->call_expr.attr_pure = true;
continue; continue;
@@ -1004,18 +1002,26 @@ static Expr *parse_call_expr(ParseContext *c, Expr *left)
case ATTRIBUTE_NOINLINE: case ATTRIBUTE_NOINLINE:
if (force_inline == new_inline) if (force_inline == new_inline)
{ {
RETURN_PRINT_ERROR_AT(poisoned_expr, attr, "Repeat of the same attribute is not allowed."); PRINT_ERROR_LAST("Repeat of the same attribute is not allowed.");
return poisoned_expr;
} }
if (force_inline != -1) if (force_inline != -1)
{ {
RETURN_PRINT_ERROR_AT(poisoned_expr, attr, "@inline and @noinline cannot be combined"); PRINT_ERROR_LAST("@inline and @noinline cannot be combined");
return poisoned_expr;
} }
force_inline = new_inline; force_inline = new_inline;
continue; continue;
default: default:
RETURN_PRINT_ERROR_AT(poisoned_expr, attr, "Only '@pure', '@inline' and '@noinline' are valid attributes for calls."); PRINT_ERROR_LAST("Only '@pure', '@inline' and '@noinline' are valid attributes for calls.");
return poisoned_expr;
} }
} }
if (tok_is(c, TOKEN_AT_TYPE_IDENT))
{
PRINT_ERROR_HERE("User defined attributes are not allowed, only @pure, @inline and @noinline.");
return poisoned_expr;
}
if (force_inline != -1) if (force_inline != -1)
{ {
call->call_expr.attr_force_inline = force_inline == 1; call->call_expr.attr_force_inline = force_inline == 1;

View File

@@ -0,0 +1,11 @@
module test;
fn VoidFn foo()
{
return fn void() {};
}
fn void main()
{
foo() @inline ();
foo() @inline (foo()); // #error: This argument would exceed the number of parameters
}