driver.cpp revision 1.1 1 1.1 joerg //===-- driver.cpp - Clang GCC-Compatible Driver --------------------------===//
2 1.1 joerg //
3 1.1 joerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 1.1 joerg // See https://llvm.org/LICENSE.txt for license information.
5 1.1 joerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 1.1 joerg //
7 1.1 joerg //===----------------------------------------------------------------------===//
8 1.1 joerg //
9 1.1 joerg // This is the entry point to the clang driver; it is a thin wrapper
10 1.1 joerg // for functionality in the Driver clang library.
11 1.1 joerg //
12 1.1 joerg //===----------------------------------------------------------------------===//
13 1.1 joerg
14 1.1 joerg #include "clang/Driver/Driver.h"
15 1.1 joerg #include "clang/Basic/DiagnosticOptions.h"
16 1.1 joerg #include "clang/Basic/Stack.h"
17 1.1 joerg #include "clang/Driver/Compilation.h"
18 1.1 joerg #include "clang/Driver/DriverDiagnostic.h"
19 1.1 joerg #include "clang/Driver/Options.h"
20 1.1 joerg #include "clang/Driver/ToolChain.h"
21 1.1 joerg #include "clang/Frontend/ChainedDiagnosticConsumer.h"
22 1.1 joerg #include "clang/Frontend/CompilerInvocation.h"
23 1.1 joerg #include "clang/Frontend/SerializedDiagnosticPrinter.h"
24 1.1 joerg #include "clang/Frontend/TextDiagnosticPrinter.h"
25 1.1 joerg #include "clang/Frontend/Utils.h"
26 1.1 joerg #include "llvm/ADT/ArrayRef.h"
27 1.1 joerg #include "llvm/ADT/SmallString.h"
28 1.1 joerg #include "llvm/ADT/SmallVector.h"
29 1.1 joerg #include "llvm/Option/ArgList.h"
30 1.1 joerg #include "llvm/Option/OptTable.h"
31 1.1 joerg #include "llvm/Option/Option.h"
32 1.1 joerg #include "llvm/Support/CommandLine.h"
33 1.1 joerg #include "llvm/Support/ErrorHandling.h"
34 1.1 joerg #include "llvm/Support/FileSystem.h"
35 1.1 joerg #include "llvm/Support/Host.h"
36 1.1 joerg #include "llvm/Support/InitLLVM.h"
37 1.1 joerg #include "llvm/Support/Path.h"
38 1.1 joerg #include "llvm/Support/Process.h"
39 1.1 joerg #include "llvm/Support/Program.h"
40 1.1 joerg #include "llvm/Support/Regex.h"
41 1.1 joerg #include "llvm/Support/Signals.h"
42 1.1 joerg #include "llvm/Support/StringSaver.h"
43 1.1 joerg #include "llvm/Support/TargetSelect.h"
44 1.1 joerg #include "llvm/Support/Timer.h"
45 1.1 joerg #include "llvm/Support/raw_ostream.h"
46 1.1 joerg #include <memory>
47 1.1 joerg #include <set>
48 1.1 joerg #include <system_error>
49 1.1 joerg using namespace clang;
50 1.1 joerg using namespace clang::driver;
51 1.1 joerg using namespace llvm::opt;
52 1.1 joerg
53 1.1 joerg std::string GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) {
54 1.1 joerg if (!CanonicalPrefixes) {
55 1.1 joerg SmallString<128> ExecutablePath(Argv0);
56 1.1 joerg // Do a PATH lookup if Argv0 isn't a valid path.
57 1.1 joerg if (!llvm::sys::fs::exists(ExecutablePath))
58 1.1 joerg if (llvm::ErrorOr<std::string> P =
59 1.1 joerg llvm::sys::findProgramByName(ExecutablePath))
60 1.1 joerg ExecutablePath = *P;
61 1.1 joerg return ExecutablePath.str();
62 1.1 joerg }
63 1.1 joerg
64 1.1 joerg // This just needs to be some symbol in the binary; C++ doesn't
65 1.1 joerg // allow taking the address of ::main however.
66 1.1 joerg void *P = (void*) (intptr_t) GetExecutablePath;
67 1.1 joerg return llvm::sys::fs::getMainExecutable(Argv0, P);
68 1.1 joerg }
69 1.1 joerg
70 1.1 joerg static const char *GetStableCStr(std::set<std::string> &SavedStrings,
71 1.1 joerg StringRef S) {
72 1.1 joerg return SavedStrings.insert(S).first->c_str();
73 1.1 joerg }
74 1.1 joerg
75 1.1 joerg /// ApplyQAOverride - Apply a list of edits to the input argument lists.
76 1.1 joerg ///
77 1.1 joerg /// The input string is a space separate list of edits to perform,
78 1.1 joerg /// they are applied in order to the input argument lists. Edits
79 1.1 joerg /// should be one of the following forms:
80 1.1 joerg ///
81 1.1 joerg /// '#': Silence information about the changes to the command line arguments.
82 1.1 joerg ///
83 1.1 joerg /// '^': Add FOO as a new argument at the beginning of the command line.
84 1.1 joerg ///
85 1.1 joerg /// '+': Add FOO as a new argument at the end of the command line.
86 1.1 joerg ///
87 1.1 joerg /// 's/XXX/YYY/': Substitute the regular expression XXX with YYY in the command
88 1.1 joerg /// line.
89 1.1 joerg ///
90 1.1 joerg /// 'xOPTION': Removes all instances of the literal argument OPTION.
91 1.1 joerg ///
92 1.1 joerg /// 'XOPTION': Removes all instances of the literal argument OPTION,
93 1.1 joerg /// and the following argument.
94 1.1 joerg ///
95 1.1 joerg /// 'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox'
96 1.1 joerg /// at the end of the command line.
97 1.1 joerg ///
98 1.1 joerg /// \param OS - The stream to write edit information to.
99 1.1 joerg /// \param Args - The vector of command line arguments.
100 1.1 joerg /// \param Edit - The override command to perform.
101 1.1 joerg /// \param SavedStrings - Set to use for storing string representations.
102 1.1 joerg static void ApplyOneQAOverride(raw_ostream &OS,
103 1.1 joerg SmallVectorImpl<const char*> &Args,
104 1.1 joerg StringRef Edit,
105 1.1 joerg std::set<std::string> &SavedStrings) {
106 1.1 joerg // This does not need to be efficient.
107 1.1 joerg
108 1.1 joerg if (Edit[0] == '^') {
109 1.1 joerg const char *Str =
110 1.1 joerg GetStableCStr(SavedStrings, Edit.substr(1));
111 1.1 joerg OS << "### Adding argument " << Str << " at beginning\n";
112 1.1 joerg Args.insert(Args.begin() + 1, Str);
113 1.1 joerg } else if (Edit[0] == '+') {
114 1.1 joerg const char *Str =
115 1.1 joerg GetStableCStr(SavedStrings, Edit.substr(1));
116 1.1 joerg OS << "### Adding argument " << Str << " at end\n";
117 1.1 joerg Args.push_back(Str);
118 1.1 joerg } else if (Edit[0] == 's' && Edit[1] == '/' && Edit.endswith("/") &&
119 1.1 joerg Edit.slice(2, Edit.size()-1).find('/') != StringRef::npos) {
120 1.1 joerg StringRef MatchPattern = Edit.substr(2).split('/').first;
121 1.1 joerg StringRef ReplPattern = Edit.substr(2).split('/').second;
122 1.1 joerg ReplPattern = ReplPattern.slice(0, ReplPattern.size()-1);
123 1.1 joerg
124 1.1 joerg for (unsigned i = 1, e = Args.size(); i != e; ++i) {
125 1.1 joerg // Ignore end-of-line response file markers
126 1.1 joerg if (Args[i] == nullptr)
127 1.1 joerg continue;
128 1.1 joerg std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]);
129 1.1 joerg
130 1.1 joerg if (Repl != Args[i]) {
131 1.1 joerg OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n";
132 1.1 joerg Args[i] = GetStableCStr(SavedStrings, Repl);
133 1.1 joerg }
134 1.1 joerg }
135 1.1 joerg } else if (Edit[0] == 'x' || Edit[0] == 'X') {
136 1.1 joerg auto Option = Edit.substr(1);
137 1.1 joerg for (unsigned i = 1; i < Args.size();) {
138 1.1 joerg if (Option == Args[i]) {
139 1.1 joerg OS << "### Deleting argument " << Args[i] << '\n';
140 1.1 joerg Args.erase(Args.begin() + i);
141 1.1 joerg if (Edit[0] == 'X') {
142 1.1 joerg if (i < Args.size()) {
143 1.1 joerg OS << "### Deleting argument " << Args[i] << '\n';
144 1.1 joerg Args.erase(Args.begin() + i);
145 1.1 joerg } else
146 1.1 joerg OS << "### Invalid X edit, end of command line!\n";
147 1.1 joerg }
148 1.1 joerg } else
149 1.1 joerg ++i;
150 1.1 joerg }
151 1.1 joerg } else if (Edit[0] == 'O') {
152 1.1 joerg for (unsigned i = 1; i < Args.size();) {
153 1.1 joerg const char *A = Args[i];
154 1.1 joerg // Ignore end-of-line response file markers
155 1.1 joerg if (A == nullptr)
156 1.1 joerg continue;
157 1.1 joerg if (A[0] == '-' && A[1] == 'O' &&
158 1.1 joerg (A[2] == '\0' ||
159 1.1 joerg (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' ||
160 1.1 joerg ('0' <= A[2] && A[2] <= '9'))))) {
161 1.1 joerg OS << "### Deleting argument " << Args[i] << '\n';
162 1.1 joerg Args.erase(Args.begin() + i);
163 1.1 joerg } else
164 1.1 joerg ++i;
165 1.1 joerg }
166 1.1 joerg OS << "### Adding argument " << Edit << " at end\n";
167 1.1 joerg Args.push_back(GetStableCStr(SavedStrings, '-' + Edit.str()));
168 1.1 joerg } else {
169 1.1 joerg OS << "### Unrecognized edit: " << Edit << "\n";
170 1.1 joerg }
171 1.1 joerg }
172 1.1 joerg
173 1.1 joerg /// ApplyQAOverride - Apply a comma separate list of edits to the
174 1.1 joerg /// input argument lists. See ApplyOneQAOverride.
175 1.1 joerg static void ApplyQAOverride(SmallVectorImpl<const char*> &Args,
176 1.1 joerg const char *OverrideStr,
177 1.1 joerg std::set<std::string> &SavedStrings) {
178 1.1 joerg raw_ostream *OS = &llvm::errs();
179 1.1 joerg
180 1.1 joerg if (OverrideStr[0] == '#') {
181 1.1 joerg ++OverrideStr;
182 1.1 joerg OS = &llvm::nulls();
183 1.1 joerg }
184 1.1 joerg
185 1.1 joerg *OS << "### CCC_OVERRIDE_OPTIONS: " << OverrideStr << "\n";
186 1.1 joerg
187 1.1 joerg // This does not need to be efficient.
188 1.1 joerg
189 1.1 joerg const char *S = OverrideStr;
190 1.1 joerg while (*S) {
191 1.1 joerg const char *End = ::strchr(S, ' ');
192 1.1 joerg if (!End)
193 1.1 joerg End = S + strlen(S);
194 1.1 joerg if (End != S)
195 1.1 joerg ApplyOneQAOverride(*OS, Args, std::string(S, End), SavedStrings);
196 1.1 joerg S = End;
197 1.1 joerg if (*S != '\0')
198 1.1 joerg ++S;
199 1.1 joerg }
200 1.1 joerg }
201 1.1 joerg
202 1.1 joerg extern int cc1_main(ArrayRef<const char *> Argv, const char *Argv0,
203 1.1 joerg void *MainAddr);
204 1.1 joerg extern int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0,
205 1.1 joerg void *MainAddr);
206 1.1 joerg extern int cc1gen_reproducer_main(ArrayRef<const char *> Argv,
207 1.1 joerg const char *Argv0, void *MainAddr);
208 1.1 joerg
209 1.1 joerg static void insertTargetAndModeArgs(const ParsedClangName &NameParts,
210 1.1 joerg SmallVectorImpl<const char *> &ArgVector,
211 1.1 joerg std::set<std::string> &SavedStrings) {
212 1.1 joerg // Put target and mode arguments at the start of argument list so that
213 1.1 joerg // arguments specified in command line could override them. Avoid putting
214 1.1 joerg // them at index 0, as an option like '-cc1' must remain the first.
215 1.1 joerg int InsertionPoint = 0;
216 1.1 joerg if (ArgVector.size() > 0)
217 1.1 joerg ++InsertionPoint;
218 1.1 joerg
219 1.1 joerg if (NameParts.DriverMode) {
220 1.1 joerg // Add the mode flag to the arguments.
221 1.1 joerg ArgVector.insert(ArgVector.begin() + InsertionPoint,
222 1.1 joerg GetStableCStr(SavedStrings, NameParts.DriverMode));
223 1.1 joerg }
224 1.1 joerg
225 1.1 joerg if (NameParts.TargetIsValid) {
226 1.1 joerg const char *arr[] = {"-target", GetStableCStr(SavedStrings,
227 1.1 joerg NameParts.TargetPrefix)};
228 1.1 joerg ArgVector.insert(ArgVector.begin() + InsertionPoint,
229 1.1 joerg std::begin(arr), std::end(arr));
230 1.1 joerg }
231 1.1 joerg }
232 1.1 joerg
233 1.1 joerg static void getCLEnvVarOptions(std::string &EnvValue, llvm::StringSaver &Saver,
234 1.1 joerg SmallVectorImpl<const char *> &Opts) {
235 1.1 joerg llvm::cl::TokenizeWindowsCommandLine(EnvValue, Saver, Opts);
236 1.1 joerg // The first instance of '#' should be replaced with '=' in each option.
237 1.1 joerg for (const char *Opt : Opts)
238 1.1 joerg if (char *NumberSignPtr = const_cast<char *>(::strchr(Opt, '#')))
239 1.1 joerg *NumberSignPtr = '=';
240 1.1 joerg }
241 1.1 joerg
242 1.1 joerg static void SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) {
243 1.1 joerg // Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE.
244 1.1 joerg TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS");
245 1.1 joerg if (TheDriver.CCPrintOptions)
246 1.1 joerg TheDriver.CCPrintOptionsFilename = ::getenv("CC_PRINT_OPTIONS_FILE");
247 1.1 joerg
248 1.1 joerg // Handle CC_PRINT_HEADERS and CC_PRINT_HEADERS_FILE.
249 1.1 joerg TheDriver.CCPrintHeaders = !!::getenv("CC_PRINT_HEADERS");
250 1.1 joerg if (TheDriver.CCPrintHeaders)
251 1.1 joerg TheDriver.CCPrintHeadersFilename = ::getenv("CC_PRINT_HEADERS_FILE");
252 1.1 joerg
253 1.1 joerg // Handle CC_LOG_DIAGNOSTICS and CC_LOG_DIAGNOSTICS_FILE.
254 1.1 joerg TheDriver.CCLogDiagnostics = !!::getenv("CC_LOG_DIAGNOSTICS");
255 1.1 joerg if (TheDriver.CCLogDiagnostics)
256 1.1 joerg TheDriver.CCLogDiagnosticsFilename = ::getenv("CC_LOG_DIAGNOSTICS_FILE");
257 1.1 joerg }
258 1.1 joerg
259 1.1 joerg static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient,
260 1.1 joerg const std::string &Path) {
261 1.1 joerg // If the clang binary happens to be named cl.exe for compatibility reasons,
262 1.1 joerg // use clang-cl.exe as the prefix to avoid confusion between clang and MSVC.
263 1.1 joerg StringRef ExeBasename(llvm::sys::path::stem(Path));
264 1.1 joerg if (ExeBasename.equals_lower("cl"))
265 1.1 joerg ExeBasename = "clang-cl";
266 1.1 joerg DiagClient->setPrefix(ExeBasename);
267 1.1 joerg }
268 1.1 joerg
269 1.1 joerg // This lets us create the DiagnosticsEngine with a properly-filled-out
270 1.1 joerg // DiagnosticOptions instance.
271 1.1 joerg static DiagnosticOptions *
272 1.1 joerg CreateAndPopulateDiagOpts(ArrayRef<const char *> argv) {
273 1.1 joerg auto *DiagOpts = new DiagnosticOptions;
274 1.1 joerg unsigned MissingArgIndex, MissingArgCount;
275 1.1 joerg InputArgList Args = getDriverOptTable().ParseArgs(
276 1.1 joerg argv.slice(1), MissingArgIndex, MissingArgCount);
277 1.1 joerg // We ignore MissingArgCount and the return value of ParseDiagnosticArgs.
278 1.1 joerg // Any errors that would be diagnosed here will also be diagnosed later,
279 1.1 joerg // when the DiagnosticsEngine actually exists.
280 1.1 joerg (void)ParseDiagnosticArgs(*DiagOpts, Args);
281 1.1 joerg return DiagOpts;
282 1.1 joerg }
283 1.1 joerg
284 1.1 joerg static void SetInstallDir(SmallVectorImpl<const char *> &argv,
285 1.1 joerg Driver &TheDriver, bool CanonicalPrefixes) {
286 1.1 joerg // Attempt to find the original path used to invoke the driver, to determine
287 1.1 joerg // the installed path. We do this manually, because we want to support that
288 1.1 joerg // path being a symlink.
289 1.1 joerg SmallString<128> InstalledPath(argv[0]);
290 1.1 joerg
291 1.1 joerg // Do a PATH lookup, if there are no directory components.
292 1.1 joerg if (llvm::sys::path::filename(InstalledPath) == InstalledPath)
293 1.1 joerg if (llvm::ErrorOr<std::string> Tmp = llvm::sys::findProgramByName(
294 1.1 joerg llvm::sys::path::filename(InstalledPath.str())))
295 1.1 joerg InstalledPath = *Tmp;
296 1.1 joerg
297 1.1 joerg // FIXME: We don't actually canonicalize this, we just make it absolute.
298 1.1 joerg if (CanonicalPrefixes)
299 1.1 joerg llvm::sys::fs::make_absolute(InstalledPath);
300 1.1 joerg
301 1.1 joerg StringRef InstalledPathParent(llvm::sys::path::parent_path(InstalledPath));
302 1.1 joerg if (llvm::sys::fs::exists(InstalledPathParent))
303 1.1 joerg TheDriver.setInstalledDir(InstalledPathParent);
304 1.1 joerg }
305 1.1 joerg
306 1.1 joerg static int ExecuteCC1Tool(ArrayRef<const char *> argv, StringRef Tool) {
307 1.1 joerg void *GetExecutablePathVP = (void *)(intptr_t) GetExecutablePath;
308 1.1 joerg if (Tool == "")
309 1.1 joerg return cc1_main(argv.slice(2), argv[0], GetExecutablePathVP);
310 1.1 joerg if (Tool == "as")
311 1.1 joerg return cc1as_main(argv.slice(2), argv[0], GetExecutablePathVP);
312 1.1 joerg if (Tool == "gen-reproducer")
313 1.1 joerg return cc1gen_reproducer_main(argv.slice(2), argv[0], GetExecutablePathVP);
314 1.1 joerg
315 1.1 joerg // Reject unknown tools.
316 1.1 joerg llvm::errs() << "error: unknown integrated tool '" << Tool << "'. "
317 1.1 joerg << "Valid tools include '-cc1' and '-cc1as'.\n";
318 1.1 joerg return 1;
319 1.1 joerg }
320 1.1 joerg
321 1.1 joerg int main(int argc_, const char **argv_) {
322 1.1 joerg noteBottomOfStack();
323 1.1 joerg llvm::InitLLVM X(argc_, argv_);
324 1.1 joerg SmallVector<const char *, 256> argv(argv_, argv_ + argc_);
325 1.1 joerg
326 1.1 joerg if (llvm::sys::Process::FixupStandardFileDescriptors())
327 1.1 joerg return 1;
328 1.1 joerg
329 1.1 joerg llvm::InitializeAllTargets();
330 1.1 joerg auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(argv[0]);
331 1.1 joerg
332 1.1 joerg llvm::BumpPtrAllocator A;
333 1.1 joerg llvm::StringSaver Saver(A);
334 1.1 joerg
335 1.1 joerg // Parse response files using the GNU syntax, unless we're in CL mode. There
336 1.1 joerg // are two ways to put clang in CL compatibility mode: argv[0] is either
337 1.1 joerg // clang-cl or cl, or --driver-mode=cl is on the command line. The normal
338 1.1 joerg // command line parsing can't happen until after response file parsing, so we
339 1.1 joerg // have to manually search for a --driver-mode=cl argument the hard way.
340 1.1 joerg // Finally, our -cc1 tools don't care which tokenization mode we use because
341 1.1 joerg // response files written by clang will tokenize the same way in either mode.
342 1.1 joerg bool ClangCLMode = false;
343 1.1 joerg if (StringRef(TargetAndMode.DriverMode).equals("--driver-mode=cl") ||
344 1.1 joerg llvm::find_if(argv, [](const char *F) {
345 1.1 joerg return F && strcmp(F, "--driver-mode=cl") == 0;
346 1.1 joerg }) != argv.end()) {
347 1.1 joerg ClangCLMode = true;
348 1.1 joerg }
349 1.1 joerg enum { Default, POSIX, Windows } RSPQuoting = Default;
350 1.1 joerg for (const char *F : argv) {
351 1.1 joerg if (strcmp(F, "--rsp-quoting=posix") == 0)
352 1.1 joerg RSPQuoting = POSIX;
353 1.1 joerg else if (strcmp(F, "--rsp-quoting=windows") == 0)
354 1.1 joerg RSPQuoting = Windows;
355 1.1 joerg }
356 1.1 joerg
357 1.1 joerg // Determines whether we want nullptr markers in argv to indicate response
358 1.1 joerg // files end-of-lines. We only use this for the /LINK driver argument with
359 1.1 joerg // clang-cl.exe on Windows.
360 1.1 joerg bool MarkEOLs = ClangCLMode;
361 1.1 joerg
362 1.1 joerg llvm::cl::TokenizerCallback Tokenizer;
363 1.1 joerg if (RSPQuoting == Windows || (RSPQuoting == Default && ClangCLMode))
364 1.1 joerg Tokenizer = &llvm::cl::TokenizeWindowsCommandLine;
365 1.1 joerg else
366 1.1 joerg Tokenizer = &llvm::cl::TokenizeGNUCommandLine;
367 1.1 joerg
368 1.1 joerg if (MarkEOLs && argv.size() > 1 && StringRef(argv[1]).startswith("-cc1"))
369 1.1 joerg MarkEOLs = false;
370 1.1 joerg llvm::cl::ExpandResponseFiles(Saver, Tokenizer, argv, MarkEOLs);
371 1.1 joerg
372 1.1 joerg // Handle -cc1 integrated tools, even if -cc1 was expanded from a response
373 1.1 joerg // file.
374 1.1 joerg auto FirstArg = std::find_if(argv.begin() + 1, argv.end(),
375 1.1 joerg [](const char *A) { return A != nullptr; });
376 1.1 joerg if (FirstArg != argv.end() && StringRef(*FirstArg).startswith("-cc1")) {
377 1.1 joerg // If -cc1 came from a response file, remove the EOL sentinels.
378 1.1 joerg if (MarkEOLs) {
379 1.1 joerg auto newEnd = std::remove(argv.begin(), argv.end(), nullptr);
380 1.1 joerg argv.resize(newEnd - argv.begin());
381 1.1 joerg }
382 1.1 joerg return ExecuteCC1Tool(argv, argv[1] + 4);
383 1.1 joerg }
384 1.1 joerg
385 1.1 joerg bool CanonicalPrefixes = true;
386 1.1 joerg for (int i = 1, size = argv.size(); i < size; ++i) {
387 1.1 joerg // Skip end-of-line response file markers
388 1.1 joerg if (argv[i] == nullptr)
389 1.1 joerg continue;
390 1.1 joerg if (StringRef(argv[i]) == "-no-canonical-prefixes") {
391 1.1 joerg CanonicalPrefixes = false;
392 1.1 joerg break;
393 1.1 joerg }
394 1.1 joerg }
395 1.1 joerg
396 1.1 joerg // Handle CL and _CL_ which permits additional command line options to be
397 1.1 joerg // prepended or appended.
398 1.1 joerg if (ClangCLMode) {
399 1.1 joerg // Arguments in "CL" are prepended.
400 1.1 joerg llvm::Optional<std::string> OptCL = llvm::sys::Process::GetEnv("CL");
401 1.1 joerg if (OptCL.hasValue()) {
402 1.1 joerg SmallVector<const char *, 8> PrependedOpts;
403 1.1 joerg getCLEnvVarOptions(OptCL.getValue(), Saver, PrependedOpts);
404 1.1 joerg
405 1.1 joerg // Insert right after the program name to prepend to the argument list.
406 1.1 joerg argv.insert(argv.begin() + 1, PrependedOpts.begin(), PrependedOpts.end());
407 1.1 joerg }
408 1.1 joerg // Arguments in "_CL_" are appended.
409 1.1 joerg llvm::Optional<std::string> Opt_CL_ = llvm::sys::Process::GetEnv("_CL_");
410 1.1 joerg if (Opt_CL_.hasValue()) {
411 1.1 joerg SmallVector<const char *, 8> AppendedOpts;
412 1.1 joerg getCLEnvVarOptions(Opt_CL_.getValue(), Saver, AppendedOpts);
413 1.1 joerg
414 1.1 joerg // Insert at the end of the argument list to append.
415 1.1 joerg argv.append(AppendedOpts.begin(), AppendedOpts.end());
416 1.1 joerg }
417 1.1 joerg }
418 1.1 joerg
419 1.1 joerg std::set<std::string> SavedStrings;
420 1.1 joerg // Handle CCC_OVERRIDE_OPTIONS, used for editing a command line behind the
421 1.1 joerg // scenes.
422 1.1 joerg if (const char *OverrideStr = ::getenv("CCC_OVERRIDE_OPTIONS")) {
423 1.1 joerg // FIXME: Driver shouldn't take extra initial argument.
424 1.1 joerg ApplyQAOverride(argv, OverrideStr, SavedStrings);
425 1.1 joerg }
426 1.1 joerg
427 1.1 joerg std::string Path = GetExecutablePath(argv[0], CanonicalPrefixes);
428 1.1 joerg
429 1.1 joerg IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts =
430 1.1 joerg CreateAndPopulateDiagOpts(argv);
431 1.1 joerg
432 1.1 joerg TextDiagnosticPrinter *DiagClient
433 1.1 joerg = new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts);
434 1.1 joerg FixupDiagPrefixExeName(DiagClient, Path);
435 1.1 joerg
436 1.1 joerg IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
437 1.1 joerg
438 1.1 joerg DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);
439 1.1 joerg
440 1.1 joerg if (!DiagOpts->DiagnosticSerializationFile.empty()) {
441 1.1 joerg auto SerializedConsumer =
442 1.1 joerg clang::serialized_diags::create(DiagOpts->DiagnosticSerializationFile,
443 1.1 joerg &*DiagOpts, /*MergeChildRecords=*/true);
444 1.1 joerg Diags.setClient(new ChainedDiagnosticConsumer(
445 1.1 joerg Diags.takeClient(), std::move(SerializedConsumer)));
446 1.1 joerg }
447 1.1 joerg
448 1.1 joerg ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false);
449 1.1 joerg
450 1.1 joerg Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags);
451 1.1 joerg SetInstallDir(argv, TheDriver, CanonicalPrefixes);
452 1.1 joerg TheDriver.setTargetAndMode(TargetAndMode);
453 1.1 joerg
454 1.1 joerg insertTargetAndModeArgs(TargetAndMode, argv, SavedStrings);
455 1.1 joerg
456 1.1 joerg SetBackdoorDriverOutputsFromEnvVars(TheDriver);
457 1.1 joerg
458 1.1 joerg std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(argv));
459 1.1 joerg int Res = 1;
460 1.1 joerg if (C && !C->containsError()) {
461 1.1 joerg SmallVector<std::pair<int, const Command *>, 4> FailingCommands;
462 1.1 joerg Res = TheDriver.ExecuteCompilation(*C, FailingCommands);
463 1.1 joerg
464 1.1 joerg // Force a crash to test the diagnostics.
465 1.1 joerg if (TheDriver.GenReproducer) {
466 1.1 joerg Diags.Report(diag::err_drv_force_crash)
467 1.1 joerg << !::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH");
468 1.1 joerg
469 1.1 joerg // Pretend that every command failed.
470 1.1 joerg FailingCommands.clear();
471 1.1 joerg for (const auto &J : C->getJobs())
472 1.1 joerg if (const Command *C = dyn_cast<Command>(&J))
473 1.1 joerg FailingCommands.push_back(std::make_pair(-1, C));
474 1.1 joerg }
475 1.1 joerg
476 1.1 joerg for (const auto &P : FailingCommands) {
477 1.1 joerg int CommandRes = P.first;
478 1.1 joerg const Command *FailingCommand = P.second;
479 1.1 joerg if (!Res)
480 1.1 joerg Res = CommandRes;
481 1.1 joerg
482 1.1 joerg // If result status is < 0, then the driver command signalled an error.
483 1.1 joerg // If result status is 70, then the driver command reported a fatal error.
484 1.1 joerg // On Windows, abort will return an exit code of 3. In these cases,
485 1.1 joerg // generate additional diagnostic information if possible.
486 1.1 joerg bool DiagnoseCrash = CommandRes < 0 || CommandRes == 70;
487 1.1 joerg #ifdef _WIN32
488 1.1 joerg DiagnoseCrash |= CommandRes == 3;
489 1.1 joerg #endif
490 1.1 joerg if (DiagnoseCrash) {
491 1.1 joerg TheDriver.generateCompilationDiagnostics(*C, *FailingCommand);
492 1.1 joerg break;
493 1.1 joerg }
494 1.1 joerg }
495 1.1 joerg }
496 1.1 joerg
497 1.1 joerg Diags.getClient()->finish();
498 1.1 joerg
499 1.1 joerg // If any timers were active but haven't been destroyed yet, print their
500 1.1 joerg // results now. This happens in -disable-free mode.
501 1.1 joerg llvm::TimerGroup::printAll(llvm::errs());
502 1.1 joerg llvm::TimerGroup::clearAll();
503 1.1 joerg
504 1.1 joerg #ifdef _WIN32
505 1.1 joerg // Exit status should not be negative on Win32, unless abnormal termination.
506 1.1 joerg // Once abnormal termiation was caught, negative status should not be
507 1.1 joerg // propagated.
508 1.1 joerg if (Res < 0)
509 1.1 joerg Res = 1;
510 1.1 joerg #endif
511 1.1 joerg
512 1.1 joerg // If we have multiple failing commands, we return the result of the first
513 1.1 joerg // failing command.
514 1.1 joerg return Res;
515 1.1 joerg }
516