[英]How to get the entire expression on the right hand side of clang abstract syntax tree?
Let us take a toy example, say I have the following code in test.cpp file: 让我们以一个玩具示例为例,说我在test.cpp文件中有以下代码:
int main()
{
int gt = 3;
int g = 10 / gt;
}
I want to find the variable name of the denominator in the division operation, then using clang I get the abstract syntax tree (AST) of the above code using the command clang -Xclang -ast-dump -fsyntax-only test.cpp
. 我想在除法运算中找到分母的变量名,然后使用clang命令
clang -Xclang -ast-dump -fsyntax-only test.cpp
获得上述代码的抽象语法树(AST)。 I get the following output 我得到以下输出
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'
From the knowledge of above AST and using clang-query, I get the variable name of the denominator using the following command 根据以上AST的知识并使用clang-query,我可以使用以下命令获取分母的变量名称
clang-query> match declRefExpr(isExpansionInMainFile(), allOf(hasAncestor(binaryOperator(hasOperatorName("/"))), hasAncestor(declStmt()) ))
I get my output as 我得到的输出为
Match #1:
/home/clang-llvm/cpp/code/test.cpp:4:15: note: "root" binds here
int g = 10 / gt;
^~
1 match.
Now that we are on the same page, I have two questions. 现在我们在同一页上,我有两个问题。
Here in the above toy example, instead of 10 if I have another variable then my query matches both the variables (numerator and denominator). 在上面的玩具示例中,如果我有另一个变量,那么我的查询将匹配两个变量(分子和分母),而不是10。 How can I restrict my clang-query to match only the variable that is the denominator of the division operation?
如何限制我的clang查询仅匹配作为除法运算分母的变量? In other words, how to find the variable that is present in the right hand side of the binary operator "/" ?
换句话说,如何找到存在于二进制运算符“ /”右侧的变量? An example is
int g = gw / gt;
一个例子是
int g = gw / gt;
Instead of a variable gt, if I have an expression in the denominator then how can I get the whole expression using clang? 如果我在分母中有一个表达式,而不是变量gt,那么如何使用clang获得整个表达式? In other words, how to get expression that is on the right hand side of the binary operator "/" in the abstract syntax tree?
换句话说,如何获取抽象语法树中二进制运算符“ /”右侧的表达式? A simple example could be
int g = gw / (gt - gw);
一个简单的例子可以是
int g = gw / (gt - gw);
and a complex example could be int g = gw / gt - gw / gr * gg / sqrt( gt - gw ^ 2) + gq;
一个复杂的例子可能是
int g = gw / gt - gw / gr * gg / sqrt( gt - gw ^ 2) + gq;
I appreciate any help in this regard. 我感谢在这方面的任何帮助。
Clang has a traversal matcher "hasRHS()", which does exactly what you want. 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;
}
Output: 输出:
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" is bind to what you want. “ myExpr”绑定到您想要的内容。 Ref: http://clang.llvm.org/docs/LibASTMatchersReference.html
参考: http : //clang.llvm.org/docs/LibASTMatchersReference.html
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.