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