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 
26 using namespace clang::driver;
27 using namespace clang;
28 using namespace llvm::opt;
29 
30 Compilation::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 
36 Compilation::~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 
60 const 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 
75 void 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 
106 static 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 
149 static bool quoteNextArg(const char *flag) {
150   return llvm::StringSwitch<bool>(flag)
151     .Case("-D", true)
152     .Default(false);
153 }
154 
155 void 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 
205 bool 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 
233 bool 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 
242 bool 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 
258 int Compilation::ExecuteCommand(const Command &C,
259                                 const Command *&FailingCommand) const {
260   llvm::sys::Path 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.str(), 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 
312 typedef SmallVectorImpl< std::pair<int, const Command *> > FailingCommandList;
313 
314 static 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 
332 static bool InputsOk(const Command &C,
333                      const FailingCommandList &FailingCommands) {
334   return !ActionFailed(&C.getSource(), FailingCommands);
335 }
336 
337 void 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 
353 void 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 
380 StringRef Compilation::getSysRoot() const {
381   return getDriver().SysRoot;
382 }
383