Skip to content

Conversation

@naveen-seth
Copy link
Contributor

@naveen-seth naveen-seth commented Nov 26, 2025

This relands #165277 by reverting #169397.

The original revert was due to a report of a broken build, which was later resolved by fully clearing the build directory.

@naveen-seth naveen-seth requested a review from shiltian November 26, 2025 02:57
@llvmbot llvmbot added clang-tools-extra lldb clangd clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules clang:as-a-library libclang and C++ API flang:driver flang Flang issues not falling into any other category labels Nov 26, 2025
@llvmbot
Copy link
Member

llvmbot commented Nov 26, 2025

@llvm/pr-subscribers-clang-modules

@llvm/pr-subscribers-clang-driver

Author: Naveen Seth Hanig (naveen-seth)

Changes

This reapplies 3773bbe by reverting a96ec1c.

The original revert was due to a report of a broken build, which was later resolved by fully clearing the build directory.


Patch is 103.65 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/169597.diff

60 Files Affected:

  • (modified) clang-tools-extra/clangd/CompileCommands.cpp (+1-2)
  • (modified) clang-tools-extra/clangd/Compiler.cpp (+1)
  • (modified) clang/docs/ReleaseNotes.rst (+2)
  • (modified) clang/include/clang/Driver/CommonArgs.h (-10)
  • (added) clang/include/clang/Driver/CreateASTUnitFromArgs.h (+80)
  • (added) clang/include/clang/Driver/CreateInvocationFromArgs.h (+76)
  • (modified) clang/include/clang/Driver/Driver.h (-4)
  • (modified) clang/include/clang/Frontend/ASTUnit.h (+64-80)
  • (modified) clang/include/clang/Frontend/CompilerInvocation.h (-10)
  • (added) clang/include/clang/Frontend/StandaloneDiagnostic.h (+82)
  • (modified) clang/include/clang/Frontend/Utils.h (-45)
  • (modified) clang/include/clang/Options/OptionUtils.h (+24)
  • (modified) clang/lib/CrossTU/CMakeLists.txt (+1)
  • (modified) clang/lib/CrossTU/CrossTranslationUnit.cpp (+2-1)
  • (modified) clang/lib/Driver/CMakeLists.txt (+4)
  • (added) clang/lib/Driver/CreateASTUnitFromArgs.cpp (+166)
  • (renamed) clang/lib/Driver/CreateInvocationFromArgs.cpp (+8-5)
  • (modified) clang/lib/Driver/Driver.cpp (+1-34)
  • (modified) clang/lib/Driver/ToolChains/Clang.cpp (+1)
  • (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (-163)
  • (modified) clang/lib/Driver/ToolChains/Flang.cpp (+1)
  • (modified) clang/lib/Frontend/ASTUnit.cpp (+51-292)
  • (modified) clang/lib/Frontend/CMakeLists.txt (+1-2)
  • (modified) clang/lib/Frontend/CompilerInvocation.cpp (-8)
  • (added) clang/lib/Frontend/StandaloneDiagnostic.cpp (+117)
  • (modified) clang/lib/Interpreter/CMakeLists.txt (+1)
  • (modified) clang/lib/Interpreter/Interpreter.cpp (+2-1)
  • (modified) clang/lib/Options/OptionUtils.cpp (+207-8)
  • (modified) clang/lib/Tooling/Tooling.cpp (+2-2)
  • (modified) clang/tools/c-index-test/CMakeLists.txt (+1)
  • (modified) clang/tools/c-index-test/core_main.cpp (+1)
  • (modified) clang/tools/diagtool/CMakeLists.txt (+1)
  • (modified) clang/tools/diagtool/ShowEnabledWarnings.cpp (+1)
  • (modified) clang/tools/driver/cc1_main.cpp (+2-1)
  • (modified) clang/tools/libclang/CIndex.cpp (+2-1)
  • (modified) clang/tools/libclang/CIndexer.cpp (+2-1)
  • (modified) clang/tools/libclang/CMakeLists.txt (+1)
  • (modified) clang/tools/libclang/Indexing.cpp (+1)
  • (modified) clang/unittests/Driver/DXCModeTest.cpp (+1)
  • (modified) clang/unittests/Driver/ToolChainTest.cpp (+1)
  • (modified) clang/unittests/Frontend/ASTUnitTest.cpp (+4-2)
  • (modified) clang/unittests/Frontend/CompilerInstanceTest.cpp (+1)
  • (modified) clang/unittests/Frontend/UtilsTest.cpp (+1)
  • (modified) clang/unittests/Sema/CMakeLists.txt (+1)
  • (modified) clang/unittests/Sema/SemaNoloadLookupTest.cpp (+1)
  • (modified) clang/unittests/Serialization/ForceCheckFileInputTest.cpp (+1)
  • (modified) clang/unittests/Serialization/LoadSpecLazilyTest.cpp (+1)
  • (modified) clang/unittests/Serialization/ModuleCacheTest.cpp (+1)
  • (modified) clang/unittests/Serialization/NoCommentsTest.cpp (+1)
  • (modified) clang/unittests/Serialization/PreambleInNamedModulesTest.cpp (+1)
  • (modified) clang/unittests/Serialization/VarDeclConstantInitTest.cpp (+1)
  • (modified) clang/unittests/Tooling/Syntax/TokensTest.cpp (+1)
  • (modified) clang/unittests/Tooling/Syntax/TreeTestBase.cpp (+1)
  • (modified) flang/lib/Frontend/CMakeLists.txt (-1)
  • (modified) flang/lib/Frontend/CompilerInvocation.cpp (+2-3)
  • (modified) lldb/source/Commands/CommandObjectTarget.cpp (+1)
  • (modified) lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt (+1-1)
  • (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangHost.cpp (+2-2)
  • (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp (+1)
  • (modified) lldb/unittests/Expression/ClangParserTest.cpp (+2-2)
diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp
index 7990f2719e9a0..4eda330716f21 100644
--- a/clang-tools-extra/clangd/CompileCommands.cpp
+++ b/clang-tools-extra/clangd/CompileCommands.cpp
@@ -132,8 +132,7 @@ std::optional<std::string> detectSysroot() {
 
 std::string detectStandardResourceDir() {
   static int StaticForMainAddr; // Just an address in this process.
-  return CompilerInvocation::GetResourcesPath("clangd",
-                                              (void *)&StaticForMainAddr);
+  return GetResourcesPath("clangd", (void *)&StaticForMainAddr);
 }
 
 // The path passed to argv[0] is important:
diff --git a/clang-tools-extra/clangd/Compiler.cpp b/clang-tools-extra/clangd/Compiler.cpp
index 6ebc2eac25745..9ea7df139382a 100644
--- a/clang-tools-extra/clangd/Compiler.cpp
+++ b/clang-tools-extra/clangd/Compiler.cpp
@@ -9,6 +9,7 @@
 #include "Compiler.h"
 #include "support/Logger.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Driver/CreateInvocationFromArgs.h"
 #include "clang/Frontend/CompilerInvocation.h"
 #include "clang/Lex/PreprocessorOptions.h"
 #include "clang/Serialization/PCHContainerOperations.h"
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c6a79ed71ca2f..c4d968bd01b65 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -84,6 +84,8 @@ Potentially Breaking Changes
 - Downstream projects that previously linked only against ``clangDriver`` may
   now (also) need to link against the new ``clangOptions`` library, since
   options-related code has been moved out of the Driver into a separate library.
+- The ``clangFrontend`` library no longer depends on ``clangDriver``, which may
+  break downstream projects that relied on this transitive dependency.
 
 C/C++ Language Potentially Breaking Changes
 -------------------------------------------
diff --git a/clang/include/clang/Driver/CommonArgs.h b/clang/include/clang/Driver/CommonArgs.h
index ac17d6211d882..264bd4965f9ad 100644
--- a/clang/include/clang/Driver/CommonArgs.h
+++ b/clang/include/clang/Driver/CommonArgs.h
@@ -291,16 +291,6 @@ void handleVectorizeLoopsArgs(const llvm::opt::ArgList &Args,
 void handleVectorizeSLPArgs(const llvm::opt::ArgList &Args,
                             llvm::opt::ArgStringList &CmdArgs);
 
-// Parse -mprefer-vector-width=. Return the Value string if well-formed.
-// Otherwise, return an empty string and issue a diagnosic message if needed.
-StringRef parseMPreferVectorWidthOption(clang::DiagnosticsEngine &Diags,
-                                        const llvm::opt::ArgList &Args);
-
-// Parse -mrecip. Return the Value string if well-formed.
-// Otherwise, return an empty string and issue a diagnosic message if needed.
-StringRef parseMRecipOption(clang::DiagnosticsEngine &Diags,
-                            const llvm::opt::ArgList &Args);
-
 // Convert ComplexRangeKind to a string that can be passed as a frontend option.
 std::string complexRangeKindToStr(LangOptions::ComplexRangeKind Range);
 
diff --git a/clang/include/clang/Driver/CreateASTUnitFromArgs.h b/clang/include/clang/Driver/CreateASTUnitFromArgs.h
new file mode 100644
index 0000000000000..30575cc04ca7c
--- /dev/null
+++ b/clang/include/clang/Driver/CreateASTUnitFromArgs.h
@@ -0,0 +1,80 @@
+//===-- CreateInvocationFromArgs.h - Create an ASTUnit from Args-*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utility for creating an ASTUnit from a vector of command line arguments.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DRIVER_CREATEASTUNITFROMARGS_H
+#define LLVM_CLANG_DRIVER_CREATEASTUNITFROMARGS_H
+
+#include "clang/Frontend/ASTUnit.h"
+
+namespace clang {
+
+/// Create an ASTUnit from a vector of command line arguments, which must
+/// specify exactly one source file.
+///
+/// \param ArgBegin - The beginning of the argument vector.
+///
+/// \param ArgEnd - The end of the argument vector.
+///
+/// \param PCHContainerOps - The PCHContainerOperations to use for loading and
+/// creating modules.
+///
+/// \param Diags - The diagnostics engine to use for reporting errors; its
+/// lifetime is expected to extend past that of the returned ASTUnit.
+///
+/// \param ResourceFilesPath - The path to the compiler resource files.
+///
+/// \param StorePreamblesInMemory - Whether to store PCH in memory. If false,
+/// PCH are stored in temporary files.
+///
+/// \param PreambleStoragePath - The path to a directory, in which to create
+/// temporary PCH files. If empty, the default system temporary directory is
+/// used. This parameter is ignored if \p StorePreamblesInMemory is true.
+///
+/// \param ModuleFormat - If provided, uses the specific module format.
+///
+/// \param ErrAST - If non-null and parsing failed without any AST to return
+/// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
+/// mainly to allow the caller to see the diagnostics.
+///
+/// \param VFS - A llvm::vfs::FileSystem to be used for all file accesses.
+/// Note that preamble is saved to a temporary directory on a RealFileSystem,
+/// so in order for it to be loaded correctly, VFS should have access to
+/// it(i.e., be an overlay over RealFileSystem). RealFileSystem will be used
+/// if \p VFS is nullptr.
+///
+// FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
+// shouldn't need to specify them at construction time.
+std::unique_ptr<ASTUnit> CreateASTUnitFromCommandLine(
+    const char **ArgBegin, const char **ArgEnd,
+    std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+    std::shared_ptr<DiagnosticOptions> DiagOpts,
+    IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
+    bool StorePreamblesInMemory = false,
+    StringRef PreambleStoragePath = StringRef(), bool OnlyLocalDecls = false,
+    CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None,
+    ArrayRef<ASTUnit::RemappedFile> RemappedFiles = {},
+    bool RemappedFilesKeepOriginalName = true,
+    unsigned PrecompilePreambleAfterNParses = 0,
+    TranslationUnitKind TUKind = TU_Complete,
+    bool CacheCodeCompletionResults = false,
+    bool IncludeBriefCommentsInCodeCompletion = false,
+    bool AllowPCHWithCompilerErrors = false,
+    SkipFunctionBodiesScope SkipFunctionBodies = SkipFunctionBodiesScope::None,
+    bool SingleFileParse = false, bool UserFilesAreVolatile = false,
+    bool ForSerialization = false, bool RetainExcludedConditionalBlocks = false,
+    std::optional<StringRef> ModuleFormat = std::nullopt,
+    std::unique_ptr<ASTUnit> *ErrAST = nullptr,
+    IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
+
+} // namespace clang
+
+#endif // LLVM_CLANG_DRIVER_CREATEASTUNITFROMARGS_H
diff --git a/clang/include/clang/Driver/CreateInvocationFromArgs.h b/clang/include/clang/Driver/CreateInvocationFromArgs.h
new file mode 100644
index 0000000000000..0e0f67373ce87
--- /dev/null
+++ b/clang/include/clang/Driver/CreateInvocationFromArgs.h
@@ -0,0 +1,76 @@
+//===--- CreateInvocationFromArgs.h - CompilerInvocation from Args --------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utility for creating a CompilerInvocation from command-line arguments, for
+// tools to use in preparation to parse a file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DRIVER_CREATEINVOCATIONFROMARGS_H
+#define LLVM_CLANG_DRIVER_CREATEINVOCATIONFROMARGS_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace clang {
+
+class CompilerInvocation;
+class DiagnosticsEngine;
+
+/// Optional inputs to createInvocation.
+struct CreateInvocationOptions {
+  /// Receives diagnostics encountered while parsing command-line flags.
+  /// If not provided, these are printed to stderr.
+  IntrusiveRefCntPtr<DiagnosticsEngine> Diags = nullptr;
+  /// Used e.g. to probe for system headers locations.
+  /// If not provided, the real filesystem is used.
+  /// FIXME: the driver does perform some non-virtualized IO.
+  IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr;
+  /// Whether to attempt to produce a non-null (possibly incorrect) invocation
+  /// if any errors were encountered.
+  /// By default, always return null on errors.
+  bool RecoverOnError = false;
+  /// Allow the driver to probe the filesystem for PCH files.
+  /// This is used to replace -include with -include-pch in the cc1 args.
+  /// FIXME: ProbePrecompiled=true is a poor, historical default.
+  /// It misbehaves if the PCH file is from GCC, has the wrong version, etc.
+  bool ProbePrecompiled = false;
+  /// If set, the target is populated with the cc1 args produced by the driver.
+  /// This may be populated even if createInvocation returns nullptr.
+  std::vector<std::string> *CC1Args = nullptr;
+};
+
+/// Interpret clang arguments in preparation to parse a file.
+///
+/// This simulates a number of steps Clang takes when its driver is invoked:
+/// - choosing actions (e.g compile + link) to run
+/// - probing the system for settings like standard library locations
+/// - spawning a cc1 subprocess to compile code, with more explicit arguments
+/// - in the cc1 process, assembling those arguments into a CompilerInvocation
+///   which is used to configure the parser
+///
+/// This simulation is lossy, e.g. in some situations one driver run would
+/// result in multiple parses. (Multi-arch, CUDA, ...).
+/// This function tries to select a reasonable invocation that tools should use.
+///
+/// Args[0] should be the driver name, such as "clang" or "/usr/bin/g++".
+/// Absolute path is preferred - this affects searching for system headers.
+///
+/// May return nullptr if an invocation could not be determined.
+/// See CreateInvocationOptions::RecoverOnError to try harder!
+std::unique_ptr<CompilerInvocation>
+createInvocation(ArrayRef<const char *> Args,
+                 CreateInvocationOptions Opts = {});
+
+} // namespace clang
+
+#endif // LLVM_CLANG_DRIVER_CREATEINVOCATIONFROMARGS_H
diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index 83bcb7cab550f..76a6c5a128efb 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -406,10 +406,6 @@ class Driver {
                               SmallString<128> &CrashDiagDir);
 
 public:
-  /// Takes the path to a binary that's either in bin/ or lib/ and returns
-  /// the path to clang's resource directory.
-  static std::string GetResourcesPath(StringRef BinaryPath);
-
   Driver(StringRef ClangExecutable, StringRef TargetTriple,
          DiagnosticsEngine &Diags, std::string Title = "clang LLVM compiler",
          IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h
index e585933a5c8be..341460e1962cb 100644
--- a/clang/include/clang/Frontend/ASTUnit.h
+++ b/clang/include/clang/Frontend/ASTUnit.h
@@ -23,11 +23,13 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetOptions.h"
 #include "clang/Frontend/PrecompiledPreamble.h"
+#include "clang/Frontend/StandaloneDiagnostic.h"
 #include "clang/Lex/HeaderSearchOptions.h"
 #include "clang/Lex/ModuleLoader.h"
 #include "clang/Lex/PreprocessingRecord.h"
 #include "clang/Sema/CodeCompleteConsumer.h"
 #include "clang/Serialization/ASTBitCodes.h"
+#include "clang/Serialization/ASTWriter.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -36,6 +38,7 @@
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator_range.h"
+#include "llvm/Bitstream/BitstreamWriter.h"
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
@@ -88,25 +91,6 @@ enum class CaptureDiagsKind { None, All, AllWithoutNonErrorsFromIncludes };
 
 /// Utility class for loading a ASTContext from an AST file.
 class ASTUnit {
-public:
-  struct StandaloneFixIt {
-    std::pair<unsigned, unsigned> RemoveRange;
-    std::pair<unsigned, unsigned> InsertFromRange;
-    std::string CodeToInsert;
-    bool BeforePreviousInsertions;
-  };
-
-  struct StandaloneDiagnostic {
-    unsigned ID;
-    DiagnosticsEngine::Level Level;
-    std::string Message;
-    std::string Filename;
-    unsigned LocOffset;
-    std::vector<std::pair<unsigned, unsigned>> Ranges;
-    std::vector<StandaloneFixIt> FixIts;
-  };
-
-private:
   std::unique_ptr<LangOptions> LangOpts;
   std::unique_ptr<CodeGenOptions> CodeGenOpts;
   // FIXME: The documentation on \c LoadFrom* member functions states that the
@@ -129,7 +113,15 @@ class ASTUnit {
   bool HadModuleLoaderFatalFailure = false;
   bool StorePreamblesInMemory = false;
 
-  struct ASTWriterData;
+  /// Utility struct for managing ASTWriter and its associated data streams.
+  struct ASTWriterData {
+    SmallString<128> Buffer;
+    llvm::BitstreamWriter Stream;
+    ASTWriter Writer;
+
+    ASTWriterData(ModuleCache &ModCache, const CodeGenOptions &CGOpts)
+        : Stream(Buffer), Writer(Stream, Buffer, ModCache, CGOpts, {}) {}
+  };
   std::unique_ptr<ASTWriterData> WriterData;
 
   FileSystemOptions FileSystemOpts;
@@ -271,11 +263,6 @@ class ASTUnit {
   static void ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
                              ASTUnit &AST, CaptureDiagsKind CaptureDiagnostics);
 
-  void
-  TranslateStoredDiagnostics(FileManager &FileMgr, SourceManager &SrcMan,
-                             const SmallVectorImpl<StandaloneDiagnostic> &Diags,
-                             SmallVectorImpl<StoredDiagnostic> &Out);
-
   void clearFileLevelDecls();
 
 public:
@@ -834,65 +821,24 @@ class ASTUnit {
       bool IncludeBriefCommentsInCodeCompletion = false,
       bool UserFilesAreVolatile = false);
 
-  /// LoadFromCommandLine - Create an ASTUnit from a vector of command line
-  /// arguments, which must specify exactly one source file.
-  ///
-  /// \param ArgBegin - The beginning of the argument vector.
-  ///
-  /// \param ArgEnd - The end of the argument vector.
-  ///
-  /// \param PCHContainerOps - The PCHContainerOperations to use for loading and
-  /// creating modules.
-  ///
-  /// \param Diags - The diagnostics engine to use for reporting errors; its
-  /// lifetime is expected to extend past that of the returned ASTUnit.
-  ///
-  /// \param ResourceFilesPath - The path to the compiler resource files.
-  ///
-  /// \param StorePreamblesInMemory - Whether to store PCH in memory. If false,
-  /// PCH are stored in temporary files.
-  ///
-  /// \param PreambleStoragePath - The path to a directory, in which to create
-  /// temporary PCH files. If empty, the default system temporary directory is
-  /// used. This parameter is ignored if \p StorePreamblesInMemory is true.
-  ///
-  /// \param ModuleFormat - If provided, uses the specific module format.
-  ///
-  /// \param ErrAST - If non-null and parsing failed without any AST to return
-  /// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
-  /// mainly to allow the caller to see the diagnostics.
-  ///
-  /// \param VFS - A llvm::vfs::FileSystem to be used for all file accesses.
-  /// Note that preamble is saved to a temporary directory on a RealFileSystem,
-  /// so in order for it to be loaded correctly, VFS should have access to
-  /// it(i.e., be an overlay over RealFileSystem). RealFileSystem will be used
-  /// if \p VFS is nullptr.
-  ///
-  // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
-  // shouldn't need to specify them at construction time.
-  static std::unique_ptr<ASTUnit> LoadFromCommandLine(
+  friend std::unique_ptr<ASTUnit> CreateASTUnitFromCommandLine(
       const char **ArgBegin, const char **ArgEnd,
       std::shared_ptr<PCHContainerOperations> PCHContainerOps,
       std::shared_ptr<DiagnosticOptions> DiagOpts,
       IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
-      bool StorePreamblesInMemory = false,
-      StringRef PreambleStoragePath = StringRef(), bool OnlyLocalDecls = false,
-      CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None,
-      ArrayRef<RemappedFile> RemappedFiles = {},
-      bool RemappedFilesKeepOriginalName = true,
-      unsigned PrecompilePreambleAfterNParses = 0,
-      TranslationUnitKind TUKind = TU_Complete,
-      bool CacheCodeCompletionResults = false,
-      bool IncludeBriefCommentsInCodeCompletion = false,
-      bool AllowPCHWithCompilerErrors = false,
-      SkipFunctionBodiesScope SkipFunctionBodies =
-          SkipFunctionBodiesScope::None,
-      bool SingleFileParse = false, bool UserFilesAreVolatile = false,
-      bool ForSerialization = false,
-      bool RetainExcludedConditionalBlocks = false,
-      std::optional<StringRef> ModuleFormat = std::nullopt,
-      std::unique_ptr<ASTUnit> *ErrAST = nullptr,
-      IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
+      bool StorePreamblesInMemory, StringRef PreambleStoragePath,
+      bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,
+      ArrayRef<ASTUnit::RemappedFile> RemappedFiles,
+      bool RemappedFilesKeepOriginalName,
+      unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
+      bool CacheCodeCompletionResults,
+      bool IncludeBriefCommentsInCodeCompletion,
+      bool AllowPCHWithCompilerErrors,
+      SkipFunctionBodiesScope SkipFunctionBodies, bool SingleFileParse,
+      bool UserFilesAreVolatile, bool ForSerialization,
+      bool RetainExcludedConditionalBlocks,
+      std::optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST,
+      IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS);
 
   /// Reparse the source files using the same command-line options that
   /// were originally used to produce this translation unit.
@@ -963,6 +909,44 @@ class ASTUnit {
   bool serialize(raw_ostream &OS);
 };
 
+/// Diagnostic consumer that saves each diagnostic it is given.
+class FilterAndStoreDiagnosticConsumer : public DiagnosticConsumer {
+  SmallVectorImpl<StoredDiagnostic> *StoredDiags;
+  SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags;
+  bool CaptureNonErrorsFromIncludes = true;
+  const LangOptions *LangOpts = nullptr;
+  SourceManager *SourceMgr = nullptr;
+
+public:
+  FilterAndStoreDiagnosticConsumer(
+      SmallVectorImpl<StoredDiagnostic> *StoredDiags,
+      SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags,
+      bool CaptureNonErrorsFromIncludes);
+
+  void BeginSourceFile(const LangOptions &LangOpts,
+                       const Preprocessor *PP = nullptr) override;
+
+  void HandleDiagnostic(DiagnosticsEngine::Level Level,
+                        const Diagnostic &Info) override;
+};
+
+/// RAII object that optionally captures and filters diagnostics, if
+/// there is no diagnostic client to capture them already.
+class CaptureDroppedDiagnostics {
+  DiagnosticsEngine &Diags;
+  FilterAndStoreDiagnosticConsumer Client;
+  DiagnosticConsumer *PreviousClient = nullptr;
+  std::unique_ptr<DiagnosticConsumer> OwningPreviousClient;
+
+public:
+  CaptureDroppedDiagnostics(
+      CaptureDiagsKind CaptureDiagnostics, DiagnosticsEngine &Diags,
+      SmallVectorImpl<StoredDiagnostic> *StoredDiags,
+      SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags);
+
+  ~CaptureDroppedDiagnostics();
+};
+
 } // namespace clang
 
 #endif // LLVM_CLANG_FRONTEND_ASTUNIT_H
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h
index b19a6e1a8acc3..4977ddb307d21 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -299,16 +299,6 @@ class CompilerInvocation : public CompilerInvocationBase {
                 ...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Nov 26, 2025

@llvm/pr-subscribers-flang-driver

Author: Naveen Seth Hanig (naveen-seth)

Changes

This reapplies 3773bbe by reverting a96ec1c.

The original revert was due to a report of a broken build, which was later resolved by fully clearing the build directory.


Patch is 103.65 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/169597.diff

60 Files Affected:

  • (modified) clang-tools-extra/clangd/CompileCommands.cpp (+1-2)
  • (modified) clang-tools-extra/clangd/Compiler.cpp (+1)
  • (modified) clang/docs/ReleaseNotes.rst (+2)
  • (modified) clang/include/clang/Driver/CommonArgs.h (-10)
  • (added) clang/include/clang/Driver/CreateASTUnitFromArgs.h (+80)
  • (added) clang/include/clang/Driver/CreateInvocationFromArgs.h (+76)
  • (modified) clang/include/clang/Driver/Driver.h (-4)
  • (modified) clang/include/clang/Frontend/ASTUnit.h (+64-80)
  • (modified) clang/include/clang/Frontend/CompilerInvocation.h (-10)
  • (added) clang/include/clang/Frontend/StandaloneDiagnostic.h (+82)
  • (modified) clang/include/clang/Frontend/Utils.h (-45)
  • (modified) clang/include/clang/Options/OptionUtils.h (+24)
  • (modified) clang/lib/CrossTU/CMakeLists.txt (+1)
  • (modified) clang/lib/CrossTU/CrossTranslationUnit.cpp (+2-1)
  • (modified) clang/lib/Driver/CMakeLists.txt (+4)
  • (added) clang/lib/Driver/CreateASTUnitFromArgs.cpp (+166)
  • (renamed) clang/lib/Driver/CreateInvocationFromArgs.cpp (+8-5)
  • (modified) clang/lib/Driver/Driver.cpp (+1-34)
  • (modified) clang/lib/Driver/ToolChains/Clang.cpp (+1)
  • (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (-163)
  • (modified) clang/lib/Driver/ToolChains/Flang.cpp (+1)
  • (modified) clang/lib/Frontend/ASTUnit.cpp (+51-292)
  • (modified) clang/lib/Frontend/CMakeLists.txt (+1-2)
  • (modified) clang/lib/Frontend/CompilerInvocation.cpp (-8)
  • (added) clang/lib/Frontend/StandaloneDiagnostic.cpp (+117)
  • (modified) clang/lib/Interpreter/CMakeLists.txt (+1)
  • (modified) clang/lib/Interpreter/Interpreter.cpp (+2-1)
  • (modified) clang/lib/Options/OptionUtils.cpp (+207-8)
  • (modified) clang/lib/Tooling/Tooling.cpp (+2-2)
  • (modified) clang/tools/c-index-test/CMakeLists.txt (+1)
  • (modified) clang/tools/c-index-test/core_main.cpp (+1)
  • (modified) clang/tools/diagtool/CMakeLists.txt (+1)
  • (modified) clang/tools/diagtool/ShowEnabledWarnings.cpp (+1)
  • (modified) clang/tools/driver/cc1_main.cpp (+2-1)
  • (modified) clang/tools/libclang/CIndex.cpp (+2-1)
  • (modified) clang/tools/libclang/CIndexer.cpp (+2-1)
  • (modified) clang/tools/libclang/CMakeLists.txt (+1)
  • (modified) clang/tools/libclang/Indexing.cpp (+1)
  • (modified) clang/unittests/Driver/DXCModeTest.cpp (+1)
  • (modified) clang/unittests/Driver/ToolChainTest.cpp (+1)
  • (modified) clang/unittests/Frontend/ASTUnitTest.cpp (+4-2)
  • (modified) clang/unittests/Frontend/CompilerInstanceTest.cpp (+1)
  • (modified) clang/unittests/Frontend/UtilsTest.cpp (+1)
  • (modified) clang/unittests/Sema/CMakeLists.txt (+1)
  • (modified) clang/unittests/Sema/SemaNoloadLookupTest.cpp (+1)
  • (modified) clang/unittests/Serialization/ForceCheckFileInputTest.cpp (+1)
  • (modified) clang/unittests/Serialization/LoadSpecLazilyTest.cpp (+1)
  • (modified) clang/unittests/Serialization/ModuleCacheTest.cpp (+1)
  • (modified) clang/unittests/Serialization/NoCommentsTest.cpp (+1)
  • (modified) clang/unittests/Serialization/PreambleInNamedModulesTest.cpp (+1)
  • (modified) clang/unittests/Serialization/VarDeclConstantInitTest.cpp (+1)
  • (modified) clang/unittests/Tooling/Syntax/TokensTest.cpp (+1)
  • (modified) clang/unittests/Tooling/Syntax/TreeTestBase.cpp (+1)
  • (modified) flang/lib/Frontend/CMakeLists.txt (-1)
  • (modified) flang/lib/Frontend/CompilerInvocation.cpp (+2-3)
  • (modified) lldb/source/Commands/CommandObjectTarget.cpp (+1)
  • (modified) lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt (+1-1)
  • (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangHost.cpp (+2-2)
  • (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp (+1)
  • (modified) lldb/unittests/Expression/ClangParserTest.cpp (+2-2)
diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp
index 7990f2719e9a0..4eda330716f21 100644
--- a/clang-tools-extra/clangd/CompileCommands.cpp
+++ b/clang-tools-extra/clangd/CompileCommands.cpp
@@ -132,8 +132,7 @@ std::optional<std::string> detectSysroot() {
 
 std::string detectStandardResourceDir() {
   static int StaticForMainAddr; // Just an address in this process.
-  return CompilerInvocation::GetResourcesPath("clangd",
-                                              (void *)&StaticForMainAddr);
+  return GetResourcesPath("clangd", (void *)&StaticForMainAddr);
 }
 
 // The path passed to argv[0] is important:
diff --git a/clang-tools-extra/clangd/Compiler.cpp b/clang-tools-extra/clangd/Compiler.cpp
index 6ebc2eac25745..9ea7df139382a 100644
--- a/clang-tools-extra/clangd/Compiler.cpp
+++ b/clang-tools-extra/clangd/Compiler.cpp
@@ -9,6 +9,7 @@
 #include "Compiler.h"
 #include "support/Logger.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Driver/CreateInvocationFromArgs.h"
 #include "clang/Frontend/CompilerInvocation.h"
 #include "clang/Lex/PreprocessorOptions.h"
 #include "clang/Serialization/PCHContainerOperations.h"
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c6a79ed71ca2f..c4d968bd01b65 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -84,6 +84,8 @@ Potentially Breaking Changes
 - Downstream projects that previously linked only against ``clangDriver`` may
   now (also) need to link against the new ``clangOptions`` library, since
   options-related code has been moved out of the Driver into a separate library.
+- The ``clangFrontend`` library no longer depends on ``clangDriver``, which may
+  break downstream projects that relied on this transitive dependency.
 
 C/C++ Language Potentially Breaking Changes
 -------------------------------------------
diff --git a/clang/include/clang/Driver/CommonArgs.h b/clang/include/clang/Driver/CommonArgs.h
index ac17d6211d882..264bd4965f9ad 100644
--- a/clang/include/clang/Driver/CommonArgs.h
+++ b/clang/include/clang/Driver/CommonArgs.h
@@ -291,16 +291,6 @@ void handleVectorizeLoopsArgs(const llvm::opt::ArgList &Args,
 void handleVectorizeSLPArgs(const llvm::opt::ArgList &Args,
                             llvm::opt::ArgStringList &CmdArgs);
 
-// Parse -mprefer-vector-width=. Return the Value string if well-formed.
-// Otherwise, return an empty string and issue a diagnosic message if needed.
-StringRef parseMPreferVectorWidthOption(clang::DiagnosticsEngine &Diags,
-                                        const llvm::opt::ArgList &Args);
-
-// Parse -mrecip. Return the Value string if well-formed.
-// Otherwise, return an empty string and issue a diagnosic message if needed.
-StringRef parseMRecipOption(clang::DiagnosticsEngine &Diags,
-                            const llvm::opt::ArgList &Args);
-
 // Convert ComplexRangeKind to a string that can be passed as a frontend option.
 std::string complexRangeKindToStr(LangOptions::ComplexRangeKind Range);
 
diff --git a/clang/include/clang/Driver/CreateASTUnitFromArgs.h b/clang/include/clang/Driver/CreateASTUnitFromArgs.h
new file mode 100644
index 0000000000000..30575cc04ca7c
--- /dev/null
+++ b/clang/include/clang/Driver/CreateASTUnitFromArgs.h
@@ -0,0 +1,80 @@
+//===-- CreateInvocationFromArgs.h - Create an ASTUnit from Args-*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utility for creating an ASTUnit from a vector of command line arguments.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DRIVER_CREATEASTUNITFROMARGS_H
+#define LLVM_CLANG_DRIVER_CREATEASTUNITFROMARGS_H
+
+#include "clang/Frontend/ASTUnit.h"
+
+namespace clang {
+
+/// Create an ASTUnit from a vector of command line arguments, which must
+/// specify exactly one source file.
+///
+/// \param ArgBegin - The beginning of the argument vector.
+///
+/// \param ArgEnd - The end of the argument vector.
+///
+/// \param PCHContainerOps - The PCHContainerOperations to use for loading and
+/// creating modules.
+///
+/// \param Diags - The diagnostics engine to use for reporting errors; its
+/// lifetime is expected to extend past that of the returned ASTUnit.
+///
+/// \param ResourceFilesPath - The path to the compiler resource files.
+///
+/// \param StorePreamblesInMemory - Whether to store PCH in memory. If false,
+/// PCH are stored in temporary files.
+///
+/// \param PreambleStoragePath - The path to a directory, in which to create
+/// temporary PCH files. If empty, the default system temporary directory is
+/// used. This parameter is ignored if \p StorePreamblesInMemory is true.
+///
+/// \param ModuleFormat - If provided, uses the specific module format.
+///
+/// \param ErrAST - If non-null and parsing failed without any AST to return
+/// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
+/// mainly to allow the caller to see the diagnostics.
+///
+/// \param VFS - A llvm::vfs::FileSystem to be used for all file accesses.
+/// Note that preamble is saved to a temporary directory on a RealFileSystem,
+/// so in order for it to be loaded correctly, VFS should have access to
+/// it(i.e., be an overlay over RealFileSystem). RealFileSystem will be used
+/// if \p VFS is nullptr.
+///
+// FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
+// shouldn't need to specify them at construction time.
+std::unique_ptr<ASTUnit> CreateASTUnitFromCommandLine(
+    const char **ArgBegin, const char **ArgEnd,
+    std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+    std::shared_ptr<DiagnosticOptions> DiagOpts,
+    IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
+    bool StorePreamblesInMemory = false,
+    StringRef PreambleStoragePath = StringRef(), bool OnlyLocalDecls = false,
+    CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None,
+    ArrayRef<ASTUnit::RemappedFile> RemappedFiles = {},
+    bool RemappedFilesKeepOriginalName = true,
+    unsigned PrecompilePreambleAfterNParses = 0,
+    TranslationUnitKind TUKind = TU_Complete,
+    bool CacheCodeCompletionResults = false,
+    bool IncludeBriefCommentsInCodeCompletion = false,
+    bool AllowPCHWithCompilerErrors = false,
+    SkipFunctionBodiesScope SkipFunctionBodies = SkipFunctionBodiesScope::None,
+    bool SingleFileParse = false, bool UserFilesAreVolatile = false,
+    bool ForSerialization = false, bool RetainExcludedConditionalBlocks = false,
+    std::optional<StringRef> ModuleFormat = std::nullopt,
+    std::unique_ptr<ASTUnit> *ErrAST = nullptr,
+    IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
+
+} // namespace clang
+
+#endif // LLVM_CLANG_DRIVER_CREATEASTUNITFROMARGS_H
diff --git a/clang/include/clang/Driver/CreateInvocationFromArgs.h b/clang/include/clang/Driver/CreateInvocationFromArgs.h
new file mode 100644
index 0000000000000..0e0f67373ce87
--- /dev/null
+++ b/clang/include/clang/Driver/CreateInvocationFromArgs.h
@@ -0,0 +1,76 @@
+//===--- CreateInvocationFromArgs.h - CompilerInvocation from Args --------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utility for creating a CompilerInvocation from command-line arguments, for
+// tools to use in preparation to parse a file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DRIVER_CREATEINVOCATIONFROMARGS_H
+#define LLVM_CLANG_DRIVER_CREATEINVOCATIONFROMARGS_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace clang {
+
+class CompilerInvocation;
+class DiagnosticsEngine;
+
+/// Optional inputs to createInvocation.
+struct CreateInvocationOptions {
+  /// Receives diagnostics encountered while parsing command-line flags.
+  /// If not provided, these are printed to stderr.
+  IntrusiveRefCntPtr<DiagnosticsEngine> Diags = nullptr;
+  /// Used e.g. to probe for system headers locations.
+  /// If not provided, the real filesystem is used.
+  /// FIXME: the driver does perform some non-virtualized IO.
+  IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr;
+  /// Whether to attempt to produce a non-null (possibly incorrect) invocation
+  /// if any errors were encountered.
+  /// By default, always return null on errors.
+  bool RecoverOnError = false;
+  /// Allow the driver to probe the filesystem for PCH files.
+  /// This is used to replace -include with -include-pch in the cc1 args.
+  /// FIXME: ProbePrecompiled=true is a poor, historical default.
+  /// It misbehaves if the PCH file is from GCC, has the wrong version, etc.
+  bool ProbePrecompiled = false;
+  /// If set, the target is populated with the cc1 args produced by the driver.
+  /// This may be populated even if createInvocation returns nullptr.
+  std::vector<std::string> *CC1Args = nullptr;
+};
+
+/// Interpret clang arguments in preparation to parse a file.
+///
+/// This simulates a number of steps Clang takes when its driver is invoked:
+/// - choosing actions (e.g compile + link) to run
+/// - probing the system for settings like standard library locations
+/// - spawning a cc1 subprocess to compile code, with more explicit arguments
+/// - in the cc1 process, assembling those arguments into a CompilerInvocation
+///   which is used to configure the parser
+///
+/// This simulation is lossy, e.g. in some situations one driver run would
+/// result in multiple parses. (Multi-arch, CUDA, ...).
+/// This function tries to select a reasonable invocation that tools should use.
+///
+/// Args[0] should be the driver name, such as "clang" or "/usr/bin/g++".
+/// Absolute path is preferred - this affects searching for system headers.
+///
+/// May return nullptr if an invocation could not be determined.
+/// See CreateInvocationOptions::RecoverOnError to try harder!
+std::unique_ptr<CompilerInvocation>
+createInvocation(ArrayRef<const char *> Args,
+                 CreateInvocationOptions Opts = {});
+
+} // namespace clang
+
+#endif // LLVM_CLANG_DRIVER_CREATEINVOCATIONFROMARGS_H
diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index 83bcb7cab550f..76a6c5a128efb 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -406,10 +406,6 @@ class Driver {
                               SmallString<128> &CrashDiagDir);
 
 public:
-  /// Takes the path to a binary that's either in bin/ or lib/ and returns
-  /// the path to clang's resource directory.
-  static std::string GetResourcesPath(StringRef BinaryPath);
-
   Driver(StringRef ClangExecutable, StringRef TargetTriple,
          DiagnosticsEngine &Diags, std::string Title = "clang LLVM compiler",
          IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h
index e585933a5c8be..341460e1962cb 100644
--- a/clang/include/clang/Frontend/ASTUnit.h
+++ b/clang/include/clang/Frontend/ASTUnit.h
@@ -23,11 +23,13 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetOptions.h"
 #include "clang/Frontend/PrecompiledPreamble.h"
+#include "clang/Frontend/StandaloneDiagnostic.h"
 #include "clang/Lex/HeaderSearchOptions.h"
 #include "clang/Lex/ModuleLoader.h"
 #include "clang/Lex/PreprocessingRecord.h"
 #include "clang/Sema/CodeCompleteConsumer.h"
 #include "clang/Serialization/ASTBitCodes.h"
+#include "clang/Serialization/ASTWriter.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -36,6 +38,7 @@
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator_range.h"
+#include "llvm/Bitstream/BitstreamWriter.h"
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
@@ -88,25 +91,6 @@ enum class CaptureDiagsKind { None, All, AllWithoutNonErrorsFromIncludes };
 
 /// Utility class for loading a ASTContext from an AST file.
 class ASTUnit {
-public:
-  struct StandaloneFixIt {
-    std::pair<unsigned, unsigned> RemoveRange;
-    std::pair<unsigned, unsigned> InsertFromRange;
-    std::string CodeToInsert;
-    bool BeforePreviousInsertions;
-  };
-
-  struct StandaloneDiagnostic {
-    unsigned ID;
-    DiagnosticsEngine::Level Level;
-    std::string Message;
-    std::string Filename;
-    unsigned LocOffset;
-    std::vector<std::pair<unsigned, unsigned>> Ranges;
-    std::vector<StandaloneFixIt> FixIts;
-  };
-
-private:
   std::unique_ptr<LangOptions> LangOpts;
   std::unique_ptr<CodeGenOptions> CodeGenOpts;
   // FIXME: The documentation on \c LoadFrom* member functions states that the
@@ -129,7 +113,15 @@ class ASTUnit {
   bool HadModuleLoaderFatalFailure = false;
   bool StorePreamblesInMemory = false;
 
-  struct ASTWriterData;
+  /// Utility struct for managing ASTWriter and its associated data streams.
+  struct ASTWriterData {
+    SmallString<128> Buffer;
+    llvm::BitstreamWriter Stream;
+    ASTWriter Writer;
+
+    ASTWriterData(ModuleCache &ModCache, const CodeGenOptions &CGOpts)
+        : Stream(Buffer), Writer(Stream, Buffer, ModCache, CGOpts, {}) {}
+  };
   std::unique_ptr<ASTWriterData> WriterData;
 
   FileSystemOptions FileSystemOpts;
@@ -271,11 +263,6 @@ class ASTUnit {
   static void ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
                              ASTUnit &AST, CaptureDiagsKind CaptureDiagnostics);
 
-  void
-  TranslateStoredDiagnostics(FileManager &FileMgr, SourceManager &SrcMan,
-                             const SmallVectorImpl<StandaloneDiagnostic> &Diags,
-                             SmallVectorImpl<StoredDiagnostic> &Out);
-
   void clearFileLevelDecls();
 
 public:
@@ -834,65 +821,24 @@ class ASTUnit {
       bool IncludeBriefCommentsInCodeCompletion = false,
       bool UserFilesAreVolatile = false);
 
-  /// LoadFromCommandLine - Create an ASTUnit from a vector of command line
-  /// arguments, which must specify exactly one source file.
-  ///
-  /// \param ArgBegin - The beginning of the argument vector.
-  ///
-  /// \param ArgEnd - The end of the argument vector.
-  ///
-  /// \param PCHContainerOps - The PCHContainerOperations to use for loading and
-  /// creating modules.
-  ///
-  /// \param Diags - The diagnostics engine to use for reporting errors; its
-  /// lifetime is expected to extend past that of the returned ASTUnit.
-  ///
-  /// \param ResourceFilesPath - The path to the compiler resource files.
-  ///
-  /// \param StorePreamblesInMemory - Whether to store PCH in memory. If false,
-  /// PCH are stored in temporary files.
-  ///
-  /// \param PreambleStoragePath - The path to a directory, in which to create
-  /// temporary PCH files. If empty, the default system temporary directory is
-  /// used. This parameter is ignored if \p StorePreamblesInMemory is true.
-  ///
-  /// \param ModuleFormat - If provided, uses the specific module format.
-  ///
-  /// \param ErrAST - If non-null and parsing failed without any AST to return
-  /// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
-  /// mainly to allow the caller to see the diagnostics.
-  ///
-  /// \param VFS - A llvm::vfs::FileSystem to be used for all file accesses.
-  /// Note that preamble is saved to a temporary directory on a RealFileSystem,
-  /// so in order for it to be loaded correctly, VFS should have access to
-  /// it(i.e., be an overlay over RealFileSystem). RealFileSystem will be used
-  /// if \p VFS is nullptr.
-  ///
-  // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
-  // shouldn't need to specify them at construction time.
-  static std::unique_ptr<ASTUnit> LoadFromCommandLine(
+  friend std::unique_ptr<ASTUnit> CreateASTUnitFromCommandLine(
       const char **ArgBegin, const char **ArgEnd,
       std::shared_ptr<PCHContainerOperations> PCHContainerOps,
       std::shared_ptr<DiagnosticOptions> DiagOpts,
       IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
-      bool StorePreamblesInMemory = false,
-      StringRef PreambleStoragePath = StringRef(), bool OnlyLocalDecls = false,
-      CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None,
-      ArrayRef<RemappedFile> RemappedFiles = {},
-      bool RemappedFilesKeepOriginalName = true,
-      unsigned PrecompilePreambleAfterNParses = 0,
-      TranslationUnitKind TUKind = TU_Complete,
-      bool CacheCodeCompletionResults = false,
-      bool IncludeBriefCommentsInCodeCompletion = false,
-      bool AllowPCHWithCompilerErrors = false,
-      SkipFunctionBodiesScope SkipFunctionBodies =
-          SkipFunctionBodiesScope::None,
-      bool SingleFileParse = false, bool UserFilesAreVolatile = false,
-      bool ForSerialization = false,
-      bool RetainExcludedConditionalBlocks = false,
-      std::optional<StringRef> ModuleFormat = std::nullopt,
-      std::unique_ptr<ASTUnit> *ErrAST = nullptr,
-      IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
+      bool StorePreamblesInMemory, StringRef PreambleStoragePath,
+      bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,
+      ArrayRef<ASTUnit::RemappedFile> RemappedFiles,
+      bool RemappedFilesKeepOriginalName,
+      unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
+      bool CacheCodeCompletionResults,
+      bool IncludeBriefCommentsInCodeCompletion,
+      bool AllowPCHWithCompilerErrors,
+      SkipFunctionBodiesScope SkipFunctionBodies, bool SingleFileParse,
+      bool UserFilesAreVolatile, bool ForSerialization,
+      bool RetainExcludedConditionalBlocks,
+      std::optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST,
+      IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS);
 
   /// Reparse the source files using the same command-line options that
   /// were originally used to produce this translation unit.
@@ -963,6 +909,44 @@ class ASTUnit {
   bool serialize(raw_ostream &OS);
 };
 
+/// Diagnostic consumer that saves each diagnostic it is given.
+class FilterAndStoreDiagnosticConsumer : public DiagnosticConsumer {
+  SmallVectorImpl<StoredDiagnostic> *StoredDiags;
+  SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags;
+  bool CaptureNonErrorsFromIncludes = true;
+  const LangOptions *LangOpts = nullptr;
+  SourceManager *SourceMgr = nullptr;
+
+public:
+  FilterAndStoreDiagnosticConsumer(
+      SmallVectorImpl<StoredDiagnostic> *StoredDiags,
+      SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags,
+      bool CaptureNonErrorsFromIncludes);
+
+  void BeginSourceFile(const LangOptions &LangOpts,
+                       const Preprocessor *PP = nullptr) override;
+
+  void HandleDiagnostic(DiagnosticsEngine::Level Level,
+                        const Diagnostic &Info) override;
+};
+
+/// RAII object that optionally captures and filters diagnostics, if
+/// there is no diagnostic client to capture them already.
+class CaptureDroppedDiagnostics {
+  DiagnosticsEngine &Diags;
+  FilterAndStoreDiagnosticConsumer Client;
+  DiagnosticConsumer *PreviousClient = nullptr;
+  std::unique_ptr<DiagnosticConsumer> OwningPreviousClient;
+
+public:
+  CaptureDroppedDiagnostics(
+      CaptureDiagsKind CaptureDiagnostics, DiagnosticsEngine &Diags,
+      SmallVectorImpl<StoredDiagnostic> *StoredDiags,
+      SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags);
+
+  ~CaptureDroppedDiagnostics();
+};
+
 } // namespace clang
 
 #endif // LLVM_CLANG_FRONTEND_ASTUNIT_H
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h
index b19a6e1a8acc3..4977ddb307d21 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -299,16 +299,6 @@ class CompilerInvocation : public CompilerInvocationBase {
                 ...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Nov 26, 2025

@llvm/pr-subscribers-clang-tools-extra

Author: Naveen Seth Hanig (naveen-seth)

Changes

This reapplies 3773bbe by reverting a96ec1c.

The original revert was due to a report of a broken build, which was later resolved by fully clearing the build directory.


Patch is 103.65 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/169597.diff

60 Files Affected:

  • (modified) clang-tools-extra/clangd/CompileCommands.cpp (+1-2)
  • (modified) clang-tools-extra/clangd/Compiler.cpp (+1)
  • (modified) clang/docs/ReleaseNotes.rst (+2)
  • (modified) clang/include/clang/Driver/CommonArgs.h (-10)
  • (added) clang/include/clang/Driver/CreateASTUnitFromArgs.h (+80)
  • (added) clang/include/clang/Driver/CreateInvocationFromArgs.h (+76)
  • (modified) clang/include/clang/Driver/Driver.h (-4)
  • (modified) clang/include/clang/Frontend/ASTUnit.h (+64-80)
  • (modified) clang/include/clang/Frontend/CompilerInvocation.h (-10)
  • (added) clang/include/clang/Frontend/StandaloneDiagnostic.h (+82)
  • (modified) clang/include/clang/Frontend/Utils.h (-45)
  • (modified) clang/include/clang/Options/OptionUtils.h (+24)
  • (modified) clang/lib/CrossTU/CMakeLists.txt (+1)
  • (modified) clang/lib/CrossTU/CrossTranslationUnit.cpp (+2-1)
  • (modified) clang/lib/Driver/CMakeLists.txt (+4)
  • (added) clang/lib/Driver/CreateASTUnitFromArgs.cpp (+166)
  • (renamed) clang/lib/Driver/CreateInvocationFromArgs.cpp (+8-5)
  • (modified) clang/lib/Driver/Driver.cpp (+1-34)
  • (modified) clang/lib/Driver/ToolChains/Clang.cpp (+1)
  • (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (-163)
  • (modified) clang/lib/Driver/ToolChains/Flang.cpp (+1)
  • (modified) clang/lib/Frontend/ASTUnit.cpp (+51-292)
  • (modified) clang/lib/Frontend/CMakeLists.txt (+1-2)
  • (modified) clang/lib/Frontend/CompilerInvocation.cpp (-8)
  • (added) clang/lib/Frontend/StandaloneDiagnostic.cpp (+117)
  • (modified) clang/lib/Interpreter/CMakeLists.txt (+1)
  • (modified) clang/lib/Interpreter/Interpreter.cpp (+2-1)
  • (modified) clang/lib/Options/OptionUtils.cpp (+207-8)
  • (modified) clang/lib/Tooling/Tooling.cpp (+2-2)
  • (modified) clang/tools/c-index-test/CMakeLists.txt (+1)
  • (modified) clang/tools/c-index-test/core_main.cpp (+1)
  • (modified) clang/tools/diagtool/CMakeLists.txt (+1)
  • (modified) clang/tools/diagtool/ShowEnabledWarnings.cpp (+1)
  • (modified) clang/tools/driver/cc1_main.cpp (+2-1)
  • (modified) clang/tools/libclang/CIndex.cpp (+2-1)
  • (modified) clang/tools/libclang/CIndexer.cpp (+2-1)
  • (modified) clang/tools/libclang/CMakeLists.txt (+1)
  • (modified) clang/tools/libclang/Indexing.cpp (+1)
  • (modified) clang/unittests/Driver/DXCModeTest.cpp (+1)
  • (modified) clang/unittests/Driver/ToolChainTest.cpp (+1)
  • (modified) clang/unittests/Frontend/ASTUnitTest.cpp (+4-2)
  • (modified) clang/unittests/Frontend/CompilerInstanceTest.cpp (+1)
  • (modified) clang/unittests/Frontend/UtilsTest.cpp (+1)
  • (modified) clang/unittests/Sema/CMakeLists.txt (+1)
  • (modified) clang/unittests/Sema/SemaNoloadLookupTest.cpp (+1)
  • (modified) clang/unittests/Serialization/ForceCheckFileInputTest.cpp (+1)
  • (modified) clang/unittests/Serialization/LoadSpecLazilyTest.cpp (+1)
  • (modified) clang/unittests/Serialization/ModuleCacheTest.cpp (+1)
  • (modified) clang/unittests/Serialization/NoCommentsTest.cpp (+1)
  • (modified) clang/unittests/Serialization/PreambleInNamedModulesTest.cpp (+1)
  • (modified) clang/unittests/Serialization/VarDeclConstantInitTest.cpp (+1)
  • (modified) clang/unittests/Tooling/Syntax/TokensTest.cpp (+1)
  • (modified) clang/unittests/Tooling/Syntax/TreeTestBase.cpp (+1)
  • (modified) flang/lib/Frontend/CMakeLists.txt (-1)
  • (modified) flang/lib/Frontend/CompilerInvocation.cpp (+2-3)
  • (modified) lldb/source/Commands/CommandObjectTarget.cpp (+1)
  • (modified) lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt (+1-1)
  • (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangHost.cpp (+2-2)
  • (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp (+1)
  • (modified) lldb/unittests/Expression/ClangParserTest.cpp (+2-2)
diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp
index 7990f2719e9a0..4eda330716f21 100644
--- a/clang-tools-extra/clangd/CompileCommands.cpp
+++ b/clang-tools-extra/clangd/CompileCommands.cpp
@@ -132,8 +132,7 @@ std::optional<std::string> detectSysroot() {
 
 std::string detectStandardResourceDir() {
   static int StaticForMainAddr; // Just an address in this process.
-  return CompilerInvocation::GetResourcesPath("clangd",
-                                              (void *)&StaticForMainAddr);
+  return GetResourcesPath("clangd", (void *)&StaticForMainAddr);
 }
 
 // The path passed to argv[0] is important:
diff --git a/clang-tools-extra/clangd/Compiler.cpp b/clang-tools-extra/clangd/Compiler.cpp
index 6ebc2eac25745..9ea7df139382a 100644
--- a/clang-tools-extra/clangd/Compiler.cpp
+++ b/clang-tools-extra/clangd/Compiler.cpp
@@ -9,6 +9,7 @@
 #include "Compiler.h"
 #include "support/Logger.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Driver/CreateInvocationFromArgs.h"
 #include "clang/Frontend/CompilerInvocation.h"
 #include "clang/Lex/PreprocessorOptions.h"
 #include "clang/Serialization/PCHContainerOperations.h"
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c6a79ed71ca2f..c4d968bd01b65 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -84,6 +84,8 @@ Potentially Breaking Changes
 - Downstream projects that previously linked only against ``clangDriver`` may
   now (also) need to link against the new ``clangOptions`` library, since
   options-related code has been moved out of the Driver into a separate library.
+- The ``clangFrontend`` library no longer depends on ``clangDriver``, which may
+  break downstream projects that relied on this transitive dependency.
 
 C/C++ Language Potentially Breaking Changes
 -------------------------------------------
diff --git a/clang/include/clang/Driver/CommonArgs.h b/clang/include/clang/Driver/CommonArgs.h
index ac17d6211d882..264bd4965f9ad 100644
--- a/clang/include/clang/Driver/CommonArgs.h
+++ b/clang/include/clang/Driver/CommonArgs.h
@@ -291,16 +291,6 @@ void handleVectorizeLoopsArgs(const llvm::opt::ArgList &Args,
 void handleVectorizeSLPArgs(const llvm::opt::ArgList &Args,
                             llvm::opt::ArgStringList &CmdArgs);
 
-// Parse -mprefer-vector-width=. Return the Value string if well-formed.
-// Otherwise, return an empty string and issue a diagnosic message if needed.
-StringRef parseMPreferVectorWidthOption(clang::DiagnosticsEngine &Diags,
-                                        const llvm::opt::ArgList &Args);
-
-// Parse -mrecip. Return the Value string if well-formed.
-// Otherwise, return an empty string and issue a diagnosic message if needed.
-StringRef parseMRecipOption(clang::DiagnosticsEngine &Diags,
-                            const llvm::opt::ArgList &Args);
-
 // Convert ComplexRangeKind to a string that can be passed as a frontend option.
 std::string complexRangeKindToStr(LangOptions::ComplexRangeKind Range);
 
diff --git a/clang/include/clang/Driver/CreateASTUnitFromArgs.h b/clang/include/clang/Driver/CreateASTUnitFromArgs.h
new file mode 100644
index 0000000000000..30575cc04ca7c
--- /dev/null
+++ b/clang/include/clang/Driver/CreateASTUnitFromArgs.h
@@ -0,0 +1,80 @@
+//===-- CreateInvocationFromArgs.h - Create an ASTUnit from Args-*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utility for creating an ASTUnit from a vector of command line arguments.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DRIVER_CREATEASTUNITFROMARGS_H
+#define LLVM_CLANG_DRIVER_CREATEASTUNITFROMARGS_H
+
+#include "clang/Frontend/ASTUnit.h"
+
+namespace clang {
+
+/// Create an ASTUnit from a vector of command line arguments, which must
+/// specify exactly one source file.
+///
+/// \param ArgBegin - The beginning of the argument vector.
+///
+/// \param ArgEnd - The end of the argument vector.
+///
+/// \param PCHContainerOps - The PCHContainerOperations to use for loading and
+/// creating modules.
+///
+/// \param Diags - The diagnostics engine to use for reporting errors; its
+/// lifetime is expected to extend past that of the returned ASTUnit.
+///
+/// \param ResourceFilesPath - The path to the compiler resource files.
+///
+/// \param StorePreamblesInMemory - Whether to store PCH in memory. If false,
+/// PCH are stored in temporary files.
+///
+/// \param PreambleStoragePath - The path to a directory, in which to create
+/// temporary PCH files. If empty, the default system temporary directory is
+/// used. This parameter is ignored if \p StorePreamblesInMemory is true.
+///
+/// \param ModuleFormat - If provided, uses the specific module format.
+///
+/// \param ErrAST - If non-null and parsing failed without any AST to return
+/// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
+/// mainly to allow the caller to see the diagnostics.
+///
+/// \param VFS - A llvm::vfs::FileSystem to be used for all file accesses.
+/// Note that preamble is saved to a temporary directory on a RealFileSystem,
+/// so in order for it to be loaded correctly, VFS should have access to
+/// it(i.e., be an overlay over RealFileSystem). RealFileSystem will be used
+/// if \p VFS is nullptr.
+///
+// FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
+// shouldn't need to specify them at construction time.
+std::unique_ptr<ASTUnit> CreateASTUnitFromCommandLine(
+    const char **ArgBegin, const char **ArgEnd,
+    std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+    std::shared_ptr<DiagnosticOptions> DiagOpts,
+    IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
+    bool StorePreamblesInMemory = false,
+    StringRef PreambleStoragePath = StringRef(), bool OnlyLocalDecls = false,
+    CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None,
+    ArrayRef<ASTUnit::RemappedFile> RemappedFiles = {},
+    bool RemappedFilesKeepOriginalName = true,
+    unsigned PrecompilePreambleAfterNParses = 0,
+    TranslationUnitKind TUKind = TU_Complete,
+    bool CacheCodeCompletionResults = false,
+    bool IncludeBriefCommentsInCodeCompletion = false,
+    bool AllowPCHWithCompilerErrors = false,
+    SkipFunctionBodiesScope SkipFunctionBodies = SkipFunctionBodiesScope::None,
+    bool SingleFileParse = false, bool UserFilesAreVolatile = false,
+    bool ForSerialization = false, bool RetainExcludedConditionalBlocks = false,
+    std::optional<StringRef> ModuleFormat = std::nullopt,
+    std::unique_ptr<ASTUnit> *ErrAST = nullptr,
+    IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
+
+} // namespace clang
+
+#endif // LLVM_CLANG_DRIVER_CREATEASTUNITFROMARGS_H
diff --git a/clang/include/clang/Driver/CreateInvocationFromArgs.h b/clang/include/clang/Driver/CreateInvocationFromArgs.h
new file mode 100644
index 0000000000000..0e0f67373ce87
--- /dev/null
+++ b/clang/include/clang/Driver/CreateInvocationFromArgs.h
@@ -0,0 +1,76 @@
+//===--- CreateInvocationFromArgs.h - CompilerInvocation from Args --------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utility for creating a CompilerInvocation from command-line arguments, for
+// tools to use in preparation to parse a file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DRIVER_CREATEINVOCATIONFROMARGS_H
+#define LLVM_CLANG_DRIVER_CREATEINVOCATIONFROMARGS_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace clang {
+
+class CompilerInvocation;
+class DiagnosticsEngine;
+
+/// Optional inputs to createInvocation.
+struct CreateInvocationOptions {
+  /// Receives diagnostics encountered while parsing command-line flags.
+  /// If not provided, these are printed to stderr.
+  IntrusiveRefCntPtr<DiagnosticsEngine> Diags = nullptr;
+  /// Used e.g. to probe for system headers locations.
+  /// If not provided, the real filesystem is used.
+  /// FIXME: the driver does perform some non-virtualized IO.
+  IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr;
+  /// Whether to attempt to produce a non-null (possibly incorrect) invocation
+  /// if any errors were encountered.
+  /// By default, always return null on errors.
+  bool RecoverOnError = false;
+  /// Allow the driver to probe the filesystem for PCH files.
+  /// This is used to replace -include with -include-pch in the cc1 args.
+  /// FIXME: ProbePrecompiled=true is a poor, historical default.
+  /// It misbehaves if the PCH file is from GCC, has the wrong version, etc.
+  bool ProbePrecompiled = false;
+  /// If set, the target is populated with the cc1 args produced by the driver.
+  /// This may be populated even if createInvocation returns nullptr.
+  std::vector<std::string> *CC1Args = nullptr;
+};
+
+/// Interpret clang arguments in preparation to parse a file.
+///
+/// This simulates a number of steps Clang takes when its driver is invoked:
+/// - choosing actions (e.g compile + link) to run
+/// - probing the system for settings like standard library locations
+/// - spawning a cc1 subprocess to compile code, with more explicit arguments
+/// - in the cc1 process, assembling those arguments into a CompilerInvocation
+///   which is used to configure the parser
+///
+/// This simulation is lossy, e.g. in some situations one driver run would
+/// result in multiple parses. (Multi-arch, CUDA, ...).
+/// This function tries to select a reasonable invocation that tools should use.
+///
+/// Args[0] should be the driver name, such as "clang" or "/usr/bin/g++".
+/// Absolute path is preferred - this affects searching for system headers.
+///
+/// May return nullptr if an invocation could not be determined.
+/// See CreateInvocationOptions::RecoverOnError to try harder!
+std::unique_ptr<CompilerInvocation>
+createInvocation(ArrayRef<const char *> Args,
+                 CreateInvocationOptions Opts = {});
+
+} // namespace clang
+
+#endif // LLVM_CLANG_DRIVER_CREATEINVOCATIONFROMARGS_H
diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index 83bcb7cab550f..76a6c5a128efb 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -406,10 +406,6 @@ class Driver {
                               SmallString<128> &CrashDiagDir);
 
 public:
-  /// Takes the path to a binary that's either in bin/ or lib/ and returns
-  /// the path to clang's resource directory.
-  static std::string GetResourcesPath(StringRef BinaryPath);
-
   Driver(StringRef ClangExecutable, StringRef TargetTriple,
          DiagnosticsEngine &Diags, std::string Title = "clang LLVM compiler",
          IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h
index e585933a5c8be..341460e1962cb 100644
--- a/clang/include/clang/Frontend/ASTUnit.h
+++ b/clang/include/clang/Frontend/ASTUnit.h
@@ -23,11 +23,13 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetOptions.h"
 #include "clang/Frontend/PrecompiledPreamble.h"
+#include "clang/Frontend/StandaloneDiagnostic.h"
 #include "clang/Lex/HeaderSearchOptions.h"
 #include "clang/Lex/ModuleLoader.h"
 #include "clang/Lex/PreprocessingRecord.h"
 #include "clang/Sema/CodeCompleteConsumer.h"
 #include "clang/Serialization/ASTBitCodes.h"
+#include "clang/Serialization/ASTWriter.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -36,6 +38,7 @@
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator_range.h"
+#include "llvm/Bitstream/BitstreamWriter.h"
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
@@ -88,25 +91,6 @@ enum class CaptureDiagsKind { None, All, AllWithoutNonErrorsFromIncludes };
 
 /// Utility class for loading a ASTContext from an AST file.
 class ASTUnit {
-public:
-  struct StandaloneFixIt {
-    std::pair<unsigned, unsigned> RemoveRange;
-    std::pair<unsigned, unsigned> InsertFromRange;
-    std::string CodeToInsert;
-    bool BeforePreviousInsertions;
-  };
-
-  struct StandaloneDiagnostic {
-    unsigned ID;
-    DiagnosticsEngine::Level Level;
-    std::string Message;
-    std::string Filename;
-    unsigned LocOffset;
-    std::vector<std::pair<unsigned, unsigned>> Ranges;
-    std::vector<StandaloneFixIt> FixIts;
-  };
-
-private:
   std::unique_ptr<LangOptions> LangOpts;
   std::unique_ptr<CodeGenOptions> CodeGenOpts;
   // FIXME: The documentation on \c LoadFrom* member functions states that the
@@ -129,7 +113,15 @@ class ASTUnit {
   bool HadModuleLoaderFatalFailure = false;
   bool StorePreamblesInMemory = false;
 
-  struct ASTWriterData;
+  /// Utility struct for managing ASTWriter and its associated data streams.
+  struct ASTWriterData {
+    SmallString<128> Buffer;
+    llvm::BitstreamWriter Stream;
+    ASTWriter Writer;
+
+    ASTWriterData(ModuleCache &ModCache, const CodeGenOptions &CGOpts)
+        : Stream(Buffer), Writer(Stream, Buffer, ModCache, CGOpts, {}) {}
+  };
   std::unique_ptr<ASTWriterData> WriterData;
 
   FileSystemOptions FileSystemOpts;
@@ -271,11 +263,6 @@ class ASTUnit {
   static void ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
                              ASTUnit &AST, CaptureDiagsKind CaptureDiagnostics);
 
-  void
-  TranslateStoredDiagnostics(FileManager &FileMgr, SourceManager &SrcMan,
-                             const SmallVectorImpl<StandaloneDiagnostic> &Diags,
-                             SmallVectorImpl<StoredDiagnostic> &Out);
-
   void clearFileLevelDecls();
 
 public:
@@ -834,65 +821,24 @@ class ASTUnit {
       bool IncludeBriefCommentsInCodeCompletion = false,
       bool UserFilesAreVolatile = false);
 
-  /// LoadFromCommandLine - Create an ASTUnit from a vector of command line
-  /// arguments, which must specify exactly one source file.
-  ///
-  /// \param ArgBegin - The beginning of the argument vector.
-  ///
-  /// \param ArgEnd - The end of the argument vector.
-  ///
-  /// \param PCHContainerOps - The PCHContainerOperations to use for loading and
-  /// creating modules.
-  ///
-  /// \param Diags - The diagnostics engine to use for reporting errors; its
-  /// lifetime is expected to extend past that of the returned ASTUnit.
-  ///
-  /// \param ResourceFilesPath - The path to the compiler resource files.
-  ///
-  /// \param StorePreamblesInMemory - Whether to store PCH in memory. If false,
-  /// PCH are stored in temporary files.
-  ///
-  /// \param PreambleStoragePath - The path to a directory, in which to create
-  /// temporary PCH files. If empty, the default system temporary directory is
-  /// used. This parameter is ignored if \p StorePreamblesInMemory is true.
-  ///
-  /// \param ModuleFormat - If provided, uses the specific module format.
-  ///
-  /// \param ErrAST - If non-null and parsing failed without any AST to return
-  /// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
-  /// mainly to allow the caller to see the diagnostics.
-  ///
-  /// \param VFS - A llvm::vfs::FileSystem to be used for all file accesses.
-  /// Note that preamble is saved to a temporary directory on a RealFileSystem,
-  /// so in order for it to be loaded correctly, VFS should have access to
-  /// it(i.e., be an overlay over RealFileSystem). RealFileSystem will be used
-  /// if \p VFS is nullptr.
-  ///
-  // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
-  // shouldn't need to specify them at construction time.
-  static std::unique_ptr<ASTUnit> LoadFromCommandLine(
+  friend std::unique_ptr<ASTUnit> CreateASTUnitFromCommandLine(
       const char **ArgBegin, const char **ArgEnd,
       std::shared_ptr<PCHContainerOperations> PCHContainerOps,
       std::shared_ptr<DiagnosticOptions> DiagOpts,
       IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
-      bool StorePreamblesInMemory = false,
-      StringRef PreambleStoragePath = StringRef(), bool OnlyLocalDecls = false,
-      CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None,
-      ArrayRef<RemappedFile> RemappedFiles = {},
-      bool RemappedFilesKeepOriginalName = true,
-      unsigned PrecompilePreambleAfterNParses = 0,
-      TranslationUnitKind TUKind = TU_Complete,
-      bool CacheCodeCompletionResults = false,
-      bool IncludeBriefCommentsInCodeCompletion = false,
-      bool AllowPCHWithCompilerErrors = false,
-      SkipFunctionBodiesScope SkipFunctionBodies =
-          SkipFunctionBodiesScope::None,
-      bool SingleFileParse = false, bool UserFilesAreVolatile = false,
-      bool ForSerialization = false,
-      bool RetainExcludedConditionalBlocks = false,
-      std::optional<StringRef> ModuleFormat = std::nullopt,
-      std::unique_ptr<ASTUnit> *ErrAST = nullptr,
-      IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
+      bool StorePreamblesInMemory, StringRef PreambleStoragePath,
+      bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,
+      ArrayRef<ASTUnit::RemappedFile> RemappedFiles,
+      bool RemappedFilesKeepOriginalName,
+      unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
+      bool CacheCodeCompletionResults,
+      bool IncludeBriefCommentsInCodeCompletion,
+      bool AllowPCHWithCompilerErrors,
+      SkipFunctionBodiesScope SkipFunctionBodies, bool SingleFileParse,
+      bool UserFilesAreVolatile, bool ForSerialization,
+      bool RetainExcludedConditionalBlocks,
+      std::optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST,
+      IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS);
 
   /// Reparse the source files using the same command-line options that
   /// were originally used to produce this translation unit.
@@ -963,6 +909,44 @@ class ASTUnit {
   bool serialize(raw_ostream &OS);
 };
 
+/// Diagnostic consumer that saves each diagnostic it is given.
+class FilterAndStoreDiagnosticConsumer : public DiagnosticConsumer {
+  SmallVectorImpl<StoredDiagnostic> *StoredDiags;
+  SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags;
+  bool CaptureNonErrorsFromIncludes = true;
+  const LangOptions *LangOpts = nullptr;
+  SourceManager *SourceMgr = nullptr;
+
+public:
+  FilterAndStoreDiagnosticConsumer(
+      SmallVectorImpl<StoredDiagnostic> *StoredDiags,
+      SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags,
+      bool CaptureNonErrorsFromIncludes);
+
+  void BeginSourceFile(const LangOptions &LangOpts,
+                       const Preprocessor *PP = nullptr) override;
+
+  void HandleDiagnostic(DiagnosticsEngine::Level Level,
+                        const Diagnostic &Info) override;
+};
+
+/// RAII object that optionally captures and filters diagnostics, if
+/// there is no diagnostic client to capture them already.
+class CaptureDroppedDiagnostics {
+  DiagnosticsEngine &Diags;
+  FilterAndStoreDiagnosticConsumer Client;
+  DiagnosticConsumer *PreviousClient = nullptr;
+  std::unique_ptr<DiagnosticConsumer> OwningPreviousClient;
+
+public:
+  CaptureDroppedDiagnostics(
+      CaptureDiagsKind CaptureDiagnostics, DiagnosticsEngine &Diags,
+      SmallVectorImpl<StoredDiagnostic> *StoredDiags,
+      SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags);
+
+  ~CaptureDroppedDiagnostics();
+};
+
 } // namespace clang
 
 #endif // LLVM_CLANG_FRONTEND_ASTUNIT_H
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h
index b19a6e1a8acc3..4977ddb307d21 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -299,16 +299,6 @@ class CompilerInvocation : public CompilerInvocationBase {
                 ...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Nov 26, 2025

@llvm/pr-subscribers-clangd

Author: Naveen Seth Hanig (naveen-seth)

Changes

This reapplies 3773bbe by reverting a96ec1c.

The original revert was due to a report of a broken build, which was later resolved by fully clearing the build directory.


Patch is 103.65 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/169597.diff

60 Files Affected:

  • (modified) clang-tools-extra/clangd/CompileCommands.cpp (+1-2)
  • (modified) clang-tools-extra/clangd/Compiler.cpp (+1)
  • (modified) clang/docs/ReleaseNotes.rst (+2)
  • (modified) clang/include/clang/Driver/CommonArgs.h (-10)
  • (added) clang/include/clang/Driver/CreateASTUnitFromArgs.h (+80)
  • (added) clang/include/clang/Driver/CreateInvocationFromArgs.h (+76)
  • (modified) clang/include/clang/Driver/Driver.h (-4)
  • (modified) clang/include/clang/Frontend/ASTUnit.h (+64-80)
  • (modified) clang/include/clang/Frontend/CompilerInvocation.h (-10)
  • (added) clang/include/clang/Frontend/StandaloneDiagnostic.h (+82)
  • (modified) clang/include/clang/Frontend/Utils.h (-45)
  • (modified) clang/include/clang/Options/OptionUtils.h (+24)
  • (modified) clang/lib/CrossTU/CMakeLists.txt (+1)
  • (modified) clang/lib/CrossTU/CrossTranslationUnit.cpp (+2-1)
  • (modified) clang/lib/Driver/CMakeLists.txt (+4)
  • (added) clang/lib/Driver/CreateASTUnitFromArgs.cpp (+166)
  • (renamed) clang/lib/Driver/CreateInvocationFromArgs.cpp (+8-5)
  • (modified) clang/lib/Driver/Driver.cpp (+1-34)
  • (modified) clang/lib/Driver/ToolChains/Clang.cpp (+1)
  • (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (-163)
  • (modified) clang/lib/Driver/ToolChains/Flang.cpp (+1)
  • (modified) clang/lib/Frontend/ASTUnit.cpp (+51-292)
  • (modified) clang/lib/Frontend/CMakeLists.txt (+1-2)
  • (modified) clang/lib/Frontend/CompilerInvocation.cpp (-8)
  • (added) clang/lib/Frontend/StandaloneDiagnostic.cpp (+117)
  • (modified) clang/lib/Interpreter/CMakeLists.txt (+1)
  • (modified) clang/lib/Interpreter/Interpreter.cpp (+2-1)
  • (modified) clang/lib/Options/OptionUtils.cpp (+207-8)
  • (modified) clang/lib/Tooling/Tooling.cpp (+2-2)
  • (modified) clang/tools/c-index-test/CMakeLists.txt (+1)
  • (modified) clang/tools/c-index-test/core_main.cpp (+1)
  • (modified) clang/tools/diagtool/CMakeLists.txt (+1)
  • (modified) clang/tools/diagtool/ShowEnabledWarnings.cpp (+1)
  • (modified) clang/tools/driver/cc1_main.cpp (+2-1)
  • (modified) clang/tools/libclang/CIndex.cpp (+2-1)
  • (modified) clang/tools/libclang/CIndexer.cpp (+2-1)
  • (modified) clang/tools/libclang/CMakeLists.txt (+1)
  • (modified) clang/tools/libclang/Indexing.cpp (+1)
  • (modified) clang/unittests/Driver/DXCModeTest.cpp (+1)
  • (modified) clang/unittests/Driver/ToolChainTest.cpp (+1)
  • (modified) clang/unittests/Frontend/ASTUnitTest.cpp (+4-2)
  • (modified) clang/unittests/Frontend/CompilerInstanceTest.cpp (+1)
  • (modified) clang/unittests/Frontend/UtilsTest.cpp (+1)
  • (modified) clang/unittests/Sema/CMakeLists.txt (+1)
  • (modified) clang/unittests/Sema/SemaNoloadLookupTest.cpp (+1)
  • (modified) clang/unittests/Serialization/ForceCheckFileInputTest.cpp (+1)
  • (modified) clang/unittests/Serialization/LoadSpecLazilyTest.cpp (+1)
  • (modified) clang/unittests/Serialization/ModuleCacheTest.cpp (+1)
  • (modified) clang/unittests/Serialization/NoCommentsTest.cpp (+1)
  • (modified) clang/unittests/Serialization/PreambleInNamedModulesTest.cpp (+1)
  • (modified) clang/unittests/Serialization/VarDeclConstantInitTest.cpp (+1)
  • (modified) clang/unittests/Tooling/Syntax/TokensTest.cpp (+1)
  • (modified) clang/unittests/Tooling/Syntax/TreeTestBase.cpp (+1)
  • (modified) flang/lib/Frontend/CMakeLists.txt (-1)
  • (modified) flang/lib/Frontend/CompilerInvocation.cpp (+2-3)
  • (modified) lldb/source/Commands/CommandObjectTarget.cpp (+1)
  • (modified) lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt (+1-1)
  • (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangHost.cpp (+2-2)
  • (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp (+1)
  • (modified) lldb/unittests/Expression/ClangParserTest.cpp (+2-2)
diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp
index 7990f2719e9a0..4eda330716f21 100644
--- a/clang-tools-extra/clangd/CompileCommands.cpp
+++ b/clang-tools-extra/clangd/CompileCommands.cpp
@@ -132,8 +132,7 @@ std::optional<std::string> detectSysroot() {
 
 std::string detectStandardResourceDir() {
   static int StaticForMainAddr; // Just an address in this process.
-  return CompilerInvocation::GetResourcesPath("clangd",
-                                              (void *)&StaticForMainAddr);
+  return GetResourcesPath("clangd", (void *)&StaticForMainAddr);
 }
 
 // The path passed to argv[0] is important:
diff --git a/clang-tools-extra/clangd/Compiler.cpp b/clang-tools-extra/clangd/Compiler.cpp
index 6ebc2eac25745..9ea7df139382a 100644
--- a/clang-tools-extra/clangd/Compiler.cpp
+++ b/clang-tools-extra/clangd/Compiler.cpp
@@ -9,6 +9,7 @@
 #include "Compiler.h"
 #include "support/Logger.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Driver/CreateInvocationFromArgs.h"
 #include "clang/Frontend/CompilerInvocation.h"
 #include "clang/Lex/PreprocessorOptions.h"
 #include "clang/Serialization/PCHContainerOperations.h"
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c6a79ed71ca2f..c4d968bd01b65 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -84,6 +84,8 @@ Potentially Breaking Changes
 - Downstream projects that previously linked only against ``clangDriver`` may
   now (also) need to link against the new ``clangOptions`` library, since
   options-related code has been moved out of the Driver into a separate library.
+- The ``clangFrontend`` library no longer depends on ``clangDriver``, which may
+  break downstream projects that relied on this transitive dependency.
 
 C/C++ Language Potentially Breaking Changes
 -------------------------------------------
diff --git a/clang/include/clang/Driver/CommonArgs.h b/clang/include/clang/Driver/CommonArgs.h
index ac17d6211d882..264bd4965f9ad 100644
--- a/clang/include/clang/Driver/CommonArgs.h
+++ b/clang/include/clang/Driver/CommonArgs.h
@@ -291,16 +291,6 @@ void handleVectorizeLoopsArgs(const llvm::opt::ArgList &Args,
 void handleVectorizeSLPArgs(const llvm::opt::ArgList &Args,
                             llvm::opt::ArgStringList &CmdArgs);
 
-// Parse -mprefer-vector-width=. Return the Value string if well-formed.
-// Otherwise, return an empty string and issue a diagnosic message if needed.
-StringRef parseMPreferVectorWidthOption(clang::DiagnosticsEngine &Diags,
-                                        const llvm::opt::ArgList &Args);
-
-// Parse -mrecip. Return the Value string if well-formed.
-// Otherwise, return an empty string and issue a diagnosic message if needed.
-StringRef parseMRecipOption(clang::DiagnosticsEngine &Diags,
-                            const llvm::opt::ArgList &Args);
-
 // Convert ComplexRangeKind to a string that can be passed as a frontend option.
 std::string complexRangeKindToStr(LangOptions::ComplexRangeKind Range);
 
diff --git a/clang/include/clang/Driver/CreateASTUnitFromArgs.h b/clang/include/clang/Driver/CreateASTUnitFromArgs.h
new file mode 100644
index 0000000000000..30575cc04ca7c
--- /dev/null
+++ b/clang/include/clang/Driver/CreateASTUnitFromArgs.h
@@ -0,0 +1,80 @@
+//===-- CreateInvocationFromArgs.h - Create an ASTUnit from Args-*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utility for creating an ASTUnit from a vector of command line arguments.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DRIVER_CREATEASTUNITFROMARGS_H
+#define LLVM_CLANG_DRIVER_CREATEASTUNITFROMARGS_H
+
+#include "clang/Frontend/ASTUnit.h"
+
+namespace clang {
+
+/// Create an ASTUnit from a vector of command line arguments, which must
+/// specify exactly one source file.
+///
+/// \param ArgBegin - The beginning of the argument vector.
+///
+/// \param ArgEnd - The end of the argument vector.
+///
+/// \param PCHContainerOps - The PCHContainerOperations to use for loading and
+/// creating modules.
+///
+/// \param Diags - The diagnostics engine to use for reporting errors; its
+/// lifetime is expected to extend past that of the returned ASTUnit.
+///
+/// \param ResourceFilesPath - The path to the compiler resource files.
+///
+/// \param StorePreamblesInMemory - Whether to store PCH in memory. If false,
+/// PCH are stored in temporary files.
+///
+/// \param PreambleStoragePath - The path to a directory, in which to create
+/// temporary PCH files. If empty, the default system temporary directory is
+/// used. This parameter is ignored if \p StorePreamblesInMemory is true.
+///
+/// \param ModuleFormat - If provided, uses the specific module format.
+///
+/// \param ErrAST - If non-null and parsing failed without any AST to return
+/// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
+/// mainly to allow the caller to see the diagnostics.
+///
+/// \param VFS - A llvm::vfs::FileSystem to be used for all file accesses.
+/// Note that preamble is saved to a temporary directory on a RealFileSystem,
+/// so in order for it to be loaded correctly, VFS should have access to
+/// it(i.e., be an overlay over RealFileSystem). RealFileSystem will be used
+/// if \p VFS is nullptr.
+///
+// FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
+// shouldn't need to specify them at construction time.
+std::unique_ptr<ASTUnit> CreateASTUnitFromCommandLine(
+    const char **ArgBegin, const char **ArgEnd,
+    std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+    std::shared_ptr<DiagnosticOptions> DiagOpts,
+    IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
+    bool StorePreamblesInMemory = false,
+    StringRef PreambleStoragePath = StringRef(), bool OnlyLocalDecls = false,
+    CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None,
+    ArrayRef<ASTUnit::RemappedFile> RemappedFiles = {},
+    bool RemappedFilesKeepOriginalName = true,
+    unsigned PrecompilePreambleAfterNParses = 0,
+    TranslationUnitKind TUKind = TU_Complete,
+    bool CacheCodeCompletionResults = false,
+    bool IncludeBriefCommentsInCodeCompletion = false,
+    bool AllowPCHWithCompilerErrors = false,
+    SkipFunctionBodiesScope SkipFunctionBodies = SkipFunctionBodiesScope::None,
+    bool SingleFileParse = false, bool UserFilesAreVolatile = false,
+    bool ForSerialization = false, bool RetainExcludedConditionalBlocks = false,
+    std::optional<StringRef> ModuleFormat = std::nullopt,
+    std::unique_ptr<ASTUnit> *ErrAST = nullptr,
+    IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
+
+} // namespace clang
+
+#endif // LLVM_CLANG_DRIVER_CREATEASTUNITFROMARGS_H
diff --git a/clang/include/clang/Driver/CreateInvocationFromArgs.h b/clang/include/clang/Driver/CreateInvocationFromArgs.h
new file mode 100644
index 0000000000000..0e0f67373ce87
--- /dev/null
+++ b/clang/include/clang/Driver/CreateInvocationFromArgs.h
@@ -0,0 +1,76 @@
+//===--- CreateInvocationFromArgs.h - CompilerInvocation from Args --------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utility for creating a CompilerInvocation from command-line arguments, for
+// tools to use in preparation to parse a file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DRIVER_CREATEINVOCATIONFROMARGS_H
+#define LLVM_CLANG_DRIVER_CREATEINVOCATIONFROMARGS_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace clang {
+
+class CompilerInvocation;
+class DiagnosticsEngine;
+
+/// Optional inputs to createInvocation.
+struct CreateInvocationOptions {
+  /// Receives diagnostics encountered while parsing command-line flags.
+  /// If not provided, these are printed to stderr.
+  IntrusiveRefCntPtr<DiagnosticsEngine> Diags = nullptr;
+  /// Used e.g. to probe for system headers locations.
+  /// If not provided, the real filesystem is used.
+  /// FIXME: the driver does perform some non-virtualized IO.
+  IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr;
+  /// Whether to attempt to produce a non-null (possibly incorrect) invocation
+  /// if any errors were encountered.
+  /// By default, always return null on errors.
+  bool RecoverOnError = false;
+  /// Allow the driver to probe the filesystem for PCH files.
+  /// This is used to replace -include with -include-pch in the cc1 args.
+  /// FIXME: ProbePrecompiled=true is a poor, historical default.
+  /// It misbehaves if the PCH file is from GCC, has the wrong version, etc.
+  bool ProbePrecompiled = false;
+  /// If set, the target is populated with the cc1 args produced by the driver.
+  /// This may be populated even if createInvocation returns nullptr.
+  std::vector<std::string> *CC1Args = nullptr;
+};
+
+/// Interpret clang arguments in preparation to parse a file.
+///
+/// This simulates a number of steps Clang takes when its driver is invoked:
+/// - choosing actions (e.g compile + link) to run
+/// - probing the system for settings like standard library locations
+/// - spawning a cc1 subprocess to compile code, with more explicit arguments
+/// - in the cc1 process, assembling those arguments into a CompilerInvocation
+///   which is used to configure the parser
+///
+/// This simulation is lossy, e.g. in some situations one driver run would
+/// result in multiple parses. (Multi-arch, CUDA, ...).
+/// This function tries to select a reasonable invocation that tools should use.
+///
+/// Args[0] should be the driver name, such as "clang" or "/usr/bin/g++".
+/// Absolute path is preferred - this affects searching for system headers.
+///
+/// May return nullptr if an invocation could not be determined.
+/// See CreateInvocationOptions::RecoverOnError to try harder!
+std::unique_ptr<CompilerInvocation>
+createInvocation(ArrayRef<const char *> Args,
+                 CreateInvocationOptions Opts = {});
+
+} // namespace clang
+
+#endif // LLVM_CLANG_DRIVER_CREATEINVOCATIONFROMARGS_H
diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index 83bcb7cab550f..76a6c5a128efb 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -406,10 +406,6 @@ class Driver {
                               SmallString<128> &CrashDiagDir);
 
 public:
-  /// Takes the path to a binary that's either in bin/ or lib/ and returns
-  /// the path to clang's resource directory.
-  static std::string GetResourcesPath(StringRef BinaryPath);
-
   Driver(StringRef ClangExecutable, StringRef TargetTriple,
          DiagnosticsEngine &Diags, std::string Title = "clang LLVM compiler",
          IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h
index e585933a5c8be..341460e1962cb 100644
--- a/clang/include/clang/Frontend/ASTUnit.h
+++ b/clang/include/clang/Frontend/ASTUnit.h
@@ -23,11 +23,13 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetOptions.h"
 #include "clang/Frontend/PrecompiledPreamble.h"
+#include "clang/Frontend/StandaloneDiagnostic.h"
 #include "clang/Lex/HeaderSearchOptions.h"
 #include "clang/Lex/ModuleLoader.h"
 #include "clang/Lex/PreprocessingRecord.h"
 #include "clang/Sema/CodeCompleteConsumer.h"
 #include "clang/Serialization/ASTBitCodes.h"
+#include "clang/Serialization/ASTWriter.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -36,6 +38,7 @@
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator_range.h"
+#include "llvm/Bitstream/BitstreamWriter.h"
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
@@ -88,25 +91,6 @@ enum class CaptureDiagsKind { None, All, AllWithoutNonErrorsFromIncludes };
 
 /// Utility class for loading a ASTContext from an AST file.
 class ASTUnit {
-public:
-  struct StandaloneFixIt {
-    std::pair<unsigned, unsigned> RemoveRange;
-    std::pair<unsigned, unsigned> InsertFromRange;
-    std::string CodeToInsert;
-    bool BeforePreviousInsertions;
-  };
-
-  struct StandaloneDiagnostic {
-    unsigned ID;
-    DiagnosticsEngine::Level Level;
-    std::string Message;
-    std::string Filename;
-    unsigned LocOffset;
-    std::vector<std::pair<unsigned, unsigned>> Ranges;
-    std::vector<StandaloneFixIt> FixIts;
-  };
-
-private:
   std::unique_ptr<LangOptions> LangOpts;
   std::unique_ptr<CodeGenOptions> CodeGenOpts;
   // FIXME: The documentation on \c LoadFrom* member functions states that the
@@ -129,7 +113,15 @@ class ASTUnit {
   bool HadModuleLoaderFatalFailure = false;
   bool StorePreamblesInMemory = false;
 
-  struct ASTWriterData;
+  /// Utility struct for managing ASTWriter and its associated data streams.
+  struct ASTWriterData {
+    SmallString<128> Buffer;
+    llvm::BitstreamWriter Stream;
+    ASTWriter Writer;
+
+    ASTWriterData(ModuleCache &ModCache, const CodeGenOptions &CGOpts)
+        : Stream(Buffer), Writer(Stream, Buffer, ModCache, CGOpts, {}) {}
+  };
   std::unique_ptr<ASTWriterData> WriterData;
 
   FileSystemOptions FileSystemOpts;
@@ -271,11 +263,6 @@ class ASTUnit {
   static void ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
                              ASTUnit &AST, CaptureDiagsKind CaptureDiagnostics);
 
-  void
-  TranslateStoredDiagnostics(FileManager &FileMgr, SourceManager &SrcMan,
-                             const SmallVectorImpl<StandaloneDiagnostic> &Diags,
-                             SmallVectorImpl<StoredDiagnostic> &Out);
-
   void clearFileLevelDecls();
 
 public:
@@ -834,65 +821,24 @@ class ASTUnit {
       bool IncludeBriefCommentsInCodeCompletion = false,
       bool UserFilesAreVolatile = false);
 
-  /// LoadFromCommandLine - Create an ASTUnit from a vector of command line
-  /// arguments, which must specify exactly one source file.
-  ///
-  /// \param ArgBegin - The beginning of the argument vector.
-  ///
-  /// \param ArgEnd - The end of the argument vector.
-  ///
-  /// \param PCHContainerOps - The PCHContainerOperations to use for loading and
-  /// creating modules.
-  ///
-  /// \param Diags - The diagnostics engine to use for reporting errors; its
-  /// lifetime is expected to extend past that of the returned ASTUnit.
-  ///
-  /// \param ResourceFilesPath - The path to the compiler resource files.
-  ///
-  /// \param StorePreamblesInMemory - Whether to store PCH in memory. If false,
-  /// PCH are stored in temporary files.
-  ///
-  /// \param PreambleStoragePath - The path to a directory, in which to create
-  /// temporary PCH files. If empty, the default system temporary directory is
-  /// used. This parameter is ignored if \p StorePreamblesInMemory is true.
-  ///
-  /// \param ModuleFormat - If provided, uses the specific module format.
-  ///
-  /// \param ErrAST - If non-null and parsing failed without any AST to return
-  /// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
-  /// mainly to allow the caller to see the diagnostics.
-  ///
-  /// \param VFS - A llvm::vfs::FileSystem to be used for all file accesses.
-  /// Note that preamble is saved to a temporary directory on a RealFileSystem,
-  /// so in order for it to be loaded correctly, VFS should have access to
-  /// it(i.e., be an overlay over RealFileSystem). RealFileSystem will be used
-  /// if \p VFS is nullptr.
-  ///
-  // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
-  // shouldn't need to specify them at construction time.
-  static std::unique_ptr<ASTUnit> LoadFromCommandLine(
+  friend std::unique_ptr<ASTUnit> CreateASTUnitFromCommandLine(
       const char **ArgBegin, const char **ArgEnd,
       std::shared_ptr<PCHContainerOperations> PCHContainerOps,
       std::shared_ptr<DiagnosticOptions> DiagOpts,
       IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
-      bool StorePreamblesInMemory = false,
-      StringRef PreambleStoragePath = StringRef(), bool OnlyLocalDecls = false,
-      CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None,
-      ArrayRef<RemappedFile> RemappedFiles = {},
-      bool RemappedFilesKeepOriginalName = true,
-      unsigned PrecompilePreambleAfterNParses = 0,
-      TranslationUnitKind TUKind = TU_Complete,
-      bool CacheCodeCompletionResults = false,
-      bool IncludeBriefCommentsInCodeCompletion = false,
-      bool AllowPCHWithCompilerErrors = false,
-      SkipFunctionBodiesScope SkipFunctionBodies =
-          SkipFunctionBodiesScope::None,
-      bool SingleFileParse = false, bool UserFilesAreVolatile = false,
-      bool ForSerialization = false,
-      bool RetainExcludedConditionalBlocks = false,
-      std::optional<StringRef> ModuleFormat = std::nullopt,
-      std::unique_ptr<ASTUnit> *ErrAST = nullptr,
-      IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
+      bool StorePreamblesInMemory, StringRef PreambleStoragePath,
+      bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,
+      ArrayRef<ASTUnit::RemappedFile> RemappedFiles,
+      bool RemappedFilesKeepOriginalName,
+      unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
+      bool CacheCodeCompletionResults,
+      bool IncludeBriefCommentsInCodeCompletion,
+      bool AllowPCHWithCompilerErrors,
+      SkipFunctionBodiesScope SkipFunctionBodies, bool SingleFileParse,
+      bool UserFilesAreVolatile, bool ForSerialization,
+      bool RetainExcludedConditionalBlocks,
+      std::optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST,
+      IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS);
 
   /// Reparse the source files using the same command-line options that
   /// were originally used to produce this translation unit.
@@ -963,6 +909,44 @@ class ASTUnit {
   bool serialize(raw_ostream &OS);
 };
 
+/// Diagnostic consumer that saves each diagnostic it is given.
+class FilterAndStoreDiagnosticConsumer : public DiagnosticConsumer {
+  SmallVectorImpl<StoredDiagnostic> *StoredDiags;
+  SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags;
+  bool CaptureNonErrorsFromIncludes = true;
+  const LangOptions *LangOpts = nullptr;
+  SourceManager *SourceMgr = nullptr;
+
+public:
+  FilterAndStoreDiagnosticConsumer(
+      SmallVectorImpl<StoredDiagnostic> *StoredDiags,
+      SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags,
+      bool CaptureNonErrorsFromIncludes);
+
+  void BeginSourceFile(const LangOptions &LangOpts,
+                       const Preprocessor *PP = nullptr) override;
+
+  void HandleDiagnostic(DiagnosticsEngine::Level Level,
+                        const Diagnostic &Info) override;
+};
+
+/// RAII object that optionally captures and filters diagnostics, if
+/// there is no diagnostic client to capture them already.
+class CaptureDroppedDiagnostics {
+  DiagnosticsEngine &Diags;
+  FilterAndStoreDiagnosticConsumer Client;
+  DiagnosticConsumer *PreviousClient = nullptr;
+  std::unique_ptr<DiagnosticConsumer> OwningPreviousClient;
+
+public:
+  CaptureDroppedDiagnostics(
+      CaptureDiagsKind CaptureDiagnostics, DiagnosticsEngine &Diags,
+      SmallVectorImpl<StoredDiagnostic> *StoredDiags,
+      SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags);
+
+  ~CaptureDroppedDiagnostics();
+};
+
 } // namespace clang
 
 #endif // LLVM_CLANG_FRONTEND_ASTUNIT_H
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h
index b19a6e1a8acc3..4977ddb307d21 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -299,16 +299,6 @@ class CompilerInvocation : public CompilerInvocationBase {
                 ...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Nov 26, 2025

@llvm/pr-subscribers-lldb

Author: Naveen Seth Hanig (naveen-seth)

Changes

This reapplies 3773bbe by reverting a96ec1c.

The original revert was due to a report of a broken build, which was later resolved by fully clearing the build directory.


Patch is 103.65 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/169597.diff

60 Files Affected:

  • (modified) clang-tools-extra/clangd/CompileCommands.cpp (+1-2)
  • (modified) clang-tools-extra/clangd/Compiler.cpp (+1)
  • (modified) clang/docs/ReleaseNotes.rst (+2)
  • (modified) clang/include/clang/Driver/CommonArgs.h (-10)
  • (added) clang/include/clang/Driver/CreateASTUnitFromArgs.h (+80)
  • (added) clang/include/clang/Driver/CreateInvocationFromArgs.h (+76)
  • (modified) clang/include/clang/Driver/Driver.h (-4)
  • (modified) clang/include/clang/Frontend/ASTUnit.h (+64-80)
  • (modified) clang/include/clang/Frontend/CompilerInvocation.h (-10)
  • (added) clang/include/clang/Frontend/StandaloneDiagnostic.h (+82)
  • (modified) clang/include/clang/Frontend/Utils.h (-45)
  • (modified) clang/include/clang/Options/OptionUtils.h (+24)
  • (modified) clang/lib/CrossTU/CMakeLists.txt (+1)
  • (modified) clang/lib/CrossTU/CrossTranslationUnit.cpp (+2-1)
  • (modified) clang/lib/Driver/CMakeLists.txt (+4)
  • (added) clang/lib/Driver/CreateASTUnitFromArgs.cpp (+166)
  • (renamed) clang/lib/Driver/CreateInvocationFromArgs.cpp (+8-5)
  • (modified) clang/lib/Driver/Driver.cpp (+1-34)
  • (modified) clang/lib/Driver/ToolChains/Clang.cpp (+1)
  • (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (-163)
  • (modified) clang/lib/Driver/ToolChains/Flang.cpp (+1)
  • (modified) clang/lib/Frontend/ASTUnit.cpp (+51-292)
  • (modified) clang/lib/Frontend/CMakeLists.txt (+1-2)
  • (modified) clang/lib/Frontend/CompilerInvocation.cpp (-8)
  • (added) clang/lib/Frontend/StandaloneDiagnostic.cpp (+117)
  • (modified) clang/lib/Interpreter/CMakeLists.txt (+1)
  • (modified) clang/lib/Interpreter/Interpreter.cpp (+2-1)
  • (modified) clang/lib/Options/OptionUtils.cpp (+207-8)
  • (modified) clang/lib/Tooling/Tooling.cpp (+2-2)
  • (modified) clang/tools/c-index-test/CMakeLists.txt (+1)
  • (modified) clang/tools/c-index-test/core_main.cpp (+1)
  • (modified) clang/tools/diagtool/CMakeLists.txt (+1)
  • (modified) clang/tools/diagtool/ShowEnabledWarnings.cpp (+1)
  • (modified) clang/tools/driver/cc1_main.cpp (+2-1)
  • (modified) clang/tools/libclang/CIndex.cpp (+2-1)
  • (modified) clang/tools/libclang/CIndexer.cpp (+2-1)
  • (modified) clang/tools/libclang/CMakeLists.txt (+1)
  • (modified) clang/tools/libclang/Indexing.cpp (+1)
  • (modified) clang/unittests/Driver/DXCModeTest.cpp (+1)
  • (modified) clang/unittests/Driver/ToolChainTest.cpp (+1)
  • (modified) clang/unittests/Frontend/ASTUnitTest.cpp (+4-2)
  • (modified) clang/unittests/Frontend/CompilerInstanceTest.cpp (+1)
  • (modified) clang/unittests/Frontend/UtilsTest.cpp (+1)
  • (modified) clang/unittests/Sema/CMakeLists.txt (+1)
  • (modified) clang/unittests/Sema/SemaNoloadLookupTest.cpp (+1)
  • (modified) clang/unittests/Serialization/ForceCheckFileInputTest.cpp (+1)
  • (modified) clang/unittests/Serialization/LoadSpecLazilyTest.cpp (+1)
  • (modified) clang/unittests/Serialization/ModuleCacheTest.cpp (+1)
  • (modified) clang/unittests/Serialization/NoCommentsTest.cpp (+1)
  • (modified) clang/unittests/Serialization/PreambleInNamedModulesTest.cpp (+1)
  • (modified) clang/unittests/Serialization/VarDeclConstantInitTest.cpp (+1)
  • (modified) clang/unittests/Tooling/Syntax/TokensTest.cpp (+1)
  • (modified) clang/unittests/Tooling/Syntax/TreeTestBase.cpp (+1)
  • (modified) flang/lib/Frontend/CMakeLists.txt (-1)
  • (modified) flang/lib/Frontend/CompilerInvocation.cpp (+2-3)
  • (modified) lldb/source/Commands/CommandObjectTarget.cpp (+1)
  • (modified) lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt (+1-1)
  • (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangHost.cpp (+2-2)
  • (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp (+1)
  • (modified) lldb/unittests/Expression/ClangParserTest.cpp (+2-2)
diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp
index 7990f2719e9a0..4eda330716f21 100644
--- a/clang-tools-extra/clangd/CompileCommands.cpp
+++ b/clang-tools-extra/clangd/CompileCommands.cpp
@@ -132,8 +132,7 @@ std::optional<std::string> detectSysroot() {
 
 std::string detectStandardResourceDir() {
   static int StaticForMainAddr; // Just an address in this process.
-  return CompilerInvocation::GetResourcesPath("clangd",
-                                              (void *)&StaticForMainAddr);
+  return GetResourcesPath("clangd", (void *)&StaticForMainAddr);
 }
 
 // The path passed to argv[0] is important:
diff --git a/clang-tools-extra/clangd/Compiler.cpp b/clang-tools-extra/clangd/Compiler.cpp
index 6ebc2eac25745..9ea7df139382a 100644
--- a/clang-tools-extra/clangd/Compiler.cpp
+++ b/clang-tools-extra/clangd/Compiler.cpp
@@ -9,6 +9,7 @@
 #include "Compiler.h"
 #include "support/Logger.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Driver/CreateInvocationFromArgs.h"
 #include "clang/Frontend/CompilerInvocation.h"
 #include "clang/Lex/PreprocessorOptions.h"
 #include "clang/Serialization/PCHContainerOperations.h"
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c6a79ed71ca2f..c4d968bd01b65 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -84,6 +84,8 @@ Potentially Breaking Changes
 - Downstream projects that previously linked only against ``clangDriver`` may
   now (also) need to link against the new ``clangOptions`` library, since
   options-related code has been moved out of the Driver into a separate library.
+- The ``clangFrontend`` library no longer depends on ``clangDriver``, which may
+  break downstream projects that relied on this transitive dependency.
 
 C/C++ Language Potentially Breaking Changes
 -------------------------------------------
diff --git a/clang/include/clang/Driver/CommonArgs.h b/clang/include/clang/Driver/CommonArgs.h
index ac17d6211d882..264bd4965f9ad 100644
--- a/clang/include/clang/Driver/CommonArgs.h
+++ b/clang/include/clang/Driver/CommonArgs.h
@@ -291,16 +291,6 @@ void handleVectorizeLoopsArgs(const llvm::opt::ArgList &Args,
 void handleVectorizeSLPArgs(const llvm::opt::ArgList &Args,
                             llvm::opt::ArgStringList &CmdArgs);
 
-// Parse -mprefer-vector-width=. Return the Value string if well-formed.
-// Otherwise, return an empty string and issue a diagnosic message if needed.
-StringRef parseMPreferVectorWidthOption(clang::DiagnosticsEngine &Diags,
-                                        const llvm::opt::ArgList &Args);
-
-// Parse -mrecip. Return the Value string if well-formed.
-// Otherwise, return an empty string and issue a diagnosic message if needed.
-StringRef parseMRecipOption(clang::DiagnosticsEngine &Diags,
-                            const llvm::opt::ArgList &Args);
-
 // Convert ComplexRangeKind to a string that can be passed as a frontend option.
 std::string complexRangeKindToStr(LangOptions::ComplexRangeKind Range);
 
diff --git a/clang/include/clang/Driver/CreateASTUnitFromArgs.h b/clang/include/clang/Driver/CreateASTUnitFromArgs.h
new file mode 100644
index 0000000000000..30575cc04ca7c
--- /dev/null
+++ b/clang/include/clang/Driver/CreateASTUnitFromArgs.h
@@ -0,0 +1,80 @@
+//===-- CreateInvocationFromArgs.h - Create an ASTUnit from Args-*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utility for creating an ASTUnit from a vector of command line arguments.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DRIVER_CREATEASTUNITFROMARGS_H
+#define LLVM_CLANG_DRIVER_CREATEASTUNITFROMARGS_H
+
+#include "clang/Frontend/ASTUnit.h"
+
+namespace clang {
+
+/// Create an ASTUnit from a vector of command line arguments, which must
+/// specify exactly one source file.
+///
+/// \param ArgBegin - The beginning of the argument vector.
+///
+/// \param ArgEnd - The end of the argument vector.
+///
+/// \param PCHContainerOps - The PCHContainerOperations to use for loading and
+/// creating modules.
+///
+/// \param Diags - The diagnostics engine to use for reporting errors; its
+/// lifetime is expected to extend past that of the returned ASTUnit.
+///
+/// \param ResourceFilesPath - The path to the compiler resource files.
+///
+/// \param StorePreamblesInMemory - Whether to store PCH in memory. If false,
+/// PCH are stored in temporary files.
+///
+/// \param PreambleStoragePath - The path to a directory, in which to create
+/// temporary PCH files. If empty, the default system temporary directory is
+/// used. This parameter is ignored if \p StorePreamblesInMemory is true.
+///
+/// \param ModuleFormat - If provided, uses the specific module format.
+///
+/// \param ErrAST - If non-null and parsing failed without any AST to return
+/// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
+/// mainly to allow the caller to see the diagnostics.
+///
+/// \param VFS - A llvm::vfs::FileSystem to be used for all file accesses.
+/// Note that preamble is saved to a temporary directory on a RealFileSystem,
+/// so in order for it to be loaded correctly, VFS should have access to
+/// it(i.e., be an overlay over RealFileSystem). RealFileSystem will be used
+/// if \p VFS is nullptr.
+///
+// FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
+// shouldn't need to specify them at construction time.
+std::unique_ptr<ASTUnit> CreateASTUnitFromCommandLine(
+    const char **ArgBegin, const char **ArgEnd,
+    std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+    std::shared_ptr<DiagnosticOptions> DiagOpts,
+    IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
+    bool StorePreamblesInMemory = false,
+    StringRef PreambleStoragePath = StringRef(), bool OnlyLocalDecls = false,
+    CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None,
+    ArrayRef<ASTUnit::RemappedFile> RemappedFiles = {},
+    bool RemappedFilesKeepOriginalName = true,
+    unsigned PrecompilePreambleAfterNParses = 0,
+    TranslationUnitKind TUKind = TU_Complete,
+    bool CacheCodeCompletionResults = false,
+    bool IncludeBriefCommentsInCodeCompletion = false,
+    bool AllowPCHWithCompilerErrors = false,
+    SkipFunctionBodiesScope SkipFunctionBodies = SkipFunctionBodiesScope::None,
+    bool SingleFileParse = false, bool UserFilesAreVolatile = false,
+    bool ForSerialization = false, bool RetainExcludedConditionalBlocks = false,
+    std::optional<StringRef> ModuleFormat = std::nullopt,
+    std::unique_ptr<ASTUnit> *ErrAST = nullptr,
+    IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
+
+} // namespace clang
+
+#endif // LLVM_CLANG_DRIVER_CREATEASTUNITFROMARGS_H
diff --git a/clang/include/clang/Driver/CreateInvocationFromArgs.h b/clang/include/clang/Driver/CreateInvocationFromArgs.h
new file mode 100644
index 0000000000000..0e0f67373ce87
--- /dev/null
+++ b/clang/include/clang/Driver/CreateInvocationFromArgs.h
@@ -0,0 +1,76 @@
+//===--- CreateInvocationFromArgs.h - CompilerInvocation from Args --------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utility for creating a CompilerInvocation from command-line arguments, for
+// tools to use in preparation to parse a file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DRIVER_CREATEINVOCATIONFROMARGS_H
+#define LLVM_CLANG_DRIVER_CREATEINVOCATIONFROMARGS_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace clang {
+
+class CompilerInvocation;
+class DiagnosticsEngine;
+
+/// Optional inputs to createInvocation.
+struct CreateInvocationOptions {
+  /// Receives diagnostics encountered while parsing command-line flags.
+  /// If not provided, these are printed to stderr.
+  IntrusiveRefCntPtr<DiagnosticsEngine> Diags = nullptr;
+  /// Used e.g. to probe for system headers locations.
+  /// If not provided, the real filesystem is used.
+  /// FIXME: the driver does perform some non-virtualized IO.
+  IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr;
+  /// Whether to attempt to produce a non-null (possibly incorrect) invocation
+  /// if any errors were encountered.
+  /// By default, always return null on errors.
+  bool RecoverOnError = false;
+  /// Allow the driver to probe the filesystem for PCH files.
+  /// This is used to replace -include with -include-pch in the cc1 args.
+  /// FIXME: ProbePrecompiled=true is a poor, historical default.
+  /// It misbehaves if the PCH file is from GCC, has the wrong version, etc.
+  bool ProbePrecompiled = false;
+  /// If set, the target is populated with the cc1 args produced by the driver.
+  /// This may be populated even if createInvocation returns nullptr.
+  std::vector<std::string> *CC1Args = nullptr;
+};
+
+/// Interpret clang arguments in preparation to parse a file.
+///
+/// This simulates a number of steps Clang takes when its driver is invoked:
+/// - choosing actions (e.g compile + link) to run
+/// - probing the system for settings like standard library locations
+/// - spawning a cc1 subprocess to compile code, with more explicit arguments
+/// - in the cc1 process, assembling those arguments into a CompilerInvocation
+///   which is used to configure the parser
+///
+/// This simulation is lossy, e.g. in some situations one driver run would
+/// result in multiple parses. (Multi-arch, CUDA, ...).
+/// This function tries to select a reasonable invocation that tools should use.
+///
+/// Args[0] should be the driver name, such as "clang" or "/usr/bin/g++".
+/// Absolute path is preferred - this affects searching for system headers.
+///
+/// May return nullptr if an invocation could not be determined.
+/// See CreateInvocationOptions::RecoverOnError to try harder!
+std::unique_ptr<CompilerInvocation>
+createInvocation(ArrayRef<const char *> Args,
+                 CreateInvocationOptions Opts = {});
+
+} // namespace clang
+
+#endif // LLVM_CLANG_DRIVER_CREATEINVOCATIONFROMARGS_H
diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index 83bcb7cab550f..76a6c5a128efb 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -406,10 +406,6 @@ class Driver {
                               SmallString<128> &CrashDiagDir);
 
 public:
-  /// Takes the path to a binary that's either in bin/ or lib/ and returns
-  /// the path to clang's resource directory.
-  static std::string GetResourcesPath(StringRef BinaryPath);
-
   Driver(StringRef ClangExecutable, StringRef TargetTriple,
          DiagnosticsEngine &Diags, std::string Title = "clang LLVM compiler",
          IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h
index e585933a5c8be..341460e1962cb 100644
--- a/clang/include/clang/Frontend/ASTUnit.h
+++ b/clang/include/clang/Frontend/ASTUnit.h
@@ -23,11 +23,13 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetOptions.h"
 #include "clang/Frontend/PrecompiledPreamble.h"
+#include "clang/Frontend/StandaloneDiagnostic.h"
 #include "clang/Lex/HeaderSearchOptions.h"
 #include "clang/Lex/ModuleLoader.h"
 #include "clang/Lex/PreprocessingRecord.h"
 #include "clang/Sema/CodeCompleteConsumer.h"
 #include "clang/Serialization/ASTBitCodes.h"
+#include "clang/Serialization/ASTWriter.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -36,6 +38,7 @@
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator_range.h"
+#include "llvm/Bitstream/BitstreamWriter.h"
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
@@ -88,25 +91,6 @@ enum class CaptureDiagsKind { None, All, AllWithoutNonErrorsFromIncludes };
 
 /// Utility class for loading a ASTContext from an AST file.
 class ASTUnit {
-public:
-  struct StandaloneFixIt {
-    std::pair<unsigned, unsigned> RemoveRange;
-    std::pair<unsigned, unsigned> InsertFromRange;
-    std::string CodeToInsert;
-    bool BeforePreviousInsertions;
-  };
-
-  struct StandaloneDiagnostic {
-    unsigned ID;
-    DiagnosticsEngine::Level Level;
-    std::string Message;
-    std::string Filename;
-    unsigned LocOffset;
-    std::vector<std::pair<unsigned, unsigned>> Ranges;
-    std::vector<StandaloneFixIt> FixIts;
-  };
-
-private:
   std::unique_ptr<LangOptions> LangOpts;
   std::unique_ptr<CodeGenOptions> CodeGenOpts;
   // FIXME: The documentation on \c LoadFrom* member functions states that the
@@ -129,7 +113,15 @@ class ASTUnit {
   bool HadModuleLoaderFatalFailure = false;
   bool StorePreamblesInMemory = false;
 
-  struct ASTWriterData;
+  /// Utility struct for managing ASTWriter and its associated data streams.
+  struct ASTWriterData {
+    SmallString<128> Buffer;
+    llvm::BitstreamWriter Stream;
+    ASTWriter Writer;
+
+    ASTWriterData(ModuleCache &ModCache, const CodeGenOptions &CGOpts)
+        : Stream(Buffer), Writer(Stream, Buffer, ModCache, CGOpts, {}) {}
+  };
   std::unique_ptr<ASTWriterData> WriterData;
 
   FileSystemOptions FileSystemOpts;
@@ -271,11 +263,6 @@ class ASTUnit {
   static void ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
                              ASTUnit &AST, CaptureDiagsKind CaptureDiagnostics);
 
-  void
-  TranslateStoredDiagnostics(FileManager &FileMgr, SourceManager &SrcMan,
-                             const SmallVectorImpl<StandaloneDiagnostic> &Diags,
-                             SmallVectorImpl<StoredDiagnostic> &Out);
-
   void clearFileLevelDecls();
 
 public:
@@ -834,65 +821,24 @@ class ASTUnit {
       bool IncludeBriefCommentsInCodeCompletion = false,
       bool UserFilesAreVolatile = false);
 
-  /// LoadFromCommandLine - Create an ASTUnit from a vector of command line
-  /// arguments, which must specify exactly one source file.
-  ///
-  /// \param ArgBegin - The beginning of the argument vector.
-  ///
-  /// \param ArgEnd - The end of the argument vector.
-  ///
-  /// \param PCHContainerOps - The PCHContainerOperations to use for loading and
-  /// creating modules.
-  ///
-  /// \param Diags - The diagnostics engine to use for reporting errors; its
-  /// lifetime is expected to extend past that of the returned ASTUnit.
-  ///
-  /// \param ResourceFilesPath - The path to the compiler resource files.
-  ///
-  /// \param StorePreamblesInMemory - Whether to store PCH in memory. If false,
-  /// PCH are stored in temporary files.
-  ///
-  /// \param PreambleStoragePath - The path to a directory, in which to create
-  /// temporary PCH files. If empty, the default system temporary directory is
-  /// used. This parameter is ignored if \p StorePreamblesInMemory is true.
-  ///
-  /// \param ModuleFormat - If provided, uses the specific module format.
-  ///
-  /// \param ErrAST - If non-null and parsing failed without any AST to return
-  /// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
-  /// mainly to allow the caller to see the diagnostics.
-  ///
-  /// \param VFS - A llvm::vfs::FileSystem to be used for all file accesses.
-  /// Note that preamble is saved to a temporary directory on a RealFileSystem,
-  /// so in order for it to be loaded correctly, VFS should have access to
-  /// it(i.e., be an overlay over RealFileSystem). RealFileSystem will be used
-  /// if \p VFS is nullptr.
-  ///
-  // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
-  // shouldn't need to specify them at construction time.
-  static std::unique_ptr<ASTUnit> LoadFromCommandLine(
+  friend std::unique_ptr<ASTUnit> CreateASTUnitFromCommandLine(
       const char **ArgBegin, const char **ArgEnd,
       std::shared_ptr<PCHContainerOperations> PCHContainerOps,
       std::shared_ptr<DiagnosticOptions> DiagOpts,
       IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
-      bool StorePreamblesInMemory = false,
-      StringRef PreambleStoragePath = StringRef(), bool OnlyLocalDecls = false,
-      CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None,
-      ArrayRef<RemappedFile> RemappedFiles = {},
-      bool RemappedFilesKeepOriginalName = true,
-      unsigned PrecompilePreambleAfterNParses = 0,
-      TranslationUnitKind TUKind = TU_Complete,
-      bool CacheCodeCompletionResults = false,
-      bool IncludeBriefCommentsInCodeCompletion = false,
-      bool AllowPCHWithCompilerErrors = false,
-      SkipFunctionBodiesScope SkipFunctionBodies =
-          SkipFunctionBodiesScope::None,
-      bool SingleFileParse = false, bool UserFilesAreVolatile = false,
-      bool ForSerialization = false,
-      bool RetainExcludedConditionalBlocks = false,
-      std::optional<StringRef> ModuleFormat = std::nullopt,
-      std::unique_ptr<ASTUnit> *ErrAST = nullptr,
-      IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
+      bool StorePreamblesInMemory, StringRef PreambleStoragePath,
+      bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,
+      ArrayRef<ASTUnit::RemappedFile> RemappedFiles,
+      bool RemappedFilesKeepOriginalName,
+      unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
+      bool CacheCodeCompletionResults,
+      bool IncludeBriefCommentsInCodeCompletion,
+      bool AllowPCHWithCompilerErrors,
+      SkipFunctionBodiesScope SkipFunctionBodies, bool SingleFileParse,
+      bool UserFilesAreVolatile, bool ForSerialization,
+      bool RetainExcludedConditionalBlocks,
+      std::optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST,
+      IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS);
 
   /// Reparse the source files using the same command-line options that
   /// were originally used to produce this translation unit.
@@ -963,6 +909,44 @@ class ASTUnit {
   bool serialize(raw_ostream &OS);
 };
 
+/// Diagnostic consumer that saves each diagnostic it is given.
+class FilterAndStoreDiagnosticConsumer : public DiagnosticConsumer {
+  SmallVectorImpl<StoredDiagnostic> *StoredDiags;
+  SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags;
+  bool CaptureNonErrorsFromIncludes = true;
+  const LangOptions *LangOpts = nullptr;
+  SourceManager *SourceMgr = nullptr;
+
+public:
+  FilterAndStoreDiagnosticConsumer(
+      SmallVectorImpl<StoredDiagnostic> *StoredDiags,
+      SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags,
+      bool CaptureNonErrorsFromIncludes);
+
+  void BeginSourceFile(const LangOptions &LangOpts,
+                       const Preprocessor *PP = nullptr) override;
+
+  void HandleDiagnostic(DiagnosticsEngine::Level Level,
+                        const Diagnostic &Info) override;
+};
+
+/// RAII object that optionally captures and filters diagnostics, if
+/// there is no diagnostic client to capture them already.
+class CaptureDroppedDiagnostics {
+  DiagnosticsEngine &Diags;
+  FilterAndStoreDiagnosticConsumer Client;
+  DiagnosticConsumer *PreviousClient = nullptr;
+  std::unique_ptr<DiagnosticConsumer> OwningPreviousClient;
+
+public:
+  CaptureDroppedDiagnostics(
+      CaptureDiagsKind CaptureDiagnostics, DiagnosticsEngine &Diags,
+      SmallVectorImpl<StoredDiagnostic> *StoredDiags,
+      SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags);
+
+  ~CaptureDroppedDiagnostics();
+};
+
 } // namespace clang
 
 #endif // LLVM_CLANG_FRONTEND_ASTUNIT_H
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h
index b19a6e1a8acc3..4977ddb307d21 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -299,16 +299,6 @@ class CompilerInvocation : public CompilerInvocationBase {
                 ...
[truncated]

@naveen-seth
Copy link
Contributor Author

Closed in favor of #169599.

@naveen-seth naveen-seth deleted the revert-169397-fix-revert-165277 branch November 26, 2025 03:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:as-a-library libclang and C++ API clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules clang-tools-extra clangd flang:driver flang Flang issues not falling into any other category lldb

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants