aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Frontend/CompilerInvocation.cpp
diff options
context:
space:
mode:
authorJan Svoboda <jan_svoboda@apple.com>2025-05-22 12:33:52 -0700
committerGitHub <noreply@github.com>2025-05-22 12:33:52 -0700
commit9e306ad4600c4d3392c194a8be88919ee758425c (patch)
treef8b15171e92d056e9006bcbe36d534a9d73155d9 /clang/lib/Frontend/CompilerInvocation.cpp
parent2b8bff6f66fd90ac658d0ae0d7f9a83ffadfd77f (diff)
downloadllvm-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.cpp27
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;
}