mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Allow omitting = true for designated initializers of bitstruct bools.
This commit is contained in:
committed by
Christoffer Lerno
parent
0dc2f0e923
commit
41db9c43e5
@@ -441,6 +441,7 @@ param_path
|
|||||||
|
|
||||||
arg
|
arg
|
||||||
: param_path '=' expr
|
: param_path '=' expr
|
||||||
|
| param_path
|
||||||
| type
|
| type
|
||||||
| param_path '=' type
|
| param_path '=' type
|
||||||
| expr
|
| expr
|
||||||
|
|||||||
@@ -211,6 +211,7 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind)
|
|||||||
return expr_list_is_constant_eval(expr->cond_expr, eval_kind);
|
return expr_list_is_constant_eval(expr->cond_expr, eval_kind);
|
||||||
case EXPR_DESIGNATOR:
|
case EXPR_DESIGNATOR:
|
||||||
expr = expr->designator_expr.value;
|
expr = expr->designator_expr.value;
|
||||||
|
if (!expr) return true;
|
||||||
goto RETRY;
|
goto RETRY;
|
||||||
case EXPR_EXPR_BLOCK:
|
case EXPR_EXPR_BLOCK:
|
||||||
case EXPR_DECL:
|
case EXPR_DECL:
|
||||||
|
|||||||
@@ -465,7 +465,7 @@ Expr *parse_vasplat(ParseContext *c)
|
|||||||
/**
|
/**
|
||||||
* param_list ::= ('...' arg | arg (',' arg)*)?
|
* param_list ::= ('...' arg | arg (',' arg)*)?
|
||||||
*
|
*
|
||||||
* parameter ::= (param_path '=')? expr
|
* parameter ::= ((param_path '=')? expr) | param_path
|
||||||
*/
|
*/
|
||||||
bool parse_arg_list(ParseContext *c, Expr ***result, TokenType param_end, bool *splat, bool vasplat)
|
bool parse_arg_list(ParseContext *c, Expr ***result, TokenType param_end, bool *splat, bool vasplat)
|
||||||
{
|
{
|
||||||
@@ -483,11 +483,9 @@ bool parse_arg_list(ParseContext *c, Expr ***result, TokenType param_end, bool *
|
|||||||
expr = expr_new(EXPR_DESIGNATOR, start_span);
|
expr = expr_new(EXPR_DESIGNATOR, start_span);
|
||||||
expr->designator_expr.path = path;
|
expr->designator_expr.path = path;
|
||||||
|
|
||||||
// Expect the '=' after.
|
if (try_consume(c, TOKEN_EQ)) {
|
||||||
CONSUME_OR_RET(TOKEN_EQ, false);
|
ASSIGN_EXPR_OR_RET(expr->designator_expr.value, parse_expr(c), false);
|
||||||
|
}
|
||||||
// Now parse the rest
|
|
||||||
ASSIGN_EXPR_OR_RET(expr->designator_expr.value, parse_expr(c), false);
|
|
||||||
|
|
||||||
RANGE_EXTEND_PREV(expr);
|
RANGE_EXTEND_PREV(expr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1331,6 +1331,10 @@ INLINE bool sema_call_expand_arguments(SemaContext *context, CalledDecl *callee,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 8g. Set the parameter
|
// 8g. Set the parameter
|
||||||
|
if (!arg->designator_expr.value)
|
||||||
|
{
|
||||||
|
RETURN_SEMA_ERROR(arg, "Expected a value for this argument.");
|
||||||
|
}
|
||||||
actual_args[index] = arg->designator_expr.value;
|
actual_args[index] = arg->designator_expr.value;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -406,15 +406,24 @@ static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type
|
|||||||
bool optional = false;
|
bool optional = false;
|
||||||
Type *inner_type = NULL;
|
Type *inner_type = NULL;
|
||||||
bool is_inferred = type_is_inferred(flattened);
|
bool is_inferred = type_is_inferred(flattened);
|
||||||
|
int bitmember_count_without_value = 0;
|
||||||
VECEACH(init_expressions, i)
|
VECEACH(init_expressions, i)
|
||||||
{
|
{
|
||||||
Expr *expr = init_expressions[i];
|
Expr *expr = init_expressions[i];
|
||||||
Decl *member;
|
Decl *member;
|
||||||
Type *result = sema_expr_analyse_designator(context, original, expr, &max_index, &member);
|
Type *result = sema_expr_analyse_designator(context, original, expr, &max_index, &member);
|
||||||
if (!result) return false;
|
if (!result) return false;
|
||||||
|
bool is_bitmember = member && member->decl_kind == DECL_VAR && member->var.kind == VARDECL_BITMEMBER;
|
||||||
Expr *value = expr->designator_expr.value;
|
Expr *value = expr->designator_expr.value;
|
||||||
|
if (!value && is_bitmember && member->var.start_bit == member->var.end_bit && type_flatten(result) == type_bool) {
|
||||||
|
assert(is_bitstruct);
|
||||||
|
value = expr_new_const_bool(INVALID_SPAN, type_bool, true);
|
||||||
|
expr->designator_expr.value = value;
|
||||||
|
bitmember_count_without_value += 1;
|
||||||
|
}
|
||||||
|
if (!value) RETURN_SEMA_ERROR(expr, "This initializer needs a value.");
|
||||||
if (!sema_analyse_expr_rhs(context, result, value, true, NULL)) return false;
|
if (!sema_analyse_expr_rhs(context, result, value, true, NULL)) return false;
|
||||||
if (member && member->decl_kind == DECL_VAR && member->var.kind == VARDECL_BITMEMBER)
|
if (is_bitmember)
|
||||||
{
|
{
|
||||||
if (!sema_bit_assignment_check(context, value, member)) return false;
|
if (!sema_bit_assignment_check(context, value, member)) return false;
|
||||||
}
|
}
|
||||||
@@ -426,6 +435,9 @@ static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (bitmember_count_without_value != 0 && bitmember_count_without_value != vec_size(init_expressions)) {
|
||||||
|
RETURN_SEMA_ERROR(initializer, "Mixing the omission of initializers is not permitted.");
|
||||||
|
}
|
||||||
Type *type;
|
Type *type;
|
||||||
if (!is_structlike && is_inferred)
|
if (!is_structlike && is_inferred)
|
||||||
{
|
{
|
||||||
@@ -522,6 +534,7 @@ static void sema_create_const_initializer_from_designated_init(ConstInitializer
|
|||||||
Expr *expr = init_expressions[i];
|
Expr *expr = init_expressions[i];
|
||||||
DesignatorElement **path = expr->designator_expr.path;
|
DesignatorElement **path = expr->designator_expr.path;
|
||||||
Expr *value = expr->designator_expr.value;
|
Expr *value = expr->designator_expr.value;
|
||||||
|
assert(value);
|
||||||
sema_update_const_initializer_with_designator(const_init, path, path + vec_size(path), value);
|
sema_update_const_initializer_with_designator(const_init, path, path + vec_size(path), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,3 +60,45 @@ fn void test3()
|
|||||||
{
|
{
|
||||||
Foo abc = { .x = -4, .z = 0, .y = 8 }; // #error: would be truncated
|
Foo abc = { .x = -4, .z = 0, .y = 8 }; // #error: would be truncated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bitstruct Flags1 : int
|
||||||
|
{
|
||||||
|
bool a;
|
||||||
|
bool b;
|
||||||
|
bool c;
|
||||||
|
}
|
||||||
|
|
||||||
|
distinct Bool = bool;
|
||||||
|
|
||||||
|
bitstruct Flags2 : int
|
||||||
|
{
|
||||||
|
bool a : 0;
|
||||||
|
Bool b : 1;
|
||||||
|
int c : 2..3;
|
||||||
|
bool d : 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Flags2_Struct
|
||||||
|
{
|
||||||
|
bool a;
|
||||||
|
bool b;
|
||||||
|
int c;
|
||||||
|
bool d;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn void test4()
|
||||||
|
{
|
||||||
|
Flags1 flags1 = {.a, .b, .c};
|
||||||
|
flags1 = {.a};
|
||||||
|
flags1 = {.a = true, .b = true, .c = false};
|
||||||
|
flags1 = {.a, .b = true, .c = true}; // #error: Mixing the omission
|
||||||
|
Foo foo = { .x = 0, .z }; // #error: needs a value
|
||||||
|
|
||||||
|
Flags2 flags2 = {.b, .d};
|
||||||
|
flags2 = {.b, .c, .d}; // #error: needs a value
|
||||||
|
flags2 = {.a, .c = 1, .d}; // #error: Mixing the omission
|
||||||
|
|
||||||
|
Flags2_Struct flags2s;
|
||||||
|
flags2s = {.b, .c, .d}; // #error: needs a value
|
||||||
|
flags2s = {.a, .c = 1, .d}; // #error: needs a value
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user