Skip to content

Commit 6eb3870

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 c4f778e commit 6eb3870

File tree

1 file changed

+99
-2
lines changed

1 file changed

+99
-2
lines changed

src/parser.c

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,6 +1206,12 @@ void read_inner_var_decl(var_t *vd, bool anon, bool is_param)
12061206
{
12071207
/* Preserve typedef pointer level - don't reset if already inherited */
12081208
vd->init_val = 0;
1209+
if (is_param) {
1210+
/* However, if the parsed variable is a function parameter,
1211+
* reset its pointer level to zero.
1212+
*/
1213+
vd->ptr_level = 0;
1214+
}
12091215

12101216
while (lex_accept(T_asterisk)) {
12111217
vd->ptr_level++;
@@ -4796,6 +4802,44 @@ void read_func_body(func_t *func)
47964802
bb_connect(body, func->exit, NEXT);
47974803
}
47984804

4805+
void print_ptr_level(int level)
4806+
{
4807+
while (level > 0) {
4808+
printf("*");
4809+
level--;
4810+
}
4811+
}
4812+
4813+
void print_func_decl(func_t *func, const char *prefix, bool newline)
4814+
{
4815+
if (prefix)
4816+
printf("%s", prefix);
4817+
printf("%s ", func->return_def.type->type_name);
4818+
print_ptr_level(func->return_def.ptr_level -
4819+
func->return_def.type->ptr_level);
4820+
printf("%s(", func->return_def.var_name);
4821+
4822+
for (int i = 0; i < func->num_params; i++) {
4823+
var_t *var = &func->param_defs[i];
4824+
4825+
printf("%s ", var->type->type_name);
4826+
4827+
print_ptr_level(var->ptr_level - var->type->ptr_level);
4828+
4829+
printf("%s", var->var_name);
4830+
4831+
if (i != func->num_params - 1)
4832+
printf(", ");
4833+
}
4834+
4835+
if (func->va_args)
4836+
printf(", ...");
4837+
printf(")");
4838+
4839+
if (newline)
4840+
printf("\n");
4841+
}
4842+
47994843
/* if first token is type */
48004844
void read_global_decl(block_t *block, bool is_const)
48014845
{
@@ -4808,12 +4852,65 @@ void read_global_decl(block_t *block, bool is_const)
48084852

48094853
if (lex_peek(T_open_bracket, NULL)) {
48104854
/* function */
4811-
func_t *func = add_func(var->var_name, false);
4855+
func_t *func = find_func(var->var_name);
4856+
func_t func_tmp;
4857+
bool check_decl = false;
4858+
4859+
if (func) {
4860+
memcpy(&func_tmp, func, sizeof(func_t));
4861+
check_decl = true;
4862+
} else
4863+
func = add_func(var->var_name, false);
4864+
48124865
memcpy(&func->return_def, var, sizeof(var_t));
48134866
block->locals.size--;
4814-
48154867
read_parameter_list_decl(func, 0);
48164868

4869+
if (check_decl) {
4870+
/* Validate whether the previous declaration and the current
4871+
* one differ.
4872+
*/
4873+
if ((func->return_def.type != func_tmp.return_def.type) ||
4874+
(func->return_def.ptr_level != func_tmp.return_def.ptr_level)) {
4875+
printf("Error: conflicting types for the function %s.\n",
4876+
func->return_def.var_name);
4877+
print_func_decl(&func_tmp, "before: ", true);
4878+
print_func_decl(func, "after: ", true);
4879+
abort();
4880+
}
4881+
4882+
if (func->num_params != func_tmp.num_params) {
4883+
printf(
4884+
"Error: confilcting number of arguments for the function "
4885+
"%s.\n",
4886+
func->return_def.var_name);
4887+
print_func_decl(&func_tmp, "before: ", true);
4888+
print_func_decl(func, "after: ", true);
4889+
abort();
4890+
}
4891+
4892+
for (int i = 0; i < func->num_params; i++) {
4893+
var_t *func_var = &func->param_defs[i];
4894+
var_t *func_tmp_var = &func_tmp.param_defs[i];
4895+
if ((func_var->type != func_tmp_var->type) ||
4896+
(func_var->ptr_level != func_tmp_var->ptr_level)) {
4897+
printf("Error: confilcting types for the function %s.\n",
4898+
func->return_def.var_name);
4899+
print_func_decl(&func_tmp, "before: ", true);
4900+
print_func_decl(func, "after: ", true);
4901+
abort();
4902+
}
4903+
}
4904+
4905+
if (func->va_args != func_tmp.va_args) {
4906+
printf("Error: conflicting types for the function %s.\n",
4907+
func->return_def.var_name);
4908+
print_func_decl(&func_tmp, "before: ", true);
4909+
print_func_decl(func, "after: ", true);
4910+
abort();
4911+
}
4912+
}
4913+
48174914
if (lex_peek(T_open_curly, NULL)) {
48184915
read_func_body(func);
48194916
return;

0 commit comments

Comments
 (0)