driver.cpp revision d5b08bee799d4f77f1a25fa5977ca77b983ab031
1//===-- driver.cpp - Clang GCC-Compatible Driver --------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This is the entry point to the clang driver; it is a thin wrapper
11// for functionality in the Driver clang library.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Driver/Compilation.h"
16#include "clang/Driver/Driver.h"
17#include "clang/Driver/Option.h"
18#include "clang/Frontend/DiagnosticOptions.h"
19#include "clang/Frontend/TextDiagnosticPrinter.h"
20
21#include "llvm/ADT/SmallString.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/ADT/OwningPtr.h"
24#include "llvm/Config/config.h"
25#include "llvm/Support/ErrorHandling.h"
26#include "llvm/Support/ManagedStatic.h"
27#include "llvm/Support/MemoryBuffer.h"
28#include "llvm/Support/PrettyStackTrace.h"
29#include "llvm/Support/Regex.h"
30#include "llvm/Support/Timer.h"
31#include "llvm/Support/raw_ostream.h"
32#include "llvm/Support/Host.h"
33#include "llvm/Support/Path.h"
34#include "llvm/Support/Program.h"
35#include "llvm/Support/Signals.h"
36#include "llvm/Support/system_error.h"
37using namespace clang;
38using namespace clang::driver;
39
40llvm::sys::Path GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) {
41  if (!CanonicalPrefixes)
42    return llvm::sys::Path(Argv0);
43
44  // This just needs to be some symbol in the binary; C++ doesn't
45  // allow taking the address of ::main however.
46  void *P = (void*) (intptr_t) GetExecutablePath;
47  return llvm::sys::Path::GetMainExecutable(Argv0, P);
48}
49
50static const char *SaveStringInSet(std::set<std::string> &SavedStrings,
51                                   llvm::StringRef S) {
52  return SavedStrings.insert(S).first->c_str();
53}
54
55/// ApplyQAOverride - Apply a list of edits to the input argument lists.
56///
57/// The input string is a space separate list of edits to perform,
58/// they are applied in order to the input argument lists. Edits
59/// should be one of the following forms:
60///
61///  '#': Silence information about the changes to the command line arguments.
62///
63///  '^': Add FOO as a new argument at the beginning of the command line.
64///
65///  '+': Add FOO as a new argument at the end of the command line.
66///
67///  's/XXX/YYY/': Substitute the regular expression XXX with YYY in the command
68///  line.
69///
70///  'xOPTION': Removes all instances of the literal argument OPTION.
71///
72///  'XOPTION': Removes all instances of the literal argument OPTION,
73///  and the following argument.
74///
75///  'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox'
76///  at the end of the command line.
77///
78/// \param OS - The stream to write edit information to.
79/// \param Args - The vector of command line arguments.
80/// \param Edit - The override command to perform.
81/// \param SavedStrings - Set to use for storing string representations.
82static void ApplyOneQAOverride(llvm::raw_ostream &OS,
83                               llvm::SmallVectorImpl<const char*> &Args,
84                               llvm::StringRef Edit,
85                               std::set<std::string> &SavedStrings) {
86  // This does not need to be efficient.
87
88  if (Edit[0] == '^') {
89    const char *Str =
90      SaveStringInSet(SavedStrings, Edit.substr(1));
91    OS << "### Adding argument " << Str << " at beginning\n";
92    Args.insert(Args.begin() + 1, Str);
93  } else if (Edit[0] == '+') {
94    const char *Str =
95      SaveStringInSet(SavedStrings, Edit.substr(1));
96    OS << "### Adding argument " << Str << " at end\n";
97    Args.push_back(Str);
98  } else if (Edit[0] == 's' && Edit[1] == '/' && Edit.endswith("/") &&
99             Edit.slice(2, Edit.size()-1).find('/') != llvm::StringRef::npos) {
100    llvm::StringRef MatchPattern = Edit.substr(2).split('/').first;
101    llvm::StringRef ReplPattern = Edit.substr(2).split('/').second;
102    ReplPattern = ReplPattern.slice(0, ReplPattern.size()-1);
103
104    for (unsigned i = 1, e = Args.size(); i != e; ++i) {
105      std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]);
106
107      if (Repl != Args[i]) {
108        OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n";
109        Args[i] = SaveStringInSet(SavedStrings, Repl);
110      }
111    }
112  } else if (Edit[0] == 'x' || Edit[0] == 'X') {
113    std::string Option = Edit.substr(1, std::string::npos);
114    for (unsigned i = 1; i < Args.size();) {
115      if (Option == Args[i]) {
116        OS << "### Deleting argument " << Args[i] << '\n';
117        Args.erase(Args.begin() + i);
118        if (Edit[0] == 'X') {
119          if (i < Args.size()) {
120            OS << "### Deleting argument " << Args[i] << '\n';
121            Args.erase(Args.begin() + i);
122          } else
123            OS << "### Invalid X edit, end of command line!\n";
124        }
125      } else
126        ++i;
127    }
128  } else if (Edit[0] == 'O') {
129    for (unsigned i = 1; i < Args.size();) {
130      const char *A = Args[i];
131      if (A[0] == '-' && A[1] == 'O' &&
132          (A[2] == '\0' ||
133           (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' ||
134                             ('0' <= A[2] && A[2] <= '9'))))) {
135        OS << "### Deleting argument " << Args[i] << '\n';
136        Args.erase(Args.begin() + i);
137      } else
138        ++i;
139    }
140    OS << "### Adding argument " << Edit << " at end\n";
141    Args.push_back(SaveStringInSet(SavedStrings, '-' + Edit.str()));
142  } else {
143    OS << "### Unrecognized edit: " << Edit << "\n";
144  }
145}
146
147/// ApplyQAOverride - Apply a comma separate list of edits to the
148/// input argument lists. See ApplyOneQAOverride.
149static void ApplyQAOverride(llvm::SmallVectorImpl<const char*> &Args,
150                            const char *OverrideStr,
151                            std::set<std::string> &SavedStrings) {
152  llvm::raw_ostream *OS = &llvm::errs();
153
154  if (OverrideStr[0] == '#') {
155    ++OverrideStr;
156    OS = &llvm::nulls();
157  }
158
159  *OS << "### QA_OVERRIDE_GCC3_OPTIONS: " << OverrideStr << "\n";
160
161  // This does not need to be efficient.
162
163  const char *S = OverrideStr;
164  while (*S) {
165    const char *End = ::strchr(S, ' ');
166    if (!End)
167      End = S + strlen(S);
168    if (End != S)
169      ApplyOneQAOverride(*OS, Args, std::string(S, End), SavedStrings);
170    S = End;
171    if (*S != '\0')
172      ++S;
173  }
174}
175
176extern int cc1_main(const char **ArgBegin, const char **ArgEnd,
177                    const char *Argv0, void *MainAddr);
178extern int cc1as_main(const char **ArgBegin, const char **ArgEnd,
179                      const char *Argv0, void *MainAddr);
180
181static void ExpandArgsFromBuf(const char *Arg,
182                              llvm::SmallVectorImpl<const char*> &ArgVector,
183                              std::set<std::string> &SavedStrings) {
184  const char *FName = Arg + 1;
185  llvm::OwningPtr<llvm::MemoryBuffer> MemBuf;
186  if (llvm::MemoryBuffer::getFile(FName, MemBuf)) {
187    ArgVector.push_back(SaveStringInSet(SavedStrings, Arg));
188    return;
189  }
190
191  const char *Buf = MemBuf->getBufferStart();
192  char InQuote = ' ';
193  std::string CurArg;
194
195  for (const char *P = Buf; ; ++P) {
196    if (*P == '\0' || (isspace(*P) && InQuote == ' ')) {
197      if (!CurArg.empty()) {
198
199        if (CurArg[0] != '@') {
200          ArgVector.push_back(SaveStringInSet(SavedStrings, CurArg));
201        } else {
202          ExpandArgsFromBuf(CurArg.c_str(), ArgVector, SavedStrings);
203        }
204
205        CurArg = "";
206      }
207      if (*P == '\0')
208        break;
209      else
210        continue;
211    }
212
213    if (isspace(*P)) {
214      if (InQuote != ' ')
215        CurArg.push_back(*P);
216      continue;
217    }
218
219    if (*P == '"' || *P == '\'') {
220      if (InQuote == *P)
221        InQuote = ' ';
222      else if (InQuote == ' ')
223        InQuote = *P;
224      else
225        CurArg.push_back(*P);
226      continue;
227    }
228
229    if (*P == '\\') {
230      ++P;
231      if (*P != '\0')
232        CurArg.push_back(*P);
233      continue;
234    }
235    CurArg.push_back(*P);
236  }
237}
238
239static void ExpandArgv(int argc, const char **argv,
240                       llvm::SmallVectorImpl<const char*> &ArgVector,
241                       std::set<std::string> &SavedStrings) {
242  for (int i = 0; i < argc; ++i) {
243    const char *Arg = argv[i];
244    if (Arg[0] != '@') {
245      ArgVector.push_back(SaveStringInSet(SavedStrings, std::string(Arg)));
246      continue;
247    }
248
249    ExpandArgsFromBuf(Arg, ArgVector, SavedStrings);
250  }
251}
252
253int main(int argc_, const char **argv_) {
254  llvm::sys::PrintStackTraceOnErrorSignal();
255  llvm::PrettyStackTraceProgram X(argc_, argv_);
256
257  std::set<std::string> SavedStrings;
258  llvm::SmallVector<const char*, 256> argv;
259
260  ExpandArgv(argc_, argv_, argv, SavedStrings);
261
262  // Handle -cc1 integrated tools.
263  if (argv.size() > 1 && llvm::StringRef(argv[1]).startswith("-cc1")) {
264    llvm::StringRef Tool = argv[1] + 4;
265
266    if (Tool == "")
267      return cc1_main(argv.data()+2, argv.data()+argv.size(), argv[0],
268                      (void*) (intptr_t) GetExecutablePath);
269    if (Tool == "as")
270      return cc1as_main(argv.data()+2, argv.data()+argv.size(), argv[0],
271                      (void*) (intptr_t) GetExecutablePath);
272
273    // Reject unknown tools.
274    llvm::errs() << "error: unknown integrated tool '" << Tool << "'\n";
275    return 1;
276  }
277
278  bool CanonicalPrefixes = true;
279  for (int i = 1, size = argv.size(); i < size; ++i) {
280    if (llvm::StringRef(argv[i]) == "-no-canonical-prefixes") {
281      CanonicalPrefixes = false;
282      break;
283    }
284  }
285
286  llvm::sys::Path Path = GetExecutablePath(argv[0], CanonicalPrefixes);
287
288  TextDiagnosticPrinter *DiagClient
289    = new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions());
290  DiagClient->setPrefix(llvm::sys::path::stem(Path.str()));
291  llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
292  Diagnostic Diags(DiagID, DiagClient);
293
294#ifdef CLANG_IS_PRODUCTION
295  const bool IsProduction = true;
296#  ifdef CLANGXX_IS_PRODUCTION
297  const bool CXXIsProduction = true;
298#  else
299  const bool CXXIsProduction = false;
300#  endif
301#else
302  const bool IsProduction = false;
303  const bool CXXIsProduction = false;
304#endif
305  Driver TheDriver(Path.str(), llvm::sys::getHostTriple(),
306                   "a.out", IsProduction, CXXIsProduction,
307                   Diags);
308
309  // Attempt to find the original path used to invoke the driver, to determine
310  // the installed path. We do this manually, because we want to support that
311  // path being a symlink.
312  llvm::sys::Path InstalledPath(argv[0]);
313
314  // Do a PATH lookup, if there are no directory components.
315  if (llvm::sys::path::filename(InstalledPath.str()) == InstalledPath.str()) {
316    llvm::sys::Path Tmp = llvm::sys::Program::FindProgramByName(
317      llvm::sys::path::filename(InstalledPath.str()));
318    if (!Tmp.empty())
319      InstalledPath = Tmp;
320  }
321  InstalledPath.makeAbsolute();
322  InstalledPath.eraseComponent();
323  if (InstalledPath.exists())
324    TheDriver.setInstalledDir(InstalledPath.str());
325
326  // Check for ".*++" or ".*++-[^-]*" to determine if we are a C++
327  // compiler. This matches things like "c++", "clang++", and "clang++-1.1".
328  //
329  // Note that we intentionally want to use argv[0] here, to support "clang++"
330  // being a symlink.
331  //
332  // We use *argv instead of argv[0] to work around a bogus g++ warning.
333  const char *progname = argv_[0];
334  std::string ProgName(llvm::sys::path::stem(progname));
335  if (llvm::StringRef(ProgName).endswith("++") ||
336      llvm::StringRef(ProgName).rsplit('-').first.endswith("++")) {
337    TheDriver.CCCIsCXX = true;
338  }
339
340  // Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE.
341  TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS");
342  if (TheDriver.CCPrintOptions)
343    TheDriver.CCPrintOptionsFilename = ::getenv("CC_PRINT_OPTIONS_FILE");
344
345  // Handle QA_OVERRIDE_GCC3_OPTIONS and CCC_ADD_ARGS, used for editing a
346  // command line behind the scenes.
347  if (const char *OverrideStr = ::getenv("QA_OVERRIDE_GCC3_OPTIONS")) {
348    // FIXME: Driver shouldn't take extra initial argument.
349    ApplyQAOverride(argv, OverrideStr, SavedStrings);
350  } else if (const char *Cur = ::getenv("CCC_ADD_ARGS")) {
351    // FIXME: Driver shouldn't take extra initial argument.
352    std::vector<const char*> ExtraArgs;
353
354    for (;;) {
355      const char *Next = strchr(Cur, ',');
356
357      if (Next) {
358        ExtraArgs.push_back(SaveStringInSet(SavedStrings,
359                                            std::string(Cur, Next)));
360        Cur = Next + 1;
361      } else {
362        if (*Cur != '\0')
363          ExtraArgs.push_back(SaveStringInSet(SavedStrings, Cur));
364        break;
365      }
366    }
367
368    argv.insert(&argv[1], ExtraArgs.begin(), ExtraArgs.end());
369  }
370
371  llvm::OwningPtr<Compilation> C(TheDriver.BuildCompilation(argv.size(),
372                                                            &argv[0]));
373  int Res = 0;
374  if (C.get())
375    Res = TheDriver.ExecuteCompilation(*C);
376
377  // If any timers were active but haven't been destroyed yet, print their
378  // results now.  This happens in -disable-free mode.
379  llvm::TimerGroup::printAll(llvm::errs());
380
381  llvm::llvm_shutdown();
382
383  return Res;
384}
385