我有一段代码:
typedef struct S1{
int a;
int b;
} S, *PS;
我可以通过clang-check获得以下AST:
| | -CXXRecordDecl 0x3dfde48 col:16隐式struct S1
| | -FieldDecl 0x3dfdef8 col:9 a' 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&#39; struct S1&#39;糖
| -RecordType 0x3dfddc0 'struct S1'
|
- CXXRecord 0x3dfdd28&#39; S1&#39;
-TypedefDecl 0x3dfe0f0 <line:1:1, line:5:7> col:7 PS 'struct S1 *'
- PointerType 0x3dfe0a0&#39; struct S1 *&#39;
-ElaboratedType 0x3dfdfc0 'struct S1' sugar
- RecordType 0x3dfddc0&#39; struct S1&#39;
`-CXXRecord 0x3dfdd28&#39; S1&#39;
如果我使用typedefDecl(),我可以匹配S和PS,但是如何获得底层cxxRecordDecl()?
答案 0 :(得分:0)
一种方法是使用遍历匹配器限定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是什么?我怀疑matcher正在点击一些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.