0

I'm using libclang with it's python binding and I'm trying to get the number of arguments for CallExpr, I found that if a member function has default value and being called with this argument missing, libclang returns the number of arguments in the function declaration and not as in the call expression.

For example :

class SomeClass
{
public:
    int sum(int x, int y)
    {
        return x + y;
    }

    int sum_def(int x, int y = 0)
    {
        return x + y;
    }
};

int main()
{
    SomeClass x;
    x.sum(10, 100);
    x.sum_def(20);
    return 0;
}

traverse ast using liblcang :

def traverse(node):
    if node.kind == clang.cindex.CursorKind.CALL_EXPR:
        print('%-35s %-20s %-10s [%-6s:%s - %-6s:%s] %s %s ' % (
        node.kind, node.spelling, node.type.spelling, node.extent.start.line, node.extent.start.column,
        node.extent.end.line, node.extent.end.column, node.location.file, node.mangled_name))
        print("%d  " % node.get_num_arguments())
        for arg in node.get_arguments():
            print("ARG=%s %s" % (arg.kind, arg.spelling))

    for child in node.get_children():
        traverse(child)

The output :

CursorKind.CALL_EXPR                sum                  int        [20    :5 - 20    :19] main.cpp
2  
ARG=CursorKind.INTEGER_LITERAL 
ARG=CursorKind.INTEGER_LITERAL 
CursorKind.CALL_EXPR                sum_def              int        [21    :5 - 21    :18] main.cpp  
2  
ARG=CursorKind.INTEGER_LITERAL 
ARG=CursorKind.UNEXPOSED_EXPR 

I would expect to get 1 as number of arguments in the CALL_EXPR for sum_def, it is possible to get it or should I parse the code myself, something I don't really want to do. Thank you.

sagi
  • 523
  • 3
  • 15

1 Answers1

0

I changed a bit the traverse function to print more details

def traverse(node, level):
    print('%s %-35s %-20s %-10s [%-6s:%s - %-6s:%s] %s %s ' % (' ' * level,
    node.kind, node.spelling, node.type.spelling, node.extent.start.line, node.extent.start.column,
    node.extent.end.line, node.extent.end.column, node.location.file, node.mangled_name))
    if node.kind == clang.cindex.CursorKind.CALL_EXPR:
        for arg in node.get_arguments():
            print("ARG=%s %s" % (arg.kind, arg.spelling))

    for child in node.get_children():
        traverse(child, level+1)

The output :

  CursorKind.CLASS_DECL               SomeClass            SomeClass  [2     :1 - 14    :2] main.cpp  
   CursorKind.CXX_ACCESS_SPEC_DECL                                     [4     :1 - 4     :8] main.cpp  
   CursorKind.CXX_METHOD               sum                  int (int, int) [5     :5 - 8     :6] main.cpp _ZN9SomeClass3sumEii 
    CursorKind.PARM_DECL                x                    int        [5     :13 - 5     :18] main.cpp _ZZN9SomeClass3sumEiiE1x 
    CursorKind.PARM_DECL                y                    int        [5     :20 - 5     :25] main.cpp _ZZN9SomeClass3sumEiiE1y 
    CursorKind.COMPOUND_STMT                                            [6     :5 - 8     :6] main.cpp  
     CursorKind.RETURN_STMT                                              [7     :9 - 7     :21] main.cpp  
      CursorKind.BINARY_OPERATOR                               int        [7     :16 - 7     :21] main.cpp  
       CursorKind.UNEXPOSED_EXPR           x                    int        [7     :16 - 7     :17] main.cpp  
        CursorKind.DECL_REF_EXPR            x                    int        [7     :16 - 7     :17] main.cpp  
       CursorKind.UNEXPOSED_EXPR           y                    int        [7     :20 - 7     :21] main.cpp  
        CursorKind.DECL_REF_EXPR            y                    int        [7     :20 - 7     :21] main.cpp  
   CursorKind.CXX_METHOD               sum_def              int (int, int) [10    :5 - 13    :6] main.cpp _ZN9SomeClass7sum_defEii 
    CursorKind.PARM_DECL                x                    int        [10    :17 - 10    :22] main.cpp _ZZN9SomeClass7sum_defEiiE1x 
    CursorKind.PARM_DECL                y                    int        [10    :24 - 10    :33] main.cpp _ZZN9SomeClass7sum_defEiiE1y 
     CursorKind.INTEGER_LITERAL                               int        [10    :32 - 10    :33] main.cpp  
    CursorKind.COMPOUND_STMT                                            [11    :5 - 13    :6] main.cpp  
     CursorKind.RETURN_STMT                                              [12    :9 - 12    :21] main.cpp  
      CursorKind.BINARY_OPERATOR                               int        [12    :16 - 12    :21] main.cpp  
       CursorKind.UNEXPOSED_EXPR           x                    int        [12    :16 - 12    :17] main.cpp  
        CursorKind.DECL_REF_EXPR            x                    int        [12    :16 - 12    :17] main.cpp  
       CursorKind.UNEXPOSED_EXPR           y                    int        [12    :20 - 12    :21] main.cpp  
        CursorKind.DECL_REF_EXPR            y                    int        [12    :20 - 12    :21] main.cpp  
  CursorKind.FUNCTION_DECL            main                 int ()     [17    :1 - 26    :2] main.cpp main 
   CursorKind.COMPOUND_STMT                                            [18    :1 - 26    :2] main.cpp  
    CursorKind.DECL_STMT                                                [19    :5 - 19    :22] main.cpp  
     CursorKind.VAR_DECL                 i                    int        [19    :5 - 19    :14] main.cpp _ZZ4mainE1i 
      CursorKind.INTEGER_LITERAL                               int        [19    :13 - 19    :14] main.cpp  
     CursorKind.VAR_DECL                 j                    int        [19    :16 - 19    :21] main.cpp _ZZ4mainE1j 
      CursorKind.INTEGER_LITERAL                               int        [19    :20 - 19    :21] main.cpp  
    CursorKind.DECL_STMT                                                [20    :5 - 20    :17] main.cpp  
     CursorKind.VAR_DECL                 x                    SomeClass  [20    :5 - 20    :16] main.cpp _ZZ4mainE1x 
      CursorKind.TYPE_REF                 class SomeClass      SomeClass  [20    :5 - 20    :14] main.cpp  
      CursorKind.CALL_EXPR                SomeClass            SomeClass  [20    :15 - 20    :16] main.cpp  
    CursorKind.CALL_EXPR                sum                  int        [21    :5 - 21    :19] main.cpp  
ARG=CursorKind.INTEGER_LITERAL 
ARG=CursorKind.INTEGER_LITERAL 
     CursorKind.MEMBER_REF_EXPR          sum                  <bound member function type> [21    :5 - 21    :10] main.cpp  
      CursorKind.DECL_REF_EXPR            x                    SomeClass  [21    :5 - 21    :6] main.cpp  
     CursorKind.INTEGER_LITERAL                               int        [21    :11 - 21    :13] main.cpp  
     CursorKind.INTEGER_LITERAL                               int        [21    :15 - 21    :18] main.cpp  
    CursorKind.CALL_EXPR                sum_def              int        [22    :5 - 22    :18] main.cpp  
ARG=CursorKind.INTEGER_LITERAL 
ARG=CursorKind.UNEXPOSED_EXPR 
     CursorKind.MEMBER_REF_EXPR          sum_def              <bound member function type> [22    :5 - 22    :14] main.cpp  
      CursorKind.DECL_REF_EXPR            x                    SomeClass  [22    :5 - 22    :6] main.cpp  
     CursorKind.INTEGER_LITERAL                               int        [22    :15 - 22    :17] main.cpp  
     CursorKind.UNEXPOSED_EXPR                                int        [0     :0 - 0     :0] None  
    CursorKind.CALL_EXPR                sum_def              int        [23    :5 - 23    :23] main.cpp  
ARG=CursorKind.INTEGER_LITERAL 
ARG=CursorKind.INTEGER_LITERAL 
     CursorKind.MEMBER_REF_EXPR          sum_def              <bound member function type> [23    :5 - 23    :14] main.cpp  
      CursorKind.DECL_REF_EXPR            x                    SomeClass  [23    :5 - 23    :6] main.cpp  
     CursorKind.INTEGER_LITERAL                               int        [23    :15 - 23    :17] main.cpp  
     CursorKind.INTEGER_LITERAL                               int        [23    :19 - 23    :22] main.cpp  
    CursorKind.CALL_EXPR                sum                  int        [24    :5 - 24    :16] main.cpp  
ARG=CursorKind.UNEXPOSED_EXPR i
ARG=CursorKind.UNEXPOSED_EXPR j
     CursorKind.MEMBER_REF_EXPR          sum                  <bound member function type> [24    :5 - 24    :10] main.cpp  
      CursorKind.DECL_REF_EXPR            x                    SomeClass  [24    :5 - 24    :6] main.cpp  
     CursorKind.UNEXPOSED_EXPR           i                    int        [24    :11 - 24    :12] main.cpp  
      CursorKind.DECL_REF_EXPR            i                    int        [24    :11 - 24    :12] main.cpp  
     CursorKind.UNEXPOSED_EXPR           j                    int        [24    :14 - 24    :15] main.cpp  
      CursorKind.DECL_REF_EXPR            j                    int        [24    :14 - 24    :15] main.cpp  
    CursorKind.RETURN_STMT                                              [25    :5 - 25    :13] main.cpp  
     CursorKind.INTEGER_LITERAL                               int        [25    :12 - 25    :13] main.cpp  

With this output, and some more testcases which I added to my source code, I understood that I should count as argument every argument that is not UNEXPOSED_EXPR, and if it is UNEXPOSED_EXRP I should check if it has children. If it does it means that I need to count it.

sagi
  • 523
  • 3
  • 15