Skip to content

Commit

Permalink
[Driver] Set the default driver mode based on the executable.
Browse files Browse the repository at this point in the history
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

llvm-svn: 278535
  • Loading branch information
Zachary Turner committed Aug 12, 2016
1 parent 0387872 commit aff19c3
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 19 deletions.
9 changes: 8 additions & 1 deletion clang/include/clang/Driver/Driver.h
Expand Up @@ -155,6 +155,9 @@ class Driver {
/// 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; }

Expand Down Expand Up @@ -291,7 +294,7 @@ class Driver {
/// @{

/// 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.
Expand Down Expand Up @@ -440,6 +443,10 @@ class Driver {
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);
Expand Down
44 changes: 26 additions & 18 deletions clang/lib/Driver/Driver.cpp
Expand Up @@ -88,31 +88,39 @@ Driver::~Driver() {
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) {
Expand Down Expand Up @@ -468,7 +476,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {

// 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?

Expand Down
25 changes: 25 additions & 0 deletions clang/unittests/Driver/ToolChainTest.cpp
Expand Up @@ -117,4 +117,29 @@ TEST(ToolChainTest, VFSGCCInstallationRelativeDir) {
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

0 comments on commit aff19c3

Please sign in to comment.