Obtaining the parent of a given libclang CXCursor

Hello all -

When using the clang_getCursor function, the caller is returned the most specific cursor at the location given. Is there a process by which I can get progressively less specific cursors? For instance, if given a position inside a function, I’d like to be able to get the cursor from that position, and then look at that cursor’s parents until I find the function declaration.

Currently, I always start at the top and work down, but under some circumstances, it would be very convenient to be able to work up instead.

Thanks for any ideas

  • Nick

Hi Nick

Have a look at clang_getCursorLexicalParent and
clang_getCursorSemanticParent.

By the way, ipython is an excellent way to explore this API. Here's how
I found the above:

   $ export PYTHONPATH=/path/to/clang/bindings/python
   $ ipython
   ::: import clang.cindex
   ::: index = clang.cindex.Index.create()
   ::: tu = index.parse('example.cpp')
   ::: cs = tu.cursor.get_children()
   ::: c = cs.next(); print c.spelling # Ignore the first few implicit typedefs
   ::: c = cs.next(); print c.spelling
   ::: c = cs.next(); print c.spelling
   ::: c = cs.next(); print c.spelling
   ::: cs = c.get_children()
   ::: c = cs.next()
   ::: c.<TAB>
   c.canonical c.get_definition c.result_type
   c.data c.get_usr c.semantic_parent
   c.displayname c.hash c.spelling
   c.enum_type c.is_definition c.translation_unit
   c.enum_value c.is_static_method c.type
   c.extent c.kind c.underlying_typedef_type
   c.from_location c.lexical_parent c.xdata
   c.from_result c.location
   c.get_children c.objc_type_encoding

Then look in clang/bindings/python/clang/cindex.py to find the names
of the corresponding C functions.

Hope this helps!

--Dave.

Hello David -

Thanks for the information - especially regarding ipython. I hadn’t seen that before.

While clang_getCursorLexicalParent and clang_getCursorSemanticParent are helpful under some circumstances, what I’m looking for is a finer grain of control. What I would really like is essentially the opposite of clang_visitChildren. The project I’m working on requires me to be able to give various information about the thing that lies at a particular cursor location. For instance, consider the following code:

#include <stddef.h>
void foo() {
size_t a;
}

If I’m given the position (3, 5) and I ask for the cursor at that location, I’m given a TypeRef cursor for the size_t type. However, what I would really like is the VarDecl that scopes that TypeRef. In order to solve this problem generically, it seems I have to go all the way to global scope and then clang_visitChildren until I find the TypeRef, all while remembering where I was before.

If I were to get the FunctionDecl cursor and then visit its children, I would get the following tree:

FunctionDecl
CompoundStmt
DeclStmt
VarDecl
TypeRef

What I really want is to be able to walk up the tree, instead of only down.

Thanks -

  • Nick

I'm afraid I'm stumped. My suggestion of using
clang_getCursor{Lexical,Semantic}Parent won't work. With the example
code you gave, each cursor's parents are: (Lexical Parent, Semantic
Parent)

FunctionDecl [TranslationUnit, TranslationUnit]
  CompoundStmt [None, FunctionDecl]
    DeclStmt [None, None]
      VarDecl [FunctionDecl, FunctionDecl]
        TypeRef [None, None]

I don't really know the AST API, so I can't say whether the above parent
values are correct. My (naive) expectation was that the lexical parent
was always the cursor immediately preceding in that hierarchy, but maybe
there's a reason it isn't so.

Cheers,
Dave.

I’m afraid I’m stumped. My suggestion of using
clang_getCursor{Lexical,Semantic}Parent won’t work. With the example
code you gave, each cursor’s parents are: (Lexical Parent, Semantic
Parent)

FunctionDecl [TranslationUnit, TranslationUnit]
CompoundStmt [None, FunctionDecl]
DeclStmt [None, None]
VarDecl [FunctionDecl, FunctionDecl]
TypeRef [None, None]

I don’t really know the AST API, so I can’t say whether the above parent
values are correct or a bug. My (naive) expectation was that the lexical
parent was always the cursor immediately preceding in that hierarchy,
but maybe there’s a reason it isn’t so.

Cheers,
Dave.

I'm afraid I'm stumped. My suggestion of using
clang_getCursor{Lexical,Semantic}Parent won't work. With the example
code you gave, each cursor's parents are: (Lexical Parent, Semantic
Parent)

FunctionDecl [TranslationUnit, TranslationUnit]
CompoundStmt [None, FunctionDecl]
   DeclStmt [None, None]
     VarDecl [FunctionDecl, FunctionDecl]
       TypeRef [None, None]

I don't really know the AST API, so I can't say whether the above parent
values are correct or a bug. My (naive) expectation was that the lexical
parent was always the cursor immediately preceding in that hierarchy,
but maybe there's a reason it isn't so.

Cheers,
Dave.