如何从 typedefDecl 获取底层 cxxRecordDecl
How to get underly cxxRecordDecl from typedefDecl
我有一段代码:
typedef struct S1{
int a;
int b;
} S, *PS;
我可以通过 clang-check 来跟踪 AST:
| |-CXXRecordDecl 0x3dfde48 col:16 隐式结构 S1
| |-FieldDecl 0x3dfdef8 col:9一个'int'
| -FieldDecl 0x3dfdf58 <line:4:5, col:9> col:9 b 'int'
|-TypedefDecl 0x3dfe010 <line:1:1, line:5:3> col:3 S 'struct S1':'struct S1'
|
-ElaboratedType 0x3dfdfc0 'struct S1' 糖
| -RecordType 0x3dfddc0 'struct S1'
|
-CXXRecord 0x3dfdd28 'S1'
-TypedefDecl 0x3dfe0f0 <line:1:1, line:5:7> col:7 PS 'struct S1 *'
-指针类型 0x3dfe0a0 'struct S1 *'
-ElaboratedType 0x3dfdfc0 'struct S1' sugar
-记录类型 0x3dfddc0 'struct S1'
`-CXXRecord 0x3dfdd28 'S1'
如果我使用 typedefDecl(),我可以匹配 S 和 PS,但是我怎样才能得到底层的 cxxRecordDecl()?
一种方法是使用遍历匹配器来限定 typedefDecl
。第一跳是 typedef 的类型,第二跳是该类型的声明。这终止于您正在查找的 cxxRecordDecl。
typedefDecl(
hasType(
hasDeclaration(
cxxRecordDecl().bind("the_struct")
))).bind("the_typedef")
这可行,但它有(至少)两个问题。首先,它还会匹配您可能不想匹配的内容,其次,它无法匹配代码中的指针 typedef 声明。看第一个问题,运行那个匹配器在clang-query
。将您的片段放入 test_input_struct_type.cpp:
$ clang-query test_input_struct_type.cpp --
clang-query> let m1 typedefDecl( hasType( hasDeclaration(cxxRecordDecl().bind("the_struct"))))
clang-query> m m1
Match #1:
Match #2:
test_input_struct_type.cpp:1:1: note: "root" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
test_input_struct_type.cpp:1:9: note: "the_struct" binds here
typedef struct S1{
^~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "the_typedef" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
2 matches.
第 2 场比赛看起来不错,但第 1 场比赛是什么?我怀疑匹配器正在命中一些 typedef 节点,这些节点似乎是由编译器在翻译单元的 AST 开头插入的。
解决第一个问题的一种方法是添加一些更具体的内容:
typedefDecl(
hasType(
elaboratedType(
namesType(
recordType(
hasDeclaration(
cxxRecordDecl().bind("the_struct")
))))).bind("the_typedef")
回到clang-query
:
clang-query> let m2 typedefDecl(hasType(elaboratedType( namesType( recordType( hasDeclaration(cxxRecordDecl().bind("the_struct")))) ))).bind("the_typedef")
clang-query> m m2
Match #1:
test_input_struct_type.cpp:1:1: note: "root" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
test_input_struct_type.cpp:1:9: note: "the_struct" binds here
typedef struct S1{
^~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "the_typedef" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
1 match.
第二个问题——找到指针typedef呢?这需要一个稍微不同的匹配器:
typedefDecl(
hasType(
pointerType(
pointee(
hasDeclaration(
cxxRecordDecl().bind("pointee_struct")
))))).bind("the_typedef")
然后可以使用 anyOf
组合两个匹配器。返回 clang-query
:
clang-query> let m2a hasType(elaboratedType( namesType( recordType( hasDeclaration(cxxRecordDecl().bind("the_struct"))))))
clang-query> let m3a hasType(pointerType( pointee( hasDeclaration(cxxRecordDecl().bind("pointee_struct")))))
clang-query> let m4 typedefDecl( anyOf(m2a,m3a)).bind("the_typedef")
clang-query> m m4
Match #1:
test_input_struct_type.cpp:1:1: note: "root" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
test_input_struct_type.cpp:1:9: note: "the_struct" binds here
typedef struct S1{
^~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "the_typedef" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
Match #2:
test_input_struct_type.cpp:1:9: note: "pointee_struct" binds here
typedef struct S1{
^~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "root" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "the_typedef" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
2 matches.
我有一段代码:
typedef struct S1{
int a;
int b;
} S, *PS;
我可以通过 clang-check 来跟踪 AST:
| |-CXXRecordDecl 0x3dfde48 col:16 隐式结构 S1
| |-FieldDecl 0x3dfdef8 col:9一个'int'
| -FieldDecl 0x3dfdf58 <line:4:5, col:9> col:9 b 'int'
|-TypedefDecl 0x3dfe010 <line:1:1, line:5:3> col:3 S 'struct S1':'struct S1'
|
-ElaboratedType 0x3dfdfc0 'struct S1' 糖
| -RecordType 0x3dfddc0 'struct S1'
|
-CXXRecord 0x3dfdd28 'S1'
-TypedefDecl 0x3dfe0f0 <line:1:1, line:5:7> col:7 PS 'struct S1 *'
-指针类型 0x3dfe0a0 'struct S1 *'
-ElaboratedType 0x3dfdfc0 'struct S1' sugar
-记录类型 0x3dfddc0 'struct S1'
`-CXXRecord 0x3dfdd28 'S1'
如果我使用 typedefDecl(),我可以匹配 S 和 PS,但是我怎样才能得到底层的 cxxRecordDecl()?
一种方法是使用遍历匹配器来限定 typedefDecl
。第一跳是 typedef 的类型,第二跳是该类型的声明。这终止于您正在查找的 cxxRecordDecl。
typedefDecl(
hasType(
hasDeclaration(
cxxRecordDecl().bind("the_struct")
))).bind("the_typedef")
这可行,但它有(至少)两个问题。首先,它还会匹配您可能不想匹配的内容,其次,它无法匹配代码中的指针 typedef 声明。看第一个问题,运行那个匹配器在clang-query
。将您的片段放入 test_input_struct_type.cpp:
$ clang-query test_input_struct_type.cpp --
clang-query> let m1 typedefDecl( hasType( hasDeclaration(cxxRecordDecl().bind("the_struct"))))
clang-query> m m1
Match #1:
Match #2:
test_input_struct_type.cpp:1:1: note: "root" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
test_input_struct_type.cpp:1:9: note: "the_struct" binds here
typedef struct S1{
^~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "the_typedef" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
2 matches.
第 2 场比赛看起来不错,但第 1 场比赛是什么?我怀疑匹配器正在命中一些 typedef 节点,这些节点似乎是由编译器在翻译单元的 AST 开头插入的。
解决第一个问题的一种方法是添加一些更具体的内容:
typedefDecl(
hasType(
elaboratedType(
namesType(
recordType(
hasDeclaration(
cxxRecordDecl().bind("the_struct")
))))).bind("the_typedef")
回到clang-query
:
clang-query> let m2 typedefDecl(hasType(elaboratedType( namesType( recordType( hasDeclaration(cxxRecordDecl().bind("the_struct")))) ))).bind("the_typedef")
clang-query> m m2
Match #1:
test_input_struct_type.cpp:1:1: note: "root" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
test_input_struct_type.cpp:1:9: note: "the_struct" binds here
typedef struct S1{
^~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "the_typedef" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
1 match.
第二个问题——找到指针typedef呢?这需要一个稍微不同的匹配器:
typedefDecl(
hasType(
pointerType(
pointee(
hasDeclaration(
cxxRecordDecl().bind("pointee_struct")
))))).bind("the_typedef")
然后可以使用 anyOf
组合两个匹配器。返回 clang-query
:
clang-query> let m2a hasType(elaboratedType( namesType( recordType( hasDeclaration(cxxRecordDecl().bind("the_struct"))))))
clang-query> let m3a hasType(pointerType( pointee( hasDeclaration(cxxRecordDecl().bind("pointee_struct")))))
clang-query> let m4 typedefDecl( anyOf(m2a,m3a)).bind("the_typedef")
clang-query> m m4
Match #1:
test_input_struct_type.cpp:1:1: note: "root" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
test_input_struct_type.cpp:1:9: note: "the_struct" binds here
typedef struct S1{
^~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "the_typedef" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
Match #2:
test_input_struct_type.cpp:1:9: note: "pointee_struct" binds here
typedef struct S1{
^~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "root" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "the_typedef" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
2 matches.