2016-07-08 4 views
0

안녕하세요 저는 매우 잘 작동하는 AST 방문자를 구현했으며 변수 선언, 함수 선언 및 함수 호출과 같은 AST에서 원하는 정보를 콘솔에 인쇄 할 수 있습니다 . 오늘 나는 실험하면서 함수 호출로 인식되지 않는 함수 호출을 발견했습니다. Syntacticaly는 함수 호출과 같습니다. ASTvisitor의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 
} 

내 코드는 다음과 같습니다 :

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> 헤더 파일에서보기를 갈 경우에 당신은 그것이 가리키는 것 실제 functiondecl로 연결됩니다 LinkageSpecDecl을라고 뭔가, 함수가 이제 MACRO

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

것을 볼 수 있습니다.

이러한 문제를 해결하기 위해 할 수있는 일은 기대하는 바를 알려주므로 구문 분석하려는 코드의 원시 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 및 다른 것들을 별도로 방문하기 때문에 구현할 수 있습니다. 당신은 적절한 기능으로 모든 것이 당신에게 올 것이므로 케이스를 던지거나 유지할 필요가 없습니다. 방문자 패턴이 어떻게 작동하는지 자세히 알아볼 수 있습니다. 나는 아주 좋은 링크가 없다면 나는 당신에게도 그것을 제공했을 것이다.

+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()도 존재합니다 .. –