Skip to content

Commit 49db4fc

Browse files
committed
[clang] Remove clangDriver dependency from clangFrontend (NFC)
This PR removes the clangDriver dependency from clangFrontend. The goal of this change is to remove dependencies on the Driver. This is part of a larger effort to support driver-managed builds for compilations using C++ named modules and/or Clang modules. This is required to eventually allow linking the dependency scanning toolingagainst the Driver without creating cyclic dependencies, which would cause build failures with dynamic linking enabled. This change is motivated by the following review comment: #152770 (comment)
1 parent f0015a2 commit 49db4fc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+695
-459
lines changed

clang-tools-extra/clangd/CompileCommands.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ std::optional<std::string> detectSysroot() {
132132

133133
std::string detectStandardResourceDir() {
134134
static int StaticForMainAddr; // Just an address in this process.
135-
return CompilerInvocation::GetResourcesPath("clangd",
136-
(void *)&StaticForMainAddr);
135+
return driver::Driver::GetResourcesPathForInvocation(
136+
"clangd", (void *)&StaticForMainAddr);
137137
}
138138

139139
// The path passed to argv[0] is important:

clang-tools-extra/clangd/Compiler.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "Compiler.h"
1010
#include "support/Logger.h"
1111
#include "clang/Basic/TargetInfo.h"
12+
#include "clang/Driver/CreateInvocationFromArgs.h"
1213
#include "clang/Frontend/CompilerInvocation.h"
1314
#include "clang/Lex/PreprocessorOptions.h"
1415
#include "clang/Serialization/PCHContainerOperations.h"
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//===-- CreateInvocationFromArgs.h - Create an ASTUnit from Args-*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Utility for creating an ASTUnit from a vector of command line arguments.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_CLANG_DRIVER_CREATEASTUNITFROMARGS_H
14+
#define LLVM_CLANG_DRIVER_CREATEASTUNITFROMARGS_H
15+
16+
#include "clang/Frontend/ASTUnit.h"
17+
18+
namespace clang {
19+
20+
/// Create an ASTUnit from a vector of command line arguments, which must
21+
/// specify exactly one source file.
22+
///
23+
/// \param ArgBegin - The beginning of the argument vector.
24+
///
25+
/// \param ArgEnd - The end of the argument vector.
26+
///
27+
/// \param PCHContainerOps - The PCHContainerOperations to use for loading and
28+
/// creating modules.
29+
///
30+
/// \param Diags - The diagnostics engine to use for reporting errors; its
31+
/// lifetime is expected to extend past that of the returned ASTUnit.
32+
///
33+
/// \param ResourceFilesPath - The path to the compiler resource files.
34+
///
35+
/// \param StorePreamblesInMemory - Whether to store PCH in memory. If false,
36+
/// PCH are stored in temporary files.
37+
///
38+
/// \param PreambleStoragePath - The path to a directory, in which to create
39+
/// temporary PCH files. If empty, the default system temporary directory is
40+
/// used. This parameter is ignored if \p StorePreamblesInMemory is true.
41+
///
42+
/// \param ModuleFormat - If provided, uses the specific module format.
43+
///
44+
/// \param ErrAST - If non-null and parsing failed without any AST to return
45+
/// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
46+
/// mainly to allow the caller to see the diagnostics.
47+
///
48+
/// \param VFS - A llvm::vfs::FileSystem to be used for all file accesses.
49+
/// Note that preamble is saved to a temporary directory on a RealFileSystem,
50+
/// so in order for it to be loaded correctly, VFS should have access to
51+
/// it(i.e., be an overlay over RealFileSystem). RealFileSystem will be used
52+
/// if \p VFS is nullptr.
53+
///
54+
// FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
55+
// shouldn't need to specify them at construction time.
56+
std::unique_ptr<ASTUnit> CreateASTUnitFromCommandLine(
57+
const char **ArgBegin, const char **ArgEnd,
58+
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
59+
std::shared_ptr<DiagnosticOptions> DiagOpts,
60+
IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
61+
bool StorePreamblesInMemory = false,
62+
StringRef PreambleStoragePath = StringRef(), bool OnlyLocalDecls = false,
63+
CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None,
64+
ArrayRef<ASTUnit::RemappedFile> RemappedFiles = {},
65+
bool RemappedFilesKeepOriginalName = true,
66+
unsigned PrecompilePreambleAfterNParses = 0,
67+
TranslationUnitKind TUKind = TU_Complete,
68+
bool CacheCodeCompletionResults = false,
69+
bool IncludeBriefCommentsInCodeCompletion = false,
70+
bool AllowPCHWithCompilerErrors = false,
71+
SkipFunctionBodiesScope SkipFunctionBodies = SkipFunctionBodiesScope::None,
72+
bool SingleFileParse = false, bool UserFilesAreVolatile = false,
73+
bool ForSerialization = false, bool RetainExcludedConditionalBlocks = false,
74+
std::optional<StringRef> ModuleFormat = std::nullopt,
75+
std::unique_ptr<ASTUnit> *ErrAST = nullptr,
76+
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
77+
78+
} // namespace clang
79+
80+
#endif // LLVM_CLANG_DRIVER_CREATEASTUNITFROMARGS_H
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//===--- CreateInvocationFromArgs.h - CompilerInvocation from Args --------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Utility for creating a CompilerInvocation from command-line arguments, for
10+
// tools to use in preparation to parse a file.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_CLANG_DRIVER_CREATEINVOCATIONFROMARGS_H
15+
#define LLVM_CLANG_DRIVER_CREATEINVOCATIONFROMARGS_H
16+
17+
#include "clang/Basic/Diagnostic.h"
18+
#include "clang/Basic/LLVM.h"
19+
#include "llvm/Support/VirtualFileSystem.h"
20+
#include <memory>
21+
#include <string>
22+
#include <vector>
23+
24+
namespace clang {
25+
26+
class CompilerInvocation;
27+
class DiagnosticsEngine;
28+
29+
/// Optional inputs to createInvocation.
30+
struct CreateInvocationOptions {
31+
/// Receives diagnostics encountered while parsing command-line flags.
32+
/// If not provided, these are printed to stderr.
33+
IntrusiveRefCntPtr<DiagnosticsEngine> Diags = nullptr;
34+
/// Used e.g. to probe for system headers locations.
35+
/// If not provided, the real filesystem is used.
36+
/// FIXME: the driver does perform some non-virtualized IO.
37+
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr;
38+
/// Whether to attempt to produce a non-null (possibly incorrect) invocation
39+
/// if any errors were encountered.
40+
/// By default, always return null on errors.
41+
bool RecoverOnError = false;
42+
/// Allow the driver to probe the filesystem for PCH files.
43+
/// This is used to replace -include with -include-pch in the cc1 args.
44+
/// FIXME: ProbePrecompiled=true is a poor, historical default.
45+
/// It misbehaves if the PCH file is from GCC, has the wrong version, etc.
46+
bool ProbePrecompiled = false;
47+
/// If set, the target is populated with the cc1 args produced by the driver.
48+
/// This may be populated even if createInvocation returns nullptr.
49+
std::vector<std::string> *CC1Args = nullptr;
50+
};
51+
52+
/// Interpret clang arguments in preparation to parse a file.
53+
///
54+
/// This simulates a number of steps Clang takes when its driver is invoked:
55+
/// - choosing actions (e.g compile + link) to run
56+
/// - probing the system for settings like standard library locations
57+
/// - spawning a cc1 subprocess to compile code, with more explicit arguments
58+
/// - in the cc1 process, assembling those arguments into a CompilerInvocation
59+
/// which is used to configure the parser
60+
///
61+
/// This simulation is lossy, e.g. in some situations one driver run would
62+
/// result in multiple parses. (Multi-arch, CUDA, ...).
63+
/// This function tries to select a reasonable invocation that tools should use.
64+
///
65+
/// Args[0] should be the driver name, such as "clang" or "/usr/bin/g++".
66+
/// Absolute path is preferred - this affects searching for system headers.
67+
///
68+
/// May return nullptr if an invocation could not be determined.
69+
/// See CreateInvocationOptions::RecoverOnError to try harder!
70+
std::unique_ptr<CompilerInvocation>
71+
createInvocation(ArrayRef<const char *> Args,
72+
CreateInvocationOptions Opts = {});
73+
74+
} // namespace clang
75+
76+
#endif // LLVM_CLANG_DRIVER_CREATEINVOCATIONFROMARGS_H

clang/include/clang/Driver/Driver.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,16 @@ class Driver {
411411
/// the path to clang's resource directory.
412412
static std::string GetResourcesPath(StringRef BinaryPath);
413413

414+
/// Get the directory where the compiler headers reside, relative to the
415+
/// compiler binary (found by the passed in arguments).
416+
///
417+
/// \param Argv0 - The program path (from argv[0]), for finding the builtin
418+
/// compiler path.
419+
/// \param MainAddr - The address of main (or some other function in the main
420+
/// executable), for finding the builtin compiler path.
421+
static std::string GetResourcesPathForInvocation(const char *Argv0,
422+
void *MainAddr);
423+
414424
Driver(StringRef ClangExecutable, StringRef TargetTriple,
415425
DiagnosticsEngine &Diags, std::string Title = "clang LLVM compiler",
416426
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);

clang/include/clang/Frontend/ASTUnit.h

Lines changed: 65 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@
2222
#include "clang/Basic/SourceLocation.h"
2323
#include "clang/Basic/SourceManager.h"
2424
#include "clang/Basic/TargetOptions.h"
25+
#include "clang/Frontend/PrecompiledPreamble.h"
26+
#include "clang/Frontend/StandaloneDiagnostic.h"
2527
#include "clang/Lex/HeaderSearchOptions.h"
2628
#include "clang/Lex/ModuleLoader.h"
2729
#include "clang/Lex/PreprocessingRecord.h"
2830
#include "clang/Sema/CodeCompleteConsumer.h"
2931
#include "clang/Serialization/ASTBitCodes.h"
30-
#include "clang/Frontend/PrecompiledPreamble.h"
32+
#include "clang/Serialization/ASTWriter.h"
3133
#include "llvm/ADT/ArrayRef.h"
3234
#include "llvm/ADT/DenseMap.h"
3335
#include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -36,6 +38,7 @@
3638
#include "llvm/ADT/StringMap.h"
3739
#include "llvm/ADT/StringRef.h"
3840
#include "llvm/ADT/iterator_range.h"
41+
#include "llvm/Bitstream/BitstreamWriter.h"
3942
#include <cassert>
4043
#include <cstddef>
4144
#include <cstdint>
@@ -88,25 +91,6 @@ enum class CaptureDiagsKind { None, All, AllWithoutNonErrorsFromIncludes };
8891

8992
/// Utility class for loading a ASTContext from an AST file.
9093
class ASTUnit {
91-
public:
92-
struct StandaloneFixIt {
93-
std::pair<unsigned, unsigned> RemoveRange;
94-
std::pair<unsigned, unsigned> InsertFromRange;
95-
std::string CodeToInsert;
96-
bool BeforePreviousInsertions;
97-
};
98-
99-
struct StandaloneDiagnostic {
100-
unsigned ID;
101-
DiagnosticsEngine::Level Level;
102-
std::string Message;
103-
std::string Filename;
104-
unsigned LocOffset;
105-
std::vector<std::pair<unsigned, unsigned>> Ranges;
106-
std::vector<StandaloneFixIt> FixIts;
107-
};
108-
109-
private:
11094
std::unique_ptr<LangOptions> LangOpts;
11195
std::unique_ptr<CodeGenOptions> CodeGenOpts;
11296
// FIXME: The documentation on \c LoadFrom* member functions states that the
@@ -129,7 +113,15 @@ class ASTUnit {
129113
bool HadModuleLoaderFatalFailure = false;
130114
bool StorePreamblesInMemory = false;
131115

132-
struct ASTWriterData;
116+
/// Utility struct for managing ASTWriter and its associated data streams.
117+
struct ASTWriterData {
118+
SmallString<128> Buffer;
119+
llvm::BitstreamWriter Stream;
120+
ASTWriter Writer;
121+
122+
ASTWriterData(ModuleCache &ModCache, const CodeGenOptions &CGOpts)
123+
: Stream(Buffer), Writer(Stream, Buffer, ModCache, CGOpts, {}) {}
124+
};
133125
std::unique_ptr<ASTWriterData> WriterData;
134126

135127
FileSystemOptions FileSystemOpts;
@@ -271,11 +263,6 @@ class ASTUnit {
271263
static void ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
272264
ASTUnit &AST, CaptureDiagsKind CaptureDiagnostics);
273265

274-
void TranslateStoredDiagnostics(FileManager &FileMgr,
275-
SourceManager &SrcMan,
276-
const SmallVectorImpl<StandaloneDiagnostic> &Diags,
277-
SmallVectorImpl<StoredDiagnostic> &Out);
278-
279266
void clearFileLevelDecls();
280267

281268
public:
@@ -834,65 +821,24 @@ class ASTUnit {
834821
bool IncludeBriefCommentsInCodeCompletion = false,
835822
bool UserFilesAreVolatile = false);
836823

837-
/// LoadFromCommandLine - Create an ASTUnit from a vector of command line
838-
/// arguments, which must specify exactly one source file.
839-
///
840-
/// \param ArgBegin - The beginning of the argument vector.
841-
///
842-
/// \param ArgEnd - The end of the argument vector.
843-
///
844-
/// \param PCHContainerOps - The PCHContainerOperations to use for loading and
845-
/// creating modules.
846-
///
847-
/// \param Diags - The diagnostics engine to use for reporting errors; its
848-
/// lifetime is expected to extend past that of the returned ASTUnit.
849-
///
850-
/// \param ResourceFilesPath - The path to the compiler resource files.
851-
///
852-
/// \param StorePreamblesInMemory - Whether to store PCH in memory. If false,
853-
/// PCH are stored in temporary files.
854-
///
855-
/// \param PreambleStoragePath - The path to a directory, in which to create
856-
/// temporary PCH files. If empty, the default system temporary directory is
857-
/// used. This parameter is ignored if \p StorePreamblesInMemory is true.
858-
///
859-
/// \param ModuleFormat - If provided, uses the specific module format.
860-
///
861-
/// \param ErrAST - If non-null and parsing failed without any AST to return
862-
/// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
863-
/// mainly to allow the caller to see the diagnostics.
864-
///
865-
/// \param VFS - A llvm::vfs::FileSystem to be used for all file accesses.
866-
/// Note that preamble is saved to a temporary directory on a RealFileSystem,
867-
/// so in order for it to be loaded correctly, VFS should have access to
868-
/// it(i.e., be an overlay over RealFileSystem). RealFileSystem will be used
869-
/// if \p VFS is nullptr.
870-
///
871-
// FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
872-
// shouldn't need to specify them at construction time.
873-
static std::unique_ptr<ASTUnit> LoadFromCommandLine(
824+
friend std::unique_ptr<ASTUnit> CreateASTUnitFromCommandLine(
874825
const char **ArgBegin, const char **ArgEnd,
875826
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
876827
std::shared_ptr<DiagnosticOptions> DiagOpts,
877828
IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
878-
bool StorePreamblesInMemory = false,
879-
StringRef PreambleStoragePath = StringRef(), bool OnlyLocalDecls = false,
880-
CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None,
881-
ArrayRef<RemappedFile> RemappedFiles = {},
882-
bool RemappedFilesKeepOriginalName = true,
883-
unsigned PrecompilePreambleAfterNParses = 0,
884-
TranslationUnitKind TUKind = TU_Complete,
885-
bool CacheCodeCompletionResults = false,
886-
bool IncludeBriefCommentsInCodeCompletion = false,
887-
bool AllowPCHWithCompilerErrors = false,
888-
SkipFunctionBodiesScope SkipFunctionBodies =
889-
SkipFunctionBodiesScope::None,
890-
bool SingleFileParse = false, bool UserFilesAreVolatile = false,
891-
bool ForSerialization = false,
892-
bool RetainExcludedConditionalBlocks = false,
893-
std::optional<StringRef> ModuleFormat = std::nullopt,
894-
std::unique_ptr<ASTUnit> *ErrAST = nullptr,
895-
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
829+
bool StorePreamblesInMemory, StringRef PreambleStoragePath,
830+
bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,
831+
ArrayRef<ASTUnit::RemappedFile> RemappedFiles,
832+
bool RemappedFilesKeepOriginalName,
833+
unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
834+
bool CacheCodeCompletionResults,
835+
bool IncludeBriefCommentsInCodeCompletion,
836+
bool AllowPCHWithCompilerErrors,
837+
SkipFunctionBodiesScope SkipFunctionBodies, bool SingleFileParse,
838+
bool UserFilesAreVolatile, bool ForSerialization,
839+
bool RetainExcludedConditionalBlocks,
840+
std::optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST,
841+
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS);
896842

897843
/// Reparse the source files using the same command-line options that
898844
/// were originally used to produce this translation unit.
@@ -963,6 +909,44 @@ class ASTUnit {
963909
bool serialize(raw_ostream &OS);
964910
};
965911

912+
/// Diagnostic consumer that saves each diagnostic it is given.
913+
class FilterAndStoreDiagnosticConsumer : public DiagnosticConsumer {
914+
SmallVectorImpl<StoredDiagnostic> *StoredDiags;
915+
SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags;
916+
bool CaptureNonErrorsFromIncludes = true;
917+
const LangOptions *LangOpts = nullptr;
918+
SourceManager *SourceMgr = nullptr;
919+
920+
public:
921+
FilterAndStoreDiagnosticConsumer(
922+
SmallVectorImpl<StoredDiagnostic> *StoredDiags,
923+
SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags,
924+
bool CaptureNonErrorsFromIncludes);
925+
926+
void BeginSourceFile(const LangOptions &LangOpts,
927+
const Preprocessor *PP = nullptr) override;
928+
929+
void HandleDiagnostic(DiagnosticsEngine::Level Level,
930+
const Diagnostic &Info) override;
931+
};
932+
933+
/// RAII object that optionally captures and filters diagnostics, if
934+
/// there is no diagnostic client to capture them already.
935+
class CaptureDroppedDiagnostics {
936+
DiagnosticsEngine &Diags;
937+
FilterAndStoreDiagnosticConsumer Client;
938+
DiagnosticConsumer *PreviousClient = nullptr;
939+
std::unique_ptr<DiagnosticConsumer> OwningPreviousClient;
940+
941+
public:
942+
CaptureDroppedDiagnostics(
943+
CaptureDiagsKind CaptureDiagnostics, DiagnosticsEngine &Diags,
944+
SmallVectorImpl<StoredDiagnostic> *StoredDiags,
945+
SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags);
946+
947+
~CaptureDroppedDiagnostics();
948+
};
949+
966950
} // namespace clang
967951

968952
#endif // LLVM_CLANG_FRONTEND_ASTUNIT_H

0 commit comments

Comments
 (0)