Currently, if --driver-mode is not passed at all, it will default
to GCC style driver. This is never an issue for clang because
it manually constructs a --driver-mode option and passes it.
However, we should still try to do as good as we can even if no
--driver-mode is passed. LibTooling, for example, does not pass
a --driver-mode option and while it could, it seems like we should
still fallback to the best possible default we can.
This is one of two steps necessary to get clang-tidy working on Windows.
Reviewed By: rnk
Differential Revision: https://reviews.llvm.org/D23454
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@278535
91177308-0d34-0410-b5e6-
96231b3b80d8
/// Whether the driver is just the preprocessor.
bool CCCIsCPP() const { return Mode == CPPMode; }
+ /// Whether the driver should follow gcc like behavior.
+ bool CCCIsCC() const { return Mode == GCCMode; }
+
/// Whether the driver should follow cl.exe like behavior.
bool IsCLMode() const { return Mode == CLMode; }
/// @{
/// 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.
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);
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) {
// We look for the driver mode option early, because the mode can affect
// how other options are parsed.
- ParseDriverMode(ArgList.slice(1));
+ ParseDriverMode(ClangExecutable, ArgList.slice(1));
// FIXME: What are we going to do with -V and -b?
S);
}
+TEST(ToolChainTest, DefaultDriverMode) {
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ struct TestDiagnosticConsumer : public DiagnosticConsumer {};
+ DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer);
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new vfs::InMemoryFileSystem);
+
+ Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,
+ InMemoryFileSystem);
+ Driver CXXDriver("/home/test/bin/clang++", "arm-linux-gnueabi", Diags,
+ InMemoryFileSystem);
+ Driver CLDriver("/home/test/bin/clang-cl", "arm-linux-gnueabi", Diags,
+ InMemoryFileSystem);
+
+ std::unique_ptr<Compilation> CC(CCDriver.BuildCompilation({"foo.cpp"}));
+ std::unique_ptr<Compilation> CXX(CXXDriver.BuildCompilation({"foo.cpp"}));
+ std::unique_ptr<Compilation> CL(CLDriver.BuildCompilation({"foo.cpp"}));
+
+ EXPECT_TRUE(CCDriver.CCCIsCC());
+ EXPECT_TRUE(CXXDriver.CCCIsCXX());
+ EXPECT_TRUE(CLDriver.IsCLMode());
+}
+
} // end anonymous namespace