Skip to content

Conversation

DrXiao
Copy link
Collaborator

@DrXiao DrXiao commented Oct 4, 2025

Since the previous parser incorrectly handles a function with a forward declaration before implementation, the code generator may produce wrong instructions due to the incorrect information provided by the frontend.

For example, consider the following example:

int func(char *a);

int func(char *a)
{
    return *a;
}

int main(void)
{
    char a = 10;
    return func(&a);
}

After parsing the forward declaration of func, it is added to the function list, and its parameter a is recorded with the type char *. 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 char **.

This can be observed when using shecc to compile and output the IRs:

==<START OF INSN DUMP>==
def int @func(char** %a) {
	%.t0 = (%a), 4
	ret %.t0
}
...

Additionally, if a function with a forward declaration differs from the later declaration, shecc still continues to parse the source instead of reporting an error:

void func(void);

int **func(void)
{
    return 3;
}

int main()
{
    func();
    return 0;
}

In the above case, shecc considers func to be a function of type int **(void).


Therefore, the proposed changes enhance the implementation of the parser to resolve the above issues.

  • Reset the pointer level of a parsed variable if it is a function parameter.
  • When parsing the function that already exists in the function list, validate that its return type and the data types of all parameters match the previous declaration.

Summary by cubic

Fix function parsing for forward-declared functions to keep parameter types correct and to error on conflicting declarations, preventing incorrect IR generation.

  • Bug Fixes
    • Reset parameter pointer level during parsing to stop pointer accumulation (e.g., char* incorrectly becoming char**).
    • Validate redeclarations against the first declaration: return type and pointer level, parameter count and types, and variadic flag. Abort with clear “before/after” signatures on mismatch.
    • Added tests covering the normal case and conflicts (return type, parameter count/type, variadic).

@DrXiao
Copy link
Collaborator Author

DrXiao commented Oct 4, 2025

For the second example, the improved shecc will report an error message as follows due to conflicting types for func:

$ qemu-arm out/shecc-stage2.elf --no-libc -o example2 example2.c
Error: conflicting types for the function func.
before: void func()
after: int **func()

Other examples:

Error: confilcting number of arguments for the function func.
before: void func(void *a)
after: void func(void *a, int x)
Error: confilcting types for the function func.
before: void func(void *a, char x)
after: void func(void *a, int x)
Error: conflicting types for the function func.
before: void func(void *a)
after: void func(void *a, ...)

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 2 files

Prompt for AI agents (all 1 issues)

Understand the root cause of the following 1 issues and fix them.


<file name="tests/driver.sh">

<violation number="1" location="tests/driver.sh:5590">
The new compile-error tests return values from `void`/pointer functions (e.g., `return 3;`), so they will always trigger diagnostics unrelated to the prototype mismatch, meaning the tests won’t catch the regression they target.</violation>
</file>

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

@DrXiao
Copy link
Collaborator Author

DrXiao commented Oct 4, 2025

Add handling for const keyword:

Error: confilcting types for the function func.
before: void func(int *a, char x)
after: void func(const int *a, char x)
Error: conflicting types for the function func.
before: void *func(int *a, char x)
after: const void *func(int *a, char x)

DrXiao added 2 commits October 4, 2025 18:58
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 sysprog21#305
Since the previous commit enhanced function parsing so that the parser
reports an error if a later function declaration differs from a previous
one, this commit adds some test cases to the test suite to validate this
functionality.
@jserv jserv merged commit 4da0b6e into sysprog21:master Oct 4, 2025
6 checks passed
@jserv
Copy link
Collaborator

jserv commented Oct 4, 2025

Thank @DrXiao for contributing!

@DrXiao DrXiao deleted the fix-forward-decl branch October 4, 2025 11:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants