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