diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Tooling/ArgumentsAdjusters.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Tooling/CompilationDatabase.cpp | 55 | ||||
-rw-r--r-- | clang/lib/Tooling/Core/Replacement.cpp | 57 | ||||
-rw-r--r-- | clang/lib/Tooling/FileMatchTrie.cpp | 33 | ||||
-rw-r--r-- | clang/lib/Tooling/JSONCompilationDatabase.cpp | 86 | ||||
-rw-r--r-- | clang/lib/Tooling/Tooling.cpp | 132 |
6 files changed, 235 insertions, 135 deletions
diff --git a/clang/lib/Tooling/ArgumentsAdjusters.cpp b/clang/lib/Tooling/ArgumentsAdjusters.cpp index 7068ec2c401..c8e9c167422 100644 --- a/clang/lib/Tooling/ArgumentsAdjusters.cpp +++ b/clang/lib/Tooling/ArgumentsAdjusters.cpp @@ -1,4 +1,4 @@ -//===--- ArgumentsAdjusters.cpp - Command line arguments adjuster ---------===// +//===- ArgumentsAdjusters.cpp - Command line arguments adjuster -----------===// // // The LLVM Compiler Infrastructure // @@ -13,6 +13,9 @@ //===----------------------------------------------------------------------===// #include "clang/Tooling/ArgumentsAdjusters.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/StringRef.h" +#include <cstddef> namespace clang { namespace tooling { @@ -21,7 +24,7 @@ namespace tooling { ArgumentsAdjuster getClangSyntaxOnlyAdjuster() { return [](const CommandLineArguments &Args, StringRef /*unused*/) { CommandLineArguments AdjustedArgs; - for (size_t i = 0, e = Args.size(); i != e; ++i) { + for (size_t i = 0, e = Args.size(); i < e; ++i) { StringRef Arg = Args[i]; // FIXME: Remove options that generate output. if (!Arg.startswith("-fcolor-diagnostics") && diff --git a/clang/lib/Tooling/CompilationDatabase.cpp b/clang/lib/Tooling/CompilationDatabase.cpp index 92b76b157dc..3464a26d1a8 100644 --- a/clang/lib/Tooling/CompilationDatabase.cpp +++ b/clang/lib/Tooling/CompilationDatabase.cpp @@ -1,4 +1,4 @@ -//===--- CompilationDatabase.cpp - ----------------------------------------===// +//===- CompilationDatabase.cpp --------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -17,7 +17,9 @@ #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" @@ -26,20 +28,38 @@ #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() {} +CompilationDatabase::~CompilationDatabase() = default; std::unique_ptr<CompilationDatabase> CompilationDatabase::loadFromDirectory(StringRef BuildDirectory, @@ -121,20 +141,20 @@ std::vector<CompileCommand> CompilationDatabase::getAllCompileCommands() const { return Result; } -CompilationDatabasePlugin::~CompilationDatabasePlugin() {} +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); } - SmallVector<std::string, 2> Inputs; - private: - void runImpl(const driver::Action *A, bool Collect) { bool CollectChildren = Collect; switch (A->getKind()) { @@ -142,16 +162,16 @@ private: CollectChildren = true; break; - case driver::Action::InputClass: { + case driver::Action::InputClass: if (Collect) { - const driver::InputAction *IA = cast<driver::InputAction>(A); + const auto *IA = cast<driver::InputAction>(A); Inputs.push_back(IA->getInputArg().getSpelling()); } - } break; + break; default: // Don't care about others - ; + break; } for (const driver::Action *AI : A->inputs()) @@ -168,7 +188,7 @@ public: void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) override { - if (Info.getID() == clang::diag::warn_drv_input_file_unused) { + 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) { @@ -186,15 +206,18 @@ public: // 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 /// \brief Strips any positional args and possible argv[0] from a command-line @@ -224,7 +247,7 @@ static bool stripPositionalArgs(std::vector<const char *> Args, TextDiagnosticPrinter DiagnosticPrinter(Output, &*DiagOpts); UnusedInputDiagConsumer DiagClient(DiagnosticPrinter); DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()), + IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts, &DiagClient, false); // The clang executable path isn't required since the jobs the driver builds @@ -362,11 +385,11 @@ class FixedCompilationDatabasePlugin : public CompilationDatabasePlugin { } }; +} // namespace + static CompilationDatabasePluginRegistry::Add<FixedCompilationDatabasePlugin> X("fixed-compilation-database", "Reads plain-text flags file"); -} // namespace - namespace clang { namespace tooling { @@ -375,5 +398,5 @@ namespace tooling { extern volatile int JSONAnchorSource; static int LLVM_ATTRIBUTE_UNUSED JSONAnchorDest = JSONAnchorSource; -} // end namespace tooling -} // end namespace clang +} // namespace tooling +} // namespace clang diff --git a/clang/lib/Tooling/Core/Replacement.cpp b/clang/lib/Tooling/Core/Replacement.cpp index 6d4f3a34014..54b7ca8fafe 100644 --- a/clang/lib/Tooling/Core/Replacement.cpp +++ b/clang/lib/Tooling/Core/Replacement.cpp @@ -1,4 +1,4 @@ -//===--- Replacement.cpp - Framework for clang refactoring tools ----------===// +//===- Replacement.cpp - Framework for clang refactoring tools ------------===// // // The LLVM Compiler Infrastructure // @@ -12,21 +12,34 @@ //===----------------------------------------------------------------------===// #include "clang/Tooling/Core/Replacement.h" - #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticIDs.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/FileSystemOptions.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/VirtualFileSystem.h" #include "clang/Lex/Lexer.h" +#include "clang/Rewrite/Core/RewriteBuffer.h" #include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/raw_os_ostream.h" - -namespace clang { -namespace tooling { +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <limits> +#include <map> +#include <string> +#include <utility> +#include <vector> + +using namespace clang; +using namespace tooling; static const char * const InvalidLocation = ""; @@ -80,6 +93,9 @@ std::string Replacement::toString() const { return Stream.str(); } +namespace clang { +namespace tooling { + bool operator<(const Replacement &LHS, const Replacement &RHS) { if (LHS.getOffset() != RHS.getOffset()) return LHS.getOffset() < RHS.getOffset(); @@ -99,6 +115,9 @@ bool operator==(const Replacement &LHS, const Replacement &RHS) { LHS.getReplacementText() == RHS.getReplacementText(); } +} // namespace tooling +} // namespace clang + void Replacement::setFromSourceLocation(const SourceManager &Sources, SourceLocation Start, unsigned Length, StringRef ReplacementText) { @@ -231,7 +250,7 @@ llvm::Error Replacements::add(const Replacement &R) { replacement_error::wrong_file_path, R, *Replaces.begin()); // Special-case header insertions. - if (R.getOffset() == UINT_MAX) { + if (R.getOffset() == std::numeric_limits<unsigned>::max()) { Replaces.insert(R); return llvm::Error::success(); } @@ -396,6 +415,7 @@ public: // Returns 'true' if an element from the second set should be merged next. bool mergeSecond() const { return MergeSecond; } + int deltaFirst() const { return DeltaFirst; } Replacement asReplacement() const { return {FilePath, Offset, Length, Text}; } @@ -485,6 +505,9 @@ static std::vector<Range> combineAndSortRanges(std::vector<Range> Ranges) { return Result; } +namespace clang { +namespace tooling { + std::vector<Range> calculateRangesAfterReplacements(const Replacements &Replaces, const std::vector<Range> &Ranges) { @@ -508,10 +531,13 @@ calculateRangesAfterReplacements(const Replacements &Replaces, return FakeReplaces.merge(Replaces).getAffectedRanges(); } +} // namespace tooling +} // namespace clang + std::vector<Range> Replacements::getAffectedRanges() const { std::vector<Range> ChangedRanges; int Shift = 0; - for (const Replacement &R : Replaces) { + for (const auto &R : Replaces) { unsigned Offset = R.getOffset() + Shift; unsigned Length = R.getReplacementText().size(); Shift += Length - R.getLength(); @@ -522,7 +548,7 @@ std::vector<Range> Replacements::getAffectedRanges() const { unsigned Replacements::getShiftedCodePosition(unsigned Position) const { unsigned Offset = 0; - for (const auto& R : Replaces) { + for (const auto &R : Replaces) { if (R.getOffset() + R.getLength() <= Position) { Offset += R.getReplacementText().size() - R.getLength(); continue; @@ -530,7 +556,7 @@ unsigned Replacements::getShiftedCodePosition(unsigned Position) const { if (R.getOffset() < Position && R.getOffset() + R.getReplacementText().size() <= Position) { Position = R.getOffset() + R.getReplacementText().size(); - if (R.getReplacementText().size() > 0) + if (!R.getReplacementText().empty()) Position--; } break; @@ -538,6 +564,9 @@ unsigned Replacements::getShiftedCodePosition(unsigned Position) const { return Position + Offset; } +namespace clang { +namespace tooling { + bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite) { bool Result = true; for (auto I = Replaces.rbegin(), E = Replaces.rend(); I != E; ++I) { @@ -596,5 +625,5 @@ std::map<std::string, Replacements> groupReplacementsByFile( return Result; } -} // end namespace tooling -} // end namespace clang +} // namespace tooling +} // namespace clang diff --git a/clang/lib/Tooling/FileMatchTrie.cpp b/clang/lib/Tooling/FileMatchTrie.cpp index 86ed036e2db..248d4e247f2 100644 --- a/clang/lib/Tooling/FileMatchTrie.cpp +++ b/clang/lib/Tooling/FileMatchTrie.cpp @@ -1,4 +1,4 @@ -//===--- FileMatchTrie.cpp - ----------------------------------------------===// +//===- FileMatchTrie.cpp --------------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -13,24 +13,30 @@ #include "clang/Tooling/FileMatchTrie.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" -#include <sstream> +#include <string> +#include <vector> + using namespace clang; using namespace tooling; namespace { + /// \brief Default \c PathComparator using \c llvm::sys::fs::equivalent(). struct DefaultPathComparator : public PathComparator { bool equivalent(StringRef FileA, StringRef FileB) const override { return FileA == FileB || llvm::sys::fs::equivalent(FileA, FileB); } }; -} + +} // namespace namespace clang { namespace tooling { + /// \brief A node of the \c FileMatchTrie. /// /// Each node has storage for up to one path and a map mapping a path segment to @@ -103,7 +109,7 @@ public: if (Children.empty()) { if (Comparator.equivalent(StringRef(Path), FileName)) return StringRef(Path); - return StringRef(); + return {}; } StringRef Element(llvm::sys::path::filename(FileName.drop_back( ConsumedLength))); @@ -119,13 +125,13 @@ public: std::vector<StringRef> AllChildren; getAll(AllChildren, MatchingChild); StringRef Result; - for (unsigned i = 0; i < AllChildren.size(); i++) { - if (Comparator.equivalent(AllChildren[i], FileName)) { + for (const auto &Child : AllChildren) { + if (Comparator.equivalent(Child, FileName)) { if (Result.empty()) { - Result = AllChildren[i]; + Result = Child; } else { IsAmbiguous = true; - return StringRef(); + return {}; } } } @@ -158,14 +164,15 @@ private: // The children of this node stored in a map based on the next path segment. llvm::StringMap<FileMatchTrieNode> Children; }; -} // end namespace tooling -} // end namespace clang + +} // namespace tooling +} // namespace clang FileMatchTrie::FileMatchTrie() - : Root(new FileMatchTrieNode), Comparator(new DefaultPathComparator()) {} + : Root(new FileMatchTrieNode), Comparator(new DefaultPathComparator()) {} FileMatchTrie::FileMatchTrie(PathComparator *Comparator) - : Root(new FileMatchTrieNode), Comparator(Comparator) {} + : Root(new FileMatchTrieNode), Comparator(Comparator) {} FileMatchTrie::~FileMatchTrie() { delete Root; @@ -179,7 +186,7 @@ StringRef FileMatchTrie::findEquivalent(StringRef FileName, raw_ostream &Error) const { if (llvm::sys::path::is_relative(FileName)) { Error << "Cannot resolve relative paths"; - return StringRef(); + return {}; } bool IsAmbiguous = false; StringRef Result = Root->findEquivalent(*Comparator, FileName, IsAmbiguous); diff --git a/clang/lib/Tooling/JSONCompilationDatabase.cpp b/clang/lib/Tooling/JSONCompilationDatabase.cpp index f9a230eb63a..67c1f5b220a 100644 --- a/clang/lib/Tooling/JSONCompilationDatabase.cpp +++ b/clang/lib/Tooling/JSONCompilationDatabase.cpp @@ -1,4 +1,4 @@ -//===--- JSONCompilationDatabase.cpp - ------------------------------------===// +//===- JSONCompilationDatabase.cpp ----------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -12,18 +12,34 @@ //===----------------------------------------------------------------------===// #include "clang/Tooling/JSONCompilationDatabase.h" +#include "clang/Basic/LLVM.h" #include "clang/Tooling/CompilationDatabase.h" #include "clang/Tooling/CompilationDatabasePluginRegistry.h" -#include "clang/Tooling/Tooling.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/StringSaver.h" +#include "llvm/Support/YAMLParser.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <memory> +#include <string> #include <system_error> +#include <tuple> +#include <utility> +#include <vector> -namespace clang { -namespace tooling { +using namespace clang; +using namespace tooling; namespace { @@ -151,17 +167,23 @@ class JSONCompilationDatabasePlugin : public CompilationDatabasePlugin { } }; -} // end namespace +} // namespace // Register the JSONCompilationDatabasePlugin with the // CompilationDatabasePluginRegistry using this statically initialized variable. static CompilationDatabasePluginRegistry::Add<JSONCompilationDatabasePlugin> X("json-compilation-database", "Reads JSON formatted compilation databases"); +namespace clang { +namespace tooling { + // This anchor is used to force the linker to link in the generated object file // and thus register the JSONCompilationDatabasePlugin. volatile int JSONAnchorSource = 0; +} // namespace tooling +} // namespace clang + std::unique_ptr<JSONCompilationDatabase> JSONCompilationDatabase::loadFromFile(StringRef FilePath, std::string &ErrorMessage, @@ -201,11 +223,10 @@ JSONCompilationDatabase::getCompileCommands(StringRef FilePath) const { llvm::raw_string_ostream ES(Error); StringRef Match = MatchTrie.findEquivalent(NativeFilePath, ES); if (Match.empty()) - return std::vector<CompileCommand>(); - llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator - CommandsRefI = IndexByFile.find(Match); + return {}; + const auto CommandsRefI = IndexByFile.find(Match); if (CommandsRefI == IndexByFile.end()) - return std::vector<CompileCommand>(); + return {}; std::vector<CompileCommand> Commands; getCommands(CommandsRefI->getValue(), Commands); return Commands; @@ -214,15 +235,8 @@ JSONCompilationDatabase::getCompileCommands(StringRef FilePath) const { std::vector<std::string> JSONCompilationDatabase::getAllFiles() const { std::vector<std::string> Result; - - llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator - CommandsRefI = IndexByFile.begin(); - const llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator - CommandsRefEnd = IndexByFile.end(); - for (; CommandsRefI != CommandsRefEnd; ++CommandsRefI) { - Result.push_back(CommandsRefI->first().str()); - } - + for (const auto &CommandRef : IndexByFile) + Result.push_back(CommandRef.first().str()); return Result; } @@ -237,28 +251,26 @@ static std::vector<std::string> nodeToCommandLine(JSONCommandLineSyntax Syntax, const std::vector<llvm::yaml::ScalarNode *> &Nodes) { SmallString<1024> Storage; - if (Nodes.size() == 1) { + if (Nodes.size() == 1) return unescapeCommandLine(Syntax, Nodes[0]->getValue(Storage)); - } std::vector<std::string> Arguments; - for (auto *Node : Nodes) { + for (const auto *Node : Nodes) Arguments.push_back(Node->getValue(Storage)); - } return Arguments; } void JSONCompilationDatabase::getCommands( ArrayRef<CompileCommandRef> CommandsRef, std::vector<CompileCommand> &Commands) const { - for (int I = 0, E = CommandsRef.size(); I != E; ++I) { + for (const auto &CommandRef : CommandsRef) { SmallString<8> DirectoryStorage; SmallString<32> FilenameStorage; SmallString<32> OutputStorage; - auto Output = std::get<3>(CommandsRef[I]); + auto Output = std::get<3>(CommandRef); Commands.emplace_back( - std::get<0>(CommandsRef[I])->getValue(DirectoryStorage), - std::get<1>(CommandsRef[I])->getValue(FilenameStorage), - nodeToCommandLine(Syntax, std::get<2>(CommandsRef[I])), + std::get<0>(CommandRef)->getValue(DirectoryStorage), + std::get<1>(CommandRef)->getValue(FilenameStorage), + nodeToCommandLine(Syntax, std::get<2>(CommandRef)), Output ? Output->getValue(OutputStorage) : ""); } } @@ -274,13 +286,13 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) { ErrorMessage = "Error while parsing YAML."; return false; } - llvm::yaml::SequenceNode *Array = dyn_cast<llvm::yaml::SequenceNode>(Root); + auto *Array = dyn_cast<llvm::yaml::SequenceNode>(Root); if (!Array) { ErrorMessage = "Expected array."; return false; } - for (auto& NextObject : *Array) { - llvm::yaml::MappingNode *Object = dyn_cast<llvm::yaml::MappingNode>(&NextObject); + for (auto &NextObject : *Array) { + auto *Object = dyn_cast<llvm::yaml::MappingNode>(&NextObject); if (!Object) { ErrorMessage = "Expected object."; return false; @@ -290,8 +302,7 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) { llvm::yaml::ScalarNode *File = nullptr; llvm::yaml::ScalarNode *Output = nullptr; for (auto& NextKeyValue : *Object) { - llvm::yaml::ScalarNode *KeyString = - dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey()); + auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey()); if (!KeyString) { ErrorMessage = "Expected strings as key."; return false; @@ -303,10 +314,8 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) { ErrorMessage = "Expected value."; return false; } - llvm::yaml::ScalarNode *ValueString = - dyn_cast<llvm::yaml::ScalarNode>(Value); - llvm::yaml::SequenceNode *SequenceString = - dyn_cast<llvm::yaml::SequenceNode>(Value); + auto *ValueString = dyn_cast<llvm::yaml::ScalarNode>(Value); + auto *SequenceString = dyn_cast<llvm::yaml::SequenceNode>(Value); if (KeyValue == "arguments" && !SequenceString) { ErrorMessage = "Expected sequence as value."; return false; @@ -319,7 +328,7 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) { } else if (KeyValue == "arguments") { Command = std::vector<llvm::yaml::ScalarNode *>(); for (auto &Argument : *SequenceString) { - auto Scalar = dyn_cast<llvm::yaml::ScalarNode>(&Argument); + auto *Scalar = dyn_cast<llvm::yaml::ScalarNode>(&Argument); if (!Scalar) { ErrorMessage = "Only strings are allowed in 'arguments'."; return false; @@ -370,6 +379,3 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) { } return true; } - -} // end namespace tooling -} // end namespace clang diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp index 7ae2950037b..caaf3aa95b8 100644 --- a/clang/lib/Tooling/Tooling.cpp +++ b/clang/lib/Tooling/Tooling.cpp @@ -1,4 +1,4 @@ -//===--- Tooling.cpp - Running clang standalone tools ---------------------===// +//===- Tooling.cpp - Running clang standalone tools -----------------------===// // // The LLVM Compiler Infrastructure // @@ -13,90 +13,114 @@ //===----------------------------------------------------------------------===// #include "clang/Tooling/Tooling.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticIDs.h" +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/FileSystemOptions.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/VirtualFileSystem.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" +#include "clang/Driver/Job.h" #include "clang/Driver/Options.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/FrontendOptions.h" #include "clang/Frontend/TextDiagnosticPrinter.h" +#include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Tooling/ArgumentsAdjusters.h" #include "clang/Tooling/CompilationDatabase.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" #include "llvm/Config/llvm-config.h" #include "llvm/Option/ArgList.h" +#include "llvm/Option/OptTable.h" #include "llvm/Option/Option.h" -#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <cstring> +#include <memory> +#include <string> +#include <system_error> #include <utility> +#include <vector> #define DEBUG_TYPE "clang-tooling" -namespace clang { -namespace tooling { +using namespace clang; +using namespace tooling; -ToolAction::~ToolAction() {} +ToolAction::~ToolAction() = default; -FrontendActionFactory::~FrontendActionFactory() {} +FrontendActionFactory::~FrontendActionFactory() = default; // FIXME: This file contains structural duplication with other parts of the // code that sets up a compiler to run tools on it, and we should refactor // it to be based on the same framework. /// \brief Builds a clang driver initialized for running clang tools. -static clang::driver::Driver *newDriver( - clang::DiagnosticsEngine *Diagnostics, const char *BinaryName, +static driver::Driver *newDriver( + DiagnosticsEngine *Diagnostics, const char *BinaryName, IntrusiveRefCntPtr<vfs::FileSystem> VFS) { - clang::driver::Driver *CompilerDriver = - new clang::driver::Driver(BinaryName, llvm::sys::getDefaultTargetTriple(), - *Diagnostics, std::move(VFS)); + driver::Driver *CompilerDriver = + new driver::Driver(BinaryName, llvm::sys::getDefaultTargetTriple(), + *Diagnostics, std::move(VFS)); CompilerDriver->setTitle("clang_based_tool"); return CompilerDriver; } /// \brief Retrieves the clang CC1 specific flags out of the compilation's jobs. /// -/// Returns NULL on error. +/// Returns nullptr on error. static const llvm::opt::ArgStringList *getCC1Arguments( - clang::DiagnosticsEngine *Diagnostics, - clang::driver::Compilation *Compilation) { + DiagnosticsEngine *Diagnostics, driver::Compilation *Compilation) { // We expect to get back exactly one Command job, if we didn't something // failed. Extract that job from the Compilation. - const clang::driver::JobList &Jobs = Compilation->getJobs(); - if (Jobs.size() != 1 || !isa<clang::driver::Command>(*Jobs.begin())) { + const driver::JobList &Jobs = Compilation->getJobs(); + if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) { SmallString<256> error_msg; llvm::raw_svector_ostream error_stream(error_msg); Jobs.Print(error_stream, "; ", true); - Diagnostics->Report(clang::diag::err_fe_expected_compiler_job) + Diagnostics->Report(diag::err_fe_expected_compiler_job) << error_stream.str(); return nullptr; } // The one job we find should be to invoke clang again. - const clang::driver::Command &Cmd = - cast<clang::driver::Command>(*Jobs.begin()); + const auto &Cmd = cast<driver::Command>(*Jobs.begin()); if (StringRef(Cmd.getCreator().getName()) != "clang") { - Diagnostics->Report(clang::diag::err_fe_expected_clang_command); + Diagnostics->Report(diag::err_fe_expected_clang_command); return nullptr; } return &Cmd.getArguments(); } +namespace clang { +namespace tooling { + /// \brief Returns a clang build invocation initialized from the CC1 flags. -clang::CompilerInvocation *newInvocation( - clang::DiagnosticsEngine *Diagnostics, - const llvm::opt::ArgStringList &CC1Args) { +CompilerInvocation *newInvocation( + DiagnosticsEngine *Diagnostics, const llvm::opt::ArgStringList &CC1Args) { assert(!CC1Args.empty() && "Must at least contain the program name!"); - clang::CompilerInvocation *Invocation = new clang::CompilerInvocation; - clang::CompilerInvocation::CreateFromArgs( + CompilerInvocation *Invocation = new CompilerInvocation; + CompilerInvocation::CreateFromArgs( *Invocation, CC1Args.data() + 1, CC1Args.data() + CC1Args.size(), *Diagnostics); Invocation->getFrontendOpts().DisableFree = false; @@ -104,7 +128,7 @@ clang::CompilerInvocation *newInvocation( return Invocation; } -bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code, +bool runToolOnCode(FrontendAction *ToolAction, const Twine &Code, const Twine &FileName, std::shared_ptr<PCHContainerOperations> PCHContainerOps) { return runToolOnCodeWithArgs(ToolAction, Code, std::vector<std::string>(), @@ -112,6 +136,9 @@ bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code, std::move(PCHContainerOps)); } +} // namespace tooling +} // namespace clang + static std::vector<std::string> getSyntaxOnlyToolArgs(const Twine &ToolName, const std::vector<std::string> &ExtraArgs, @@ -124,13 +151,15 @@ getSyntaxOnlyToolArgs(const Twine &ToolName, return Args; } +namespace clang { +namespace tooling { + bool runToolOnCodeWithArgs( - clang::FrontendAction *ToolAction, const Twine &Code, + FrontendAction *ToolAction, const Twine &Code, const std::vector<std::string> &Args, const Twine &FileName, const Twine &ToolName, std::shared_ptr<PCHContainerOperations> PCHContainerOps, const FileContentMappings &VirtualMappedFiles) { - SmallString<16> FileNameStorage; StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage); llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem( @@ -190,7 +219,7 @@ void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine, TokenRef.startswith("--driver-mode=")); } auto TargetMode = - clang::driver::ToolChain::getTargetAndModeFromProgramName(InvokedAs); + driver::ToolChain::getTargetAndModeFromProgramName(InvokedAs); if (!AlreadyHasMode && TargetMode.DriverMode) { CommandLine.insert(++CommandLine.begin(), TargetMode.DriverMode); } @@ -201,6 +230,9 @@ void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine, } } +} // namespace tooling +} // namespace clang + namespace { class SingleFrontendActionFactory : public FrontendActionFactory { @@ -212,22 +244,20 @@ public: FrontendAction *create() override { return Action; } }; -} +} // namespace ToolInvocation::ToolInvocation( std::vector<std::string> CommandLine, ToolAction *Action, FileManager *Files, std::shared_ptr<PCHContainerOperations> PCHContainerOps) : CommandLine(std::move(CommandLine)), Action(Action), OwnsAction(false), - Files(Files), PCHContainerOps(std::move(PCHContainerOps)), - DiagConsumer(nullptr) {} + Files(Files), PCHContainerOps(std::move(PCHContainerOps)) {} ToolInvocation::ToolInvocation( std::vector<std::string> CommandLine, FrontendAction *FAction, FileManager *Files, std::shared_ptr<PCHContainerOperations> PCHContainerOps) : CommandLine(std::move(CommandLine)), Action(new SingleFrontendActionFactory(FAction)), OwnsAction(true), - Files(Files), PCHContainerOps(std::move(PCHContainerOps)), - DiagConsumer(nullptr) {} + Files(Files), PCHContainerOps(std::move(PCHContainerOps)) {} ToolInvocation::~ToolInvocation() { if (OwnsAction) @@ -254,23 +284,22 @@ bool ToolInvocation::run() { TextDiagnosticPrinter DiagnosticPrinter( llvm::errs(), &*DiagOpts); DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts, + IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts, DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false); - const std::unique_ptr<clang::driver::Driver> Driver( + const std::unique_ptr<driver::Driver> Driver( newDriver(&Diagnostics, BinaryName, Files->getVirtualFileSystem())); // Since the input might only be virtual, don't check whether it exists. Driver->setCheckInputsExist(false); - const std::unique_ptr<clang::driver::Compilation> Compilation( + const std::unique_ptr<driver::Compilation> Compilation( Driver->BuildCompilation(llvm::makeArrayRef(Argv))); if (!Compilation) return false; const llvm::opt::ArgStringList *const CC1Args = getCC1Arguments( &Diagnostics, Compilation.get()); - if (!CC1Args) { + if (!CC1Args) return false; - } - std::unique_ptr<clang::CompilerInvocation> Invocation( + std::unique_ptr<CompilerInvocation> Invocation( newInvocation(&Diagnostics, *CC1Args)); // FIXME: remove this when all users have migrated! for (const auto &It : MappedFileContents) { @@ -285,8 +314,8 @@ bool ToolInvocation::run() { } bool ToolInvocation::runInvocation( - const char *BinaryName, clang::driver::Compilation *Compilation, - std::shared_ptr<clang::CompilerInvocation> Invocation, + const char *BinaryName, driver::Compilation *Compilation, + std::shared_ptr<CompilerInvocation> Invocation, std::shared_ptr<PCHContainerOperations> PCHContainerOps) { // Show the invocation, with -v. if (Invocation->getHeaderSearchOpts().Verbose) { @@ -304,7 +333,7 @@ bool FrontendActionFactory::runInvocation( std::shared_ptr<PCHContainerOperations> PCHContainerOps, DiagnosticConsumer *DiagConsumer) { // Create a compiler instance to handle the actual work. - clang::CompilerInstance Compiler(std::move(PCHContainerOps)); + CompilerInstance Compiler(std::move(PCHContainerOps)); Compiler.setInvocation(std::move(Invocation)); Compiler.setFileManager(Files); @@ -334,15 +363,14 @@ ClangTool::ClangTool(const CompilationDatabase &Compilations, PCHContainerOps(std::move(PCHContainerOps)), OverlayFileSystem(new vfs::OverlayFileSystem(BaseFS)), InMemoryFileSystem(new vfs::InMemoryFileSystem), - Files(new FileManager(FileSystemOptions(), OverlayFileSystem)), - DiagConsumer(nullptr) { + Files(new FileManager(FileSystemOptions(), OverlayFileSystem)) { OverlayFileSystem->pushOverlay(InMemoryFileSystem); appendArgumentsAdjuster(getClangStripOutputAdjuster()); appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster()); appendArgumentsAdjuster(getClangStripDependencyFileAdjuster()); } -ClangTool::~ClangTool() {} +ClangTool::~ClangTool() = default; void ClangTool::mapVirtualFile(StringRef FilePath, StringRef Content) { MappedFileContents.push_back(std::make_pair(FilePath, Content)); @@ -491,13 +519,17 @@ public: return true; } }; -} + +} // namespace int ClangTool::buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs) { ASTBuilderAction Action(ASTs); return run(&Action); } +namespace clang { +namespace tooling { + std::unique_ptr<ASTUnit> buildASTFromCode(const Twine &Code, const Twine &FileName, std::shared_ptr<PCHContainerOperations> PCHContainerOps) { @@ -538,5 +570,5 @@ std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs( return std::move(ASTs[0]); } -} // end namespace tooling -} // end namespace clang +} // namespace tooling +} // namespace clang |