driver.cpp revision 226633
11556Srgrimes//===-- driver.cpp - Clang GCC-Compatible Driver --------------------------===//
21556Srgrimes//
31556Srgrimes//                     The LLVM Compiler Infrastructure
41556Srgrimes//
51556Srgrimes// This file is distributed under the University of Illinois Open Source
61556Srgrimes// License. See LICENSE.TXT for details.
71556Srgrimes//
81556Srgrimes//===----------------------------------------------------------------------===//
91556Srgrimes//
101556Srgrimes// This is the entry point to the clang driver; it is a thin wrapper
111556Srgrimes// for functionality in the Driver clang library.
121556Srgrimes//
131556Srgrimes//===----------------------------------------------------------------------===//
141556Srgrimes
151556Srgrimes#include "clang/Driver/Compilation.h"
161556Srgrimes#include "clang/Driver/Driver.h"
171556Srgrimes#include "clang/Driver/Option.h"
181556Srgrimes#include "clang/Frontend/DiagnosticOptions.h"
191556Srgrimes#include "clang/Frontend/TextDiagnosticPrinter.h"
201556Srgrimes
211556Srgrimes#include "llvm/ADT/ArrayRef.h"
221556Srgrimes#include "llvm/ADT/SmallString.h"
231556Srgrimes#include "llvm/ADT/SmallVector.h"
241556Srgrimes#include "llvm/ADT/OwningPtr.h"
251556Srgrimes#include "llvm/Config/config.h"
261556Srgrimes#include "llvm/Support/ErrorHandling.h"
271556Srgrimes#include "llvm/Support/FileSystem.h"
281556Srgrimes#include "llvm/Support/ManagedStatic.h"
291556Srgrimes#include "llvm/Support/MemoryBuffer.h"
301556Srgrimes#include "llvm/Support/PrettyStackTrace.h"
311556Srgrimes#include "llvm/Support/Regex.h"
321556Srgrimes#include "llvm/Support/Timer.h"
331556Srgrimes#include "llvm/Support/raw_ostream.h"
3436150Scharnier#include "llvm/Support/Host.h"
3536150Scharnier#include "llvm/Support/Path.h"
3636150Scharnier#include "llvm/Support/Program.h"
371556Srgrimes#include "llvm/Support/Signals.h"
3899110Sobrien#include "llvm/Support/TargetRegistry.h"
3999110Sobrien#include "llvm/Support/TargetSelect.h"
401556Srgrimes#include "llvm/Support/system_error.h"
41100437Stjr#include <cctype>
4217987Speterusing namespace clang;
43102576Skeramidausing namespace clang::driver;
4417987Speter
45153091Sstefanfllvm::sys::Path GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) {
4645266Scracauer  if (!CanonicalPrefixes)
4753891Scracauer    return llvm::sys::Path(Argv0);
4817987Speter
491556Srgrimes  // This just needs to be some symbol in the binary; C++ doesn't
501556Srgrimes  // allow taking the address of ::main however.
511556Srgrimes  void *P = (void*) (intptr_t) GetExecutablePath;
521556Srgrimes  return llvm::sys::Path::GetMainExecutable(Argv0, P);
531556Srgrimes}
541556Srgrimes
551556Srgrimesstatic const char *SaveStringInSet(std::set<std::string> &SavedStrings,
561556Srgrimes                                   StringRef S) {
571556Srgrimes  return SavedStrings.insert(S).first->c_str();
581556Srgrimes}
591556Srgrimes
601556Srgrimes/// ApplyQAOverride - Apply a list of edits to the input argument lists.
611556Srgrimes///
621556Srgrimes/// The input string is a space separate list of edits to perform,
631556Srgrimes/// they are applied in order to the input argument lists. Edits
641556Srgrimes/// should be one of the following forms:
651556Srgrimes///
661556Srgrimes///  '#': Silence information about the changes to the command line arguments.
671556Srgrimes///
681556Srgrimes///  '^': Add FOO as a new argument at the beginning of the command line.
691556Srgrimes///
7017987Speter///  '+': Add FOO as a new argument at the end of the command line.
711556Srgrimes///
7217987Speter///  's/XXX/YYY/': Substitute the regular expression XXX with YYY in the command
731556Srgrimes///  line.
7417987Speter///
751556Srgrimes///  'xOPTION': Removes all instances of the literal argument OPTION.
761556Srgrimes///
77201053Sjilles///  'XOPTION': Removes all instances of the literal argument OPTION,
78213760Sobrien///  and the following argument.
791556Srgrimes///
801556Srgrimes///  'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox'
81213760Sobrien///  at the end of the command line.
821556Srgrimes///
831556Srgrimes/// \param OS - The stream to write edit information to.
841556Srgrimes/// \param Args - The vector of command line arguments.
851556Srgrimes/// \param Edit - The override command to perform.
861556Srgrimes/// \param SavedStrings - Set to use for storing string representations.
8717987Speterstatic void ApplyOneQAOverride(raw_ostream &OS,
881556Srgrimes                               SmallVectorImpl<const char*> &Args,
891556Srgrimes                               StringRef Edit,
90213811Sobrien                               std::set<std::string> &SavedStrings) {
91213811Sobrien  // This does not need to be efficient.
92213811Sobrien
93213811Sobrien  if (Edit[0] == '^') {
94213811Sobrien    const char *Str =
95213811Sobrien      SaveStringInSet(SavedStrings, Edit.substr(1));
96213811Sobrien    OS << "### Adding argument " << Str << " at beginning\n";
97213811Sobrien    Args.insert(Args.begin() + 1, Str);
98213811Sobrien  } else if (Edit[0] == '+') {
991556Srgrimes    const char *Str =
1001556Srgrimes      SaveStringInSet(SavedStrings, Edit.substr(1));
1011556Srgrimes    OS << "### Adding argument " << Str << " at end\n";
1021556Srgrimes    Args.push_back(Str);
1031556Srgrimes  } else if (Edit[0] == 's' && Edit[1] == '/' && Edit.endswith("/") &&
1041556Srgrimes             Edit.slice(2, Edit.size()-1).find('/') != StringRef::npos) {
1051556Srgrimes    StringRef MatchPattern = Edit.substr(2).split('/').first;
1061556Srgrimes    StringRef ReplPattern = Edit.substr(2).split('/').second;
1071556Srgrimes    ReplPattern = ReplPattern.slice(0, ReplPattern.size()-1);
1081556Srgrimes
1091556Srgrimes    for (unsigned i = 1, e = Args.size(); i != e; ++i) {
1101556Srgrimes      std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]);
1111556Srgrimes
1121556Srgrimes      if (Repl != Args[i]) {
1131556Srgrimes        OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n";
1141556Srgrimes        Args[i] = SaveStringInSet(SavedStrings, Repl);
1151556Srgrimes      }
1161556Srgrimes    }
1171556Srgrimes  } else if (Edit[0] == 'x' || Edit[0] == 'X') {
1181556Srgrimes    std::string Option = Edit.substr(1, std::string::npos);
1191556Srgrimes    for (unsigned i = 1; i < Args.size();) {
1201556Srgrimes      if (Option == Args[i]) {
1211556Srgrimes        OS << "### Deleting argument " << Args[i] << '\n';
12246684Skris        Args.erase(Args.begin() + i);
1231556Srgrimes        if (Edit[0] == 'X') {
1241556Srgrimes          if (i < Args.size()) {
12517987Speter            OS << "### Deleting argument " << Args[i] << '\n';
12690111Simp            Args.erase(Args.begin() + i);
1271556Srgrimes          } else
1281556Srgrimes            OS << "### Invalid X edit, end of command line!\n";
1291556Srgrimes        }
1301556Srgrimes      } else
1311556Srgrimes        ++i;
1321556Srgrimes    }
1331556Srgrimes  } else if (Edit[0] == 'O') {
1341556Srgrimes    for (unsigned i = 1; i < Args.size();) {
1351556Srgrimes      const char *A = Args[i];
1361556Srgrimes      if (A[0] == '-' && A[1] == 'O' &&
1371556Srgrimes          (A[2] == '\0' ||
1381556Srgrimes           (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' ||
1391556Srgrimes                             ('0' <= A[2] && A[2] <= '9'))))) {
1401556Srgrimes        OS << "### Deleting argument " << Args[i] << '\n';
1411556Srgrimes        Args.erase(Args.begin() + i);
1421556Srgrimes      } else
1431556Srgrimes        ++i;
1441556Srgrimes    }
1451556Srgrimes    OS << "### Adding argument " << Edit << " at end\n";
1461556Srgrimes    Args.push_back(SaveStringInSet(SavedStrings, '-' + Edit.str()));
147193169Sstefanf  } else {
148210829Sjilles    OS << "### Unrecognized edit: " << Edit << "\n";
149210829Sjilles  }
1501556Srgrimes}
1511556Srgrimes
1521556Srgrimes/// ApplyQAOverride - Apply a comma separate list of edits to the
1531556Srgrimes/// input argument lists. See ApplyOneQAOverride.
1541556Srgrimesstatic void ApplyQAOverride(SmallVectorImpl<const char*> &Args,
1551556Srgrimes                            const char *OverrideStr,
1561556Srgrimes                            std::set<std::string> &SavedStrings) {
1571556Srgrimes  raw_ostream *OS = &llvm::errs();
1581556Srgrimes
159193169Sstefanf  if (OverrideStr[0] == '#') {
16090111Simp    ++OverrideStr;
1611556Srgrimes    OS = &llvm::nulls();
1621556Srgrimes  }
163194128Sjilles
164210829Sjilles  *OS << "### QA_OVERRIDE_GCC3_OPTIONS: " << OverrideStr << "\n";
1651556Srgrimes
166194128Sjilles  // This does not need to be efficient.
167194128Sjilles
168210829Sjilles  const char *S = OverrideStr;
1691556Srgrimes  while (*S) {
1701556Srgrimes    const char *End = ::strchr(S, ' ');
1711556Srgrimes    if (!End)
172194128Sjilles      End = S + strlen(S);
173194128Sjilles    if (End != S)
174194128Sjilles      ApplyOneQAOverride(*OS, Args, std::string(S, End), SavedStrings);
175194128Sjilles    S = End;
176194128Sjilles    if (*S != '\0')
177210829Sjilles      ++S;
178194128Sjilles  }
1791556Srgrimes}
1801556Srgrimes
1811556Srgrimesextern int cc1_main(const char **ArgBegin, const char **ArgEnd,
1821556Srgrimes                    const char *Argv0, void *MainAddr);
183210829Sjillesextern int cc1as_main(const char **ArgBegin, const char **ArgEnd,
184210829Sjilles                      const char *Argv0, void *MainAddr);
185194128Sjilles
186194128Sjillesstatic void ExpandArgsFromBuf(const char *Arg,
1871556Srgrimes                              SmallVectorImpl<const char*> &ArgVector,
1881556Srgrimes                              std::set<std::string> &SavedStrings) {
1891556Srgrimes  const char *FName = Arg + 1;
1901556Srgrimes  llvm::OwningPtr<llvm::MemoryBuffer> MemBuf;
1911556Srgrimes  if (llvm::MemoryBuffer::getFile(FName, MemBuf)) {
1921556Srgrimes    ArgVector.push_back(SaveStringInSet(SavedStrings, Arg));
1931556Srgrimes    return;
1941556Srgrimes  }
1951556Srgrimes
19690111Simp  const char *Buf = MemBuf->getBufferStart();
19717987Speter  char InQuote = ' ';
198149927Sstefanf  std::string CurArg;
199149927Sstefanf
200149927Sstefanf  for (const char *P = Buf; ; ++P) {
2011556Srgrimes    if (*P == '\0' || (isspace(*P) && InQuote == ' ')) {
2021556Srgrimes      if (!CurArg.empty()) {
2031556Srgrimes
2041556Srgrimes        if (CurArg[0] != '@') {
2051556Srgrimes          ArgVector.push_back(SaveStringInSet(SavedStrings, CurArg));
20617987Speter        } else {
2071556Srgrimes          ExpandArgsFromBuf(CurArg.c_str(), ArgVector, SavedStrings);
20817987Speter        }
209149802Sstefanf
2101556Srgrimes        CurArg = "";
2111556Srgrimes      }
212149932Sstefanf      if (*P == '\0')
2131556Srgrimes        break;
2141556Srgrimes      else
2151556Srgrimes        continue;
2161556Srgrimes    }
2171556Srgrimes
2181556Srgrimes    if (isspace(*P)) {
21918754Ssteve      if (InQuote != ' ')
2201556Srgrimes        CurArg.push_back(*P);
22118754Ssteve      continue;
2221556Srgrimes    }
2231556Srgrimes
2241556Srgrimes    if (*P == '"' || *P == '\'') {
2251556Srgrimes      if (InQuote == *P)
2261556Srgrimes        InQuote = ' ';
2271556Srgrimes      else if (InQuote == ' ')
2281556Srgrimes        InQuote = *P;
2291556Srgrimes      else
2301556Srgrimes        CurArg.push_back(*P);
231205154Sjilles      continue;
2321556Srgrimes    }
2331556Srgrimes
2341556Srgrimes    if (*P == '\\') {
235149927Sstefanf      ++P;
2361556Srgrimes      if (*P != '\0')
2371556Srgrimes        CurArg.push_back(*P);
2381556Srgrimes      continue;
2391556Srgrimes    }
2401556Srgrimes    CurArg.push_back(*P);
2411556Srgrimes  }
2421556Srgrimes}
2431556Srgrimes
24420425Sstevestatic void ExpandArgv(int argc, const char **argv,
2451556Srgrimes                       SmallVectorImpl<const char*> &ArgVector,
24617987Speter                       std::set<std::string> &SavedStrings) {
2471556Srgrimes  for (int i = 0; i < argc; ++i) {
24820425Ssteve    const char *Arg = argv[i];
24920425Ssteve    if (Arg[0] != '@') {
2501556Srgrimes      ArgVector.push_back(SaveStringInSet(SavedStrings, std::string(Arg)));
2511556Srgrimes      continue;
2521556Srgrimes    }
2531556Srgrimes
254149933Sstefanf    ExpandArgsFromBuf(Arg, ArgVector, SavedStrings);
2551556Srgrimes  }
2561556Srgrimes}
257149933Sstefanf
2581556Srgrimesstatic void ParseProgName(SmallVectorImpl<const char *> &ArgVector,
2591556Srgrimes                          std::set<std::string> &SavedStrings,
2601556Srgrimes                          Driver &TheDriver)
2611556Srgrimes{
2621556Srgrimes  // Try to infer frontend type and default target from the program name.
2631556Srgrimes
2641556Srgrimes  // suffixes[] contains the list of known driver suffixes.
2651556Srgrimes  // Suffixes are compared against the program name in order.
2661556Srgrimes  // If there is a match, the frontend type is updated as necessary (CPP/C++).
2671556Srgrimes  // If there is no match, a second round is done after stripping the last
2681556Srgrimes  // hyphen and everything following it. This allows using something like
2691556Srgrimes  // "clang++-2.9".
2701556Srgrimes
2711556Srgrimes  // If there is a match in either the first or second round,
2721556Srgrimes  // the function tries to identify a target as prefix. E.g.
273149927Sstefanf  // "x86_64-linux-clang" as interpreted as suffix "clang" with
2741556Srgrimes  // target prefix "x86_64-linux". If such a target prefix is found,
2751556Srgrimes  // is gets added via -ccc-host-triple as implicit first argument.
2761556Srgrimes  static const struct {
277149927Sstefanf    const char *Suffix;
2781556Srgrimes    bool IsCXX;
2791556Srgrimes    bool IsCPP;
2801556Srgrimes  } suffixes [] = {
2811556Srgrimes    { "clang", false, false },
2821556Srgrimes    { "clang++", true, false },
2831556Srgrimes    { "clang-c++", true, false },
2841556Srgrimes    { "clang-cc", false, false },
2851556Srgrimes    { "clang-cpp", false, true },
2861556Srgrimes    { "clang-g++", true, false },
287149927Sstefanf    { "clang-gcc", false, false },
2881556Srgrimes    { "cc", false, false },
2891556Srgrimes    { "cpp", false, true },
2901556Srgrimes    { "++", true, false },
2911556Srgrimes  };
292213811Sobrien  std::string ProgName(llvm::sys::path::stem(ArgVector[0]));
293149933Sstefanf  StringRef ProgNameRef(ProgName);
29417987Speter  StringRef Prefix;
2951556Srgrimes
2961556Srgrimes  for (int Components = 2; Components; --Components) {
2971556Srgrimes    bool FoundMatch = false;
2981556Srgrimes    size_t i;
2991556Srgrimes
3001556Srgrimes    for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) {
3011556Srgrimes      if (ProgNameRef.endswith(suffixes[i].Suffix)) {
3021556Srgrimes        FoundMatch = true;
3031556Srgrimes        if (suffixes[i].IsCXX)
3041556Srgrimes          TheDriver.CCCIsCXX = true;
3051556Srgrimes        if (suffixes[i].IsCPP)
3061556Srgrimes          TheDriver.CCCIsCPP = true;
3071556Srgrimes        break;
308212475Sjilles      }
309212475Sjilles    }
3101556Srgrimes
3111556Srgrimes    if (FoundMatch) {
3121556Srgrimes      StringRef::size_type LastComponent = ProgNameRef.rfind('-',
3131556Srgrimes        ProgNameRef.size() - strlen(suffixes[i].Suffix));
3141556Srgrimes      if (LastComponent != StringRef::npos)
3151556Srgrimes        Prefix = ProgNameRef.slice(0, LastComponent);
3161556Srgrimes      break;
3171556Srgrimes    }
3181556Srgrimes
319149933Sstefanf    StringRef::size_type LastComponent = ProgNameRef.rfind('-');
3201556Srgrimes    if (LastComponent == StringRef::npos)
3211556Srgrimes      break;
3221556Srgrimes    ProgNameRef = ProgNameRef.slice(0, LastComponent);
3231556Srgrimes  }
3241556Srgrimes
3251556Srgrimes  if (Prefix.empty())
3261556Srgrimes    return;
3271556Srgrimes
3281556Srgrimes  std::string IgnoredError;
3291556Srgrimes  if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) {
330213811Sobrien    SmallVectorImpl<const char *>::iterator it = ArgVector.begin();
331149933Sstefanf    if (it != ArgVector.end())
33217987Speter      ++it;
3331556Srgrimes    ArgVector.insert(it, SaveStringInSet(SavedStrings, Prefix));
3341556Srgrimes    ArgVector.insert(it,
3351556Srgrimes      SaveStringInSet(SavedStrings, std::string("-ccc-host-triple")));
3361556Srgrimes  }
3371556Srgrimes}
3381556Srgrimes
3391556Srgrimesint main(int argc_, const char **argv_) {
3401556Srgrimes  llvm::sys::PrintStackTraceOnErrorSignal();
34117987Speter  llvm::PrettyStackTraceProgram X(argc_, argv_);
3421556Srgrimes
3431556Srgrimes  std::set<std::string> SavedStrings;
3441556Srgrimes  SmallVector<const char*, 256> argv;
3451556Srgrimes
3461556Srgrimes  ExpandArgv(argc_, argv_, argv, SavedStrings);
3471556Srgrimes
3481556Srgrimes  // Handle -cc1 integrated tools.
3491556Srgrimes  if (argv.size() > 1 && StringRef(argv[1]).startswith("-cc1")) {
3501556Srgrimes    StringRef Tool = argv[1] + 4;
3511556Srgrimes
352149933Sstefanf    if (Tool == "")
3531556Srgrimes      return cc1_main(argv.data()+2, argv.data()+argv.size(), argv[0],
3541556Srgrimes                      (void*) (intptr_t) GetExecutablePath);
3551556Srgrimes    if (Tool == "as")
3561556Srgrimes      return cc1as_main(argv.data()+2, argv.data()+argv.size(), argv[0],
3571556Srgrimes                      (void*) (intptr_t) GetExecutablePath);
3581556Srgrimes
3591556Srgrimes    // Reject unknown tools.
3601556Srgrimes    llvm::errs() << "error: unknown integrated tool '" << Tool << "'\n";
3611556Srgrimes    return 1;
3621556Srgrimes  }
3631556Srgrimes
3641556Srgrimes  bool CanonicalPrefixes = true;
3651556Srgrimes  for (int i = 1, size = argv.size(); i < size; ++i) {
3661556Srgrimes    if (StringRef(argv[i]) == "-no-canonical-prefixes") {
3671556Srgrimes      CanonicalPrefixes = false;
3681556Srgrimes      break;
3691556Srgrimes    }
370213811Sobrien  }
37190111Simp
37217987Speter  llvm::sys::Path Path = GetExecutablePath(argv[0], CanonicalPrefixes);
3731556Srgrimes
3741556Srgrimes  TextDiagnosticPrinter *DiagClient
3751556Srgrimes    = new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions());
3761556Srgrimes  DiagClient->setPrefix(llvm::sys::path::stem(Path.str()));
3771556Srgrimes  llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
3781556Srgrimes  DiagnosticsEngine Diags(DiagID, DiagClient);
3791556Srgrimes
38017987Speter#ifdef CLANG_IS_PRODUCTION
381172440Sstefanf  const bool IsProduction = true;
3821556Srgrimes#else
3831556Srgrimes  const bool IsProduction = false;
3841556Srgrimes#endif
3851556Srgrimes  Driver TheDriver(Path.str(), llvm::sys::getHostTriple(),
3861556Srgrimes                   "a.out", IsProduction, Diags);
3871556Srgrimes
3881556Srgrimes  // Attempt to find the original path used to invoke the driver, to determine
3891556Srgrimes  // the installed path. We do this manually, because we want to support that
3901556Srgrimes  // path being a symlink.
3911556Srgrimes  {
3921556Srgrimes    llvm::SmallString<128> InstalledPath(argv[0]);
3931556Srgrimes
3941556Srgrimes    // Do a PATH lookup, if there are no directory components.
3951556Srgrimes    if (llvm::sys::path::filename(InstalledPath) == InstalledPath) {
3961556Srgrimes      llvm::sys::Path Tmp = llvm::sys::Program::FindProgramByName(
3971556Srgrimes        llvm::sys::path::filename(InstalledPath.str()));
3981556Srgrimes      if (!Tmp.empty())
3991556Srgrimes        InstalledPath = Tmp.str();
4001556Srgrimes    }
4011556Srgrimes    llvm::sys::fs::make_absolute(InstalledPath);
4021556Srgrimes    InstalledPath = llvm::sys::path::parent_path(InstalledPath);
403213811Sobrien    bool exists;
40490111Simp    if (!llvm::sys::fs::exists(InstalledPath.str(), exists) && exists)
40517987Speter      TheDriver.setInstalledDir(InstalledPath);
4061556Srgrimes  }
4071556Srgrimes
4081556Srgrimes  llvm::InitializeAllTargets();
4091556Srgrimes  ParseProgName(argv, SavedStrings, TheDriver);
410194774Sjilles
411194774Sjilles  // Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE.
4121556Srgrimes  TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS");
4131556Srgrimes  if (TheDriver.CCPrintOptions)
4141556Srgrimes    TheDriver.CCPrintOptionsFilename = ::getenv("CC_PRINT_OPTIONS_FILE");
4151556Srgrimes
416201053Sjilles  // Handle CC_PRINT_HEADERS and CC_PRINT_HEADERS_FILE.
4171556Srgrimes  TheDriver.CCPrintHeaders = !!::getenv("CC_PRINT_HEADERS");
41845916Scracauer  if (TheDriver.CCPrintHeaders)
4191556Srgrimes    TheDriver.CCPrintHeadersFilename = ::getenv("CC_PRINT_HEADERS_FILE");
4201556Srgrimes
4211556Srgrimes  // Handle CC_LOG_DIAGNOSTICS and CC_LOG_DIAGNOSTICS_FILE.
4221556Srgrimes  TheDriver.CCLogDiagnostics = !!::getenv("CC_LOG_DIAGNOSTICS");
4231556Srgrimes  if (TheDriver.CCLogDiagnostics)
424205154Sjilles    TheDriver.CCLogDiagnosticsFilename = ::getenv("CC_LOG_DIAGNOSTICS_FILE");
425205154Sjilles
426205154Sjilles  // Handle QA_OVERRIDE_GCC3_OPTIONS and CCC_ADD_ARGS, used for editing a
4271556Srgrimes  // command line behind the scenes.
428213811Sobrien  if (const char *OverrideStr = ::getenv("QA_OVERRIDE_GCC3_OPTIONS")) {
429205154Sjilles    // FIXME: Driver shouldn't take extra initial argument.
430205154Sjilles    ApplyQAOverride(argv, OverrideStr, SavedStrings);
431205154Sjilles  } else if (const char *Cur = ::getenv("CCC_ADD_ARGS")) {
432205154Sjilles    // FIXME: Driver shouldn't take extra initial argument.
433205154Sjilles    std::vector<const char*> ExtraArgs;
434205154Sjilles
435205154Sjilles    for (;;) {
436205154Sjilles      const char *Next = strchr(Cur, ',');
437205154Sjilles
438205154Sjilles      if (Next) {
439205154Sjilles        ExtraArgs.push_back(SaveStringInSet(SavedStrings,
440205154Sjilles                                            std::string(Cur, Next)));
441205154Sjilles        Cur = Next + 1;
442205154Sjilles      } else {
443205154Sjilles        if (*Cur != '\0')
444205154Sjilles          ExtraArgs.push_back(SaveStringInSet(SavedStrings, Cur));
445205154Sjilles        break;
446205154Sjilles      }
447205154Sjilles    }
448205154Sjilles
449205154Sjilles    argv.insert(&argv[1], ExtraArgs.begin(), ExtraArgs.end());
450205154Sjilles  }
451205154Sjilles
452205154Sjilles  llvm::OwningPtr<Compilation> C(TheDriver.BuildCompilation(argv));
453205154Sjilles  int Res = 0;
454205154Sjilles  const Command *FailingCommand = 0;
455205154Sjilles  if (C.get())
456205154Sjilles    Res = TheDriver.ExecuteCompilation(*C, FailingCommand);
457205154Sjilles
458205154Sjilles  // If result status is < 0, then the driver command signalled an error.
459205154Sjilles  // In this case, generate additional diagnostic information if possible.
460205154Sjilles  if (Res < 0)
461205154Sjilles    TheDriver.generateCompilationDiagnostics(*C, FailingCommand);
462205154Sjilles
463205154Sjilles  // If any timers were active but haven't been destroyed yet, print their
464205154Sjilles  // results now.  This happens in -disable-free mode.
4651556Srgrimes  llvm::TimerGroup::printAll(llvm::errs());
4661556Srgrimes
4671556Srgrimes  llvm::llvm_shutdown();
4681556Srgrimes
469213811Sobrien  return Res;
47090111Simp}
47117987Speter