2016-07-08 11 views
0

你好,我已经实现了一个工作得很好的AST访问者,它可以在控制台中打印我想从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; 
} 

表达如果(呼叫 - > getDirectCallee())是不是为那些通话真。

如何提取“函数名”及其参数,如我正在做的“正常”函数调用? 甚至有人告诉我为什么这些调用不被AST递归访问者认为是正常的函数调用。

谢谢。

回答

0

它没有显示给你的原因是因为它实际上不是一个函数。如果您在<cstdarg>头文件中去看看,你会看到该函数是一个宏

#define va_start(ap, param) __builtin_va_start(ap, param) 

现在,它的东西,就是所谓的LinkageSpecDecl这将链接到它的指向实际functiondecl。

解决此类问题的一些方法是查看您试图解析的代码的原始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 
} 

然后产生它的使用AST转储(假设上面的代码存储在temp.cpp):

clang -Xclang -ast-dump -fsyntax-only temp.cpp 

另一个指针会代替visitStmt,并检查该functiondecl,你可以做的是实现visitFuncDecl,visitDeclRef和其他,因为这将分开访问它们。你将不必做任何事情,因为所有的事情都会以适当的方式传达给你。您可以阅读更多关于访问者模式如何工作的信息。我没有很好的联系,否则我也会给你。

+0

谢谢你的回答。这将澄清事情,并会让我继续前进。我转储相应的行,我可以看到__builtin_va_start(ap,param),但是我从来没有像之前那样(定义一个函数调用的宏)之类的东西。在你最后一点上,我已经实现了VisitVarDecl和VisitFuctionDecl。 VisitStmt将帮助我获得函数调用。如果有更好的方法让他们请让我知道。 –

+0

您可以调用像visitCallExpr,visitCXXMemberCallExpr这样的函数来执行常规函数和成员函数调用。可能会有更多,但我不知道这一点。此外,如果您的原始问题已解决,我会很感激,如果您标记它。 –

+0

感谢您的评论。我不知道visitCallExpr存在!我在doxygen中没有遇到过这个功能。我正在使用这个源http://clang.llvm.org/doxygen/classclang_1_1idx_1_1ASTVisitor.html 你是对的。 VisitCallExpr()也存在.. –