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