我有以下c代码test1.c
:
double multiply(double x, double y) {
return x * y * y;
}
int main(int argc, char const *argv[])
{
double a;
int b;
float d;
double x = 3.0;
double y = 5.0;
double z = multiply(x,y);
return 0;
}
我试图通过实现bool VistVarDecl(clang::VarDecl *vardecl)
让RecursiveASTVisitor访问变量声明(clang::VarDecl(。然而,clang::VarDecl
节点从未被访问过,尽管我已经访问了AST中的所有其他节点。此外,在test1.c
I上使用clang-query
可以匹配varDecl
。
我的递归ASTVistor如下:
struct MyASTVisitor : public clang::RecursiveASTVistor<MyASTVisitor> {
bool VistVarDecl(clang::VarDecl *vardecl) {
llvm::outs() << "Found a VarDecl";
};
bool VisitFunctionDecl(clang::FunctionDecl *decl) {
llvm::outs() << "Found a FunctionDecl";
};
// other functions implemented similarly just to see if it visits properly
bool VisitParmVarmDecl(clang::ParmVarDecl *paramvardecl);
bool VisitCallExpr(clang::CallExpr *callexpr);
bool VisitImplicitCastExpr(clang::ImplicitCastExpr *castexpr);
bool VisitBinaryOperator(clang::BinaryOperator *bo);
bool VisitDeclStmt(clang::DeclStmt *declstmt);
bool VisitDeclRefExpr(clang::DeclRefExpr *declrefexpr);
bool VisitFloatingLiteral(clang::FloatingLiteral *floatliteral);
};
struct MyASTConsumer : public clang::ASTConsumer {
bool HandleTopLevelDecl(clang::DeclGroupRef DR) override {
for (clang::DeclGroupRef::iterator b = DR.begin(), e = DR.end(); b != e; ++b) {
Visitor.TraverseDecl(*b);
}
return true;
}
private:
MyASTVisitor Visitor;
};
有人知道clang::VarDecl
节点是唯一没有被RecursiveASTVisitor
访问但被clang-query
匹配的节点吗?
clang的AST转储如下所示:
TranslationUnitDecl 0x7fba2300ce08 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x7fba2300d6a0 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
| `-BuiltinType 0x7fba2300d3a0 '__int128'
|-TypedefDecl 0x7fba2300d710 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x7fba2300d3c0 'unsigned __int128'
|-TypedefDecl 0x7fba2300da18 <<invalid sloc>> <invalid sloc> implicit __NSConstantString 'struct __NSConstantString_tag'
| `-RecordType 0x7fba2300d7f0 'struct __NSConstantString_tag'
| `-Record 0x7fba2300d768 '__NSConstantString_tag'
|-TypedefDecl 0x7fba2300dab0 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x7fba2300da70 'char *'
| `-BuiltinType 0x7fba2300cea0 'char'
|-TypedefDecl 0x7fba2300dda8 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]'
| `-ConstantArrayType 0x7fba2300dd50 'struct __va_list_tag [1]' 1
| `-RecordType 0x7fba2300db90 'struct __va_list_tag'
| `-Record 0x7fba2300db08 '__va_list_tag'
|-FunctionDecl 0x7fba22829370 <test4.c:2:1, line:4:1> line:2:8 used multiply 'double (double, double)'
| |-ParmVarDecl 0x7fba22829218 <col:17, col:24> col:24 used x 'double'
| |-ParmVarDecl 0x7fba22829298 <col:27, col:34> col:34 used y 'double'
| `-CompoundStmt 0x7fba22829560 <col:37, line:4:1>
| `-ReturnStmt 0x7fba22829550 <line:3:2, col:17>
| `-BinaryOperator 0x7fba22829530 <col:9, col:17> 'double' '*'
| |-BinaryOperator 0x7fba228294d8 <col:9, col:13> 'double' '*'
| | |-ImplicitCastExpr 0x7fba228294a8 <col:9> 'double' <LValueToRValue>
| | | `-DeclRefExpr 0x7fba22829468 <col:9> 'double' lvalue ParmVar 0x7fba22829218 'x' 'double'
| | `-ImplicitCastExpr 0x7fba228294c0 <col:13> 'double' <LValueToRValue>
| | `-DeclRefExpr 0x7fba22829488 <col:13> 'double' lvalue ParmVar 0x7fba22829298 'y' 'double'
| `-ImplicitCastExpr 0x7fba22829518 <col:17> 'double' <LValueToRValue>
| `-DeclRefExpr 0x7fba228294f8 <col:17> 'double' lvalue ParmVar 0x7fba22829298 'y' 'double'
`-FunctionDecl 0x7fba228297d0 <line:6:1, line:22:1> line:6:5 main 'int (int, const char **)'
|-ParmVarDecl 0x7fba22829590 <col:10, col:14> col:14 argc 'int'
|-ParmVarDecl 0x7fba228296b0 <col:20, col:37> col:32 argv 'const char **':'const char **'
`-CompoundStmt 0x7fba22829da8 <line:7:1, line:22:1>
|-DeclStmt 0x7fba22829928 <line:10:2, col:10>
| `-VarDecl 0x7fba228298c0 <col:2, col:9> col:9 a 'double'
|-DeclStmt 0x7fba228299c0 <line:12:2, col:7>
| `-VarDecl 0x7fba22829958 <col:2, col:6> col:6 b 'int'
|-DeclStmt 0x7fba22829a58 <line:14:2, col:9>
| `-VarDecl 0x7fba228299f0 <col:2, col:8> col:8 d 'float'
|-DeclStmt 0x7fba22829b10 <line:16:2, col:16>
| `-VarDecl 0x7fba22829a88 <col:2, col:13> col:9 used x 'double' cinit
| `-FloatingLiteral 0x7fba22829af0 <col:13> 'double' 3.000000e+00
|-DeclStmt 0x7fba22829bc8 <line:17:2, col:16>
| `-VarDecl 0x7fba22829b40 <col:2, col:13> col:9 used y 'double' cinit
| `-FloatingLiteral 0x7fba22829ba8 <col:13> 'double' 5.000000e+00
|-DeclStmt 0x7fba22829d60 <line:19:2, col:26>
| `-VarDecl 0x7fba22829bf8 <col:2, col:25> col:9 z 'double' cinit
| `-CallExpr 0x7fba22829d00 <col:13, col:25> 'double'
| |-ImplicitCastExpr 0x7fba22829ce8 <col:13> 'double (*)(double, double)' <FunctionToPointerDecay>
| | `-DeclRefExpr 0x7fba22829c60 <col:13> 'double (double, double)' Function 0x7fba22829370 'multiply' 'double (double, double)'
| |-ImplicitCastExpr 0x7fba22829d30 <col:22> 'double' <LValueToRValue>
| | `-DeclRefExpr 0x7fba22829c80 <col:22> 'double' lvalue Var 0x7fba22829a88 'x' 'double'
| `-ImplicitCastExpr 0x7fba22829d48 <col:24> 'double' <LValueToRValue>
| `-DeclRefExpr 0x7fba22829ca0 <col:24> 'double' lvalue Var 0x7fba22829b40 'y' 'double'
`-ReturnStmt 0x7fba22829d98 <line:21:2, col:9>
`-IntegerLiteral 0x7fba22829d78 <col:9> 'int' 0
正如评论中所指出的,这里的问题几乎可以肯定是在Visit
方法的末尾未能显式地return true
:
bool VisitFunctionDecl(clang::FunctionDecl *decl) {
llvm::outs() << "Found a FunctionDecl";
};
省略return
会导致未定义的行为。在实践中,用于传递返回值的寄存器中的任何内容都可以按原样使用,因此,如果该寄存器恰好包含0,则false
会被有效地返回。
在访问其主体之前调用VisitFunctionDecl
,如果返回false
,则整个遍历将中止,因此它永远不会到达VarDecl
节点。
引用文件:
从这些重写函数中的一个返回false将中止整个遍历。