CreateInvocationFromCommandLine.cpp revision 239462
155714Skris//===--- CreateInvocationFromCommandLine.cpp - CompilerInvocation from Args ==//
255714Skris//
355714Skris//                     The LLVM Compiler Infrastructure
455714Skris//
555714Skris// This file is distributed under the University of Illinois Open Source
655714Skris// License. See LICENSE.TXT for details.
755714Skris//
8280297Sjkim//===----------------------------------------------------------------------===//
955714Skris//
1055714Skris// Construct a compiler invocation object for command line driver arguments
1155714Skris//
1255714Skris//===----------------------------------------------------------------------===//
1355714Skris
1455714Skris#include "clang/Frontend/Utils.h"
15280297Sjkim#include "clang/Frontend/CompilerInstance.h"
1655714Skris#include "clang/Frontend/DiagnosticOptions.h"
1755714Skris#include "clang/Frontend/FrontendDiagnostic.h"
1855714Skris#include "clang/Driver/Compilation.h"
1955714Skris#include "clang/Driver/Driver.h"
2055714Skris#include "clang/Driver/ArgList.h"
2155714Skris#include "clang/Driver/Options.h"
22280297Sjkim#include "clang/Driver/Tool.h"
2355714Skris#include "llvm/Support/Host.h"
2455714Skrisusing namespace clang;
2555714Skris
2655714Skris/// createInvocationFromCommandLine - Construct a compiler invocation object for
2755714Skris/// a command line argument vector.
2855714Skris///
2955714Skris/// \return A CompilerInvocation, or 0 if none was built for the given
3055714Skris/// argument vector.
3155714SkrisCompilerInvocation *
3255714Skrisclang::createInvocationFromCommandLine(ArrayRef<const char *> ArgList,
3355714Skris                            IntrusiveRefCntPtr<DiagnosticsEngine> Diags) {
3455714Skris  if (!Diags.getPtr()) {
3555714Skris    // No diagnostics engine was provided, so create our own diagnostics object
3655714Skris    // with the default options.
37280297Sjkim    DiagnosticOptions DiagOpts;
3855714Skris    Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgList.size(),
3955714Skris                                                ArgList.begin());
40280297Sjkim  }
4155714Skris
4255714Skris  SmallVector<const char *, 16> Args;
4355714Skris  Args.push_back("<clang>"); // FIXME: Remove dummy argument.
4455714Skris  Args.insert(Args.end(), ArgList.begin(), ArgList.end());
4555714Skris
4655714Skris  // FIXME: Find a cleaner way to force the driver into restricted modes.
4755714Skris  Args.push_back("-fsyntax-only");
4855714Skris
4955714Skris  // FIXME: We shouldn't have to pass in the path info.
5055714Skris  driver::Driver TheDriver("clang", llvm::sys::getDefaultTargetTriple(),
5155714Skris                           "a.out", false, *Diags);
52280297Sjkim  // Force driver to use clang.
5355714Skris  // FIXME: This seems like a hack. Maybe the "Clang" tool subclass should be
5455714Skris  // available for using it to get the arguments, thus avoiding the overkill
5555714Skris  // of using the driver.
5655714Skris  TheDriver.setForcedClangUse();
5755714Skris
5855714Skris  // Don't check that inputs exist, they may have been remapped.
5955714Skris  TheDriver.setCheckInputsExist(false);
6055714Skris
6155714Skris  OwningPtr<driver::Compilation> C(TheDriver.BuildCompilation(Args));
6255714Skris
6355714Skris  // Just print the cc1 options if -### was present.
6455714Skris  if (C->getArgs().hasArg(driver::options::OPT__HASH_HASH_HASH)) {
6555714Skris    C->PrintJob(llvm::errs(), C->getJobs(), "\n", true);
66280297Sjkim    return 0;
67280297Sjkim  }
68280297Sjkim
6955714Skris  // We expect to get back exactly one command job, if we didn't something
70280297Sjkim  // failed.
71280297Sjkim  const driver::JobList &Jobs = C->getJobs();
7255714Skris  if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) {
73280297Sjkim    SmallString<256> Msg;
74280297Sjkim    llvm::raw_svector_ostream OS(Msg);
75280297Sjkim    C->PrintJob(OS, C->getJobs(), "; ", true);
76280297Sjkim    Diags->Report(diag::err_fe_expected_compiler_job) << OS.str();
7755714Skris    return 0;
78280297Sjkim  }
79280297Sjkim
8055714Skris  const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
81280297Sjkim  if (StringRef(Cmd->getCreator().getName()) != "clang") {
82280297Sjkim    Diags->Report(diag::err_fe_expected_clang_command);
83280297Sjkim    return 0;
84280297Sjkim  }
85280297Sjkim
86280297Sjkim  const driver::ArgStringList &CCArgs = Cmd->getArguments();
87280297Sjkim  OwningPtr<CompilerInvocation> CI(new CompilerInvocation());
88280297Sjkim  if (!CompilerInvocation::CreateFromArgs(*CI,
89280297Sjkim                                     const_cast<const char **>(CCArgs.data()),
90280297Sjkim                                     const_cast<const char **>(CCArgs.data()) +
91280297Sjkim                                     CCArgs.size(),
92280297Sjkim                                     *Diags))
93280297Sjkim    return 0;
94280297Sjkim  return CI.take();
95280297Sjkim}
96280297Sjkim