Clang Cindex: проблема с получением иерархии классов, когда задействованы шаблоны - PullRequest
0 голосов
/ 04 января 2019

Я пытаюсь получить полную иерархию класса, используя привязку Clang Python.

В основном то, что я делаю, это:

  • Найдите курсор CLASS_DECL, объявляющий класс.
  • Переберите его дочерние элементы, ища CXX_BASE_SPECIFIER узел.
  • Получить родительское объявление через get_definition() или type.get_declaration()

Однако у меня возникла проблема, когда родительским классом являются шаблоны. Я привел довольно простой пример, демонстрирующий проблему.

import clang.cindex

clang.cindex.Config.set_library_file('/usr/lib/llvm-6.0/lib/libclang.so')


def get_template_args(node):
    t = node.type
    if t.get_num_template_arguments() < 0:
        return []
    for i in range(t.get_num_template_arguments()):
        yield t.get_template_argument_type(i)


def str_node_type(node):
    if isinstance(node, clang.cindex.Cursor):
        return '[K={}] [S={}] [DN={}] [ISDEF: {}]'.format(node.kind, node.spelling, node.displayname,
                                                          node.is_definition())
    else:
        return '[K={}] [Type:{}]'.format(node.kind, node.spelling)


def find_parent2(node):
    print('\tFind parent2')
    print('\t\tNode {}'.format(str_node_type(node)))
    print('\t\tNum template args: {}'.format(node.canonical.get_num_template_arguments()))
    for c in node.get_children():
        if c.kind == clang.cindex.CursorKind.CXX_BASE_SPECIFIER:
            print('\t\tFound base: {}'.format(str_node_type(c)))


def find_parent(classdecl_node):
    for c in classdecl_node.get_children():
        if c.kind == clang.cindex.CursorKind.CXX_BASE_SPECIFIER:
            print('\tFound base: {}'.format(str_node_type(c)))
            definition = c.get_definition()
            print('\tTemplate arguments for type {}: {}'.format(str_node_type(definition.type),
                                                                definition.type.get_num_template_arguments()))
            for a in get_template_args(c):
                print('\t\tArg: {}'.format(str_node_type(a)))
            find_parent2(c.type.get_declaration())  # or find_parent2(definition)


def main():
    tu = clang.cindex.TranslationUnit.from_source('class.cpp', ['-std=c++11', '-O0'],
                                                  options=clang.cindex.TranslationUnit.PARSE_INCOMPLETE | clang.cindex.TranslationUnit.PARSE_SKIP_FUNCTION_BODIES)

    for node in tu.cursor.get_children():
        if (node.kind == clang.cindex.CursorKind.CLASS_DECL or
                node.kind == clang.cindex.CursorKind.STRUCT_DECL):
            print('Found class declaration:{}'.format(str_node_type(node)))
            find_parent(node)


if __name__ == "__main__":
    main()

Соответствующий файл C ++, который анализируется:

template<typename T>
class GrandParent
{
};

template<typename T>
class Parent : public GrandParent<T> {};

class VerySimple {};
class Simple : public VerySimple {};

class Child : public Parent<int>, public  Simple
{
};

Читая вывод, мы видим, что мы можем найти класс VerySimple, который является прародителем без шаблонов. Однако мы не видим упоминания GrandParent, который является шаблоном класса.

Found class declaration:[K=CursorKind.CLASS_DECL] [S=VerySimple] [DN=VerySimple] [ISDEF: True]
Found class declaration:[K=CursorKind.CLASS_DECL] [S=Simple] [DN=Simple] [ISDEF: True]
        Found base: [K=CursorKind.CXX_BASE_SPECIFIER] [S=class VerySimple] [DN=class VerySimple] [ISDEF: False]
        Template arguments for type [K=TypeKind.RECORD] [Type:VerySimple]: -1
        Find parent2
                Node [K=CursorKind.CLASS_DECL] [S=VerySimple] [DN=VerySimple] [ISDEF: True]
                Num template args: -1
Found class declaration:[K=CursorKind.CLASS_DECL] [S=Child] [DN=Child] [ISDEF: True]
        Found base: [K=CursorKind.CXX_BASE_SPECIFIER] [S=Parent<int>] [DN=Parent<int>] [ISDEF: False]
        Template arguments for type [K=TypeKind.RECORD] [Type:Parent<int>]: 1
                Arg: [K=TypeKind.INT] [Type:int]
        Find parent2
                Node [K=CursorKind.CLASS_DECL] [S=Parent] [DN=Parent<int>] [ISDEF: True]
                Num template args: -1
        Found base: [K=CursorKind.CXX_BASE_SPECIFIER] [S=class Simple] [DN=class Simple] [ISDEF: False]
        Template arguments for type [K=TypeKind.RECORD] [Type:Simple]: -1
        Find parent2
                Node [K=CursorKind.CLASS_DECL] [S=Simple] [DN=Simple] [ISDEF: True]
                Num template args: -1
                Found base: [K=CursorKind.CXX_BASE_SPECIFIER] [S=class VerySimple] [DN=class VerySimple] [ISDEF: False]

Я не уверен, что я здесь упускаю или неправильно понимаю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...