我现在正在使用 LLVM + Clang 。我使用 ASTUnit 来构建树,然后使用 RecursiveASTVisitor 来遍历树。
clang::ASTUnit* AST;
clang::DiagnosticOptions diagOpts;
llvm::IntrusiveRefCntPtr<clang::Diagnostic> diags = clang::CompilerInstance::createDiagnostics(diagOpts, 0, 0);
const char** ptr = new const char*[1];
ptr[0] = argv[1];
clang::CompilerInvocation *ci = new clang::CompilerInvocation();
clang::CompilerInvocation::CreateFromArgs(*ci, ptr, ptr+1, *diags);
ci->setLangDefaults(clang::IK_CXX, clang::LangStandard::lang_cxx98);
ci->getPreprocessorOutputOpts().ShowComments = 1;
ci->getPreprocessorOutputOpts().ShowLineMarkers = 1;
AST = clang::ASTUnit::LoadFromCompilerInvocation(ci, diags);
...
...
MyRecursiveASTVisitor myvis(AST->getASTContext());
myvis.TraverseDecl(AST->getASTContext().getTranslationUnitDecl());
我想避免访问包含的系统库。有可能吗?
答案 0 :(得分:3)
我想我找到了某种解决方案,但不是最后一种解决方案!
在继承的ASTVisitor类中:
class MyRecursiveASTVisitor : public clang::RecursiveASTVisitor<MyRecursiveASTVisitor>
您可以覆盖功能 TraverseDecl 。在此函数中,您可以遍历声明。如果不以递归方式调用此函数,则当声明不是来自主文件时,可以避免遍历其他文件中的声明。
bool TraverseDecl ( clang::Decl *D )
{
bool rval;
if (!D) return true;
if (sm.isFromMainFile(D->getLocation()) || std::string(D->getDeclKindName()) == "TranslationUnit")
{
bool rval = clang::RecursiveASTVisitor<MyRecursiveASTVisitor>::TraverseDecl(D);
}
else
rval = true;
return rval;
}
在此上下文中, sm 是 MyRecursiveASTVisitor 类的 clang :: SourceManager 。您可以在覆盖的 TraverseStmt 函数中避免遍历来自其他文件的语句。
现在我只知道如何声明声明或声明是来自系统库还是用户定义的库。