Skip to content
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 145 additions & 33 deletions src/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ void parse_array_init(var_t *var,
block_t *parent,
basic_block_t **bb,
bool emit_code);

void parse_array_compound_literal(var_t *var,
block_t *parent,
basic_block_t **bb,
bool emit_code);

label_t *find_label(char *name)
{
Expand Down Expand Up @@ -1283,6 +1286,71 @@ void parse_array_init(var_t *var,
}
}

void parse_array_compound_literal(var_t *var,
block_t *parent,
basic_block_t **bb,
bool emit_code)
{
int elem_size = var->type->size;
int count = 0;
var->array_size = 0;
var->init_val = 0;
if (!lex_peek(T_close_curly, NULL)) {
for (;;) {
read_expr(parent, bb);
read_ternary_operation(parent, bb);
var_t *value = opstack_pop();
if (count == 0)
var->init_val = value->init_val;
if (emit_code) {
var_t target = {0};
target.type = var->type;
target.ptr_level = 0;
var_t *store_val = resize_var(parent, bb, value, &target);
var_t *elem_addr =
compute_element_address(parent, bb, var, count, elem_size);
add_insn(parent, *bb, OP_write, NULL, elem_addr, store_val,
elem_size, NULL);
}
count++;
if (!lex_accept(T_comma))
break;
if (lex_peek(T_close_curly, NULL))
break;
}
}
lex_expect(T_close_curly);
var->array_size = count;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a new blank line.

static bool is_array_literal_temp(var_t *var)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_array_literal_temp is misleading. Refine it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you expand on what does misleading mean, that will be helpful, thank you

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you expand on what does misleading mean, that will be helpful, thank you

Check https://github.com/sysprog21/shecc/blob/master/CONTRIBUTING.md carefully.

{
return var && var->array_size > 0 && var->var_name[0] == '.';
}

static var_t *scalarize_array_literal(block_t *parent,
basic_block_t **bb,
var_t *array_var,
type_t *hint_type)
{
if (!is_array_literal_temp(array_var))
return array_var;

type_t *elem_type = hint_type ? hint_type : array_var->type;
if (!elem_type)
elem_type = TY_int;

int elem_size = elem_type->size;
if (elem_size <= 0)
elem_size = TY_int->size;

var_t *scalar = require_typed_var(parent, elem_type);
scalar->ptr_level = 0;
gen_name_to(scalar->var_name);
scalar->init_val = array_var->init_val;

add_insn(parent, *bb, OP_read, scalar, array_var, NULL, elem_size, NULL);
return scalar;
}
void read_inner_var_decl(var_t *vd, bool anon, bool is_param)
{
/* Preserve typedef pointer level - don't reset if already inherited */
Expand Down Expand Up @@ -1575,7 +1643,16 @@ void read_func_parameters(func_t *func, block_t *parent, basic_block_t **bb)
read_ternary_operation(parent, bb);

param = opstack_pop();

if (func) {
if (param_num < func->num_params) {
var_t *target = &func->param_defs[param_num];
if (!target->ptr_level && !target->array_size)
param = scalarize_array_literal(parent, bb, param,
target->type);
} else if (func->va_args) {
param = scalarize_array_literal(parent, bb, param, TY_int);
Copy link

@cubic-dev-ai cubic-dev-ai bot Oct 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing an array compound literal to a variadic function now yields the first element value instead of the temporary array’s address, so variadic calls like printf("%p", (int[]){1,2}); receive an integer instead of a pointer.

Prompt for AI agents
Address the following comment on src/parser.c at line 1653:

<comment>Passing an array compound literal to a variadic function now yields the first element value instead of the temporary array’s address, so variadic calls like `printf(&quot;%p&quot;, (int[]){1,2});` receive an integer instead of a pointer.</comment>

<file context>
@@ -1575,7 +1643,16 @@ void read_func_parameters(func_t *func, block_t *parent, basic_block_t **bb)
+                    param = scalarize_array_literal(parent, bb, param,
+                                                    target-&gt;type);
+            } else if (func-&gt;va_args) {
+                param = scalarize_array_literal(parent, bb, param, TY_int);
+            }
+        }
</file context>

✅ Addressed in d6b9fbf

}
}
/* Handle parameter type conversion for direct calls.
* Indirect calls currently don't provide function instance.
*/
Expand Down Expand Up @@ -2017,9 +2094,16 @@ void read_expr_operand(block_t *parent, basic_block_t **bb)
bool is_array_literal = (cast_ptr_level == -1);
if (is_array_literal)
cast_ptr_level = 0; /* Reset for normal processing */

bool consumed_close_brace = false;
/* Check if this is a pointer compound literal */
if (cast_ptr_level > 0) {
if (is_array_literal) {
compound_var->array_size = 0;
add_insn(parent, *bb, OP_allocat, compound_var, NULL, NULL, 0,
NULL);
parse_array_compound_literal(compound_var, parent, bb, true);
opstack_push(compound_var);
consumed_close_brace = true;
} else if (cast_ptr_level > 0) {
/* Pointer compound literal: (int*){&x} */
compound_var->ptr_level = cast_ptr_level;

Expand Down Expand Up @@ -2187,7 +2271,8 @@ void read_expr_operand(block_t *parent, basic_block_t **bb)
}
}

lex_expect(T_close_curly);
if (!consumed_close_brace)
lex_expect(T_close_curly);
} else {
/* Regular parenthesized expression */
read_expr(parent, bb);
Expand Down Expand Up @@ -2810,6 +2895,16 @@ void read_expr(block_t *parent, basic_block_t **bb)
continue; /* skip normal processing */
}

bool rs1_is_ptr_like = rs1 && (rs1->ptr_level || rs1->array_size);
bool rs2_is_ptr_like = rs2 && (rs2->ptr_level || rs2->array_size);

if (is_array_literal_temp(rs1) && !rs2_is_ptr_like)
Copy link

@cubic-dev-ai cubic-dev-ai bot Oct 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Array compound literals are scalarized before binary pointer arithmetic; e.g. (int[]){1,2} + 1 now produces the integer 2 instead of a pointer to the second element.

Prompt for AI agents
Address the following comment on src/parser.c at line 2901:

<comment>Array compound literals are scalarized before binary pointer arithmetic; e.g. `(int[]){1,2} + 1` now produces the integer `2` instead of a pointer to the second element.</comment>

<file context>
@@ -2810,6 +2895,16 @@ void read_expr(block_t *parent, basic_block_t **bb)
+        bool rs1_is_ptr_like = rs1 &amp;&amp; (rs1-&gt;ptr_level || rs1-&gt;array_size);
+        bool rs2_is_ptr_like = rs2 &amp;&amp; (rs2-&gt;ptr_level || rs2-&gt;array_size);
+
+        if (is_array_literal_temp(rs1) &amp;&amp; !rs2_is_ptr_like)
+            rs1 = scalarize_array_literal(parent, bb, rs1,
+                                          rs2 &amp;&amp; rs2-&gt;type ? rs2-&gt;type : NULL);
</file context>
Fix with Cubic

rs1 = scalarize_array_literal(parent, bb, rs1,
rs2 && rs2->type ? rs2->type : NULL);

if (is_array_literal_temp(rs2) && !rs1_is_ptr_like)
rs2 = scalarize_array_literal(parent, bb, rs2,
rs1 && rs1->type ? rs1->type : NULL);
/* Constant folding for binary operations */
if (rs1 && rs2 && rs1->init_val && !rs1->ptr_level && !rs1->is_global &&
rs2->init_val && !rs2->ptr_level && !rs2->is_global) {
Expand Down Expand Up @@ -3430,7 +3525,7 @@ void finalize_logical(opcode_t op,

void read_ternary_operation(block_t *parent, basic_block_t **bb)
{
var_t *vd, *rs1;
var_t *vd;

if (!lex_accept(T_question))
return;
Expand All @@ -3455,17 +3550,39 @@ void read_ternary_operation(block_t *parent, basic_block_t **bb)
abort();
}

rs1 = opstack_pop();
vd = require_var(parent);
gen_name_to(vd->var_name);
add_insn(parent, then_, OP_assign, vd, rs1, NULL, 0, NULL);
var_t *true_val = opstack_pop();

/* false branch */
read_expr(parent, &else_);
bb_connect(*bb, else_, ELSE);
var_t *false_val = opstack_pop();
bool true_array = is_array_literal_temp(true_val);
bool false_array = is_array_literal_temp(false_val);

if (true_array && !false_array)
true_val = scalarize_array_literal(parent, &then_, true_val,
false_val ? false_val->type : NULL);

rs1 = opstack_pop();
add_insn(parent, else_, OP_assign, vd, rs1, NULL, 0, NULL);
if (false_array && !true_array)
false_val = scalarize_array_literal(parent, &else_, false_val,
true_val ? true_val->type : NULL);

vd = require_var(parent);
gen_name_to(vd->var_name);
add_insn(parent, then_, OP_assign, vd, true_val, NULL, 0, NULL);
add_insn(parent, else_, OP_assign, vd, false_val, NULL, 0, NULL);

var_t *array_ref = NULL;
if (is_array_literal_temp(true_val))
array_ref = true_val;
else if (is_array_literal_temp(false_val))
array_ref = false_val;

if (array_ref) {
vd->array_size = array_ref->array_size;
vd->init_val = array_ref->init_val;
vd->type = array_ref->type;
}

vd->is_ternary_ret = true;
opstack_push(vd);
Expand Down Expand Up @@ -3614,6 +3731,11 @@ bool read_body_assignment(char *token,

read_expr(parent, bb);

var_t *rhs_val = opstack_pop();
if (!lvalue.ptr_level && !lvalue.is_reference)
rhs_val = scalarize_array_literal(parent, bb, rhs_val,
lvalue.type);
opstack_push(rhs_val);
vd = require_var(parent);
vd->init_val = increment_size;
gen_name_to(vd->var_name);
Expand Down Expand Up @@ -4356,27 +4478,12 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)

var_t *expr_result = opstack_pop();

/* Handle array compound literal to scalar assignment.
* When assigning array compound literals to scalar
* variables, use the first element value rather than array
* address.
*/
if (expr_result && expr_result->array_size > 0 &&
!var->ptr_level && var->array_size == 0 && var->type &&
(var->type->base_type == TYPE_int ||
var->type->base_type == TYPE_short) &&
expr_result->var_name[0] == '.') {
var_t *first_elem = require_var(parent);
first_elem->type = var->type;
gen_name_to(first_elem->var_name);

/* Extract first element from compound literal array */
add_insn(parent, bb, OP_read, first_elem, expr_result,
NULL, var->type->size, NULL);
expr_result = first_elem;
}
var_t *rhs = expr_result;
if (!var->ptr_level && var->array_size == 0)
rhs =
scalarize_array_literal(parent, bb, rhs, var->type);

rs1 = resize_var(parent, &bb, expr_result, var);
rs1 = resize_var(parent, &bb, rhs, var);
add_insn(parent, bb, OP_assign, var, rs1, NULL, 0, NULL);
}
}
Expand Down Expand Up @@ -4468,8 +4575,13 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
} else {
read_expr(parent, &bb);
read_ternary_operation(parent, &bb);
var_t *expr_result = opstack_pop();
var_t *rhs = expr_result;
if (!nv->ptr_level && nv->array_size == 0)
rhs = scalarize_array_literal(parent, bb, rhs,
nv->type);

rs1 = resize_var(parent, &bb, opstack_pop(), nv);
rs1 = resize_var(parent, &bb, rhs, nv);
add_insn(parent, bb, OP_assign, nv, rs1, NULL, 0, NULL);
}
}
Expand Down
Loading