summaryrefslogtreecommitdiffstats
path: root/tools/driver/driver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/driver/driver.cpp')
-rw-r--r--tools/driver/driver.cpp160
1 files changed, 123 insertions, 37 deletions
diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp
index c4b12cb..c058ece 100644
--- a/tools/driver/driver.cpp
+++ b/tools/driver/driver.cpp
@@ -19,15 +19,19 @@
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Config/config.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Host.h"
#include "llvm/System/Path.h"
+#include "llvm/System/Program.h"
#include "llvm/System/Signals.h"
using namespace clang;
using namespace clang::driver;
@@ -75,7 +79,7 @@ static const char *SaveStringInSet(std::set<std::string> &SavedStrings,
/// \param Edit - The override command to perform.
/// \param SavedStrings - Set to use for storing string representations.
static void ApplyOneQAOverride(llvm::raw_ostream &OS,
- std::vector<const char*> &Args,
+ llvm::SmallVectorImpl<const char*> &Args,
llvm::StringRef Edit,
std::set<std::string> &SavedStrings) {
// This does not need to be efficient.
@@ -141,7 +145,7 @@ static void ApplyOneQAOverride(llvm::raw_ostream &OS,
/// ApplyQAOverride - Apply a comma separate list of edits to the
/// input argument lists. See ApplyOneQAOverride.
-static void ApplyQAOverride(std::vector<const char*> &Args,
+static void ApplyQAOverride(llvm::SmallVectorImpl<const char*> &Args,
const char *OverrideStr,
std::set<std::string> &SavedStrings) {
llvm::raw_ostream *OS = &llvm::errs();
@@ -173,19 +177,97 @@ extern int cc1_main(const char **ArgBegin, const char **ArgEnd,
extern int cc1as_main(const char **ArgBegin, const char **ArgEnd,
const char *Argv0, void *MainAddr);
-int main(int argc, const char **argv) {
+static void ExpandArgsFromBuf(const char *Arg,
+ llvm::SmallVectorImpl<const char*> &ArgVector,
+ std::set<std::string> &SavedStrings) {
+ const char *FName = Arg + 1;
+ llvm::MemoryBuffer *MemBuf = llvm::MemoryBuffer::getFile(FName);
+ if (!MemBuf) {
+ ArgVector.push_back(SaveStringInSet(SavedStrings, Arg));
+ return;
+ }
+
+ const char *Buf = MemBuf->getBufferStart();
+ char InQuote = ' ';
+ std::string CurArg;
+
+ for (const char *P = Buf; ; ++P) {
+ if (*P == '\0' || (isspace(*P) && InQuote == ' ')) {
+ if (!CurArg.empty()) {
+
+ if (CurArg[0] != '@') {
+ ArgVector.push_back(SaveStringInSet(SavedStrings, CurArg));
+ } else {
+ ExpandArgsFromBuf(CurArg.c_str(), ArgVector, SavedStrings);
+ }
+
+ CurArg = "";
+ }
+ if (*P == '\0')
+ break;
+ else
+ continue;
+ }
+
+ if (isspace(*P)) {
+ if (InQuote != ' ')
+ CurArg.push_back(*P);
+ continue;
+ }
+
+ if (*P == '"' || *P == '\'') {
+ if (InQuote == *P)
+ InQuote = ' ';
+ else if (InQuote == ' ')
+ InQuote = *P;
+ else
+ CurArg.push_back(*P);
+ continue;
+ }
+
+ if (*P == '\\') {
+ ++P;
+ if (*P != '\0')
+ CurArg.push_back(*P);
+ continue;
+ }
+ CurArg.push_back(*P);
+ }
+ delete MemBuf;
+}
+
+static void ExpandArgv(int argc, const char **argv,
+ llvm::SmallVectorImpl<const char*> &ArgVector,
+ std::set<std::string> &SavedStrings) {
+ for (int i = 0; i < argc; ++i) {
+ const char *Arg = argv[i];
+ if (Arg[0] != '@') {
+ ArgVector.push_back(SaveStringInSet(SavedStrings, std::string(Arg)));
+ continue;
+ }
+
+ ExpandArgsFromBuf(Arg, ArgVector, SavedStrings);
+ }
+}
+
+int main(int argc_, const char **argv_) {
llvm::sys::PrintStackTraceOnErrorSignal();
- llvm::PrettyStackTraceProgram X(argc, argv);
+ llvm::PrettyStackTraceProgram X(argc_, argv_);
+
+ std::set<std::string> SavedStrings;
+ llvm::SmallVector<const char*, 256> argv;
+
+ ExpandArgv(argc_, argv_, argv, SavedStrings);
// Handle -cc1 integrated tools.
- if (argc > 1 && llvm::StringRef(argv[1]).startswith("-cc1")) {
+ if (argv.size() > 1 && llvm::StringRef(argv[1]).startswith("-cc1")) {
llvm::StringRef Tool = argv[1] + 4;
if (Tool == "")
- return cc1_main(argv+2, argv+argc, argv[0],
+ return cc1_main(argv.data()+2, argv.data()+argv.size(), argv[0],
(void*) (intptr_t) GetExecutablePath);
if (Tool == "as")
- return cc1as_main(argv+2, argv+argc, argv[0],
+ return cc1as_main(argv.data()+2, argv.data()+argv.size(), argv[0],
(void*) (intptr_t) GetExecutablePath);
// Reject unknown tools.
@@ -194,7 +276,7 @@ int main(int argc, const char **argv) {
}
bool CanonicalPrefixes = true;
- for (int i = 1; i < argc; ++i) {
+ for (int i = 1, size = argv.size(); i < size; ++i) {
if (llvm::StringRef(argv[i]) == "-no-canonical-prefixes") {
CanonicalPrefixes = false;
break;
@@ -203,10 +285,10 @@ int main(int argc, const char **argv) {
llvm::sys::Path Path = GetExecutablePath(argv[0], CanonicalPrefixes);
- TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions());
- DiagClient.setPrefix(Path.getBasename());
-
- Diagnostic Diags(&DiagClient);
+ TextDiagnosticPrinter *DiagClient
+ = new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions());
+ DiagClient->setPrefix(Path.getBasename());
+ Diagnostic Diags(DiagClient);
#ifdef CLANG_IS_PRODUCTION
const bool IsProduction = true;
@@ -219,11 +301,27 @@ int main(int argc, const char **argv) {
const bool IsProduction = false;
const bool CXXIsProduction = false;
#endif
- Driver TheDriver(Path.getBasename(), Path.getDirname(),
- llvm::sys::getHostTriple(),
+ Driver TheDriver(Path.str(), llvm::sys::getHostTriple(),
"a.out", IsProduction, CXXIsProduction,
Diags);
+ // Attempt to find the original path used to invoke the driver, to determine
+ // the installed path. We do this manually, because we want to support that
+ // path being a symlink.
+ llvm::sys::Path InstalledPath(argv[0]);
+
+ // Do a PATH lookup, if there are no directory components.
+ if (InstalledPath.getLast() == InstalledPath.str()) {
+ llvm::sys::Path Tmp =
+ llvm::sys::Program::FindProgramByName(InstalledPath.getLast());
+ if (!Tmp.empty())
+ InstalledPath = Tmp;
+ }
+ InstalledPath.makeAbsolute();
+ InstalledPath.eraseComponent();
+ if (InstalledPath.exists())
+ TheDriver.setInstalledDir(InstalledPath.str());
+
// Check for ".*++" or ".*++-[^-]*" to determine if we are a C++
// compiler. This matches things like "c++", "clang++", and "clang++-1.1".
//
@@ -231,15 +329,14 @@ int main(int argc, const char **argv) {
// being a symlink.
//
// We use *argv instead of argv[0] to work around a bogus g++ warning.
- std::string ProgName(llvm::sys::Path(*argv).getBasename());
+ const char *progname = argv_[0];
+ std::string ProgName(llvm::sys::Path(progname).getBasename());
if (llvm::StringRef(ProgName).endswith("++") ||
llvm::StringRef(ProgName).rsplit('-').first.endswith("++")) {
TheDriver.CCCIsCXX = true;
TheDriver.CCCGenericGCCName = "g++";
}
- llvm::OwningPtr<Compilation> C;
-
// Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE.
TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS");
if (TheDriver.CCPrintOptions)
@@ -247,46 +344,35 @@ int main(int argc, const char **argv) {
// Handle QA_OVERRIDE_GCC3_OPTIONS and CCC_ADD_ARGS, used for editing a
// command line behind the scenes.
- std::set<std::string> SavedStrings;
if (const char *OverrideStr = ::getenv("QA_OVERRIDE_GCC3_OPTIONS")) {
// FIXME: Driver shouldn't take extra initial argument.
- std::vector<const char*> StringPointers(argv, argv + argc);
-
- ApplyQAOverride(StringPointers, OverrideStr, SavedStrings);
-
- C.reset(TheDriver.BuildCompilation(StringPointers.size(),
- &StringPointers[0]));
+ ApplyQAOverride(argv, OverrideStr, SavedStrings);
} else if (const char *Cur = ::getenv("CCC_ADD_ARGS")) {
- std::vector<const char*> StringPointers;
-
// FIXME: Driver shouldn't take extra initial argument.
- StringPointers.push_back(argv[0]);
+ std::vector<const char*> ExtraArgs;
for (;;) {
const char *Next = strchr(Cur, ',');
if (Next) {
- StringPointers.push_back(SaveStringInSet(SavedStrings,
- std::string(Cur, Next)));
+ ExtraArgs.push_back(SaveStringInSet(SavedStrings,
+ std::string(Cur, Next)));
Cur = Next + 1;
} else {
if (*Cur != '\0')
- StringPointers.push_back(SaveStringInSet(SavedStrings, Cur));
+ ExtraArgs.push_back(SaveStringInSet(SavedStrings, Cur));
break;
}
}
- StringPointers.insert(StringPointers.end(), argv + 1, argv + argc);
-
- C.reset(TheDriver.BuildCompilation(StringPointers.size(),
- &StringPointers[0]));
- } else
- C.reset(TheDriver.BuildCompilation(argc, argv));
+ argv.insert(&argv[1], ExtraArgs.begin(), ExtraArgs.end());
+ }
+ llvm::OwningPtr<Compilation> C(TheDriver.BuildCompilation(argv.size(),
+ &argv[0]));
int Res = 0;
if (C.get())
Res = TheDriver.ExecuteCompilation(*C);
-
// If any timers were active but haven't been destroyed yet, print their
// results now. This happens in -disable-free mode.
OpenPOWER on IntegriCloud