1import gc
2
3from clang.cindex import CursorKind
4from clang.cindex import TranslationUnit
5from clang.cindex import TypeKind
6from nose.tools import raises
7from .util import get_cursor
8from .util import get_tu
9
10kInput = """\
11
12typedef int I;
13
14struct 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
27def 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
79def 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
99constarrayInput="""
100struct teststruct {
101  void *A[2];
102};
103"""
104def 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
116def 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
135def test_typekind_spelling():
136    """Ensure TypeKind.spelling works."""
137    tu = get_tu('int a;')
138    a = get_cursor(tu, 'a')
139
140    assert a is not None
141    assert a.type.kind.spelling == 'Int'
142
143def test_function_argument_types():
144    """Ensure that Type.argument_types() works as expected."""
145    tu = get_tu('void f(int, int);')
146    f = get_cursor(tu, 'f')
147    assert f is not None
148
149    args = f.type.argument_types()
150    assert args is not None
151    assert len(args) == 2
152
153    t0 = args[0]
154    assert t0 is not None
155    assert t0.kind == TypeKind.INT
156
157    t1 = args[1]
158    assert t1 is not None
159    assert t1.kind == TypeKind.INT
160
161    args2 = list(args)
162    assert len(args2) == 2
163    assert t0 == args2[0]
164    assert t1 == args2[1]
165
166@raises(TypeError)
167def test_argument_types_string_key():
168    """Ensure that non-int keys raise a TypeError."""
169    tu = get_tu('void f(int, int);')
170    f = get_cursor(tu, 'f')
171    assert f is not None
172
173    args = f.type.argument_types()
174    assert len(args) == 2
175
176    args['foo']
177
178@raises(IndexError)
179def test_argument_types_negative_index():
180    """Ensure that negative indexes on argument_types Raises an IndexError."""
181    tu = get_tu('void f(int, int);')
182    f = get_cursor(tu, 'f')
183    args = f.type.argument_types()
184
185    args[-1]
186
187@raises(IndexError)
188def test_argument_types_overflow_index():
189    """Ensure that indexes beyond the length of Type.argument_types() raise."""
190    tu = get_tu('void f(int, int);')
191    f = get_cursor(tu, 'f')
192    args = f.type.argument_types()
193
194    args[2]
195
196@raises(Exception)
197def test_argument_types_invalid_type():
198    """Ensure that obtaining argument_types on a Type without them raises."""
199    tu = get_tu('int i;')
200    i = get_cursor(tu, 'i')
201    assert i is not None
202
203    i.type.argument_types()
204
205def test_is_pod():
206    """Ensure Type.is_pod() works."""
207    tu = get_tu('int i; void f();')
208    i = get_cursor(tu, 'i')
209    f = get_cursor(tu, 'f')
210
211    assert i is not None
212    assert f is not None
213
214    assert i.type.is_pod()
215    assert not f.type.is_pod()
216
217def test_function_variadic():
218    """Ensure Type.is_function_variadic works."""
219
220    source ="""
221#include <stdarg.h>
222
223void foo(int a, ...);
224void bar(int a, int b);
225"""
226
227    tu = get_tu(source)
228    foo = get_cursor(tu, 'foo')
229    bar = get_cursor(tu, 'bar')
230
231    assert foo is not None
232    assert bar is not None
233
234    assert isinstance(foo.type.is_function_variadic(), bool)
235    assert foo.type.is_function_variadic()
236    assert not bar.type.is_function_variadic()
237
238def test_element_type():
239    """Ensure Type.element_type works."""
240    tu = get_tu('int i[5];')
241    i = get_cursor(tu, 'i')
242    assert i is not None
243
244    assert i.type.kind == TypeKind.CONSTANTARRAY
245    assert i.type.element_type.kind == TypeKind.INT
246
247@raises(Exception)
248def test_invalid_element_type():
249    """Ensure Type.element_type raises if type doesn't have elements."""
250    tu = get_tu('int i;')
251    i = get_cursor(tu, 'i')
252    assert i is not None
253    i.element_type
254
255def test_element_count():
256    """Ensure Type.element_count works."""
257    tu = get_tu('int i[5]; int j;')
258    i = get_cursor(tu, 'i')
259    j = get_cursor(tu, 'j')
260
261    assert i is not None
262    assert j is not None
263
264    assert i.type.element_count == 5
265
266    try:
267        j.type.element_count
268        assert False
269    except:
270        assert True
271
272def test_is_volatile_qualified():
273    """Ensure Type.is_volatile_qualified works."""
274
275    tu = get_tu('volatile int i = 4; int j = 2;')
276
277    i = get_cursor(tu, 'i')
278    j = get_cursor(tu, 'j')
279
280    assert i is not None
281    assert j is not None
282
283    assert isinstance(i.type.is_volatile_qualified(), bool)
284    assert i.type.is_volatile_qualified()
285    assert not j.type.is_volatile_qualified()
286
287def test_is_restrict_qualified():
288    """Ensure Type.is_restrict_qualified works."""
289
290    tu = get_tu('struct s { void * restrict i; void * j; };')
291
292    i = get_cursor(tu, 'i')
293    j = get_cursor(tu, 'j')
294
295    assert i is not None
296    assert j is not None
297
298    assert isinstance(i.type.is_restrict_qualified(), bool)
299    assert i.type.is_restrict_qualified()
300    assert not j.type.is_restrict_qualified()
301