Compilation.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  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. #include "clang/Driver/Compilation.h"
  10. #include "clang/Driver/Action.h"
  11. #include "clang/Driver/Driver.h"
  12. #include "clang/Driver/DriverDiagnostic.h"
  13. #include "clang/Driver/Options.h"
  14. #include "clang/Driver/ToolChain.h"
  15. #include "llvm/ADT/STLExtras.h"
  16. #include "llvm/Option/ArgList.h"
  17. #include "llvm/Support/FileSystem.h"
  18. #include "llvm/Support/raw_ostream.h"
  19. using namespace clang::driver;
  20. using namespace clang;
  21. using namespace llvm::opt;
  22. Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
  23. InputArgList *_Args, DerivedArgList *_TranslatedArgs)
  24. : TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args),
  25. TranslatedArgs(_TranslatedArgs), Redirects(nullptr),
  26. ForDiagnostics(false) {}
  27. Compilation::~Compilation() {
  28. delete TranslatedArgs;
  29. delete Args;
  30. // Free any derived arg lists.
  31. for (llvm::DenseMap<std::pair<const ToolChain*, const char*>,
  32. DerivedArgList*>::iterator it = TCArgs.begin(),
  33. ie = TCArgs.end(); it != ie; ++it)
  34. if (it->second != TranslatedArgs)
  35. delete it->second;
  36. // Free the actions, if built.
  37. for (ActionList::iterator it = Actions.begin(), ie = Actions.end();
  38. it != ie; ++it)
  39. delete *it;
  40. // Free redirections of stdout/stderr.
  41. if (Redirects) {
  42. delete Redirects[1];
  43. delete Redirects[2];
  44. delete [] Redirects;
  45. }
  46. }
  47. const DerivedArgList &Compilation::getArgsForToolChain(const ToolChain *TC,
  48. const char *BoundArch) {
  49. if (!TC)
  50. TC = &DefaultToolChain;
  51. DerivedArgList *&Entry = TCArgs[std::make_pair(TC, BoundArch)];
  52. if (!Entry) {
  53. Entry = TC->TranslateArgs(*TranslatedArgs, BoundArch);
  54. if (!Entry)
  55. Entry = TranslatedArgs;
  56. }
  57. return *Entry;
  58. }
  59. bool Compilation::CleanupFile(const char *File, bool IssueErrors) const {
  60. // FIXME: Why are we trying to remove files that we have not created? For
  61. // example we should only try to remove a temporary assembly file if
  62. // "clang -cc1" succeed in writing it. Was this a workaround for when
  63. // clang was writing directly to a .s file and sometimes leaving it behind
  64. // during a failure?
  65. // FIXME: If this is necessary, we can still try to split
  66. // llvm::sys::fs::remove into a removeFile and a removeDir and avoid the
  67. // duplicated stat from is_regular_file.
  68. // Don't try to remove files which we don't have write access to (but may be
  69. // able to remove), or non-regular files. Underlying tools may have
  70. // intentionally not overwritten them.
  71. if (!llvm::sys::fs::can_write(File) || !llvm::sys::fs::is_regular_file(File))
  72. return true;
  73. if (std::error_code EC = llvm::sys::fs::remove(File)) {
  74. // Failure is only failure if the file exists and is "regular". We checked
  75. // for it being regular before, and llvm::sys::fs::remove ignores ENOENT,
  76. // so we don't need to check again.
  77. if (IssueErrors)
  78. getDriver().Diag(clang::diag::err_drv_unable_to_remove_file)
  79. << EC.message();
  80. return false;
  81. }
  82. return true;
  83. }
  84. bool Compilation::CleanupFileList(const ArgStringList &Files,
  85. bool IssueErrors) const {
  86. bool Success = true;
  87. for (ArgStringList::const_iterator
  88. it = Files.begin(), ie = Files.end(); it != ie; ++it)
  89. Success &= CleanupFile(*it, IssueErrors);
  90. return Success;
  91. }
  92. bool Compilation::CleanupFileMap(const ArgStringMap &Files,
  93. const JobAction *JA,
  94. bool IssueErrors) const {
  95. bool Success = true;
  96. for (ArgStringMap::const_iterator
  97. it = Files.begin(), ie = Files.end(); it != ie; ++it) {
  98. // If specified, only delete the files associated with the JobAction.
  99. // Otherwise, delete all files in the map.
  100. if (JA && it->first != JA)
  101. continue;
  102. Success &= CleanupFile(it->second, IssueErrors);
  103. }
  104. return Success;
  105. }
  106. int Compilation::ExecuteCommand(const Command &C,
  107. const Command *&FailingCommand) const {
  108. if ((getDriver().CCPrintOptions ||
  109. getArgs().hasArg(options::OPT_v)) && !getDriver().CCGenDiagnostics) {
  110. raw_ostream *OS = &llvm::errs();
  111. // Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the
  112. // output stream.
  113. if (getDriver().CCPrintOptions && getDriver().CCPrintOptionsFilename) {
  114. std::string Error;
  115. OS = new llvm::raw_fd_ostream(getDriver().CCPrintOptionsFilename, Error,
  116. llvm::sys::fs::F_Append |
  117. llvm::sys::fs::F_Text);
  118. if (!Error.empty()) {
  119. getDriver().Diag(clang::diag::err_drv_cc_print_options_failure)
  120. << Error;
  121. FailingCommand = &C;
  122. delete OS;
  123. return 1;
  124. }
  125. }
  126. if (getDriver().CCPrintOptions)
  127. *OS << "[Logging clang options]";
  128. C.Print(*OS, "\n", /*Quote=*/getDriver().CCPrintOptions);
  129. if (OS != &llvm::errs())
  130. delete OS;
  131. }
  132. std::string Error;
  133. bool ExecutionFailed;
  134. int Res = C.Execute(Redirects, &Error, &ExecutionFailed);
  135. if (!Error.empty()) {
  136. assert(Res && "Error string set with 0 result code!");
  137. getDriver().Diag(clang::diag::err_drv_command_failure) << Error;
  138. }
  139. if (Res)
  140. FailingCommand = &C;
  141. return ExecutionFailed ? 1 : Res;
  142. }
  143. typedef SmallVectorImpl< std::pair<int, const Command *> > FailingCommandList;
  144. static bool ActionFailed(const Action *A,
  145. const FailingCommandList &FailingCommands) {
  146. if (FailingCommands.empty())
  147. return false;
  148. for (FailingCommandList::const_iterator CI = FailingCommands.begin(),
  149. CE = FailingCommands.end(); CI != CE; ++CI)
  150. if (A == &(CI->second->getSource()))
  151. return true;
  152. for (Action::const_iterator AI = A->begin(), AE = A->end(); AI != AE; ++AI)
  153. if (ActionFailed(*AI, FailingCommands))
  154. return true;
  155. return false;
  156. }
  157. static bool InputsOk(const Command &C,
  158. const FailingCommandList &FailingCommands) {
  159. return !ActionFailed(&C.getSource(), FailingCommands);
  160. }
  161. void Compilation::ExecuteJob(const Job &J,
  162. FailingCommandList &FailingCommands) const {
  163. if (const Command *C = dyn_cast<Command>(&J)) {
  164. if (!InputsOk(*C, FailingCommands))
  165. return;
  166. const Command *FailingCommand = nullptr;
  167. if (int Res = ExecuteCommand(*C, FailingCommand))
  168. FailingCommands.push_back(std::make_pair(Res, FailingCommand));
  169. } else {
  170. const JobList *Jobs = cast<JobList>(&J);
  171. for (JobList::const_iterator it = Jobs->begin(), ie = Jobs->end();
  172. it != ie; ++it)
  173. ExecuteJob(**it, FailingCommands);
  174. }
  175. }
  176. void Compilation::initCompilationForDiagnostics() {
  177. ForDiagnostics = true;
  178. // Free actions and jobs.
  179. DeleteContainerPointers(Actions);
  180. Jobs.clear();
  181. // Clear temporary/results file lists.
  182. TempFiles.clear();
  183. ResultFiles.clear();
  184. FailureResultFiles.clear();
  185. // Remove any user specified output. Claim any unclaimed arguments, so as
  186. // to avoid emitting warnings about unused args.
  187. OptSpecifier OutputOpts[] = { options::OPT_o, options::OPT_MD,
  188. options::OPT_MMD };
  189. for (unsigned i = 0, e = llvm::array_lengthof(OutputOpts); i != e; ++i) {
  190. if (TranslatedArgs->hasArg(OutputOpts[i]))
  191. TranslatedArgs->eraseArg(OutputOpts[i]);
  192. }
  193. TranslatedArgs->ClaimAllArgs();
  194. // Redirect stdout/stderr to /dev/null.
  195. Redirects = new const StringRef*[3]();
  196. Redirects[0] = nullptr;
  197. Redirects[1] = new const StringRef();
  198. Redirects[2] = new const StringRef();
  199. }
  200. StringRef Compilation::getSysRoot() const {
  201. return getDriver().SysRoot;
  202. }