driver.cpp revision 5633c1e4a7a5dd6dc5a4468f1660fabe70b0d2f8
1//===-- driver.cpp - Clang GCC-Compatible Driver --------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This is the entry point to the clang driver; it is a thin wrapper 11// for functionality in the Driver clang library. 12// 13//===----------------------------------------------------------------------===// 14 15#include "clang/Driver/Compilation.h" 16#include "clang/Driver/Driver.h" 17#include "clang/Driver/Option.h" 18#include "clang/Frontend/DiagnosticOptions.h" 19#include "clang/Frontend/TextDiagnosticPrinter.h" 20 21#include "llvm/ADT/SmallString.h" 22#include "llvm/ADT/SmallVector.h" 23#include "llvm/ADT/OwningPtr.h" 24#include "llvm/Config/config.h" 25#include "llvm/Support/ErrorHandling.h" 26#include "llvm/Support/ManagedStatic.h" 27#include "llvm/Support/MemoryBuffer.h" 28#include "llvm/Support/PrettyStackTrace.h" 29#include "llvm/Support/Regex.h" 30#include "llvm/Support/Timer.h" 31#include "llvm/Support/raw_ostream.h" 32#include "llvm/System/Host.h" 33#include "llvm/System/Path.h" 34#include "llvm/System/Signals.h" 35using namespace clang; 36using namespace clang::driver; 37 38llvm::sys::Path GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) { 39 if (!CanonicalPrefixes) 40 return llvm::sys::Path(Argv0); 41 42 // This just needs to be some symbol in the binary; C++ doesn't 43 // allow taking the address of ::main however. 44 void *P = (void*) (intptr_t) GetExecutablePath; 45 return llvm::sys::Path::GetMainExecutable(Argv0, P); 46} 47 48static const char *SaveStringInSet(std::set<std::string> &SavedStrings, 49 llvm::StringRef S) { 50 return SavedStrings.insert(S).first->c_str(); 51} 52 53/// ApplyQAOverride - Apply a list of edits to the input argument lists. 54/// 55/// The input string is a space separate list of edits to perform, 56/// they are applied in order to the input argument lists. Edits 57/// should be one of the following forms: 58/// 59/// '#': Silence information about the changes to the command line arguments. 60/// 61/// '^': Add FOO as a new argument at the beginning of the command line. 62/// 63/// '+': Add FOO as a new argument at the end of the command line. 64/// 65/// 's/XXX/YYY/': Substitute the regular expression XXX with YYY in the command 66/// line. 67/// 68/// 'xOPTION': Removes all instances of the literal argument OPTION. 69/// 70/// 'XOPTION': Removes all instances of the literal argument OPTION, 71/// and the following argument. 72/// 73/// 'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox' 74/// at the end of the command line. 75/// 76/// \param OS - The stream to write edit information to. 77/// \param Args - The vector of command line arguments. 78/// \param Edit - The override command to perform. 79/// \param SavedStrings - Set to use for storing string representations. 80static void ApplyOneQAOverride(llvm::raw_ostream &OS, 81 llvm::SmallVectorImpl<const char*> &Args, 82 llvm::StringRef Edit, 83 std::set<std::string> &SavedStrings) { 84 // This does not need to be efficient. 85 86 if (Edit[0] == '^') { 87 const char *Str = 88 SaveStringInSet(SavedStrings, Edit.substr(1)); 89 OS << "### Adding argument " << Str << " at beginning\n"; 90 Args.insert(Args.begin() + 1, Str); 91 } else if (Edit[0] == '+') { 92 const char *Str = 93 SaveStringInSet(SavedStrings, Edit.substr(1)); 94 OS << "### Adding argument " << Str << " at end\n"; 95 Args.push_back(Str); 96 } else if (Edit[0] == 's' && Edit[1] == '/' && Edit.endswith("/") && 97 Edit.slice(2, Edit.size()-1).find('/') != llvm::StringRef::npos) { 98 llvm::StringRef MatchPattern = Edit.substr(2).split('/').first; 99 llvm::StringRef ReplPattern = Edit.substr(2).split('/').second; 100 ReplPattern = ReplPattern.slice(0, ReplPattern.size()-1); 101 102 for (unsigned i = 1, e = Args.size(); i != e; ++i) { 103 std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]); 104 105 if (Repl != Args[i]) { 106 OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n"; 107 Args[i] = SaveStringInSet(SavedStrings, Repl); 108 } 109 } 110 } else if (Edit[0] == 'x' || Edit[0] == 'X') { 111 std::string Option = Edit.substr(1, std::string::npos); 112 for (unsigned i = 1; i < Args.size();) { 113 if (Option == Args[i]) { 114 OS << "### Deleting argument " << Args[i] << '\n'; 115 Args.erase(Args.begin() + i); 116 if (Edit[0] == 'X') { 117 if (i < Args.size()) { 118 OS << "### Deleting argument " << Args[i] << '\n'; 119 Args.erase(Args.begin() + i); 120 } else 121 OS << "### Invalid X edit, end of command line!\n"; 122 } 123 } else 124 ++i; 125 } 126 } else if (Edit[0] == 'O') { 127 for (unsigned i = 1; i < Args.size();) { 128 const char *A = Args[i]; 129 if (A[0] == '-' && A[1] == 'O' && 130 (A[2] == '\0' || 131 (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' || 132 ('0' <= A[2] && A[2] <= '9'))))) { 133 OS << "### Deleting argument " << Args[i] << '\n'; 134 Args.erase(Args.begin() + i); 135 } else 136 ++i; 137 } 138 OS << "### Adding argument " << Edit << " at end\n"; 139 Args.push_back(SaveStringInSet(SavedStrings, '-' + Edit.str())); 140 } else { 141 OS << "### Unrecognized edit: " << Edit << "\n"; 142 } 143} 144 145/// ApplyQAOverride - Apply a comma separate list of edits to the 146/// input argument lists. See ApplyOneQAOverride. 147static void ApplyQAOverride(llvm::SmallVectorImpl<const char*> &Args, 148 const char *OverrideStr, 149 std::set<std::string> &SavedStrings) { 150 llvm::raw_ostream *OS = &llvm::errs(); 151 152 if (OverrideStr[0] == '#') { 153 ++OverrideStr; 154 OS = &llvm::nulls(); 155 } 156 157 *OS << "### QA_OVERRIDE_GCC3_OPTIONS: " << OverrideStr << "\n"; 158 159 // This does not need to be efficient. 160 161 const char *S = OverrideStr; 162 while (*S) { 163 const char *End = ::strchr(S, ' '); 164 if (!End) 165 End = S + strlen(S); 166 if (End != S) 167 ApplyOneQAOverride(*OS, Args, std::string(S, End), SavedStrings); 168 S = End; 169 if (*S != '\0') 170 ++S; 171 } 172} 173 174extern int cc1_main(const char **ArgBegin, const char **ArgEnd, 175 const char *Argv0, void *MainAddr); 176extern int cc1as_main(const char **ArgBegin, const char **ArgEnd, 177 const char *Argv0, void *MainAddr); 178 179static void ExpandArgsFromBuf(const char *Arg, 180 llvm::SmallVectorImpl<const char*> &ArgVector, 181 std::set<std::string> &SavedStrings) { 182 const char *FName = Arg + 1; 183 llvm::MemoryBuffer *MemBuf = llvm::MemoryBuffer::getFile(FName); 184 if (!MemBuf) { 185 ArgVector.push_back(SaveStringInSet(SavedStrings, Arg)); 186 return; 187 } 188 189 const char *Buf = MemBuf->getBufferStart(); 190 char InQuote = ' '; 191 std::string CurArg; 192 193 for (const char *P = Buf; ; ++P) { 194 if (*P == '\0' || (isspace(*P) && InQuote == ' ')) { 195 if (!CurArg.empty()) { 196 197 if (CurArg[0] != '@') { 198 ArgVector.push_back(SaveStringInSet(SavedStrings, CurArg)); 199 } else { 200 ExpandArgsFromBuf(CurArg.c_str(), ArgVector, SavedStrings); 201 } 202 203 CurArg = ""; 204 } 205 if (*P == '\0') 206 break; 207 else 208 continue; 209 } 210 211 if (isspace(*P)) { 212 if (InQuote != ' ') 213 CurArg.push_back(*P); 214 continue; 215 } 216 217 if (*P == '"' || *P == '\'') { 218 if (InQuote == *P) 219 InQuote = ' '; 220 else if (InQuote == ' ') 221 InQuote = *P; 222 else 223 CurArg.push_back(*P); 224 continue; 225 } 226 227 if (*P == '\\') { 228 ++P; 229 if (*P != '\0') 230 CurArg.push_back(*P); 231 continue; 232 } 233 CurArg.push_back(*P); 234 } 235 delete MemBuf; 236} 237 238static void ExpandArgv(int argc, const char **argv, 239 llvm::SmallVectorImpl<const char*> &ArgVector, 240 std::set<std::string> &SavedStrings) { 241 for (int i = 0; i < argc; ++i) { 242 const char *Arg = argv[i]; 243 if (Arg[0] != '@') { 244 ArgVector.push_back(SaveStringInSet(SavedStrings, std::string(Arg))); 245 continue; 246 } 247 248 ExpandArgsFromBuf(Arg, ArgVector, SavedStrings); 249 } 250} 251 252int main(int argc_, const char **argv_) { 253 llvm::sys::PrintStackTraceOnErrorSignal(); 254 llvm::PrettyStackTraceProgram X(argc_, argv_); 255 256 std::set<std::string> SavedStrings; 257 llvm::SmallVector<const char*, 256> argv; 258 259 ExpandArgv(argc_, argv_, argv, SavedStrings); 260 261 // Handle -cc1 integrated tools. 262 if (argv.size() > 1 && llvm::StringRef(argv[1]).startswith("-cc1")) { 263 llvm::StringRef Tool = argv[1] + 4; 264 265 if (Tool == "") 266 return cc1_main(argv.data()+2, argv.data()+argv.size(), argv[0], 267 (void*) (intptr_t) GetExecutablePath); 268 if (Tool == "as") 269 return cc1as_main(argv.data()+2, argv.data()+argv.size(), argv[0], 270 (void*) (intptr_t) GetExecutablePath); 271 272 // Reject unknown tools. 273 llvm::errs() << "error: unknown integrated tool '" << Tool << "'\n"; 274 return 1; 275 } 276 277 bool CanonicalPrefixes = true; 278 for (int i = 1, size = argv.size(); i < size; ++i) { 279 if (llvm::StringRef(argv[i]) == "-no-canonical-prefixes") { 280 CanonicalPrefixes = false; 281 break; 282 } 283 } 284 285 llvm::sys::Path Path = GetExecutablePath(argv[0], CanonicalPrefixes); 286 287 TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions()); 288 DiagClient.setPrefix(Path.getBasename()); 289 290 Diagnostic Diags(&DiagClient); 291 292#ifdef CLANG_IS_PRODUCTION 293 const bool IsProduction = true; 294# ifdef CLANGXX_IS_PRODUCTION 295 const bool CXXIsProduction = true; 296# else 297 const bool CXXIsProduction = false; 298# endif 299#else 300 const bool IsProduction = false; 301 const bool CXXIsProduction = false; 302#endif 303 Driver TheDriver(Path.str(), llvm::sys::getHostTriple(), 304 "a.out", IsProduction, CXXIsProduction, 305 Diags); 306 307 // Check for ".*++" or ".*++-[^-]*" to determine if we are a C++ 308 // compiler. This matches things like "c++", "clang++", and "clang++-1.1". 309 // 310 // Note that we intentionally want to use argv[0] here, to support "clang++" 311 // being a symlink. 312 // 313 // We use *argv instead of argv[0] to work around a bogus g++ warning. 314 const char *progname = argv_[0]; 315 std::string ProgName(llvm::sys::Path(progname).getBasename()); 316 if (llvm::StringRef(ProgName).endswith("++") || 317 llvm::StringRef(ProgName).rsplit('-').first.endswith("++")) { 318 TheDriver.CCCIsCXX = true; 319 TheDriver.CCCGenericGCCName = "g++"; 320 } 321 322 // Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE. 323 TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS"); 324 if (TheDriver.CCPrintOptions) 325 TheDriver.CCPrintOptionsFilename = ::getenv("CC_PRINT_OPTIONS_FILE"); 326 327 // Handle QA_OVERRIDE_GCC3_OPTIONS and CCC_ADD_ARGS, used for editing a 328 // command line behind the scenes. 329 if (const char *OverrideStr = ::getenv("QA_OVERRIDE_GCC3_OPTIONS")) { 330 // FIXME: Driver shouldn't take extra initial argument. 331 ApplyQAOverride(argv, OverrideStr, SavedStrings); 332 } else if (const char *Cur = ::getenv("CCC_ADD_ARGS")) { 333 // FIXME: Driver shouldn't take extra initial argument. 334 std::vector<const char*> ExtraArgs; 335 336 for (;;) { 337 const char *Next = strchr(Cur, ','); 338 339 if (Next) { 340 ExtraArgs.push_back(SaveStringInSet(SavedStrings, 341 std::string(Cur, Next))); 342 Cur = Next + 1; 343 } else { 344 if (*Cur != '\0') 345 ExtraArgs.push_back(SaveStringInSet(SavedStrings, Cur)); 346 break; 347 } 348 } 349 350 argv.insert(&argv[1], ExtraArgs.begin(), ExtraArgs.end()); 351 } 352 353 llvm::OwningPtr<Compilation> C(TheDriver.BuildCompilation(argv.size(), 354 &argv[0])); 355 int Res = 0; 356 if (C.get()) 357 Res = TheDriver.ExecuteCompilation(*C); 358 359 // If any timers were active but haven't been destroyed yet, print their 360 // results now. This happens in -disable-free mode. 361 llvm::TimerGroup::printAll(llvm::errs()); 362 363 llvm::llvm_shutdown(); 364 365 return Res; 366} 367