diff options
author | Zachary Turner <zturner@google.com> | 2016-08-18 19:31:48 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2016-08-18 19:31:48 +0000 |
commit | cd39b643d9e1e5e7d5a85874a9176501c227c9f1 (patch) | |
tree | ee77c14bc45157d91878cb95f7e55cf807608d09 /lib/Tooling/JSONCompilationDatabase.cpp | |
parent | b2df6a41f4d626eec3a9de7cbca7b23a28f7b8b7 (diff) | |
download | clang-cd39b643d9e1e5e7d5a85874a9176501c227c9f1.tar.gz |
Resubmit "[Tooling] Parse compilation database command lines on Windows."
This patch introduced the ability to decide at runtime whether to parse
JSON compilation database command lines using Gnu syntax or Windows
syntax. However, there were many existing unit tests written that
hardcoded Gnu-specific paths. These tests were now failing because
the auto-detection logic was choosing to parse them using Windows
rules.
This resubmission of the patch fixes this by introducing an enum
which defines the syntax mode, which defaults to auto-detect, but
for which the unit tests force Gnu style parsing.
Reviewed By: alexfh
Differential Revision: https://reviews.llvm.org/D23628
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@279120 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Tooling/JSONCompilationDatabase.cpp')
-rw-r--r-- | lib/Tooling/JSONCompilationDatabase.cpp | 54 |
1 files changed, 42 insertions, 12 deletions
diff --git a/lib/Tooling/JSONCompilationDatabase.cpp b/lib/Tooling/JSONCompilationDatabase.cpp index 299fbdc149..07292da6b3 100644 --- a/lib/Tooling/JSONCompilationDatabase.cpp +++ b/lib/Tooling/JSONCompilationDatabase.cpp @@ -16,7 +16,10 @@ #include "clang/Tooling/CompilationDatabasePluginRegistry.h" #include "clang/Tooling/Tooling.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Path.h" +#include "llvm/Support/StringSaver.h" #include <system_error> namespace clang { @@ -111,8 +114,31 @@ class CommandLineArgumentParser { std::vector<std::string> CommandLine; }; -std::vector<std::string> unescapeCommandLine( - StringRef EscapedCommandLine) { +std::vector<std::string> unescapeCommandLine(JSONCommandLineSyntax Syntax, + StringRef EscapedCommandLine) { + if (Syntax == JSONCommandLineSyntax::AutoDetect) { + llvm::Triple Triple(llvm::sys::getProcessTriple()); + if (Triple.getOS() == llvm::Triple::OSType::Win32) { + // Assume Windows command line parsing on Win32 unless the triple + // explicitly + // tells us otherwise. + if (!Triple.hasEnvironment() || + Triple.getEnvironment() == llvm::Triple::EnvironmentType::MSVC) + Syntax = JSONCommandLineSyntax::Windows; + else + Syntax = JSONCommandLineSyntax::Gnu; + } + } + + if (Syntax == JSONCommandLineSyntax::Windows) { + llvm::BumpPtrAllocator Alloc; + llvm::StringSaver Saver(Alloc); + llvm::SmallVector<const char *, 64> T; + llvm::cl::TokenizeWindowsCommandLine(EscapedCommandLine, Saver, T); + std::vector<std::string> Result(T.begin(), T.end()); + return Result; + } + assert(Syntax == JSONCommandLineSyntax::Gnu); CommandLineArgumentParser parser(EscapedCommandLine); return parser.parse(); } @@ -123,7 +149,8 @@ class JSONCompilationDatabasePlugin : public CompilationDatabasePlugin { SmallString<1024> JSONDatabasePath(Directory); llvm::sys::path::append(JSONDatabasePath, "compile_commands.json"); std::unique_ptr<CompilationDatabase> Database( - JSONCompilationDatabase::loadFromFile(JSONDatabasePath, ErrorMessage)); + JSONCompilationDatabase::loadFromFile( + JSONDatabasePath, ErrorMessage, JSONCommandLineSyntax::AutoDetect)); if (!Database) return nullptr; return Database; @@ -143,7 +170,8 @@ volatile int JSONAnchorSource = 0; std::unique_ptr<JSONCompilationDatabase> JSONCompilationDatabase::loadFromFile(StringRef FilePath, - std::string &ErrorMessage) { + std::string &ErrorMessage, + JSONCommandLineSyntax Syntax) { llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> DatabaseBuffer = llvm::MemoryBuffer::getFile(FilePath); if (std::error_code Result = DatabaseBuffer.getError()) { @@ -151,7 +179,7 @@ JSONCompilationDatabase::loadFromFile(StringRef FilePath, return nullptr; } std::unique_ptr<JSONCompilationDatabase> Database( - new JSONCompilationDatabase(std::move(*DatabaseBuffer))); + new JSONCompilationDatabase(std::move(*DatabaseBuffer), Syntax)); if (!Database->parse(ErrorMessage)) return nullptr; return Database; @@ -159,11 +187,12 @@ JSONCompilationDatabase::loadFromFile(StringRef FilePath, std::unique_ptr<JSONCompilationDatabase> JSONCompilationDatabase::loadFromBuffer(StringRef DatabaseString, - std::string &ErrorMessage) { + std::string &ErrorMessage, + JSONCommandLineSyntax Syntax) { std::unique_ptr<llvm::MemoryBuffer> DatabaseBuffer( llvm::MemoryBuffer::getMemBuffer(DatabaseString)); std::unique_ptr<JSONCompilationDatabase> Database( - new JSONCompilationDatabase(std::move(DatabaseBuffer))); + new JSONCompilationDatabase(std::move(DatabaseBuffer), Syntax)); if (!Database->parse(ErrorMessage)) return nullptr; return Database; @@ -211,10 +240,11 @@ JSONCompilationDatabase::getAllCompileCommands() const { } static std::vector<std::string> -nodeToCommandLine(const std::vector<llvm::yaml::ScalarNode *> &Nodes) { +nodeToCommandLine(JSONCommandLineSyntax Syntax, + const std::vector<llvm::yaml::ScalarNode *> &Nodes) { SmallString<1024> Storage; if (Nodes.size() == 1) { - return unescapeCommandLine(Nodes[0]->getValue(Storage)); + return unescapeCommandLine(Syntax, Nodes[0]->getValue(Storage)); } std::vector<std::string> Arguments; for (auto *Node : Nodes) { @@ -230,9 +260,9 @@ void JSONCompilationDatabase::getCommands( SmallString<8> DirectoryStorage; SmallString<32> FilenameStorage; Commands.emplace_back( - std::get<0>(CommandsRef[I])->getValue(DirectoryStorage), - std::get<1>(CommandsRef[I])->getValue(FilenameStorage), - nodeToCommandLine(std::get<2>(CommandsRef[I]))); + std::get<0>(CommandsRef[I])->getValue(DirectoryStorage), + std::get<1>(CommandsRef[I])->getValue(FilenameStorage), + nodeToCommandLine(Syntax, std::get<2>(CommandsRef[I]))); } } |