Clang之二 : AST节点解析

前言:为了基于clang对我们的代码做一些分析,我们最常用的就是去分析AST(抽象语法树),为了能达到分析AST的目的,我们首先需要做的是能看懂AST,因此本篇博客的目的是带大家学习一下AST中的常用节点以及其所对应的语法点 (这里只匹配OC语法)

一、AST节点含义解析

1、TranslationUnitDecl:

顶层节点

2、TypedefDecl:

3、ObjCInterfaceDecl

这个就是oc接口的声明
ex:
@interface Foo
@end

4、ObjCCategoryDecl

这个就是oc category的声明
ex:
@interface Foo (Additions)
@end

5、ObjCImplementationDecl

这个就是oc implementation的声明
@implementation Foo
@end

6、ObjCMethodDecl

这个节点表示:函数的声明和实现。这个节点是最重要的,也是最常见的一个节点!
ex:
@interface Foo
- (void)method;
@end

  @implementation Foo
  - (void)method {}
  @end

这种类型的节点,内部肯定会会有子节点。如:ImplicitParamDecl(oc中任何函数都有这个节点,因为必备这个参数)CompoundStmt (函数体)、VarDecl(局部变量)。

例如:我们看一下setUpHaoyuView 这个函数的AST结构如下:
            ObjCMethodDecl //消息发送调用的函数
              - ImplicitParamDecl //隐式参数 self
              - ImplicitParamDecl //隐式参数 _cmd
              - CompoundStmt //函数体
                - CallExpr //调用c或者c++函数
                - ImplicitCastExpr //隐式类型转换
                - DeclRefExpr //表达式变量

具体的实际代码以及转换后的AST如下:

- (void)setUpHaoyuView { //原始代码
    NSString *ahaoyuHaha = [[NSString alloc] initWithString:@"Hello"];
    [self setupGTestFunc:ahaoyuHaha];
}

AST: //转化后AST

|-ObjCMethodDecl 0x7f9ffcb3ac30  line:28:1 - setUpHaoyuView 'void'
| | |-ImplicitParamDecl 0x7f9ffe013648 <>  implicit used self 'UIViewController *const __strong'
| | |-ImplicitParamDecl 0x7f9ffe0136a8 <>  implicit _cmd 'SEL':'SEL *'
| | |-VarDecl 0x7f9ffe013720  col:15 used ahaoyuHaha 'NSString *__strong' cinit  //局部变量声明,每一个方法的AST都是,先罗列代码中所有的局部变量,然后列出方法体。
| | | `-ExprWithCleanups 0x7f9ffe013a60  'NSString *'
| | |   `-ImplicitCastExpr 0x7f9ffe013a48  'NSString *' 
| | |     `-ObjCMessageExpr 0x7f9ffe013a10  'NSString *' selector=initWithString:
| | |       |-ImplicitCastExpr 0x7f9ffe0137c0  'NSString *' 
| | |       | `-ObjCMessageExpr 0x7f9ffe013790  'NSString *' selector=alloc class='NSString'
| | |       `-ObjCStringLiteral 0x7f9ffe013838  'NSString *'
| | |         `-StringLiteral 0x7f9ffe013818  'char [6]' lvalue "Hello"
| | `-CompoundStmt 0x7f9ffe013b68  //方法体{ }
| |   |-DeclStmt 0x7f9ffe013a78 
| |   | `-VarDecl 0x7f9ffe013720  col:15 used ahaoyuHaha 'NSString *__strong' cinit
| |   |   `-ExprWithCleanups 0x7f9ffe013a60  'NSString *'
| |   |     `-ImplicitCastExpr 0x7f9ffe013a48  'NSString *' 
| |   |       `-ObjCMessageExpr 0x7f9ffe013a10  'NSString *' selector=initWithString:
| |   |         |-ImplicitCastExpr 0x7f9ffe0137c0  'NSString *' 
| |   |         | `-ObjCMessageExpr 0x7f9ffe013790  'NSString *' selector=alloc class='NSString'
| |   |         `-ObjCStringLiteral 0x7f9ffe013838  'NSString *'
| |   |           `-StringLiteral 0x7f9ffe013818  'char [6]' lvalue "Hello"
| |   `-ObjCMessageExpr 0x7f9ffe013b30  'void' selector=setupGTestFunc:
| |     |-ImplicitCastExpr 0x7f9ffe013b00  'UIViewController *' 
| |     | `-DeclRefExpr 0x7f9ffe013a90  'UIViewController *const __strong' lvalue ImplicitParam 0x7f9ffe013648 'self' 'UIViewController *const __strong'
| |     `-ImplicitCastExpr 0x7f9ffe013b18  'NSString *' 
| |       `-DeclRefExpr 0x7f9ffe013ac8  'NSString *__strong' lvalue Var 0x7f9ffe013720 'ahaoyuHaha' 'NSString *__strong'

7、ObjCPropertyDecl

这个节点表示:我们程序中定义的oc属性
@interface Foo
@property BOOL enabled;
@end

8、ObjCIvarDecl

表示:实例变量(私有变量)
ex:
@implementation Foo
{
BOOL _enabled;

}
@end

9、VarDecl

这个节点:只代表局部变量,不能代表成员变量。函数体内的局部变量

10、ObjCPropertyImplDecl

代表属性在类或者分类的implementation部分的实现声明,@synthesize prop1 = ivar1;

11、ImplicitParamDecl:

继承自VarDecl,代表各种类型的隐式参数。
例如:c++中的this、virtual table pointers、以及captured context
或者oc中的:self, _cmd。每个oc函数默认会有这两个参数

12、ParmVarDecl:

该节点表示:参数声明

OC属性在AST中常见的两种变现形式:

1)声明属性的同时,使用了synthesize关键字。

@property (nonatomic, strong) NSString *haoyuString;
@synthesize haoyuString = _haoyuString;

生成的AST如下:

ObjCIvarDecl :指出属性的实例变量 即:_haoyuString
ObjCPropertyImplDecl:指出haoyuString的synthesize
    - ObjCProperty:这不是节点了:DeclNodes.inc文件中的 一个宏,代表对应的属性
    - ObjCIvar:同上 ,代表实例变量。理解为叶子!!

|-ObjCIvarDecl 0x7ff2a6a68d88  col:27 referenced _haoyuString 'NSString *__strong' synthesize private
| |-ObjCPropertyImplDecl 0x7ff2a6a68de0  col:13 haoyuString synthesize
| | |-ObjCProperty 0x7ff2a6a33e00 'haoyuString'
| | `-ObjCIvar 0x7ff2a6a68d88 '_haoyuString' 'NSString *__strong'

2)不使用synthesize关键字

@property (nonatomic, strong) NSString *haoyuString;

生成的AST如下:

 ObjCPropertyDecl 0x7f96f693a400  col:41 haoyuString 'NSString *' readwrite nonatomic strong
| |-ObjCMethodDecl 0x7f96f693a478  col:41 implicit - haoyuString 'NSString *'
| |-ObjCMethodDecl 0x7f96f693a4f8  col:41 implicit - setHaoyuString: 'void'
| | `-ParmVarDecl 0x7f96f693a578  col:41 haoyuString 'NSString *'

3)使用dynamic关键字,不会创建setter和getter函数

ObjCPropertyImplDecl 0x7fee7e02f788  col:10 haoyuString dynamic
| | `-ObjCProperty 0x7fee7eb72000 'haoyuString'
//可以看到这时没有ObjCMethodDecl节点出现。

以上的

常见的数据类型

1、ObjCStringLiteral:

该节点对应:oc中NSString 类型

2、StringLiteral:

char[]类型的字符表示。oc中字符串用char类型来表示。

来看一个例子,字符串声明在AST中表示:

NSString *str = @"hahahah"; //oc中赋值代码

AST中的表示为:

VarDecl 0x7fd06cc91ae8  col:15 str 'NSString *__strong' cinit //声明局部变量
| | | `-ObjCStringLiteral 0x7fd06cc91ba8  'NSString *' //声明变量类型
| | |   `-StringLiteral 0x7fd06cc91b88  'char [8]' lvalue "hahahah" //右边的字符串有char类型表示

3、IntegerLiteral:

对应:整型变量,如NSInteger、int

NSInteger haoyuA = 10;

AST:

|-VarDecl 0x7ffe6db8c0a0  col:15 haoyuA 'NSInteger':'long' cinit
| | | `-ImplicitCastExpr 0x7ffe6db8c120  'NSInteger':'long' 
| | |   `-IntegerLiteral 0x7ffe6db8c100  'int' 10

4、FloatingLiteral:

对应:浮点数

CGFloat haoFloat = 2.3f;
AST:
-VarDecl 0x7ffe6db8c160  col:13 haoFloat 'CGFloat':'double' cinit
| | | `-ImplicitCastExpr 0x7ffe6db8c1e0  'CGFloat':'double' 
| | |   `-FloatingLiteral 0x7ffe6db8c1c0  'float' 2.300000e+00

5、ObjCArrayLiteral

数组

NSArray *arr = @["sss",];

AST表示如下:

|-VarDecl 0x7fec3c1cf050  col:14 arr 'NSArray *__strong' cinit
| | | `-ExprWithCleanups 0x7fec3c1c8b68  'NSArray *'//这里可以看到,arr这个局部变量被自动添加了autoRelease。
| | |   `-ImplicitCastExpr 0x7fec3c1c8b50  'NSArray *' 
| | |     `-ObjCArrayLiteral 0x7fec3c1c8b18  'NSArray *' //数组类型
| | |       |-ImplicitCastExpr 0x7fec3c1c8ae8  'ObjectType _Nonnull':'id' 
| | |       | `-ObjCStringLiteral 0x7fec3c1c8ac8  'NSString *' //代表数组中第一个字符串元素
| | |       |   `-StringLiteral 0x7fec3c1cf108  'char [4]' lvalue "sss"
| | |       `-ImplicitCastExpr 0x7fec3c1c8b00  'ObjectType _Nonnull':'id' 
| | |         `-ImplicitCastExpr 0x7fec3c1c8638  'NSNumber *' 
| | |           `-ObjCBoxedExpr 0x7fec3c1c8610  'NSNumber *' selector=numberWithInt: //代表数组中第2个元素:@(1)
| | |             `-ParenExpr 0x7fec3c1cf148  'int'
| | |               `-IntegerLiteral 0x7fec3c1cf128  'int' 1

6、ObjCDictionaryLiteral

对应:字典类型

NSDictionary *dic = @{@"key11":@"value11"};

AST:

|-VarDecl 0x7fec3c1c8be0  col:19 dic 'NSDictionary *__strong' cinit
| | | `-ExprWithCleanups 0x7fec3c1c9510  'NSDictionary *'
| | |   `-ImplicitCastExpr 0x7fec3c1c94f8  'NSDictionary *' 
| | |     `-ObjCDictionaryLiteral 0x7fec3c1c94c0  'NSDictionary *' //表示代码中的字典NSDictionary
| | |       |-ImplicitCastExpr 0x7fec3c1c9490  'id _Nonnull':'id'  //字典中声明的key,按照字符串类型来解析。
| | |       | `-ObjCStringLiteral 0x7fec3c1c8cb8  'NSString *'
| | |       |   `-StringLiteral 0x7fec3c1c8c98  'char [6]' lvalue "key11"
| | |       `-ImplicitCastExpr 0x7fec3c1c94a8  'ObjectType _Nonnull':'id' 
| | |         `-ObjCStringLiteral 0x7fec3c1c8cf8  'NSString *' //字典中声明的value,同样按照字符串类型来解析
| | |           `-StringLiteral 0x7fec3c1c8cd8  'char [8]' lvalue "value11"

Type 类型:

1、TypedefDecl:

对应typedef

2、BlockPointerType:

block的指针类型声明

3、ParenType:

block的函数原型

4、FunctionProtoType:

函数协议类型

5、TypedefType:(注意同TypedefDecl区别)

参数类型或者是返回值类型,包含Typedef类型以及BuiltinType编译原类型

语法

1、CompoundStmt:

该节点代表:代表了像{ stmt stmt } 这样的statement的集合。实际上就是用'{}' and '{{}}' 包裹的代码块。
例如:函数{} 或者 for循环 for (;;) {{}} 这些形式的代码中,的{} 或者 {{}}。
其内部会包含很多子节点。

2、DeclStmt:

适配器类,用于混合声明与语句和表达式。
例如,CompoundStmt混合了语句、表达式和声明(变量、类型)。另一个例子是ForStmt,其中第一个语句可以是表达式或声明。
文档上写的很抽象,有些博客上写的是:变量声明 ,这里感觉不恰当,应该是语句声明。常出现在局部变量的声明语句解析出来的AST中。如:

NSString *str = @"hahahah";

在AST中对应的表示为:

|-DeclStmt 0x7f9ffc07b1c8  //语句声明
| |   | `-VarDecl 0x7f9ffc07b0e8  col:15 str 'NSString *__strong' cinit //局部变量声明
| |   |   `-ObjCStringLiteral 0x7f9ffc07b1a8  'NSString *'
| |   |     `-StringLiteral 0x7f9ffc07b188  'char [8]' lvalue "hahahah"

3、 DeclRefExpr:

该节点对应的是:表达式中使用到的变量。例如:if(x) \ bool x \ if(x) { } 表达式中,x就是DeclRefExpr。常见的结构组合如下:

  ObjCMessageExpr
      ImplicitCastExpr
      DeclRefExpr:表达式的变量声明 (同DeclStmt区别,后者是变量声明,前者是在表>达式中出现的变量)
DeclStmt 同DeclRefExpr区别:
//以下面的代码为例。
NSString *ahaoyuHaha = [[NSString alloc] initWithString:@"Hello"];
[self setupGTestFunc];
//在AST中:
ahaoyuHaha :在AST中就是DeclStmt.
self:在AST中就是DeclRefExpr.

4、ObjCAutoreleasePoolStmt

该节点:Matches an Objective-C autorelease pool statement.

Given
  @autoreleasepool {
    int x = 0;
  }
autoreleasePoolStmt(stmt()) matches the declaration of "x"
inside the autorelease pool.            

5、ReturnStmt:

return的表达式,多个return出口有多个,这就是为啥编译也会变慢的原因

6、IfStmt:

if表达语句

7、ObjCAtSynchronizedStmt:

对应@Synchronized。注意不是synthesize!!

8、ObjCAtTryStmt:

对应@try

9、ForStmt:

对应for

10、UnaryOperator:

对应i++

11、ObjCAtCatchStmt:

对应@catch

常用表达式:

1、ExprWithCleanups

表示一个表达式(通常是一个完整的表达式),该表达式引入要在子表达式求值结束时运行的清理。
表达式引入的清理最常见的来源是c++中的临时对象,但是其他几种表达式可以创建清理,包括在ARC中返回一个Objective-C指针的每个调用。
此表达式还跟踪子表达式是否包含潜在计算的block。block的生命周期是封闭范围的范围。

出现场景:函数体内出现的局部变量等
NSString *haoyu = [NSString alloc] initwithString:@"xxx"];
std::string str = std::string();

通俗一些理解就是:ARC下带上了autorelease的变量

2、PseudoObjectExpr:

OC属性get方法的返回类型。这里暂且也先这样理解,6.7经常组合出现

3、OpaqueValueExpr:

文档写的太抽象了,没看懂。暂且理解为:关键字表达式。self.

4、ObjCPropertyRefExpr:

属性表达式。例如:self.haoyuString = @"xxxx";

5、ObjCIvarRefExpr:

私有变量参与的表达式,比如:_aaa=@“xxx”

6、ImplicitCastExpr:

隐式转换,代表数字类型的转换,'int64_t':'long long' 代表int64_t转成longlong,代表位转换, 代表ARC模式下的返回值,可以假设带上了autorelease,

7、CallExpr:

调用C/C++函数方法。例如: x.y() 或 y() 或 X x 或 x.y() 或 y()

8、 BlockExpr:

该节点表示block的实现
例如: "^{ }" 或 void f() { ^{}(); }

9、ObjCBoxedExpr:

通常对应 @() 用法。

例如: BOOL isTest = @(1); 会被解析成:
 ObjCBoxedExpr 0x7fa48d188710  'NSNumber *' selector=numberWithInt:  //将int转换成number

10、ParenExpr:

表示括号表达式,常跟上面的一起出现。

11、CStyleCastExpr:

c语言类型的转换

12、ObjCSubscriptRefExpr:

NSDictionary[]对应的方法调用

13、ObjCMessageExpr:

表示oc中消息发送的节点.
例如: [[NSString alloc] initWithString:@"Hello"]; 这里会产生2个ObjCMessageExpr节点。

我们看一下blockAST中表示:
源代码如下:

//特意把行号也标注上了,因为在AST中会标注每个节点在原文件中的位置!
29  - (void)setUpHaoyuView {
30    NSString *ahaoyuHaha = [[NSString alloc] initWithString:@"Hello"];
31 //    [self setupGTestFunc:ahaoyuHaha];
32 //    self.haoyuString = @"aaaa";
33 //    BOOL isTest = @(1);
34    void (^haoyuTestBlcok)(void) = ^{
35        [self setupGTestFunc:ahaoyuHaha];
36    };
37 }
|-ObjCMethodDecl 0x7f96f696f230  line:29:1 - setUpHaoyuView 'void'
| | |-ImplicitParamDecl 0x7f96f693c7b0 <>  implicit used self 'UIViewController *const __strong'
| | |-ImplicitParamDecl 0x7f96f693c810 <>  implicit _cmd 'SEL':'SEL *'
| | |-VarDecl 0x7f96f693c888  col:15 used ahaoyuHaha 'NSString *__strong' cinit
| | | `-ExprWithCleanups 0x7f96f693cbc0  'NSString *'
| | |   `-ImplicitCastExpr 0x7f96f693cba8  'NSString *' 
| | |     `-ObjCMessageExpr 0x7f96f693cb70  'NSString *' selector=initWithString:
| | |       |-ImplicitCastExpr 0x7f96f693c928  'NSString *' 
| | |       | `-ObjCMessageExpr 0x7f96f693c8f8  'NSString *' selector=alloc class='NSString'
| | |       `-ObjCStringLiteral 0x7f96f693c998  'NSString *'
| | |         `-StringLiteral 0x7f96f693c978  'char [6]' lvalue "Hello"
| | |-VarDecl 0x7f96f693cc90  line:34:12 haoyuTestBlcok 'void (^__strong)(void)' cinit
| | | `-ExprWithCleanups 0x7f96f693cee0  'void (^)(void)'
| | |   |-cleanup Block 0x7f96f693ccf0
| | |   `-BlockExpr 0x7f96f693cec8  'void (^)(void)'
| | |     `-BlockDecl 0x7f96f693ccf0  line:34:36
| | |       |-capture ImplicitParam 0x7f96f693c7b0 'self' 'UIViewController *const __strong'
| | |       |-capture Var 0x7f96f693c888 'ahaoyuHaha' 'NSString *__strong'
| | |       `-CompoundStmt 0x7f96f693ce90 
| | |         `-ObjCMessageExpr 0x7f96f693ce58  'void' selector=setupGTestFunc:
| | |           |-ImplicitCastExpr 0x7f96f693ce28  'UIViewController *' 
| | |           | `-DeclRefExpr 0x7f96f693cdb8  'UIViewController *const __strong' lvalue ImplicitParam 0x7f96f693c7b0 'self' 'UIViewController *const __strong'
| | |           `-ImplicitCastExpr 0x7f96f693ce40  'NSString *' 
| | |             `-DeclRefExpr 0x7f96f693cdf0  'NSString *const __strong' lvalue Var 0x7f96f693c888 'ahaoyuHaha' 'NSString *__strong'
| | |-BlockDecl 0x7f96f693ccf0  line:34:36
| | | |-capture ImplicitParam 0x7f96f693c7b0 'self' 'UIViewController *const __strong'
| | | |-capture Var 0x7f96f693c888 'ahaoyuHaha' 'NSString *__strong'
| | | `-CompoundStmt 0x7f96f693ce90 
| | |   `-ObjCMessageExpr 0x7f96f693ce58  'void' selector=setupGTestFunc:
| | |     |-ImplicitCastExpr 0x7f96f693ce28  'UIViewController *' 
| | |     | `-DeclRefExpr 0x7f96f693cdb8  'UIViewController *const __strong' lvalue ImplicitParam 0x7f96f693c7b0 'self' 'UIViewController *const __strong'
| | |     `-ImplicitCastExpr 0x7f96f693ce40  'NSString *' 
| | |       `-DeclRefExpr 0x7f96f693cdf0  'NSString *const __strong' lvalue Var 0x7f96f693c888 'ahaoyuHaha' 'NSString *__strong'
| | `-CompoundStmt 0x7f96f693cf18 
| |   |-DeclStmt 0x7f96f693cbd8 
| |   | `-VarDecl 0x7f96f693c888  col:15 used ahaoyuHaha 'NSString *__strong' cinit
| |   |   `-ExprWithCleanups 0x7f96f693cbc0  'NSString *'
| |   |     `-ImplicitCastExpr 0x7f96f693cba8  'NSString *' 
| |   |       `-ObjCMessageExpr 0x7f96f693cb70  'NSString *' selector=initWithString:
| |   |         |-ImplicitCastExpr 0x7f96f693c928  'NSString *' 
| |   |         | `-ObjCMessageExpr 0x7f96f693c8f8  'NSString *' selector=alloc class='NSString'
| |   |         `-ObjCStringLiteral 0x7f96f693c998  'NSString *'
| |   |           `-StringLiteral 0x7f96f693c978  'char [6]' lvalue "Hello"
| |   `-DeclStmt 0x7f96f693cf00 
| |     `-VarDecl 0x7f96f693cc90  line:34:12 haoyuTestBlcok 'void (^__strong)(void)' cinit
| |       `-ExprWithCleanups 0x7f96f693cee0  'void (^)(void)'
| |         |-cleanup Block 0x7f96f693ccf0
| |         `-BlockExpr 0x7f96f693cec8  'void (^)(void)'
| |           `-BlockDecl 0x7f96f693ccf0  line:34:36
| |             |-capture ImplicitParam 0x7f96f693c7b0 'self' 'UIViewController *const __strong'
| |             |-capture Var 0x7f96f693c888 'ahaoyuHaha' 'NSString *__strong'
| |             `-CompoundStmt 0x7f96f693ce90 
| |               `-ObjCMessageExpr 0x7f96f693ce58  'void' selector=setupGTestFunc:
| |                 |-ImplicitCastExpr 0x7f96f693ce28  'UIViewController *' 
| |                 | `-DeclRefExpr 0x7f96f693cdb8  'UIViewController *const __strong' lvalue ImplicitParam 0x7f96f693c7b0 'self' 'UIViewController *const __strong'
| |                 `-ImplicitCastExpr 0x7f96f693ce40  'NSString *' 
| |                   `-DeclRefExpr 0x7f96f693cdf0  'NSString *const __strong' lvalue Var 0x7f96f693c888 'ahaoyuHaha' 'NSString *__strong'

分析一下:
因为我们在函数中定义了一个block类型的临时变量haoyuTestBlcok,并且为其赋值了一个block
所以我们看到结构是这样的:

ObjCMethodDecl:
  - ImplicitParamDecl
  - ImplicitParamDecl
  - VarDecl
  - VarDecl:  这个变量声明节点表示的是:我们定义的haoyuTestBlcok 这个变量,因为给它赋的值就是一个block。所有他下面挂有一个BlockDecl节点。
    - ExprWithCleanups
    - BlockExpr
      -BlockDecl:
         - capture:这里代表的是捕获的self变量
         - capture:这里则是捕获的 ahaoyuHaha 变量
         - CompoundStmt:这里代表的是{ }体重的内容。
            - ObjCMessageExpr :这里是标识block体内的函数调用。对应:我们在block中执行了 [self setupGTestFunc:ahaoyuHaha]; 函数调用。
        
  - BlockDecl: 这里的block声明对应的 “=” 右边定义的block,它跟上面的BlockDecl实质上一个。我们可以看其内存地址,都为0x7f96f693ccf0。
  - CompoundStmt: 这里则代表函数体。我们可以看到他的代码范围是: 即:29行到37行。
(同样,它里面也会包含一个BlockDecl节点,该节点跟上面的仍然是同一个节点)

//从上面的AST中也可以看出,BlockDecl有多种途径可以到达。  所以我们遍历查找某个节点时也会可以有多种方式。


二、AST结构分析

有了上面的基础后,我们在来看一个相对完整的AST,分析下它的结构。以下面的代码为例,我们分析一下其转化为AST后的内容。

@interface UIViewController ()

@property (nonatomic, strong) NSString *haoyuString;
@property (nonatomic, strong) UIView *haoyuView;
@property (nonatomic, copy) void (^haoyuTestBlcok)(void);

@end

@implementation UIViewController

- (void)viewDidLoad {
    NSString *str = @"hahahah";
    [self setUpHaoyuView];
}



- (void)setUpHaoyuView {
    NSString *ahaoyuHaha = [[NSString alloc] initWithString:@"Hello"];
    void (^haoyuTestBlcok)(void) = ^{
        [self setupGTestFunc:ahaoyuHaha];
    };
}
- (void)setupGTestFunc:(NSString *)stringA {
    NSLog(@"=====字符串:%@",stringA);
}

@end

经过clang转换后得到的AST如下:

TranslationUnitDecl 0x7ffc9982de08 <> 
|-TypedefDecl 0x7ffc9982e6a0 <>  implicit __int128_t '__int128'
| `-BuiltinType 0x7ffc9982e3a0 '__int128'
|-TypedefDecl 0x7ffc9982e708 <>  implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x7ffc9982e3c0 'unsigned __int128'
|-TypedefDecl 0x7ffc9982e7a0 <>  implicit SEL 'SEL *'
| `-PointerType 0x7ffc9982e760 'SEL *' imported
|   `-BuiltinType 0x7ffc9982e600 'SEL'
|-TypedefDecl 0x7ffc9982e878 <>  implicit id 'id'
| `-ObjCObjectPointerType 0x7ffc9982e820 'id' imported
|   `-ObjCObjectType 0x7ffc9982e7f0 'id' imported
|-TypedefDecl 0x7ffc9982e958 <>  implicit Class 'Class'
| `-ObjCObjectPointerType 0x7ffc9982e900 'Class' imported
|   `-ObjCObjectType 0x7ffc9982e8d0 'Class' imported
|-ObjCInterfaceDecl 0x7ffc9982e9a8 <>  implicit Protocol
|-TypedefDecl 0x7ffc9982ece8 <>  implicit __NSConstantString 'struct __NSConstantString_tag'
| `-RecordType 0x7ffc9982eb00 'struct __NSConstantString_tag'
|   `-Record 0x7ffc9982ea70 '__NSConstantString_tag'
|-TypedefDecl 0x7ffc9982ed80 <>  implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x7ffc9982ed40 'char *'
|   `-BuiltinType 0x7ffc9982dea0 'char'
|-TypedefDecl 0x7ffc9986b868 <>  implicit __builtin_va_list 'struct __va_list_tag [1]'
| `-ConstantArrayType 0x7ffc9986b810 'struct __va_list_tag [1]' 1 
|   `-RecordType 0x7ffc9986b690 'struct __va_list_tag'
|     `-Record 0x7ffc9986b600 '__va_list_tag'
|-ImportDecl 0x7ffc9986c548  col:1 implicit UIKit
|-ObjCCategoryDecl 0x7ffc9c0b5748  line:11:12
| |-ObjCInterface 0x7ffc9c09bd80 'UIViewController'
| |-ObjCPropertyDecl 0x7ffc9c0af400  col:41 haoyuString 'NSString *' readwrite nonatomic strong
| |-ObjCMethodDecl 0x7ffc9c0af478  col:41 implicit - haoyuString 'NSString *'
| |-ObjCMethodDecl 0x7ffc9c0af4f8  col:41 implicit - setHaoyuString: 'void'
| | `-ParmVarDecl 0x7ffc9c0af578  col:41 haoyuString 'NSString *'
| |-ObjCPropertyDecl 0x7ffc9c0c5e30  col:39 haoyuView 'UIView *' readwrite nonatomic strong
| |-ObjCMethodDecl 0x7ffc9c0c5ea8  col:39 implicit - haoyuView 'UIView *'
| |-ObjCMethodDecl 0x7ffc9c0c5f28  col:39 implicit - setHaoyuView: 'void'
| | `-ParmVarDecl 0x7ffc9c0c5fa8  col:39 haoyuView 'UIView *'
| |-ObjCPropertyDecl 0x7ffc9c0c6168  col:36 haoyuTestBlcok 'void (^)(void)' readwrite copy nonatomic
| |-ObjCMethodDecl 0x7ffc9c0d2a00  col:36 implicit - haoyuTestBlcok 'void (^)(void)'
| `-ObjCMethodDecl 0x7ffc9c0d2a80  col:36 implicit - setHaoyuTestBlcok: 'void'
|   `-ParmVarDecl 0x7ffc9c0d2b00  col:36 haoyuTestBlcok 'void (^)(void)'
|-ObjCImplementationDecl 0x7ffc9c0e3d08  line:19:17 UIViewController
| |-ObjCInterface 0x7ffc9c09bd80 'UIViewController'
| |-ObjCMethodDecl 0x7ffc9c0e3d98  line:21:1 - viewDidLoad 'void'
| | |-ImplicitParamDecl 0x7ffc9c11a610 <>  implicit used self 'UIViewController *const __strong'
| | |-ImplicitParamDecl 0x7ffc9c11a670 <>  implicit _cmd 'SEL':'SEL *'
| | |-VarDecl 0x7ffc9c11a6e8  col:15 str 'NSString *__strong' cinit
| | | `-ObjCStringLiteral 0x7ffc9c11a7a8  'NSString *'
| | |   `-StringLiteral 0x7ffc9c11a788  'char [8]' lvalue "hahahah"
| | `-CompoundStmt 0x7ffc9c0b0ff8 
| |   |-DeclStmt 0x7ffc9c11a7c8 
| |   | `-VarDecl 0x7ffc9c11a6e8  col:15 str 'NSString *__strong' cinit
| |   |   `-ObjCStringLiteral 0x7ffc9c11a7a8  'NSString *'
| |   |     `-StringLiteral 0x7ffc9c11a788  'char [8]' lvalue "hahahah"
| |   `-ObjCMessageExpr 0x7ffc9c123030  'void' selector=setUpHaoyuView
| |     `-ImplicitCastExpr 0x7ffc9c123018  'UIViewController *' 
| |       `-DeclRefExpr 0x7ffc9c11a7e0  'UIViewController *const __strong' lvalue ImplicitParam 0x7ffc9c11a610 'self' 'UIViewController *const __strong'
| |-ObjCMethodDecl 0x7ffc9c0e3e30  line:28:1 - setUpHaoyuView 'void'
| | |-ImplicitParamDecl 0x7ffc9c0b1048 <>  implicit used self 'UIViewController *const __strong'
| | |-ImplicitParamDecl 0x7ffc9c0b10a8 <>  implicit _cmd 'SEL':'SEL *'
| | |-VarDecl 0x7ffc9c0b1120  col:15 used ahaoyuHaha 'NSString *__strong' cinit
| | | `-ExprWithCleanups 0x7ffc9c0b1460  'NSString *'
| | |   `-ImplicitCastExpr 0x7ffc9c0b1448  'NSString *' 
| | |     `-ObjCMessageExpr 0x7ffc9c0b1410  'NSString *' selector=initWithString:
| | |       |-ImplicitCastExpr 0x7ffc9c0b11c0  'NSString *' 
| | |       | `-ObjCMessageExpr 0x7ffc9c0b1190  'NSString *' selector=alloc class='NSString'
| | |       `-ObjCStringLiteral 0x7ffc9c0b1238  'NSString *'
| | |         `-StringLiteral 0x7ffc9c0b1218  'char [6]' lvalue "Hello"
| | |-VarDecl 0x7ffc9c0b1530  line:30:12 haoyuTestBlcok 'void (^__strong)(void)' cinit
| | | `-ExprWithCleanups 0x7ffc9c0b1780  'void (^)(void)'
| | |   |-cleanup Block 0x7ffc9c0b1590
| | |   `-BlockExpr 0x7ffc9c0b1768  'void (^)(void)'
| | |     `-BlockDecl 0x7ffc9c0b1590  line:30:36
| | |       |-capture ImplicitParam 0x7ffc9c0b1048 'self' 'UIViewController *const __strong'
| | |       |-capture Var 0x7ffc9c0b1120 'ahaoyuHaha' 'NSString *__strong'
| | |       `-CompoundStmt 0x7ffc9c0b1730 
| | |         `-ObjCMessageExpr 0x7ffc9c0b16f8  'void' selector=setupGTestFunc:
| | |           |-ImplicitCastExpr 0x7ffc9c0b16c8  'UIViewController *' 
| | |           | `-DeclRefExpr 0x7ffc9c0b1658  'UIViewController *const __strong' lvalue ImplicitParam 0x7ffc9c0b1048 'self' 'UIViewController *const __strong'
| | |           `-ImplicitCastExpr 0x7ffc9c0b16e0  'NSString *' 
| | |             `-DeclRefExpr 0x7ffc9c0b1690  'NSString *const __strong' lvalue Var 0x7ffc9c0b1120 'ahaoyuHaha' 'NSString *__strong'
| | |-BlockDecl 0x7ffc9c0b1590  line:30:36
| | | |-capture ImplicitParam 0x7ffc9c0b1048 'self' 'UIViewController *const __strong'
| | | |-capture Var 0x7ffc9c0b1120 'ahaoyuHaha' 'NSString *__strong'
| | | `-CompoundStmt 0x7ffc9c0b1730 
| | |   `-ObjCMessageExpr 0x7ffc9c0b16f8  'void' selector=setupGTestFunc:
| | |     |-ImplicitCastExpr 0x7ffc9c0b16c8  'UIViewController *' 
| | |     | `-DeclRefExpr 0x7ffc9c0b1658  'UIViewController *const __strong' lvalue ImplicitParam 0x7ffc9c0b1048 'self' 'UIViewController *const __strong'
| | |     `-ImplicitCastExpr 0x7ffc9c0b16e0  'NSString *' 
| | |       `-DeclRefExpr 0x7ffc9c0b1690  'NSString *const __strong' lvalue Var 0x7ffc9c0b1120 'ahaoyuHaha' 'NSString *__strong'
| | `-CompoundStmt 0x7ffc9c0b17b8 
| |   |-DeclStmt 0x7ffc9c0b1478 
| |   | `-VarDecl 0x7ffc9c0b1120  col:15 used ahaoyuHaha 'NSString *__strong' cinit
| |   |   `-ExprWithCleanups 0x7ffc9c0b1460  'NSString *'
| |   |     `-ImplicitCastExpr 0x7ffc9c0b1448  'NSString *' 
| |   |       `-ObjCMessageExpr 0x7ffc9c0b1410  'NSString *' selector=initWithString:
| |   |         |-ImplicitCastExpr 0x7ffc9c0b11c0  'NSString *' 
| |   |         | `-ObjCMessageExpr 0x7ffc9c0b1190  'NSString *' selector=alloc class='NSString'
| |   |         `-ObjCStringLiteral 0x7ffc9c0b1238  'NSString *'
| |   |           `-StringLiteral 0x7ffc9c0b1218  'char [6]' lvalue "Hello"
| |   `-DeclStmt 0x7ffc9c0b17a0 
| |     `-VarDecl 0x7ffc9c0b1530  line:30:12 haoyuTestBlcok 'void (^__strong)(void)' cinit
| |       `-ExprWithCleanups 0x7ffc9c0b1780  'void (^)(void)'
| |         |-cleanup Block 0x7ffc9c0b1590
| |         `-BlockExpr 0x7ffc9c0b1768  'void (^)(void)'
| |           `-BlockDecl 0x7ffc9c0b1590  line:30:36
| |             |-capture ImplicitParam 0x7ffc9c0b1048 'self' 'UIViewController *const __strong'
| |             |-capture Var 0x7ffc9c0b1120 'ahaoyuHaha' 'NSString *__strong'
| |             `-CompoundStmt 0x7ffc9c0b1730 
| |               `-ObjCMessageExpr 0x7ffc9c0b16f8  'void' selector=setupGTestFunc:
| |                 |-ImplicitCastExpr 0x7ffc9c0b16c8  'UIViewController *' 
| |                 | `-DeclRefExpr 0x7ffc9c0b1658  'UIViewController *const __strong' lvalue ImplicitParam 0x7ffc9c0b1048 'self' 'UIViewController *const __strong'
| |                 `-ImplicitCastExpr 0x7ffc9c0b16e0  'NSString *' 
| |                   `-DeclRefExpr 0x7ffc9c0b1690  'NSString *const __strong' lvalue Var 0x7ffc9c0b1120 'ahaoyuHaha' 'NSString *__strong'
| |-ObjCMethodDecl 0x7ffc9c0e3ee0  line:34:1 - setupGTestFunc: 'void'
| | |-ImplicitParamDecl 0x7ffc9c0b1808 <>  implicit self 'UIViewController *const __strong'
| | |-ImplicitParamDecl 0x7ffc9c0b1868 <>  implicit _cmd 'SEL':'SEL *'
| | |-ParmVarDecl 0x7ffc9c0e3f60  col:36 used stringA 'NSString *__strong'
| | `-CompoundStmt 0x7ffc9c0b1a70 
| |   `-CallExpr 0x7ffc9c0b1a10  'void'
| |     |-ImplicitCastExpr 0x7ffc9c0b19f8  'void (*)(id, ...)' 
| |     | `-DeclRefExpr 0x7ffc9c0b18c8  'void (id, ...)' Function 0x7ffc9c0e3fe8 'NSLog' 'void (id, ...)'
| |     |-ImplicitCastExpr 0x7ffc9c0b1a40  'id':'id' 
| |     | `-ObjCStringLiteral 0x7ffc9c0b1958  'NSString *'
| |     |   `-StringLiteral 0x7ffc9c0b1928  'char [18]' lvalue "=====\345\255\227\347\254\246\344\270\262:%@"
| |     `-ImplicitCastExpr 0x7ffc9c0b1a58  'NSString *' 
| |       `-DeclRefExpr 0x7ffc9c0b1978  'NSString *__strong' lvalue ParmVar 0x7ffc9c0e3f60 'stringA' 'NSString *__strong'
| |-ObjCIvarDecl 0x7ffc9c115630  col:54 implicit _view 'UIView * _Null_unspecified __strong':'UIView *__strong' synthesize private
| |-ObjCPropertyImplDecl 0x7ffc9c115688 <, col:54>  view synthesize
| | |-ObjCProperty 0x7ffc9c0d3560 'view'
| | `-ObjCIvar 0x7ffc9c115630 '_view' 'UIView * _Null_unspecified __strong':'UIView *__strong'
| |-ObjCIvarDecl 0x7ffc9c115880  col:58 implicit _viewIfLoaded 'UIView * _Nullable __strong':'UIView *__strong' synthesize private
| |-ObjCPropertyImplDecl 0x7ffc9c1158d8 <, col:58>  viewIfLoaded synthesize

实在太长了,我做了一下删减,把从UIViewController中继承的一些方法属性和方法给省略。

最顶层的节点是TranslationUnitDecl。接下来是两大部分ObjCCategoryDecl、ObjCImplementationDecl。然后在各自的节点下又有子节点。了解所有节点后。整体还是很简单的。

TranslationUnitDecl
  -ObjCCategoryDecl
    -ObjCInterface
    -ObjCPropertyDecl //声明property属性
    -ObjCMethodDecl  //属性对应的getter。这里参考一个method解析转换即可。
    -ObjCMethodDecl  //setter方法
      -ParmVarDecl ///setter方法中用到的参数
    ......
  -ObjCImplementationDecl //对应我们的implemention实现,下面都是各种方法的声明。
    -ObjCInterface
    -ObjCMethodDecl
      -ImplicitParamDecl //这里会一直都都有这两个默认参数
      -ImplicitParamDecl //同上
      -VarDecl //函数中定义的局部变量
        ...
      -CompoundStmt  //每个函数的方法体
        ...
  -ObjCMethodDecl
    .......

综上就是整个AST的结构,我们可以参照这个结构来理解AST内容。

大家可以结合上面讲到的各节点的含义来具体理解一下我们得出的AST内容。先参考这个结构,有问题可以给我发信息。

参考:
这里提供一个比较不错的参考:官方提供的ASTMatcher 文档,用来在遍历AST时,获取每个节点。
同仁写的一篇文章

你可能感兴趣的:(Clang之二 : AST节点解析)