Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to retrieve function call argument values using libclang

Is it possible to retrieve the argument values of a clang.cindex.CursorKind.CALL_EXPR cursor?

When I dump the AST using the compiler (clang++ -ast-dump source.cpp) I get info about function calls (call expressions) and their arguments. But I'm not able to replicate it using the bindings for python (where the AST is retrieved using libclang's parser).

Here's the source code I'm using:

#include <iostream>
#include <GL/glut.h>
#include <EGL/egl.h>

#define MULTILINE(...) #__VA_ARGS__

void renderFunction()
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0, 0.0, 1.0);
    glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
    glBegin(GL_QUADS);
        glVertex2f(-0.5, -0.5);
        glVertex2f(-0.5, 0.5);
        glVertex2f(0.5, 0.5);
        glVertex2f(0.5, -0.5);
    glEnd();
    glFlush();
}

int main(int argc, char *argv[])
{          
    glutInit(&argc, argv);       
    glutInitDisplayMode(GLUT_SINGLE);
    glutInitWindowSize(500,500);
    glutInitWindowPosition(100,100);
    glutCreateWindow("OpenGL - First window demo");
    glutDisplayFunc(renderFunction);
    glutMainLoop();    

    return 0;
}

Here's a part of its AST dump:

|   |-CallExpr 0x430b540 <line:10:5, col:32> 'void'
|   | |-ImplicitCastExpr 0x430b528 <col:5> 'void (*)(GLbitfield)' <FunctionToPointerDecay>
|   | | `-DeclRefExpr 0x430b4d0 <col:5> 'void (GLbitfield)' lvalue Function 0x3d3b060 'glClear' 'void (GLbitfield)'
|   | `-ImplicitCastExpr 0x430b570 </usr/include/GL/gl.h:691:31> 'GLbitfield':'unsigned int' <IntegralCast>
|   |   `-IntegerLiteral 0x430b4b0 <col:31> 'int' 16384

I'd like to retrieve the IntegerLiteral value part in the last line by evaluating the call expression cursor.

like image 794
Raúl Roa Avatar asked Aug 27 '14 07:08

Raúl Roa


1 Answers

You can get this information from the list of tokens, for IntegerLiteral the first token will be your number (not really that neat but better than nothing!).

Example cpp program:

#define FOO 6

void foo(int x) {}

int main()
{
    foo(FOO);
    return 0;
}

Example python code to parse it and print out just the IntegerLiteral value (using lib clang):

import clang.cindex
import sys

path = '/your/path/to/libclang.so'
clang.cindex.Config.set_library_file(path)

def get_ts(source_path):
    index = clang.cindex.Index.create()
    return index.parse(source_path)

def print_node(node):
    if node.kind == clang.cindex.CursorKind.INTEGER_LITERAL:
        print node.type.kind, node.get_tokens().next().spelling
    map(print_node, node.get_children())

ts = get_ts('test.cpp')
map(print_node, ts.cursor.get_children())

Output:

TypeKind.INT 6
TypeKind.INT 0
like image 142
pm007 Avatar answered Nov 14 '22 03:11

pm007