This is useful for being able to parse the preprocessor directive blocks even the header that defined the macro that they check for hasn't been included.
Details
- Reviewers
klimek benlangmuir - Commits
- rGad870f828586: [preprocessor] When preprocessor option 'SingleFileParseMode' is enabled, parse…
rC305797: [preprocessor] When preprocessor option 'SingleFileParseMode' is enabled, parse…
rL305797: [preprocessor] When preprocessor option 'SingleFileParseMode' is enabled, parse…
Diff Detail
- Repository
- rL LLVM
Event Timeline
Hello Argyrios,
This is a good addition to simplify reuse of preprocessor in IDEs. Thanks for doing this.
From our experience of integrating clang PP into NetBeans, the following change gives more flexibility:
- introduce method in PPCallbacks and consult it what is the preferred value for undefined symbol
It will be similar to approach used for unresolved includes and FileNotFound method.
It also gives dynamic behavior for clients: client might still prefer to keep skipping some blocks like unix, mac, win, solaris, LP64, cplusplus, ...
Thanks,
Vladimir.
Hey Vladimir, what you are proposing is orthogonal to this patch. You are proposing for "the client to provide the value for an undefined identifier", and the patch is about the client not knowing what the value should be so it fallbacks to parsing all tokens to get the max amount of info. Note that both of the techniques can be combined well, if the client provides the value, the preprocessor will take it into account, otherwise if it is stays unresolved it will fallback to lexing all tokens.
But what you are proposing is not a replacement for what the patch is doing.
It would be nice if the doc comment for the single file parse mode flag was updated to include this new functionality.
lib/Lex/PPDirectives.cpp | ||
---|---|---|
2709 ↗ | (On Diff #102761) | Nitpick: this is misaligned. Same with many other calls to pushConditionalLevel in this patch. |
2774 ↗ | (On Diff #102761) | Why is wasSkipping false here? |
lib/Lex/PPDirectives.cpp | ||
---|---|---|
2774 ↗ | (On Diff #102761) | For #if it sets wasskip to true to indicate later for HandleElseDirective that the block should not be skipped. |
lib/Lex/PPDirectives.cpp | ||
---|---|---|
2774 ↗ | (On Diff #102761) | Thanks for explaining. That makes sense to me. |
Enhanced doc-comment for the preprocessor option, and fixed indentation on a couple of calls.
Generally this patch lg from my side - how many patches for single file mode are coming down the road, though? I'm somewhat concerned about the overall complexity it'll add to clang.
When I saw your first patch my reaction was "wow, this works with this little change - cool".
With this patch it's "well, that doesn't seem to add too much complexity, so looks good".
I don't want to realize 5 patches down the line that we're sprinkling all of clang with single file conditional code without some discussion about the strategy with Richard.
include/clang/Lex/Preprocessor.h | ||
---|---|---|
1838–1841 ↗ | (On Diff #102885) | A short comment on the struct what the semantics are would be helpful. |
I'm not sure :-)
What I find problematic in this patch is PPOpts->SingleFileParseMode checks.
Let's suppose we implement what I mentioned above => how is it going to co-exist nicely? I think code will be less understandable with both: check of flag and call to PPCallbacks.
What I propose is to move the logic from the PPOpts single flag into PPCallbacks. And from check of flag to query of PPCallbacks.
Of course when you create PPCallbacks you can consult global SingleFileParseMode to create default implementation to answer "any symbol is defined", so you get your use-case easily handled, but it also gives others more flexibility.
Thanks,
Vladimir.
There is no other patch for using this preprocessor option. Any related improvements down the road will be about general improvements for error recovery, for example things like this:
- Introduce an UnresolvedTypename type instead of changing unresolved types to int.
- For @interace A : B, don't completely drop B from the super-class list of A if it is unresolved.
These kind of improvements are not conditional.
There is a bit of misunderstanding on what this patch is doing, the patch is not about answering "any symbol is defined". See my cfe-dev email (http://lists.llvm.org/pipermail/cfe-dev/2017-June/054254.html) that provides some more context.
The patch is doing these 2 things:
- Keep track of whether a preprocessor directive condition used a symbol that was not resolved at all
- If above is true then make the preprocessor parse all directive blocks, not arbitrary choose one of them.
Here's an example to clarify the difference:
Say that you have this code:
#if TARGET_IOS @interface A @end #else @interface B @end #endif
- Without any changes this will happen:
- TARGET_IOS is unresolved so it will be treated as 0
- #if block will be skipped, #else will be parsed
- AST will contain @interface B
- With adding a PPCallback that answers "any symbol is defined" (what you are proposing):
- TARGET_IOS is undefined but the PPCallback sets it to 1
- #if block will be parsed, #else will be skipped
- AST will contain @interface A
- With this patch and enabling SingleFileParseMode
- TARGET_IOS is unresolved
- Both #if and #else blocks will be parsed
- AST will contain both @interface A and @interface B
As you can see 2. and 3. above are not overlapping so they can "co-exist nicely" like this:
- TARGET_IOS is undefined, ask the PPCallback if it has a value for it or not
- If the callback provides a value then parse as 1. or 2. depending on the value
- If the callback cannot provide a specific value then parse as 3.
Here's an example to clarify the difference:
Thanks for the example. You are right, I missed this difference in patch.