Allow (Foo) { 1, 2 } syntax for compound literals.

This commit is contained in:
Christoffer Lerno
2025-02-14 12:49:09 +01:00
parent e0cfe56121
commit 7ca70b20be
7 changed files with 1352 additions and 15 deletions

View File

@@ -430,6 +430,7 @@
- Add `$member.get(value)` to replace `value.$eval($member.nameof)`
- Improve the error message when the compilation does not produce any files #1390.
- Add `fmod` implementation for nolibc.
- Allow `(Foo) { 1, 2 }` syntax for compound literals.
### Fixes

File diff suppressed because it is too large Load Diff

View File

@@ -7,6 +7,7 @@
typedef Expr *(*ParseFn)(ParseContext *context, Expr *);
static Expr *parse_subscript_expr(ParseContext *c, Expr *left);
static Expr *parse_initializer_list(ParseContext *c, Expr *left);
typedef struct
{
@@ -840,11 +841,6 @@ static Expr *parse_grouping_expr(ParseContext *c, Expr *left)
case EXPR_TYPEINFO:
{
TypeInfo *info = expr->type_expr;
if (tok_is(c, TOKEN_LBRACE) && info->resolve_status != RESOLVE_DONE)
{
PRINT_ERROR_HERE("Unexpected start of a block '{' here. If you intended a compound literal, remove the () around the type.");
return poisoned_expr;
}
// Create a cast expr
if (rules[c->tok].prefix)
{
@@ -883,7 +879,7 @@ static Expr *parse_grouping_expr(ParseContext *c, Expr *left)
* ;
*
*/
Expr *parse_initializer_list(ParseContext *c, Expr *left)
static Expr *parse_initializer_list(ParseContext *c, Expr *left)
{
ASSERT(!left && "Unexpected left hand side");
Expr *initializer_list = EXPR_NEW_TOKEN(EXPR_INITIALIZER_LIST);

View File

@@ -5651,6 +5651,12 @@ static inline bool sema_expr_analyse_cast(SemaContext *context, Expr *expr, bool
if (invalid_cast_ref) *invalid_cast_ref = false;
Expr *inner = exprptr(expr->cast_expr.expr);
TypeInfo *type_info = type_infoptr(expr->cast_expr.type_info);
if (inner->expr_kind == EXPR_INITIALIZER_LIST)
{
expr->expr_kind = EXPR_COMPOUND_LITERAL;
expr->expr_compound_literal = (ExprCompoundLiteral) { .initializer = inner, .type_info = type_info };
return sema_expr_analyse_compound_literal(context, expr);
}
bool success = sema_resolve_type_info(context, type_info, RESOLVE_TYPE_ALLOW_INFER);
if (!sema_analyse_expr(context, inner) || !success) return false;
@@ -9027,8 +9033,7 @@ static inline bool sema_expr_analyse_generic_ident(SemaContext *context, Expr *e
Expr *parent = exprptr(expr->generic_ident_expr.parent);
if (parent->expr_kind != EXPR_UNRESOLVED_IDENTIFIER)
{
SEMA_ERROR(parent, "Expected an identifier to parameterize.");
return false;
RETURN_SEMA_ERROR(parent, "Expected an identifier to parameterize.");
}
Decl *symbol = sema_analyse_parameterized_identifier(context, parent->unresolved_ident_expr.path,
parent->unresolved_ident_expr.ident, parent->span,

View File

@@ -836,8 +836,7 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex
expr_rewrite_to_const_zero(expr, to);
return true;
}
SEMA_ERROR(expr, "Pointers cannot be initialized using an initializer list, instead you need to take the address of an array.");
return false;
RETURN_SEMA_ERROR(expr, "Pointers cannot be initialized using an initializer list, instead you need to take the address of an array.");
case TYPE_VOID:
case TYPE_POISONED:
case TYPE_FUNC_RAW:
@@ -845,7 +844,7 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex
case TYPE_OPTIONAL:
case TYPE_TYPEINFO:
case TYPE_MEMBER:
break;
RETURN_SEMA_ERROR(expr, "You cannot use %s with an initializer list.", type_quoted_error_string(to));
default:
if (is_zero_init)
{
@@ -855,8 +854,7 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex
}
break;
}
SEMA_ERROR(expr, "'%s' cannot use compound literal initialization, did you intend to use a cast?", type_to_error_string(to));
return false;
RETURN_SEMA_ERROR(expr, "You cannot use %s with a non-empty initializer list.", type_quoted_error_string(to));
}
void const_init_rewrite_to_value(ConstInitializer *const_init, Expr *value)

View File

@@ -2,7 +2,7 @@ struct Foo { int a; }
fn void test2()
{
int x = int{ 32 }; // #error: 'int' cannot use compound literal initialization, did you intend to use a cast
int x = int{ 32 }; // #error: 'int' with a non-empty initializer list
}
fn void test3()

View File

@@ -2,5 +2,5 @@ module testing;
fn void main()
{
(void){}; // #error: You cannot cast 'untyped_list' to 'void'
(void){}; // #error: You cannot use 'void' with an initializer list
}