Skip to content

Commit 65ca335

Browse files
committed
Support multiple declarators in struct member decl
This commit allows struct members to be declared with multiple variables on the same line, matching standard C syntax. For example: struct node { struct node *next, *prev; // Now supported int value; }; The fix handles comma-separated declarators by parsing additional variables after the first one, inheriting the base type while parsing pointer levels and array dimensions independently for each declarator.
1 parent e04a60d commit 65ca335

File tree

4 files changed

+74
-18
lines changed

4 files changed

+74
-18
lines changed

lib/c.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -576,8 +576,7 @@ int fputc(int c, FILE *stream)
576576
#define IS_CHUNK_GET_FREED(size) (size & CHUNK_SIZE_FREED_MASK)
577577

578578
typedef struct chunk {
579-
struct chunk *next;
580-
struct chunk *prev;
579+
struct chunk *next, *prev;
581580
int size;
582581
} chunk_t;
583582

src/defs.h

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,7 @@ typedef struct {
266266
typedef struct ref_block ref_block_t;
267267

268268
struct ref_block_list {
269-
ref_block_t *head;
270-
ref_block_t *tail;
269+
ref_block_t *head, *tail;
271270
};
272271

273272
typedef struct ref_block_list ref_block_list_t;
@@ -276,8 +275,7 @@ typedef struct insn insn_t;
276275

277276
typedef struct use_chain_node {
278277
insn_t *insn;
279-
struct use_chain_node *next;
280-
struct use_chain_node *prev;
278+
struct use_chain_node *next, *prev;
281279
} use_chain_t;
282280

283281
typedef struct var var_t;
@@ -306,8 +304,7 @@ struct var {
306304
int subscripts_idx;
307305
rename_t rename;
308306
ref_block_list_t ref_block_list; /* blocks which kill variable */
309-
use_chain_t *users_head;
310-
use_chain_t *users_tail;
307+
use_chain_t *users_head, *users_tail;
311308
struct insn *last_assign;
312309
int consumed;
313310
bool is_ternary_ret;
@@ -408,8 +405,7 @@ struct phi_operand {
408405
typedef struct phi_operand phi_operand_t;
409406

410407
struct insn {
411-
struct insn *next;
412-
struct insn *prev;
408+
struct insn *next, *prev;
413409
int idx;
414410
opcode_t opcode;
415411
var_t *rd;
@@ -423,13 +419,11 @@ struct insn {
423419
};
424420

425421
typedef struct {
426-
insn_t *head;
427-
insn_t *tail;
422+
insn_t *head, *tail;
428423
} insn_list_t;
429424

430425
typedef struct {
431-
ph2_ir_t *head;
432-
ph2_ir_t *tail;
426+
ph2_ir_t *head, *tail;
433427
} ph2_ir_list_t;
434428

435429
typedef enum { NEXT, ELSE, THEN } bb_connection_type_t;
@@ -448,8 +442,7 @@ struct symbol {
448442
typedef struct symbol symbol_t;
449443

450444
typedef struct {
451-
symbol_t *head;
452-
symbol_t *tail;
445+
symbol_t *head, *tail;
453446
} symbol_list_t;
454447

455448
struct basic_block {
@@ -519,8 +512,7 @@ struct func {
519512
};
520513

521514
typedef struct {
522-
func_t *head;
523-
func_t *tail;
515+
func_t *head, *tail;
524516
} func_list_t;
525517

526518
typedef struct {

src/parser.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2870,6 +2870,31 @@ void read_global_statement(void)
28702870
read_full_var_decl(v, 0, 1);
28712871
v->offset = size;
28722872
size += size_var(v);
2873+
2874+
/* Handle multiple variable declarations with same base type */
2875+
while (lex_accept(T_comma)) {
2876+
if (i >= MAX_FIELDS)
2877+
error("Too many struct fields");
2878+
2879+
var_t *nv = &type->fields[i++];
2880+
nv->type = v->type;
2881+
nv->var_name[0] = '\0';
2882+
nv->is_ptr = 0;
2883+
nv->is_func = false;
2884+
nv->is_global = false;
2885+
nv->array_size = 0;
2886+
nv->offset = 0;
2887+
nv->init_val = 0;
2888+
nv->liveness = 0;
2889+
nv->in_loop = 0;
2890+
nv->base = NULL;
2891+
nv->subscript = 0;
2892+
nv->subscripts_idx = 0;
2893+
read_inner_var_decl(nv, 0, 1);
2894+
nv->offset = size;
2895+
size += size_var(nv);
2896+
}
2897+
28732898
lex_expect(T_semicolon);
28742899
} while (!lex_accept(T_close_curly));
28752900

@@ -2922,6 +2947,32 @@ void read_global_statement(void)
29222947
read_full_var_decl(v, 0, 1);
29232948
v->offset = size;
29242949
size += size_var(v);
2950+
2951+
/* Handle multiple variable declarations with same base type
2952+
*/
2953+
while (lex_accept(T_comma)) {
2954+
if (i >= MAX_FIELDS)
2955+
error("Too many struct fields");
2956+
2957+
var_t *nv = &type->fields[i++];
2958+
nv->type = v->type;
2959+
nv->var_name[0] = '\0';
2960+
nv->is_ptr = 0;
2961+
nv->is_func = false;
2962+
nv->is_global = false;
2963+
nv->array_size = 0;
2964+
nv->offset = 0;
2965+
nv->init_val = 0;
2966+
nv->liveness = 0;
2967+
nv->in_loop = 0;
2968+
nv->base = NULL;
2969+
nv->subscript = 0;
2970+
nv->subscripts_idx = 0;
2971+
read_inner_var_decl(nv, 0, 1);
2972+
nv->offset = size;
2973+
size += size_var(nv);
2974+
}
2975+
29252976
lex_expect(T_semicolon);
29262977
} while (!lex_accept(T_close_curly));
29272978
}

tests/driver.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,20 @@ int main() {
423423
}
424424
EOF
425425

426+
# struct with multiple pointer declarations in same line
427+
try_ 42 << EOF
428+
typedef struct chunk {
429+
struct chunk *next, *prev;
430+
int size;
431+
} chunk_t;
432+
433+
int main() {
434+
chunk_t c;
435+
c.size = 42;
436+
return c.size;
437+
}
438+
EOF
439+
426440
# arrays
427441
try_ 12 << EOF
428442
int nth_of(int *a, int i) {

0 commit comments

Comments
 (0)