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