Revert " [clang] Refactor to remove clangDriver dependency from clangFrontend and flangFrontend (#165277)" (#169397)

This reverts commit 3773bbe and relands the last revert attempt 40334b8.
3773bbe broke the build for the build configuration described in here:
https://github.com/llvm/llvm-project/pull/165277#issuecomment-3572432250
This commit is contained in:
Naveen Seth Hanig 2025-11-24 21:09:30 +01:00 committed by GitHub
parent 5c15f57923
commit dea330b38d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
60 changed files with 681 additions and 934 deletions

View File

@ -132,7 +132,8 @@ std::optional<std::string> detectSysroot() {
std::string detectStandardResourceDir() {
static int StaticForMainAddr; // Just an address in this process.
return GetResourcesPath("clangd", (void *)&StaticForMainAddr);
return CompilerInvocation::GetResourcesPath("clangd",
(void *)&StaticForMainAddr);
}
// The path passed to argv[0] is important:

View File

@ -9,7 +9,6 @@
#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"

View File

@ -84,8 +84,6 @@ 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
-------------------------------------------

View File

@ -291,6 +291,16 @@ 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);

View File

@ -1,80 +0,0 @@
//===-- 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

View File

@ -1,76 +0,0 @@
//===--- 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

View File

@ -406,6 +406,10 @@ private:
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);

View File

@ -23,13 +23,11 @@
#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"
@ -38,7 +36,6 @@
#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>
@ -91,6 +88,25 @@ 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
@ -113,15 +129,7 @@ class ASTUnit {
bool HadModuleLoaderFatalFailure = false;
bool StorePreamblesInMemory = false;
/// 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, {}) {}
};
struct ASTWriterData;
std::unique_ptr<ASTWriterData> WriterData;
FileSystemOptions FileSystemOpts;
@ -263,6 +271,11 @@ 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:
@ -821,24 +834,65 @@ public:
bool IncludeBriefCommentsInCodeCompletion = false,
bool UserFilesAreVolatile = false);
friend std::unique_ptr<ASTUnit> CreateASTUnitFromCommandLine(
/// 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(
const char **ArgBegin, const char **ArgEnd,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
std::shared_ptr<DiagnosticOptions> DiagOpts,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
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);
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);
/// Reparse the source files using the same command-line options that
/// were originally used to produce this translation unit.
@ -909,44 +963,6 @@ public:
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

View File

@ -299,6 +299,16 @@ public:
DiagnosticsEngine &Diags,
const char *Argv0 = nullptr);
/// Get the directory where the compiler headers
/// reside, relative to the compiler binary (found by the passed in
/// arguments).
///
/// \param Argv0 - The program path (from argv[0]), for finding the builtin
/// compiler path.
/// \param MainAddr - The address of main (or some other function in the main
/// executable), for finding the builtin compiler path.
static std::string GetResourcesPath(const char *Argv0, void *MainAddr);
/// Populate \p Opts with the default set of pointer authentication-related
/// options given \p LangOpts and \p Triple.
///

View File

@ -1,82 +0,0 @@
//===--- StandaloneDiagnostic.h - Serializable Diagnostic -------*- 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
//
//===----------------------------------------------------------------------===//
//
// A serializable diagnostic representation to retain diagnostics after their
// SourceManager has been destroyed.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_FRONTEND_STANDALONEDIAGNOSTICS_H
#define LLVM_CLANG_FRONTEND_STANDALONEDIAGNOSTICS_H
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/StringExtras.h"
#include <cassert>
#include <string>
#include <vector>
namespace clang {
/// Represents a StoredDiagnostic in a form that can be retained until after its
/// SourceManager has been destroyed.
///
/// Source locations are stored as a combination of filename and offsets into
/// that file.
/// To report the diagnostic, it must first be translated back into a
/// StoredDiagnostic with a new associated SourceManager.
struct StandaloneDiagnostic {
/// Represents a CharSourceRange within a StandaloneDiagnostic.
struct SourceOffsetRange {
SourceOffsetRange(CharSourceRange Range, const SourceManager &SrcMgr,
const LangOptions &LangOpts);
unsigned Begin = 0;
unsigned End = 0;
};
/// Represents a FixItHint within a StandaloneDiagnostic.
struct StandaloneFixIt {
StandaloneFixIt(const SourceManager &SrcMgr, const LangOptions &LangOpts,
const FixItHint &FixIt);
SourceOffsetRange RemoveRange;
SourceOffsetRange InsertFromRange;
std::string CodeToInsert;
bool BeforePreviousInsertions;
};
StandaloneDiagnostic(const LangOptions &LangOpts,
const StoredDiagnostic &InDiag);
DiagnosticsEngine::Level Level;
SrcMgr::CharacteristicKind FileKind;
unsigned ID = 0;
unsigned FileOffset = 0;
std::string Message;
std::string Filename;
std::vector<SourceOffsetRange> Ranges;
std::vector<StandaloneFixIt> FixIts;
};
/// Translates \c StandaloneDiag into a StoredDiagnostic, associating it with
/// the provided FileManager and SourceManager.
///
/// This allows the diagnostic to be emitted using the diagnostics engine, since
/// StandaloneDiagnostics themselfs cannot be emitted directly.
StoredDiagnostic
translateStandaloneDiag(FileManager &FileMgr, SourceManager &SrcMgr,
const StandaloneDiagnostic &StandaloneDiag,
llvm::StringMap<SourceLocation> &SrcLocCache);
} // namespace clang
#endif // STANDALONEDIAGNOSTICS

View File

@ -192,6 +192,51 @@ IntrusiveRefCntPtr<ExternalSemaSource>
createChainedIncludesSource(CompilerInstance &CI,
IntrusiveRefCntPtr<ASTReader> &OutReader);
/// 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::ShouldRecoverOnErrors to try harder!
std::unique_ptr<CompilerInvocation>
createInvocation(ArrayRef<const char *> Args,
CreateInvocationOptions Opts = {});
} // namespace clang
#endif // LLVM_CLANG_FRONTEND_UTILS_H

View File

@ -28,7 +28,6 @@ class ArgList;
} // namespace llvm
namespace clang {
/// Return the value of the last argument as an integer, or a default. If Diags
/// is non-null, emits an error if the argument is given, but non-integral.
int getLastArgIntValue(const llvm::opt::ArgList &Args,
@ -54,29 +53,6 @@ inline uint64_t getLastArgUInt64Value(const llvm::opt::ArgList &Args,
return getLastArgUInt64Value(Args, Id, Default, &Diags, Base);
}
// 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);
/// Get the directory where the compiler headers reside, relative to the
/// compiler binary path \p BinaryPath.
std::string GetResourcesPath(StringRef BinaryPath);
/// Get the directory where the compiler headers reside, relative to the
/// compiler binary path (found by the passed in arguments).
///
/// \param Argv0 The program path (from argv[0]), for finding the builtin
/// compiler path.
/// \param MainAddr The address of main (or some other function in the main
/// executable), for finding the builtin compiler path.
std::string GetResourcesPath(const char *Argv0, void *MainAddr);
} // namespace clang
#endif // LLVM_CLANG_OPTIONS_OPTIONUTILS_H

View File

@ -9,7 +9,6 @@ add_clang_library(clangCrossTU
LINK_LIBS
clangAST
clangBasic
clangDriver
clangFrontend
clangIndex
)

View File

@ -16,7 +16,6 @@
#include "clang/Basic/DiagnosticDriver.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CrossTU/CrossTUDiagnostic.h"
#include "clang/Driver/CreateASTUnitFromArgs.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
@ -620,7 +619,7 @@ CrossTranslationUnitContext::ASTLoader::loadFromSource(
auto Diags = llvm::makeIntrusiveRefCnt<DiagnosticsEngine>(DiagID, *DiagOpts,
DiagClient);
return CreateASTUnitFromCommandLine(
return ASTUnit::LoadFromCommandLine(
CommandLineArgs.begin(), (CommandLineArgs.end()),
CI.getPCHContainerOperations(), DiagOpts, Diags,
CI.getHeaderSearchOpts().ResourceDir);

View File

@ -17,8 +17,6 @@ endif()
add_clang_library(clangDriver
Action.cpp
Compilation.cpp
CreateASTUnitFromArgs.cpp
CreateInvocationFromArgs.cpp
Distro.cpp
Driver.cpp
Job.cpp
@ -98,8 +96,6 @@ add_clang_library(clangDriver
LINK_LIBS
clangBasic
clangFrontend
clangSerialization
clangLex
clangOptions
${system_libs}

View File

@ -1,166 +0,0 @@
//===--- CreateASTUnitFromArgs.h - Create an ASTUnit 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 an ASTUnit from a vector of command line arguments.
//
//===----------------------------------------------------------------------===//
#include "clang/Driver/CreateASTUnitFromArgs.h"
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Serialization/ModuleCache.h"
#include "llvm/Support/CrashRecoveryContext.h"
using 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> clang::CreateASTUnitFromCommandLine(
const char **ArgBegin, const char **ArgEnd,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
std::shared_ptr<DiagnosticOptions> DiagOpts,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
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) {
assert(Diags.get() && "no DiagnosticsEngine was provided");
// If no VFS was provided, create one that tracks the physical file system.
// If '-working-directory' was passed as an argument, 'createInvocation' will
// set this as the current working directory of the VFS.
if (!VFS)
VFS = llvm::vfs::createPhysicalFileSystem();
SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
std::shared_ptr<CompilerInvocation> CI;
{
CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags,
&StoredDiagnostics, nullptr);
CreateInvocationOptions CIOpts;
CIOpts.VFS = VFS;
CIOpts.Diags = Diags;
CIOpts.ProbePrecompiled = true; // FIXME: historical default. Needed?
CI = createInvocation(llvm::ArrayRef(ArgBegin, ArgEnd), std::move(CIOpts));
if (!CI)
return nullptr;
}
// Override any files that need remapping
for (const auto &RemappedFile : RemappedFiles) {
CI->getPreprocessorOpts().addRemappedFile(RemappedFile.first,
RemappedFile.second);
}
PreprocessorOptions &PPOpts = CI->getPreprocessorOpts();
PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName;
PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors;
PPOpts.SingleFileParseMode = SingleFileParse;
PPOpts.RetainExcludedConditionalBlocks = RetainExcludedConditionalBlocks;
// Override the resources path.
CI->getHeaderSearchOpts().ResourceDir = std::string(ResourceFilesPath);
CI->getFrontendOpts().SkipFunctionBodies =
SkipFunctionBodies == SkipFunctionBodiesScope::PreambleAndMainFile;
if (ModuleFormat)
CI->getHeaderSearchOpts().ModuleFormat = std::string(*ModuleFormat);
// Create the AST unit.
std::unique_ptr<ASTUnit> AST;
AST.reset(new ASTUnit(false));
AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();
AST->StoredDiagnostics.swap(StoredDiagnostics);
ASTUnit::ConfigureDiags(Diags, *AST, CaptureDiagnostics);
AST->DiagOpts = DiagOpts;
AST->Diagnostics = Diags;
AST->FileSystemOpts = CI->getFileSystemOpts();
AST->CodeGenOpts = std::make_unique<CodeGenOptions>(CI->getCodeGenOpts());
VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS);
AST->FileMgr =
llvm::makeIntrusiveRefCnt<FileManager>(AST->FileSystemOpts, VFS);
AST->StorePreamblesInMemory = StorePreamblesInMemory;
AST->PreambleStoragePath = PreambleStoragePath;
AST->ModCache = createCrossProcessModuleCache();
AST->OnlyLocalDecls = OnlyLocalDecls;
AST->CaptureDiagnostics = CaptureDiagnostics;
AST->TUKind = TUKind;
AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
AST->IncludeBriefCommentsInCodeCompletion =
IncludeBriefCommentsInCodeCompletion;
AST->UserFilesAreVolatile = UserFilesAreVolatile;
AST->Invocation = CI;
AST->SkipFunctionBodies = SkipFunctionBodies;
if (ForSerialization)
AST->WriterData.reset(
new ASTUnit::ASTWriterData(*AST->ModCache, *AST->CodeGenOpts));
// Zero out now to ease cleanup during crash recovery.
CI = nullptr;
Diags = nullptr;
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> ASTUnitCleanup(AST.get());
if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps),
PrecompilePreambleAfterNParses, VFS)) {
// Some error occurred, if caller wants to examine diagnostics, pass it the
// ASTUnit.
if (ErrAST) {
AST->StoredDiagnostics.swap(AST->FailedParseDiagnostics);
ErrAST->swap(AST);
}
return nullptr;
}
return AST;
}

View File

@ -66,7 +66,6 @@
#include "clang/Driver/ToolChain.h"
#include "clang/Driver/Types.h"
#include "clang/Lex/DependencyDirectivesScanner.h"
#include "clang/Options/OptionUtils.h"
#include "clang/Options/Options.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
@ -126,6 +125,40 @@ template <typename F> static bool usesInput(const ArgList &Args, F &&Fn) {
});
}
// static
std::string Driver::GetResourcesPath(StringRef BinaryPath) {
// Since the resource directory is embedded in the module hash, it's important
// that all places that need it call this function, so that they get the
// exact same string ("a/../b/" and "b/" get different hashes, for example).
// Dir is bin/ or lib/, depending on where BinaryPath is.
StringRef Dir = llvm::sys::path::parent_path(BinaryPath);
SmallString<128> P(Dir);
StringRef ConfiguredResourceDir(CLANG_RESOURCE_DIR);
if (!ConfiguredResourceDir.empty()) {
// FIXME: We should fix the behavior of llvm::sys::path::append so we don't
// need to check for absolute paths here.
if (llvm::sys::path::is_absolute(ConfiguredResourceDir))
P = ConfiguredResourceDir;
else
llvm::sys::path::append(P, ConfiguredResourceDir);
} else {
// On Windows, libclang.dll is in bin/.
// On non-Windows, libclang.so/.dylib is in lib/.
// With a static-library build of libclang, LibClangPath will contain the
// path of the embedding binary, which for LLVM binaries will be in bin/.
// ../lib gets us to lib/ in both cases.
P = llvm::sys::path::parent_path(Dir);
// This search path is also created in the COFF driver of lld, so any
// changes here also needs to happen in lld/COFF/Driver.cpp
llvm::sys::path::append(P, CLANG_INSTALL_LIBDIR_BASENAME, "clang",
CLANG_VERSION_MAJOR_STRING);
}
return std::string(P);
}
CUIDOptions::CUIDOptions(llvm::opt::DerivedArgList &Args, const Driver &D)
: UseCUID(Kind::Hash) {
if (Arg *A = Args.getLastArg(options::OPT_fuse_cuid_EQ)) {

View File

@ -32,7 +32,6 @@
#include "clang/Driver/SanitizerArgs.h"
#include "clang/Driver/Types.h"
#include "clang/Driver/XRayArgs.h"
#include "clang/Options/OptionUtils.h"
#include "clang/Options/Options.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallSet.h"

View File

@ -3398,6 +3398,169 @@ void tools::handleInterchangeLoopsArgs(const ArgList &Args,
CmdArgs.push_back("-floop-interchange");
}
// Parse -mprefer-vector-width=. Return the Value string if well-formed.
// Otherwise, return an empty string and issue a diagnosic message if needed.
StringRef tools::parseMPreferVectorWidthOption(clang::DiagnosticsEngine &Diags,
const llvm::opt::ArgList &Args) {
Arg *A = Args.getLastArg(options::OPT_mprefer_vector_width_EQ);
if (!A)
return "";
StringRef Value = A->getValue();
unsigned Width LLVM_ATTRIBUTE_UNINITIALIZED;
// Only "none" and Integer values are accepted by
// -mprefer-vector-width=<value>.
if (Value != "none" && Value.getAsInteger(10, Width)) {
Diags.Report(clang::diag::err_drv_invalid_value)
<< A->getOption().getName() << Value;
return "";
}
return Value;
}
// This is a helper function for validating the optional refinement step
// parameter in reciprocal argument strings. Return false if there is an error
// parsing the refinement step. Otherwise, return true and set the Position
// of the refinement step in the input string.
static bool getRefinementStep(StringRef In, clang::DiagnosticsEngine &Diags,
const Arg &A, size_t &Position) {
const char RefinementStepToken = ':';
Position = In.find(RefinementStepToken);
if (Position != StringRef::npos) {
StringRef Option = A.getOption().getName();
StringRef RefStep = In.substr(Position + 1);
// Allow exactly one numeric character for the additional refinement
// step parameter. This is reasonable for all currently-supported
// operations and architectures because we would expect that a larger value
// of refinement steps would cause the estimate "optimization" to
// under-perform the native operation. Also, if the estimate does not
// converge quickly, it probably will not ever converge, so further
// refinement steps will not produce a better answer.
if (RefStep.size() != 1) {
Diags.Report(diag::err_drv_invalid_value) << Option << RefStep;
return false;
}
char RefStepChar = RefStep[0];
if (RefStepChar < '0' || RefStepChar > '9') {
Diags.Report(diag::err_drv_invalid_value) << Option << RefStep;
return false;
}
}
return true;
}
// Parse -mrecip. Return the Value string if well-formed.
// Otherwise, return an empty string and issue a diagnosic message if needed.
StringRef tools::parseMRecipOption(clang::DiagnosticsEngine &Diags,
const ArgList &Args) {
StringRef DisabledPrefixIn = "!";
StringRef DisabledPrefixOut = "!";
StringRef EnabledPrefixOut = "";
StringRef Out = "";
Arg *A = Args.getLastArg(options::OPT_mrecip, options::OPT_mrecip_EQ);
if (!A)
return "";
unsigned NumOptions = A->getNumValues();
if (NumOptions == 0) {
// No option is the same as "all".
return "all";
}
// Pass through "all", "none", or "default" with an optional refinement step.
if (NumOptions == 1) {
StringRef Val = A->getValue(0);
size_t RefStepLoc;
if (!getRefinementStep(Val, Diags, *A, RefStepLoc))
return "";
StringRef ValBase = Val.slice(0, RefStepLoc);
if (ValBase == "all" || ValBase == "none" || ValBase == "default") {
return Val;
}
}
// Each reciprocal type may be enabled or disabled individually.
// Check each input value for validity, concatenate them all back together,
// and pass through.
llvm::StringMap<bool> OptionStrings;
OptionStrings.insert(std::make_pair("divd", false));
OptionStrings.insert(std::make_pair("divf", false));
OptionStrings.insert(std::make_pair("divh", false));
OptionStrings.insert(std::make_pair("vec-divd", false));
OptionStrings.insert(std::make_pair("vec-divf", false));
OptionStrings.insert(std::make_pair("vec-divh", false));
OptionStrings.insert(std::make_pair("sqrtd", false));
OptionStrings.insert(std::make_pair("sqrtf", false));
OptionStrings.insert(std::make_pair("sqrth", false));
OptionStrings.insert(std::make_pair("vec-sqrtd", false));
OptionStrings.insert(std::make_pair("vec-sqrtf", false));
OptionStrings.insert(std::make_pair("vec-sqrth", false));
for (unsigned i = 0; i != NumOptions; ++i) {
StringRef Val = A->getValue(i);
bool IsDisabled = Val.starts_with(DisabledPrefixIn);
// Ignore the disablement token for string matching.
if (IsDisabled)
Val = Val.substr(1);
size_t RefStep;
if (!getRefinementStep(Val, Diags, *A, RefStep))
return "";
StringRef ValBase = Val.slice(0, RefStep);
llvm::StringMap<bool>::iterator OptionIter = OptionStrings.find(ValBase);
if (OptionIter == OptionStrings.end()) {
// Try again specifying float suffix.
OptionIter = OptionStrings.find(ValBase.str() + 'f');
if (OptionIter == OptionStrings.end()) {
// The input name did not match any known option string.
Diags.Report(diag::err_drv_unknown_argument) << Val;
return "";
}
// The option was specified without a half or float or double suffix.
// Make sure that the double or half entry was not already specified.
// The float entry will be checked below.
if (OptionStrings[ValBase.str() + 'd'] ||
OptionStrings[ValBase.str() + 'h']) {
Diags.Report(diag::err_drv_invalid_value)
<< A->getOption().getName() << Val;
return "";
}
}
if (OptionIter->second == true) {
// Duplicate option specified.
Diags.Report(diag::err_drv_invalid_value)
<< A->getOption().getName() << Val;
return "";
}
// Mark the matched option as found. Do not allow duplicate specifiers.
OptionIter->second = true;
// If the precision was not specified, also mark the double and half entry
// as found.
if (ValBase.back() != 'f' && ValBase.back() != 'd' &&
ValBase.back() != 'h') {
OptionStrings[ValBase.str() + 'd'] = true;
OptionStrings[ValBase.str() + 'h'] = true;
}
// Build the output string.
StringRef Prefix = IsDisabled ? DisabledPrefixOut : EnabledPrefixOut;
Out = Args.MakeArgString(Out + Prefix + Val);
if (i != NumOptions - 1)
Out = Args.MakeArgString(Out + ",");
}
return Out;
}
std::string tools::complexRangeKindToStr(LangOptions::ComplexRangeKind Range) {
switch (Range) {
case LangOptions::ComplexRangeKind::CX_Full:

View File

@ -11,7 +11,6 @@
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Driver/CommonArgs.h"
#include "clang/Options/OptionUtils.h"
#include "clang/Options/Options.h"
#include "llvm/Frontend/Debug/Options.h"
#include "llvm/Support/Path.h"

View File

@ -44,7 +44,6 @@
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/MultiplexConsumer.h"
#include "clang/Frontend/PrecompiledPreamble.h"
#include "clang/Frontend/StandaloneDiagnostic.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
@ -211,6 +210,15 @@ getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation,
return llvm::MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(), FilePath);
}
struct ASTUnit::ASTWriterData {
SmallString<128> Buffer;
llvm::BitstreamWriter Stream;
ASTWriter Writer;
ASTWriterData(ModuleCache &ModCache, const CodeGenOptions &CGOpts)
: Stream(Buffer), Writer(Stream, Buffer, ModCache, CGOpts, {}) {}
};
void ASTUnit::clearFileLevelDecls() {
FileDecls.clear();
}
@ -573,24 +581,73 @@ public:
Counter = NewCounter;
}
};
} // anonymous namespace
FilterAndStoreDiagnosticConsumer::FilterAndStoreDiagnosticConsumer(
SmallVectorImpl<StoredDiagnostic> *StoredDiags,
SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags,
bool CaptureNonErrorsFromIncludes)
: StoredDiags(StoredDiags), StandaloneDiags(StandaloneDiags),
CaptureNonErrorsFromIncludes(CaptureNonErrorsFromIncludes) {
assert((StoredDiags || StandaloneDiags) &&
"No output collections were passed to StoredDiagnosticConsumer.");
}
/// Diagnostic consumer that saves each diagnostic it is given.
class FilterAndStoreDiagnosticConsumer : public DiagnosticConsumer {
SmallVectorImpl<StoredDiagnostic> *StoredDiags;
SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags;
bool CaptureNonErrorsFromIncludes = true;
const LangOptions *LangOpts = nullptr;
SourceManager *SourceMgr = nullptr;
void FilterAndStoreDiagnosticConsumer::BeginSourceFile(
const LangOptions &LangOpts, const Preprocessor *PP) {
this->LangOpts = &LangOpts;
if (PP)
SourceMgr = &PP->getSourceManager();
}
public:
FilterAndStoreDiagnosticConsumer(
SmallVectorImpl<StoredDiagnostic> *StoredDiags,
SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags,
bool CaptureNonErrorsFromIncludes)
: StoredDiags(StoredDiags), StandaloneDiags(StandaloneDiags),
CaptureNonErrorsFromIncludes(CaptureNonErrorsFromIncludes) {
assert((StoredDiags || StandaloneDiags) &&
"No output collections were passed to StoredDiagnosticConsumer.");
}
void BeginSourceFile(const LangOptions &LangOpts,
const Preprocessor *PP = nullptr) override {
this->LangOpts = &LangOpts;
if (PP)
SourceMgr = &PP->getSourceManager();
}
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<ASTUnit::StandaloneDiagnostic> *StandaloneDiags)
: Diags(Diags),
Client(StoredDiags, StandaloneDiags,
CaptureDiagnostics !=
CaptureDiagsKind::AllWithoutNonErrorsFromIncludes) {
if (CaptureDiagnostics != CaptureDiagsKind::None ||
Diags.getClient() == nullptr) {
OwningPreviousClient = Diags.takeClient();
PreviousClient = Diags.getClient();
Diags.setClient(&Client, false);
}
}
~CaptureDroppedDiagnostics() {
if (Diags.getClient() == &Client)
Diags.setClient(PreviousClient, !!OwningPreviousClient.release());
}
};
} // namespace
static ASTUnit::StandaloneDiagnostic
makeStandaloneDiagnostic(const LangOptions &LangOpts,
const StoredDiagnostic &InDiag);
static bool isInMainFile(const clang::Diagnostic &D) {
if (!D.hasSourceManager() || !D.getLocation().isValid())
@ -626,32 +683,12 @@ void FilterAndStoreDiagnosticConsumer::HandleDiagnostic(
StoredDiag.emplace(Level, Info);
ResultDiag = &*StoredDiag;
}
StandaloneDiags->emplace_back(*LangOpts, *ResultDiag);
StandaloneDiags->push_back(
makeStandaloneDiagnostic(*LangOpts, *ResultDiag));
}
}
}
CaptureDroppedDiagnostics::CaptureDroppedDiagnostics(
CaptureDiagsKind CaptureDiagnostics, DiagnosticsEngine &Diags,
SmallVectorImpl<StoredDiagnostic> *StoredDiags,
SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags)
: Diags(Diags),
Client(StoredDiags, StandaloneDiags,
CaptureDiagnostics !=
CaptureDiagsKind::AllWithoutNonErrorsFromIncludes) {
if (CaptureDiagnostics != CaptureDiagsKind::None ||
Diags.getClient() == nullptr) {
OwningPreviousClient = Diags.takeClient();
PreviousClient = Diags.getClient();
Diags.setClient(&Client, false);
}
}
CaptureDroppedDiagnostics::~CaptureDroppedDiagnostics() {
if (Diags.getClient() == &Client)
Diags.setClient(PreviousClient, !!OwningPreviousClient.release());
}
IntrusiveRefCntPtr<ASTReader> ASTUnit::getASTReader() const {
return Reader;
}
@ -1073,7 +1110,7 @@ private:
unsigned Hash = 0;
std::vector<Decl *> TopLevelDecls;
std::vector<LocalDeclID> TopLevelDeclIDs;
llvm::SmallVector<StandaloneDiagnostic, 4> PreambleDiags;
llvm::SmallVector<ASTUnit::StandaloneDiagnostic, 4> PreambleDiags;
};
} // namespace
@ -1222,17 +1259,10 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
if (!Act->BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]))
return true;
if (SavedMainFileBuffer) {
StoredDiagnostics.clear();
StoredDiagnostics.reserve(PreambleDiagnostics.size());
llvm::transform(std::move(PreambleDiagnostics),
std::back_inserter(StoredDiagnostics),
[&](auto &&StandaloneDiag) {
return translateStandaloneDiag(
getFileManager(), getSourceManager(),
std::move(StandaloneDiag), PreambleSrcLocCache);
});
} else
if (SavedMainFileBuffer)
TranslateStoredDiagnostics(getFileManager(), getSourceManager(),
PreambleDiagnostics, StoredDiagnostics);
else
PreambleSrcLocCache.clear();
if (llvm::Error Err = Act->Execute()) {
@ -1251,6 +1281,51 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
return false;
}
static std::pair<unsigned, unsigned>
makeStandaloneRange(CharSourceRange Range, const SourceManager &SM,
const LangOptions &LangOpts) {
CharSourceRange FileRange = Lexer::makeFileCharRange(Range, SM, LangOpts);
unsigned Offset = SM.getFileOffset(FileRange.getBegin());
unsigned EndOffset = SM.getFileOffset(FileRange.getEnd());
return std::make_pair(Offset, EndOffset);
}
static ASTUnit::StandaloneFixIt makeStandaloneFixIt(const SourceManager &SM,
const LangOptions &LangOpts,
const FixItHint &InFix) {
ASTUnit::StandaloneFixIt OutFix;
OutFix.RemoveRange = makeStandaloneRange(InFix.RemoveRange, SM, LangOpts);
OutFix.InsertFromRange =
makeStandaloneRange(InFix.InsertFromRange, SM, LangOpts);
OutFix.CodeToInsert = InFix.CodeToInsert;
OutFix.BeforePreviousInsertions = InFix.BeforePreviousInsertions;
return OutFix;
}
static ASTUnit::StandaloneDiagnostic
makeStandaloneDiagnostic(const LangOptions &LangOpts,
const StoredDiagnostic &InDiag) {
ASTUnit::StandaloneDiagnostic OutDiag;
OutDiag.ID = InDiag.getID();
OutDiag.Level = InDiag.getLevel();
OutDiag.Message = std::string(InDiag.getMessage());
OutDiag.LocOffset = 0;
if (InDiag.getLocation().isInvalid())
return OutDiag;
const SourceManager &SM = InDiag.getLocation().getManager();
SourceLocation FileLoc = SM.getFileLoc(InDiag.getLocation());
OutDiag.Filename = std::string(SM.getFilename(FileLoc));
if (OutDiag.Filename.empty())
return OutDiag;
OutDiag.LocOffset = SM.getFileOffset(FileLoc);
for (const auto &Range : InDiag.getRanges())
OutDiag.Ranges.push_back(makeStandaloneRange(Range, SM, LangOpts));
for (const auto &FixIt : InDiag.getFixIts())
OutDiag.FixIts.push_back(makeStandaloneFixIt(SM, LangOpts, FixIt));
return OutDiag;
}
/// Attempt to build or re-use a precompiled preamble when (re-)parsing
/// the source file.
///
@ -1705,6 +1780,114 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
return AST;
}
std::unique_ptr<ASTUnit> ASTUnit::LoadFromCommandLine(
const char **ArgBegin, const char **ArgEnd,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
std::shared_ptr<DiagnosticOptions> DiagOpts,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
bool StorePreamblesInMemory, StringRef PreambleStoragePath,
bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,
ArrayRef<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) {
assert(Diags.get() && "no DiagnosticsEngine was provided");
// If no VFS was provided, create one that tracks the physical file system.
// If '-working-directory' was passed as an argument, 'createInvocation' will
// set this as the current working directory of the VFS.
if (!VFS)
VFS = llvm::vfs::createPhysicalFileSystem();
SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
std::shared_ptr<CompilerInvocation> CI;
{
CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags,
&StoredDiagnostics, nullptr);
CreateInvocationOptions CIOpts;
CIOpts.VFS = VFS;
CIOpts.Diags = Diags;
CIOpts.ProbePrecompiled = true; // FIXME: historical default. Needed?
CI = createInvocation(llvm::ArrayRef(ArgBegin, ArgEnd), std::move(CIOpts));
if (!CI)
return nullptr;
}
// Override any files that need remapping
for (const auto &RemappedFile : RemappedFiles) {
CI->getPreprocessorOpts().addRemappedFile(RemappedFile.first,
RemappedFile.second);
}
PreprocessorOptions &PPOpts = CI->getPreprocessorOpts();
PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName;
PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors;
PPOpts.SingleFileParseMode = SingleFileParse;
PPOpts.RetainExcludedConditionalBlocks = RetainExcludedConditionalBlocks;
// Override the resources path.
CI->getHeaderSearchOpts().ResourceDir = std::string(ResourceFilesPath);
CI->getFrontendOpts().SkipFunctionBodies =
SkipFunctionBodies == SkipFunctionBodiesScope::PreambleAndMainFile;
if (ModuleFormat)
CI->getHeaderSearchOpts().ModuleFormat = std::string(*ModuleFormat);
// Create the AST unit.
std::unique_ptr<ASTUnit> AST;
AST.reset(new ASTUnit(false));
AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();
AST->StoredDiagnostics.swap(StoredDiagnostics);
ConfigureDiags(Diags, *AST, CaptureDiagnostics);
AST->DiagOpts = DiagOpts;
AST->Diagnostics = Diags;
AST->FileSystemOpts = CI->getFileSystemOpts();
AST->CodeGenOpts = std::make_unique<CodeGenOptions>(CI->getCodeGenOpts());
VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS);
AST->FileMgr =
llvm::makeIntrusiveRefCnt<FileManager>(AST->FileSystemOpts, VFS);
AST->StorePreamblesInMemory = StorePreamblesInMemory;
AST->PreambleStoragePath = PreambleStoragePath;
AST->ModCache = createCrossProcessModuleCache();
AST->OnlyLocalDecls = OnlyLocalDecls;
AST->CaptureDiagnostics = CaptureDiagnostics;
AST->TUKind = TUKind;
AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
AST->IncludeBriefCommentsInCodeCompletion =
IncludeBriefCommentsInCodeCompletion;
AST->UserFilesAreVolatile = UserFilesAreVolatile;
AST->Invocation = CI;
AST->SkipFunctionBodies = SkipFunctionBodies;
if (ForSerialization)
AST->WriterData.reset(new ASTWriterData(*AST->ModCache, *AST->CodeGenOpts));
// Zero out now to ease cleanup during crash recovery.
CI = nullptr;
Diags = nullptr;
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> ASTUnitCleanup(AST.get());
if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps),
PrecompilePreambleAfterNParses, VFS)) {
// Some error occurred, if caller wants to examine diagnostics, pass it the
// ASTUnit.
if (ErrAST) {
AST->StoredDiagnostics.swap(AST->FailedParseDiagnostics);
ErrAST->swap(AST);
}
return nullptr;
}
return AST;
}
bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
ArrayRef<RemappedFile> RemappedFiles,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
@ -2223,6 +2406,64 @@ bool ASTUnit::serialize(raw_ostream &OS) {
return serializeUnit(Writer, Buffer, getSema(), OS);
}
void ASTUnit::TranslateStoredDiagnostics(
FileManager &FileMgr, SourceManager &SrcMgr,
const SmallVectorImpl<StandaloneDiagnostic> &Diags,
SmallVectorImpl<StoredDiagnostic> &Out) {
// Map the standalone diagnostic into the new source manager. We also need to
// remap all the locations to the new view. This includes the diag location,
// any associated source ranges, and the source ranges of associated fix-its.
// FIXME: There should be a cleaner way to do this.
SmallVector<StoredDiagnostic, 4> Result;
Result.reserve(Diags.size());
for (const auto &SD : Diags) {
// Rebuild the StoredDiagnostic.
if (SD.Filename.empty())
continue;
auto FE = FileMgr.getOptionalFileRef(SD.Filename);
if (!FE)
continue;
SourceLocation FileLoc;
auto ItFileID = PreambleSrcLocCache.find(SD.Filename);
if (ItFileID == PreambleSrcLocCache.end()) {
FileID FID = SrcMgr.translateFile(*FE);
FileLoc = SrcMgr.getLocForStartOfFile(FID);
PreambleSrcLocCache[SD.Filename] = FileLoc;
} else {
FileLoc = ItFileID->getValue();
}
if (FileLoc.isInvalid())
continue;
SourceLocation L = FileLoc.getLocWithOffset(SD.LocOffset);
FullSourceLoc Loc(L, SrcMgr);
SmallVector<CharSourceRange, 4> Ranges;
Ranges.reserve(SD.Ranges.size());
for (const auto &Range : SD.Ranges) {
SourceLocation BL = FileLoc.getLocWithOffset(Range.first);
SourceLocation EL = FileLoc.getLocWithOffset(Range.second);
Ranges.push_back(CharSourceRange::getCharRange(BL, EL));
}
SmallVector<FixItHint, 2> FixIts;
FixIts.reserve(SD.FixIts.size());
for (const auto &FixIt : SD.FixIts) {
FixIts.push_back(FixItHint());
FixItHint &FH = FixIts.back();
FH.CodeToInsert = FixIt.CodeToInsert;
SourceLocation BL = FileLoc.getLocWithOffset(FixIt.RemoveRange.first);
SourceLocation EL = FileLoc.getLocWithOffset(FixIt.RemoveRange.second);
FH.RemoveRange = CharSourceRange::getCharRange(BL, EL);
}
Result.push_back(
StoredDiagnostic(SD.Level, SD.ID, SD.Message, Loc, Ranges, FixIts));
}
Result.swap(Out);
}
void ASTUnit::addFileLevelDecl(Decl *D) {
assert(D);

View File

@ -17,6 +17,7 @@ add_clang_library(clangFrontend
ChainedIncludesSource.cpp
CompilerInstance.cpp
CompilerInvocation.cpp
CreateInvocationFromCommandLine.cpp
DependencyFile.cpp
DependencyGraph.cpp
DiagnosticRenderer.cpp
@ -35,7 +36,6 @@ add_clang_library(clangFrontend
SARIFDiagnosticPrinter.cpp
SerializedDiagnosticPrinter.cpp
SerializedDiagnosticReader.cpp
StandaloneDiagnostic.cpp
TestModuleFileExtension.cpp
TextDiagnostic.cpp
TextDiagnosticBuffer.cpp
@ -51,6 +51,7 @@ add_clang_library(clangFrontend
clangAPINotes
clangAST
clangBasic
clangDriver
clangOptions
clangEdit
clangLex

View File

@ -27,6 +27,7 @@
#include "clang/Basic/Version.h"
#include "clang/Basic/XRayInstr.h"
#include "clang/Config/config.h"
#include "clang/Driver/Driver.h"
#include "clang/Frontend/CommandLineSourceLoc.h"
#include "clang/Frontend/DependencyOutputOptions.h"
#include "clang/Frontend/FrontendOptions.h"
@ -3272,6 +3273,13 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
return Diags.getNumErrors() == NumErrorsBefore;
}
std::string CompilerInvocation::GetResourcesPath(const char *Argv0,
void *MainAddr) {
std::string ClangExecutable =
llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
return driver::Driver::GetResourcesPath(ClangExecutable);
}
static void GenerateHeaderSearchArgs(const HeaderSearchOptions &Opts,
ArgumentConsumer Consumer) {
const HeaderSearchOptions *HeaderSearchOpts = &Opts;

View File

@ -1,4 +1,4 @@
//===--- CreateInvocationFromArgs.h - CompilerInvocation from Args --------===//
//===--- CreateInvocationFromCommandLine.cpp - 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.
@ -10,9 +10,9 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Basic/DiagnosticFrontend.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Tool.h"
@ -24,13 +24,12 @@
#include "llvm/Option/ArgList.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/TargetParser/Host.h"
using namespace clang;
using namespace llvm::opt;
namespace clang {
std::unique_ptr<CompilerInvocation>
createInvocation(ArrayRef<const char *> ArgList, CreateInvocationOptions Opts) {
clang::createInvocation(ArrayRef<const char *> ArgList,
CreateInvocationOptions Opts) {
assert(!ArgList.empty());
std::optional<DiagnosticOptions> LocalDiagOpts;
IntrusiveRefCntPtr<DiagnosticsEngine> Diags;
@ -115,5 +114,3 @@ createInvocation(ArrayRef<const char *> ArgList, CreateInvocationOptions Opts) {
return nullptr;
return CI;
}
} // namespace clang

View File

@ -1,117 +0,0 @@
//===--- StandaloneDiagnostic.h - Serializable Diagnostic ------------- ---===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "clang/Frontend/StandaloneDiagnostic.h"
#include "clang/Lex/Lexer.h"
namespace clang {
StandaloneDiagnostic::SourceOffsetRange::SourceOffsetRange(
CharSourceRange Range, const SourceManager &SrcMgr,
const LangOptions &LangOpts) {
const auto FileRange = Lexer::makeFileCharRange(Range, SrcMgr, LangOpts);
Begin = SrcMgr.getFileOffset(FileRange.getBegin());
End = SrcMgr.getFileOffset(FileRange.getEnd());
}
StandaloneDiagnostic::StandaloneFixIt::StandaloneFixIt(
const SourceManager &SrcMgr, const LangOptions &LangOpts,
const FixItHint &FixIt)
: RemoveRange(FixIt.RemoveRange, SrcMgr, LangOpts),
InsertFromRange(FixIt.InsertFromRange, SrcMgr, LangOpts),
CodeToInsert(FixIt.CodeToInsert),
BeforePreviousInsertions(FixIt.BeforePreviousInsertions) {}
StandaloneDiagnostic::StandaloneDiagnostic(const LangOptions &LangOpts,
const StoredDiagnostic &InDiag)
: Level(InDiag.getLevel()), ID(InDiag.getID()),
Message(InDiag.getMessage()) {
const FullSourceLoc &FullLoc = InDiag.getLocation();
// This is not an invalid diagnostic; invalid SourceLocations are used to
// represent diagnostics without a specific SourceLocation.
if (FullLoc.isInvalid())
return;
const auto &SrcMgr = FullLoc.getManager();
FileKind = SrcMgr.getFileCharacteristic(static_cast<SourceLocation>(FullLoc));
const auto FileLoc = SrcMgr.getFileLoc(static_cast<SourceLocation>(FullLoc));
FileOffset = SrcMgr.getFileOffset(FileLoc);
Filename = SrcMgr.getFilename(FileLoc);
assert(!Filename.empty() && "diagnostic with location has no source file?");
Ranges.reserve(InDiag.getRanges().size());
for (const auto &Range : InDiag.getRanges())
Ranges.emplace_back(Range, SrcMgr, LangOpts);
FixIts.reserve(InDiag.getFixIts().size());
for (const auto &FixIt : InDiag.getFixIts())
FixIts.emplace_back(SrcMgr, LangOpts, FixIt);
}
StoredDiagnostic
translateStandaloneDiag(FileManager &FileMgr, SourceManager &SrcMgr,
const StandaloneDiagnostic &StandaloneDiag,
llvm::StringMap<SourceLocation> &SrcLocCache) {
const auto FileRef = FileMgr.getOptionalFileRef(StandaloneDiag.Filename);
if (!FileRef)
return StoredDiagnostic(StandaloneDiag.Level, StandaloneDiag.ID,
StandaloneDiag.Message);
// Try to get FileLoc from cache first
SourceLocation FileLoc;
auto It = SrcLocCache.find(StandaloneDiag.Filename);
if (It != SrcLocCache.end()) {
FileLoc = It->getValue();
}
// Cache miss - compute and cache the location
if (FileLoc.isInvalid()) {
const auto FileID =
SrcMgr.getOrCreateFileID(*FileRef, StandaloneDiag.FileKind);
FileLoc = SrcMgr.getLocForStartOfFile(FileID);
if (FileLoc.isInvalid())
return StoredDiagnostic(StandaloneDiag.Level, StandaloneDiag.ID,
StandaloneDiag.Message);
SrcLocCache[StandaloneDiag.Filename] = FileLoc;
}
const auto DiagLoc = FileLoc.getLocWithOffset(StandaloneDiag.FileOffset);
const FullSourceLoc Loc(DiagLoc, SrcMgr);
auto ConvertOffsetRange =
[&](const StandaloneDiagnostic::SourceOffsetRange &Range) {
return CharSourceRange(
SourceRange(FileLoc.getLocWithOffset(Range.Begin),
FileLoc.getLocWithOffset(Range.End)),
/*IsTokenRange*/ false);
};
SmallVector<CharSourceRange, 4> TranslatedRanges;
TranslatedRanges.reserve(StandaloneDiag.Ranges.size());
transform(StandaloneDiag.Ranges, std::back_inserter(TranslatedRanges),
ConvertOffsetRange);
SmallVector<FixItHint, 2> TranslatedFixIts;
TranslatedFixIts.reserve(StandaloneDiag.FixIts.size());
for (const auto &FixIt : StandaloneDiag.FixIts) {
FixItHint TranslatedFixIt;
TranslatedFixIt.CodeToInsert = FixIt.CodeToInsert;
TranslatedFixIt.RemoveRange = ConvertOffsetRange(FixIt.RemoveRange);
TranslatedFixIt.InsertFromRange = ConvertOffsetRange(FixIt.InsertFromRange);
TranslatedFixIt.BeforePreviousInsertions = FixIt.BeforePreviousInsertions;
TranslatedFixIts.push_back(std::move(TranslatedFixIt));
}
return StoredDiagnostic(StandaloneDiag.Level, StandaloneDiag.ID,
StandaloneDiag.Message, Loc, TranslatedRanges,
TranslatedFixIts);
}
} // namespace clang

View File

@ -46,7 +46,6 @@ add_clang_library(clangInterpreter
clangFrontend
clangFrontendTool
clangLex
clangOptions
clangParse
clangSema
clangSerialization

View File

@ -42,7 +42,6 @@
#include "clang/Interpreter/Interpreter.h"
#include "clang/Interpreter/Value.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Options/OptionUtils.h"
#include "clang/Options/Options.h"
#include "clang/Sema/Lookup.h"
#include "clang/Serialization/ObjectFilePCHContainerReader.h"
@ -106,7 +105,7 @@ CreateCI(const llvm::opt::ArgStringList &Argv) {
if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&
Clang->getHeaderSearchOpts().ResourceDir.empty())
Clang->getHeaderSearchOpts().ResourceDir =
GetResourcesPath(Argv[0], nullptr);
CompilerInvocation::GetResourcesPath(Argv[0], nullptr);
Clang->createVirtualFileSystem();

View File

@ -9,12 +9,7 @@
#include "clang/Options/OptionUtils.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticDriver.h"
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
#include "clang/Options/Options.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
using namespace clang;
using namespace llvm::opt;
@ -36,211 +31,17 @@ IntTy getLastArgIntValueImpl(const ArgList &Args, OptSpecifier Id,
}
} // namespace
int clang::getLastArgIntValue(const ArgList &Args, OptSpecifier Id, int Default,
DiagnosticsEngine *Diags, unsigned Base) {
namespace clang {
int getLastArgIntValue(const ArgList &Args, OptSpecifier Id, int Default,
DiagnosticsEngine *Diags, unsigned Base) {
return getLastArgIntValueImpl<int>(Args, Id, Default, Diags, Base);
}
uint64_t clang::getLastArgUInt64Value(const ArgList &Args, OptSpecifier Id,
uint64_t Default,
DiagnosticsEngine *Diags, unsigned Base) {
uint64_t getLastArgUInt64Value(const ArgList &Args, OptSpecifier Id,
uint64_t Default, DiagnosticsEngine *Diags,
unsigned Base) {
return getLastArgIntValueImpl<uint64_t>(Args, Id, Default, Diags, Base);
}
StringRef clang::parseMPreferVectorWidthOption(clang::DiagnosticsEngine &Diags,
const llvm::opt::ArgList &Args) {
const Arg *A = Args.getLastArg(options::OPT_mprefer_vector_width_EQ);
if (!A)
return "";
StringRef Value = A->getValue();
unsigned Width LLVM_ATTRIBUTE_UNINITIALIZED;
// Only "none" and Integer values are accepted by
// -mprefer-vector-width=<value>.
if (Value != "none" && Value.getAsInteger(10, Width)) {
Diags.Report(clang::diag::err_drv_invalid_value)
<< A->getOption().getName() << Value;
return "";
}
return Value;
}
// This is a helper function for validating the optional refinement step
// parameter in reciprocal argument strings. Return false if there is an error
// parsing the refinement step. Otherwise, return true and set the Position
// of the refinement step in the input string.
static bool getRefinementStep(StringRef In, clang::DiagnosticsEngine &Diags,
const Arg &A, size_t &Position) {
const char RefinementStepToken = ':';
Position = In.find(RefinementStepToken);
if (Position != StringRef::npos) {
StringRef Option = A.getOption().getName();
StringRef RefStep = In.substr(Position + 1);
// Allow exactly one numeric character for the additional refinement
// step parameter. This is reasonable for all currently-supported
// operations and architectures because we would expect that a larger value
// of refinement steps would cause the estimate "optimization" to
// under-perform the native operation. Also, if the estimate does not
// converge quickly, it probably will not ever converge, so further
// refinement steps will not produce a better answer.
if (RefStep.size() != 1) {
Diags.Report(diag::err_drv_invalid_value) << Option << RefStep;
return false;
}
char RefStepChar = RefStep[0];
if (RefStepChar < '0' || RefStepChar > '9') {
Diags.Report(diag::err_drv_invalid_value) << Option << RefStep;
return false;
}
}
return true;
}
StringRef clang::parseMRecipOption(clang::DiagnosticsEngine &Diags,
const ArgList &Args) {
StringRef DisabledPrefixIn = "!";
StringRef DisabledPrefixOut = "!";
StringRef EnabledPrefixOut = "";
StringRef Out = "";
const Arg *A = Args.getLastArg(options::OPT_mrecip, options::OPT_mrecip_EQ);
if (!A)
return "";
const unsigned NumOptions = A->getNumValues();
if (NumOptions == 0) {
// No option is the same as "all".
return "all";
}
// Pass through "all", "none", or "default" with an optional refinement step.
if (NumOptions == 1) {
StringRef Val = A->getValue(0);
size_t RefStepLoc;
if (!getRefinementStep(Val, Diags, *A, RefStepLoc))
return "";
StringRef ValBase = Val.slice(0, RefStepLoc);
if (ValBase == "all" || ValBase == "none" || ValBase == "default") {
return Val;
}
}
// Each reciprocal type may be enabled or disabled individually.
// Check each input value for validity, concatenate them all back together,
// and pass through.
llvm::StringMap<bool> OptionStrings;
OptionStrings.insert(std::make_pair("divd", false));
OptionStrings.insert(std::make_pair("divf", false));
OptionStrings.insert(std::make_pair("divh", false));
OptionStrings.insert(std::make_pair("vec-divd", false));
OptionStrings.insert(std::make_pair("vec-divf", false));
OptionStrings.insert(std::make_pair("vec-divh", false));
OptionStrings.insert(std::make_pair("sqrtd", false));
OptionStrings.insert(std::make_pair("sqrtf", false));
OptionStrings.insert(std::make_pair("sqrth", false));
OptionStrings.insert(std::make_pair("vec-sqrtd", false));
OptionStrings.insert(std::make_pair("vec-sqrtf", false));
OptionStrings.insert(std::make_pair("vec-sqrth", false));
for (unsigned i = 0; i != NumOptions; ++i) {
StringRef Val = A->getValue(i);
bool IsDisabled = Val.starts_with(DisabledPrefixIn);
// Ignore the disablement token for string matching.
if (IsDisabled)
Val = Val.substr(1);
size_t RefStep;
if (!getRefinementStep(Val, Diags, *A, RefStep))
return "";
StringRef ValBase = Val.slice(0, RefStep);
llvm::StringMap<bool>::iterator OptionIter = OptionStrings.find(ValBase);
if (OptionIter == OptionStrings.end()) {
// Try again specifying float suffix.
OptionIter = OptionStrings.find(ValBase.str() + 'f');
if (OptionIter == OptionStrings.end()) {
// The input name did not match any known option string.
Diags.Report(diag::err_drv_unknown_argument) << Val;
return "";
}
// The option was specified without a half or float or double suffix.
// Make sure that the double or half entry was not already specified.
// The float entry will be checked below.
if (OptionStrings[ValBase.str() + 'd'] ||
OptionStrings[ValBase.str() + 'h']) {
Diags.Report(diag::err_drv_invalid_value)
<< A->getOption().getName() << Val;
return "";
}
}
if (OptionIter->second == true) {
// Duplicate option specified.
Diags.Report(diag::err_drv_invalid_value)
<< A->getOption().getName() << Val;
return "";
}
// Mark the matched option as found. Do not allow duplicate specifiers.
OptionIter->second = true;
// If the precision was not specified, also mark the double and half entry
// as found.
if (ValBase.back() != 'f' && ValBase.back() != 'd' &&
ValBase.back() != 'h') {
OptionStrings[ValBase.str() + 'd'] = true;
OptionStrings[ValBase.str() + 'h'] = true;
}
// Build the output string.
StringRef Prefix = IsDisabled ? DisabledPrefixOut : EnabledPrefixOut;
Out = Args.MakeArgString(Out + Prefix + Val);
if (i != NumOptions - 1)
Out = Args.MakeArgString(Out + ",");
}
return Out;
}
std::string clang::GetResourcesPath(StringRef BinaryPath) {
// Since the resource directory is embedded in the module hash, it's important
// that all places that need it call this function, so that they get the
// exact same string ("a/../b/" and "b/" get different hashes, for example).
// Dir is bin/ or lib/, depending on where BinaryPath is.
StringRef Dir = llvm::sys::path::parent_path(BinaryPath);
SmallString<128> P(Dir);
StringRef ConfiguredResourceDir(CLANG_RESOURCE_DIR);
if (!ConfiguredResourceDir.empty()) {
// FIXME: We should fix the behavior of llvm::sys::path::append so we don't
// need to check for absolute paths here.
if (llvm::sys::path::is_absolute(ConfiguredResourceDir))
P = ConfiguredResourceDir;
else
llvm::sys::path::append(P, ConfiguredResourceDir);
} else {
// On Windows, libclang.dll is in bin/.
// On non-Windows, libclang.so/.dylib is in lib/.
// With a static-library build of libclang, LibClangPath will contain the
// path of the embedding binary, which for LLVM binaries will be in bin/.
// ../lib gets us to lib/ in both cases.
P = llvm::sys::path::parent_path(Dir);
// This search path is also created in the COFF driver of lld, so any
// changes here also needs to happen in lld/COFF/Driver.cpp
llvm::sys::path::append(P, CLANG_INSTALL_LIBDIR_BASENAME, "clang",
CLANG_VERSION_MAJOR_STRING);
}
return std::string(P);
}
std::string clang::GetResourcesPath(const char *Argv0, void *MainAddr) {
const std::string ClangExecutable =
llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
return GetResourcesPath(ClangExecutable);
}
} // namespace clang

View File

@ -31,7 +31,6 @@
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Options/OptionUtils.h"
#include "clang/Options/Options.h"
#include "clang/Tooling/ArgumentsAdjusters.h"
#include "clang/Tooling/CompilationDatabase.h"
@ -511,7 +510,8 @@ static void injectResourceDir(CommandLineArguments &Args, const char *Argv0,
// If there's no override in place add our resource dir.
Args = getInsertArgumentAdjuster(
("-resource-dir=" + GetResourcesPath(Argv0, MainAddr)).c_str())(Args, "");
("-resource-dir=" + CompilerInvocation::GetResourcesPath(Argv0, MainAddr))
.c_str())(Args, "");
}
int ClangTool::run(ToolAction *Action) {

View File

@ -27,7 +27,6 @@ else()
libclang
clangAST
clangBasic
clangDriver
clangFrontend
clangIndex
clangSerialization

View File

@ -8,7 +8,6 @@
#include "clang/AST/Mangle.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"

View File

@ -15,6 +15,5 @@ add_clang_tool(diagtool
clang_target_link_libraries(diagtool
PRIVATE
clangBasic
clangDriver
clangFrontend
)

View File

@ -9,7 +9,6 @@
#include "DiagTool.h"
#include "DiagnosticNames.h"
#include "clang/Basic/LLVM.h"
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"

View File

@ -17,7 +17,6 @@
#include "clang/Basic/TargetOptions.h"
#include "clang/CodeGen/ObjectFilePCHContainerWriter.h"
#include "clang/Config/config.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
@ -270,7 +269,7 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&
Clang->getHeaderSearchOpts().ResourceDir.empty())
Clang->getHeaderSearchOpts().ResourceDir =
GetResourcesPath(Argv0, MainAddr);
CompilerInvocation::GetResourcesPath(Argv0, MainAddr);
/// Create the actual file system.
Clang->createVirtualFileSystem(llvm::vfs::getRealFileSystem(), DiagsBuffer);

View File

@ -38,7 +38,6 @@
#include "clang/Basic/Stack.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
#include "clang/Driver/CreateASTUnitFromArgs.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Index/CommentToXML.h"
@ -4362,7 +4361,7 @@ clang_parseTranslationUnit_Impl(CXIndex CIdx, const char *source_filename,
LibclangInvocationReporter InvocationReporter(
*CXXIdx, LibclangInvocationReporter::OperationKind::ParseOperation,
options, llvm::ArrayRef(*Args), /*InvocationArgs=*/{}, unsaved_files);
std::unique_ptr<ASTUnit> Unit = CreateASTUnitFromCommandLine(
std::unique_ptr<ASTUnit> Unit = ASTUnit::LoadFromCommandLine(
Args->data(), Args->data() + Args->size(),
CXXIdx->getPCHContainerOperations(), DiagOpts, Diags,
CXXIdx->getClangResourcesPath(), CXXIdx->getStorePreamblesInMemory(),

View File

@ -16,7 +16,6 @@
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
#include "clang/Driver/Driver.h"
#include "clang/Options/OptionUtils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/FileSystem.h"
@ -138,7 +137,7 @@ const std::string &CIndexer::getClangResourcesPath() {
#endif
// Cache our result.
ResourcesPath = GetResourcesPath(LibClangPath);
ResourcesPath = driver::Driver::GetResourcesPath(LibClangPath);
return ResourcesPath;
}

View File

@ -65,7 +65,6 @@ set(LIBS
clangFrontend
clangIndex
clangLex
clangOptions
clangRewrite
clangSema
clangSerialization

View File

@ -15,7 +15,6 @@
#include "CXString.h"
#include "CXTranslationUnit.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"

View File

@ -15,7 +15,6 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/ToolChain.h"
#include "clang/Frontend/CompilerInstance.h"

View File

@ -17,7 +17,6 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Driver/Driver.h"
#include "clang/Frontend/CompilerInstance.h"
#include "llvm/ADT/ArrayRef.h"

View File

@ -9,8 +9,6 @@
#include <fstream>
#include "clang/Basic/FileManager.h"
#include "clang/Driver/CreateASTUnitFromArgs.h"
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
@ -175,7 +173,7 @@ TEST_F(ASTUnitTest, LoadFromCommandLineEarlyError) {
auto PCHContainerOps = std::make_shared<PCHContainerOperations>();
std::unique_ptr<clang::ASTUnit> ErrUnit;
std::unique_ptr<ASTUnit> AST = CreateASTUnitFromCommandLine(
std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromCommandLine(
&Args[0], &Args[4], PCHContainerOps, DiagOpts, Diags, "", false, "",
false, CaptureDiagsKind::All, {}, true, 0, TU_Complete, false, false,
false, SkipFunctionBodiesScope::None, false, true, false, false,
@ -203,7 +201,7 @@ TEST_F(ASTUnitTest, LoadFromCommandLineWorkingDirectory) {
auto PCHContainerOps = std::make_shared<PCHContainerOperations>();
std::unique_ptr<clang::ASTUnit> ErrUnit;
std::unique_ptr<ASTUnit> AST = CreateASTUnitFromCommandLine(
std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromCommandLine(
&Args[0], &Args[4], PCHContainerOps, DiagOpts, Diags, "", false, "",
false, CaptureDiagsKind::All, {}, true, 0, TU_Complete, false, false,
false, SkipFunctionBodiesScope::None, false, true, false, false,

View File

@ -8,7 +8,6 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Basic/FileManager.h"
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"

View File

@ -9,7 +9,6 @@
#include "clang/Frontend/Utils.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Lex/PreprocessorOptions.h"

View File

@ -13,7 +13,6 @@ add_distinct_clang_unittest(SemaTests
clangAST
clangASTMatchers
clangBasic
clangDriver
clangFrontend
clangParse
clangSema

View File

@ -10,7 +10,6 @@
#include "clang/AST/DeclarationName.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendActions.h"

View File

@ -9,7 +9,6 @@
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Basic/FileManager.h"
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"

View File

@ -6,7 +6,6 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendActions.h"

View File

@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/FileManager.h"
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"

View File

@ -9,7 +9,6 @@
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Basic/FileManager.h"
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"

View File

@ -6,7 +6,6 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"

View File

@ -9,7 +9,6 @@
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Basic/FileManager.h"
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"

View File

@ -20,7 +20,6 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TokenKinds.def"
#include "clang/Basic/TokenKinds.h"
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/Utils.h"

View File

@ -13,7 +13,6 @@
#include "TreeTestBase.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/LLVM.h"
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendAction.h"

View File

@ -75,6 +75,7 @@ add_flang_library(flangFrontend
CLANG_LIBS
clangBasic
clangDriver
clangOptions
)

View File

@ -325,9 +325,10 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
for (auto *a : args.filtered(clang::options::OPT_fpass_plugin_EQ))
opts.LLVMPassPlugins.push_back(a->getValue());
opts.Reciprocals = clang::parseMRecipOption(diags, args);
opts.Reciprocals = clang::driver::tools::parseMRecipOption(diags, args);
opts.PreferVectorWidth = clang::parseMPreferVectorWidthOption(diags, args);
opts.PreferVectorWidth =
clang::driver::tools::parseMPreferVectorWidthOption(diags, args);
// -fembed-offload-object option
for (auto *a : args.filtered(clang::options::OPT_fembed_offload_object_EQ))

View File

@ -60,7 +60,6 @@
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private-enumerations.h"
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"

View File

@ -51,10 +51,10 @@ add_lldb_library(lldbPluginExpressionParserClang
CLANG_LIBS
clangAST
clangCodeGen
clangDriver
clangEdit
clangFrontend
clangLex
clangOptions
clangParse
clangRewrite
clangRewriteFrontend

View File

@ -10,7 +10,7 @@
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
#include "clang/Options/OptionUtils.h"
#include "clang/Driver/Driver.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
@ -53,7 +53,7 @@ static bool DefaultComputeClangResourceDirectory(FileSpec &lldb_shlib_spec,
std::string raw_path = lldb_shlib_spec.GetPath();
llvm::StringRef parent_dir = llvm::sys::path::parent_path(raw_path);
static const std::string clang_resource_path =
clang::GetResourcesPath("bin/lldb");
clang::driver::Driver::GetResourcesPath("bin/lldb");
static const llvm::StringRef kResourceDirSuffixes[] = {
// LLVM.org's build of LLDB uses the clang resource directory placed

View File

@ -10,7 +10,6 @@
#include "clang/Basic/DiagnosticFrontend.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"

View File

@ -8,7 +8,7 @@
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
#include "clang/Options/OptionUtils.h"
#include "clang/Driver/Driver.h"
#include "Plugins/ExpressionParser/Clang/ClangHost.h"
#include "TestingSupport/SubsystemRAII.h"
@ -43,7 +43,7 @@ TEST_F(ClangHostTest, ComputeClangResourceDirectory) {
std::string path_to_liblldb = "C:\\foo\\bar\\lib\\";
#endif
std::string path_to_clang_dir =
clang::GetResourcesPath(path_to_liblldb + "liblldb");
clang::driver::Driver::GetResourcesPath(path_to_liblldb + "liblldb");
llvm::SmallString<256> path_to_clang_lib_dir_real;
llvm::sys::fs::real_path(path_to_clang_dir, path_to_clang_lib_dir_real);