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