summaryrefslogtreecommitdiff
path: root/external/bsd/llvm/dist/clang/lib/Tooling/CompilationDatabase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'external/bsd/llvm/dist/clang/lib/Tooling/CompilationDatabase.cpp')
-rw-r--r--external/bsd/llvm/dist/clang/lib/Tooling/CompilationDatabase.cpp402
1 files changed, 0 insertions, 402 deletions
diff --git a/external/bsd/llvm/dist/clang/lib/Tooling/CompilationDatabase.cpp b/external/bsd/llvm/dist/clang/lib/Tooling/CompilationDatabase.cpp
deleted file mode 100644
index 31a769fa21e..00000000000
--- a/external/bsd/llvm/dist/clang/lib/Tooling/CompilationDatabase.cpp
+++ /dev/null
@@ -1,402 +0,0 @@
-//===- CompilationDatabase.cpp --------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains implementations of the CompilationDatabase base class
-// and the FixedCompilationDatabase.
-//
-// FIXME: Various functions that take a string &ErrorMessage should be upgraded
-// to Expected.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Tooling/CompilationDatabase.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/DiagnosticIDs.h"
-#include "clang/Basic/DiagnosticOptions.h"
-#include "clang/Basic/LLVM.h"
-#include "clang/Driver/Action.h"
-#include "clang/Driver/Compilation.h"
-#include "clang/Driver/Driver.h"
-#include "clang/Driver/DriverDiagnostic.h"
-#include "clang/Driver/Job.h"
-#include "clang/Frontend/TextDiagnosticPrinter.h"
-#include "clang/Tooling/CompilationDatabasePluginRegistry.h"
-#include "clang/Tooling/Tooling.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Option/Arg.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/LineIterator.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <cstring>
-#include <iterator>
-#include <memory>
-#include <sstream>
-#include <string>
-#include <system_error>
-#include <utility>
-#include <vector>
-
-using namespace clang;
-using namespace tooling;
-
-LLVM_INSTANTIATE_REGISTRY(CompilationDatabasePluginRegistry)
-
-CompilationDatabase::~CompilationDatabase() = default;
-
-std::unique_ptr<CompilationDatabase>
-CompilationDatabase::loadFromDirectory(StringRef BuildDirectory,
- std::string &ErrorMessage) {
- llvm::raw_string_ostream ErrorStream(ErrorMessage);
- for (CompilationDatabasePluginRegistry::iterator
- It = CompilationDatabasePluginRegistry::begin(),
- Ie = CompilationDatabasePluginRegistry::end();
- It != Ie; ++It) {
- std::string DatabaseErrorMessage;
- std::unique_ptr<CompilationDatabasePlugin> Plugin(It->instantiate());
- if (std::unique_ptr<CompilationDatabase> DB =
- Plugin->loadFromDirectory(BuildDirectory, DatabaseErrorMessage))
- return DB;
- ErrorStream << It->getName() << ": " << DatabaseErrorMessage << "\n";
- }
- return nullptr;
-}
-
-static std::unique_ptr<CompilationDatabase>
-findCompilationDatabaseFromDirectory(StringRef Directory,
- std::string &ErrorMessage) {
- std::stringstream ErrorStream;
- bool HasErrorMessage = false;
- while (!Directory.empty()) {
- std::string LoadErrorMessage;
-
- if (std::unique_ptr<CompilationDatabase> DB =
- CompilationDatabase::loadFromDirectory(Directory, LoadErrorMessage))
- return DB;
-
- if (!HasErrorMessage) {
- ErrorStream << "No compilation database found in " << Directory.str()
- << " or any parent directory\n" << LoadErrorMessage;
- HasErrorMessage = true;
- }
-
- Directory = llvm::sys::path::parent_path(Directory);
- }
- ErrorMessage = ErrorStream.str();
- return nullptr;
-}
-
-std::unique_ptr<CompilationDatabase>
-CompilationDatabase::autoDetectFromSource(StringRef SourceFile,
- std::string &ErrorMessage) {
- SmallString<1024> AbsolutePath(getAbsolutePath(SourceFile));
- StringRef Directory = llvm::sys::path::parent_path(AbsolutePath);
-
- std::unique_ptr<CompilationDatabase> DB =
- findCompilationDatabaseFromDirectory(Directory, ErrorMessage);
-
- if (!DB)
- ErrorMessage = ("Could not auto-detect compilation database for file \"" +
- SourceFile + "\"\n" + ErrorMessage).str();
- return DB;
-}
-
-std::unique_ptr<CompilationDatabase>
-CompilationDatabase::autoDetectFromDirectory(StringRef SourceDir,
- std::string &ErrorMessage) {
- SmallString<1024> AbsolutePath(getAbsolutePath(SourceDir));
-
- std::unique_ptr<CompilationDatabase> DB =
- findCompilationDatabaseFromDirectory(AbsolutePath, ErrorMessage);
-
- if (!DB)
- ErrorMessage = ("Could not auto-detect compilation database from directory \"" +
- SourceDir + "\"\n" + ErrorMessage).str();
- return DB;
-}
-
-std::vector<CompileCommand> CompilationDatabase::getAllCompileCommands() const {
- std::vector<CompileCommand> Result;
- for (const auto &File : getAllFiles()) {
- auto C = getCompileCommands(File);
- std::move(C.begin(), C.end(), std::back_inserter(Result));
- }
- return Result;
-}
-
-CompilationDatabasePlugin::~CompilationDatabasePlugin() = default;
-
-namespace {
-
-// Helper for recursively searching through a chain of actions and collecting
-// all inputs, direct and indirect, of compile jobs.
-struct CompileJobAnalyzer {
- SmallVector<std::string, 2> Inputs;
-
- void run(const driver::Action *A) {
- runImpl(A, false);
- }
-
-private:
- void runImpl(const driver::Action *A, bool Collect) {
- bool CollectChildren = Collect;
- switch (A->getKind()) {
- case driver::Action::CompileJobClass:
- CollectChildren = true;
- break;
-
- case driver::Action::InputClass:
- if (Collect) {
- const auto *IA = cast<driver::InputAction>(A);
- Inputs.push_back(IA->getInputArg().getSpelling());
- }
- break;
-
- default:
- // Don't care about others
- break;
- }
-
- for (const driver::Action *AI : A->inputs())
- runImpl(AI, CollectChildren);
- }
-};
-
-// Special DiagnosticConsumer that looks for warn_drv_input_file_unused
-// diagnostics from the driver and collects the option strings for those unused
-// options.
-class UnusedInputDiagConsumer : public DiagnosticConsumer {
-public:
- UnusedInputDiagConsumer(DiagnosticConsumer &Other) : Other(Other) {}
-
- void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
- const Diagnostic &Info) override {
- if (Info.getID() == diag::warn_drv_input_file_unused) {
- // Arg 1 for this diagnostic is the option that didn't get used.
- UnusedInputs.push_back(Info.getArgStdStr(0));
- } else if (DiagLevel >= DiagnosticsEngine::Error) {
- // If driver failed to create compilation object, show the diagnostics
- // to user.
- Other.HandleDiagnostic(DiagLevel, Info);
- }
- }
-
- DiagnosticConsumer &Other;
- SmallVector<std::string, 2> UnusedInputs;
-};
-
-// Unary functor for asking "Given a StringRef S1, does there exist a string
-// S2 in Arr where S1 == S2?"
-struct MatchesAny {
- MatchesAny(ArrayRef<std::string> Arr) : Arr(Arr) {}
-
- bool operator() (StringRef S) {
- for (const std::string *I = Arr.begin(), *E = Arr.end(); I != E; ++I)
- if (*I == S)
- return true;
- return false;
- }
-
-private:
- ArrayRef<std::string> Arr;
-};
-
-} // namespace
-
-/// Strips any positional args and possible argv[0] from a command-line
-/// provided by the user to construct a FixedCompilationDatabase.
-///
-/// FixedCompilationDatabase requires a command line to be in this format as it
-/// constructs the command line for each file by appending the name of the file
-/// to be compiled. FixedCompilationDatabase also adds its own argv[0] to the
-/// start of the command line although its value is not important as it's just
-/// ignored by the Driver invoked by the ClangTool using the
-/// FixedCompilationDatabase.
-///
-/// FIXME: This functionality should probably be made available by
-/// clang::driver::Driver although what the interface should look like is not
-/// clear.
-///
-/// \param[in] Args Args as provided by the user.
-/// \return Resulting stripped command line.
-/// \li true if successful.
-/// \li false if \c Args cannot be used for compilation jobs (e.g.
-/// contains an option like -E or -version).
-static bool stripPositionalArgs(std::vector<const char *> Args,
- std::vector<std::string> &Result,
- std::string &ErrorMsg) {
- IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
- llvm::raw_string_ostream Output(ErrorMsg);
- TextDiagnosticPrinter DiagnosticPrinter(Output, &*DiagOpts);
- UnusedInputDiagConsumer DiagClient(DiagnosticPrinter);
- DiagnosticsEngine Diagnostics(
- IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
- &*DiagOpts, &DiagClient, false);
-
- // The clang executable path isn't required since the jobs the driver builds
- // will not be executed.
- std::unique_ptr<driver::Driver> NewDriver(new driver::Driver(
- /* ClangExecutable= */ "", llvm::sys::getDefaultTargetTriple(),
- Diagnostics));
- NewDriver->setCheckInputsExist(false);
-
- // This becomes the new argv[0]. The value is actually not important as it
- // isn't used for invoking Tools.
- Args.insert(Args.begin(), "clang-tool");
-
- // By adding -c, we force the driver to treat compilation as the last phase.
- // It will then issue warnings via Diagnostics about un-used options that
- // would have been used for linking. If the user provided a compiler name as
- // the original argv[0], this will be treated as a linker input thanks to
- // insertng a new argv[0] above. All un-used options get collected by
- // UnusedInputdiagConsumer and get stripped out later.
- Args.push_back("-c");
-
- // Put a dummy C++ file on to ensure there's at least one compile job for the
- // driver to construct. If the user specified some other argument that
- // prevents compilation, e.g. -E or something like -version, we may still end
- // up with no jobs but then this is the user's fault.
- Args.push_back("placeholder.cpp");
-
- // Remove -no-integrated-as; it's not used for syntax checking,
- // and it confuses targets which don't support this option.
- Args.erase(std::remove_if(Args.begin(), Args.end(),
- MatchesAny(std::string("-no-integrated-as"))),
- Args.end());
-
- const std::unique_ptr<driver::Compilation> Compilation(
- NewDriver->BuildCompilation(Args));
- if (!Compilation)
- return false;
-
- const driver::JobList &Jobs = Compilation->getJobs();
-
- CompileJobAnalyzer CompileAnalyzer;
-
- for (const auto &Cmd : Jobs) {
- // Collect only for Assemble and Compile jobs. If we do all jobs we get
- // duplicates since Link jobs point to Assemble jobs as inputs.
- if (Cmd.getSource().getKind() == driver::Action::AssembleJobClass ||
- Cmd.getSource().getKind() == driver::Action::CompileJobClass) {
- CompileAnalyzer.run(&Cmd.getSource());
- }
- }
-
- if (CompileAnalyzer.Inputs.empty()) {
- ErrorMsg = "warning: no compile jobs found\n";
- return false;
- }
-
- // Remove all compilation input files from the command line. This is
- // necessary so that getCompileCommands() can construct a command line for
- // each file.
- std::vector<const char *>::iterator End = std::remove_if(
- Args.begin(), Args.end(), MatchesAny(CompileAnalyzer.Inputs));
-
- // Remove all inputs deemed unused for compilation.
- End = std::remove_if(Args.begin(), End, MatchesAny(DiagClient.UnusedInputs));
-
- // Remove the -c add above as well. It will be at the end right now.
- assert(strcmp(*(End - 1), "-c") == 0);
- --End;
-
- Result = std::vector<std::string>(Args.begin() + 1, End);
- return true;
-}
-
-std::unique_ptr<FixedCompilationDatabase>
-FixedCompilationDatabase::loadFromCommandLine(int &Argc,
- const char *const *Argv,
- std::string &ErrorMsg,
- Twine Directory) {
- ErrorMsg.clear();
- if (Argc == 0)
- return nullptr;
- const char *const *DoubleDash = std::find(Argv, Argv + Argc, StringRef("--"));
- if (DoubleDash == Argv + Argc)
- return nullptr;
- std::vector<const char *> CommandLine(DoubleDash + 1, Argv + Argc);
- Argc = DoubleDash - Argv;
-
- std::vector<std::string> StrippedArgs;
- if (!stripPositionalArgs(CommandLine, StrippedArgs, ErrorMsg))
- return nullptr;
- return llvm::make_unique<FixedCompilationDatabase>(Directory, StrippedArgs);
-}
-
-std::unique_ptr<FixedCompilationDatabase>
-FixedCompilationDatabase::loadFromFile(StringRef Path, std::string &ErrorMsg) {
- ErrorMsg.clear();
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
- llvm::MemoryBuffer::getFile(Path);
- if (std::error_code Result = File.getError()) {
- ErrorMsg = "Error while opening fixed database: " + Result.message();
- return nullptr;
- }
- std::vector<std::string> Args{llvm::line_iterator(**File),
- llvm::line_iterator()};
- return llvm::make_unique<FixedCompilationDatabase>(
- llvm::sys::path::parent_path(Path), std::move(Args));
-}
-
-FixedCompilationDatabase::
-FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) {
- std::vector<std::string> ToolCommandLine(1, "clang-tool");
- ToolCommandLine.insert(ToolCommandLine.end(),
- CommandLine.begin(), CommandLine.end());
- CompileCommands.emplace_back(Directory, StringRef(),
- std::move(ToolCommandLine),
- StringRef());
-}
-
-std::vector<CompileCommand>
-FixedCompilationDatabase::getCompileCommands(StringRef FilePath) const {
- std::vector<CompileCommand> Result(CompileCommands);
- Result[0].CommandLine.push_back(FilePath);
- Result[0].Filename = FilePath;
- return Result;
-}
-
-namespace {
-
-class FixedCompilationDatabasePlugin : public CompilationDatabasePlugin {
- std::unique_ptr<CompilationDatabase>
- loadFromDirectory(StringRef Directory, std::string &ErrorMessage) override {
- SmallString<1024> DatabasePath(Directory);
- llvm::sys::path::append(DatabasePath, "compile_flags.txt");
- return FixedCompilationDatabase::loadFromFile(DatabasePath, ErrorMessage);
- }
-};
-
-} // namespace
-
-static CompilationDatabasePluginRegistry::Add<FixedCompilationDatabasePlugin>
-X("fixed-compilation-database", "Reads plain-text flags file");
-
-namespace clang {
-namespace tooling {
-
-// This anchor is used to force the linker to link in the generated object file
-// and thus register the JSONCompilationDatabasePlugin.
-extern volatile int JSONAnchorSource;
-static int LLVM_ATTRIBUTE_UNUSED JSONAnchorDest = JSONAnchorSource;
-
-} // namespace tooling
-} // namespace clang