aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Tooling/JSONCompilationDatabase.cpp
diff options
context:
space:
mode:
authorManuel Klimek <klimek@google.com>2015-08-14 09:55:36 +0000
committerManuel Klimek <klimek@google.com>2015-08-14 09:55:36 +0000
commit54042e743c92748b149ab4069949ab884b3a292a (patch)
tree47a0a4a92352b8dc894da71cbe587fb2cb04ebf3 /clang/lib/Tooling/JSONCompilationDatabase.cpp
parent63be1987121e6674e66ddab2b4379282d56923f4 (diff)
downloadllvm-54042e743c92748b149ab4069949ab884b3a292a.zip
llvm-54042e743c92748b149ab4069949ab884b3a292a.tar.gz
llvm-54042e743c92748b149ab4069949ab884b3a292a.tar.bz2
Add structed way to express command line options in the compilation database.
Currently, arguments are passed via the string attribute 'command', assuming a shell-escaped / quoted command line to extract the original arguments. This works well enough on Unix systems, but turns out to be problematic for Windows tools to generate. This CL adds a new attribute 'arguments', an array of strings, which specifies the exact command line arguments. If 'arguments' is available in the compilation database, it is preferred to 'commands'. Currently there is no plan to retire 'commands': there are enough different use cases where users want to create their own mechanism for creating compilation databases, that it doesn't make sense to force them all to implement shell command line parsing. Patch by Daniel Dilts. llvm-svn: 245036
Diffstat (limited to 'clang/lib/Tooling/JSONCompilationDatabase.cpp')
-rw-r--r--clang/lib/Tooling/JSONCompilationDatabase.cpp69
1 files changed, 42 insertions, 27 deletions
diff --git a/clang/lib/Tooling/JSONCompilationDatabase.cpp b/clang/lib/Tooling/JSONCompilationDatabase.cpp
index 454a2ff..421651c 100644
--- a/clang/lib/Tooling/JSONCompilationDatabase.cpp
+++ b/clang/lib/Tooling/JSONCompilationDatabase.cpp
@@ -221,9 +221,8 @@ void JSONCompilationDatabase::getCommands(
SmallString<8> DirectoryStorage;
SmallString<1024> CommandStorage;
Commands.emplace_back(
- // FIXME: Escape correctly:
- CommandsRef[I].first->getValue(DirectoryStorage),
- unescapeCommandLine(CommandsRef[I].second->getValue(CommandStorage)));
+ CommandsRef[I].first->getValue(DirectoryStorage),
+ CommandsRef[I].second);
}
}
@@ -243,43 +242,59 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) {
ErrorMessage = "Expected array.";
return false;
}
- for (llvm::yaml::SequenceNode::iterator AI = Array->begin(),
- AE = Array->end();
- AI != AE; ++AI) {
- llvm::yaml::MappingNode *Object = dyn_cast<llvm::yaml::MappingNode>(&*AI);
+ for (auto& NextObject : *Array) {
+ llvm::yaml::MappingNode *Object = dyn_cast<llvm::yaml::MappingNode>(&NextObject);
if (!Object) {
ErrorMessage = "Expected object.";
return false;
}
llvm::yaml::ScalarNode *Directory = nullptr;
- llvm::yaml::ScalarNode *Command = nullptr;
+ std::vector<std::string> Arguments;
+ std::vector<std::string> Command;
llvm::yaml::ScalarNode *File = nullptr;
- for (llvm::yaml::MappingNode::iterator KVI = Object->begin(),
- KVE = Object->end();
- KVI != KVE; ++KVI) {
- llvm::yaml::Node *Value = (*KVI).getValue();
+ bool ArgumentsFound = false;
+ bool CommandFound = false;
+ for (auto& NextKeyValue : *Object) {
+ llvm::yaml::ScalarNode *KeyString =
+ dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+ if (!KeyString) {
+ ErrorMessage = "Expected strings as key.";
+ return false;
+ }
+ SmallString<10> KeyStorage;
+ StringRef KeyValue = KeyString->getValue(KeyStorage);
+ llvm::yaml::Node *Value = NextKeyValue.getValue();
if (!Value) {
ErrorMessage = "Expected value.";
return false;
}
llvm::yaml::ScalarNode *ValueString =
dyn_cast<llvm::yaml::ScalarNode>(Value);
- if (!ValueString) {
- ErrorMessage = "Expected string as value.";
+ llvm::yaml::SequenceNode *SequenceString =
+ dyn_cast<llvm::yaml::SequenceNode>(Value);
+ if (KeyValue == "arguments" && !SequenceString) {
+ ErrorMessage = "Expected sequence as value.";
return false;
- }
- llvm::yaml::ScalarNode *KeyString =
- dyn_cast<llvm::yaml::ScalarNode>((*KVI).getKey());
- if (!KeyString) {
- ErrorMessage = "Expected strings as key.";
+ } else if (KeyValue != "arguments" && !ValueString) {
+ ErrorMessage = "Expected string as value.";
return false;
}
- SmallString<8> KeyStorage;
- if (KeyString->getValue(KeyStorage) == "directory") {
+ if (KeyValue == "directory") {
Directory = ValueString;
- } else if (KeyString->getValue(KeyStorage) == "command") {
- Command = ValueString;
- } else if (KeyString->getValue(KeyStorage) == "file") {
+ } else if (KeyValue == "arguments") {
+ for (auto& NextArgument : *SequenceString) {
+ SmallString<128> CommandStorage;
+ auto ValueString = dyn_cast<llvm::yaml::ScalarNode>(&NextArgument);
+
+ Arguments.push_back(ValueString->getValue(CommandStorage));
+ }
+ ArgumentsFound = true;
+ } else if (KeyValue == "command") {
+ SmallString<1024> CommandStorage;
+ // FIXME: Escape correctly:
+ Command = unescapeCommandLine(ValueString->getValue(CommandStorage));
+ CommandFound = true;
+ } else if (KeyValue == "file") {
File = ValueString;
} else {
ErrorMessage = ("Unknown key: \"" +
@@ -291,8 +306,8 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) {
ErrorMessage = "Missing key: \"file\".";
return false;
}
- if (!Command) {
- ErrorMessage = "Missing key: \"command\".";
+ if (!ArgumentsFound && !CommandFound) {
+ ErrorMessage = "Missing key: \"command\" or \"arguments\".";
return false;
}
if (!Directory) {
@@ -312,7 +327,7 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) {
llvm::sys::path::native(FileName, NativeFilePath);
}
IndexByFile[NativeFilePath].push_back(
- CompileCommandRef(Directory, Command));
+ CompileCommandRef(Directory, ArgumentsFound ? Arguments : Command));
MatchTrie.insert(NativeFilePath);
}
return true;