zturner created this revision.
zturner added reviewers: alexfh, djasper, rnk.
zturner added a subscriber: cfe-commits.
Herald added a subscriber: klimek.

Attempting to run clang-tidy with the clang-cl driver results in a number of 
warnings and errors that make the tool unusable.  The two main issues, and the 
solutions implemented here are:

  # Command lines are tokenized differently on Windows and non-windows 
platforms.  Using standard tokenization on Windows leads to -- among other 
things -- all path separators being stripped from paths.  Obviously this won't 
work, so the fix implemented here is to use the correct windows command line 
tokenizer when clang-tidy is running on Windows.
  # The underlying clang driver does not attempt to auto-detect driver mode 
(CL, GCC, etc) from the program name.  It relies only on the existence of a 
`--driver-mode=<mode>` option.  We already have a function to detect the driver 
mode based on the program name, so the solution implemented here is to use the 
program name as a default, which will be overridden by the existence of a 
`--driver-mode` option.

With this patch, clang-tidy runs with clang-cl.

```
D:\src\llvm\tools\lldb>d:\src\llvmbuild\ninja\bin\clang-tidy.exe source\lldb.cpp
1448 warnings generated.
warning: argument unused during compilation: '-mincremental-linker-compatible' 
[clang-diagnostic-unused-command-line-argument]
warning: unknown argument ignored in clang-cl: 
'-resource-dir=d:\src\llvmbuild\ninja\bin\..\lib\clang\4.0.0' 
[clang-diagnostic-unk
nown-argument]
D:\src\llvm\tools\lldb\source\lldb.cpp:71:24: warning: invalid case style for 
variable 'g_version_str' [readability-identifier-nam
ing]
    static std::string g_version_str;
                       ^
D:\src\llvm\tools\lldb\source\lldb.cpp:76:22: warning: invalid case style for 
variable 'lldb_repo' [readability-identifier-naming]

        const char * lldb_repo = GetLLDBRepository();
                     ^
D:\src\llvm\tools\lldb\source\lldb.cpp:83:21: warning: invalid case style for 
variable 'lldb_rev' [readability-identifier-naming]
        const char *lldb_rev = GetLLDBRevision();
                    ^
D:\src\llvm\tools\lldb\source\lldb.cpp:89:21: warning: invalid case style for 
variable 'clang_rev' [readability-identifier-naming]

        std::string clang_rev (clang::getClangRevision());
                    ^
D:\src\llvm\tools\lldb\source\lldb.cpp:95:21: warning: invalid case style for 
variable 'llvm_rev' [readability-identifier-naming]
        std::string llvm_rev (clang::getLLVMRevision());
                    ^
Suppressed 1441 warnings (1441 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use 
-system-headers to display errors from system headers as
well.
```

https://reviews.llvm.org/D23409

Files:
  include/clang/Driver/Driver.h
  lib/Driver/Driver.cpp
  lib/Tooling/JSONCompilationDatabase.cpp

Index: lib/Tooling/JSONCompilationDatabase.cpp
===================================================================
--- lib/Tooling/JSONCompilationDatabase.cpp
+++ 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 {
@@ -113,8 +116,17 @@
 
 std::vector<std::string> unescapeCommandLine(
     StringRef EscapedCommandLine) {
+#if defined(LLVM_ON_WIN32)
+  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;
+#else
   CommandLineArgumentParser parser(EscapedCommandLine);
   return parser.parse();
+#endif
 }
 
 class JSONCompilationDatabasePlugin : public CompilationDatabasePlugin {
Index: lib/Driver/Driver.cpp
===================================================================
--- lib/Driver/Driver.cpp
+++ lib/Driver/Driver.cpp
@@ -88,31 +88,39 @@
   llvm::DeleteContainerSeconds(ToolChains);
 }
 
-void Driver::ParseDriverMode(ArrayRef<const char *> Args) {
-  const std::string OptName =
-      getOpts().getOption(options::OPT_driver_mode).getPrefixedName();
+void Driver::ParseDriverMode(StringRef ProgramName,
+                             ArrayRef<const char *> Args) {
+  auto Default = ToolChain::getTargetAndModeFromProgramName(ProgramName);
+  StringRef DefaultMode(Default.second);
+  setDriverModeFromOption(DefaultMode);
 
   for (const char *ArgPtr : Args) {
     // Ingore nullptrs, they are response file's EOL markers
     if (ArgPtr == nullptr)
       continue;
     const StringRef Arg = ArgPtr;
-    if (!Arg.startswith(OptName))
-      continue;
+    setDriverModeFromOption(Arg);
+  }
+}
+
+void Driver::setDriverModeFromOption(StringRef Opt) {
+  const std::string OptName =
+      getOpts().getOption(options::OPT_driver_mode).getPrefixedName();
+  if (!Opt.startswith(OptName))
+    return;
+  StringRef Value = Opt.drop_front(OptName.size());
 
-    const StringRef Value = Arg.drop_front(OptName.size());
-    const unsigned M = llvm::StringSwitch<unsigned>(Value)
-                           .Case("gcc", GCCMode)
-                           .Case("g++", GXXMode)
-                           .Case("cpp", CPPMode)
-                           .Case("cl", CLMode)
-                           .Default(~0U);
+  const unsigned M = llvm::StringSwitch<unsigned>(Value)
+                         .Case("gcc", GCCMode)
+                         .Case("g++", GXXMode)
+                         .Case("cpp", CPPMode)
+                         .Case("cl", CLMode)
+                         .Default(~0U);
 
-    if (M != ~0U)
-      Mode = static_cast<DriverMode>(M);
-    else
-      Diag(diag::err_drv_unsupported_option_argument) << OptName << Value;
-  }
+  if (M != ~0U)
+    Mode = static_cast<DriverMode>(M);
+  else
+    Diag(diag::err_drv_unsupported_option_argument) << OptName << Value;
 }
 
 InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings) {
@@ -468,7 +476,7 @@
 
   // We look for the driver mode option early, because the mode can affect
   // how other options are parsed.
-  ParseDriverMode(ArgList.slice(1));
+  ParseDriverMode(ArgList[0], ArgList.slice(1));
 
   // FIXME: What are we going to do with -V and -b?
 
Index: include/clang/Driver/Driver.h
===================================================================
--- include/clang/Driver/Driver.h
+++ include/clang/Driver/Driver.h
@@ -291,7 +291,7 @@
   /// @{
 
   /// ParseDriverMode - Look for and handle the driver mode option in Args.
-  void ParseDriverMode(ArrayRef<const char *> Args);
+  void ParseDriverMode(StringRef ProgramName, ArrayRef<const char *> Args);
 
   /// ParseArgStrings - Parse the given list of strings into an
   /// ArgList.
@@ -440,6 +440,10 @@
   LTOKind getLTOMode() const { return LTOMode; }
 
 private:
+  /// Set the driver mode (cl, gcc, etc) from an option string of the form
+  /// --driver-mode=<mode>.
+  void setDriverModeFromOption(StringRef Opt);
+
   /// Parse the \p Args list for LTO options and record the type of LTO
   /// compilation based on which -f(no-)?lto(=.*)? option occurs last.
   void setLTOMode(const llvm::opt::ArgList &Args);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to