In the compilation database command must be escaped.  This can cause problems 
on some systems (Windows).  cmd is added as a list of command line arguments 
that will not be escaped.

http://reviews.llvm.org/D10365

Files:
  include/clang/Tooling/JSONCompilationDatabase.h
  lib/Tooling/JSONCompilationDatabase.cpp
  unittests/Tooling/CompilationDatabaseTest.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/Tooling/JSONCompilationDatabase.h
===================================================================
--- include/clang/Tooling/JSONCompilationDatabase.h
+++ include/clang/Tooling/JSONCompilationDatabase.h
@@ -94,7 +94,7 @@
   // Tuple (directory, commandline) where 'commandline' pointing to the
   // corresponding nodes in the YAML stream.
   typedef std::pair<llvm::yaml::ScalarNode*,
-                    llvm::yaml::ScalarNode*> CompileCommandRef;
+                    std::vector<std::string>> CompileCommandRef;
 
   /// \brief Converts the given array of CompileCommandRefs to CompileCommands.
   void getCommands(ArrayRef<CompileCommandRef> CommandsRef,
Index: lib/Tooling/JSONCompilationDatabase.cpp
===================================================================
--- lib/Tooling/JSONCompilationDatabase.cpp
+++ lib/Tooling/JSONCompilationDatabase.cpp
@@ -221,9 +221,8 @@
     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);
   }
 }
 
@@ -252,11 +251,20 @@
       return false;
     }
     llvm::yaml::ScalarNode *Directory = nullptr;
-    llvm::yaml::ScalarNode *Command = nullptr;
+    std::vector<std::string> Args;
+    bool CommandFound = false;
     llvm::yaml::ScalarNode *File = nullptr;
     for (llvm::yaml::MappingNode::iterator KVI = Object->begin(),
                                            KVE = Object->end();
          KVI != KVE; ++KVI) {
+      llvm::yaml::ScalarNode *KeyString =
+          dyn_cast<llvm::yaml::ScalarNode>((*KVI).getKey());
+      if (!KeyString) {
+        ErrorMessage = "Expected strings as key.";
+        return false;
+      }
+      SmallString<8> KeyStorage;
+      StringRef KeyValue = KeyString->getValue(KeyStorage);
       llvm::yaml::Node *Value = (*KVI).getValue();
       if (!Value) {
         ErrorMessage = "Expected value.";
@@ -264,23 +272,42 @@
       }
       llvm::yaml::ScalarNode *ValueString =
           dyn_cast<llvm::yaml::ScalarNode>(Value);
-      if (!ValueString) {
+      llvm::yaml::SequenceNode *SequenceString =
+          dyn_cast<llvm::yaml::SequenceNode>(Value);
+      if (KeyValue == "cmd" && !SequenceString) {
+        ErrorMessage = "Expected sequence as value.";
+        return false;
+      } else if (KeyValue != "cmd" && !ValueString) {
         ErrorMessage = "Expected string as value.";
         return false;
       }
-      llvm::yaml::ScalarNode *KeyString =
-          dyn_cast<llvm::yaml::ScalarNode>((*KVI).getKey());
-      if (!KeyString) {
-        ErrorMessage = "Expected strings as key.";
-        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 == "command") {
+        if (CommandFound) {
+          ErrorMessage = "Multiple command and cmd found";
+          return false;
+        }
+        SmallString<1024> CommandStorage;
+        // FIXME: Escape correctly:
+        Args = unescapeCommandLine(ValueString->getValue(CommandStorage));
+        CommandFound = true;
+      } else if (KeyValue == "file") {
         File = ValueString;
+      } else if (KeyValue == "cmd") {
+        if (CommandFound) {
+          ErrorMessage = "Multiple command and cmd found";
+          return false;
+        }
+        for (llvm::yaml::SequenceNode::iterator CI = SequenceString->begin(),
+          CE = SequenceString->end();
+          CI != CE; ++CI) {
+          SmallString<128> CommandStorage;
+          auto ValueString = dyn_cast<llvm::yaml::ScalarNode>(&*CI);
+
+          Args.push_back(ValueString->getValue(CommandStorage));
+        }
+        CommandFound = true;
       } else {
         ErrorMessage = ("Unknown key: \"" +
                         KeyString->getRawValue() + "\"").str();
@@ -291,8 +318,8 @@
       ErrorMessage = "Missing key: \"file\".";
       return false;
     }
-    if (!Command) {
-      ErrorMessage = "Missing key: \"command\".";
+    if (!CommandFound) {
+      ErrorMessage = "Missing key: \"command\" or \"cmd\".";
       return false;
     }
     if (!Directory) {
@@ -312,7 +339,7 @@
       llvm::sys::path::native(FileName, NativeFilePath);
     }
     IndexByFile[NativeFilePath].push_back(
-        CompileCommandRef(Directory, Command));
+        CompileCommandRef(Directory, Args));
     MatchTrie.insert(NativeFilePath);
   }
   return true;
Index: unittests/Tooling/CompilationDatabaseTest.cpp
===================================================================
--- unittests/Tooling/CompilationDatabaseTest.cpp
+++ unittests/Tooling/CompilationDatabaseTest.cpp
@@ -36,8 +36,13 @@
   expectFailure("[{[]:\"\"}]", "Incorrectly typed entry");
   expectFailure("[{}]", "Empty entry");
   expectFailure("[{\"directory\":\"\",\"command\":\"\"}]", "Missing file");
-  expectFailure("[{\"directory\":\"\",\"file\":\"\"}]", "Missing command");
+  expectFailure("[{\"directory\":\"\",\"file\":\"\"}]", "Missing command or cmd");
   expectFailure("[{\"command\":\"\",\"file\":\"\"}]", "Missing directory");
+  expectFailure("[{\"directory\":\"\",\"cmd\":[]}]", "Missing file");
+  expectFailure("[{\"cmd\":\"\",\"file\":\"\"}]", "Missing directory");
+  expectFailure("[{\"command\":\"\",\"cmd\":[],\"file\":\"\"}]", "Command and cmd");
+  expectFailure("[{\"directory\":\"\",\"cmd\":\"\",\"file\":\"\"}]", "Cmd not array");
+  expectFailure("[{\"directory\":\"\",\"command\":[],\"file\":\"\"}]", "Command not string");
 }
 
 static std::vector<std::string> getAllFiles(StringRef JSONDatabase,
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to