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