要查找基礎類型,AST是一個很好的工作級別。 Clang可以使用AST Matchers和Callbacks自動執行和擴展此過程,並與libtooling結合使用。例如,AST匹配組合
fieldDecl(hasType(tyoedefType().bind("typedef"))).bind("field")
將匹配被聲明與一個typedef代替C結構域內置型。調用bind()
使AST節點可以訪問回調。這裏有一個回調,其run()
方法獲取基礎類型的字段聲明:
virtual void run(clang::ast_matchers::MatchFinder::MatchResult const & result) override
{
using namespace clang;
FieldDecl * f_decl =
const_cast<FieldDecl *>(result.Nodes.getNodeAs<FieldDecl>("field"));
TypedefType * tt = const_cast<TypedefType *>(
result.Nodes.getNodeAs<TypedefType>("typedef"));
if(f_decl && tt) {
QualType ut = tt->getDecl()->getUnderlyingType();
TypedefNameDecl * tnd = tt->getDecl();
std::string struct_name = f_decl->getParent()->getNameAsString();
std::string fld_name = f_decl->getNameAsString();
std::string ut_name = ut.getAsString();
std::string tnd_name = tnd->getNameAsString();
std::cout << "Struct '" << struct_name << "' declares field '"
<< fld_name << " with typedef name = '" << tnd_name << "'"
<< ", underlying type = '" << ut_name << "'" << std::endl;
}
else {
// error handling
}
return;
} // run
一旦被放入Clang的工具和內置,運行
typedef-report Foo.h -- # Note two dashes
產生
Struct 'Foo' declares field 'a' with typedef name = 'M_Int', underlying type = 'int'
Struct 'Foo' declares field 'p_f' with typedef name = 'P_Float', underlying type = 'float *'
我在Code Analysis and Refactoring Examples with Clang Tools project中放置了一個完整的工作示例應用程序(請參閱apps/TypedefFinder.cc)。