使用 clang llvm 检查变量在任意源位置的作用域是否具有范围
Check whether a variable has scope at an arbitrary Source Location using clang llvm
我是 clang libtool 的新手,正在努力解决以下问题。
我想对给定的c/c ++程序执行源到源的转换,以便"转换"程序在不同程序点打印所有"范围内"变量值。
例如,在下面的程序中,我想打印范围位于各种 SourceLocation 的变量值(例如,在编号为 8 和 10 的行尾)。 为此,我需要知道变量 c 在第 8 行末尾没有作用域,同样变量 i 和 c 在第 10 行末尾没有作用域。
是否有任何 API 可以帮助查找变量在给定的源位置是否具有范围?如何检查变量是否在程序中的特定源位置具有作用域?
1:void f(){
2: int a=10;
3: for(int i=0; i<10;i++){
4: if(a>10){
5: int b = a+20;
6: {
7: int c = b+10;
8: }
9: }
10: }
11:}
转换后的程序(对于此示例)将如下所示:
1:void f(){
2: int a=10;
3: for(int i=0; i<10;i++){
4: if(a>10){
5: int b = a+20;
6: {
7: int c = b+10;
8: };printf("%d %d %dn", a, b, i);
9: }
10: };printf("%dn", a);
11:}
我想过实现它,但是像 clang 这样的大工具应该已经实现了这个 API!! 或者应该有一些有效/简单的方法来做到这一点。
使用clang-libtooling执行此操作的最佳策略是什么?
谢谢。
Clang提供了一个名为AST Matcher(参考)的API。
使用 clang -Xclang -ast-dump -fsyntax-only test.c
编译代码会转储 AST。
`-FunctionDecl 0x3b0a750 <test_ast.cpp:1:1, line:9:1> line:1:6 f 'void (void)'
`-CompoundStmt 0x3b51958 <col:10, line:9:1>
|-DeclStmt 0x3b0a8c8 <line:2:3, col:13>
| `-VarDecl 0x3b0a848 <col:3, col:11> col:7 used a 'int' cinit
| `-IntegerLiteral 0x3b0a8a8 <col:11> 'int' 10
`-ForStmt 0x3b51920 <line:3:3, line:8:3>
|-DeclStmt 0x3b0a970 <line:3:8, col:17>
| `-VarDecl 0x3b0a8f0 <col:8, col:16> col:12 used i 'int' cinit
| `-IntegerLiteral 0x3b0a950 <col:16> 'int' 0
|-<<<NULL>>>
|-BinaryOperator 0x3b0a9e8 <col:19, col:23> '_Bool' '<'
| |-ImplicitCastExpr 0x3b0a9d0 <col:19> 'int' <LValueToRValue>
| | `-DeclRefExpr 0x3b0a988 <col:19> 'int' lvalue Var 0x3b0a8f0 'i' 'int'
| `-IntegerLiteral 0x3b0a9b0 <col:23> 'int' 10
|-UnaryOperator 0x3b0aa38 <col:27, col:28> 'int' postfix '++'
| `-DeclRefExpr 0x3b0aa10 <col:27> 'int' lvalue Var 0x3b0a8f0 'i' 'int'
`-CompoundStmt 0x3b51900 <col:32, line:8:3>
`-IfStmt 0x3b518d0 <line:4:5, line:7:5>
|-<<<NULL>>>
|-BinaryOperator 0x3b51640 <line:4:9, col:13> '_Bool' '>'
| |-ImplicitCastExpr 0x3b51628 <col:9> 'int' <LValueToRValue>
| | `-DeclRefExpr 0x3b515e0 <col:9> 'int' lvalue Var 0x3b0a848 'a' 'int'
| `-IntegerLiteral 0x3b51608 <col:13> 'int' 10
|-CompoundStmt 0x3b518a8 <col:17, line:7:5>
| |-DeclStmt 0x3b51760 <line:5:7, col:21>
| | `-VarDecl 0x3b51678 <col:7, col:19> col:11 used b 'int' cinit
| | `-BinaryOperator 0x3b51738 <col:15, col:19> 'int' '+'
| | |-ImplicitCastExpr 0x3b51720 <col:15> 'int' <LValueToRValue>
| | | `-DeclRefExpr 0x3b516d8 <col:15> 'int' lvalue Var 0x3b0a848 'a' 'int'
| | `-IntegerLiteral 0x3b51700 <col:19> 'int' 20
| `-CompoundStmt 0x3b51888 <line:6:7, col:25>
| `-DeclStmt 0x3b51870 <col:9, col:23>
| `-VarDecl 0x3b51788 <col:9, col:21> col:13 c 'int' cinit
| `-BinaryOperator 0x3b51848 <col:17, col:21> 'int' '+'
| |-ImplicitCastExpr 0x3b51830 <col:17> 'int' <LValueToRValue>
| | `-DeclRefExpr 0x3b517e8 <col:17> 'int' lvalue Var 0x3b51678 'b' 'int'
| `-IntegerLiteral 0x3b51810 <col:21> 'int' 10
`-<<<NULL>>>
您可以使用 AST 匹配器遍历 AST 并与CompoundStmt
匹配,这将为你提供与 C/C++ 中的作用域对应的 AST 节点。从这里,您可以开始跟踪所有VarDecl
以查找作用域内的变量声明。对于您想要的东西,没有开箱即用的解决方案,但 Clang 为您提供了实现它的工具。
你也可以阅读Eli Bendersky的这篇博文(链接)。他演示了如何使用 AST Matchers 和 Clang 的重写工具来编写您想要的工具。
相关文章:
- 在新作用域中使用unique_lock是否等效于在使用共享资源的工作结束时解锁调用
- 是否有 GCC 标志来发出有关作用域内相同变量重定义的警告?
- 在一个作用域中推送五个对象指针,然后检查对象的布尔值是否为 false,会给出错误
- 大括号的作用域是否用于注释目的,从而降低C++代码的速度
- 是否随作用域分配和解除分配堆栈帧
- 类的堆分配对象是否在其作用域之后但在 C++ 中调用其析构函数之前处于活动状态
- 是否避免因变量作用域而取消分配
- static关键字是否影响作用域
- 提升::作用域的线程是否自动分离
- 如何在C++中检查变量是否在作用域中
- 是否有C++标准类在作用域出口处将变量设置为值
- 使用 clang llvm 检查变量在任意源位置的作用域是否具有范围
- 无作用域枚举是否仍然有用
- 如何找出一个变量是否在clang AST的特定源位置的作用域中
- 在c++中是否有办法访问外部作用域中的局部变量?
- 在c++中是否可以在switch作用域之外声明变量?
- 在iPhone xcode应用程序中,是否可以声明一个具有全局作用域的指针?
- 基于堆栈的RAII是否保证仅在超出c++的作用域后才能运行?
- 是否有可能在不使用指针的情况下将变量的作用域扩展到if语句之外?
- 是否可以使作用域枚举("enum class")在上下文中可转换为布尔值?