[cfe-dev] Clang function call expressions

Georgiou, Andreas via cfe-dev cfe-dev at lists.llvm.org
Tue Jul 12 05:28:39 PDT 2016


thank you very much for your answer!!

________________________________
From: Richard Trieu <rtrieu at google.com>
Sent: 12 July 2016 03:37:08
To: mats petersson
Cc: Georgiou, Andreas; cfe-dev at lists.llvm.org
Subject: Re: [cfe-dev] Clang function call expressions

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<mailto: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<mailto: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<mailto:rtrieu at google.com>>
Sent: 08 July 2016 22:39:02
To: Georgiou, Andreas
Cc: cfe-dev at lists.llvm.org<mailto: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<mailto: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<mailto: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<mailto: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/20160712/35caa4b4/attachment-0001.html>


More information about the cfe-dev mailing list