I’m trying to implement a #pragma FRR printfrr_ext "%pI4" (struct in_addr *) for Linux kernel-style extended printf type checking (existing GCC plugin: frr/tools/gcc-plugins at master · FRRouting/frr · GitHub) and scratching my head about parsing the type in the pragma.
It doesn’t seem possible to get to the Parser * from inside the PragmaHandler in order to call Parser::ParseTypeName, am I missing something? It looks like clang is intentionally hiding/making opaque the Parser * to prevent people from messing with it?
If there’s some good way to do this I’d appreciate some hints…
I’m afraid it will be pretty difficult given the fact that pragma handler is operating within preprocessor (which runs the lexer) so in principle you only have tokens from the lexer
I’m afraid it will be pretty difficult given the fact that pragma handler is operating within preprocessor (which runs the lexer) so in principle you only have tokens from the lexer
I see… can you double check my understanding?
Looking at how #pragma pack is handled, it seems that the handling is split. The pragma handler creates a tok::annot_foobar token and the parser code then acts upon it. Which is not something I can do in a plugin because I essentially need to add a switch case in Parser::ParseExternalDeclaration (where most other pragmas are handled)…
… and I probably also need to add a new PRAGMA_ANNOTATION() token type into TokenKinds.def to carry my pragma details from the handler into the parser, which is another thing a plugin can’t do …
correct, there is only so much you can do within a plugin
You can, however, inject new tokens to the preprocessor. For instance via Preprocessor::EnterTokenStream. I’ve never seriously tried it but theoretically you can use that to insert artificial code (in the form tokens, of course) into the original source text.
and then walk the AST and trigger special magic handling when seeing one of these functions, grabbing the type from the arg and the format string from the return value…
… but that seems … quite hacky … and would be visible in compiled output by the added magic function when building non-optimized …
(Edit.: I guess the plugin could also delete the function from the AST)
(Edit 2.: Also if the user makes a mistake in the pragma, the compiler error is going to reference some weird stuff that is nowhere to be found in the actual source file…)
It is. But you’re working on something really early in the frontend pipeline. It’s not like clang doesn’t want to give you a parser instance or AST: they’re just not there yet.
Correct, you can write an AST plugin, which gives you much more semantics
You can synthesize source locations for tokens you inject into the token stream