AST 访问者函数调用表达式无法正确识别函数调用
AST visitor function call expression not recognizes correctly the function call
你好,我已经实现了一个 AST 访问器,它工作得很好,它可以在控制台中打印我想要从 AST 获得的信息,例如变量声明、函数声明和函数调用。今天我在做实验时遇到了一个函数调用,它不被识别为函数调用。语法上与函数调用相同。这是代码:
void
TIFFError(const char* module, const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt); <------------------------------ THIS IS THE FUNCTION CALL
if (_TIFFerrorHandler)
(*_TIFFerrorHandler)(module, fmt, ap);
if (_TIFFerrorHandlerExt)
(*_TIFFerrorHandlerExt)(0, module, fmt, ap);
va_end(ap); <--------------------------------AND THIS ONE
}
我的 ASTvisitor 代码是这样的:
bool VisitStmt(Stmt *st)
{
FullSourceLoc FullLocation = astContext->getFullLoc(st->getLocStart());
FileID fileID = FullLocation.getFileID();
unsigned int thisFileID = fileID.getHashValue();
if(thisFileID == 1) //checks if the node is in the main = input file.
{
if (CallExpr *call = dyn_cast<CallExpr>(st))
{
numFuncCalls++;
//call->dump(); //prints the corresponding line of the AST.
FunctionDecl *func_decl;
if(call->getDirectCallee())
{
func_decl = call ->getDirectCallee();
string funcCall = func_decl->getNameInfo().getName().getAsString();
cout << "Function call: " << funcCall << " with arguments ";
APIs << funcCall << ",";
for(int i=0, j = call->getNumArgs(); i<j; i++)
{
//For each argument it prints its type. The function must be declared otherwise it will return int-for unknown argument type.
APIs << call->getArg(i)->getType().getAsString()<< ",";
cout << call->getArg(i)->getType().getAsString() << ", ";
}
cout << "\n";
}
else
{
Expr *expr = call->getCallee();
string exprCall = expr->getStmtClassName();
cout << "Expression call: " << exprCall << " with arguments ";
APIs << exprCall << ",";
for(int i=0, j = call->getNumArgs(); i<j; i++)
{
//For each argument it prints its type. The function must be declared otherwise it will return int-for unknown argument type.
APIs << call->getArg(i)->getType().getAsString()<< ",";
cout << call->getArg(i)->getType().getAsString() << ", ";
}
cout << "\n";
}
}
}
return true;
}
对于这些调用,表达式 if(call->getDirectCallee()) 不正确。
如何像处理 "normal" 函数调用那样提取 "function name" 及其参数?
或者甚至有人告诉我为什么这些调用不能被 AST 递归访问者识别为正常的函数调用。
谢谢。
它没有作为函数显示给您的原因是因为它实际上不是函数。如果您查看 <cstdarg>
头文件,您会发现该函数是一个 MACRO
#define va_start(ap, param) __builtin_va_start(ap, param)
现在,它是一个叫做 LinkageSpecDecl 的东西,它将 link 到它指向的实际函数声明。
解决此类问题的方法是查看您尝试解析的代码的原始 ASTDump,因为它会告诉您预期的结果。
比如我把你的函数改成了这个。
#include <cstdarg>
void TIFFError(const char* module, const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt); <------------------------------ THIS IS THE FUNCTION CALL
if (_TIFFerrorHandler)
(*_TIFFerrorHandler)(module, fmt, ap);
if (_TIFFerrorHandlerExt)
(*_TIFFerrorHandlerExt)(0, module, fmt, ap);
va_end(ap); <--------------------------------AND THIS ONE
}
然后使用(假设上面的代码存储在 temp.cpp)生成它的 ast 转储:
clang -Xclang -ast-dump -fsyntax-only temp.cpp
另一个指针将代替 visitStmt 并在其中检查 functiondecl,您可以做的是实现 visitFuncDecl、visitDeclRef 和其他指针,因为那样会单独访问它们。您不必执行转换和维护案例,因为一切都会以适当的方式出现。您可以阅读有关访问者模式如何为此工作的更多信息。我没有很好的 link 否则我也会给你的。
你好,我已经实现了一个 AST 访问器,它工作得很好,它可以在控制台中打印我想要从 AST 获得的信息,例如变量声明、函数声明和函数调用。今天我在做实验时遇到了一个函数调用,它不被识别为函数调用。语法上与函数调用相同。这是代码:
void
TIFFError(const char* module, const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt); <------------------------------ THIS IS THE FUNCTION CALL
if (_TIFFerrorHandler)
(*_TIFFerrorHandler)(module, fmt, ap);
if (_TIFFerrorHandlerExt)
(*_TIFFerrorHandlerExt)(0, module, fmt, ap);
va_end(ap); <--------------------------------AND THIS ONE
}
我的 ASTvisitor 代码是这样的:
bool VisitStmt(Stmt *st)
{
FullSourceLoc FullLocation = astContext->getFullLoc(st->getLocStart());
FileID fileID = FullLocation.getFileID();
unsigned int thisFileID = fileID.getHashValue();
if(thisFileID == 1) //checks if the node is in the main = input file.
{
if (CallExpr *call = dyn_cast<CallExpr>(st))
{
numFuncCalls++;
//call->dump(); //prints the corresponding line of the AST.
FunctionDecl *func_decl;
if(call->getDirectCallee())
{
func_decl = call ->getDirectCallee();
string funcCall = func_decl->getNameInfo().getName().getAsString();
cout << "Function call: " << funcCall << " with arguments ";
APIs << funcCall << ",";
for(int i=0, j = call->getNumArgs(); i<j; i++)
{
//For each argument it prints its type. The function must be declared otherwise it will return int-for unknown argument type.
APIs << call->getArg(i)->getType().getAsString()<< ",";
cout << call->getArg(i)->getType().getAsString() << ", ";
}
cout << "\n";
}
else
{
Expr *expr = call->getCallee();
string exprCall = expr->getStmtClassName();
cout << "Expression call: " << exprCall << " with arguments ";
APIs << exprCall << ",";
for(int i=0, j = call->getNumArgs(); i<j; i++)
{
//For each argument it prints its type. The function must be declared otherwise it will return int-for unknown argument type.
APIs << call->getArg(i)->getType().getAsString()<< ",";
cout << call->getArg(i)->getType().getAsString() << ", ";
}
cout << "\n";
}
}
}
return true;
}
对于这些调用,表达式 if(call->getDirectCallee()) 不正确。
如何像处理 "normal" 函数调用那样提取 "function name" 及其参数? 或者甚至有人告诉我为什么这些调用不能被 AST 递归访问者识别为正常的函数调用。
谢谢。
它没有作为函数显示给您的原因是因为它实际上不是函数。如果您查看 <cstdarg>
头文件,您会发现该函数是一个 MACRO
#define va_start(ap, param) __builtin_va_start(ap, param)
现在,它是一个叫做 LinkageSpecDecl 的东西,它将 link 到它指向的实际函数声明。
解决此类问题的方法是查看您尝试解析的代码的原始 ASTDump,因为它会告诉您预期的结果。
比如我把你的函数改成了这个。
#include <cstdarg>
void TIFFError(const char* module, const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt); <------------------------------ THIS IS THE FUNCTION CALL
if (_TIFFerrorHandler)
(*_TIFFerrorHandler)(module, fmt, ap);
if (_TIFFerrorHandlerExt)
(*_TIFFerrorHandlerExt)(0, module, fmt, ap);
va_end(ap); <--------------------------------AND THIS ONE
}
然后使用(假设上面的代码存储在 temp.cpp)生成它的 ast 转储:
clang -Xclang -ast-dump -fsyntax-only temp.cpp
另一个指针将代替 visitStmt 并在其中检查 functiondecl,您可以做的是实现 visitFuncDecl、visitDeclRef 和其他指针,因为那样会单独访问它们。您不必执行转换和维护案例,因为一切都会以适当的方式出现。您可以阅读有关访问者模式如何为此工作的更多信息。我没有很好的 link 否则我也会给你的。