Compilation.cpp revision 8ce9054eb9051008b6a9850714701099d2a016b1
1//===--- Compilation.cpp - Compilation Task Implementation ----------------===// 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#include "clang/Driver/Compilation.h" 11#include "clang/Driver/Action.h" 12#include "clang/Driver/Driver.h" 13#include "clang/Driver/DriverDiagnostic.h" 14#include "clang/Driver/Options.h" 15#include "clang/Driver/ToolChain.h" 16#include "llvm/ADT/STLExtras.h" 17#include "llvm/ADT/StringSwitch.h" 18#include "llvm/Option/ArgList.h" 19#include "llvm/Support/FileSystem.h" 20#include "llvm/Support/PathV1.h" 21#include "llvm/Support/Program.h" 22#include "llvm/Support/raw_ostream.h" 23#include <errno.h> 24#include <sys/stat.h> 25 26using namespace clang::driver; 27using namespace clang; 28using namespace llvm::opt; 29 30Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain, 31 InputArgList *_Args, DerivedArgList *_TranslatedArgs) 32 : TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args), 33 TranslatedArgs(_TranslatedArgs), Redirects(0) { 34} 35 36Compilation::~Compilation() { 37 delete TranslatedArgs; 38 delete Args; 39 40 // Free any derived arg lists. 41 for (llvm::DenseMap<std::pair<const ToolChain*, const char*>, 42 DerivedArgList*>::iterator it = TCArgs.begin(), 43 ie = TCArgs.end(); it != ie; ++it) 44 if (it->second != TranslatedArgs) 45 delete it->second; 46 47 // Free the actions, if built. 48 for (ActionList::iterator it = Actions.begin(), ie = Actions.end(); 49 it != ie; ++it) 50 delete *it; 51 52 // Free redirections of stdout/stderr. 53 if (Redirects) { 54 delete Redirects[1]; 55 delete Redirects[2]; 56 delete [] Redirects; 57 } 58} 59 60const DerivedArgList &Compilation::getArgsForToolChain(const ToolChain *TC, 61 const char *BoundArch) { 62 if (!TC) 63 TC = &DefaultToolChain; 64 65 DerivedArgList *&Entry = TCArgs[std::make_pair(TC, BoundArch)]; 66 if (!Entry) { 67 Entry = TC->TranslateArgs(*TranslatedArgs, BoundArch); 68 if (!Entry) 69 Entry = TranslatedArgs; 70 } 71 72 return *Entry; 73} 74 75void Compilation::PrintJob(raw_ostream &OS, const Job &J, 76 const char *Terminator, bool Quote) const { 77 if (const Command *C = dyn_cast<Command>(&J)) { 78 OS << " \"" << C->getExecutable() << '"'; 79 for (ArgStringList::const_iterator it = C->getArguments().begin(), 80 ie = C->getArguments().end(); it != ie; ++it) { 81 OS << ' '; 82 if (!Quote && !std::strpbrk(*it, " \"\\$")) { 83 OS << *it; 84 continue; 85 } 86 87 // Quote the argument and escape shell special characters; this isn't 88 // really complete but is good enough. 89 OS << '"'; 90 for (const char *s = *it; *s; ++s) { 91 if (*s == '"' || *s == '\\' || *s == '$') 92 OS << '\\'; 93 OS << *s; 94 } 95 OS << '"'; 96 } 97 OS << Terminator; 98 } else { 99 const JobList *Jobs = cast<JobList>(&J); 100 for (JobList::const_iterator 101 it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it) 102 PrintJob(OS, **it, Terminator, Quote); 103 } 104} 105 106static bool skipArg(const char *Flag, bool &SkipNextArg) { 107 StringRef FlagRef(Flag); 108 109 // Assume we're going to see -Flag <Arg>. 110 SkipNextArg = true; 111 112 // These flags are all of the form -Flag <Arg> and are treated as two 113 // arguments. Therefore, we need to skip the flag and the next argument. 114 bool Res = llvm::StringSwitch<bool>(Flag) 115 .Cases("-I", "-MF", "-MT", "-MQ", true) 116 .Cases("-o", "-coverage-file", "-dependency-file", true) 117 .Cases("-fdebug-compilation-dir", "-idirafter", true) 118 .Cases("-include", "-include-pch", "-internal-isystem", true) 119 .Cases("-internal-externc-isystem", "-iprefix", "-iwithprefix", true) 120 .Cases("-iwithprefixbefore", "-isysroot", "-isystem", "-iquote", true) 121 .Cases("-resource-dir", "-serialize-diagnostic-file", true) 122 .Case("-dwarf-debug-flags", true) 123 .Default(false); 124 125 // Match found. 126 if (Res) 127 return Res; 128 129 // The remaining flags are treated as a single argument. 130 SkipNextArg = false; 131 132 // These flags are all of the form -Flag and have no second argument. 133 Res = llvm::StringSwitch<bool>(Flag) 134 .Cases("-M", "-MM", "-MG", "-MP", "-MD", true) 135 .Case("-MMD", true) 136 .Default(false); 137 138 // Match found. 139 if (Res) 140 return Res; 141 142 // These flags are treated as a single argument (e.g., -F<Dir>). 143 if (FlagRef.startswith("-F") || FlagRef.startswith("-I")) 144 return true; 145 146 return false; 147} 148 149static bool quoteNextArg(const char *flag) { 150 return llvm::StringSwitch<bool>(flag) 151 .Case("-D", true) 152 .Default(false); 153} 154 155void Compilation::PrintDiagnosticJob(raw_ostream &OS, const Job &J) const { 156 if (const Command *C = dyn_cast<Command>(&J)) { 157 OS << C->getExecutable(); 158 unsigned QuoteNextArg = 0; 159 for (ArgStringList::const_iterator it = C->getArguments().begin(), 160 ie = C->getArguments().end(); it != ie; ++it) { 161 162 bool SkipNext; 163 if (skipArg(*it, SkipNext)) { 164 if (SkipNext) ++it; 165 continue; 166 } 167 168 if (!QuoteNextArg) 169 QuoteNextArg = quoteNextArg(*it) ? 2 : 0; 170 171 OS << ' '; 172 173 if (QuoteNextArg == 1) 174 OS << '"'; 175 176 if (!std::strpbrk(*it, " \"\\$")) { 177 OS << *it; 178 } else { 179 // Quote the argument and escape shell special characters; this isn't 180 // really complete but is good enough. 181 OS << '"'; 182 for (const char *s = *it; *s; ++s) { 183 if (*s == '"' || *s == '\\' || *s == '$') 184 OS << '\\'; 185 OS << *s; 186 } 187 OS << '"'; 188 } 189 190 if (QuoteNextArg) { 191 if (QuoteNextArg == 1) 192 OS << '"'; 193 --QuoteNextArg; 194 } 195 } 196 OS << '\n'; 197 } else { 198 const JobList *Jobs = cast<JobList>(&J); 199 for (JobList::const_iterator 200 it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it) 201 PrintDiagnosticJob(OS, **it); 202 } 203} 204 205bool Compilation::CleanupFile(const char *File, bool IssueErrors) const { 206 llvm::sys::Path P(File); 207 std::string Error; 208 209 // Don't try to remove files which we don't have write access to (but may be 210 // able to remove), or non-regular files. Underlying tools may have 211 // intentionally not overwritten them. 212 if (!llvm::sys::fs::can_write(File) || !P.isRegularFile()) 213 return true; 214 215 if (P.eraseFromDisk(false, &Error)) { 216 // Failure is only failure if the file exists and is "regular". There is 217 // a race condition here due to the limited interface of 218 // llvm::sys::Path, we want to know if the removal gave ENOENT. 219 220 // FIXME: Grumble, P.exists() is broken. PR3837. 221 struct stat buf; 222 if (::stat(P.c_str(), &buf) == 0 ? (buf.st_mode & S_IFMT) == S_IFREG : 223 (errno != ENOENT)) { 224 if (IssueErrors) 225 getDriver().Diag(clang::diag::err_drv_unable_to_remove_file) 226 << Error; 227 return false; 228 } 229 } 230 return true; 231} 232 233bool Compilation::CleanupFileList(const ArgStringList &Files, 234 bool IssueErrors) const { 235 bool Success = true; 236 for (ArgStringList::const_iterator 237 it = Files.begin(), ie = Files.end(); it != ie; ++it) 238 Success &= CleanupFile(*it, IssueErrors); 239 return Success; 240} 241 242bool Compilation::CleanupFileMap(const ArgStringMap &Files, 243 const JobAction *JA, 244 bool IssueErrors) const { 245 bool Success = true; 246 for (ArgStringMap::const_iterator 247 it = Files.begin(), ie = Files.end(); it != ie; ++it) { 248 249 // If specified, only delete the files associated with the JobAction. 250 // Otherwise, delete all files in the map. 251 if (JA && it->first != JA) 252 continue; 253 Success &= CleanupFile(it->second, IssueErrors); 254 } 255 return Success; 256} 257 258int Compilation::ExecuteCommand(const Command &C, 259 const Command *&FailingCommand) const { 260 std::string Prog(C.getExecutable()); 261 const char **Argv = new const char*[C.getArguments().size() + 2]; 262 Argv[0] = C.getExecutable(); 263 std::copy(C.getArguments().begin(), C.getArguments().end(), Argv+1); 264 Argv[C.getArguments().size() + 1] = 0; 265 266 if ((getDriver().CCCEcho || getDriver().CCPrintOptions || 267 getArgs().hasArg(options::OPT_v)) && !getDriver().CCGenDiagnostics) { 268 raw_ostream *OS = &llvm::errs(); 269 270 // Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the 271 // output stream. 272 if (getDriver().CCPrintOptions && getDriver().CCPrintOptionsFilename) { 273 std::string Error; 274 OS = new llvm::raw_fd_ostream(getDriver().CCPrintOptionsFilename, 275 Error, 276 llvm::raw_fd_ostream::F_Append); 277 if (!Error.empty()) { 278 getDriver().Diag(clang::diag::err_drv_cc_print_options_failure) 279 << Error; 280 FailingCommand = &C; 281 delete OS; 282 return 1; 283 } 284 } 285 286 if (getDriver().CCPrintOptions) 287 *OS << "[Logging clang options]"; 288 289 PrintJob(*OS, C, "\n", /*Quote=*/getDriver().CCPrintOptions); 290 291 if (OS != &llvm::errs()) 292 delete OS; 293 } 294 295 std::string Error; 296 bool ExecutionFailed; 297 int Res = llvm::sys::ExecuteAndWait(Prog, Argv, /*env*/ 0, Redirects, 298 /*secondsToWait*/ 0, /*memoryLimit*/ 0, 299 &Error, &ExecutionFailed); 300 if (!Error.empty()) { 301 assert(Res && "Error string set with 0 result code!"); 302 getDriver().Diag(clang::diag::err_drv_command_failure) << Error; 303 } 304 305 if (Res) 306 FailingCommand = &C; 307 308 delete[] Argv; 309 return ExecutionFailed ? 1 : Res; 310} 311 312typedef SmallVectorImpl< std::pair<int, const Command *> > FailingCommandList; 313 314static bool ActionFailed(const Action *A, 315 const FailingCommandList &FailingCommands) { 316 317 if (FailingCommands.empty()) 318 return false; 319 320 for (FailingCommandList::const_iterator CI = FailingCommands.begin(), 321 CE = FailingCommands.end(); CI != CE; ++CI) 322 if (A == &(CI->second->getSource())) 323 return true; 324 325 for (Action::const_iterator AI = A->begin(), AE = A->end(); AI != AE; ++AI) 326 if (ActionFailed(*AI, FailingCommands)) 327 return true; 328 329 return false; 330} 331 332static bool InputsOk(const Command &C, 333 const FailingCommandList &FailingCommands) { 334 return !ActionFailed(&C.getSource(), FailingCommands); 335} 336 337void Compilation::ExecuteJob(const Job &J, 338 FailingCommandList &FailingCommands) const { 339 if (const Command *C = dyn_cast<Command>(&J)) { 340 if (!InputsOk(*C, FailingCommands)) 341 return; 342 const Command *FailingCommand = 0; 343 if (int Res = ExecuteCommand(*C, FailingCommand)) 344 FailingCommands.push_back(std::make_pair(Res, FailingCommand)); 345 } else { 346 const JobList *Jobs = cast<JobList>(&J); 347 for (JobList::const_iterator it = Jobs->begin(), ie = Jobs->end(); 348 it != ie; ++it) 349 ExecuteJob(**it, FailingCommands); 350 } 351} 352 353void Compilation::initCompilationForDiagnostics() { 354 // Free actions and jobs. 355 DeleteContainerPointers(Actions); 356 Jobs.clear(); 357 358 // Clear temporary/results file lists. 359 TempFiles.clear(); 360 ResultFiles.clear(); 361 FailureResultFiles.clear(); 362 363 // Remove any user specified output. Claim any unclaimed arguments, so as 364 // to avoid emitting warnings about unused args. 365 OptSpecifier OutputOpts[] = { options::OPT_o, options::OPT_MD, 366 options::OPT_MMD }; 367 for (unsigned i = 0, e = llvm::array_lengthof(OutputOpts); i != e; ++i) { 368 if (TranslatedArgs->hasArg(OutputOpts[i])) 369 TranslatedArgs->eraseArg(OutputOpts[i]); 370 } 371 TranslatedArgs->ClaimAllArgs(); 372 373 // Redirect stdout/stderr to /dev/null. 374 Redirects = new const StringRef*[3](); 375 Redirects[0] = 0; 376 Redirects[1] = new const StringRef(); 377 Redirects[2] = new const StringRef(); 378} 379 380StringRef Compilation::getSysRoot() const { 381 return getDriver().SysRoot; 382} 383