diff options
author | Jan Svoboda <jan_svoboda@apple.com> | 2025-05-22 12:33:52 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-05-22 12:33:52 -0700 |
commit | 9e306ad4600c4d3392c194a8be88919ee758425c (patch) | |
tree | f8b15171e92d056e9006bcbe36d534a9d73155d9 /clang/lib/Frontend/CompilerInvocation.cpp | |
parent | 2b8bff6f66fd90ac658d0ae0d7f9a83ffadfd77f (diff) | |
download | llvm-9e306ad4600c4d3392c194a8be88919ee758425c.zip llvm-9e306ad4600c4d3392c194a8be88919ee758425c.tar.gz llvm-9e306ad4600c4d3392c194a8be88919ee758425c.tar.bz2 |
[clang] Remove intrusive reference count from `DiagnosticOptions` (#139584)
The `DiagnosticOptions` class is currently intrusively
reference-counted, which makes reasoning about its lifetime very
difficult in some cases. For example, `CompilerInvocation` owns the
`DiagnosticOptions` instance (wrapped in `llvm::IntrusiveRefCntPtr`) and
only exposes an accessor returning `DiagnosticOptions &`. One would
think this gives `CompilerInvocation` exclusive ownership of the object,
but that's not the case:
```c++
void shareOwnership(CompilerInvocation &CI) {
llvm::IntrusiveRefCntPtr<DiagnosticOptions> CoOwner = &CI.getDiagnosticOptions();
// ...
}
```
This is a perfectly valid pattern that is being actually used in the
codebase.
I would like to ensure the ownership of `DiagnosticOptions` by
`CompilerInvocation` is guaranteed to be exclusive. This can be
leveraged for a copy-on-write optimization later on. This PR changes
usages of `DiagnosticOptions` across `clang`, `clang-tools-extra` and
`lldb` to not be intrusively reference-counted.
Diffstat (limited to 'clang/lib/Frontend/CompilerInvocation.cpp')
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 27 |
1 files changed, 7 insertions, 20 deletions
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 3c23073..9c33910 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -125,21 +125,14 @@ static Expected<std::optional<uint32_t>> parseToleranceOption(StringRef Arg) { // Initialization. //===----------------------------------------------------------------------===// -namespace { template <class T> std::shared_ptr<T> make_shared_copy(const T &X) { return std::make_shared<T>(X); } -template <class T> -llvm::IntrusiveRefCntPtr<T> makeIntrusiveRefCntCopy(const T &X) { - return llvm::makeIntrusiveRefCnt<T>(X); -} -} // namespace - CompilerInvocationBase::CompilerInvocationBase() : LangOpts(std::make_shared<LangOptions>()), TargetOpts(std::make_shared<TargetOptions>()), - DiagnosticOpts(llvm::makeIntrusiveRefCnt<DiagnosticOptions>()), + DiagnosticOpts(std::make_shared<DiagnosticOptions>()), HSOpts(std::make_shared<HeaderSearchOptions>()), PPOpts(std::make_shared<PreprocessorOptions>()), AnalyzerOpts(std::make_shared<AnalyzerOptions>()), @@ -156,7 +149,7 @@ CompilerInvocationBase::deep_copy_assign(const CompilerInvocationBase &X) { if (this != &X) { LangOpts = make_shared_copy(X.getLangOpts()); TargetOpts = make_shared_copy(X.getTargetOpts()); - DiagnosticOpts = makeIntrusiveRefCntCopy(X.getDiagnosticOpts()); + DiagnosticOpts = make_shared_copy(X.getDiagnosticOpts()); HSOpts = make_shared_copy(X.getHeaderSearchOpts()); PPOpts = make_shared_copy(X.getPreprocessorOpts()); AnalyzerOpts = make_shared_copy(X.getAnalyzerOpts()); @@ -202,7 +195,6 @@ CompilerInvocation::operator=(const CowCompilerInvocation &X) { return *this; } -namespace { template <typename T> T &ensureOwned(std::shared_ptr<T> &Storage) { if (Storage.use_count() > 1) @@ -210,14 +202,6 @@ T &ensureOwned(std::shared_ptr<T> &Storage) { return *Storage; } -template <typename T> -T &ensureOwned(llvm::IntrusiveRefCntPtr<T> &Storage) { - if (Storage.useCount() > 1) - Storage = llvm::makeIntrusiveRefCnt<T>(*Storage); - return *Storage; -} -} // namespace - LangOptions &CowCompilerInvocation::getMutLangOpts() { return ensureOwned(LangOpts); } @@ -844,7 +828,8 @@ static bool RoundTrip(ParseFn Parse, GenerateFn Generate, }; // Setup a dummy DiagnosticsEngine. - DiagnosticsEngine DummyDiags(new DiagnosticIDs(), new DiagnosticOptions()); + DiagnosticOptions DummyDiagOpts; + DiagnosticsEngine DummyDiags(new DiagnosticIDs(), DummyDiagOpts); DummyDiags.setClient(new TextDiagnosticBuffer()); // Run the first parse on the original arguments with the dummy invocation and @@ -2663,9 +2648,11 @@ clang::CreateAndPopulateDiagOpts(ArrayRef<const char *> Argv) { bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, DiagnosticsEngine *Diags, bool DefaultDiagColor) { + std::optional<DiagnosticOptions> IgnoringDiagOpts; std::optional<DiagnosticsEngine> IgnoringDiags; if (!Diags) { - IgnoringDiags.emplace(new DiagnosticIDs(), new DiagnosticOptions(), + IgnoringDiagOpts.emplace(); + IgnoringDiags.emplace(new DiagnosticIDs(), *IgnoringDiagOpts, new IgnoringDiagConsumer()); Diags = &*IgnoringDiags; } |