• 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_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