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