mkl
mkl

Reputation: 675

Use python bindings to clang to check if a C++ type is a pointer, reference, etc. in canonical fashion?

Consider an object t of type clang.cindex.Type representing a C++ variable declaration such as const T& x; or a parameter declaration occurring in something like

template<typename... Ts> void f(Ts&&...);

Is there a canonical way to determine if t is/represents (1) a pointer, (2) a lvalue or rvalue reference, (3) a parameter pack?

Obviously, by manually parsing t.spelling, one can solve the above problems, roughly as follows: Assume that the file x.h contains

const T & x;

Then the following code will print True:

import clang
from clang import cindex

def is_lvalue_ref(type):
    spell = type.spelling  # 'const T &'
    tokens = spell.split(' ')  # ['const', 'T', '&']
    return (tokens[-1] == '&') 
cindex.Config.set_library_path('/Library/Developer/CommandLineTools/usr/lib')
index = cindex.Index.create()
tu = index.parse('x.h', ['c++', '-std=c++17'])
for x in tu.cursor.get_children():
    # x is CursorKind.VAR_DECL
    print(is_lvalue_ref(x.type))

(For pointers or parameter packs, proceed similarly.) But clearly, this is undesirable! Is there a canonical way to achieve this?

Upvotes: 2

Views: 1337

Answers (1)

Lorenzo Binosi
Lorenzo Binosi

Reputation: 21

I think i'm super late right now, but i had the same problem and solved in a canonical way.

Whenever you have a PARM_DECL you can understand if some qualifier is applied in this way:

node.type.get_pointee().is_const_qualified()

It returns True if the parameter declaration has the const qualifier, like:

const string &

EDIT:

I have finally found the solution: once you have a typekind object you just access the attribute kind and if it is a reference its kind will be TypeKind.LVALUEREFERENCE.

node.type.kind

If you want to access the underlying type of the reference you need to get it through get_pointee(), so

node.type.get_pointee().spelling

Upvotes: 2

Related Questions