[cfe-dev] Clang function call expressions

Richard Trieu via cfe-dev cfe-dev at lists.llvm.org
Mon Jul 11 19:37:08 PDT 2016


The ASTContext holds a reference to a SourceManager that you can use.  The
function getSourceManager() will let you access it.  The getExpansionLoc
from SourceManager will help get the source of the macro expansion.

On Mon, Jul 11, 2016 at 3:34 AM, mats petersson <mats at planetcatfish.com>
wrote:

> Your AST dump doesn't list the va_start, which is EITHER because it
> expands to nothing, or because your code filters it out and doesn't print
> it - as suggested above, that the "location" is not what you expect,
> because a macro expands with the location from the macro definition, not
> the location of the macro being used.
>
> va_start and va_end are implementation defined, and are usually macros.
> Depending on the system, this may expand to a function or some other
> expression - or nothing. It all depends on "what needs to be done" in the
> calling convention combination of compiler, OS and processor architecture.
>
>
> --
> Mats
>
> On 9 July 2016 at 13:50, Georgiou, Andreas via cfe-dev <
> cfe-dev at lists.llvm.org> wrote:
>
>> Dear all,
>>
>>
>> This is the ast dump of the function call:
>>
>>
>> CallExpr 0x3adb460 'void'
>> |-ImplicitCastExpr 0x3adb448 'void (*)(const char *, const char *,
>> __va_list_tag *)' <FunctionToPointerDecay>
>> | `-ParenExpr 0x3adb3b0 'void (const char *, const char *, __va_list_tag
>> *)':'void (const char *, const char *, __va_list_tag *)'
>> |   `-UnaryOperator 0x3adb390 'void (const char *, const char *,
>> __va_list_tag *)':'void (const char *, const char *, __va_list_tag *)'
>> prefix '*'
>> |     `-ImplicitCastExpr 0x3adb378 'TIFFErrorHandler':'void (*)(const
>> char *, const char *, __va_list_tag *)' <LValueToRValue>
>> |       `-DeclRefExpr 0x3adb350 'TIFFErrorHandler':'void (*)(const char
>> *, const char *, __va_list_tag *)' lvalue Var 0x3ad89e0 '_TIFFerrorHandler'
>> 'TIFFErrorHandler':'void (*)(const char *, const char *, __va_list_tag *)'
>> |-ImplicitCastExpr 0x3adb4a0 'const char *' <LValueToRValue>
>> | `-DeclRefExpr 0x3adb3d0 'const char *' lvalue ParmVar 0x3adad80
>> 'module' 'const char *'
>> |-ImplicitCastExpr 0x3adb4b8 'const char *' <LValueToRValue>
>> | `-DeclRefExpr 0x3adb3f8 'const char *' lvalue ParmVar 0x3adadf0 'fmt'
>> 'const char *'
>> `-ImplicitCastExpr 0x3adb4d0 '__va_list_tag *' <ArrayToPointerDecay>
>>   `-DeclRefExpr 0x3adb420 'va_list':'__va_list_tag [1]' lvalue Var
>> 0x3adafa0 'ap' 'va_list':'__va_list_tag [1]'
>> CallExpr 0x3adb688 'void'
>> |-ImplicitCastExpr 0x3adb670 'void (*)(thandle_t, const char *, const
>> char *, __va_list_tag *)' <FunctionToPointerDecay>
>> | `-ParenExpr 0x3adb5b8 'void (thandle_t, const char *, const char *,
>> __va_list_tag *)':'void (thandle_t, const char *, const char *,
>> __va_list_tag *)'
>> |   `-UnaryOperator 0x3adb598 'void (thandle_t, const char *, const char
>> *, __va_list_tag *)':'void (thandle_t, const char *, const char *,
>> __va_list_tag *)' prefix '*'
>> |     `-ImplicitCastExpr 0x3adb580 'TIFFErrorHandlerExt':'void
>> (*)(thandle_t, const char *, const char *, __va_list_tag *)'
>> <LValueToRValue>
>> |       `-DeclRefExpr 0x3adb558 'TIFFErrorHandlerExt':'void
>> (*)(thandle_t, const char *, const char *, __va_list_tag *)' lvalue Var
>> 0x3ada590 '_TIFFerrorHandlerExt' 'TIFFErrorHandlerExt':'void (*)(thandle_t,
>> const char *, const char *, __va_list_tag *)'
>> |-ImplicitCastExpr 0x3adb6d0 'thandle_t':'void *' <NullToPointer>
>> | `-IntegerLiteral 0x3adb5d8 'int' 0
>> |-ImplicitCastExpr 0x3adb6e8 'const char *' <LValueToRValue>
>> | `-DeclRefExpr 0x3adb5f8 'const char *' lvalue ParmVar 0x3adad80
>> 'module' 'const char *'
>> |-ImplicitCastExpr 0x3adb700 'const char *' <LValueToRValue>
>> | `-DeclRefExpr 0x3adb620 'const char *' lvalue ParmVar 0x3adadf0 'fmt'
>> 'const char *'
>> `-ImplicitCastExpr 0x3adb718 '__va_list_tag *' <ArrayToPointerDecay>
>>   `-DeclRefExpr 0x3adb648 'va_list':'__va_list_tag [1]' lvalue Var
>> 0x3adafa0 'ap' 'va_list':'__va_list_tag [1]'
>>
>> On stackoverflow somebody told me its a macro which defines a function
>> call. Is there a way I can extract the original function call from the
>> macro definition?
>>
>> Also you talked about removing the   if(thisFileID == 1), but I want a
>> way to extract only the function calls  or variable definitions from the
>> file i use as input. This was the only way I figure out to get it work. I
>> know I have to use the SourceManager since the last has a function called
>> getMainFileID() but I couldnt initialise the SourceManager.
>>
>> Here is the code:
>>
>>
>> class ExampleVisitor : public RecursiveASTVisitor<ExampleVisitor> {
>> private:
>>     ASTContext *astContext; // used for getting additional AST info
>> public:
>>     explicit ExampleVisitor(CompilerInstance *CI)
>>       : astContext(&(CI->getASTContext()))// directly initialize private
>> members
>>     {
>> }
>>
>>     bool VisitVarDecl(VarDecl *var)
>>     {
>>         FullSourceLoc FullLocation =
>> astContext->getFullLoc(var->getLocStart());
>>     FileID fileID = FullLocation.getFileID();
>>     //SourceManager SM(astContext->getSourceManager());
>>     //FileID MFileID = SM.getMainFileID();
>>     //unsigned int mainFileID = MFileID.getHashValue();
>> // if(thisFileID == mainFileID) do ...
>> unsigned int thisFileID = fileID.getHashValue();
>> if (thisFileID == 1) //checks if the node is in the main = input file.
>> {
>> if(var->hasLocalStorage() || var->isStaticLocal ())
>> {
>> //var->dump(); //prints the corresponding line of the AST.
>> numVariables++;
>> string varName = var->getQualifiedNameAsString();
>> string varType = var->getType().getAsString();
>> REPORT << "Variable Declaration: " << varName << " of type " << varType
>> << "\n";
>> APIs << varType << ",";
>> }
>> }
>>         return true;
>>     }
>>
>> As you can see my goal is to use a source file which includes header
>> files and extract from it some variable type definitions function calls
>> etc. Any ideas are welcomed.
>>
>> Again thank you for your time
>>
>>
>>
>> ------------------------------
>> *From:* Richard Trieu <rtrieu at google.com>
>> *Sent:* 08 July 2016 22:39:02
>> *To:* Georgiou, Andreas
>> *Cc:* cfe-dev at lists.llvm.org
>> *Subject:* Re: [cfe-dev] Clang function call expressions
>>
>> Can you get the AST dump of the function call so we can have a look at
>> it?  The output from "call->dump();" will help since va_start and va_end
>> may be implemented differently on different systems.
>>
>> Also another thing to consider is that the functions may actually be
>> function-like macros, which may given an unexpected location for you.
>> Removing the check "if(thisFileID == 1)" may help.
>>
>> On Fri, Jul 8, 2016 at 7:48 AM, Georgiou, Andreas via cfe-dev <
>> cfe-dev at lists.llvm.org> wrote:
>>
>>> Hello I have implemented an AST visitor which is working quite good and
>>> it can print me on the console the information I want from the AST such as
>>> variable declarations, function declarations and function calls. Today
>>> while I was experimenting I came across a function call which is not
>>> recognized as a function call. syntacticaly is the same as a function call.
>>> Here is the code:
>>>
>>>
>>> void  //this is a part of the tiff library for linux. its in the source
>>> file tif_error.c in libtiff directory
>>> 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
>>> }
>>>
>>> My code of the ASTvisitor is this:
>>>
>>>
>>>  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;
>>>     }
>>>
>>> The expression if(call->getDirectCallee()) is not true for those calls.
>>>
>>>
>>> How can I extract the "function name" and its arguments like I am doing
>>> with the "normal" function calls?
>>>
>>>
>>> Thank you.
>>>
>>> _______________________________________________
>>> cfe-dev mailing list
>>> cfe-dev at lists.llvm.org
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>>
>>>
>>
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20160711/5b47bb61/attachment.html>


More information about the cfe-dev mailing list