Skip to content

Conversation

@jansvoboda11
Copy link
Contributor

This PR makes CompilerInvocation the sole owner of the LangOptions instance.

@llvmbot llvmbot added the clang Clang issues not falling into any other category label Apr 28, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 28, 2025

@llvm/pr-subscribers-clang

Author: Jan Svoboda (jansvoboda11)

Changes

This PR makes CompilerInvocation the sole owner of the LangOptions instance.


Full diff: https://github.com/llvm/llvm-project/pull/137675.diff

5 Files Affected:

  • (modified) clang/include/clang/Frontend/ASTUnit.h (+2-2)
  • (modified) clang/include/clang/Frontend/CompilerInstance.h (-3)
  • (modified) clang/include/clang/Frontend/CompilerInvocation.h (-6)
  • (modified) clang/lib/Frontend/ASTUnit.cpp (+6-4)
  • (modified) clang/lib/Frontend/FrontendAction.cpp (+1-1)
diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h
index 2baa2d1cc540d..73686b0eacbe2 100644
--- a/clang/include/clang/Frontend/ASTUnit.h
+++ b/clang/include/clang/Frontend/ASTUnit.h
@@ -106,7 +106,7 @@ class ASTUnit {
   };
 
 private:
-  std::shared_ptr<LangOptions>            LangOpts;
+  std::unique_ptr<LangOptions> LangOpts;
   IntrusiveRefCntPtr<DiagnosticsEngine>   Diagnostics;
   IntrusiveRefCntPtr<FileManager>         FileMgr;
   IntrusiveRefCntPtr<SourceManager>       SourceMgr;
@@ -704,7 +704,7 @@ class ASTUnit {
                   IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
                   const FileSystemOptions &FileSystemOpts,
                   const HeaderSearchOptions &HSOpts,
-                  std::shared_ptr<LangOptions> LangOpts = nullptr,
+                  const LangOptions *LangOpts = nullptr,
                   bool OnlyLocalDecls = false,
                   CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None,
                   bool AllowASTWithCompilerErrors = false,
diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h
index 7de4fb531d0e7..78ac1079354de 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -327,9 +327,6 @@ class CompilerInstance : public ModuleLoader {
 
   LangOptions &getLangOpts() { return Invocation->getLangOpts(); }
   const LangOptions &getLangOpts() const { return Invocation->getLangOpts(); }
-  std::shared_ptr<LangOptions> getLangOptsPtr() const {
-    return Invocation->getLangOptsPtr();
-  }
 
   PreprocessorOptions &getPreprocessorOpts() {
     return Invocation->getPreprocessorOpts();
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h
index 1827ff0f6816d..31bf7e94efab8 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -265,12 +265,6 @@ class CompilerInvocation : public CompilerInvocationBase {
   }
   /// @}
 
-  /// Base class internals.
-  /// @{
-  using CompilerInvocationBase::LangOpts;
-  std::shared_ptr<LangOptions> getLangOptsPtr() { return LangOpts; }
-  /// @}
-
   /// Create a compiler invocation from a list of input options.
   /// \returns true on success.
   ///
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp
index 3e4da76916585..e05385d119870 100644
--- a/clang/lib/Frontend/ASTUnit.cpp
+++ b/clang/lib/Frontend/ASTUnit.cpp
@@ -805,7 +805,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
     StringRef Filename, const PCHContainerReader &PCHContainerRdr,
     WhatToLoad ToLoad, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
     const FileSystemOptions &FileSystemOpts, const HeaderSearchOptions &HSOpts,
-    std::shared_ptr<LangOptions> LangOpts, bool OnlyLocalDecls,
+    const LangOptions *LangOpts, bool OnlyLocalDecls,
     CaptureDiagsKind CaptureDiagnostics, bool AllowASTWithCompilerErrors,
     bool UserFilesAreVolatile, IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
   std::unique_ptr<ASTUnit> AST(new ASTUnit(true));
@@ -819,7 +819,8 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
 
   ConfigureDiags(Diags, *AST, CaptureDiagnostics);
 
-  AST->LangOpts = LangOpts ? LangOpts : std::make_shared<LangOptions>();
+  AST->LangOpts = LangOpts ? std::make_unique<LangOptions>(*LangOpts)
+                           : std::make_unique<LangOptions>();
   AST->OnlyLocalDecls = OnlyLocalDecls;
   AST->CaptureDiagnostics = CaptureDiagnostics;
   AST->Diagnostics = Diags;
@@ -1211,7 +1212,8 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
          "IR inputs not support here!");
 
   // Configure the various subsystems.
-  LangOpts = Clang->getInvocation().LangOpts;
+  LangOpts =
+      std::make_unique<LangOptions>(Clang->getInvocation().getLangOpts());
   FileSystemOpts = Clang->getFileSystemOpts();
 
   ResetForParse();
@@ -1486,7 +1488,7 @@ void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) {
   // Steal the created target, context, and preprocessor if they have been
   // created.
   assert(CI.hasInvocation() && "missing invocation");
-  LangOpts = CI.getInvocation().LangOpts;
+  LangOpts = std::make_unique<LangOptions>(CI.getInvocation().getLangOpts());
   TheSema = CI.takeSema();
   Consumer = CI.takeASTConsumer();
   if (CI.hasASTContext())
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 783d1a64132b6..9b2aa253c90ee 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -847,7 +847,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
 
     std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile(
         InputFile, CI.getPCHContainerReader(), ASTUnit::LoadEverything, Diags,
-        CI.getFileSystemOpts(), CI.getHeaderSearchOpts(), CI.getLangOptsPtr());
+        CI.getFileSystemOpts(), CI.getHeaderSearchOpts(), &CI.getLangOpts());
 
     if (!AST)
       return false;

@github-actions
Copy link

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff HEAD~1 HEAD --extensions h,cpp -- clang/include/clang/Frontend/ASTUnit.h clang/include/clang/Frontend/CompilerInstance.h clang/include/clang/Frontend/CompilerInvocation.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Frontend/FrontendAction.cpp
View the diff from clang-format here.
diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h
index 73686b0ea..ac99f0fb2 100644
--- a/clang/include/clang/Frontend/ASTUnit.h
+++ b/clang/include/clang/Frontend/ASTUnit.h
@@ -698,19 +698,17 @@ public:
   /// lifetime is expected to extend past that of the returned ASTUnit.
   ///
   /// \returns - The initialized ASTUnit or null if the AST failed to load.
-  static std::unique_ptr<ASTUnit>
-  LoadFromASTFile(StringRef Filename, const PCHContainerReader &PCHContainerRdr,
-                  WhatToLoad ToLoad,
-                  IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
-                  const FileSystemOptions &FileSystemOpts,
-                  const HeaderSearchOptions &HSOpts,
-                  const LangOptions *LangOpts = nullptr,
-                  bool OnlyLocalDecls = false,
-                  CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None,
-                  bool AllowASTWithCompilerErrors = false,
-                  bool UserFilesAreVolatile = false,
-                  IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
-                      llvm::vfs::getRealFileSystem());
+  static std::unique_ptr<ASTUnit> LoadFromASTFile(
+      StringRef Filename, const PCHContainerReader &PCHContainerRdr,
+      WhatToLoad ToLoad, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
+      const FileSystemOptions &FileSystemOpts,
+      const HeaderSearchOptions &HSOpts, const LangOptions *LangOpts = nullptr,
+      bool OnlyLocalDecls = false,
+      CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None,
+      bool AllowASTWithCompilerErrors = false,
+      bool UserFilesAreVolatile = false,
+      IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
+          llvm::vfs::getRealFileSystem());
 
 private:
   /// Helper function for \c LoadFromCompilerInvocation() and

@vsapsai
Copy link
Collaborator

vsapsai commented Apr 29, 2025

I'm feeling stupid but how does it work with ASan? I'm confused because in CompilerInvocationBase we have std::shared_ptr<LangOptions> LangOpts and in ASTUnit we have std::unique_ptr<LangOptions> LangOpts. I don't get how this PR

makes CompilerInvocation the sole owner of the LangOptions instance

Seems like the ownership is shared between CompilerInvocation and ASTUnit.

@jansvoboda11
Copy link
Contributor Author

The unique_ptr in ASTUnit always stores a copy of the shared_ptr in CompilerInvocation.

@vsapsai
Copy link
Collaborator

vsapsai commented Apr 29, 2025

The unique_ptr in ASTUnit always stores a copy of the shared_ptr in CompilerInvocation.

And we need unique_ptr in ASTUnit instead of a direct value so we can change LangOpts in ASTUnit::Parse?

Copy link
Collaborator

@vsapsai vsapsai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also looks like this assert doesn't serve its value anymore

  const LangOptions &getLangOpts() const {
    assert(LangOpts && "ASTUnit does not have language options");
    return *LangOpts;
  }

But it is a minor cleanup, not blocking.

@jansvoboda11
Copy link
Contributor Author

jansvoboda11 commented Apr 29, 2025

The unique_ptr in ASTUnit always stores a copy of the shared_ptr in CompilerInvocation.

And we need unique_ptr in ASTUnit instead of a direct value so we can change LangOpts in ASTUnit::Parse?

Not really, using LangOptions directly instead of std::unique_ptr<LangOptions> allows reassignment too. I chose std::unique_ptr to:

  • prevent increase of ASTUnit size,
  • avoid unconditional initialization of ASTUnit::LangOpts in the constructor (which would be an unnecessary change in this PR I think).

@jansvoboda11
Copy link
Contributor Author

Also looks like this assert doesn't serve its value anymore

  const LangOptions &getLangOpts() const {
    assert(LangOpts && "ASTUnit does not have language options");
    return *LangOpts;
  }

But it is a minor cleanup, not blocking.

I think it still does have a value because LangOpts is not initialized in the constructor and only gets initialized conditionally. So there still are times where it's null.

@jansvoboda11 jansvoboda11 requested a review from vsapsai April 29, 2025 17:22
@vsapsai
Copy link
Collaborator

vsapsai commented Apr 29, 2025

Not really, using LangOptions directly instead of std::unique_ptr<LangOptions> allows reassignment too. I chose std::unique_ptr to:

  • prevent increase of ASTUnit size,
  • avoid unconditional initialization of ASTUnit::LangOpts in the constructor (which would be an unnecessary change in this PR I think).

I think that is a reasonable choice.

Copy link
Collaborator

@vsapsai vsapsai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok to merge after fixing the formatting.

@jansvoboda11 jansvoboda11 merged commit c85e43b into llvm:main Apr 29, 2025
3 of 5 checks passed
@jansvoboda11 jansvoboda11 deleted the language-options-ptr branch April 29, 2025 17:37
@llvm-ci
Copy link
Collaborator

llvm-ci commented Apr 29, 2025

LLVM Buildbot has detected a new failure on builder openmp-offload-amdgpu-runtime-2 running on rocm-worker-hw-02 while building clang at step 6 "test-openmp".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/10/builds/4385

Here is the relevant piece of the build log for the reference
Step 6 (test-openmp) failure: test (failure)
******************** TEST 'libarcher :: races/task-taskwait-nested.c' FAILED ********************
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 13
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/./bin/clang -fopenmp  -gdwarf-4 -O1 -fsanitize=thread  -I /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests -I /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -L /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -Wl,-rpath,/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/runtime/src   /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/races/task-taskwait-nested.c -o /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/tools/archer/tests/races/Output/task-taskwait-nested.c.tmp -latomic && env TSAN_OPTIONS='ignore_noninstrumented_modules=0:ignore_noninstrumented_modules=1' /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/deflake.bash /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/tools/archer/tests/races/Output/task-taskwait-nested.c.tmp 2>&1 | tee /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/tools/archer/tests/races/Output/task-taskwait-nested.c.tmp.log | /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/./bin/FileCheck /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/races/task-taskwait-nested.c
# executed command: /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/./bin/clang -fopenmp -gdwarf-4 -O1 -fsanitize=thread -I /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests -I /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -L /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -Wl,-rpath,/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/runtime/src /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/races/task-taskwait-nested.c -o /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/tools/archer/tests/races/Output/task-taskwait-nested.c.tmp -latomic
# note: command had no output on stdout or stderr
# executed command: env TSAN_OPTIONS=ignore_noninstrumented_modules=0:ignore_noninstrumented_modules=1 /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/deflake.bash /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/tools/archer/tests/races/Output/task-taskwait-nested.c.tmp
# note: command had no output on stdout or stderr
# executed command: tee /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/tools/archer/tests/races/Output/task-taskwait-nested.c.tmp.log
# note: command had no output on stdout or stderr
# executed command: /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/./bin/FileCheck /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/races/task-taskwait-nested.c
# .---command stderr------------
# | /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/races/task-taskwait-nested.c:54:16: error: CHECK-NEXT: is not on the line after the previous match
# | // CHECK-NEXT: #0 {{.*}}task-taskwait-nested.c:34
# |                ^
# | <stdin>:11:2: note: 'next' match was here
# |  #0 .omp_outlined..1 /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/races/task-taskwait-nested.c:34:12 (task-taskwait-nested.c.tmp+0x126e74)
# |  ^
# | <stdin>:4:17: note: previous match ended here
# |  Write of size 4 at 0x7fffffffe790 by main thread:
# |                 ^
# | <stdin>:5:1: note: non-matching line after previous match is here
# |  #0 main.omp_outlined_debug__ /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/races/task-taskwait-nested.c:44:8 (task-taskwait-nested.c.tmp+0x126dd5)
# | ^
# | 
# | Input file: <stdin>
# | Check file: /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/races/task-taskwait-nested.c
# | 
# | -dump-input=help explains the following input dump.
# | 
# | Input was:
# | <<<<<<
# |          .
# |          .
# |          .
# |          6:  #1 main.omp_outlined /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/races/task-taskwait-nested.c:24:1 (task-taskwait-nested.c.tmp+0x126dd5) 
# |          7:  #2 __kmp_invoke_microtask <null> (libomp.so+0xebb88) 
# |          8:  #3 main /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/races/task-taskwait-nested.c:24:1 (task-taskwait-nested.c.tmp+0x126fc7) 
# |          9:  
# |         10:  Previous write of size 4 at 0x7fffffffe790 by thread T4: 
# |         11:  #0 .omp_outlined..1 /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/races/task-taskwait-nested.c:34:12 (task-taskwait-nested.c.tmp+0x126e74) 
# | next:54      !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                           error: match on wrong line
# |         12:  #1 .omp_task_entry. /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/races/task-taskwait-nested.c:29:1 (task-taskwait-nested.c.tmp+0x126e74) 
# |         13:  #2 __kmp_invoke_task(int, kmp_task*, kmp_taskdata*) kmp_tasking.cpp (libomp.so+0x86b0e) 
# |         14:  
# |         15:  As if synchronized via sleep: 
# |         16:  #0 usleep /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp:399:3 (task-taskwait-nested.c.tmp+0x9fc77) 
...

IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
…m#137675)

This PR makes `CompilerInvocation` the sole owner of the `LangOptions`
instance.
GeorgeARM pushed a commit to GeorgeARM/llvm-project that referenced this pull request May 7, 2025
…m#137675)

This PR makes `CompilerInvocation` the sole owner of the `LangOptions`
instance.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants