[clang] [clang-tools-extra] [clang] Do not share ownership of `PreprocessorOptions` (PR #133467)
Jan Svoboda via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 28 10:58:31 PDT 2025
jansvoboda11 wrote:
> Are you planning to do the same for LangOpts and HSOpts? What's the ultimate goal here?
Yes, I'd like to do this for all options. The immediate goal is for `CompilerInvocation` to be the only class responsible for managing lifetimes of the underlying `Options` objects. In addition to that, I want to change `CompilerInstance` APIs to make it impossible to modify the invocation once `Preprocessor`, `HeaderSearch` and similar objects hold the reference to its `Options` object. This makes it possible for `CompilerInvocation` to safely implement copy-on-write semantics.
We can use this to avoid making copies of the entire invocation when compiling a chain of implicit modules, for example.
But more importantly, once we know there are no mutable references to `CompilerInvocation` or its options, we can use the internal pointers to speed up checks for equality of two invocations with a common ancestor, allowing efficient deduplication of some tasks in the dependency scanner, which would currently require comparison of the stringified arguments.
My idea is that the build system creates one common invocation for a build target and then passes that to the dependency scanner along with any file-specific options. This not only saves time of re-running the driver and re-parsing command lines, but also enables deduplicating the construction of the dependency graph, which we currently do in full for each TU. Note that we can't just use the strict context hash for this deduplication, since we care about the canonical command lines. This should change the complexity of creating dependency graphs from (roughly) `O(N*M)` to `O(N+M)`, where `N` is the number of TUs in a target and `M` is the size of the common parts of their individual dependency graphs.
> There's also this comment on `CompilerInvocationBase`:
>
> ```
> /// ... It keeps individual option objects
> /// behind reference-counted pointers, which is useful for clients that want to
> /// keep select option objects alive (even after CompilerInvocation gets
> /// destroyed) without making a copy.
> ```
>
> Which only makes sense if these `shared_ptr`s are exposed somewhere.
Yeah, I think this is mostly used in `ASTUnit`, where I think a reasonable trade-off is to just keep the entire invocation alive instead of individual options.
https://github.com/llvm/llvm-project/pull/133467
More information about the cfe-commits
mailing list