clangでASTをdumpする


Objective-CのAST(抽象構文木)をdumpするやり方を調べたのでメモ。
以前はxml形式、バイナリ形式で出力ができたらしいが、LLVM version 3.4ではできなかった。

詳細は`clang -cc1 --help`を参照。

例として以下のクラスのASTを取得する。

```:Objective-C
#import <Foundation/Foundation.h>

@interface Spam : NSObject
@property(retain) NSString *ham;

- (instancetype)initWithHam:(NSString *)ham;
@end
```

```:Objective-C
#import "Spam.h"

@implementation Spam
- (instancetype)initWithHam:(NSString *)ham{
    if (self = [super init]) {
        _ham = ham;
    }
    return self;
}
@end
```


# dumpするコマンド
##シンボル一覧を取得

```
$ clang -cc1 -ast-list -fblocks -x objective-c Spam.h
```

###出力結果
```
__int128_t
__uint128_t
SEL
id

...(省略)...

NSXPCListenerEndpoint::_internal
Spam
Spam::ham
Spam::initWithHam:
ham
```

##ASTをdump
```
$ clang -cc1 -ast-dump -fblocks -x objective-c Spam.h
```
###出力結果
```
TranslationUnitDecl 0x1028218d0 <<invalid sloc>>
|-TypedefDecl 0x102821dd0 <<invalid sloc>> __int128_t '__int128'
|-TypedefDecl 0x102821e30 <<invalid sloc>> __uint128_t 'unsigned __int128'
|-TypedefDecl 0x102821ec0 <<invalid sloc>> SEL 'SEL *'
|-TypedefDecl 0x102821f90 <<invalid sloc>> id 'id'
|-TypedefDecl 0x102822060 <<invalid sloc>> Class 'Class *'

...(省略)...

|   `-ParmVarDecl 0x1053064c0 <col:30> protocol 'Protocol *'
|-ObjCInterfaceDecl 0x105306560 prev 0x105301ad0 <line:194:1, line:198:2> NSXPCListenerEndpoint
| |-super ObjCInterface 0x103181710 'NSObject'
| |-ObjCProtocol 0x1031b2f00 'NSSecureCoding'
| |-AvailabilityAttr 0x1053065d0 </System/Library/Frameworks/CoreFoundation.framework/Headers/CFAvailability.h:95:49, col:81> macosx 10.8 0 0 ""
| |-VisibilityAttr 0x105306660 </System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:259:55, col:75> Default
| `-ObjCIvarDecl 0x105306700 </System/Library/Frameworks/Foundation.framework/Headers/NSXPCConnection.h:196:5, col:11> _internal 'void *' private
`-ObjCInterfaceDecl 0x105306760 <Spam.h:3:1, line:7:2> Spam
  |-super ObjCInterface 0x103181710 'NSObject'
  |-ObjCPropertyDecl 0x105306870 <line:4:1, col:29> ham 'NSString *' readwrite retain atomic
  |-ObjCMethodDecl 0x105306900 <line:6:1, col:44> - initWithHam: 'instancetype':'id'
  | `-ParmVarDecl 0x105306990 <col:30, col:41> ham 'NSString *'
  |-ObjCMethodDecl 0x1053069f0 <line:4:29> - ham 'NSString *'
  `-ObjCMethodDecl 0x105306a80 <col:29> - setHam: 'void'
    `-ParmVarDecl 0x105306b10 <col:29> ham 'NSString *'
```


##ASTをpretty-print
```
$ clang -cc1 -ast-print -fblocks -x objective-c Spam.h
```
###出力結果
```
typedef SEL *SEL;
typedef id id;
typedef Class *Class;

...(省略)...

@interface NSXPCListenerEndpoint : NSObject<NSSecureCoding> {
    void * _internal;
}
@end
@interface Spam : NSObject
@property ( readwrite,retain,atomic ) NSString * ham;
- (instancetype) initWithHam:(NSString *)ham;
@end
```


##特定のシンボルに関連する部分のみ取得
`-ast-list`で取得したシンボル名を指定して、そのシンボルに関連する部分のみdumpする。

```
$ clang -cc1 -ast-dump -fblocks -x objective-c Spam.h -ast-dump-filter Spam
```
###出力結果
```
Dumping Spam:
ObjCInterfaceDecl 0x105506760 <Spam.h:3:1, line:7:2> Spam
|-super ObjCInterface 0x102a13110 'NSObject'
|-ObjCPropertyDecl 0x105506870 <line:4:1, col:29> ham 'NSString *' readwrite retain atomic
|-ObjCMethodDecl 0x105506900 <line:6:1, col:44> - initWithHam: 'instancetype':'id'
| `-ParmVarDecl 0x105506990 <col:30, col:41> ham 'NSString *'
|-ObjCMethodDecl 0x1055069f0 <line:4:29> - ham 'NSString *'
`-ObjCMethodDecl 0x105506a80 <col:29> - setHam: 'void'
  `-ParmVarDecl 0x105506b10 <col:29> ham 'NSString *'
```

`-ast-dump-filter`は`-ast-print`に対しても利用可能。



dump関連のオプションはまだある。詳細はhelp参照。