如何获取clang抽象语法树右侧的整个表达式?
How to get the entire expression on the right hand side of clang abstract syntax tree?
让我们举个例子,假设我在 test.cpp 文件中有以下代码:
int main()
{
int gt = 3;
int g = 10 / gt;
}
我想在除法运算中找到分母的变量名,然后使用 clang 我使用命令 clang -Xclang -ast-dump -fsyntax-only test.cpp
得到上面代码的抽象语法树(AST)。我得到以下输出
TranslationUnitDecl 0x34f8100 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x34f8638 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
| `-BuiltinType 0x34f8350 '__int128'
|-TypedefDecl 0x34f8698 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x34f8370 'unsigned __int128'
|-TypedefDecl 0x34f8728 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x34f86f0 'char *'
| `-BuiltinType 0x34f8190 'char'
|-TypedefDecl 0x34f8a48 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]'
| `-ConstantArrayType 0x34f89f0 'struct __va_list_tag [1]' 1
| `-RecordType 0x34f8810 'struct __va_list_tag'
| `-CXXRecord 0x34f8778 '__va_list_tag'
`-FunctionDecl 0x34f8af0 <test.cpp:1:1, line:5:1> line:1:5 main 'int (void)'
`-CompoundStmt 0x34f8dc0 <line:2:1, line:5:1>
|-DeclStmt 0x34f8c98 <line:3:2, col:12>
| `-VarDecl 0x34f8c18 <col:2, col:11> col:6 used gt 'int' cinit
| `-IntegerLiteral 0x34f8c78 <col:11> 'int' 3
`-DeclStmt 0x34f8da8 <line:4:2, col:17>
`-VarDecl 0x34f8cc0 <col:2, col:15> col:6 g 'int' cinit
`-BinaryOperator 0x34f8d80 <col:10, col:15> 'int' '/'
|-IntegerLiteral 0x34f8d20 <col:10> 'int' 10
`-ImplicitCastExpr 0x34f8d68 <col:15> 'int' <LValueToRValue>
`-DeclRefExpr 0x34f8d40 <col:15> 'int' lvalue Var 0x34f8c18 'gt' 'int'
根据上述 AST 的知识和使用 clang-query,我使用以下命令获取分母的变量名
clang-query> match declRefExpr(isExpansionInMainFile(), allOf(hasAncestor(binaryOperator(hasOperatorName("/"))), hasAncestor(declStmt()) ))
我的输出是
Match #1:
/home/clang-llvm/cpp/code/test.cpp:4:15: note: "root" binds here
int g = 10 / gt;
^~
1 match.
既然我们在同一页上,我有两个问题。
在上面的玩具示例中,如果我有另一个,而不是 10
变量然后我的查询匹配两个变量(分子和
分母)。我怎样才能限制我的 clang-query 只匹配
作为除法运算的分母的变量?其他
单词,如何找到右手的变量
二元运算符“/”的一侧?一个例子是 int g = gw / gt;
而不是变量gt,如果我在分母中有一个表达式
那么如何使用 clang 获得整个表达式?换一种说法,
如何获得二进制文件右侧的表达式
抽象语法树中的运算符“/”?一个简单的例子可以是
int g = gw / (gt - gw);
一个复杂的例子可以是 int g = gw
/ gt - gw / gr * gg / sqrt( gt - gw ^ 2) + gq;
非常感谢这方面的任何帮助。
Clang 有一个遍历匹配器 "hasRHS()",它完全可以满足您的需求。
int main()
{
int gt = 3;
int g = 10 / gt;
int gw, gg, gr, gq;
int g1 = gw / gt;
int g2 = gw / (gt-gw);
int g3 = gw / gt - gw / gr * gg / ( gt - gw ^ 2) + gq;
return 0;
}
输出:
clang-query> match varDecl(hasDescendant(binaryOperator(hasOperatorName("/"), hasRHS(expr().bind("myExpr")))))
Match #1:
/home/test.cpp:4:18: note: "myExpr" binds here
int g = 10 / gt;
^~
/home/test.cpp:4:5: note: "root" binds here
int g = 10 / gt;
^~~~~~~~~~~~~~~
Match #2:
/home/test.cpp:7:19: note: "myExpr" binds here
int g1 = gw / gt;
^~
/home/test.cpp:7:5: note: "root" binds here
int g1 = gw / gt;
^~~~~~~~~~~~~~~~
Match #3:
/home/test.cpp:8:19: note: "myExpr" binds here
int g2 = gw / (gt-gw);
^~~~~~~
/home/test.cpp:8:5: note: "root" binds here
int g2 = gw / (gt-gw);
^~~~~~~~~~~~~~~~~~~~~
Match #4:
/home/test.cpp:9:19: note: "myExpr" binds here
int g3 = gw / gt - gw / gr * gg / ( gt - gw ^ 2) + gq;
^~
/home/test.cpp:9:5: note: "root" binds here
int g3 = gw / gt - gw / gr * gg / ( gt - gw ^ 2) + gq;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 matches.
"myExpr" 绑定到你想要的。
参考:http://clang.llvm.org/docs/LibASTMatchersReference.html
让我们举个例子,假设我在 test.cpp 文件中有以下代码:
int main()
{
int gt = 3;
int g = 10 / gt;
}
我想在除法运算中找到分母的变量名,然后使用 clang 我使用命令 clang -Xclang -ast-dump -fsyntax-only test.cpp
得到上面代码的抽象语法树(AST)。我得到以下输出
TranslationUnitDecl 0x34f8100 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x34f8638 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
| `-BuiltinType 0x34f8350 '__int128'
|-TypedefDecl 0x34f8698 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x34f8370 'unsigned __int128'
|-TypedefDecl 0x34f8728 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x34f86f0 'char *'
| `-BuiltinType 0x34f8190 'char'
|-TypedefDecl 0x34f8a48 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]'
| `-ConstantArrayType 0x34f89f0 'struct __va_list_tag [1]' 1
| `-RecordType 0x34f8810 'struct __va_list_tag'
| `-CXXRecord 0x34f8778 '__va_list_tag'
`-FunctionDecl 0x34f8af0 <test.cpp:1:1, line:5:1> line:1:5 main 'int (void)'
`-CompoundStmt 0x34f8dc0 <line:2:1, line:5:1>
|-DeclStmt 0x34f8c98 <line:3:2, col:12>
| `-VarDecl 0x34f8c18 <col:2, col:11> col:6 used gt 'int' cinit
| `-IntegerLiteral 0x34f8c78 <col:11> 'int' 3
`-DeclStmt 0x34f8da8 <line:4:2, col:17>
`-VarDecl 0x34f8cc0 <col:2, col:15> col:6 g 'int' cinit
`-BinaryOperator 0x34f8d80 <col:10, col:15> 'int' '/'
|-IntegerLiteral 0x34f8d20 <col:10> 'int' 10
`-ImplicitCastExpr 0x34f8d68 <col:15> 'int' <LValueToRValue>
`-DeclRefExpr 0x34f8d40 <col:15> 'int' lvalue Var 0x34f8c18 'gt' 'int'
根据上述 AST 的知识和使用 clang-query,我使用以下命令获取分母的变量名
clang-query> match declRefExpr(isExpansionInMainFile(), allOf(hasAncestor(binaryOperator(hasOperatorName("/"))), hasAncestor(declStmt()) ))
我的输出是
Match #1:
/home/clang-llvm/cpp/code/test.cpp:4:15: note: "root" binds here
int g = 10 / gt;
^~
1 match.
既然我们在同一页上,我有两个问题。
在上面的玩具示例中,如果我有另一个,而不是 10 变量然后我的查询匹配两个变量(分子和 分母)。我怎样才能限制我的 clang-query 只匹配 作为除法运算的分母的变量?其他 单词,如何找到右手的变量 二元运算符“/”的一侧?一个例子是
int g = gw / gt;
而不是变量gt,如果我在分母中有一个表达式 那么如何使用 clang 获得整个表达式?换一种说法, 如何获得二进制文件右侧的表达式 抽象语法树中的运算符“/”?一个简单的例子可以是
int g = gw / (gt - gw);
一个复杂的例子可以是int g = gw / gt - gw / gr * gg / sqrt( gt - gw ^ 2) + gq;
非常感谢这方面的任何帮助。
Clang 有一个遍历匹配器 "hasRHS()",它完全可以满足您的需求。
int main()
{
int gt = 3;
int g = 10 / gt;
int gw, gg, gr, gq;
int g1 = gw / gt;
int g2 = gw / (gt-gw);
int g3 = gw / gt - gw / gr * gg / ( gt - gw ^ 2) + gq;
return 0;
}
输出:
clang-query> match varDecl(hasDescendant(binaryOperator(hasOperatorName("/"), hasRHS(expr().bind("myExpr")))))
Match #1:
/home/test.cpp:4:18: note: "myExpr" binds here
int g = 10 / gt;
^~
/home/test.cpp:4:5: note: "root" binds here
int g = 10 / gt;
^~~~~~~~~~~~~~~
Match #2:
/home/test.cpp:7:19: note: "myExpr" binds here
int g1 = gw / gt;
^~
/home/test.cpp:7:5: note: "root" binds here
int g1 = gw / gt;
^~~~~~~~~~~~~~~~
Match #3:
/home/test.cpp:8:19: note: "myExpr" binds here
int g2 = gw / (gt-gw);
^~~~~~~
/home/test.cpp:8:5: note: "root" binds here
int g2 = gw / (gt-gw);
^~~~~~~~~~~~~~~~~~~~~
Match #4:
/home/test.cpp:9:19: note: "myExpr" binds here
int g3 = gw / gt - gw / gr * gg / ( gt - gw ^ 2) + gq;
^~
/home/test.cpp:9:5: note: "root" binds here
int g3 = gw / gt - gw / gr * gg / ( gt - gw ^ 2) + gq;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 matches.
"myExpr" 绑定到你想要的。 参考:http://clang.llvm.org/docs/LibASTMatchersReference.html