clang python绑定:如何查找变量的类型

时间:2018-02-12 15:54:13

标签: python c++ clang

我正在尝试使用clang及其python绑定来处理C / C ++代码的AST。

我有以下测试C ++代码:

#include <stdio.h>

class myclass {
public:
        void mymethod() {
                printf("method\n");
        }
};

void testfunc() {
        myclass var;
        var.mymethod();
}

我编写了以下python代码(简化和缩短)来完成它:

#! /usr/bin/python

import clang.cindex
import sys

def walk(node):
    if node.kind == clang.cindex.CursorKind.CALL_EXPR:
        print 'name: %s, type: %s' % (node.spelling or node.displayname, node.type.spelling)

    for c in node.get_children():
        walk(c)

index = clang.cindex.Index.create()
walk(index.parse(sys.argv[1]).cursor)

现在,当我的代码在testfunc中到达var.mymethod()时,它会显示&#34; mymethod&#34;和&#34;无效&#34;。不是我的预期。我试图检索调用mymethod的类类型,而不是方法的返回类型。

1 个答案:

答案 0 :(得分:1)

如上面的评论中所述,您将获得该函数的返回类型。这不是调用<div id="trigger"></div> <img src="https://www.aaltowave.com/img/still2.svg"/> <script> jQuery(function() { var $window = jQuery(window); var endpoint = jQuery("#trigger").offset().top - $window.height(); $window.on('scroll', function() { if ( (endpoint) < $window.scrollTop() ) { jQuery( "img[src='https://www.aaltowave.com/img/still2.svg']" ).attr("src","https://www.aaltowave.com/img/movement22.svg");} });});</script> 的变量的类型。

查看AST输出(使用clang -Xclang -ast-dump -fno-diagnostics-color),这是mymethod的定义

testfunc

然后,您可以在`-FunctionDecl 0x5e14080 <line:9:1, line:12:1> line:9:6 testfunc 'void ()' `-CompoundStmt 0x5e14750 <col:17, line:12:1> |-DeclStmt 0x5e146b0 <line:10:9, col:20> | `-VarDecl 0x5e14130 <col:9, col:17> col:17 used var 'myclass' callinit | `-CXXConstructExpr 0x5e14680 <col:17> 'myclass' 'void () noexcept' `-CXXMemberCallExpr 0x5e14728 <line:11:9, col:22> 'void' `-MemberExpr 0x5e146f0 <col:9, col:13> '<bound member function type>' .mymethod 0x5e13dd0 `-DeclRefExpr 0x5e146c8 <col:9> 'myclass' lvalue Var 0x5e14130 'var' 'myclass' 内看到CXXMemberCallExpr内部MemberExpr,其中DeclRefExpr引用var及其类型myclass 。你究竟是如何在Python中编写的,我不确定,但是通过从CALL_EXPR条目中转储一些内部结构来解决这个问题并不是非常困难。

使用上面的代码,我修改它看起来像这样:

#! /usr/bin/python

import clang.cindex
import sys

def find_decl_ref_expr(node):
    for c in node.get_children():
        if c.kind == clang.cindex.CursorKind.DECL_REF_EXPR:
            print "Member function call via", c.type.spelling, c.displayname
        else:
            find_decl_ref_expr(c)


def called_from(node):
    for c in node.get_children():
        if c.kind == clang.cindex.CursorKind.MEMBER_REF_EXPR:
            find_decl_ref_expr(c);

def walk(node):
    if node.kind == clang.cindex.CursorKind.CALL_EXPR:
        print 'name: %s, type: %s' % (node.spelling or node.displayname, node.type.spelling)
    called_from(node)

    for c in node.get_children():
        walk(c)

index = clang.cindex.Index.create()
walk(index.parse(sys.argv[1]).cursor)

它有点有效,但它绝对不是一个完整的解决方案。例如,添加通过数组使用的指针也会打印用于进入数组的索引。为了完全理解复杂的代码,我不确定您实际需要做什么[例如如果myclass是一个具有各种指针和索引操作的类的几个层]。

我还发布了一些我用它来检查每个节点中的代码的代码:

def dump_children(node):
    for c in node.get_children():
        print c.kind, c.type.spelling
        dump_children(c)