Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix edge case with macro recursion #11

Merged
merged 1 commit into from
Dec 20, 2024

Conversation

MattX
Copy link
Contributor

@MattX MattX commented Dec 19, 2024

The code previously only prevented replacement of the innermost macro being replaced, but mutual recursion of macros was not handled quite according to the standard (to my understanding, and I checked with clang). This commit keeps a set of macros that have already been used in the current macro expansion, and refuses to expand them further.

I've also slightly refactored the code to reduce nesting and to make it easier to extend to function-like macros (which I'm interested in working on next).

The relevant part of the standard (which is not completely unambiguous) is:

6.10.3.4 Rescanning and further replacement

(...)Then, the resulting preprocessing token sequence is rescanned, along with all subsequent preprocessing tokens of the source file, for more macro names to replace.

If the name of the macro being replaced is found during this scan of the replacement list (not including the rest of the source file’s preprocessing tokens), it is not replaced. Furthermore, if any nested replacements encounter the name of the macro being replaced, it is not replaced. These nonreplaced macro name preprocessing tokens are no longer available for further replacement even if they are later (re)examined in contexts in which that macro name preprocessing token would otherwise have been replaced.

The code previously only prevented replacement of the innermost macro being replaced, but mutual recursion of macros was not handled quite according to the standard (to my understanding, also checked with clang). This commit keeps a set of macros that have already been used in the current macro expansion, and refuses to expand them further.

The relevant part of the standard is:

> Then, the resulting preprocessing token sequence is rescanned, along with all subsequent preprocessing tokens of the source file, for more macro names to replace.
>
> If the name of the macro being replaced is found during this scan of the replacement list (not including the rest of the source file’s preprocessing tokens), it is not replaced. Furthermore, if any nested replacements encounter the name of the macro being replaced, it is not replaced. These nonreplaced macro name preprocessing tokens are no longer available for further replacement even if they are later (re)examined in contexts in which that macro name preprocessing token would otherwise have been replaced.
@PhilippRados
Copy link
Owner

I'll look into it tomorrow. If you haven't yet make sure to check out the c-testsuite especially if you're planning to implement something more involved as function-like macros. This page tracks its progress: https://placid-eris-c19.notion.site/check-all-errors-from-c-testsuite-6f3fa2a3c24a4711b5e89f45354db540.
I'll also implement a proper Makefile for all test suites to make this easier and integrate it into CI.

@MattX
Copy link
Contributor Author

MattX commented Dec 20, 2024

Nice! Yeah, I saw the link on the readme and got c-testsuite to work (with a little fidgeting). I think none of the tests in there are affected by this specific issue / fix, but for function-like macros, that's definitely something I'll leverage.

@PhilippRados PhilippRados merged commit acba2fe into PhilippRados:master Dec 20, 2024
8 checks passed
@MattX MattX deleted the fix-macro-recursion branch December 23, 2024 14:46
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