Skip to content

Commit 295a422

Browse files
committed
Enhance function parsing
Since the previous parser may incorrectly handle a function with a forward declaration before implementation, the code generator produces wrong instructions for a function because the frontend provides incorrect information. For example, consider the following code: int func(int *a); int func(int *a) { return *a; } int main() { /* ... */ } After parsing the forward declaration of 'func', it is added to the function list, and its parameter 'a' is recorded with the type 'int *'. When the function implementation is later parsed, the parser processes the declaration again, but the pointer level of 'a' is accumulated, causing the type of 'a' to become 'int **'. Therefore, to resolve the above issue and enhance the function parsing, these changes improve the parser to correctly handle functions with forward declarations, and report an error message if a later declaration differs from a previous one. Close #305
1 parent 9062977 commit 295a422

File tree

1 file changed

+108
-2
lines changed

1 file changed

+108
-2
lines changed

src/parser.c

Lines changed: 108 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,6 +1287,12 @@ void read_inner_var_decl(var_t *vd, bool anon, bool is_param)
12871287
{
12881288
/* Preserve typedef pointer level - don't reset if already inherited */
12891289
vd->init_val = 0;
1290+
if (is_param) {
1291+
/* However, if the parsed variable is a function parameter,
1292+
* reset its pointer level to zero.
1293+
*/
1294+
vd->ptr_level = 0;
1295+
}
12901296

12911297
while (lex_accept(T_asterisk)) {
12921298
vd->ptr_level++;
@@ -4917,6 +4923,49 @@ void read_func_body(func_t *func)
49174923
label_idx = 0;
49184924
}
49194925

4926+
void print_ptr_level(int level)
4927+
{
4928+
while (level > 0) {
4929+
printf("*");
4930+
level--;
4931+
}
4932+
}
4933+
4934+
void print_func_decl(func_t *func, const char *prefix, bool newline)
4935+
{
4936+
if (prefix)
4937+
printf("%s", prefix);
4938+
4939+
if (func->return_def.is_const_qualified)
4940+
printf("const ");
4941+
printf("%s ", func->return_def.type->type_name);
4942+
print_ptr_level(func->return_def.ptr_level -
4943+
func->return_def.type->ptr_level);
4944+
printf("%s(", func->return_def.var_name);
4945+
4946+
for (int i = 0; i < func->num_params; i++) {
4947+
var_t *var = &func->param_defs[i];
4948+
4949+
if (var->is_const_qualified)
4950+
printf("const ");
4951+
printf("%s ", var->type->type_name);
4952+
4953+
print_ptr_level(var->ptr_level - var->type->ptr_level);
4954+
4955+
printf("%s", var->var_name);
4956+
4957+
if (i != func->num_params - 1)
4958+
printf(", ");
4959+
}
4960+
4961+
if (func->va_args)
4962+
printf(", ...");
4963+
printf(")");
4964+
4965+
if (newline)
4966+
printf("\n");
4967+
}
4968+
49204969
/* if first token is type */
49214970
void read_global_decl(block_t *block, bool is_const)
49224971
{
@@ -4929,12 +4978,69 @@ void read_global_decl(block_t *block, bool is_const)
49294978

49304979
if (lex_peek(T_open_bracket, NULL)) {
49314980
/* function */
4932-
func_t *func = add_func(var->var_name, false);
4981+
func_t *func = find_func(var->var_name);
4982+
func_t func_tmp;
4983+
bool check_decl = false;
4984+
4985+
if (func) {
4986+
memcpy(&func_tmp, func, sizeof(func_t));
4987+
check_decl = true;
4988+
} else
4989+
func = add_func(var->var_name, false);
4990+
49334991
memcpy(&func->return_def, var, sizeof(var_t));
49344992
block->locals.size--;
4935-
49364993
read_parameter_list_decl(func, 0);
49374994

4995+
if (check_decl) {
4996+
/* Validate whether the previous declaration and the current
4997+
* one differ.
4998+
*/
4999+
if ((func->return_def.type != func_tmp.return_def.type) ||
5000+
(func->return_def.ptr_level != func_tmp.return_def.ptr_level) ||
5001+
(func->return_def.is_const_qualified !=
5002+
func_tmp.return_def.is_const_qualified)) {
5003+
printf("Error: conflicting types for the function %s.\n",
5004+
func->return_def.var_name);
5005+
print_func_decl(&func_tmp, "before: ", true);
5006+
print_func_decl(func, "after: ", true);
5007+
abort();
5008+
}
5009+
5010+
if (func->num_params != func_tmp.num_params) {
5011+
printf(
5012+
"Error: confilcting number of arguments for the function "
5013+
"%s.\n",
5014+
func->return_def.var_name);
5015+
print_func_decl(&func_tmp, "before: ", true);
5016+
print_func_decl(func, "after: ", true);
5017+
abort();
5018+
}
5019+
5020+
for (int i = 0; i < func->num_params; i++) {
5021+
var_t *func_var = &func->param_defs[i];
5022+
var_t *func_tmp_var = &func_tmp.param_defs[i];
5023+
if ((func_var->type != func_tmp_var->type) ||
5024+
(func_var->ptr_level != func_tmp_var->ptr_level) ||
5025+
(func_var->is_const_qualified !=
5026+
func_tmp_var->is_const_qualified)) {
5027+
printf("Error: confilcting types for the function %s.\n",
5028+
func->return_def.var_name);
5029+
print_func_decl(&func_tmp, "before: ", true);
5030+
print_func_decl(func, "after: ", true);
5031+
abort();
5032+
}
5033+
}
5034+
5035+
if (func->va_args != func_tmp.va_args) {
5036+
printf("Error: conflicting types for the function %s.\n",
5037+
func->return_def.var_name);
5038+
print_func_decl(&func_tmp, "before: ", true);
5039+
print_func_decl(func, "after: ", true);
5040+
abort();
5041+
}
5042+
}
5043+
49385044
if (lex_peek(T_open_curly, NULL)) {
49395045
read_func_body(func);
49405046
return;

0 commit comments

Comments
 (0)