• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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