我正在阅读Getting Started with LLVM Core Libraries
书,并尝试实现第100页Chapter 4: Frontend
的示例。但是在代码clang::ParseAST(CI.getSema());
的最后一行出现了错误:
[bash@bash book]$ ./book_clang test.c
fatal error: error opening file '<invalid loc>':
我应该添加些什么来准备
ParseAST
?码:
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/Support/CommandLine.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "llvm/Support/Host.h"
#include <memory>
#include <string>
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Frontend/ASTConsumers.h"
#include "llvm/Support/raw_ostream.h"
#include "clang/Parse/ParseAST.h"
#include "clang/AST/ASTContext.h"
static llvm::cl::opt<std::string> fileName(llvm::cl::Positional, llvm::cl::desc("Input file"), llvm::cl::Required);
int main(int argc, char **argv)
{
llvm::cl::ParseCommandLineOptions(argc, argv, "My simple front end\n");
clang::CompilerInstance CI;
clang::DiagnosticOptions diagnosticOptions;
CI.createDiagnostics();
std::shared_ptr<clang::TargetOptions> PTO = std::make_shared<clang::TargetOptions>();
PTO->Triple = llvm::sys::getDefaultTargetTriple();
clang::TargetInfo *PTI = clang::TargetInfo::CreateTargetInfo(CI.getDiagnostics(), PTO);
CI.setTarget(PTI);
CI.createFileManager();//References getFileSystemOpts(), clang::vfs::getRealFileSystem(), hasVirtualFileSystem(), and setVirtualFileSystem().
CI.createSourceManager( CI.getFileManager());//References getDiagnostics().
CI.createPreprocessor(clang::TU_Complete);
CI.getPreprocessorOpts().UsePredefines = false;
std::unique_ptr< clang::ASTConsumer > astConsumer = clang::CreateASTPrinter(NULL, "");
CI.setASTConsumer(std::move(astConsumer));
CI.createASTContext();
CI.createSema(clang::TU_Complete, NULL);//after getASTConsumer(), getASTContext(), and getPreprocessor().
const clang::FileEntry *file = CI.getFileManager().getFile(fileName);
if (!file) {
llvm::errs() << "File not found: " << fileName;
return 1;
}
CI.getSourceManager().createFileID(file, clang::SourceLocation(), clang::SrcMgr::C_User);
CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0);
clang::ParseAST(CI.getSema());
// Print AST statistics
// CI.getASTContext().PrintStats();
// CI.getASTContext().Idents.PrintStats();
return 0;
}
对于可执行文件,需要传递c文件,例如:
test.c
int main() {
char *msg = "Hello, world!\n";
write(1, msg, 14);
return 0;
}
最佳答案
问题已经解决了。需要为MainFileID
的CompilerInstence
设置SourceManager
clang::FileID mainFileID = CI.getSourceManager().createFileID(file, clang::SourceLocation(), clang::SrcMgr::C_User);
CI.getSourceManager().setMainFileID(mainFileID);
问题是
clang::ParseAST
调用(S
是Sema
)S.getPreprocessor().EnterMainSourceFile();
调用SourceMgr.getMainFileID();
void Preprocessor::EnterMainSourceFile() {
assert(NumEnteredSourceFiles == 0 && "Cannot reenter the main file!");
FileID MainFileID = SourceMgr.getMainFileID();
但是
MainFileID
尚未设置已更正的完整代码是:
#include "llvm/Support/CommandLine.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "llvm/Support/Host.h"
#include <memory>
#include <string>
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Frontend/ASTConsumers.h"
#include "llvm/Support/raw_ostream.h"
#include "clang/Parse/ParseAST.h"
#include "clang/AST/ASTContext.h"
static llvm::cl::opt<std::string> fileName(llvm::cl::Positional, llvm::cl::desc("Input file"), llvm::cl::Required);
int main(int argc, char **argv)
{
llvm::cl::ParseCommandLineOptions(argc, argv, "My simple front end\n");
clang::CompilerInstance CI;
clang::DiagnosticOptions diagnosticOptions;
CI.createDiagnostics();
std::shared_ptr<clang::TargetOptions> PTO = std::make_shared<clang::TargetOptions>();
PTO->Triple = llvm::sys::getDefaultTargetTriple();
clang::TargetInfo *PTI = clang::TargetInfo::CreateTargetInfo(CI.getDiagnostics(), PTO);
CI.setTarget(PTI);
CI.createFileManager();//References getFileSystemOpts(), clang::vfs::getRealFileSystem(), hasVirtualFileSystem(), and setVirtualFileSystem().
CI.createSourceManager( CI.getFileManager());//References getDiagnostics().
CI.createPreprocessor(clang::TU_Complete);
CI.getPreprocessorOpts().UsePredefines = false;
std::unique_ptr< clang::ASTConsumer > astConsumer = clang::CreateASTPrinter(NULL, "");
CI.setASTConsumer(std::move(astConsumer));
CI.createASTContext();
CI.createSema(clang::TU_Complete, NULL);//after getASTConsumer(), getASTContext(), and getPreprocessor().
const clang::FileEntry *file = CI.getFileManager().getFile(fileName);
if (!file) {
llvm::errs() << "File not found: " << fileName;
return 1;
}
clang::FileID mainFileID = CI.getSourceManager().createFileID(file, clang::SourceLocation(), clang::SrcMgr::C_User);
CI.getSourceManager().setMainFileID(mainFileID);
CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0);
clang::ParseAST(CI.getSema());
// Print AST statistics
CI.getASTContext().PrintStats();
CI.getASTContext().Idents.PrintStats();
return 0;
}