-
Notifications
You must be signed in to change notification settings - Fork 577
op.c: Make ifdef structure of argument to S_op_clear_gv() less objectionable to syntax parsers #23255
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
base: blead
Are you sure you want to change the base?
Conversation
…ionable to syntax parsers The prior structure of this syntax made it look to tree-sitter-based parsers as if two separate functions were being defined, though only the second of which was ever finished. This resulted in the entire rest of the file appearing to be nested inside the first function, meaning no top-level function analysis was performed on them. This has various knock-on effects on code analysis in tooling such as editors or browsers. The fix for it moves the `#ifdef` syntax inside the argument parentheses to ensure that only one function appears to be created, so the entire rest of the file is parsed as normal.
CPP #ifdefs, inside func call decls or inside a CPP macro invoke call site. This blows up most if not all MSVCs versions ever published, and is super not portable, considering P5P never prohibited ( aka support terminated) commercial Unix OS closed source C compilers, which can get as quirky/strange, just like MSVC gets quirky very easily. My IDEs/syntax high lighters don't freak at those double prototypes. The first line is just a weird pre-declaration of the function with a missing Alternative, 1, just make a one off union type, or 2, declare a void * and cast correctly, in macros, at all caller sites and the callee body site. Alt 1 is noisy and verbose in callers to do all the union struct formalities, unless macros are used. Or heck, just make a CPP macro token, that resolves to string If no-threads AV*/GV* logic, vs ithread-only pad logic, is too verbose and too special cased in too many places, some new CPP macros in perl.h/etc need to be written to make everything more readable and more compact on the screen. |
I believe only the last one is indeed forbidden by the C standard:
There's no macro call here, and indeed, the snippet from this PR compiles even on the oldest version of MSVC that I have installed (2005). Of course, our codebase is full of macros, many of them look like normal functions (embed.h aliases), so it's very easy to run into this issue. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's a reasonable change.
Another approach might be something like:
#ifdef USE_ITHREADS
typedef PADOFFSET SVOP_svref_t;
#define SVOP_svref_t(o) (cPADOPx(o)->op_padix)
#define MDEREF_svref(pitem) ((pitem)->pad_offset)
#else
typedef SV *SVOP_svref_t;
#define SVOP_svref_t(o) (cSVOPx(o)->op_sv)
#define MDEREF_svref(pitem) ((pitem)->sv)
#endif
though that makes more macro hell (and may make the mderef calls harder to check the correctness of, since pitem is normally item++
there)
The prior structure of this syntax made it look to tree-sitter-based parsers as if two separate functions were being defined, though only the second of which was ever finished. This resulted in the entire rest of the file appearing to be nested inside the first function, meaning no top-level function analysis was performed on them. This has various knock-on effects on code analysis in tooling such as editors or browsers.
For example, see the two separate fold regions in this editor screenshot:

When this function is folded, it appears to be a 15800-line long function that consumes the entire rest of the file:

The fix for it moves the
#ifdef
syntax inside the argument parentheses to ensure that only one function appears to be created, so the entire rest of the file is parsed as normal.