From 9e306ad4600c4d3392c194a8be88919ee758425c Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Thu, 22 May 2025 12:33:52 -0700 Subject: [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 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. --- clang/unittests/Frontend/UtilsTest.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'clang/unittests/Frontend/UtilsTest.cpp') diff --git a/clang/unittests/Frontend/UtilsTest.cpp b/clang/unittests/Frontend/UtilsTest.cpp index 47ca321..cf385a5 100644 --- a/clang/unittests/Frontend/UtilsTest.cpp +++ b/clang/unittests/Frontend/UtilsTest.cpp @@ -26,11 +26,12 @@ TEST(BuildCompilerInvocationTest, RecoverMultipleJobs) { std::vector Args = {"clang", "--target=macho", "-arch", "i386", "-arch", "x86_64", "foo.cpp"}; clang::IgnoringDiagConsumer D; + clang::DiagnosticOptions DiagOpts; CreateInvocationOptions Opts; Opts.RecoverOnError = true; Opts.VFS = new llvm::vfs::InMemoryFileSystem(); - Opts.Diags = clang::CompilerInstance::createDiagnostics( - *Opts.VFS, new DiagnosticOptions, &D, false); + Opts.Diags = clang::CompilerInstance::createDiagnostics(*Opts.VFS, DiagOpts, + &D, false); std::unique_ptr CI = createInvocation(Args, Opts); ASSERT_TRUE(CI); EXPECT_THAT(CI->getTargetOpts().Triple, testing::StartsWith("i386-")); @@ -45,9 +46,9 @@ TEST(BuildCompilerInvocationTest, ProbePrecompiled) { FS->addFile("foo.h.pch", 0, llvm::MemoryBuffer::getMemBuffer("")); clang::IgnoringDiagConsumer D; + clang::DiagnosticOptions DiagOpts; llvm::IntrusiveRefCntPtr CommandLineDiagsEngine = - clang::CompilerInstance::createDiagnostics(*FS, new DiagnosticOptions, &D, - false); + clang::CompilerInstance::createDiagnostics(*FS, DiagOpts, &D, false); // Default: ProbePrecompiled=false CreateInvocationOptions CIOpts; CIOpts.Diags = CommandLineDiagsEngine; -- cgit v1.1