1#!/usr/bin/env python 2 3import pprint 4import re 5import os, sys 6import io 7import unittest 8 9sys.path[0:0] = ['.', '..'] 10 11from pycparser import c_parser 12from pycparser.c_ast import * 13from pycparser.c_parser import CParser, Coord, ParseError 14 15_c_parser = c_parser.CParser( 16 lex_optimize=False, 17 yacc_debug=True, 18 yacc_optimize=False, 19 yacctab='yacctab') 20 21 22def expand_decl(decl): 23 """ Converts the declaration into a nested list. 24 """ 25 typ = type(decl) 26 27 if typ == TypeDecl: 28 return ['TypeDecl', expand_decl(decl.type)] 29 elif typ == IdentifierType: 30 return ['IdentifierType', decl.names] 31 elif typ == ID: 32 return ['ID', decl.name] 33 elif typ in [Struct, Union]: 34 decls = [expand_decl(d) for d in decl.decls or []] 35 return [typ.__name__, decl.name, decls] 36 else: 37 nested = expand_decl(decl.type) 38 39 if typ == Decl: 40 if decl.quals: 41 return ['Decl', decl.quals, decl.name, nested] 42 else: 43 return ['Decl', decl.name, nested] 44 elif typ == Typename: # for function parameters 45 if decl.quals: 46 return ['Typename', decl.quals, nested] 47 else: 48 return ['Typename', nested] 49 elif typ == ArrayDecl: 50 dimval = decl.dim.value if decl.dim else '' 51 return ['ArrayDecl', dimval, decl.dim_quals, nested] 52 elif typ == PtrDecl: 53 if decl.quals: 54 return ['PtrDecl', decl.quals, nested] 55 else: 56 return ['PtrDecl', nested] 57 elif typ == Typedef: 58 return ['Typedef', decl.name, nested] 59 elif typ == FuncDecl: 60 if decl.args: 61 params = [expand_decl(param) for param in decl.args.params] 62 else: 63 params = [] 64 return ['FuncDecl', params, nested] 65 66 67def expand_init(init): 68 """ Converts an initialization into a nested list 69 """ 70 typ = type(init) 71 72 if typ == NamedInitializer: 73 des = [expand_init(dp) for dp in init.name] 74 return (des, expand_init(init.expr)) 75 elif typ in (InitList, ExprList): 76 return [expand_init(expr) for expr in init.exprs] 77 elif typ == Constant: 78 return ['Constant', init.type, init.value] 79 elif typ == ID: 80 return ['ID', init.name] 81 elif typ == UnaryOp: 82 return ['UnaryOp', init.op, expand_decl(init.expr)] 83 84 85class TestCParser_base(unittest.TestCase): 86 def parse(self, txt, filename=''): 87 return self.cparser.parse(txt, filename) 88 89 def setUp(self): 90 self.cparser = _c_parser 91 92 def assert_coord(self, node, line, column=None, file=None): 93 self.assertEqual(node.coord.line, line) 94 if column is not None: 95 self.assertEqual(node.coord.column, column) 96 if file: 97 self.assertEqual(node.coord.file, file) 98 99 100 101class TestCParser_fundamentals(TestCParser_base): 102 def get_decl(self, txt, index=0): 103 """ Given a source and an index returns the expanded 104 declaration at that index. 105 106 FileAST holds a list of 'external declarations'. 107 index is the offset of the desired declaration in that 108 list. 109 """ 110 t = self.parse(txt).ext[index] 111 return expand_decl(t) 112 113 def get_decl_init(self, txt, index=0): 114 """ Returns the expanded initializer of the declaration 115 at index. 116 """ 117 t = self.parse(txt).ext[index] 118 return expand_init(t.init) 119 120 def test_FileAST(self): 121 t = self.parse('int a; char c;') 122 self.assertIsInstance(t, FileAST) 123 self.assertEqual(len(t.ext), 2) 124 125 # empty file 126 t2 = self.parse('') 127 self.assertIsInstance(t2, FileAST) 128 self.assertEqual(len(t2.ext), 0) 129 130 def test_empty_toplevel_decl(self): 131 code = 'int foo;;' 132 t = self.parse(code) 133 self.assertIsInstance(t, FileAST) 134 self.assertEqual(len(t.ext), 1) 135 self.assertEqual(self.get_decl(code), 136 ['Decl', 'foo', 137 ['TypeDecl', ['IdentifierType', ['int']]]]) 138 139 def test_coords(self): 140 """ Tests the "coordinates" of parsed elements - file 141 name, line and column numbers, with modification 142 insterted by #line directives. 143 """ 144 self.assert_coord(self.parse('int a;').ext[0], 1, 5) 145 146 t1 = """ 147 int a; 148 int b;\n\n 149 int c; 150 """ 151 f1 = self.parse(t1, filename='test.c') 152 self.assert_coord(f1.ext[0], 2, 13, 'test.c') 153 self.assert_coord(f1.ext[1], 3, 13, 'test.c') 154 self.assert_coord(f1.ext[2], 6, 13, 'test.c') 155 156 t1_1 = ''' 157 int main() { 158 k = p; 159 printf("%d", b); 160 return 0; 161 }''' 162 f1_1 = self.parse(t1_1, filename='test.c') 163 self.assert_coord(f1_1.ext[0].body.block_items[0], 3, 13, 'test.c') 164 self.assert_coord(f1_1.ext[0].body.block_items[1], 4, 13, 'test.c') 165 166 t1_2 = ''' 167 int main () { 168 int p = (int) k; 169 }''' 170 f1_2 = self.parse(t1_2, filename='test.c') 171 # make sure that the Cast has a coord (issue 23) 172 self.assert_coord(f1_2.ext[0].body.block_items[0].init, 3, 21, file='test.c') 173 174 t2 = """ 175 #line 99 176 int c; 177 """ 178 self.assert_coord(self.parse(t2).ext[0], 99, 13) 179 180 t3 = """ 181 int dsf; 182 char p; 183 #line 3000 "in.h" 184 char d; 185 """ 186 f3 = self.parse(t3, filename='test.c') 187 self.assert_coord(f3.ext[0], 2, 13, 'test.c') 188 self.assert_coord(f3.ext[1], 3, 14, 'test.c') 189 self.assert_coord(f3.ext[2], 3000, 14, 'in.h') 190 191 t4 = """ 192 #line 20 "restore.h" 193 int maydler(char); 194 195 #line 30 "includes/daween.ph" 196 long j, k; 197 198 #line 50000 199 char* ro; 200 """ 201 f4 = self.parse(t4, filename='myb.c') 202 self.assert_coord(f4.ext[0], 20, 13, 'restore.h') 203 self.assert_coord(f4.ext[1], 30, 14, 'includes/daween.ph') 204 self.assert_coord(f4.ext[2], 30, 17, 'includes/daween.ph') 205 self.assert_coord(f4.ext[3], 50000, 13, 'includes/daween.ph') 206 207 t5 = """ 208 int 209 #line 99 210 c; 211 """ 212 self.assert_coord(self.parse(t5).ext[0], 99, 9) 213 214 # coord for ellipsis 215 t6 = """ 216 int foo(int j, 217 ...) { 218 }""" 219 f6 = self.parse(t6, filename='z.c') 220 self.assert_coord(self.parse(t6).ext[0].decl.type.args.params[1], 3, 17) 221 222 def test_forloop_coord(self): 223 t = '''\ 224 void foo() { 225 for(int z=0; z<4; 226 z++){} 227 } 228 ''' 229 s = self.parse(t, filename='f.c') 230 forloop = s.ext[0].body.block_items[0] 231 self.assert_coord(forloop.init, 2, 13, 'f.c') 232 self.assert_coord(forloop.cond, 2, 26, 'f.c') 233 self.assert_coord(forloop.next, 3, 17, 'f.c') 234 235 def test_simple_decls(self): 236 self.assertEqual(self.get_decl('int a;'), 237 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]]) 238 239 self.assertEqual(self.get_decl('unsigned int a;'), 240 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['unsigned', 'int']]]]) 241 242 self.assertEqual(self.get_decl('_Bool a;'), 243 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['_Bool']]]]) 244 245 self.assertEqual(self.get_decl('float _Complex fcc;'), 246 ['Decl', 'fcc', ['TypeDecl', ['IdentifierType', ['float', '_Complex']]]]) 247 248 self.assertEqual(self.get_decl('char* string;'), 249 ['Decl', 'string', 250 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]) 251 252 self.assertEqual(self.get_decl('long ar[15];'), 253 ['Decl', 'ar', 254 ['ArrayDecl', '15', [], 255 ['TypeDecl', ['IdentifierType', ['long']]]]]) 256 257 self.assertEqual(self.get_decl('long long ar[15];'), 258 ['Decl', 'ar', 259 ['ArrayDecl', '15', [], 260 ['TypeDecl', ['IdentifierType', ['long', 'long']]]]]) 261 262 self.assertEqual(self.get_decl('unsigned ar[];'), 263 ['Decl', 'ar', 264 ['ArrayDecl', '', [], 265 ['TypeDecl', ['IdentifierType', ['unsigned']]]]]) 266 267 self.assertEqual(self.get_decl('int strlen(char* s);'), 268 ['Decl', 'strlen', 269 ['FuncDecl', 270 [['Decl', 's', 271 ['PtrDecl', 272 ['TypeDecl', ['IdentifierType', ['char']]]]]], 273 ['TypeDecl', ['IdentifierType', ['int']]]]]) 274 275 self.assertEqual(self.get_decl('int strcmp(char* s1, char* s2);'), 276 ['Decl', 'strcmp', 277 ['FuncDecl', 278 [ ['Decl', 's1', 279 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]], 280 ['Decl', 's2', 281 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]] 282 ], 283 ['TypeDecl', ['IdentifierType', ['int']]]]]) 284 285 # function return values and parameters may not have type information 286 self.assertEqual(self.get_decl('extern foobar(foo, bar);'), 287 ['Decl', 'foobar', 288 ['FuncDecl', 289 [ ['ID', 'foo'], 290 ['ID', 'bar'] 291 ], 292 ['TypeDecl', ['IdentifierType', ['int']]]]]) 293 294 def test_int128(self): 295 self.assertEqual(self.get_decl('__int128 a;'), 296 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['__int128']]]]) 297 298 299 def test_nested_decls(self): # the fun begins 300 self.assertEqual(self.get_decl('char** ar2D;'), 301 ['Decl', 'ar2D', 302 ['PtrDecl', ['PtrDecl', 303 ['TypeDecl', ['IdentifierType', ['char']]]]]]) 304 305 self.assertEqual(self.get_decl('int (*a)[1][2];'), 306 ['Decl', 'a', 307 ['PtrDecl', 308 ['ArrayDecl', '1', [], 309 ['ArrayDecl', '2', [], 310 ['TypeDecl', ['IdentifierType', ['int']]]]]]]) 311 312 self.assertEqual(self.get_decl('int *a[1][2];'), 313 ['Decl', 'a', 314 ['ArrayDecl', '1', [], 315 ['ArrayDecl', '2', [], 316 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['int']]]]]]]) 317 318 self.assertEqual(self.get_decl('char* const* p;'), 319 ['Decl', 'p', 320 ['PtrDecl', ['PtrDecl', ['const'], 321 ['TypeDecl', ['IdentifierType', ['char']]]]]]) 322 323 self.assertEqual(self.get_decl('char* * const p;'), 324 ['Decl', 'p', 325 ['PtrDecl', ['const'], ['PtrDecl', 326 ['TypeDecl', ['IdentifierType', ['char']]]]]]) 327 328 self.assertEqual(self.get_decl('char ***ar3D[40];'), 329 ['Decl', 'ar3D', 330 ['ArrayDecl', '40', [], 331 ['PtrDecl', ['PtrDecl', ['PtrDecl', 332 ['TypeDecl', ['IdentifierType', ['char']]]]]]]]) 333 334 self.assertEqual(self.get_decl('char (***ar3D)[40];'), 335 ['Decl', 'ar3D', 336 ['PtrDecl', ['PtrDecl', ['PtrDecl', 337 ['ArrayDecl', '40', [], ['TypeDecl', ['IdentifierType', ['char']]]]]]]]) 338 339 self.assertEqual(self.get_decl('int (*x[4])(char, int);'), 340 ['Decl', 'x', 341 ['ArrayDecl', '4', [], 342 ['PtrDecl', 343 ['FuncDecl', 344 [ ['Typename', ['TypeDecl', ['IdentifierType', ['char']]]], 345 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]], 346 ['TypeDecl', ['IdentifierType', ['int']]]]]]]) 347 348 self.assertEqual(self.get_decl('char *(*(**foo [][8])())[];'), 349 ['Decl', 'foo', 350 ['ArrayDecl', '', [], 351 ['ArrayDecl', '8', [], 352 ['PtrDecl', ['PtrDecl', 353 ['FuncDecl', 354 [], 355 ['PtrDecl', 356 ['ArrayDecl', '', [], 357 ['PtrDecl', 358 ['TypeDecl', 359 ['IdentifierType', ['char']]]]]]]]]]]]) 360 361 # explore named and unnamed function pointer parameters, 362 # with and without qualifiers 363 364 # unnamed w/o quals 365 self.assertEqual(self.get_decl('int (*k)(int);'), 366 ['Decl', 'k', 367 ['PtrDecl', 368 ['FuncDecl', 369 [['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]], 370 ['TypeDecl', ['IdentifierType', ['int']]]]]]) 371 372 # unnamed w/ quals 373 self.assertEqual(self.get_decl('int (*k)(const int);'), 374 ['Decl', 'k', 375 ['PtrDecl', 376 ['FuncDecl', 377 [['Typename', ['const'], ['TypeDecl', ['IdentifierType', ['int']]]]], 378 ['TypeDecl', ['IdentifierType', ['int']]]]]]) 379 380 # named w/o quals 381 self.assertEqual(self.get_decl('int (*k)(int q);'), 382 ['Decl', 'k', 383 ['PtrDecl', 384 ['FuncDecl', 385 [['Decl', 'q', ['TypeDecl', ['IdentifierType', ['int']]]]], 386 ['TypeDecl', ['IdentifierType', ['int']]]]]]) 387 388 # named w/ quals 389 self.assertEqual(self.get_decl('int (*k)(const volatile int q);'), 390 ['Decl', 'k', 391 ['PtrDecl', 392 ['FuncDecl', 393 [['Decl', ['const', 'volatile'], 'q', 394 ['TypeDecl', ['IdentifierType', ['int']]]]], 395 ['TypeDecl', ['IdentifierType', ['int']]]]]]) 396 397 self.assertEqual(self.get_decl('int (*k)(const volatile int* q);'), 398 ['Decl', 'k', 399 ['PtrDecl', 400 ['FuncDecl', 401 [['Decl', ['const', 'volatile'], 'q', 402 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['int']]]]]], 403 ['TypeDecl', ['IdentifierType', ['int']]]]]]) 404 405 # restrict qualifier 406 self.assertEqual(self.get_decl('int (*k)(restrict int* q);'), 407 ['Decl', 'k', 408 ['PtrDecl', 409 ['FuncDecl', 410 [['Decl', ['restrict'], 'q', 411 ['PtrDecl', 412 ['TypeDecl', ['IdentifierType', ['int']]]]]], 413 ['TypeDecl', ['IdentifierType', ['int']]]]]]) 414 415 def test_func_decls_with_array_dim_qualifiers(self): 416 self.assertEqual(self.get_decl('int zz(int p[static 10]);'), 417 ['Decl', 'zz', 418 ['FuncDecl', 419 [['Decl', 'p', ['ArrayDecl', '10', ['static'], 420 ['TypeDecl', ['IdentifierType', ['int']]]]]], 421 ['TypeDecl', ['IdentifierType', ['int']]]]]) 422 423 self.assertEqual(self.get_decl('int zz(int p[const 10]);'), 424 ['Decl', 'zz', 425 ['FuncDecl', 426 [['Decl', 'p', ['ArrayDecl', '10', ['const'], 427 ['TypeDecl', ['IdentifierType', ['int']]]]]], 428 ['TypeDecl', ['IdentifierType', ['int']]]]]) 429 430 self.assertEqual(self.get_decl('int zz(int p[restrict][5]);'), 431 ['Decl', 'zz', 432 ['FuncDecl', 433 [['Decl', 'p', ['ArrayDecl', '', ['restrict'], 434 ['ArrayDecl', '5', [], 435 ['TypeDecl', ['IdentifierType', ['int']]]]]]], 436 ['TypeDecl', ['IdentifierType', ['int']]]]]) 437 438 self.assertEqual(self.get_decl('int zz(int p[const restrict static 10][5]);'), 439 ['Decl', 'zz', 440 ['FuncDecl', 441 [['Decl', 'p', ['ArrayDecl', '10', ['const', 'restrict', 'static'], 442 ['ArrayDecl', '5', [], 443 ['TypeDecl', ['IdentifierType', ['int']]]]]]], 444 ['TypeDecl', ['IdentifierType', ['int']]]]]) 445 446 def test_qualifiers_storage_specifiers(self): 447 def assert_qs(txt, index, quals, storage): 448 d = self.parse(txt).ext[index] 449 self.assertEqual(d.quals, quals) 450 self.assertEqual(d.storage, storage) 451 452 assert_qs("extern int p;", 0, [], ['extern']) 453 assert_qs("const long p = 6;", 0, ['const'], []) 454 455 d1 = "static const int p, q, r;" 456 for i in range(3): 457 assert_qs(d1, i, ['const'], ['static']) 458 459 d2 = "static char * const p;" 460 assert_qs(d2, 0, [], ['static']) 461 pdecl = self.parse(d2).ext[0].type 462 self.assertIsInstance(pdecl, PtrDecl) 463 self.assertEqual(pdecl.quals, ['const']) 464 465 def test_sizeof(self): 466 e = """ 467 void foo() 468 { 469 int a = sizeof k; 470 int b = sizeof(int); 471 int c = sizeof(int**);; 472 473 char* p = "just to make sure this parses w/o error..."; 474 int d = sizeof(int()); 475 } 476 """ 477 compound = self.parse(e).ext[0].body 478 479 s1 = compound.block_items[0].init 480 self.assertIsInstance(s1, UnaryOp) 481 self.assertEqual(s1.op, 'sizeof') 482 self.assertIsInstance(s1.expr, ID) 483 self.assertEqual(s1.expr.name, 'k') 484 485 s2 = compound.block_items[1].init 486 self.assertEqual(expand_decl(s2.expr), 487 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]) 488 489 s3 = compound.block_items[2].init 490 self.assertEqual(expand_decl(s3.expr), 491 ['Typename', 492 ['PtrDecl', 493 ['PtrDecl', 494 ['TypeDecl', 495 ['IdentifierType', ['int']]]]]]) 496 497 def test_offsetof(self): 498 e = """ 499 void foo() { 500 int a = offsetof(struct S, p); 501 a.b = offsetof(struct sockaddr, sp) + strlen(bar); 502 int a = offsetof(struct S, p.q.r); 503 int a = offsetof(struct S, p[5].q[4][5]); 504 } 505 """ 506 compound = self.parse(e).ext[0].body 507 s1 = compound.block_items[0].init 508 self.assertIsInstance(s1, FuncCall) 509 self.assertIsInstance(s1.name, ID) 510 self.assertEqual(s1.name.name, 'offsetof') 511 self.assertIsInstance(s1.args.exprs[0], Typename) 512 self.assertIsInstance(s1.args.exprs[1], ID) 513 s3 = compound.block_items[2].init 514 self.assertIsInstance(s3.args.exprs[1], StructRef) 515 s4 = compound.block_items[3].init 516 self.assertIsInstance(s4.args.exprs[1], ArrayRef) 517 518 def test_compound_statement(self): 519 e = """ 520 void foo() { 521 } 522 """ 523 compound = self.parse(e).ext[0].body 524 self.assertIsInstance(compound, Compound) 525 self.assert_coord(compound, 2) 526 527 # The C99 compound literal feature 528 # 529 def test_compound_literals(self): 530 ps1 = self.parse(r''' 531 void foo() { 532 p = (long long){k}; 533 tc = (struct jk){.a = {1, 2}, .b[0] = t}; 534 }''') 535 536 compound = ps1.ext[0].body.block_items[0].rvalue 537 self.assertEqual(expand_decl(compound.type), 538 ['Typename', ['TypeDecl', ['IdentifierType', ['long', 'long']]]]) 539 self.assertEqual(expand_init(compound.init), 540 [['ID', 'k']]) 541 542 compound = ps1.ext[0].body.block_items[1].rvalue 543 self.assertEqual(expand_decl(compound.type), 544 ['Typename', ['TypeDecl', ['Struct', 'jk', []]]]) 545 self.assertEqual(expand_init(compound.init), 546 [ 547 ([['ID', 'a']], [['Constant', 'int', '1'], ['Constant', 'int', '2']]), 548 ([['ID', 'b'], ['Constant', 'int', '0']], ['ID', 't'])]) 549 550 def test_enums(self): 551 e1 = "enum mycolor op;" 552 e1_type = self.parse(e1).ext[0].type.type 553 554 self.assertIsInstance(e1_type, Enum) 555 self.assertEqual(e1_type.name, 'mycolor') 556 self.assertEqual(e1_type.values, None) 557 558 e2 = "enum mysize {large=20, small, medium} shoes;" 559 e2_type = self.parse(e2).ext[0].type.type 560 561 self.assertIsInstance(e2_type, Enum) 562 self.assertEqual(e2_type.name, 'mysize') 563 564 e2_elist = e2_type.values 565 self.assertIsInstance(e2_elist, EnumeratorList) 566 567 for e2_eval in e2_elist.enumerators: 568 self.assertIsInstance(e2_eval, Enumerator) 569 570 self.assertEqual(e2_elist.enumerators[0].name, 'large') 571 self.assertEqual(e2_elist.enumerators[0].value.value, '20') 572 self.assertEqual(e2_elist.enumerators[2].name, 'medium') 573 self.assertEqual(e2_elist.enumerators[2].value, None) 574 575 # enum with trailing comma (C99 feature) 576 e3 = """ 577 enum 578 { 579 red, 580 blue, 581 green, 582 } color; 583 """ 584 585 e3_type = self.parse(e3).ext[0].type.type 586 self.assertIsInstance(e3_type, Enum) 587 e3_elist = e3_type.values 588 self.assertIsInstance(e3_elist, EnumeratorList) 589 590 for e3_eval in e3_elist.enumerators: 591 self.assertIsInstance(e3_eval, Enumerator) 592 593 self.assertEqual(e3_elist.enumerators[0].name, 'red') 594 self.assertEqual(e3_elist.enumerators[0].value, None) 595 self.assertEqual(e3_elist.enumerators[1].name, 'blue') 596 self.assertEqual(e3_elist.enumerators[2].name, 'green') 597 598 def test_typedef(self): 599 # without typedef, error 600 s1 = """ 601 node k; 602 """ 603 self.assertRaises(ParseError, self.parse, s1) 604 605 # now with typedef, works 606 s2 = """ 607 typedef void* node; 608 node k; 609 """ 610 ps2 = self.parse(s2) 611 self.assertEqual(expand_decl(ps2.ext[0]), 612 ['Typedef', 'node', 613 ['PtrDecl', 614 ['TypeDecl', ['IdentifierType', ['void']]]]]) 615 616 self.assertEqual(expand_decl(ps2.ext[1]), 617 ['Decl', 'k', 618 ['TypeDecl', ['IdentifierType', ['node']]]]) 619 620 s3 = """ 621 typedef int T; 622 typedef T *pT; 623 624 pT aa, bb; 625 """ 626 ps3 = self.parse(s3) 627 self.assertEqual(expand_decl(ps3.ext[3]), 628 ['Decl', 'bb', 629 ['TypeDecl', ['IdentifierType', ['pT']]]]) 630 631 s4 = ''' 632 typedef char* __builtin_va_list; 633 typedef __builtin_va_list __gnuc_va_list; 634 ''' 635 ps4 = self.parse(s4) 636 self.assertEqual(expand_decl(ps4.ext[1]), 637 ['Typedef', '__gnuc_va_list', 638 ['TypeDecl', 639 ['IdentifierType', ['__builtin_va_list']]]]) 640 641 s5 = '''typedef struct tagHash Hash;''' 642 ps5 = self.parse(s5) 643 self.assertEqual(expand_decl(ps5.ext[0]), 644 ['Typedef', 'Hash', ['TypeDecl', ['Struct', 'tagHash', []]]]) 645 646 def test_struct_union(self): 647 s1 = """ 648 struct { 649 int id; 650 char* name; 651 } joe; 652 """ 653 654 self.assertEqual(expand_decl(self.parse(s1).ext[0]), 655 ['Decl', 'joe', 656 ['TypeDecl', ['Struct', None, 657 [ ['Decl', 'id', 658 ['TypeDecl', 659 ['IdentifierType', ['int']]]], 660 ['Decl', 'name', 661 ['PtrDecl', 662 ['TypeDecl', 663 ['IdentifierType', ['char']]]]]]]]]) 664 665 s2 = """ 666 struct node p; 667 """ 668 self.assertEqual(expand_decl(self.parse(s2).ext[0]), 669 ['Decl', 'p', 670 ['TypeDecl', ['Struct', 'node', []]]]) 671 672 s21 = """ 673 union pri ra; 674 """ 675 self.assertEqual(expand_decl(self.parse(s21).ext[0]), 676 ['Decl', 'ra', 677 ['TypeDecl', ['Union', 'pri', []]]]) 678 679 s3 = """ 680 struct node* p; 681 """ 682 self.assertEqual(expand_decl(self.parse(s3).ext[0]), 683 ['Decl', 'p', 684 ['PtrDecl', 685 ['TypeDecl', ['Struct', 'node', []]]]]) 686 687 s4 = """ 688 struct node; 689 """ 690 self.assertEqual(expand_decl(self.parse(s4).ext[0]), 691 ['Decl', None, 692 ['Struct', 'node', []]]) 693 694 s5 = """ 695 union 696 { 697 struct 698 { 699 int type; 700 } n; 701 702 struct 703 { 704 int type; 705 int intnode; 706 } ni; 707 } u; 708 """ 709 self.assertEqual(expand_decl(self.parse(s5).ext[0]), 710 ['Decl', 'u', 711 ['TypeDecl', 712 ['Union', None, 713 [['Decl', 'n', 714 ['TypeDecl', 715 ['Struct', None, 716 [['Decl', 'type', 717 ['TypeDecl', ['IdentifierType', ['int']]]]]]]], 718 ['Decl', 'ni', 719 ['TypeDecl', 720 ['Struct', None, 721 [['Decl', 'type', 722 ['TypeDecl', ['IdentifierType', ['int']]]], 723 ['Decl', 'intnode', 724 ['TypeDecl', ['IdentifierType', ['int']]]]]]]]]]]]) 725 726 s6 = """ 727 typedef struct foo_tag 728 { 729 void* data; 730 } foo, *pfoo; 731 """ 732 s6_ast = self.parse(s6) 733 734 self.assertEqual(expand_decl(s6_ast.ext[0]), 735 ['Typedef', 'foo', 736 ['TypeDecl', 737 ['Struct', 'foo_tag', 738 [['Decl', 'data', 739 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]]) 740 741 self.assertEqual(expand_decl(s6_ast.ext[1]), 742 ['Typedef', 'pfoo', 743 ['PtrDecl', 744 ['TypeDecl', 745 ['Struct', 'foo_tag', 746 [['Decl', 'data', 747 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]]]) 748 749 s7 = r""" 750 struct _on_exit_args { 751 void * _fnargs[32]; 752 void * _dso_handle[32]; 753 754 long _fntypes; 755 #line 77 "D:\eli\cpp_stuff\libc_include/sys/reent.h" 756 757 long _is_cxa; 758 }; 759 """ 760 761 s7_ast = self.parse(s7, filename='test.c') 762 self.assert_coord(s7_ast.ext[0].type.decls[2], 6, 22, 'test.c') 763 self.assert_coord(s7_ast.ext[0].type.decls[3], 78, 22, 764 r'D:\eli\cpp_stuff\libc_include/sys/reent.h') 765 766 s8 = """ 767 typedef enum tagReturnCode {SUCCESS, FAIL} ReturnCode; 768 769 typedef struct tagEntry 770 { 771 char* key; 772 char* value; 773 } Entry; 774 775 776 typedef struct tagNode 777 { 778 Entry* entry; 779 780 struct tagNode* next; 781 } Node; 782 783 typedef struct tagHash 784 { 785 unsigned int table_size; 786 787 Node** heads; 788 789 } Hash; 790 """ 791 s8_ast = self.parse(s8) 792 self.assertEqual(expand_decl(s8_ast.ext[3]), 793 ['Typedef', 'Hash', 794 ['TypeDecl', ['Struct', 'tagHash', 795 [['Decl', 'table_size', 796 ['TypeDecl', ['IdentifierType', ['unsigned', 'int']]]], 797 ['Decl', 'heads', 798 ['PtrDecl', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['Node']]]]]]]]]]) 799 800 def test_struct_with_extra_semis_inside(self): 801 s1 = """ 802 struct { 803 int a;; 804 } foo; 805 """ 806 s1_ast = self.parse(s1) 807 self.assertEqual(expand_decl(s1_ast.ext[0]), 808 ['Decl', 'foo', 809 ['TypeDecl', ['Struct', None, 810 [['Decl', 'a', 811 ['TypeDecl', ['IdentifierType', ['int']]]]]]]]) 812 813 s2 = """ 814 struct { 815 int a;;;; 816 float b, c; 817 ;; 818 char d; 819 } foo; 820 """ 821 s2_ast = self.parse(s2) 822 self.assertEqual(expand_decl(s2_ast.ext[0]), 823 ['Decl', 'foo', 824 ['TypeDecl', ['Struct', None, 825 [['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]], 826 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['float']]]], 827 ['Decl', 'c', ['TypeDecl', ['IdentifierType', ['float']]]], 828 ['Decl', 'd', 829 ['TypeDecl', ['IdentifierType', ['char']]]]]]]]) 830 831 def test_anonymous_struct_union(self): 832 s1 = """ 833 union 834 { 835 union 836 { 837 int i; 838 long l; 839 }; 840 841 struct 842 { 843 int type; 844 int intnode; 845 }; 846 } u; 847 """ 848 849 self.assertEqual(expand_decl(self.parse(s1).ext[0]), 850 ['Decl', 'u', 851 ['TypeDecl', 852 ['Union', None, 853 [['Decl', None, 854 ['Union', None, 855 [['Decl', 'i', 856 ['TypeDecl', 857 ['IdentifierType', ['int']]]], 858 ['Decl', 'l', 859 ['TypeDecl', 860 ['IdentifierType', ['long']]]]]]], 861 ['Decl', None, 862 ['Struct', None, 863 [['Decl', 'type', 864 ['TypeDecl', 865 ['IdentifierType', ['int']]]], 866 ['Decl', 'intnode', 867 ['TypeDecl', 868 ['IdentifierType', ['int']]]]]]]]]]]) 869 870 s2 = """ 871 struct 872 { 873 int i; 874 union 875 { 876 int id; 877 char* name; 878 }; 879 float f; 880 } joe; 881 """ 882 883 self.assertEqual(expand_decl(self.parse(s2).ext[0]), 884 ['Decl', 'joe', 885 ['TypeDecl', 886 ['Struct', None, 887 [['Decl', 'i', 888 ['TypeDecl', 889 ['IdentifierType', ['int']]]], 890 ['Decl', None, 891 ['Union', None, 892 [['Decl', 'id', 893 ['TypeDecl', 894 ['IdentifierType', ['int']]]], 895 ['Decl', 'name', 896 ['PtrDecl', 897 ['TypeDecl', 898 ['IdentifierType', ['char']]]]]]]], 899 ['Decl', 'f', 900 ['TypeDecl', 901 ['IdentifierType', ['float']]]]]]]]) 902 903 # ISO/IEC 9899:201x Commitee Draft 2010-11-16, N1539 904 # section 6.7.2.1, par. 19, example 1 905 s3 = """ 906 struct v { 907 union { 908 struct { int i, j; }; 909 struct { long k, l; } w; 910 }; 911 int m; 912 } v1; 913 """ 914 915 self.assertEqual(expand_decl(self.parse(s3).ext[0]), 916 ['Decl', 'v1', 917 ['TypeDecl', 918 ['Struct', 'v', 919 [['Decl', None, 920 ['Union', None, 921 [['Decl', None, 922 ['Struct', None, 923 [['Decl', 'i', 924 ['TypeDecl', 925 ['IdentifierType', ['int']]]], 926 ['Decl', 'j', 927 ['TypeDecl', 928 ['IdentifierType', ['int']]]]]]], 929 ['Decl', 'w', 930 ['TypeDecl', 931 ['Struct', None, 932 [['Decl', 'k', 933 ['TypeDecl', 934 ['IdentifierType', ['long']]]], 935 ['Decl', 'l', 936 ['TypeDecl', 937 ['IdentifierType', ['long']]]]]]]]]]], 938 ['Decl', 'm', 939 ['TypeDecl', 940 ['IdentifierType', ['int']]]]]]]]) 941 942 s4 = """ 943 struct v { 944 int i; 945 float; 946 } v2;""" 947 # just make sure this doesn't raise ParseError 948 self.parse(s4) 949 950 def test_struct_members_namespace(self): 951 """ Tests that structure/union member names reside in a separate 952 namespace and can be named after existing types. 953 """ 954 s1 = """ 955 typedef int Name; 956 typedef Name NameArray[10]; 957 958 struct { 959 Name Name; 960 Name NameArray[3]; 961 } sye; 962 963 void main(void) 964 { 965 sye.Name = 1; 966 } 967 """ 968 969 s1_ast = self.parse(s1) 970 self.assertEqual(expand_decl(s1_ast.ext[2]), 971 ['Decl', 'sye', 972 ['TypeDecl', ['Struct', None, 973 [ ['Decl', 'Name', 974 ['TypeDecl', 975 ['IdentifierType', ['Name']]]], 976 ['Decl', 'NameArray', 977 ['ArrayDecl', '3', [], 978 ['TypeDecl', ['IdentifierType', ['Name']]]]]]]]]) 979 self.assertEqual(s1_ast.ext[3].body.block_items[0].lvalue.field.name, 'Name') 980 981 def test_struct_bitfields(self): 982 # a struct with two bitfields, one unnamed 983 s1 = """ 984 struct { 985 int k:6; 986 int :2; 987 } joe; 988 """ 989 990 parsed_struct = self.parse(s1).ext[0] 991 992 # We can see here the name of the decl for the unnamed bitfield is 993 # None, but expand_decl doesn't show bitfield widths 994 # ... 995 self.assertEqual(expand_decl(parsed_struct), 996 ['Decl', 'joe', 997 ['TypeDecl', ['Struct', None, 998 [ ['Decl', 'k', 999 ['TypeDecl', 1000 ['IdentifierType', ['int']]]], 1001 ['Decl', None, 1002 ['TypeDecl', 1003 ['IdentifierType', ['int']]]]]]]]) 1004 1005 # ... 1006 # so we test them manually 1007 self.assertEqual(parsed_struct.type.type.decls[0].bitsize.value, '6') 1008 self.assertEqual(parsed_struct.type.type.decls[1].bitsize.value, '2') 1009 1010 def test_struct_empty(self): 1011 """ 1012 Tests that parsing an empty struct works. 1013 1014 Empty structs do NOT follow C99 (See 6.2.5-20 of the C99 standard). 1015 This is nevertheless supported by some compilers (clang, gcc), 1016 especially when using FORTIFY code. 1017 Some compilers (visual) will fail to compile with an error. 1018 """ 1019 # an empty struct. This is NOT C99 compliant 1020 s1 = """ 1021 struct foo { }; 1022 """ 1023 1024 parsed_struct = self.parse(s1).ext[0] 1025 self.assertEqual(expand_decl(parsed_struct), 1026 ['Decl', None, ['Struct', 'foo', []]]) 1027 1028 s2 = """struct { } foo;""" 1029 parsed_struct = self.parse(s2).ext[0] 1030 self.assertEqual(expand_decl(parsed_struct), 1031 ['Decl', 'foo', ['TypeDecl', ['Struct', None, []]]]) 1032 1033 s3 = """union { } foo;""" 1034 parsed_struct = self.parse(s3).ext[0] 1035 self.assertEqual(expand_decl(parsed_struct), 1036 ['Decl', 'foo', ['TypeDecl', ['Union', None, []]]]) 1037 1038 def test_tags_namespace(self): 1039 """ Tests that the tags of structs/unions/enums reside in a separate namespace and 1040 can be named after existing types. 1041 """ 1042 s1 = """ 1043 typedef int tagEntry; 1044 1045 struct tagEntry 1046 { 1047 char* key; 1048 char* value; 1049 } Entry; 1050 """ 1051 1052 s1_ast = self.parse(s1) 1053 self.assertEqual(expand_decl(s1_ast.ext[1]), 1054 ['Decl', 'Entry', 1055 ['TypeDecl', ['Struct', 'tagEntry', 1056 [['Decl', 'key', 1057 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]], 1058 ['Decl', 'value', 1059 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]]) 1060 1061 s2 = """ 1062 struct tagEntry; 1063 1064 typedef struct tagEntry tagEntry; 1065 1066 struct tagEntry 1067 { 1068 char* key; 1069 char* value; 1070 } Entry; 1071 """ 1072 1073 s2_ast = self.parse(s2) 1074 self.assertEqual(expand_decl(s2_ast.ext[2]), 1075 ['Decl', 'Entry', 1076 ['TypeDecl', ['Struct', 'tagEntry', 1077 [['Decl', 'key', 1078 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]], 1079 ['Decl', 'value', 1080 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]]) 1081 1082 s3 = """ 1083 typedef int mytag; 1084 1085 enum mytag {ABC, CDE}; 1086 enum mytag joe; 1087 """ 1088 1089 s3_type = self.parse(s3).ext[1].type 1090 1091 self.assertIsInstance(s3_type, Enum) 1092 self.assertEqual(s3_type.name, 'mytag') 1093 1094 def test_multi_decls(self): 1095 d1 = 'int a, b;' 1096 1097 self.assertEqual(self.get_decl(d1, 0), 1098 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]]) 1099 self.assertEqual(self.get_decl(d1, 1), 1100 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['int']]]]) 1101 1102 d2 = 'char* p, notp, ar[4];' 1103 self.assertEqual(self.get_decl(d2, 0), 1104 ['Decl', 'p', 1105 ['PtrDecl', 1106 ['TypeDecl', ['IdentifierType', ['char']]]]]) 1107 self.assertEqual(self.get_decl(d2, 1), 1108 ['Decl', 'notp', ['TypeDecl', ['IdentifierType', ['char']]]]) 1109 self.assertEqual(self.get_decl(d2, 2), 1110 ['Decl', 'ar', 1111 ['ArrayDecl', '4', [], 1112 ['TypeDecl', ['IdentifierType', ['char']]]]]) 1113 1114 def test_invalid_multiple_types_error(self): 1115 bad = [ 1116 'int enum {ab, cd} fubr;', 1117 'enum kid char brbr;'] 1118 1119 for b in bad: 1120 self.assertRaises(ParseError, self.parse, b) 1121 1122 def test_duplicate_typedef(self): 1123 """ Tests that redeclarations of existing types are parsed correctly. 1124 This is non-standard, but allowed by many compilers. 1125 """ 1126 d1 = ''' 1127 typedef int numbertype; 1128 typedef int numbertype; 1129 ''' 1130 1131 self.assertEqual(self.get_decl(d1, 0), 1132 ['Typedef', 'numbertype', 1133 ['TypeDecl', ['IdentifierType', ['int']]]]) 1134 self.assertEqual(self.get_decl(d1, 1), 1135 ['Typedef', 'numbertype', 1136 ['TypeDecl', ['IdentifierType', ['int']]]]) 1137 1138 d2 = ''' 1139 typedef int (*funcptr)(int x); 1140 typedef int (*funcptr)(int x); 1141 ''' 1142 self.assertEqual(self.get_decl(d2, 0), 1143 ['Typedef', 'funcptr', 1144 ['PtrDecl', ['FuncDecl', 1145 [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]], 1146 ['TypeDecl', ['IdentifierType', ['int']]]]]]) 1147 self.assertEqual(self.get_decl(d2, 1), 1148 ['Typedef', 'funcptr', 1149 ['PtrDecl', ['FuncDecl', 1150 [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]], 1151 ['TypeDecl', ['IdentifierType', ['int']]]]]]) 1152 1153 d3 = ''' 1154 typedef int numberarray[5]; 1155 typedef int numberarray[5]; 1156 ''' 1157 self.assertEqual(self.get_decl(d3, 0), 1158 ['Typedef', 'numberarray', 1159 ['ArrayDecl', '5', [], 1160 ['TypeDecl', ['IdentifierType', ['int']]]]]) 1161 self.assertEqual(self.get_decl(d3, 1), 1162 ['Typedef', 'numberarray', 1163 ['ArrayDecl', '5', [], 1164 ['TypeDecl', ['IdentifierType', ['int']]]]]) 1165 1166 def test_decl_inits(self): 1167 d1 = 'int a = 16;' 1168 #~ self.parse(d1).show() 1169 self.assertEqual(self.get_decl(d1), 1170 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]]) 1171 self.assertEqual(self.get_decl_init(d1), 1172 ['Constant', 'int', '16']) 1173 1174 d1_1 = 'float f = 0xEF.56p1;' 1175 self.assertEqual(self.get_decl_init(d1_1), 1176 ['Constant', 'float', '0xEF.56p1']) 1177 1178 d1_2 = 'int bitmask = 0b1001010;' 1179 self.assertEqual(self.get_decl_init(d1_2), 1180 ['Constant', 'int', '0b1001010']) 1181 1182 d2 = 'long ar[] = {7, 8, 9};' 1183 self.assertEqual(self.get_decl(d2), 1184 ['Decl', 'ar', 1185 ['ArrayDecl', '', [], 1186 ['TypeDecl', ['IdentifierType', ['long']]]]]) 1187 self.assertEqual(self.get_decl_init(d2), 1188 [ ['Constant', 'int', '7'], 1189 ['Constant', 'int', '8'], 1190 ['Constant', 'int', '9']]) 1191 1192 d21 = 'long ar[4] = {};' 1193 self.assertEqual(self.get_decl_init(d21), []) 1194 1195 d3 = 'char p = j;' 1196 self.assertEqual(self.get_decl(d3), 1197 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['char']]]]) 1198 self.assertEqual(self.get_decl_init(d3), 1199 ['ID', 'j']) 1200 1201 d4 = "char x = 'c', *p = {0, 1, 2, {4, 5}, 6};" 1202 self.assertEqual(self.get_decl(d4, 0), 1203 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['char']]]]) 1204 self.assertEqual(self.get_decl_init(d4, 0), 1205 ['Constant', 'char', "'c'"]) 1206 self.assertEqual(self.get_decl(d4, 1), 1207 ['Decl', 'p', 1208 ['PtrDecl', 1209 ['TypeDecl', ['IdentifierType', ['char']]]]]) 1210 1211 self.assertEqual(self.get_decl_init(d4, 1), 1212 [ ['Constant', 'int', '0'], 1213 ['Constant', 'int', '1'], 1214 ['Constant', 'int', '2'], 1215 [['Constant', 'int', '4'], 1216 ['Constant', 'int', '5']], 1217 ['Constant', 'int', '6']]) 1218 1219 d5 = 'float d = 1.0;' 1220 self.assertEqual(self.get_decl_init(d5), 1221 ['Constant', 'double', '1.0']) 1222 1223 d51 = 'float ld = 1.0l;' 1224 self.assertEqual(self.get_decl_init(d51), 1225 ['Constant', 'long double', '1.0l']) 1226 1227 d52 = 'float ld = 1.0L;' 1228 self.assertEqual(self.get_decl_init(d52), 1229 ['Constant', 'long double', '1.0L']) 1230 1231 d53 = 'float ld = 1.0f;' 1232 self.assertEqual(self.get_decl_init(d53), 1233 ['Constant', 'float', '1.0f']) 1234 1235 d54 = 'float ld = 1.0F;' 1236 self.assertEqual(self.get_decl_init(d54), 1237 ['Constant', 'float', '1.0F']) 1238 1239 d55 = 'float ld = 0xDE.38p0;' 1240 self.assertEqual(self.get_decl_init(d55), 1241 ['Constant', 'float', '0xDE.38p0']) 1242 1243 def test_decl_named_inits(self): 1244 d1 = 'int a = {.k = 16};' 1245 self.assertEqual(self.get_decl_init(d1), 1246 [( [['ID', 'k']], 1247 ['Constant', 'int', '16'])]) 1248 1249 d2 = 'int a = { [0].a = {1}, [1].a[0] = 2 };' 1250 self.assertEqual(self.get_decl_init(d2), 1251 [ 1252 ([['Constant', 'int', '0'], ['ID', 'a']], 1253 [['Constant', 'int', '1']]), 1254 ([['Constant', 'int', '1'], ['ID', 'a'], ['Constant', 'int', '0']], 1255 ['Constant', 'int', '2'])]) 1256 1257 d3 = 'int a = { .a = 1, .c = 3, 4, .b = 5};' 1258 self.assertEqual(self.get_decl_init(d3), 1259 [ 1260 ([['ID', 'a']], ['Constant', 'int', '1']), 1261 ([['ID', 'c']], ['Constant', 'int', '3']), 1262 ['Constant', 'int', '4'], 1263 ([['ID', 'b']], ['Constant', 'int', '5'])]) 1264 1265 def test_function_definitions(self): 1266 def parse_fdef(str): 1267 return self.parse(str).ext[0] 1268 1269 def fdef_decl(fdef): 1270 return expand_decl(fdef.decl) 1271 1272 f1 = parse_fdef(''' 1273 int factorial(int p) 1274 { 1275 return 3; 1276 } 1277 ''') 1278 1279 self.assertEqual(fdef_decl(f1), 1280 ['Decl', 'factorial', 1281 ['FuncDecl', 1282 [['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]]], 1283 ['TypeDecl', ['IdentifierType', ['int']]]]]) 1284 1285 self.assertEqual(type(f1.body.block_items[0]), Return) 1286 1287 f2 = parse_fdef(''' 1288 char* zzz(int p, char* c) 1289 { 1290 int a; 1291 char b; 1292 1293 a = b + 2; 1294 return 3; 1295 } 1296 ''') 1297 1298 self.assertEqual(fdef_decl(f2), 1299 ['Decl', 'zzz', 1300 ['FuncDecl', 1301 [ ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]], 1302 ['Decl', 'c', ['PtrDecl', 1303 ['TypeDecl', ['IdentifierType', ['char']]]]]], 1304 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]) 1305 1306 self.assertEqual(list(map(type, f2.body.block_items)), 1307 [Decl, Decl, Assignment, Return]) 1308 1309 f3 = parse_fdef(''' 1310 char* zzz(p, c) 1311 long p, *c; 1312 { 1313 int a; 1314 char b; 1315 1316 a = b + 2; 1317 return 3; 1318 } 1319 ''') 1320 1321 self.assertEqual(fdef_decl(f3), 1322 ['Decl', 'zzz', 1323 ['FuncDecl', 1324 [ ['ID', 'p'], 1325 ['ID', 'c']], 1326 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]) 1327 1328 self.assertEqual(list(map(type, f3.body.block_items)), 1329 [Decl, Decl, Assignment, Return]) 1330 1331 self.assertEqual(expand_decl(f3.param_decls[0]), 1332 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['long']]]]) 1333 self.assertEqual(expand_decl(f3.param_decls[1]), 1334 ['Decl', 'c', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['long']]]]]) 1335 1336 # function return values and parameters may not have type information 1337 f4 = parse_fdef(''' 1338 que(p) 1339 { 1340 return 3; 1341 } 1342 ''') 1343 1344 self.assertEqual(fdef_decl(f4), 1345 ['Decl', 'que', 1346 ['FuncDecl', 1347 [['ID', 'p']], 1348 ['TypeDecl', ['IdentifierType', ['int']]]]]) 1349 1350 def test_unified_string_literals(self): 1351 # simple string, for reference 1352 d1 = self.get_decl_init('char* s = "hello";') 1353 self.assertEqual(d1, ['Constant', 'string', '"hello"']) 1354 1355 d2 = self.get_decl_init('char* s = "hello" " world";') 1356 self.assertEqual(d2, ['Constant', 'string', '"hello world"']) 1357 1358 # the test case from issue 6 1359 d3 = self.parse(r''' 1360 int main() { 1361 fprintf(stderr, 1362 "Wrong Params?\n" 1363 "Usage:\n" 1364 "%s <binary_file_path>\n", 1365 argv[0] 1366 ); 1367 } 1368 ''') 1369 1370 self.assertEqual( 1371 d3.ext[0].body.block_items[0].args.exprs[1].value, 1372 r'"Wrong Params?\nUsage:\n%s <binary_file_path>\n"') 1373 1374 d4 = self.get_decl_init('char* s = "" "foobar";') 1375 self.assertEqual(d4, ['Constant', 'string', '"foobar"']) 1376 1377 d5 = self.get_decl_init(r'char* s = "foo\"" "bar";') 1378 self.assertEqual(d5, ['Constant', 'string', r'"foo\"bar"']) 1379 1380 def test_unified_wstring_literals(self): 1381 d1 = self.get_decl_init('char* s = L"hello" L"world";') 1382 self.assertEqual(d1, ['Constant', 'string', 'L"helloworld"']) 1383 1384 d2 = self.get_decl_init('char* s = L"hello " L"world" L" and I";') 1385 self.assertEqual(d2, ['Constant', 'string', 'L"hello world and I"']) 1386 1387 def test_inline_specifier(self): 1388 ps2 = self.parse('static inline void inlinefoo(void);') 1389 self.assertEqual(ps2.ext[0].funcspec, ['inline']) 1390 1391 # variable length array 1392 def test_vla(self): 1393 ps2 = self.parse(r''' 1394 int main() { 1395 int size; 1396 int var[size = 5]; 1397 1398 int var2[*]; 1399 } 1400 ''') 1401 self.assertIsInstance(ps2.ext[0].body.block_items[1].type.dim, Assignment) 1402 self.assertIsInstance(ps2.ext[0].body.block_items[2].type.dim, ID) 1403 1404 def test_pragma(self): 1405 s1 = r''' 1406 #pragma bar 1407 void main() { 1408 #pragma foo 1409 for(;;) {} 1410 #pragma 1411 } 1412 struct s { 1413 #pragma baz 1414 } s; 1415 ''' 1416 s1_ast = self.parse(s1) 1417 self.assertIsInstance(s1_ast.ext[0], Pragma) 1418 self.assertEqual(s1_ast.ext[0].string, 'bar') 1419 self.assertEqual(s1_ast.ext[0].coord.line, 2) 1420 1421 self.assertIsInstance(s1_ast.ext[1].body.block_items[0], Pragma) 1422 self.assertEqual(s1_ast.ext[1].body.block_items[0].string, 'foo') 1423 self.assertEqual(s1_ast.ext[1].body.block_items[0].coord.line, 4) 1424 1425 self.assertIsInstance(s1_ast.ext[1].body.block_items[2], Pragma) 1426 self.assertEqual(s1_ast.ext[1].body.block_items[2].string, '') 1427 self.assertEqual(s1_ast.ext[1].body.block_items[2].coord.line, 6) 1428 1429 self.assertIsInstance(s1_ast.ext[2].type.type.decls[0], Pragma) 1430 self.assertEqual(s1_ast.ext[2].type.type.decls[0].string, 'baz') 1431 self.assertEqual(s1_ast.ext[2].type.type.decls[0].coord.line, 9) 1432 1433 def test_pragmacomp_or_statement(self): 1434 s1 = r''' 1435 void main() { 1436 int sum = 0; 1437 for (int i; i < 3; i++) 1438 #pragma omp critical 1439 sum += 1; 1440 1441 while(sum < 10) 1442 #pragma omp critical 1443 sum += 1; 1444 1445 mylabel: 1446 #pragma foo 1447 sum += 10; 1448 1449 if (sum > 10) 1450 #pragma bar 1451 sum = 10; 1452 1453 switch (sum) 1454 case 10: 1455 #pragma foo 1456 sum = 20; 1457 } 1458 ''' 1459 s1_ast = self.parse(s1) 1460 self.assertIsInstance(s1_ast.ext[0].body.block_items[1], For) 1461 self.assertIsInstance(s1_ast.ext[0].body.block_items[1].stmt, Compound) 1462 self.assertIsInstance(s1_ast.ext[0].body.block_items[1].stmt.block_items[0], Pragma) 1463 self.assertIsInstance(s1_ast.ext[0].body.block_items[1].stmt.block_items[1], Assignment) 1464 self.assertIsInstance(s1_ast.ext[0].body.block_items[2], While) 1465 self.assertIsInstance(s1_ast.ext[0].body.block_items[2].stmt, Compound) 1466 self.assertIsInstance(s1_ast.ext[0].body.block_items[2].stmt.block_items[0], Pragma) 1467 self.assertIsInstance(s1_ast.ext[0].body.block_items[2].stmt.block_items[1], Assignment) 1468 self.assertIsInstance(s1_ast.ext[0].body.block_items[3], Label) 1469 self.assertIsInstance(s1_ast.ext[0].body.block_items[3].stmt, Compound) 1470 self.assertIsInstance(s1_ast.ext[0].body.block_items[3].stmt.block_items[0], Pragma) 1471 self.assertIsInstance(s1_ast.ext[0].body.block_items[3].stmt.block_items[1], Assignment) 1472 self.assertIsInstance(s1_ast.ext[0].body.block_items[4], If) 1473 self.assertIsInstance(s1_ast.ext[0].body.block_items[4].iftrue, Compound) 1474 self.assertIsInstance(s1_ast.ext[0].body.block_items[4].iftrue.block_items[0], Pragma) 1475 self.assertIsInstance(s1_ast.ext[0].body.block_items[4].iftrue.block_items[1], Assignment) 1476 self.assertIsInstance(s1_ast.ext[0].body.block_items[5], Switch) 1477 self.assertIsInstance(s1_ast.ext[0].body.block_items[5].stmt.stmts[0], Compound) 1478 self.assertIsInstance(s1_ast.ext[0].body.block_items[5].stmt.stmts[0].block_items[0], Pragma) 1479 self.assertIsInstance(s1_ast.ext[0].body.block_items[5].stmt.stmts[0].block_items[1], Assignment) 1480 1481 1482class TestCParser_whole_code(TestCParser_base): 1483 """ Testing of parsing whole chunks of code. 1484 1485 Since I don't want to rely on the structure of ASTs too 1486 much, most of these tests are implemented with visitors. 1487 """ 1488 # A simple helper visitor that lists the values of all the 1489 # Constant nodes it sees. 1490 # 1491 class ConstantVisitor(NodeVisitor): 1492 def __init__(self): 1493 self.values = [] 1494 1495 def visit_Constant(self, node): 1496 self.values.append(node.value) 1497 1498 # This visitor counts the amount of references to the ID 1499 # with the name provided to it in the constructor. 1500 # 1501 class IDNameCounter(NodeVisitor): 1502 def __init__(self, name): 1503 self.name = name 1504 self.nrefs = 0 1505 1506 def visit_ID(self, node): 1507 if node.name == self.name: 1508 self.nrefs += 1 1509 1510 # Counts the amount of nodes of a given class 1511 # 1512 class NodeKlassCounter(NodeVisitor): 1513 def __init__(self, node_klass): 1514 self.klass = node_klass 1515 self.n = 0 1516 1517 def generic_visit(self, node): 1518 if node.__class__ == self.klass: 1519 self.n += 1 1520 1521 NodeVisitor.generic_visit(self, node) 1522 1523 def assert_all_Constants(self, code, constants): 1524 """ Asserts that the list of all Constant values (by 1525 'preorder' appearance) in the chunk of code is as 1526 given. 1527 """ 1528 if isinstance(code, str): 1529 parsed = self.parse(code) 1530 else: 1531 parsed = code 1532 1533 cv = self.ConstantVisitor() 1534 cv.visit(parsed) 1535 self.assertEqual(cv.values, constants) 1536 1537 def assert_num_ID_refs(self, code, name, num): 1538 """ Asserts the number of references to the ID with 1539 the given name. 1540 """ 1541 if isinstance(code, str): 1542 parsed = self.parse(code) 1543 else: 1544 parsed = code 1545 1546 iv = self.IDNameCounter(name) 1547 iv.visit(parsed) 1548 self.assertEqual(iv.nrefs, num) 1549 1550 def assert_num_klass_nodes(self, code, klass, num): 1551 """ Asserts the amount of klass nodes in the code. 1552 """ 1553 if isinstance(code, str): 1554 parsed = self.parse(code) 1555 else: 1556 parsed = code 1557 1558 cv = self.NodeKlassCounter(klass) 1559 cv.visit(parsed) 1560 self.assertEqual(cv.n, num) 1561 1562 def test_expressions(self): 1563 e1 = '''int k = (r + 10.0) >> 6 + 8 << (3 & 0x14);''' 1564 self.assert_all_Constants(e1, ['10.0', '6', '8', '3', '0x14']) 1565 1566 e2 = r'''char n = '\n', *prefix = "st_";''' 1567 self.assert_all_Constants(e2, [r"'\n'", '"st_"']) 1568 1569 s1 = r'''int main() { 1570 int i = 5, j = 6, k = 1; 1571 if ((i=j && k == 1) || k > j) 1572 printf("Hello, world\n"); 1573 return 0; 1574 }''' 1575 ps1 = self.parse(s1) 1576 self.assert_all_Constants(ps1, 1577 ['5', '6', '1', '1', '"Hello, world\\n"', '0']) 1578 self.assert_num_ID_refs(ps1, 'i', 1) 1579 self.assert_num_ID_refs(ps1, 'j', 2) 1580 1581 1582 def test_statements(self): 1583 s1 = r''' 1584 void foo(){ 1585 if (sp == 1) 1586 if (optind >= argc || 1587 argv[optind][0] != '-' || argv[optind][1] == '\0') 1588 return -1; 1589 else if (strcmp(argv[optind], "--") == 0) { 1590 optind++; 1591 return -1; 1592 } 1593 } 1594 ''' 1595 1596 self.assert_all_Constants(s1, 1597 ['1', '0', r"'-'", '1', r"'\0'", '1', r'"--"', '0', '1']) 1598 1599 ps1 = self.parse(s1) 1600 self.assert_num_ID_refs(ps1, 'argv', 3) 1601 self.assert_num_ID_refs(ps1, 'optind', 5) 1602 1603 self.assert_num_klass_nodes(ps1, If, 3) 1604 self.assert_num_klass_nodes(ps1, Return, 2) 1605 self.assert_num_klass_nodes(ps1, FuncCall, 1) # strcmp 1606 self.assert_num_klass_nodes(ps1, BinaryOp, 7) 1607 1608 # In the following code, Hash and Node were defined as 1609 # int to pacify the parser that sees they're used as 1610 # types 1611 # 1612 s2 = r''' 1613 typedef int Hash, Node; 1614 1615 void HashDestroy(Hash* hash) 1616 { 1617 unsigned int i; 1618 1619 if (hash == NULL) 1620 return; 1621 1622 for (i = 0; i < hash->table_size; ++i) 1623 { 1624 Node* temp = hash->heads[i]; 1625 1626 while (temp != NULL) 1627 { 1628 Node* temp2 = temp; 1629 1630 free(temp->entry->key); 1631 free(temp->entry->value); 1632 free(temp->entry); 1633 1634 temp = temp->next; 1635 1636 free(temp2); 1637 } 1638 } 1639 1640 free(hash->heads); 1641 hash->heads = NULL; 1642 1643 free(hash); 1644 } 1645 ''' 1646 1647 ps2 = self.parse(s2) 1648 self.assert_num_klass_nodes(ps2, FuncCall, 6) 1649 self.assert_num_klass_nodes(ps2, FuncDef, 1) 1650 self.assert_num_klass_nodes(ps2, For, 1) 1651 self.assert_num_klass_nodes(ps2, While, 1) 1652 self.assert_num_klass_nodes(ps2, StructRef, 10) 1653 1654 # declarations don't count 1655 self.assert_num_ID_refs(ps2, 'hash', 6) 1656 self.assert_num_ID_refs(ps2, 'i', 4) 1657 1658 s3 = r''' 1659 void x(void) { 1660 int a, b; 1661 if (a < b) 1662 do { 1663 a = 0; 1664 } while (0); 1665 else if (a == b) { 1666 a = 1; 1667 } 1668 } 1669 ''' 1670 1671 ps3 = self.parse(s3) 1672 self.assert_num_klass_nodes(ps3, DoWhile, 1) 1673 self.assert_num_ID_refs(ps3, 'a', 4) 1674 self.assert_all_Constants(ps3, ['0', '0', '1']) 1675 1676 def test_empty_statements(self): 1677 s1 = r''' 1678 void foo(void){ 1679 ; 1680 return;; 1681 1682 ; 1683 } 1684 ''' 1685 ps1 = self.parse(s1) 1686 self.assert_num_klass_nodes(ps1, EmptyStatement, 3) 1687 self.assert_num_klass_nodes(ps1, Return, 1) 1688 self.assert_coord(ps1.ext[0].body.block_items[0], 3) 1689 self.assert_coord(ps1.ext[0].body.block_items[1], 4) 1690 self.assert_coord(ps1.ext[0].body.block_items[2], 4) 1691 self.assert_coord(ps1.ext[0].body.block_items[3], 6) 1692 1693 def test_switch_statement(self): 1694 def assert_case_node(node, const_value): 1695 self.assertIsInstance(node, Case) 1696 self.assertIsInstance(node.expr, Constant) 1697 self.assertEqual(node.expr.value, const_value) 1698 1699 def assert_default_node(node): 1700 self.assertIsInstance(node, Default) 1701 1702 s1 = r''' 1703 int foo(void) { 1704 switch (myvar) { 1705 case 10: 1706 k = 10; 1707 p = k + 1; 1708 return 10; 1709 case 20: 1710 case 30: 1711 return 20; 1712 default: 1713 break; 1714 } 1715 return 0; 1716 } 1717 ''' 1718 ps1 = self.parse(s1) 1719 switch = ps1.ext[0].body.block_items[0] 1720 1721 block = switch.stmt.block_items 1722 assert_case_node(block[0], '10') 1723 self.assertEqual(len(block[0].stmts), 3) 1724 assert_case_node(block[1], '20') 1725 self.assertEqual(len(block[1].stmts), 0) 1726 assert_case_node(block[2], '30') 1727 self.assertEqual(len(block[2].stmts), 1) 1728 assert_default_node(block[3]) 1729 1730 s2 = r''' 1731 int foo(void) { 1732 switch (myvar) { 1733 default: 1734 joe = moe; 1735 return 10; 1736 case 10: 1737 case 20: 1738 case 30: 1739 case 40: 1740 break; 1741 } 1742 return 0; 1743 } 1744 ''' 1745 ps2 = self.parse(s2) 1746 switch = ps2.ext[0].body.block_items[0] 1747 1748 block = switch.stmt.block_items 1749 assert_default_node(block[0]) 1750 self.assertEqual(len(block[0].stmts), 2) 1751 assert_case_node(block[1], '10') 1752 self.assertEqual(len(block[1].stmts), 0) 1753 assert_case_node(block[2], '20') 1754 self.assertEqual(len(block[1].stmts), 0) 1755 assert_case_node(block[3], '30') 1756 self.assertEqual(len(block[1].stmts), 0) 1757 assert_case_node(block[4], '40') 1758 self.assertEqual(len(block[4].stmts), 1) 1759 1760 def test_for_statement(self): 1761 s2 = r''' 1762 void x(void) 1763 { 1764 int i; 1765 for (i = 0; i < 5; ++i) { 1766 x = 50; 1767 } 1768 } 1769 ''' 1770 ps2 = self.parse(s2) 1771 self.assert_num_klass_nodes(ps2, For, 1) 1772 # here there are 3 refs to 'i' since the declaration doesn't count as 1773 # a ref in the visitor 1774 # 1775 self.assert_num_ID_refs(ps2, 'i', 3) 1776 1777 s3 = r''' 1778 void x(void) 1779 { 1780 for (int i = 0; i < 5; ++i) { 1781 x = 50; 1782 } 1783 } 1784 ''' 1785 ps3 = self.parse(s3) 1786 self.assert_num_klass_nodes(ps3, For, 1) 1787 # here there are 2 refs to 'i' since the declaration doesn't count as 1788 # a ref in the visitor 1789 # 1790 self.assert_num_ID_refs(ps3, 'i', 2) 1791 1792 s4 = r''' 1793 void x(void) { 1794 for (int i = 0;;) 1795 i; 1796 } 1797 ''' 1798 ps4 = self.parse(s4) 1799 self.assert_num_ID_refs(ps4, 'i', 1) 1800 1801 def _open_c_file(self, name): 1802 """ Find a c file by name, taking into account the current dir can be 1803 in a couple of typical places 1804 """ 1805 testdir = os.path.dirname(__file__) 1806 name = os.path.join(testdir, 'c_files', name) 1807 assert os.path.exists(name) 1808 return io.open(name) 1809 1810 def test_whole_file(self): 1811 # See how pycparser handles a whole, real C file. 1812 # 1813 with self._open_c_file('memmgr_with_h.c') as f: 1814 code = f.read() 1815 p = self.parse(code) 1816 1817 self.assert_num_klass_nodes(p, FuncDef, 5) 1818 1819 # each FuncDef also has a FuncDecl. 4 declarations 1820 # + 5 definitions, overall 9 1821 self.assert_num_klass_nodes(p, FuncDecl, 9) 1822 1823 self.assert_num_klass_nodes(p, Typedef, 4) 1824 1825 self.assertEqual(p.ext[4].coord.line, 88) 1826 self.assertEqual(p.ext[4].coord.file, "./memmgr.h") 1827 1828 self.assertEqual(p.ext[6].coord.line, 10) 1829 self.assertEqual(p.ext[6].coord.file, "memmgr.c") 1830 1831 def test_whole_file_with_stdio(self): 1832 # Parse a whole file with stdio.h included by cpp 1833 # 1834 with self._open_c_file('cppd_with_stdio_h.c') as f: 1835 code = f.read() 1836 p = self.parse(code) 1837 1838 self.assertIsInstance(p.ext[0], Typedef) 1839 self.assertEqual(p.ext[0].coord.line, 213) 1840 self.assertEqual(p.ext[0].coord.file, r"D:\eli\cpp_stuff\libc_include/stddef.h") 1841 1842 self.assertIsInstance(p.ext[-1], FuncDef) 1843 self.assertEqual(p.ext[-1].coord.line, 15) 1844 self.assertEqual(p.ext[-1].coord.file, "example_c_file.c") 1845 1846 self.assertIsInstance(p.ext[-8], Typedef) 1847 self.assertIsInstance(p.ext[-8].type, TypeDecl) 1848 self.assertEqual(p.ext[-8].name, 'cookie_io_functions_t') 1849 1850 1851class TestCParser_typenames(TestCParser_base): 1852 """ Test issues related to the typedef-name problem. 1853 """ 1854 def test_innerscope_typedef(self): 1855 # should fail since TT is not a type in bar 1856 s1 = r''' 1857 void foo() { 1858 typedef char TT; 1859 TT x; 1860 } 1861 void bar() { 1862 TT y; 1863 } 1864 ''' 1865 self.assertRaises(ParseError, self.parse, s1) 1866 1867 # should succeed since TT is not a type in bar 1868 s2 = r''' 1869 void foo() { 1870 typedef char TT; 1871 TT x; 1872 } 1873 void bar() { 1874 unsigned TT; 1875 } 1876 ''' 1877 self.assertIsInstance(self.parse(s2), FileAST) 1878 1879 def test_ambiguous_parameters(self): 1880 # From ISO/IEC 9899:TC2, 6.7.5.3.11: 1881 # "If, in a parameter declaration, an identifier can be treated either 1882 # as a typedef name or as a parameter name, it shall be taken as a 1883 # typedef name." 1884 1885 # foo takes an int named aa 1886 # bar takes a function taking a TT 1887 s1 = r''' 1888 typedef char TT; 1889 int foo(int (aa)); 1890 int bar(int (TT)); 1891 ''' 1892 s1_ast = self.parse(s1) 1893 self.assertEqual(expand_decl(s1_ast.ext[1].type.args.params[0]), 1894 ['Decl', 'aa', ['TypeDecl', ['IdentifierType', ['int']]]]) 1895 self.assertEqual(expand_decl(s1_ast.ext[2].type.args.params[0]), 1896 ['Typename', ['FuncDecl', 1897 [['Typename', ['TypeDecl', ['IdentifierType', ['TT']]]]], 1898 ['TypeDecl', ['IdentifierType', ['int']]]]]) 1899 1900 # foo takes a function taking a char 1901 # bar takes a function taking a function taking a char 1902 s2 = r''' 1903 typedef char TT; 1904 int foo(int (aa (char))); 1905 int bar(int (TT (char))); 1906 ''' 1907 s2_ast = self.parse(s2) 1908 self.assertEqual(expand_decl(s2_ast.ext[1].type.args.params[0]), 1909 ['Decl', 'aa', ['FuncDecl', 1910 [['Typename', ['TypeDecl', ['IdentifierType', ['char']]]]], 1911 ['TypeDecl', ['IdentifierType', ['int']]]]]) 1912 self.assertEqual(expand_decl(s2_ast.ext[2].type.args.params[0]), 1913 ['Typename', ['FuncDecl', 1914 [['Typename', ['FuncDecl', 1915 [['Typename', ['TypeDecl', ['IdentifierType', ['char']]]]], 1916 ['TypeDecl', ['IdentifierType', ['TT']]]]]], 1917 ['TypeDecl', ['IdentifierType', ['int']]]]]) 1918 1919 1920 # foo takes an int array named aa 1921 # bar takes a function taking a TT array 1922 s3 = r''' 1923 typedef char TT; 1924 int foo(int (aa[])); 1925 int bar(int (TT[])); 1926 ''' 1927 s3_ast = self.parse(s3) 1928 self.assertEqual(expand_decl(s3_ast.ext[1].type.args.params[0]), 1929 ['Decl', 'aa', ['ArrayDecl', '', [], ['TypeDecl', ['IdentifierType', ['int']]]]]) 1930 self.assertEqual(expand_decl(s3_ast.ext[2].type.args.params[0]), 1931 ['Typename', ['FuncDecl', 1932 [['Typename', ['ArrayDecl', '', [], ['TypeDecl', ['IdentifierType', ['TT']]]]]], 1933 ['TypeDecl', ['IdentifierType', ['int']]]]]) 1934 1935 def test_innerscope_reuse_typedef_name(self): 1936 # identifiers can be reused in inner scopes; the original should be 1937 # restored at the end of the block 1938 s1 = r''' 1939 typedef char TT; 1940 void foo(void) { 1941 unsigned TT; 1942 TT = 10; 1943 } 1944 TT x = 5; 1945 ''' 1946 s1_ast = self.parse(s1) 1947 self.assertEqual(expand_decl(s1_ast.ext[1].body.block_items[0]), 1948 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]]) 1949 self.assertEqual(expand_decl(s1_ast.ext[2]), 1950 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['TT']]]]) 1951 1952 # this should be recognized even with an initializer 1953 s2 = r''' 1954 typedef char TT; 1955 void foo(void) { 1956 unsigned TT = 10; 1957 } 1958 ''' 1959 s2_ast = self.parse(s2) 1960 self.assertEqual(expand_decl(s2_ast.ext[1].body.block_items[0]), 1961 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]]) 1962 1963 # before the second local variable, TT is a type; after, it's a 1964 # variable 1965 s3 = r''' 1966 typedef char TT; 1967 void foo(void) { 1968 TT tt = sizeof(TT); 1969 unsigned TT = 10; 1970 } 1971 ''' 1972 s3_ast = self.parse(s3) 1973 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[0]), 1974 ['Decl', 'tt', ['TypeDecl', ['IdentifierType', ['TT']]]]) 1975 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[1]), 1976 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]]) 1977 1978 # a variable and its type can even share the same name 1979 s4 = r''' 1980 typedef char TT; 1981 void foo(void) { 1982 TT TT = sizeof(TT); 1983 unsigned uu = TT * 2; 1984 } 1985 ''' 1986 s4_ast = self.parse(s4) 1987 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[0]), 1988 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['TT']]]]) 1989 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[1]), 1990 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['unsigned']]]]) 1991 1992 # ensure an error is raised if a type, redeclared as a variable, is 1993 # used as a type 1994 s5 = r''' 1995 typedef char TT; 1996 void foo(void) { 1997 unsigned TT = 10; 1998 TT erroneous = 20; 1999 } 2000 ''' 2001 self.assertRaises(ParseError, self.parse, s5) 2002 2003 # reusing a type name should work with multiple declarators 2004 s6 = r''' 2005 typedef char TT; 2006 void foo(void) { 2007 unsigned TT, uu; 2008 } 2009 ''' 2010 s6_ast = self.parse(s6) 2011 items = s6_ast.ext[1].body.block_items 2012 self.assertEqual(expand_decl(items[0]), 2013 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]]) 2014 self.assertEqual(expand_decl(items[1]), 2015 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['unsigned']]]]) 2016 2017 # reusing a type name should work after a pointer 2018 s7 = r''' 2019 typedef char TT; 2020 void foo(void) { 2021 unsigned * TT; 2022 } 2023 ''' 2024 s7_ast = self.parse(s7) 2025 items = s7_ast.ext[1].body.block_items 2026 self.assertEqual(expand_decl(items[0]), 2027 ['Decl', 'TT', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['unsigned']]]]]) 2028 2029 # redefine a name in the middle of a multi-declarator declaration 2030 s8 = r''' 2031 typedef char TT; 2032 void foo(void) { 2033 int tt = sizeof(TT), TT, uu = sizeof(TT); 2034 int uu = sizeof(tt); 2035 } 2036 ''' 2037 s8_ast = self.parse(s8) 2038 items = s8_ast.ext[1].body.block_items 2039 self.assertEqual(expand_decl(items[0]), 2040 ['Decl', 'tt', ['TypeDecl', ['IdentifierType', ['int']]]]) 2041 self.assertEqual(expand_decl(items[1]), 2042 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['int']]]]) 2043 self.assertEqual(expand_decl(items[2]), 2044 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['int']]]]) 2045 2046 # Don't test this until we have support for it 2047 # self.assertEqual(expand_init(items[0].init), 2048 # ['UnaryOp', 'sizeof', ['Typename', ['TypeDecl', ['IdentifierType', ['TT']]]]]) 2049 # self.assertEqual(expand_init(items[2].init), 2050 # ['UnaryOp', 'sizeof', ['ID', 'TT']]) 2051 2052 def test_parameter_reuse_typedef_name(self): 2053 # identifiers can be reused as parameter names; parameter name scope 2054 # begins and ends with the function body; it's important that TT is 2055 # used immediately before the LBRACE or after the RBRACE, to test 2056 # a corner case 2057 s1 = r''' 2058 typedef char TT; 2059 void foo(unsigned TT, TT bar) { 2060 TT = 10; 2061 } 2062 TT x = 5; 2063 ''' 2064 s1_ast = self.parse(s1) 2065 self.assertEqual(expand_decl(s1_ast.ext[1].decl), 2066 ['Decl', 'foo', 2067 ['FuncDecl', 2068 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]], 2069 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]], 2070 ['TypeDecl', ['IdentifierType', ['void']]]]]) 2071 2072 # the scope of a parameter name in a function declaration ends at the 2073 # end of the declaration...so it is effectively never used; it's 2074 # important that TT is used immediately after the declaration, to 2075 # test a corner case 2076 s2 = r''' 2077 typedef char TT; 2078 void foo(unsigned TT, TT bar); 2079 TT x = 5; 2080 ''' 2081 s2_ast = self.parse(s2) 2082 self.assertEqual(expand_decl(s2_ast.ext[1]), 2083 ['Decl', 'foo', 2084 ['FuncDecl', 2085 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]], 2086 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]], 2087 ['TypeDecl', ['IdentifierType', ['void']]]]]) 2088 2089 # ensure an error is raised if a type, redeclared as a parameter, is 2090 # used as a type 2091 s3 = r''' 2092 typedef char TT; 2093 void foo(unsigned TT, TT bar) { 2094 TT erroneous = 20; 2095 } 2096 ''' 2097 self.assertRaises(ParseError, self.parse, s3) 2098 2099 def test_nested_function_decls(self): 2100 # parameter names of nested function declarations must not escape into 2101 # the top-level function _definition's_ scope; the following must 2102 # succeed because TT is still a typedef inside foo's body 2103 s1 = r''' 2104 typedef char TT; 2105 void foo(unsigned bar(int TT)) { 2106 TT x = 10; 2107 } 2108 ''' 2109 self.assertIsInstance(self.parse(s1), FileAST) 2110 2111 def test_samescope_reuse_name(self): 2112 # a typedef name cannot be reused as an object name in the same scope 2113 s1 = r''' 2114 typedef char TT; 2115 char TT = 5; 2116 ''' 2117 self.assertRaises(ParseError, self.parse, s1) 2118 2119 # ...and vice-versa 2120 s2 = r''' 2121 char TT = 5; 2122 typedef char TT; 2123 ''' 2124 self.assertRaises(ParseError, self.parse, s2) 2125 2126 2127if __name__ == '__main__': 2128 #~ suite = unittest.TestLoader().loadTestsFromNames( 2129 #~ ['test_c_parser.TestCParser_fundamentals.test_typedef']) 2130 2131 #~ unittest.TextTestRunner(verbosity=2).run(suite) 2132 unittest.main() 2133