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.