Clang 中 AST 相关类简介(不定时更新)
1. Decl(declaration)
它表示程序中的一个声明。
1.1 FunctionDecl
表示一个函数声明(declaration)或定义(definition)。
因为一个给定的函数可以在程序中声明多次,所以可能有几个 FunctionDecls
对应于该函数。当遍历此 FunctionDecl
上下文中的声明列表时(例如,翻译单元),只会找到其中的一个 FunctionDecl
;这个 FunctionDecl
包含关于函数的所有已知信息。另外,此函数的前置声明可以通过 getPreviousDecl()
链获得。
一个函数声明可能是:
- 一个非定义声明,
- 一个定义。一个函数可能被如下定义:
- 它有一个 body,或者在稍后解析中将会有一个 body。
- 它有一个未实例化(uninstantiated)的 body。此 body 不存在,因为尚未使用该函数,但是此声明被视为一个定义,并且不允许对该函数进行其他定义。
- 它没有一个用户指定的 body,但它不允许重新定义(redefinition),因为它是 deleted/defaulted 或通过其他机制(alias、ifunc)定义的。
它的 public 成员函数:
- DeclarationNameInfo getNameInfo() const
使用它来获取函数名:FunctionDecl *f; std::string funcName = f->getNameInfo().getName().getAsString();
- QualType getReturnType() const
获取函数的返回类型 - SourceRange getSourceRange() const
- bool hasBody() const
如果此 Decl 表示代码体(如函数或方法定义)的声明,则返回 true。
注意,如果这个 Decl 的任何 redeclaration 表示代码体的声明,那么 hasBody 也可以返回 true。 - bool isDefined() const
如果函数的有一个不需要被实例化(instantiate)的定义,则返回true。 - 函数的参数遍历
FunctionDecl *f; Rewriter rw; for(FunctionDecl::param_iterator start = f->param_begin(), end = f->param_end(); start!=end; start++){ // 输出代码中的形式参数 llvm::errs() << rw.getRewrittenText((**start).getSourceRange()) << "\n"; }
2. Stmt(statement)
这个类表示程序中的一个语句。语句是程序的基本构建块,一个语句相当于一条完整的计算机指令,大部分语句都以 ;
结尾。包括:
- 表达式语句
主要是函数调用语句(printf()
)和赋值语句(value = expression;
) - 语句块
{}
括起来的语句 - 空语句
即;
- 控制语句
分为循环语句(for
、while
)、选择/条件语句(if
、switch
)、特殊语句(return
、continue
、break
)
int i; // 这是一个声明
i = 5; // 这是一个语句;`i = 5`是一个表达式
{ // 这是一个复合语句
int j;
j = 4;
}
3. Expr(expression)
它表示程序中的一个表达式。表达式是由运算符和运算对象组成,运算对象可以是常量、变量或二者的结合。一些表达式由子表达式(非 full-expression
)组成。表达式最重要的特性之一就是每个表达式都有一个值。变量、常量、函数调用本身也是一个表达式。
3.1 FullExpr
代表一个“full-expression”
节点,完全表达式即它不是另一个表达式的子表达式。
3.2 ExprWithCleanups
它表示一个表达式(通常是 full-expression
),该表达式引入要在子表达式求值结束时运行的清理(cleanup
)。
表达式引入的清理最常见的来源是 C++ 中的临时对象(temporary objects),但是其他几种表达式也会创建清理,包括 ARC 中返回一个 Objective-C 指针的每个调用。
该表达式还跟踪子表达式是否包含一个潜在求值的 block literal
。 一个 block literal
的生命周期是 enclosing scope
的长度(extent)。
该类的 public 成员:
using CleanupObject = BlockDecl *;
清理中保存的对象的类型。记住一组blocks
很有用;我们也可以记住一组temporaries
,但目前没有必要。
3.3 CallExpr
它表示一个函数调用(C99 6.5.2.2, C++ [expr.call])。CallExpr
本身表示一个普通的函数调用,例如,f(x, 2)
。
它的子类可以表示导致一个函数调用的替代语法(语义上)。例如,CXXOperatorCallExpr
是它的一个子类,用于重载操作符调用,该子类使用操作符语法,例如 str1 + str2
解析为一个函数调用。
它的 public 成员函数:
FunctionDecl *getDirectCallee();
如果被调用方是一个FunctionDecl
,则返回它。否则返回null。unsigned getBuiltinCallee() const;
如果这是对builtin的调用,返回被调用者的builtin ID。如果不是,返回0。(对于C程序可以使用它来判断调用的是否是自己编写的函数,C++中不行)QualType getCallReturnType(const ASTContext &Ctx) const;
获取它的返回类型。