原文
ClangAST简介
幻灯片
介绍
Clang的AST与其他一些编译器生成的AST不同,因为它与编写的C++代码和C++标准类似.如,在AST中,按非简化形式提供括号式和编译时常量.
这使得Clang的AST非常适合重构.
可通过生成的Doxygen获得所有ClangAST节点的文档.搜索引擎也会索引doxygen的在线文档,它搜索clang,并且AST节点的类名一般会显示要查找类的doxygen(如,搜索:clangParenExpr).
检查AST
熟悉ClangAST的一个好方法是在一些简单示例代码中,实际查看它.Clang有可用-ast-dump标志启用的内置AST-dump模式.
看看简单AST示例:
$ cat test.cc
int f(int x) {int result = (x / 42);return result;
}
# Clang by default is a frontend for many tools; -Xclang is used to pass
# options directly to the C++ frontend.
$ clang -Xclang -ast-dump -fsyntax-only test.cc
TranslationUnitDecl 0x5aea0d0 <<invalid sloc>>
... 略clang...
`-FunctionDecl 0x5aeab50 <test.cc:1:1, line:4:1> f 'int (int)'|-ParmVarDecl 0x5aeaa90 <line:1:7, col:11> x 'int'`-CompoundStmt 0x5aead88 <col:14, line:4:1>|-DeclStmt 0x5aead10 <line:2:3, col:24>| `-VarDecl 0x5aeac10 <col:3, col:23> result 'int'| `-ParenExpr 0x5aeacf0 <col:16, col:23> 'int'| `-BinaryOperator 0x5aeacc8 <col:17, col:21> 'int' '/'| |-ImplicitCastExpr 0x5aeacb0 <col:17> 'int' <LValueToRValue>| | `-DeclRefExpr 0x5aeac68 <col:17> 'int' lvalue ParmVar 0x5aeaa90 'x' 'int'| `-IntegerLiteral 0x5aeac90 <col:21> 'int' 42`-ReturnStmt 0x5aead68 <line:3:3, col:10>`-ImplicitCastExpr 0x5aead50 <col:10> 'int' <LValueToRValue>`-DeclRefExpr 0x5aead28 <col:10> 'int' lvalue Var 0x5aeac10 'result' 'int'
翻译单元中的顶级声明总是为翻译单元声明这里.本例中,第一个用户书面声明是"f"函数声明."f"的主体是个复合语句这里,其子节点是声明结果变量的声明语句和返回语句.
AST环境
有关翻译单元的AST的所有信息都绑定在ASTContext类中.它允许从getTranslationUnitDecl开始遍历整个翻译单元,或对已解析翻译单元,访问Clang的标识表.
AST节点
Clang的AST节点是按没有共同祖先类层次建模的.相反,(对如Decl和Stmt)基本节点类型有多个较大的层次1,2.
许多重要的AST节点从Type,Decl,DeclContext或Stmt继承,有些类从Decl和DeclContext继承1,2.
AST中还有许多节点不属于更大的层次,只能从指定的其他节点(如CXXBaseSpecifier)访问1.
因此,要遍历完整的AST,需要从TranslationUnitDecl开始,然后递归遍历可从该节点访问的所有内容,必须针对每个指定节点类型编码此信息.
也在RecursiveASTVisitor这里中编码此算法.见RecursiveASTVisitor教程.
ClangAST中的两个最基本节点是(Stmt)语句和(Decl)声明.注意,(Expr)式也是Clang的AST中的语句.