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