Home | History | Annotate | Download | only in cindex
      1 import gc
      2 
      3 from clang.cindex import CursorKind
      4 from clang.cindex import TranslationUnit
      5 from clang.cindex import TypeKind
      6 from nose.tools import raises
      7 from .util import get_cursor
      8 from .util import get_tu
      9 
     10 kInput = """\
     11 
     12 typedef int I;
     13 
     14 struct teststruct {
     15   int a;
     16   I b;
     17   long c;
     18   unsigned long d;
     19   signed long e;
     20   const int f;
     21   int *g;
     22   int ***h;
     23 };
     24 
     25 """
     26 
     27 def test_a_struct():
     28     tu = get_tu(kInput)
     29 
     30     teststruct = get_cursor(tu, 'teststruct')
     31     assert teststruct is not None, "Could not find teststruct."
     32     fields = list(teststruct.get_children())
     33     assert all(x.kind == CursorKind.FIELD_DECL for x in fields)
     34     assert all(x.translation_unit is not None for x in fields)
     35 
     36     assert fields[0].spelling == 'a'
     37     assert not fields[0].type.is_const_qualified()
     38     assert fields[0].type.kind == TypeKind.INT
     39     assert fields[0].type.get_canonical().kind == TypeKind.INT
     40 
     41     assert fields[1].spelling == 'b'
     42     assert not fields[1].type.is_const_qualified()
     43     assert fields[1].type.kind == TypeKind.TYPEDEF
     44     assert fields[1].type.get_canonical().kind == TypeKind.INT
     45     assert fields[1].type.get_declaration().spelling == 'I'
     46 
     47     assert fields[2].spelling == 'c'
     48     assert not fields[2].type.is_const_qualified()
     49     assert fields[2].type.kind == TypeKind.LONG
     50     assert fields[2].type.get_canonical().kind == TypeKind.LONG
     51 
     52     assert fields[3].spelling == 'd'
     53     assert not fields[3].type.is_const_qualified()
     54     assert fields[3].type.kind == TypeKind.ULONG
     55     assert fields[3].type.get_canonical().kind == TypeKind.ULONG
     56 
     57     assert fields[4].spelling == 'e'
     58     assert not fields[4].type.is_const_qualified()
     59     assert fields[4].type.kind == TypeKind.LONG
     60     assert fields[4].type.get_canonical().kind == TypeKind.LONG
     61 
     62     assert fields[5].spelling == 'f'
     63     assert fields[5].type.is_const_qualified()
     64     assert fields[5].type.kind == TypeKind.INT
     65     assert fields[5].type.get_canonical().kind == TypeKind.INT
     66 
     67     assert fields[6].spelling == 'g'
     68     assert not fields[6].type.is_const_qualified()
     69     assert fields[6].type.kind == TypeKind.POINTER
     70     assert fields[6].type.get_pointee().kind == TypeKind.INT
     71 
     72     assert fields[7].spelling == 'h'
     73     assert not fields[7].type.is_const_qualified()
     74     assert fields[7].type.kind == TypeKind.POINTER
     75     assert fields[7].type.get_pointee().kind == TypeKind.POINTER
     76     assert fields[7].type.get_pointee().get_pointee().kind == TypeKind.POINTER
     77     assert fields[7].type.get_pointee().get_pointee().get_pointee().kind == TypeKind.INT
     78 
     79 def test_references():
     80     """Ensure that a Type maintains a reference to a TranslationUnit."""
     81 
     82     tu = get_tu('int x;')
     83     children = list(tu.cursor.get_children())
     84     assert len(children) > 0
     85 
     86     cursor = children[0]
     87     t = cursor.type
     88 
     89     assert isinstance(t.translation_unit, TranslationUnit)
     90 
     91     # Delete main TranslationUnit reference and force a GC.
     92     del tu
     93     gc.collect()
     94     assert isinstance(t.translation_unit, TranslationUnit)
     95 
     96     # If the TU was destroyed, this should cause a segfault.
     97     decl = t.get_declaration()
     98 
     99 constarrayInput="""
    100 struct teststruct {
    101   void *A[2];
    102 };
    103 """
    104 def testConstantArray():
    105     tu = get_tu(constarrayInput)
    106 
    107     teststruct = get_cursor(tu, 'teststruct')
    108     assert teststruct is not None, "Didn't find teststruct??"
    109     fields = list(teststruct.get_children())
    110     assert fields[0].spelling == 'A'
    111     assert fields[0].type.kind == TypeKind.CONSTANTARRAY
    112     assert fields[0].type.get_array_element_type() is not None
    113     assert fields[0].type.get_array_element_type().kind == TypeKind.POINTER
    114     assert fields[0].type.get_array_size() == 2
    115 
    116 def test_equal():
    117     """Ensure equivalence operators work on Type."""
    118     source = 'int a; int b; void *v;'
    119     tu = get_tu(source)
    120 
    121     a = get_cursor(tu, 'a')
    122     b = get_cursor(tu, 'b')
    123     v = get_cursor(tu, 'v')
    124 
    125     assert a is not None
    126     assert b is not None
    127     assert v is not None
    128 
    129     assert a.type == b.type
    130     assert a.type != v.type
    131 
    132     assert a.type != None
    133     assert a.type != 'foo'
    134 
    135 def test_type_spelling():
    136     """Ensure Type.spelling works."""
    137     tu = get_tu('int c[5]; void f(int i[]); int x; int v[x];')
    138     c = get_cursor(tu, 'c')
    139     i = get_cursor(tu, 'i')
    140     x = get_cursor(tu, 'x')
    141     v = get_cursor(tu, 'v')
    142     assert c is not None
    143     assert i is not None
    144     assert x is not None
    145     assert v is not None
    146     assert c.type.spelling == "int [5]"
    147     assert i.type.spelling == "int []"
    148     assert x.type.spelling == "int"
    149     assert v.type.spelling == "int [x]"
    150 
    151 def test_typekind_spelling():
    152     """Ensure TypeKind.spelling works."""
    153     tu = get_tu('int a;')
    154     a = get_cursor(tu, 'a')
    155 
    156     assert a is not None
    157     assert a.type.kind.spelling == 'Int'
    158 
    159 def test_function_argument_types():
    160     """Ensure that Type.argument_types() works as expected."""
    161     tu = get_tu('void f(int, int);')
    162     f = get_cursor(tu, 'f')
    163     assert f is not None
    164 
    165     args = f.type.argument_types()
    166     assert args is not None
    167     assert len(args) == 2
    168 
    169     t0 = args[0]
    170     assert t0 is not None
    171     assert t0.kind == TypeKind.INT
    172 
    173     t1 = args[1]
    174     assert t1 is not None
    175     assert t1.kind == TypeKind.INT
    176 
    177     args2 = list(args)
    178     assert len(args2) == 2
    179     assert t0 == args2[0]
    180     assert t1 == args2[1]
    181 
    182 @raises(TypeError)
    183 def test_argument_types_string_key():
    184     """Ensure that non-int keys raise a TypeError."""
    185     tu = get_tu('void f(int, int);')
    186     f = get_cursor(tu, 'f')
    187     assert f is not None
    188 
    189     args = f.type.argument_types()
    190     assert len(args) == 2
    191 
    192     args['foo']
    193 
    194 @raises(IndexError)
    195 def test_argument_types_negative_index():
    196     """Ensure that negative indexes on argument_types Raises an IndexError."""
    197     tu = get_tu('void f(int, int);')
    198     f = get_cursor(tu, 'f')
    199     args = f.type.argument_types()
    200 
    201     args[-1]
    202 
    203 @raises(IndexError)
    204 def test_argument_types_overflow_index():
    205     """Ensure that indexes beyond the length of Type.argument_types() raise."""
    206     tu = get_tu('void f(int, int);')
    207     f = get_cursor(tu, 'f')
    208     args = f.type.argument_types()
    209 
    210     args[2]
    211 
    212 @raises(Exception)
    213 def test_argument_types_invalid_type():
    214     """Ensure that obtaining argument_types on a Type without them raises."""
    215     tu = get_tu('int i;')
    216     i = get_cursor(tu, 'i')
    217     assert i is not None
    218 
    219     i.type.argument_types()
    220 
    221 def test_is_pod():
    222     """Ensure Type.is_pod() works."""
    223     tu = get_tu('int i; void f();')
    224     i = get_cursor(tu, 'i')
    225     f = get_cursor(tu, 'f')
    226 
    227     assert i is not None
    228     assert f is not None
    229 
    230     assert i.type.is_pod()
    231     assert not f.type.is_pod()
    232 
    233 def test_function_variadic():
    234     """Ensure Type.is_function_variadic works."""
    235 
    236     source ="""
    237 #include <stdarg.h>
    238 
    239 void foo(int a, ...);
    240 void bar(int a, int b);
    241 """
    242 
    243     tu = get_tu(source)
    244     foo = get_cursor(tu, 'foo')
    245     bar = get_cursor(tu, 'bar')
    246 
    247     assert foo is not None
    248     assert bar is not None
    249 
    250     assert isinstance(foo.type.is_function_variadic(), bool)
    251     assert foo.type.is_function_variadic()
    252     assert not bar.type.is_function_variadic()
    253 
    254 def test_element_type():
    255     """Ensure Type.element_type works."""
    256     tu = get_tu('int c[5]; void f(int i[]); int x; int v[x];')
    257     c = get_cursor(tu, 'c')
    258     i = get_cursor(tu, 'i')
    259     v = get_cursor(tu, 'v')
    260     assert c is not None
    261     assert i is not None
    262     assert v is not None
    263 
    264     assert c.type.kind == TypeKind.CONSTANTARRAY
    265     assert c.type.element_type.kind == TypeKind.INT
    266     assert i.type.kind == TypeKind.INCOMPLETEARRAY
    267     assert i.type.element_type.kind == TypeKind.INT
    268     assert v.type.kind == TypeKind.VARIABLEARRAY
    269     assert v.type.element_type.kind == TypeKind.INT
    270 
    271 @raises(Exception)
    272 def test_invalid_element_type():
    273     """Ensure Type.element_type raises if type doesn't have elements."""
    274     tu = get_tu('int i;')
    275     i = get_cursor(tu, 'i')
    276     assert i is not None
    277     i.element_type
    278 
    279 def test_element_count():
    280     """Ensure Type.element_count works."""
    281     tu = get_tu('int i[5]; int j;')
    282     i = get_cursor(tu, 'i')
    283     j = get_cursor(tu, 'j')
    284 
    285     assert i is not None
    286     assert j is not None
    287 
    288     assert i.type.element_count == 5
    289 
    290     try:
    291         j.type.element_count
    292         assert False
    293     except:
    294         assert True
    295 
    296 def test_is_volatile_qualified():
    297     """Ensure Type.is_volatile_qualified works."""
    298 
    299     tu = get_tu('volatile int i = 4; int j = 2;')
    300 
    301     i = get_cursor(tu, 'i')
    302     j = get_cursor(tu, 'j')
    303 
    304     assert i is not None
    305     assert j is not None
    306 
    307     assert isinstance(i.type.is_volatile_qualified(), bool)
    308     assert i.type.is_volatile_qualified()
    309     assert not j.type.is_volatile_qualified()
    310 
    311 def test_is_restrict_qualified():
    312     """Ensure Type.is_restrict_qualified works."""
    313 
    314     tu = get_tu('struct s { void * restrict i; void * j; };')
    315 
    316     i = get_cursor(tu, 'i')
    317     j = get_cursor(tu, 'j')
    318 
    319     assert i is not None
    320     assert j is not None
    321 
    322     assert isinstance(i.type.is_restrict_qualified(), bool)
    323     assert i.type.is_restrict_qualified()
    324     assert not j.type.is_restrict_qualified()
    325 
    326 def test_record_layout():
    327     """Ensure Cursor.type.get_size, Cursor.type.get_align and
    328     Cursor.type.get_offset works."""
    329 
    330     source ="""
    331 struct a {
    332     long a1;
    333     long a2:3;
    334     long a3:4;
    335     long long a4;
    336 };
    337 """
    338     tries=[(['-target','i386-linux-gnu'],(4,16,0,32,35,64)),
    339            (['-target','nvptx64-unknown-unknown'],(8,24,0,64,67,128)),
    340            (['-target','i386-pc-win32'],(8,16,0,32,35,64)),
    341            (['-target','msp430-none-none'],(2,14,0,32,35,48))]
    342     for flags, values in tries:
    343         align,total,a1,a2,a3,a4 = values
    344 
    345         tu = get_tu(source, flags=flags)
    346         teststruct = get_cursor(tu, 'a')
    347         fields = list(teststruct.get_children())
    348 
    349         assert teststruct.type.get_align() == align
    350         assert teststruct.type.get_size() == total
    351         assert teststruct.type.get_offset(fields[0].spelling) == a1
    352         assert teststruct.type.get_offset(fields[1].spelling) == a2
    353         assert teststruct.type.get_offset(fields[2].spelling) == a3
    354         assert teststruct.type.get_offset(fields[3].spelling) == a4
    355         assert fields[0].is_bitfield() == False
    356         assert fields[1].is_bitfield() == True
    357         assert fields[1].get_bitfield_width() == 3
    358         assert fields[2].is_bitfield() == True
    359         assert fields[2].get_bitfield_width() == 4
    360         assert fields[3].is_bitfield() == False
    361 
    362 def test_offset():
    363     """Ensure Cursor.get_record_field_offset works in anonymous records"""
    364     source="""
    365 struct Test {
    366   struct {int a;} typeanon;
    367   struct {
    368     int bariton;
    369     union {
    370       int foo;
    371     };
    372   };
    373   int bar;
    374 };"""
    375     tries=[(['-target','i386-linux-gnu'],(4,16,0,32,64,96)),
    376            (['-target','nvptx64-unknown-unknown'],(8,24,0,32,64,96)),
    377            (['-target','i386-pc-win32'],(8,16,0,32,64,96)),
    378            (['-target','msp430-none-none'],(2,14,0,32,64,96))]
    379     for flags, values in tries:
    380         align,total,f1,bariton,foo,bar = values
    381         tu = get_tu(source)
    382         teststruct = get_cursor(tu, 'Test')
    383         children = list(teststruct.get_children())
    384         fields = list(teststruct.type.get_fields())
    385         assert children[0].kind == CursorKind.STRUCT_DECL
    386         assert children[0].spelling != "typeanon"
    387         assert children[1].spelling == "typeanon"
    388         assert fields[0].kind == CursorKind.FIELD_DECL
    389         assert fields[1].kind == CursorKind.FIELD_DECL
    390         assert fields[1].is_anonymous()
    391         assert teststruct.type.get_offset("typeanon") == f1
    392         assert teststruct.type.get_offset("bariton") == bariton
    393         assert teststruct.type.get_offset("foo") == foo
    394         assert teststruct.type.get_offset("bar") == bar
    395 
    396 
    397 def test_decay():
    398     """Ensure decayed types are handled as the original type"""
    399 
    400     tu = get_tu("void foo(int a[]);")
    401     foo = get_cursor(tu, 'foo')
    402     a = foo.type.argument_types()[0]
    403 
    404     assert a.kind == TypeKind.INCOMPLETEARRAY
    405     assert a.element_type.kind == TypeKind.INT
    406     assert a.get_canonical().kind == TypeKind.INCOMPLETEARRAY
    407