2016-07-08 3 views
0

Здравствуйте, я внедрил посетителя 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()) не верно для этих вызовов.

Как извлечь «имя функции» и его аргументы, как я делаю с «нормальными» вызовами функций? Или даже кто-нибудь дает мне представление о том, почему эти вызовы не распознаются рекурсивным посетителем АСТ, как обычные вызовы функций.

спасибо.

ответ

0

Причина, по которой он не отображается вам как функция, состоит в том, что на самом деле это не функция. Если вы посмотрите на <cstdarg> заголовочный файл, вы увидите, что функция является MACRO

#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 
} 

А затем генерируется это аст дамп с помощью (предположим, что верхний код хранится в 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() также существует .. –

 Смежные вопросы

  • Нет связанных вопросов^_^