clang API Documentation

CreateInvocationFromCommandLine.cpp
Go to the documentation of this file.
00001 //===--- CreateInvocationFromCommandLine.cpp - CompilerInvocation from Args ==//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // Construct a compiler invocation object for command line driver arguments
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "clang/Frontend/Utils.h"
00015 #include "clang/Frontend/CompilerInstance.h"
00016 #include "clang/Frontend/DiagnosticOptions.h"
00017 #include "clang/Frontend/FrontendDiagnostic.h"
00018 #include "clang/Driver/Compilation.h"
00019 #include "clang/Driver/Driver.h"
00020 #include "clang/Driver/ArgList.h"
00021 #include "clang/Driver/Options.h"
00022 #include "clang/Driver/Tool.h"
00023 #include "llvm/Support/Host.h"
00024 using namespace clang;
00025 
00026 /// createInvocationFromCommandLine - Construct a compiler invocation object for
00027 /// a command line argument vector.
00028 ///
00029 /// \return A CompilerInvocation, or 0 if none was built for the given
00030 /// argument vector.
00031 CompilerInvocation *
00032 clang::createInvocationFromCommandLine(ArrayRef<const char *> ArgList,
00033                             IntrusiveRefCntPtr<DiagnosticsEngine> Diags) {
00034   if (!Diags.getPtr()) {
00035     // No diagnostics engine was provided, so create our own diagnostics object
00036     // with the default options.
00037     DiagnosticOptions DiagOpts;
00038     Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgList.size(),
00039                                                 ArgList.begin());
00040   }
00041 
00042   SmallVector<const char *, 16> Args;
00043   Args.push_back("<clang>"); // FIXME: Remove dummy argument.
00044   Args.insert(Args.end(), ArgList.begin(), ArgList.end());
00045 
00046   // FIXME: Find a cleaner way to force the driver into restricted modes. We
00047   // also want to force it to use clang.
00048   Args.push_back("-fsyntax-only");
00049 
00050   // FIXME: We shouldn't have to pass in the path info.
00051   driver::Driver TheDriver("clang", llvm::sys::getDefaultTargetTriple(),
00052                            "a.out", false, *Diags);
00053 
00054   // Don't check that inputs exist, they may have been remapped.
00055   TheDriver.setCheckInputsExist(false);
00056 
00057   OwningPtr<driver::Compilation> C(TheDriver.BuildCompilation(Args));
00058 
00059   // Just print the cc1 options if -### was present.
00060   if (C->getArgs().hasArg(driver::options::OPT__HASH_HASH_HASH)) {
00061     C->PrintJob(llvm::errs(), C->getJobs(), "\n", true);
00062     return 0;
00063   }
00064 
00065   // We expect to get back exactly one command job, if we didn't something
00066   // failed.
00067   const driver::JobList &Jobs = C->getJobs();
00068   if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) {
00069     SmallString<256> Msg;
00070     llvm::raw_svector_ostream OS(Msg);
00071     C->PrintJob(OS, C->getJobs(), "; ", true);
00072     Diags->Report(diag::err_fe_expected_compiler_job) << OS.str();
00073     return 0;
00074   }
00075 
00076   const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
00077   if (StringRef(Cmd->getCreator().getName()) != "clang") {
00078     Diags->Report(diag::err_fe_expected_clang_command);
00079     return 0;
00080   }
00081 
00082   const driver::ArgStringList &CCArgs = Cmd->getArguments();
00083   OwningPtr<CompilerInvocation> CI(new CompilerInvocation());
00084   if (!CompilerInvocation::CreateFromArgs(*CI,
00085                                      const_cast<const char **>(CCArgs.data()),
00086                                      const_cast<const char **>(CCArgs.data()) +
00087                                      CCArgs.size(),
00088                                      *Diags))
00089     return 0;
00090   return CI.take();
00091 }