@@ -130,9 +130,9 @@ var_t *opstack_pop(void)
130
130
131
131
void read_expr (block_t * parent , basic_block_t * * bb );
132
132
133
- int write_symbol (char * data )
133
+ int write_symbol (const char * data )
134
134
{
135
- int start_len = elf_data -> size ;
135
+ const int start_len = elf_data -> size ;
136
136
elf_write_str (elf_data , data );
137
137
elf_write_byte (elf_data , 0 );
138
138
return start_len ;
@@ -1191,11 +1191,19 @@ void parse_array_init(var_t *var,
1191
1191
1192
1192
void read_inner_var_decl (var_t * vd , bool anon , bool is_param )
1193
1193
{
1194
- vd -> init_val = 0 ;
1195
1194
/* Preserve typedef pointer level - don't reset if already inherited */
1195
+ vd -> init_val = 0 ;
1196
1196
1197
- while (lex_accept (T_asterisk ))
1197
+ while (lex_accept (T_asterisk )) {
1198
1198
vd -> ptr_level ++ ;
1199
+ /* Check for const after asterisk (e.g., int * const ptr).
1200
+ * For now, we just consume const qualifiers after pointer.
1201
+ * Full support would require tracking const-ness of the pointer
1202
+ * itself vs the pointed-to data separately.
1203
+ */
1204
+ while (lex_peek (T_const , NULL ))
1205
+ lex_accept (T_const );
1206
+ }
1199
1207
1200
1208
/* is it function pointer declaration? */
1201
1209
if (lex_accept (T_open_bracket )) {
@@ -1325,8 +1333,15 @@ void read_parameter_list_decl(func_t *func, bool anon)
1325
1333
lex_accept (T_comma );
1326
1334
}
1327
1335
1328
- while (lex_peek (T_identifier , NULL ) == 1 ) {
1329
- read_full_var_decl (& func -> param_defs [vn ++ ], anon , true);
1336
+ while (lex_peek (T_identifier , NULL ) == 1 || lex_peek (T_const , NULL )) {
1337
+ /* Check for const qualifier */
1338
+ bool is_const = false;
1339
+ if (lex_accept (T_const ))
1340
+ is_const = true;
1341
+
1342
+ read_full_var_decl (& func -> param_defs [vn ], anon , true);
1343
+ func -> param_defs [vn ].is_const_qualified = is_const ;
1344
+ vn ++ ;
1330
1345
lex_accept (T_comma );
1331
1346
}
1332
1347
func -> num_params = vn ;
@@ -1360,7 +1375,7 @@ void read_literal_param(block_t *parent, basic_block_t *bb)
1360
1375
combined_len += literal_len ;
1361
1376
}
1362
1377
1363
- int index = write_symbol (combined );
1378
+ const int index = write_symbol (combined );
1364
1379
1365
1380
var_t * vd = require_typed_ptr_var (parent , TY_char , true);
1366
1381
gen_name_to (vd -> var_name );
@@ -3808,6 +3823,7 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
3808
3823
type_t * type ;
3809
3824
var_t * vd , * rs1 , * rs2 , * var ;
3810
3825
opcode_t prefix_op = OP_generic ;
3826
+ bool is_const = false;
3811
3827
3812
3828
if (!bb )
3813
3829
printf ("Warning: unreachable code detected\n" );
@@ -4127,6 +4143,7 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
4127
4143
type = find_type (token , find_type_flag );
4128
4144
if (type ) {
4129
4145
var = require_typed_var (parent , type );
4146
+ var -> is_const_qualified = is_const ;
4130
4147
read_partial_var_decl (var , NULL );
4131
4148
add_insn (parent , bb , OP_allocat , var , NULL , NULL , 0 , NULL );
4132
4149
add_symbol (bb , var );
@@ -4332,14 +4349,22 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
4332
4349
error ("Unknown struct/union type" );
4333
4350
}
4334
4351
4352
+ /* Handle const qualifier for local variable declarations */
4353
+ if (lex_accept (T_const )) {
4354
+ is_const = true;
4355
+ /* After const, we expect a type */
4356
+ if (!lex_peek (T_identifier , token ))
4357
+ error ("Expected type after const" );
4358
+ }
4359
+
4335
4360
/* statement with prefix */
4336
- if (lex_accept (T_increment ))
4361
+ if (! is_const && lex_accept (T_increment ))
4337
4362
prefix_op = OP_add ;
4338
- else if (lex_accept (T_decrement ))
4363
+ else if (! is_const && lex_accept (T_decrement ))
4339
4364
prefix_op = OP_sub ;
4340
4365
/* must be an identifier or asterisk (for pointer dereference) */
4341
4366
bool has_asterisk = lex_peek (T_asterisk , NULL );
4342
- if (!lex_peek (T_identifier , token ) && !has_asterisk )
4367
+ if (!is_const && ! lex_peek (T_identifier , token ) && !has_asterisk )
4343
4368
error ("Unexpected token" );
4344
4369
4345
4370
/* handle macro parameter substitution for statements */
@@ -4411,6 +4436,7 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
4411
4436
4412
4437
if (type ) {
4413
4438
var = require_typed_var (parent , type );
4439
+ var -> is_const_qualified = is_const ;
4414
4440
read_full_var_decl (var , false, false);
4415
4441
add_insn (parent , bb , OP_allocat , var , NULL , NULL , 0 , NULL );
4416
4442
add_symbol (bb , var );
@@ -4729,10 +4755,11 @@ void read_func_body(func_t *func)
4729
4755
}
4730
4756
4731
4757
/* if first token is type */
4732
- void read_global_decl (block_t * block )
4758
+ void read_global_decl (block_t * block , bool is_const )
4733
4759
{
4734
4760
var_t * var = require_var (block );
4735
4761
var -> is_global = true;
4762
+ var -> is_const_qualified = is_const ;
4736
4763
4737
4764
/* new function, or variables under parent */
4738
4765
read_full_var_decl (var , false, false);
@@ -4818,6 +4845,7 @@ void initialize_struct_field(var_t *nv, var_t *v, int offset)
4818
4845
nv -> ptr_level = 0 ;
4819
4846
nv -> is_func = false;
4820
4847
nv -> is_global = false;
4848
+ nv -> is_const_qualified = false;
4821
4849
nv -> array_size = 0 ;
4822
4850
nv -> offset = offset ;
4823
4851
nv -> init_val = 0 ;
@@ -4832,6 +4860,11 @@ void read_global_statement(void)
4832
4860
{
4833
4861
char token [MAX_ID_LEN ];
4834
4862
block_t * block = GLOBAL_BLOCK ; /* global block */
4863
+ bool is_const = false;
4864
+
4865
+ /* Handle const qualifier */
4866
+ if (lex_accept (T_const ))
4867
+ is_const = true;
4835
4868
4836
4869
if (lex_accept (T_struct )) {
4837
4870
int i = 0 , size = 0 ;
@@ -4847,6 +4880,7 @@ void read_global_statement(void)
4847
4880
/* one or more declarators */
4848
4881
var_t * var = require_typed_var (block , decl_type );
4849
4882
var -> is_global = true; /* Global struct variable */
4883
+ var -> is_const_qualified = is_const ;
4850
4884
read_partial_var_decl (var , NULL );
4851
4885
add_insn (block , GLOBAL_FUNC -> bbs , OP_allocat , var , NULL , NULL , 0 ,
4852
4886
NULL );
@@ -5144,7 +5178,7 @@ void read_global_statement(void)
5144
5178
lex_expect (T_semicolon );
5145
5179
}
5146
5180
} else if (lex_peek (T_identifier , NULL )) {
5147
- read_global_decl (block );
5181
+ read_global_decl (block , is_const );
5148
5182
} else
5149
5183
error ("Syntax error in global statement" );
5150
5184
}
@@ -5155,6 +5189,7 @@ void parse_internal(void)
5155
5189
GLOBAL_FUNC = add_func ("" , true);
5156
5190
GLOBAL_FUNC -> stack_size = 4 ;
5157
5191
GLOBAL_FUNC -> bbs = arena_calloc (BB_ARENA , 1 , sizeof (basic_block_t ));
5192
+ GLOBAL_FUNC -> bbs -> belong_to = GLOBAL_FUNC ; /* Prevent nullptr deref in RA */
5158
5193
5159
5194
/* built-in types */
5160
5195
TY_void = add_named_type ("void" );
0 commit comments