Open6

nccc: Clangの -dump-ast=json から各種定義を抽出したい

okuokuokuoku

というわけで各種オブジェクトを抽出していく。(JSONだと読みづらいので以下YAMLに一旦変換している)

ASTからはマクロは抽出できないため、残った

  • C関数
  • C型(typedef)
  • struct
  • union
  • enum

がターゲットになる。

prev

https://zenn.dev/okuoku/scraps/c5539fc0d668b9

okuokuokuoku

基本構造

全てのASTノードは id kind を持つ。root の kindTranslationUnitDecl となり、その中の inner 配列が個々の宣言となる。

定義には loc オブジェクトが付き、これを使って定義位置を取得できる。

例えば、定義されている関数名を列挙したければ、 FunctionDecl をkindとして持つノードの name を列挙することになる。

  - id: '0x21e7f6efe58'
    kind: FunctionDecl
    loc:
      offset: 6937
      file: e:/repos/em2native-tests/_build/Android@armeabi-v7a/_yfrm_headers/SDL2\SDL_platform.h
      line: 265
      col: 38
      tokLen: 15
      includedFrom:
        file: e:/repos/em2native-tests/_build/Android@armeabi-v7a/_yfrm_headers/SDL2\SDL_config.h
    range:
      begin:
        offset: 6900
        col: 1
        tokLen: 6
        includedFrom:
          file: e:/repos/em2native-tests/_build/Android@armeabi-v7a/_yfrm_headers/SDL2\SDL_config.h
      end:
        offset: 6958
        col: 59
        tokLen: 1
        includedFrom:
          file: e:/repos/em2native-tests/_build/Android@armeabi-v7a/_yfrm_headers/SDL2\SDL_config.h
    name: SDL_GetPlatform
    mangledName: SDL_GetPlatform
    type:
      qualType: const char *(void)
    storageClass: extern
    inner: (略)
okuokuokuoku

関数

まず簡単なケースということで関数の抽出をする。関数を表現するASTノードは

kind: FunctionDecl
kind: FunctionProtoType

の2つとなる。 FunctionDecl が通常の意味の関数定義で、 FunctionProtoType は関数型の表現に使われる。

  - id: '0x21e7facc180'
    kind: FunctionDecl
    name: SDL_WasInit
    mangledName: SDL_WasInit
    type:
      qualType: Uint32 (Uint32)
    storageClass: extern
    inner:
      - id: '0x21e7facc0a8'
        kind: ParmVarDecl
        name: flags
        type:
          desugaredQualType: unsigned int
          qualType: Uint32
          typeAliasDeclId: '0x21e7f95c5d0'
      - id: '0x21e7facc230'
        kind: VisibilityAttr
        visibility: default

関数の型と引数

関数の型は qualType フィールドに 文字列で 保持される。これは別途パースしないといけない。ただし基本的には 戻り型 (引数型, 引数型, ...) となっているが引数の型は ParamVarDecl に含まれるのでパースする必要はない。

  - id: '0x21e7f8a45d0'
    kind: FunctionDecl
    name: qsort
    mangledName: qsort
    type:
      qualType: void (void *, size_t, size_t, __compar_fn_t)
    inner:
      - id: '0x21e7f8a42f8'
        kind: ParmVarDecl
        name: __base
        type:
          qualType: void *
      - id: '0x21e7f8a4378'
        kind: ParmVarDecl
        name: __nmemb
        type:
          desugaredQualType: unsigned long
          qualType: size_t
          typeAliasDeclId: '0x21e7f7f5320'
      - id: '0x21e7f8a43f8'
        kind: ParmVarDecl
        name: __size
        type:
          desugaredQualType: unsigned long
          qualType: size_t
          typeAliasDeclId: '0x21e7f7f5320'
      - id: '0x21e7f8a4478'
        kind: ParmVarDecl
        name: _compar
        type:
          desugaredQualType: int (*)(const void *, const void *)
          qualType: __compar_fn_t
          typeAliasDeclId: '0x21e7f87cc18'

ここで型 __compar_fn_t

  - id: '0x21e7f87cc18'
    kind: TypedefDecl
    isReferenced: true
    name: __compar_fn_t
    type:
      qualType: int (*)(const void *, const void *)
    inner:
      - id: '0x21e7f87cba0'
        kind: PointerType
        type:
          qualType: int (*)(const void *, const void *)
        inner:
          - id: '0x21e7f87cb40'
            kind: ParenType
            type:
              qualType: int (const void *, const void *)
            inner:
              - id: '0x21e7f87cb00'
                kind: FunctionProtoType
                type:
                  qualType: int (const void *, const void *)
                cc: cdecl
                inner:
                  - id: '0x21e7f6ef040'
                    kind: BuiltinType
                    type:
                      qualType: int
                  - id: '0x21e7f878140'
                    kind: PointerType
                    type:
                      qualType: const void *
                    inner:
                      - id: '0x21e7f6eefa1'
                        kind: QualType
                        type:
                          qualType: const void
                        qualifiers: const
                        inner:
                          - id: '0x21e7f6eefa0'
                            kind: BuiltinType
                            type:
                              qualType: void
                  - id: '0x21e7f878140'
                    kind: PointerType
                    type:
                      qualType: const void *
                    inner:
                      - id: '0x21e7f6eefa1'
                        kind: QualType
                        type:
                          qualType: const void
                        qualifiers: const
                        inner:
                          - id: '0x21e7f6eefa0'
                            kind: BuiltinType
                            type:
                              qualType: void
okuokuokuoku

struct / union

これらはRecordとして纏めて扱われる。

kind: RecordDecl
kind: RecordType

宣言は RecordDecl ノードで行われ、そのinnerの FieldDecl で個々のフィールドが宣言される。struct/unionの区別は tagUsed フィールドで指定される。

  - id: '0x21e7fa08900'
    kind: RecordDecl
    name: SDL_Color
    tagUsed: struct
    completeDefinition: true
    inner:
      - id: '0x21e7fa089b0'
        kind: FieldDecl
        name: r
        type:
          desugaredQualType: unsigned char
          qualType: Uint8
          typeAliasDeclId: '0x21e7f95c1d0'
      - id: '0x21e7fa08a18'
        kind: FieldDecl
        name: g
        type:
          desugaredQualType: unsigned char
          qualType: Uint8
          typeAliasDeclId: '0x21e7f95c1d0'
      - id: '0x21e7fa08a80'
        kind: FieldDecl
        name: b
        type:
          desugaredQualType: unsigned char
          qualType: Uint8
          typeAliasDeclId: '0x21e7f95c1d0'
      - id: '0x21e7fa08ae8'
        kind: FieldDecl
        name: a
        type:
          desugaredQualType: unsigned char
          qualType: Uint8
          typeAliasDeclId: '0x21e7f95c1d0'
okuokuokuoku

enum

enum は2種のノードで構成される。

kind: EnumConstantDecl
kind: EnumDecl

... 定数定義が入っている場合は。。? クラスがある場合は。。?

  - id: '0x21e7fac5850'
    kind: EnumDecl
    inner:
      - id: '0x21e7fac5910'
        kind: EnumConstantDecl
        name: ShapeModeDefault
        type:
          qualType: int
      - id: '0x21e7fac5990'
        kind: EnumConstantDecl
        name: ShapeModeBinarizeAlpha
        type:
          qualType: int
        inner:
      - id: '0x21e7fac5a10'
        kind: EnumConstantDecl
        name: ShapeModeReverseBinarizeAlpha
        type:
          qualType: int
      - id: '0x21e7fac5a90'
        kind: EnumConstantDecl
        name: ShapeModeColorKey
        type:
          qualType: int
okuokuokuoku

typedef

typedefは TypedefDeclElaboratedType で表現される。

  - id: '0x21e7fac5b58'
    kind: TypedefDecl
    isReferenced: true
    name: WindowShapeMode
    type:
      desugaredQualType: WindowShapeMode
      qualType: enum WindowShapeMode
    inner:
      - id: '0x21e7fac5af0'
        kind: ElaboratedType
        type:
          qualType: enum WindowShapeMode
        ownedTagDecl:
          id: '0x21e7fac5850'
          kind: EnumDecl
          name: ''
        inner:
          - id: '0x21e7fac58f0'
            kind: EnumType
            type:
              qualType: WindowShapeMode
            decl:
              id: '0x21e7fac5850'
              kind: EnumDecl
              name: ''