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_type_spelling(): 136 """Ensure Type.spelling works.""" 137 tu = get_tu('int c[5]; 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 151def 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 159def 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) 183def 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) 195def 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) 204def 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) 213def 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 221def 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 233def test_function_variadic(): 234 """Ensure Type.is_function_variadic works.""" 235 236 source =""" 237#include <stdarg.h> 238 239void foo(int a, ...); 240void 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 254def test_element_type(): 255 """Ensure Type.element_type works.""" 256 tu = get_tu('int c[5]; 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) 272def 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 279def 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 296def 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 311def 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 326def test_record_layout(): 327 """Ensure Cursor.type.get_size, Cursor.type.get_align and 328 Cursor.type.get_offset works.""" 329 330 source =""" 331struct 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 362def test_offset(): 363 """Ensure Cursor.get_record_field_offset works in anonymous records""" 364 source=""" 365struct 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 397def 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