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