Skip to content

Commit a9f4cbc

Browse files
committed
Fix array compound literal parsing to preserve pointer semantics
Implement proper array compound literal handling that emits element writes, counts initializers, and returns the temporary array pointer instead of collapsing to the first element. This restores correct pointer semantics and avoids discarding array literals during parsing. Struct and scalar compound literals are unchanged. The parser now tracks whether the closing brace was already consumed by the array helper to prevent double reads.
1 parent 3cbbdee commit a9f4cbc

File tree

1 file changed

+51
-4
lines changed

1 file changed

+51
-4
lines changed

src/parser.c

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ void parse_array_init(var_t *var,
4545
block_t *parent,
4646
basic_block_t **bb,
4747
bool emit_code);
48-
48+
void parse_array_compound_literal(var_t *var,
49+
block_t *parent,
50+
basic_block_t **bb,
51+
bool emit_code);
4952

5053
label_t *find_label(char *name)
5154
{
@@ -1330,6 +1333,42 @@ void parse_array_init(var_t *var,
13301333
}
13311334
}
13321335

1336+
void parse_array_compound_literal(var_t *var,
1337+
block_t *parent,
1338+
basic_block_t **bb,
1339+
bool emit_code)
1340+
{
1341+
int elem_size = var->type->size;
1342+
int count = 0;
1343+
var->array_size = 0;
1344+
var->init_val = 0;
1345+
if (!lex_peek(T_close_curly, NULL)) {
1346+
for (;;) {
1347+
read_expr(parent, bb);
1348+
read_ternary_operation(parent, bb);
1349+
var_t *value = opstack_pop();
1350+
if (count == 0)
1351+
var->init_val = value->init_val;
1352+
if (emit_code) {
1353+
var_t target = {0};
1354+
target.type = var->type;
1355+
target.ptr_level = 0;
1356+
var_t *store_val = resize_var(parent, bb, value, &target);
1357+
var_t *elem_addr = compute_element_address(
1358+
parent, bb, var, count, elem_size);
1359+
add_insn(parent, *bb, OP_write, NULL, elem_addr, store_val,
1360+
elem_size, NULL);
1361+
}
1362+
count++;
1363+
if (!lex_accept(T_comma))
1364+
break;
1365+
if (lex_peek(T_close_curly, NULL))
1366+
break;
1367+
}
1368+
}
1369+
lex_expect(T_close_curly);
1370+
var->array_size = count;
1371+
}
13331372
void read_inner_var_decl(var_t *vd, bool anon, bool is_param)
13341373
{
13351374
/* Preserve typedef pointer level - don't reset if already inherited */
@@ -2064,9 +2103,16 @@ void read_expr_operand(block_t *parent, basic_block_t **bb)
20642103
bool is_array_literal = (cast_ptr_level == -1);
20652104
if (is_array_literal)
20662105
cast_ptr_level = 0; /* Reset for normal processing */
2067-
2106+
bool consumed_close_brace = false;
20682107
/* Check if this is a pointer compound literal */
2069-
if (cast_ptr_level > 0) {
2108+
if (is_array_literal) {
2109+
compound_var->array_size = 0;
2110+
add_insn(parent, *bb, OP_allocat, compound_var, NULL, NULL, 0,
2111+
NULL);
2112+
parse_array_compound_literal(compound_var, parent, bb, true);
2113+
opstack_push(compound_var);
2114+
consumed_close_brace = true;
2115+
} else if (cast_ptr_level > 0) {
20702116
/* Pointer compound literal: (int*){&x} */
20712117
compound_var->ptr_level = cast_ptr_level;
20722118

@@ -2234,7 +2280,8 @@ void read_expr_operand(block_t *parent, basic_block_t **bb)
22342280
}
22352281
}
22362282

2237-
lex_expect(T_close_curly);
2283+
if (!consumed_close_brace)
2284+
lex_expect(T_close_curly);
22382285
} else {
22392286
/* Regular parenthesized expression */
22402287
read_expr(parent, bb);

0 commit comments

Comments
 (0)