Coverage Report

Created: 2020-02-18 08:44

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