1*02d32aecSArgyrios Kyrtzidis //===--- CreateInvocationFromCommandLine.cpp - CompilerInvocation from Args ==// 2*02d32aecSArgyrios Kyrtzidis // 3*02d32aecSArgyrios Kyrtzidis // The LLVM Compiler Infrastructure 4*02d32aecSArgyrios Kyrtzidis // 5*02d32aecSArgyrios Kyrtzidis // This file is distributed under the University of Illinois Open Source 6*02d32aecSArgyrios Kyrtzidis // License. See LICENSE.TXT for details. 7*02d32aecSArgyrios Kyrtzidis // 8*02d32aecSArgyrios Kyrtzidis //===----------------------------------------------------------------------===// 9*02d32aecSArgyrios Kyrtzidis // 10*02d32aecSArgyrios Kyrtzidis // Construct a compiler invocation object for command line driver arguments 11*02d32aecSArgyrios Kyrtzidis // 12*02d32aecSArgyrios Kyrtzidis //===----------------------------------------------------------------------===// 13*02d32aecSArgyrios Kyrtzidis 14*02d32aecSArgyrios Kyrtzidis #include "clang/Frontend/Utils.h" 15*02d32aecSArgyrios Kyrtzidis #include "clang/Frontend/CompilerInstance.h" 16*02d32aecSArgyrios Kyrtzidis #include "clang/Frontend/DiagnosticOptions.h" 17*02d32aecSArgyrios Kyrtzidis #include "clang/Frontend/FrontendDiagnostic.h" 18*02d32aecSArgyrios Kyrtzidis #include "clang/Driver/Compilation.h" 19*02d32aecSArgyrios Kyrtzidis #include "clang/Driver/Driver.h" 20*02d32aecSArgyrios Kyrtzidis #include "clang/Driver/ArgList.h" 21*02d32aecSArgyrios Kyrtzidis #include "clang/Driver/Options.h" 22*02d32aecSArgyrios Kyrtzidis #include "clang/Driver/Tool.h" 23*02d32aecSArgyrios Kyrtzidis #include "llvm/Support/Host.h" 24*02d32aecSArgyrios Kyrtzidis using namespace clang; 25*02d32aecSArgyrios Kyrtzidis 26*02d32aecSArgyrios Kyrtzidis /// createInvocationFromCommandLine - Construct a compiler invocation object for 27*02d32aecSArgyrios Kyrtzidis /// a command line argument vector. 28*02d32aecSArgyrios Kyrtzidis /// 29*02d32aecSArgyrios Kyrtzidis /// \return A CompilerInvocation, or 0 if none was built for the given 30*02d32aecSArgyrios Kyrtzidis /// argument vector. 31*02d32aecSArgyrios Kyrtzidis CompilerInvocation * 32*02d32aecSArgyrios Kyrtzidis clang::createInvocationFromCommandLine(llvm::ArrayRef<const char *> ArgList, 33*02d32aecSArgyrios Kyrtzidis llvm::IntrusiveRefCntPtr<Diagnostic> Diags) { 34*02d32aecSArgyrios Kyrtzidis if (!Diags.getPtr()) { 35*02d32aecSArgyrios Kyrtzidis // No diagnostics engine was provided, so create our own diagnostics object 36*02d32aecSArgyrios Kyrtzidis // with the default options. 37*02d32aecSArgyrios Kyrtzidis DiagnosticOptions DiagOpts; 38*02d32aecSArgyrios Kyrtzidis Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgList.size(), 39*02d32aecSArgyrios Kyrtzidis ArgList.begin()); 40*02d32aecSArgyrios Kyrtzidis } 41*02d32aecSArgyrios Kyrtzidis 42*02d32aecSArgyrios Kyrtzidis llvm::SmallVector<const char *, 16> Args; 43*02d32aecSArgyrios Kyrtzidis Args.push_back("<clang>"); // FIXME: Remove dummy argument. 44*02d32aecSArgyrios Kyrtzidis Args.insert(Args.end(), ArgList.begin(), ArgList.end()); 45*02d32aecSArgyrios Kyrtzidis 46*02d32aecSArgyrios Kyrtzidis // FIXME: Find a cleaner way to force the driver into restricted modes. We 47*02d32aecSArgyrios Kyrtzidis // also want to force it to use clang. 48*02d32aecSArgyrios Kyrtzidis Args.push_back("-fsyntax-only"); 49*02d32aecSArgyrios Kyrtzidis 50*02d32aecSArgyrios Kyrtzidis // FIXME: We shouldn't have to pass in the path info. 51*02d32aecSArgyrios Kyrtzidis driver::Driver TheDriver("clang", llvm::sys::getHostTriple(), 52*02d32aecSArgyrios Kyrtzidis "a.out", false, false, *Diags); 53*02d32aecSArgyrios Kyrtzidis 54*02d32aecSArgyrios Kyrtzidis // Don't check that inputs exist, they may have been remapped. 55*02d32aecSArgyrios Kyrtzidis TheDriver.setCheckInputsExist(false); 56*02d32aecSArgyrios Kyrtzidis 57*02d32aecSArgyrios Kyrtzidis llvm::OwningPtr<driver::Compilation> C(TheDriver.BuildCompilation(Args)); 58*02d32aecSArgyrios Kyrtzidis 59*02d32aecSArgyrios Kyrtzidis // Just print the cc1 options if -### was present. 60*02d32aecSArgyrios Kyrtzidis if (C->getArgs().hasArg(driver::options::OPT__HASH_HASH_HASH)) { 61*02d32aecSArgyrios Kyrtzidis C->PrintJob(llvm::errs(), C->getJobs(), "\n", true); 62*02d32aecSArgyrios Kyrtzidis return 0; 63*02d32aecSArgyrios Kyrtzidis } 64*02d32aecSArgyrios Kyrtzidis 65*02d32aecSArgyrios Kyrtzidis // We expect to get back exactly one command job, if we didn't something 66*02d32aecSArgyrios Kyrtzidis // failed. 67*02d32aecSArgyrios Kyrtzidis const driver::JobList &Jobs = C->getJobs(); 68*02d32aecSArgyrios Kyrtzidis if (Jobs.size() != 1 || !isa<driver::Command>(Jobs.begin())) { 69*02d32aecSArgyrios Kyrtzidis llvm::SmallString<256> Msg; 70*02d32aecSArgyrios Kyrtzidis llvm::raw_svector_ostream OS(Msg); 71*02d32aecSArgyrios Kyrtzidis C->PrintJob(OS, C->getJobs(), "; ", true); 72*02d32aecSArgyrios Kyrtzidis Diags->Report(diag::err_fe_expected_compiler_job) << OS.str(); 73*02d32aecSArgyrios Kyrtzidis return 0; 74*02d32aecSArgyrios Kyrtzidis } 75*02d32aecSArgyrios Kyrtzidis 76*02d32aecSArgyrios Kyrtzidis const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin()); 77*02d32aecSArgyrios Kyrtzidis if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") { 78*02d32aecSArgyrios Kyrtzidis Diags->Report(diag::err_fe_expected_clang_command); 79*02d32aecSArgyrios Kyrtzidis return 0; 80*02d32aecSArgyrios Kyrtzidis } 81*02d32aecSArgyrios Kyrtzidis 82*02d32aecSArgyrios Kyrtzidis const driver::ArgStringList &CCArgs = Cmd->getArguments(); 83*02d32aecSArgyrios Kyrtzidis CompilerInvocation *CI = new CompilerInvocation(); 84*02d32aecSArgyrios Kyrtzidis CompilerInvocation::CreateFromArgs(*CI, 85*02d32aecSArgyrios Kyrtzidis const_cast<const char **>(CCArgs.data()), 86*02d32aecSArgyrios Kyrtzidis const_cast<const char **>(CCArgs.data()) + 87*02d32aecSArgyrios Kyrtzidis CCArgs.size(), 88*02d32aecSArgyrios Kyrtzidis *Diags); 89*02d32aecSArgyrios Kyrtzidis return CI; 90*02d32aecSArgyrios Kyrtzidis } 91