]> granicus.if.org Git - clang/commitdiff
Add ASTUnit::LoadFromCommandLine, which creates an ASTUnit out of a list of
authorDaniel Dunbar <daniel@zuster.org>
Wed, 2 Dec 2009 03:23:45 +0000 (03:23 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Wed, 2 Dec 2009 03:23:45 +0000 (03:23 +0000)
(clang/driver) command line arguments (including the source file).
 - The arguments are expected to include the source file.

 - The idea is that even though this is a somewhat odd API, its the form which
   many tools can most easily use (for example, by interposing with the compiler).

Also, switch index-test's -ast-from-source to use this entry point, and provide
a -arg command line argument which can be used to test that the command line
arguments are handled correctly.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90288 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticFrontendKinds.td
include/clang/Frontend/ASTUnit.h
lib/Frontend/ASTUnit.cpp
tools/index-test/index-test.cpp

index cbc287c58c8987dbb8a1001874c8da5324874ef4..9dbd9cfa210992a6c2dc6d20c5662ecc8a16efa1 100644 (file)
@@ -15,8 +15,8 @@ def err_fe_error_reading_stdin : Error<"error reading stdin">;
 def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal;
 def err_fe_invalid_ast_file : Error<"invalid AST file: '%0'">, DefaultFatal;
 def err_fe_invalid_ast_action : Error<"invalid action for AST input">, DefaultFatal;
-def err_fe_invalid_code_complete_file
-  : Error<"cannot locate code-completion file %0">, DefaultFatal;
+def err_fe_invalid_code_complete_file : Error<
+    "cannot locate code-completion file %0">, DefaultFatal;
 def err_fe_stdout_binary : Error<"unable to change standard output to binary">,
   DefaultFatal;
 def err_fe_dependency_file_requires_MT : Error<
@@ -29,6 +29,10 @@ def err_fe_unable_to_find_fixit_file : Error<
     "FIX-IT could not find file '%0'">;
 def err_fe_invalid_plugin_name : Error<
     "unable to find plugin '%0'">;
+def err_fe_expected_compiler_job : Error<
+    "unable to handle compilation, expected exactly one compiler job in '%0'">;
+def err_fe_expected_clang_command : Error<
+    "expected a clang compiler command">;
 
 def err_verify_bogus_characters : Error<
     "bogus characters before '{{' in expected string">;
index 04dc5ed8cc5639e5c7733aeec59f8f9f88251848..c55638a2370956d974c9f2f9fb3d44a725d3ce90 100644 (file)
@@ -122,6 +122,30 @@ public:
                                              bool OnlyLocalDecls = false,
                                              bool UseBumpAllocator = false);
 
+  /// LoadFromCommandLine - Create an ASTUnit from a vector of command line
+  /// arguments, which must specify exactly one source file.
+  ///
+  /// \param ArgBegin - The beginning of the argument vector.
+  ///
+  /// \param ArgEnd - The end of the argument vector.
+  ///
+  /// \param Diags - The diagnostics engine to use for reporting errors.
+  ///
+  /// \param Argv0 - The program path (from argv[0]), for finding the builtin
+  /// compiler path.
+  ///
+  /// \param MainAddr - The address of main (or some other function in the main
+  /// executable), for finding the builtin compiler path.
+  //
+  // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
+  // shouldn't need to specify them at construction time.
+  static ASTUnit *LoadFromCommandLine(const char **ArgBegin,
+                                      const char **ArgEnd,
+                                      Diagnostic &Diags,
+                                      const char *Arg0,
+                                      void *MainAddr,
+                                      bool OnlyLocalDecls = false,
+                                      bool UseBumpAllocator = false);
 };
 
 } // namespace clang
index 3f07b880f795e274d9343738ba66c9b76d1a823b..6e3a1e1fa7b73c9682ca73ac034a6673200bde02 100644 (file)
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/DeclVisitor.h"
 #include "clang/AST/StmtVisitor.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Job.h"
+#include "clang/Driver/Tool.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/FrontendActions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
 #include "clang/Frontend/FrontendOptions.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/Preprocessor.h"
@@ -26,6 +31,7 @@
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/Diagnostic.h"
 #include "llvm/LLVMContext.h"
+#include "llvm/System/Host.h"
 #include "llvm/System/Path.h"
 using namespace clang;
 
@@ -262,3 +268,52 @@ error:
   Clang.takeDiagnostics();
   return 0;
 }
+
+ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
+                                      const char **ArgEnd,
+                                      Diagnostic &Diags,
+                                      const char *Argv0,
+                                      void *MainAddr,
+                                      bool OnlyLocalDecls,
+                                      bool UseBumpAllocator) {
+  llvm::SmallVector<const char *, 16> Args;
+  Args.push_back("<clang>"); // FIXME: Remove dummy argument.
+  Args.insert(Args.end(), ArgBegin, ArgEnd);
+
+  // FIXME: Find a cleaner way to force the driver into restricted modes. We
+  // also want to force it to use clang.
+  Args.push_back("-fsyntax-only");
+
+  llvm::sys::Path Path = llvm::sys::Path::GetMainExecutable(Argv0, MainAddr);
+  driver::Driver TheDriver(Path.getBasename().c_str(),Path.getDirname().c_str(),
+                           llvm::sys::getHostTriple().c_str(),
+                           "a.out", false, Diags);
+  llvm::OwningPtr<driver::Compilation> C(
+    TheDriver.BuildCompilation(Args.size(), Args.data()));
+
+  // We expect to get back exactly one command job, if we didn't something
+  // failed.
+  const driver::JobList &Jobs = C->getJobs();
+  if (Jobs.size() != 1 || !isa<driver::Command>(Jobs.begin())) {
+    llvm::SmallString<256> Msg;
+    llvm::raw_svector_ostream OS(Msg);
+    C->PrintJob(OS, C->getJobs(), "; ", true);
+    Diags.Report(diag::err_fe_expected_compiler_job) << OS.str();
+    return 0;
+  }
+
+  const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
+  if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
+    Diags.Report(diag::err_fe_expected_clang_command);
+    return 0;
+  }
+
+  const driver::ArgStringList &CCArgs = Cmd->getArguments();
+  CompilerInvocation CI;
+  CompilerInvocation::CreateFromArgs(CI, (const char**) CCArgs.data(),
+                                     (const char**) CCArgs.data()+CCArgs.size(),
+                                     Argv0, MainAddr, Diags);
+
+  return LoadFromCompilerInvocation(CI, Diags, OnlyLocalDecls,
+                                    UseBumpAllocator);
+}
index dd7cbb21642c914ce834c34a69dc92deba6882b6..fc8547b784c5fef9d9703d3478130befb6fde3d8 100644 (file)
@@ -208,20 +208,24 @@ static void ProcessASTLocation(ASTLocation ASTLoc, Indexer &Idxer) {
 
 static llvm::cl::opt<bool>
 ASTFromSource("ast-from-source",
-              llvm::cl::desc("Treat the inputs as source files to parse."));
+              llvm::cl::desc("Treat the inputs as source files to parse"));
+
+static llvm::cl::list<std::string>
+CompilerArgs("arg", llvm::cl::desc("Extra arguments to use during parsing"));
 
 static llvm::cl::list<std::string>
 InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input AST files>"));
 
-void CreateCompilerInvocation(const std::string &Filename,
-                              CompilerInvocation &CI, Diagnostic &Diags,
-                              const char *argv0) {
+ASTUnit *CreateFromSource(const std::string &Filename, Diagnostic &Diags,
+                          const char *Argv0) {
   llvm::SmallVector<const char *, 16> Args;
   Args.push_back(Filename.c_str());
+  for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i)
+    Args.push_back(CompilerArgs[i].c_str());
 
-  void *MainAddr = (void*) (intptr_t) CreateCompilerInvocation;
-  CompilerInvocation::CreateFromArgs(CI, Args.data(), Args.data() + Args.size(),
-                                     argv0, MainAddr, Diags);
+  return ASTUnit::LoadFromCommandLine(Args.data(), Args.data() + Args.size(),
+                                      Diags, Argv0,
+                                      (void*) (intptr_t) CreateFromSource);
 }
 
 int main(int argc, char **argv) {
@@ -249,10 +253,8 @@ int main(int argc, char **argv) {
     llvm::OwningPtr<ASTUnit> AST;
 
     if (ASTFromSource) {
-      CompilerInvocation CI;
-      CreateCompilerInvocation(InFile, CI, *Diags, argv[0]);
-      AST.reset(ASTUnit::LoadFromCompilerInvocation(CI, *Diags));
-      if (!AST)
+      AST.reset(CreateFromSource(InFile, *Diags, argv[0]));
+      if (!AST || Diags->getNumErrors())
         ErrMsg = "unable to create AST";
     } else
       AST.reset(ASTUnit::LoadFromPCHFile(InFile, &ErrMsg));