forked from OSchip/llvm-project
Add ASTUnit::LoadFromCommandLine, which creates an ASTUnit out of a list of
(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. llvm-svn: 90288
This commit is contained in:
parent
120c77e4e9
commit
55a17b66cd
|
@ -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">;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -17,8 +17,13 @@
|
|||
#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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue