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