 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
67.5% |
54 / 80 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
75.0% |
60 / 80 |
| |
|
Line Coverage: |
88.0% |
73 / 83 |
| |
 |
|
 |
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 :
12 : #include "clang/Driver/Action.h"
13 : #include "clang/Driver/ArgList.h"
14 : #include "clang/Driver/Driver.h"
15 : #include "clang/Driver/DriverDiagnostic.h"
16 : #include "clang/Driver/Options.h"
17 : #include "clang/Driver/ToolChain.h"
18 :
19 : #include "llvm/Support/raw_ostream.h"
20 : #include "llvm/System/Program.h"
21 : #include <sys/stat.h>
22 : #include <errno.h>
23 : using namespace clang::driver;
24 :
25 : Compilation::Compilation(const Driver &D,
26 : const ToolChain &_DefaultToolChain,
27 248: InputArgList *_Args)
28 248: : TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args) {
29 248: }
30 :
31 248: Compilation::~Compilation() {
248: branch 0 taken
0: branch 1 not taken
248: branch 3 taken
248: branch 4 taken
32 248: delete Args;
33 :
34 : // Free any derived arg lists.
207: branch 3 taken
248: branch 4 taken
0: branch 8 not taken
0: branch 9 not taken
35 455: for (llvm::DenseMap<std::pair<const ToolChain*, const char*>,
36 248: DerivedArgList*>::iterator it = TCArgs.begin(),
37 248: ie = TCArgs.end(); it != ie; ++it)
207: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
0: branch 6 not taken
38 207: delete it->second;
39 :
40 : // Free the actions, if built.
235: branch 2 taken
248: branch 3 taken
0: branch 6 not taken
0: branch 7 not taken
41 483: for (ActionList::iterator it = Actions.begin(), ie = Actions.end();
42 : it != ie; ++it)
235: branch 0 taken
0: branch 1 not taken
235: branch 3 taken
235: branch 4 taken
43 235: delete *it;
44 248: }
45 :
46 : const DerivedArgList &Compilation::getArgsForToolChain(const ToolChain *TC,
47 235: const char *BoundArch) {
0: branch 0 not taken
235: branch 1 taken
48 235: if (!TC)
49 0: TC = &DefaultToolChain;
50 :
51 235: DerivedArgList *&Entry = TCArgs[std::make_pair(TC, BoundArch)];
207: branch 0 taken
28: branch 1 taken
52 235: if (!Entry)
53 207: Entry = TC->TranslateArgs(*Args, BoundArch);
54 :
55 235: return *Entry;
56 : }
57 :
58 : void Compilation::PrintJob(llvm::raw_ostream &OS, const Job &J,
59 138: const char *Terminator, bool Quote) const {
84: branch 1 taken
54: branch 2 taken
60 138: if (const Command *C = dyn_cast<Command>(&J)) {
61 84: OS << " \"" << C->getExecutable() << '"';
1614: branch 2 taken
84: branch 3 taken
62 1782: for (ArgStringList::const_iterator it = C->getArguments().begin(),
63 84: ie = C->getArguments().end(); it != ie; ++it) {
1580: branch 0 taken
34: branch 1 taken
64 1614: if (Quote)
65 1580: OS << " \"" << *it << '"';
66 : else
67 34: OS << ' ' << *it;
68 : }
69 84: OS << Terminator;
2: branch 1 taken
52: branch 2 taken
70 54: } else if (const PipedJob *PJ = dyn_cast<PipedJob>(&J)) {
2: branch 0 taken
2: branch 1 taken
71 4: for (PipedJob::const_iterator
72 2: it = PJ->begin(), ie = PJ->end(); it != ie; ++it)
0: branch 1 not taken
2: branch 2 taken
73 2: PrintJob(OS, **it, (it + 1 != PJ->end()) ? " |\n" : "\n", Quote);
74 : } else {
75 52: const JobList *Jobs = cast<JobList>(&J);
81: branch 0 taken
52: branch 1 taken
76 133: for (JobList::const_iterator
77 52: it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it)
78 81: PrintJob(OS, **it, Terminator, Quote);
79 : }
80 138: }
81 :
82 : bool Compilation::CleanupFileList(const ArgStringList &Files,
83 188: bool IssueErrors) const {
84 188: bool Success = true;
85 :
2: branch 1 taken
11: branch 2 taken
2: branch 4 taken
11: branch 5 taken
13: branch 6 taken
188: branch 7 taken
86 214: for (ArgStringList::const_iterator
87 188: it = Files.begin(), ie = Files.end(); it != ie; ++it) {
88 :
89 13: llvm::sys::Path P(*it);
90 13: std::string Error;
91 :
11: branch 1 taken
2: branch 2 taken
92 13: if (!P.isRegularFile()) {
93 : // If we have a special file in our list, i.e. /dev/null
94 : // then don't call eraseFromDisk() and just continue.
95 11: continue;
96 : }
97 :
0: branch 1 not taken
2: branch 2 taken
98 2: if (P.eraseFromDisk(false, &Error)) {
99 : // Failure is only failure if the file doesn't exist. There is a
100 : // race condition here due to the limited interface of
101 : // llvm::sys::Path, we want to know if the removal gave E_NOENT.
102 :
103 : // FIXME: Grumble, P.exists() is broken. PR3837.
104 : struct stat buf;
0: branch 2 not taken
0: branch 3 not taken
0: branch 5 not taken
0: branch 6 not taken
0: branch 7 not taken
0: branch 8 not taken
105 0: if (::stat(P.c_str(), &buf) == 0
106 : || errno != ENOENT) {
0: branch 0 not taken
0: branch 1 not taken
107 0: if (IssueErrors)
108 : getDriver().Diag(clang::diag::err_drv_unable_to_remove_file)
109 0: << Error;
110 0: Success = false;
111 : }
112 : }
113 : }
114 :
115 188: return Success;
116 : }
117 :
118 : int Compilation::ExecuteCommand(const Command &C,
119 144: const Command *&FailingCommand) const {
120 144: llvm::sys::Path Prog(C.getExecutable());
121 144: const char **Argv = new const char*[C.getArguments().size() + 2];
122 144: Argv[0] = C.getExecutable();
123 144: std::copy(C.getArguments().begin(), C.getArguments().end(), Argv+1);
124 144: Argv[C.getArguments().size() + 1] = 0;
125 :
141: branch 1 taken
3: branch 2 taken
0: branch 6 not taken
141: branch 7 taken
3: branch 8 taken
141: branch 9 taken
126 144: if (getDriver().CCCEcho || getArgs().hasArg(options::OPT_v))
127 3: PrintJob(llvm::errs(), C, "\n", false);
128 :
129 144: std::string Error;
130 : int Res =
131 : llvm::sys::Program::ExecuteAndWait(Prog, Argv,
132 : /*env*/0, /*redirects*/0,
133 : /*secondsToWait*/0, /*memoryLimit*/0,
134 144: &Error);
0: branch 1 not taken
144: branch 2 taken
135 144: if (!Error.empty()) {
0: branch 0 not taken
0: branch 1 not taken
136 0: assert(Res && "Error string set with 0 result code!");
137 0: getDriver().Diag(clang::diag::err_drv_command_failure) << Error;
138 : }
139 :
5: branch 0 taken
139: branch 1 taken
140 144: if (Res)
141 5: FailingCommand = &C;
142 :
144: branch 0 taken
0: branch 1 not taken
143 144: delete[] Argv;
144 144: return Res;
145 : }
146 :
147 : int Compilation::ExecuteJob(const Job &J,
148 327: const Command *&FailingCommand) const {
134: branch 1 taken
193: branch 2 taken
149 327: if (const Command *C = dyn_cast<Command>(&J)) {
150 134: return ExecuteCommand(*C, FailingCommand);
10: branch 1 taken
183: branch 2 taken
151 193: } else if (const PipedJob *PJ = dyn_cast<PipedJob>(&J)) {
152 : // Piped commands with a single job are easy.
10: branch 1 taken
0: branch 2 not taken
153 10: if (PJ->size() == 1)
154 10: return ExecuteCommand(**PJ->begin(), FailingCommand);
155 :
156 0: FailingCommand = *PJ->begin();
157 0: getDriver().Diag(clang::diag::err_drv_unsupported_opt) << "-pipe";
158 0: return 1;
159 : } else {
160 183: const JobList *Jobs = cast<JobList>(&J);
144: branch 0 taken
178: branch 1 taken
161 322: for (JobList::const_iterator
162 183: it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it)
5: branch 1 taken
139: branch 2 taken
163 144: if (int Res = ExecuteJob(**it, FailingCommand))
164 5: return Res;
165 178: return 0;
166 : }
167 : }
Generated: 2010-02-10 01:31 by zcov