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