1193326Sed//===-- driver.cpp - Clang GCC-Compatible Driver --------------------------===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed//
10193326Sed// This is the entry point to the clang driver; it is a thin wrapper
11193326Sed// for functionality in the Driver clang library.
12193326Sed//
13193326Sed//===----------------------------------------------------------------------===//
14193326Sed
15252723Sdim#include "clang/Basic/CharInfo.h"
16245431Sdim#include "clang/Basic/DiagnosticOptions.h"
17193326Sed#include "clang/Driver/Compilation.h"
18193326Sed#include "clang/Driver/Driver.h"
19252723Sdim#include "clang/Driver/DriverDiagnostic.h"
20252723Sdim#include "clang/Driver/Options.h"
21235633Sdim#include "clang/Frontend/CompilerInvocation.h"
22204643Srdivacky#include "clang/Frontend/TextDiagnosticPrinter.h"
23235633Sdim#include "clang/Frontend/Utils.h"
24221345Sdim#include "llvm/ADT/ArrayRef.h"
25252723Sdim#include "llvm/ADT/OwningPtr.h"
26193326Sed#include "llvm/ADT/SmallString.h"
27212904Sdim#include "llvm/ADT/SmallVector.h"
28263509Sdim#include "llvm/ADT/STLExtras.h"
29263509Sdim#include "llvm/Option/ArgList.h"
30263509Sdim#include "llvm/Option/OptTable.h"
31263509Sdim#include "llvm/Option/Option.h"
32263509Sdim#include "llvm/Support/CommandLine.h"
33212904Sdim#include "llvm/Support/ErrorHandling.h"
34218893Sdim#include "llvm/Support/FileSystem.h"
35252723Sdim#include "llvm/Support/Host.h"
36193326Sed#include "llvm/Support/ManagedStatic.h"
37212904Sdim#include "llvm/Support/MemoryBuffer.h"
38252723Sdim#include "llvm/Support/Path.h"
39193326Sed#include "llvm/Support/PrettyStackTrace.h"
40263509Sdim#include "llvm/Support/Process.h"
41252723Sdim#include "llvm/Support/Program.h"
42204643Srdivacky#include "llvm/Support/Regex.h"
43218893Sdim#include "llvm/Support/Signals.h"
44226890Sdim#include "llvm/Support/TargetRegistry.h"
45226890Sdim#include "llvm/Support/TargetSelect.h"
46252723Sdim#include "llvm/Support/Timer.h"
47252723Sdim#include "llvm/Support/raw_ostream.h"
48218893Sdim#include "llvm/Support/system_error.h"
49193326Sedusing namespace clang;
50193326Sedusing namespace clang::driver;
51263509Sdimusing namespace llvm::opt;
52193326Sed
53263509Sdimstd::string GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) {
54200583Srdivacky  if (!CanonicalPrefixes)
55263509Sdim    return Argv0;
56200583Srdivacky
57193326Sed  // This just needs to be some symbol in the binary; C++ doesn't
58193326Sed  // allow taking the address of ::main however.
59193326Sed  void *P = (void*) (intptr_t) GetExecutablePath;
60263509Sdim  return llvm::sys::fs::getMainExecutable(Argv0, P);
61193326Sed}
62193326Sed
63198092Srdivackystatic const char *SaveStringInSet(std::set<std::string> &SavedStrings,
64226890Sdim                                   StringRef S) {
65193326Sed  return SavedStrings.insert(S).first->c_str();
66193326Sed}
67193326Sed
68193326Sed/// ApplyQAOverride - Apply a list of edits to the input argument lists.
69193326Sed///
70193326Sed/// The input string is a space separate list of edits to perform,
71193326Sed/// they are applied in order to the input argument lists. Edits
72193326Sed/// should be one of the following forms:
73193326Sed///
74198092Srdivacky///  '#': Silence information about the changes to the command line arguments.
75198092Srdivacky///
76193326Sed///  '^': Add FOO as a new argument at the beginning of the command line.
77193326Sed///
78193326Sed///  '+': Add FOO as a new argument at the end of the command line.
79193326Sed///
80204643Srdivacky///  's/XXX/YYY/': Substitute the regular expression XXX with YYY in the command
81204643Srdivacky///  line.
82193326Sed///
83193326Sed///  'xOPTION': Removes all instances of the literal argument OPTION.
84193326Sed///
85193326Sed///  'XOPTION': Removes all instances of the literal argument OPTION,
86193326Sed///  and the following argument.
87193326Sed///
88193326Sed///  'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox'
89193326Sed///  at the end of the command line.
90198092Srdivacky///
91198092Srdivacky/// \param OS - The stream to write edit information to.
92198092Srdivacky/// \param Args - The vector of command line arguments.
93198092Srdivacky/// \param Edit - The override command to perform.
94198092Srdivacky/// \param SavedStrings - Set to use for storing string representations.
95226890Sdimstatic void ApplyOneQAOverride(raw_ostream &OS,
96226890Sdim                               SmallVectorImpl<const char*> &Args,
97226890Sdim                               StringRef Edit,
98206084Srdivacky                               std::set<std::string> &SavedStrings) {
99193326Sed  // This does not need to be efficient.
100193326Sed
101198092Srdivacky  if (Edit[0] == '^') {
102198092Srdivacky    const char *Str =
103204643Srdivacky      SaveStringInSet(SavedStrings, Edit.substr(1));
104198092Srdivacky    OS << "### Adding argument " << Str << " at beginning\n";
105198092Srdivacky    Args.insert(Args.begin() + 1, Str);
106198092Srdivacky  } else if (Edit[0] == '+') {
107198092Srdivacky    const char *Str =
108204643Srdivacky      SaveStringInSet(SavedStrings, Edit.substr(1));
109198092Srdivacky    OS << "### Adding argument " << Str << " at end\n";
110198092Srdivacky    Args.push_back(Str);
111204643Srdivacky  } else if (Edit[0] == 's' && Edit[1] == '/' && Edit.endswith("/") &&
112226890Sdim             Edit.slice(2, Edit.size()-1).find('/') != StringRef::npos) {
113226890Sdim    StringRef MatchPattern = Edit.substr(2).split('/').first;
114226890Sdim    StringRef ReplPattern = Edit.substr(2).split('/').second;
115204643Srdivacky    ReplPattern = ReplPattern.slice(0, ReplPattern.size()-1);
116204643Srdivacky
117204643Srdivacky    for (unsigned i = 1, e = Args.size(); i != e; ++i) {
118204643Srdivacky      std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]);
119204643Srdivacky
120204643Srdivacky      if (Repl != Args[i]) {
121204643Srdivacky        OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n";
122204643Srdivacky        Args[i] = SaveStringInSet(SavedStrings, Repl);
123204643Srdivacky      }
124204643Srdivacky    }
125198092Srdivacky  } else if (Edit[0] == 'x' || Edit[0] == 'X') {
126198092Srdivacky    std::string Option = Edit.substr(1, std::string::npos);
127198092Srdivacky    for (unsigned i = 1; i < Args.size();) {
128198092Srdivacky      if (Option == Args[i]) {
129198092Srdivacky        OS << "### Deleting argument " << Args[i] << '\n';
130198092Srdivacky        Args.erase(Args.begin() + i);
131198092Srdivacky        if (Edit[0] == 'X') {
132198092Srdivacky          if (i < Args.size()) {
133198092Srdivacky            OS << "### Deleting argument " << Args[i] << '\n';
134198092Srdivacky            Args.erase(Args.begin() + i);
135198092Srdivacky          } else
136198092Srdivacky            OS << "### Invalid X edit, end of command line!\n";
137198092Srdivacky        }
138198092Srdivacky      } else
139198092Srdivacky        ++i;
140198092Srdivacky    }
141198092Srdivacky  } else if (Edit[0] == 'O') {
142198092Srdivacky    for (unsigned i = 1; i < Args.size();) {
143198092Srdivacky      const char *A = Args[i];
144198092Srdivacky      if (A[0] == '-' && A[1] == 'O' &&
145198092Srdivacky          (A[2] == '\0' ||
146198092Srdivacky           (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' ||
147198092Srdivacky                             ('0' <= A[2] && A[2] <= '9'))))) {
148198092Srdivacky        OS << "### Deleting argument " << Args[i] << '\n';
149198092Srdivacky        Args.erase(Args.begin() + i);
150198092Srdivacky      } else
151198092Srdivacky        ++i;
152198092Srdivacky    }
153198092Srdivacky    OS << "### Adding argument " << Edit << " at end\n";
154204643Srdivacky    Args.push_back(SaveStringInSet(SavedStrings, '-' + Edit.str()));
155198092Srdivacky  } else {
156198092Srdivacky    OS << "### Unrecognized edit: " << Edit << "\n";
157198092Srdivacky  }
158193326Sed}
159193326Sed
160193326Sed/// ApplyQAOverride - Apply a comma separate list of edits to the
161193326Sed/// input argument lists. See ApplyOneQAOverride.
162226890Sdimstatic void ApplyQAOverride(SmallVectorImpl<const char*> &Args,
163206084Srdivacky                            const char *OverrideStr,
164206084Srdivacky                            std::set<std::string> &SavedStrings) {
165226890Sdim  raw_ostream *OS = &llvm::errs();
166193326Sed
167198092Srdivacky  if (OverrideStr[0] == '#') {
168198092Srdivacky    ++OverrideStr;
169198092Srdivacky    OS = &llvm::nulls();
170198092Srdivacky  }
171198092Srdivacky
172198092Srdivacky  *OS << "### QA_OVERRIDE_GCC3_OPTIONS: " << OverrideStr << "\n";
173198092Srdivacky
174193326Sed  // This does not need to be efficient.
175193326Sed
176193326Sed  const char *S = OverrideStr;
177193326Sed  while (*S) {
178193326Sed    const char *End = ::strchr(S, ' ');
179193326Sed    if (!End)
180193326Sed      End = S + strlen(S);
181193326Sed    if (End != S)
182198092Srdivacky      ApplyOneQAOverride(*OS, Args, std::string(S, End), SavedStrings);
183193326Sed    S = End;
184193326Sed    if (*S != '\0')
185193326Sed      ++S;
186193326Sed  }
187193326Sed}
188193326Sed
189199990Srdivackyextern int cc1_main(const char **ArgBegin, const char **ArgEnd,
190199990Srdivacky                    const char *Argv0, void *MainAddr);
191208600Srdivackyextern int cc1as_main(const char **ArgBegin, const char **ArgEnd,
192208600Srdivacky                      const char *Argv0, void *MainAddr);
193199512Srdivacky
194226890Sdimstatic void ParseProgName(SmallVectorImpl<const char *> &ArgVector,
195221345Sdim                          std::set<std::string> &SavedStrings,
196221345Sdim                          Driver &TheDriver)
197221345Sdim{
198221345Sdim  // Try to infer frontend type and default target from the program name.
199221345Sdim
200221345Sdim  // suffixes[] contains the list of known driver suffixes.
201221345Sdim  // Suffixes are compared against the program name in order.
202221345Sdim  // If there is a match, the frontend type is updated as necessary (CPP/C++).
203221345Sdim  // If there is no match, a second round is done after stripping the last
204221345Sdim  // hyphen and everything following it. This allows using something like
205221345Sdim  // "clang++-2.9".
206221345Sdim
207221345Sdim  // If there is a match in either the first or second round,
208221345Sdim  // the function tries to identify a target as prefix. E.g.
209221345Sdim  // "x86_64-linux-clang" as interpreted as suffix "clang" with
210221345Sdim  // target prefix "x86_64-linux". If such a target prefix is found,
211235633Sdim  // is gets added via -target as implicit first argument.
212221345Sdim  static const struct {
213221345Sdim    const char *Suffix;
214263509Sdim    const char *ModeFlag;
215221345Sdim  } suffixes [] = {
216263509Sdim    { "clang",     0 },
217263509Sdim    { "clang++",   "--driver-mode=g++" },
218263509Sdim    { "clang-CC",  "--driver-mode=g++" },
219263509Sdim    { "clang-c++", "--driver-mode=g++" },
220263509Sdim    { "clang-cc",  0 },
221263509Sdim    { "clang-cpp", "--driver-mode=cpp" },
222263509Sdim    { "clang-g++", "--driver-mode=g++" },
223263509Sdim    { "clang-gcc", 0 },
224263509Sdim    { "clang-cl",  "--driver-mode=cl"  },
225263509Sdim    { "CC",        "--driver-mode=g++" },
226263509Sdim    { "cc",        0 },
227263509Sdim    { "cpp",       "--driver-mode=cpp" },
228263509Sdim    { "cl" ,       "--driver-mode=cl"  },
229263509Sdim    { "++",        "--driver-mode=g++" },
230221345Sdim  };
231221345Sdim  std::string ProgName(llvm::sys::path::stem(ArgVector[0]));
232263509Sdim#ifdef _WIN32
233263509Sdim  std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(),
234263509Sdim                 toLowercase);
235263509Sdim#endif
236226890Sdim  StringRef ProgNameRef(ProgName);
237226890Sdim  StringRef Prefix;
238221345Sdim
239221345Sdim  for (int Components = 2; Components; --Components) {
240221345Sdim    bool FoundMatch = false;
241221345Sdim    size_t i;
242221345Sdim
243221345Sdim    for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) {
244221345Sdim      if (ProgNameRef.endswith(suffixes[i].Suffix)) {
245221345Sdim        FoundMatch = true;
246263509Sdim        SmallVectorImpl<const char *>::iterator it = ArgVector.begin();
247263509Sdim        if (it != ArgVector.end())
248263509Sdim          ++it;
249263509Sdim        if (suffixes[i].ModeFlag)
250263509Sdim          ArgVector.insert(it, suffixes[i].ModeFlag);
251221345Sdim        break;
252221345Sdim      }
253221345Sdim    }
254221345Sdim
255221345Sdim    if (FoundMatch) {
256226890Sdim      StringRef::size_type LastComponent = ProgNameRef.rfind('-',
257221345Sdim        ProgNameRef.size() - strlen(suffixes[i].Suffix));
258226890Sdim      if (LastComponent != StringRef::npos)
259221345Sdim        Prefix = ProgNameRef.slice(0, LastComponent);
260221345Sdim      break;
261221345Sdim    }
262221345Sdim
263226890Sdim    StringRef::size_type LastComponent = ProgNameRef.rfind('-');
264226890Sdim    if (LastComponent == StringRef::npos)
265221345Sdim      break;
266221345Sdim    ProgNameRef = ProgNameRef.slice(0, LastComponent);
267221345Sdim  }
268221345Sdim
269221345Sdim  if (Prefix.empty())
270221345Sdim    return;
271221345Sdim
272221345Sdim  std::string IgnoredError;
273221345Sdim  if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) {
274226890Sdim    SmallVectorImpl<const char *>::iterator it = ArgVector.begin();
275224145Sdim    if (it != ArgVector.end())
276224145Sdim      ++it;
277263509Sdim    const char* Strings[] =
278263509Sdim      { SaveStringInSet(SavedStrings, std::string("-target")),
279263509Sdim        SaveStringInSet(SavedStrings, Prefix) };
280263509Sdim    ArgVector.insert(it, Strings, Strings + llvm::array_lengthof(Strings));
281221345Sdim  }
282221345Sdim}
283221345Sdim
284263509Sdimnamespace {
285263509Sdim  class StringSetSaver : public llvm::cl::StringSaver {
286263509Sdim  public:
287263509Sdim    StringSetSaver(std::set<std::string> &Storage) : Storage(Storage) {}
288263509Sdim    const char *SaveString(const char *Str) LLVM_OVERRIDE {
289263509Sdim      return SaveStringInSet(Storage, Str);
290263509Sdim    }
291263509Sdim  private:
292263509Sdim    std::set<std::string> &Storage;
293263509Sdim  };
294263509Sdim}
295263509Sdim
296212904Sdimint main(int argc_, const char **argv_) {
297193326Sed  llvm::sys::PrintStackTraceOnErrorSignal();
298212904Sdim  llvm::PrettyStackTraceProgram X(argc_, argv_);
299193326Sed
300263509Sdim  SmallVector<const char *, 256> argv;
301263509Sdim  llvm::SpecificBumpPtrAllocator<char> ArgAllocator;
302263509Sdim  llvm::error_code EC = llvm::sys::Process::GetArgumentVector(
303263509Sdim      argv, llvm::ArrayRef<const char *>(argv_, argc_), ArgAllocator);
304263509Sdim  if (EC) {
305263509Sdim    llvm::errs() << "error: couldn't get arguments: " << EC.message() << '\n';
306263509Sdim    return 1;
307263509Sdim  }
308263509Sdim
309212904Sdim  std::set<std::string> SavedStrings;
310263509Sdim  StringSetSaver Saver(SavedStrings);
311263509Sdim  llvm::cl::ExpandResponseFiles(Saver, llvm::cl::TokenizeGNUCommandLine, argv);
312212904Sdim
313208600Srdivacky  // Handle -cc1 integrated tools.
314226890Sdim  if (argv.size() > 1 && StringRef(argv[1]).startswith("-cc1")) {
315226890Sdim    StringRef Tool = argv[1] + 4;
316199990Srdivacky
317208600Srdivacky    if (Tool == "")
318212904Sdim      return cc1_main(argv.data()+2, argv.data()+argv.size(), argv[0],
319208600Srdivacky                      (void*) (intptr_t) GetExecutablePath);
320208600Srdivacky    if (Tool == "as")
321212904Sdim      return cc1as_main(argv.data()+2, argv.data()+argv.size(), argv[0],
322208600Srdivacky                      (void*) (intptr_t) GetExecutablePath);
323208600Srdivacky
324208600Srdivacky    // Reject unknown tools.
325208600Srdivacky    llvm::errs() << "error: unknown integrated tool '" << Tool << "'\n";
326208600Srdivacky    return 1;
327208600Srdivacky  }
328208600Srdivacky
329200583Srdivacky  bool CanonicalPrefixes = true;
330212904Sdim  for (int i = 1, size = argv.size(); i < size; ++i) {
331226890Sdim    if (StringRef(argv[i]) == "-no-canonical-prefixes") {
332200583Srdivacky      CanonicalPrefixes = false;
333200583Srdivacky      break;
334200583Srdivacky    }
335200583Srdivacky  }
336200583Srdivacky
337252723Sdim  // Handle QA_OVERRIDE_GCC3_OPTIONS and CCC_ADD_ARGS, used for editing a
338252723Sdim  // command line behind the scenes.
339252723Sdim  if (const char *OverrideStr = ::getenv("QA_OVERRIDE_GCC3_OPTIONS")) {
340252723Sdim    // FIXME: Driver shouldn't take extra initial argument.
341252723Sdim    ApplyQAOverride(argv, OverrideStr, SavedStrings);
342252723Sdim  }
343252723Sdim
344263509Sdim  std::string Path = GetExecutablePath(argv[0], CanonicalPrefixes);
345200583Srdivacky
346245431Sdim  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions;
347235633Sdim  {
348263509Sdim    OwningPtr<OptTable> Opts(createDriverOptTable());
349235633Sdim    unsigned MissingArgIndex, MissingArgCount;
350263509Sdim    OwningPtr<InputArgList> Args(Opts->ParseArgs(argv.begin()+1, argv.end(),
351263509Sdim                                                 MissingArgIndex,
352263509Sdim                                                 MissingArgCount));
353235633Sdim    // We ignore MissingArgCount and the return value of ParseDiagnosticArgs.
354235633Sdim    // Any errors that would be diagnosed here will also be diagnosed later,
355235633Sdim    // when the DiagnosticsEngine actually exists.
356245431Sdim    (void) ParseDiagnosticArgs(*DiagOpts, *Args);
357235633Sdim  }
358235633Sdim  // Now we can create the DiagnosticsEngine with a properly-filled-out
359235633Sdim  // DiagnosticOptions instance.
360212904Sdim  TextDiagnosticPrinter *DiagClient
361245431Sdim    = new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts);
362263509Sdim
363263509Sdim  // If the clang binary happens to be named cl.exe for compatibility reasons,
364263509Sdim  // use clang-cl.exe as the prefix to avoid confusion between clang and MSVC.
365263509Sdim  StringRef ExeBasename(llvm::sys::path::filename(Path));
366263509Sdim  if (ExeBasename.equals_lower("cl.exe"))
367263509Sdim    ExeBasename = "clang-cl.exe";
368263509Sdim  DiagClient->setPrefix(ExeBasename);
369263509Sdim
370235633Sdim  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
371235633Sdim
372245431Sdim  DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);
373252723Sdim  ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false);
374193326Sed
375263509Sdim  Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), "a.out", Diags);
376193326Sed
377212904Sdim  // Attempt to find the original path used to invoke the driver, to determine
378212904Sdim  // the installed path. We do this manually, because we want to support that
379212904Sdim  // path being a symlink.
380218893Sdim  {
381235633Sdim    SmallString<128> InstalledPath(argv[0]);
382212904Sdim
383218893Sdim    // Do a PATH lookup, if there are no directory components.
384218893Sdim    if (llvm::sys::path::filename(InstalledPath) == InstalledPath) {
385263509Sdim      std::string Tmp = llvm::sys::FindProgramByName(
386218893Sdim        llvm::sys::path::filename(InstalledPath.str()));
387218893Sdim      if (!Tmp.empty())
388263509Sdim        InstalledPath = Tmp;
389218893Sdim    }
390218893Sdim    llvm::sys::fs::make_absolute(InstalledPath);
391218893Sdim    InstalledPath = llvm::sys::path::parent_path(InstalledPath);
392218893Sdim    bool exists;
393218893Sdim    if (!llvm::sys::fs::exists(InstalledPath.str(), exists) && exists)
394218893Sdim      TheDriver.setInstalledDir(InstalledPath);
395212904Sdim  }
396212904Sdim
397221345Sdim  llvm::InitializeAllTargets();
398221345Sdim  ParseProgName(argv, SavedStrings, TheDriver);
399199482Srdivacky
400205408Srdivacky  // Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE.
401205408Srdivacky  TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS");
402205408Srdivacky  if (TheDriver.CCPrintOptions)
403205408Srdivacky    TheDriver.CCPrintOptionsFilename = ::getenv("CC_PRINT_OPTIONS_FILE");
404205408Srdivacky
405218893Sdim  // Handle CC_PRINT_HEADERS and CC_PRINT_HEADERS_FILE.
406218893Sdim  TheDriver.CCPrintHeaders = !!::getenv("CC_PRINT_HEADERS");
407218893Sdim  if (TheDriver.CCPrintHeaders)
408218893Sdim    TheDriver.CCPrintHeadersFilename = ::getenv("CC_PRINT_HEADERS_FILE");
409218893Sdim
410221345Sdim  // Handle CC_LOG_DIAGNOSTICS and CC_LOG_DIAGNOSTICS_FILE.
411221345Sdim  TheDriver.CCLogDiagnostics = !!::getenv("CC_LOG_DIAGNOSTICS");
412221345Sdim  if (TheDriver.CCLogDiagnostics)
413221345Sdim    TheDriver.CCLogDiagnosticsFilename = ::getenv("CC_LOG_DIAGNOSTICS_FILE");
414221345Sdim
415235633Sdim  OwningPtr<Compilation> C(TheDriver.BuildCompilation(argv));
416193326Sed  int Res = 0;
417252723Sdim  SmallVector<std::pair<int, const Command *>, 4> FailingCommands;
418193326Sed  if (C.get())
419252723Sdim    Res = TheDriver.ExecuteCompilation(*C, FailingCommands);
420226890Sdim
421245431Sdim  // Force a crash to test the diagnostics.
422252723Sdim  if (::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")) {
423252723Sdim    Diags.Report(diag::err_drv_force_crash) << "FORCE_CLANG_DIAGNOSTICS_CRASH";
424252723Sdim    const Command *FailingCommand = 0;
425252723Sdim    FailingCommands.push_back(std::make_pair(-1, FailingCommand));
426252723Sdim  }
427245431Sdim
428252723Sdim  for (SmallVectorImpl< std::pair<int, const Command *> >::iterator it =
429252723Sdim         FailingCommands.begin(), ie = FailingCommands.end(); it != ie; ++it) {
430252723Sdim    int CommandRes = it->first;
431252723Sdim    const Command *FailingCommand = it->second;
432252723Sdim    if (!Res)
433252723Sdim      Res = CommandRes;
434226890Sdim
435252723Sdim    // If result status is < 0, then the driver command signalled an error.
436252723Sdim    // If result status is 70, then the driver command reported a fatal error.
437252723Sdim    // In these cases, generate additional diagnostic information if possible.
438252723Sdim    if (CommandRes < 0 || CommandRes == 70) {
439252723Sdim      TheDriver.generateCompilationDiagnostics(*C, FailingCommand);
440252723Sdim      break;
441252723Sdim    }
442252723Sdim  }
443252723Sdim
444206084Srdivacky  // If any timers were active but haven't been destroyed yet, print their
445206084Srdivacky  // results now.  This happens in -disable-free mode.
446206084Srdivacky  llvm::TimerGroup::printAll(llvm::errs());
447206084Srdivacky
448193326Sed  llvm::llvm_shutdown();
449193326Sed
450245431Sdim#ifdef _WIN32
451245431Sdim  // Exit status should not be negative on Win32, unless abnormal termination.
452245431Sdim  // Once abnormal termiation was caught, negative status should not be
453245431Sdim  // propagated.
454245431Sdim  if (Res < 0)
455245431Sdim    Res = 1;
456245431Sdim#endif
457245431Sdim
458252723Sdim  // If we have multiple failing commands, we return the result of the first
459252723Sdim  // failing command.
460193326Sed  return Res;
461193326Sed}
462