When a clang tool runs on a translation unit that uses modular headers, no
PPCallbacks will be invoked for the code in the modular headers (since they are
not parsed, but loaded as AST). Since some tools depend on PPCallbacks for all
transitively included headers, a solution is to re-lex the modular headers
from the sources stored along with AST inside module files. This patch makes it
possible to re-attach PPCallbacks from the compiler's Preprocessor to a custom
one that will be used to re-lex all transitively included headers. It also
updates clang-tidy checks to be compatible with this mode of operation.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
- Build Status
Buildable 28184 Build 28183: arc lint + arc unit
Event Timeline
clang/include/clang/Lex/PPCallbacks.h | ||
---|---|---|
346 | This seems pretty tangly from a layering point of view, giving each object a reference to the other. I always find it hard to reason about ownership in such cases. What about lifecycle methods beginPreprocessing(Preprocessor*) and endPreprocessing(Preprocessor*)? It will look similar in practice: subclasses that need it can still track the PP instance, but the circular references will only be there when needed, and will be explicit. |
clang/include/clang/Lex/PPCallbacks.h | ||
---|---|---|
346 | We can do that as well. However, adding another couple of overrides to each PPCallbacks implementation will result in quite some boilerplate. How would you look at creating an intermediate class in the PPCallbacks -> <users' PPCallbacks handlers> hierarchy that will handle beginPreprocessing/endPreprocessing and expose the preprocessor pointer via a protected getPreprocessor() method? |
clang/include/clang/Lex/PPCallbacks.h | ||
---|---|---|
346 | I think that would probably obscure the intent, I really think this is subtle enough to be explicit, and would be only about as boilerplatey as today (the PP pointer is set by a method rather than in the constructor). But I'm more concerned about the interfaces in Lex/ than the specific callsites in clang-tidy, so if such a helper class were private to clang-tidy, that seems ok. |
I've found an alternative way to deal with PPCallbacks when analyzing code in modular mode. See https://reviews.llvm.org/D59528. Abandoning this revision.
This seems pretty tangly from a layering point of view, giving each object a reference to the other. I always find it hard to reason about ownership in such cases.
What about lifecycle methods beginPreprocessing(Preprocessor*) and endPreprocessing(Preprocessor*)? It will look similar in practice: subclasses that need it can still track the PP instance, but the circular references will only be there when needed, and will be explicit.