blob: 63b4c6f6c4b7e7466c08fb16306cab1677a1ae6e [file] [log] [blame]
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001#!/usr/bin/env python
2
3import pprint
4import re
5import sys
6import unittest
7
8sys.path.insert(0, '..')
9
10from pycparser import c_parser
11from pycparser.c_ast import *
12from pycparser.c_parser import CParser, Coord, ParseError
13
Eli Bendersky3921e8e2010-05-21 09:05:39 +030014_c_parser = c_parser.CParser(
15 lex_optimize=False,
16 yacc_debug=True,
17 yacc_optimize=False,
18 yacctab='yacctab')
19
20
21def expand_decl(decl):
22 """ Converts the declaration into a nested list.
23 """
24 typ = type(decl)
25
26 if typ == TypeDecl:
27 return ['TypeDecl', expand_decl(decl.type)]
28 elif typ == IdentifierType:
29 return ['IdentifierType', decl.names]
30 elif typ == ID:
31 return ['ID', decl.name]
32 elif typ in [Struct, Union]:
33 decls = [expand_decl(d) for d in decl.decls or []]
34 return [typ.__name__, decl.name, decls]
35 else:
36 nested = expand_decl(decl.type)
37
38 if typ == Decl:
39 if decl.quals:
40 return ['Decl', decl.quals, decl.name, nested]
41 else:
42 return ['Decl', decl.name, nested]
43 elif typ == Typename: # for function parameters
44 if decl.quals:
45 return ['Typename', decl.quals, nested]
46 else:
47 return ['Typename', nested]
48 elif typ == ArrayDecl:
49 dimval = decl.dim.value if decl.dim else ''
50 return ['ArrayDecl', dimval, nested]
51 elif typ == PtrDecl:
52 return ['PtrDecl', nested]
53 elif typ == Typedef:
54 return ['Typedef', decl.name, nested]
55 elif typ == FuncDecl:
56 if decl.args:
57 params = [expand_decl(param) for param in decl.args.params]
58 else:
59 params = []
60 return ['FuncDecl', params, nested]
61
62
63def expand_init(init):
64 """ Converts an initialization into a nested list
65 """
66 typ = type(init)
67
eli.benderskyf890a862010-10-30 12:13:23 +020068 if typ == NamedInitializer:
69 des = [expand_init(dp) for dp in init.name]
70 return (des, expand_init(init.expr))
71 elif typ == ExprList:
72 return [expand_init(expr) for expr in init.exprs]
73 elif typ == Constant:
Eli Bendersky3921e8e2010-05-21 09:05:39 +030074 return ['Constant', init.type, init.value]
75 elif typ == ID:
76 return ['ID', init.name]
Eli Bendersky3921e8e2010-05-21 09:05:39 +030077
78
eli.bendersky85d2e732011-05-20 19:47:26 +030079class TestCParser_base(unittest.TestCase):
Eli Bendersky3921e8e2010-05-21 09:05:39 +030080 def parse(self, txt, filename=''):
81 return self.cparser.parse(txt, filename)
82
83 def setUp(self):
84 self.cparser = _c_parser
85
eli.bendersky85d2e732011-05-20 19:47:26 +030086
87class TestCParser_fundamentals(TestCParser_base):
Eli Bendersky3921e8e2010-05-21 09:05:39 +030088 def get_decl(self, txt, index=0):
89 """ Given a source and an index returns the expanded
90 declaration at that index.
91
92 FileAST holds a list of 'external declarations'.
93 index is the offset of the desired declaration in that
94 list.
95 """
96 t = self.parse(txt).ext[index]
97 return expand_decl(t)
98
99 def get_decl_init(self, txt, index=0):
100 """ Returns the expanded initializer of the declaration
101 at index.
102 """
103 t = self.parse(txt).ext[index]
104 return expand_init(t.init)
105
106 def test_FileAST(self):
107 t = self.parse('int a; char c;')
108 self.failUnless(isinstance(t, FileAST))
109 self.assertEqual(len(t.ext), 2)
110
eli.bendersky38165b72011-02-04 08:13:39 +0200111 def test_empty_toplevel_decl(self):
112 code = 'int foo;;'
113 t = self.parse(code)
114 self.failUnless(isinstance(t, FileAST))
115 self.assertEqual(len(t.ext), 1)
116 self.assertEqual(self.get_decl(code),
117 ['Decl', 'foo',
118 ['TypeDecl', ['IdentifierType', ['int']]]])
119
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300120 def assert_coord(self, node, line, file=None):
121 self.assertEqual(node.coord.line, line)
122 if file:
123 self.assertEqual(node.coord.file, file)
124
125 def test_coords(self):
eli.bendersky38165b72011-02-04 08:13:39 +0200126 """ Tests the "coordinates" of parsed elements - file
127 name and line numbers, with modification insterted by
128 #line directives.
129 """
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300130 self.assert_coord(self.parse('int a;').ext[0], 1)
131
132 t1 = """
133 int a;
134 int b;\n\n
135 int c;
136 """
137 f1 = self.parse(t1, filename='test.c')
138 self.assert_coord(f1.ext[0], 2, 'test.c')
139 self.assert_coord(f1.ext[1], 3, 'test.c')
140 self.assert_coord(f1.ext[2], 6, 'test.c')
141
142 t1_1 = '''
143 int main() {
144 k = p;
145 printf("%d", b);
146 return 0;
147 }'''
148 f1_1 = self.parse(t1_1, filename='test.c')
eli.benderskyef29ff92010-10-29 16:25:43 +0200149 self.assert_coord(f1_1.ext[0].body.block_items[0], 3, 'test.c')
150 self.assert_coord(f1_1.ext[0].body.block_items[1], 4, 'test.c')
eli.benderskyfc96e5e2011-03-04 09:51:23 +0200151
152 t1_2 = '''
153 int main () {
154 int p = (int) k;
155 }'''
156 f1_2 = self.parse(t1_2, filename='test.c')
157 # make sure that the Cast has a coord (issue 23)
158 self.assert_coord(f1_2.ext[0].body.block_items[0].init, 3, 'test.c')
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300159
160 t2 = """
161 #line 99
162 int c;
163 """
164 self.assert_coord(self.parse(t2).ext[0], 99)
165
166 t3 = """
167 int dsf;
168 char p;
169 #line 3000 "in.h"
170 char d;
171 """
172 f3 = self.parse(t3, filename='test.c')
173 self.assert_coord(f3.ext[0], 2, 'test.c')
174 self.assert_coord(f3.ext[1], 3, 'test.c')
175 self.assert_coord(f3.ext[2], 3000, 'in.h')
176
177 t4 = """
178 #line 20 "restore.h"
179 int maydler(char);
180
181 #line 30 "includes/daween.ph"
182 long j, k;
183
184 #line 50000
185 char* ro;
186 """
187 f4 = self.parse(t4, filename='myb.c')
188 self.assert_coord(f4.ext[0], 20, 'restore.h')
189 self.assert_coord(f4.ext[1], 30, 'includes/daween.ph')
190 self.assert_coord(f4.ext[2], 30, 'includes/daween.ph')
191 self.assert_coord(f4.ext[3], 50000, 'includes/daween.ph')
192
193 t5 = """
194 int
195 #line 99
196 c;
197 """
198 self.assert_coord(self.parse(t5).ext[0], 99)
199
200 def test_simple_decls(self):
201 self.assertEqual(self.get_decl('int a;'),
202 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
203
204 self.assertEqual(self.get_decl('unsigned int a;'),
205 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int', 'unsigned']]]])
206
eli.benderskyaffe0322011-09-24 06:16:55 +0300207 self.assertEqual(self.get_decl('_Bool a;'),
208 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['_Bool']]]])
209
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300210 self.assertEqual(self.get_decl('char* string;'),
211 ['Decl', 'string',
212 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]])
213
214 self.assertEqual(self.get_decl('long ar[15];'),
215 ['Decl', 'ar',
216 ['ArrayDecl', '15',
217 ['TypeDecl', ['IdentifierType', ['long']]]]])
eli.bendersky98f45372010-10-30 09:46:29 +0200218
219 self.assertEqual(self.get_decl('long long ar[15];'),
220 ['Decl', 'ar',
221 ['ArrayDecl', '15',
eli.benderskyf890a862010-10-30 12:13:23 +0200222 ['TypeDecl', ['IdentifierType', ['long', 'long']]]]])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300223
224 self.assertEqual(self.get_decl('unsigned ar[];'),
225 ['Decl', 'ar',
226 ['ArrayDecl', '',
227 ['TypeDecl', ['IdentifierType', ['unsigned']]]]])
228
229 self.assertEqual(self.get_decl('int strlen(char* s);'),
230 ['Decl', 'strlen',
231 ['FuncDecl',
232 [['Decl', 's',
233 ['PtrDecl',
234 ['TypeDecl', ['IdentifierType', ['char']]]]]],
235 ['TypeDecl', ['IdentifierType', ['int']]]]])
236
237 self.assertEqual(self.get_decl('int strcmp(char* s1, char* s2);'),
238 ['Decl', 'strcmp',
239 ['FuncDecl',
240 [ ['Decl', 's1',
241 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
242 ['Decl', 's2',
243 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]
244 ],
245 ['TypeDecl', ['IdentifierType', ['int']]]]])
246
247 def test_nested_decls(self): # the fun begins
248 self.assertEqual(self.get_decl('char** ar2D;'),
249 ['Decl', 'ar2D',
250 ['PtrDecl', ['PtrDecl',
251 ['TypeDecl', ['IdentifierType', ['char']]]]]])
252
253 self.assertEqual(self.get_decl('int (*a)[1][2];'),
254 ['Decl', 'a',
255 ['PtrDecl',
256 ['ArrayDecl', '1',
257 ['ArrayDecl', '2',
258 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
259
260 self.assertEqual(self.get_decl('int *a[1][2];'),
261 ['Decl', 'a',
262 ['ArrayDecl', '1',
263 ['ArrayDecl', '2',
264 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['int']]]]]]])
265
266 self.assertEqual(self.get_decl('char ***ar3D[40];'),
267 ['Decl', 'ar3D',
268 ['ArrayDecl', '40',
269 ['PtrDecl', ['PtrDecl', ['PtrDecl',
270 ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
271
272 self.assertEqual(self.get_decl('char (***ar3D)[40];'),
273 ['Decl', 'ar3D',
274 ['PtrDecl', ['PtrDecl', ['PtrDecl',
275 ['ArrayDecl', '40', ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
276
277 self.assertEqual(self.get_decl('int (*x[4])(char, int);'),
278 ['Decl', 'x',
279 ['ArrayDecl', '4',
280 ['PtrDecl',
281 ['FuncDecl',
282 [ ['Typename', ['TypeDecl', ['IdentifierType', ['char']]]],
283 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
284 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
285
286 self.assertEqual(self.get_decl('char *(*(**foo [][8])())[];'),
287 ['Decl', 'foo',
288 ['ArrayDecl', '',
289 ['ArrayDecl', '8',
290 ['PtrDecl', ['PtrDecl',
291 ['FuncDecl',
292 [],
293 ['PtrDecl',
294 ['ArrayDecl', '',
295 ['PtrDecl',
296 ['TypeDecl',
297 ['IdentifierType', ['char']]]]]]]]]]]])
298
299 # explore named and unnamed function pointer parameters,
300 # with and without qualifiers
301 #
302
303 # unnamed w/o quals
304 self.assertEqual(self.get_decl('int (*k)(int);'),
305 ['Decl', 'k',
306 ['PtrDecl',
307 ['FuncDecl',
308 [['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
309 ['TypeDecl', ['IdentifierType', ['int']]]]]])
310
311 # unnamed w/ quals
312 self.assertEqual(self.get_decl('int (*k)(const int);'),
313 ['Decl', 'k',
314 ['PtrDecl',
315 ['FuncDecl',
316 [['Typename', ['const'], ['TypeDecl', ['IdentifierType', ['int']]]]],
317 ['TypeDecl', ['IdentifierType', ['int']]]]]])
318
319 # named w/o quals
320 self.assertEqual(self.get_decl('int (*k)(int q);'),
321 ['Decl', 'k',
322 ['PtrDecl',
323 ['FuncDecl',
324 [['Decl', 'q', ['TypeDecl', ['IdentifierType', ['int']]]]],
325 ['TypeDecl', ['IdentifierType', ['int']]]]]])
326
327 # named w/ quals
328 self.assertEqual(self.get_decl('int (*k)(const volatile int q);'),
329 ['Decl', 'k',
330 ['PtrDecl',
331 ['FuncDecl',
332 [['Decl', ['volatile', 'const'], 'q',
333 ['TypeDecl', ['IdentifierType', ['int']]]]],
334 ['TypeDecl', ['IdentifierType', ['int']]]]]])
335
eli.bendersky79d5cf62010-10-29 13:33:52 +0200336 # restrict qualifier
337 self.assertEqual(self.get_decl('int (*k)(restrict int* q);'),
338 ['Decl', 'k',
339 ['PtrDecl',
340 ['FuncDecl',
341 [['Decl', ['restrict'], 'q',
342 ['PtrDecl',
343 ['TypeDecl', ['IdentifierType', ['int']]]]]],
344 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300345
346 def test_qualifiers_storage_specifiers(self):
347 def assert_qs(txt, index, quals, storage):
348 d = self.parse(txt).ext[index]
349 self.assertEqual(d.quals, quals)
350 self.assertEqual(d.storage, storage)
351
352 assert_qs("extern int p;", 0, [], ['extern'])
353 assert_qs("const long p = 6;", 0, ['const'], [])
354
355 d1 = "static const int p, q, r;"
356 for i in range(3):
357 assert_qs(d1, i, ['const'], ['static'])
358
359 d2 = "static char * const p;"
360 assert_qs(d2, 0, [], ['static'])
361 pdecl = self.parse(d2).ext[0].type
362 self.failUnless(isinstance(pdecl, PtrDecl))
363 self.assertEqual(pdecl.quals, ['const'])
364
365 def test_sizeof(self):
366 e = """
367 void foo()
368 {
369 int a = sizeof k;
370 int b = sizeof(int);
eli.benderskyc51e1d32011-02-04 08:52:33 +0200371 int c = sizeof(int**);;
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300372
373 char* p = "just to make sure this parses w/o error...";
374 int d = sizeof(int());
375 }
376 """
377 compound = self.parse(e).ext[0].body
378
eli.benderskyef29ff92010-10-29 16:25:43 +0200379 s1 = compound.block_items[0].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300380 self.assertTrue(isinstance(s1, UnaryOp))
381 self.assertEqual(s1.op, 'sizeof')
382 self.assertTrue(isinstance(s1.expr, ID))
383 self.assertEqual(s1.expr.name, 'k')
384
eli.benderskyef29ff92010-10-29 16:25:43 +0200385 s2 = compound.block_items[1].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300386 self.assertEqual(expand_decl(s2.expr),
387 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]])
388
eli.benderskyef29ff92010-10-29 16:25:43 +0200389 s3 = compound.block_items[2].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300390 self.assertEqual(expand_decl(s3.expr),
391 ['Typename',
392 ['PtrDecl',
393 ['PtrDecl',
394 ['TypeDecl',
395 ['IdentifierType', ['int']]]]]])
396
eli.bendersky9f481562010-10-30 15:50:47 +0200397 # The C99 compound literal feature
398 #
eli.benderskyf890a862010-10-30 12:13:23 +0200399 def test_compound_literals(self):
eli.bendersky9f481562010-10-30 15:50:47 +0200400 ps1 = self.parse(r'''
eli.benderskyf890a862010-10-30 12:13:23 +0200401 void foo() {
eli.bendersky9f481562010-10-30 15:50:47 +0200402 p = (long long){k};
403 tc = (struct jk){.a = {1, 2}, .b[0] = t};
404 }''')
eli.benderskyf890a862010-10-30 12:13:23 +0200405
eli.bendersky9f481562010-10-30 15:50:47 +0200406 compound = ps1.ext[0].body.block_items[0].rvalue
407 self.assertEqual(expand_decl(compound.type),
408 ['Typename', ['TypeDecl', ['IdentifierType', ['long', 'long']]]])
409 self.assertEqual(expand_init(compound.init),
410 [['ID', 'k']])
411
412 compound = ps1.ext[0].body.block_items[1].rvalue
413 self.assertEqual(expand_decl(compound.type),
414 ['Typename', ['TypeDecl', ['Struct', 'jk', []]]])
415 self.assertEqual(expand_init(compound.init),
416 [
417 ([['ID', 'a']], [['Constant', 'int', '1'], ['Constant', 'int', '2']]),
418 ([['ID', 'b'], ['Constant', 'int', '0']], ['ID', 't'])])
eli.benderskyf890a862010-10-30 12:13:23 +0200419
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300420 def test_enums(self):
421 e1 = "enum mycolor op;"
422 e1_type = self.parse(e1).ext[0].type.type
423
424 self.assertTrue(isinstance(e1_type, Enum))
425 self.assertEqual(e1_type.name, 'mycolor')
426 self.assertEqual(e1_type.values, None)
427
428 e2 = "enum mysize {large=20, small, medium} shoes;"
429 e2_type = self.parse(e2).ext[0].type.type
430
431 self.assertTrue(isinstance(e2_type, Enum))
432 self.assertEqual(e2_type.name, 'mysize')
433
434 e2_elist = e2_type.values
435 self.assertTrue(isinstance(e2_elist, EnumeratorList))
436
437 for e2_eval in e2_elist.enumerators:
438 self.assertTrue(isinstance(e2_eval, Enumerator))
439
440 self.assertEqual(e2_elist.enumerators[0].name, 'large')
441 self.assertEqual(e2_elist.enumerators[0].value.value, '20')
442 self.assertEqual(e2_elist.enumerators[2].name, 'medium')
443 self.assertEqual(e2_elist.enumerators[2].value, None)
444
445 # enum with trailing comma (C99 feature)
446 e3 = """
447 enum
448 {
449 red,
450 blue,
451 green,
452 } color;
453 """
454
455 e3_type = self.parse(e3).ext[0].type.type
456 self.assertTrue(isinstance(e3_type, Enum))
457 e3_elist = e3_type.values
458 self.assertTrue(isinstance(e3_elist, EnumeratorList))
459
460 for e3_eval in e3_elist.enumerators:
461 self.assertTrue(isinstance(e3_eval, Enumerator))
462
463 self.assertEqual(e3_elist.enumerators[0].name, 'red')
464 self.assertEqual(e3_elist.enumerators[0].value, None)
465 self.assertEqual(e3_elist.enumerators[1].name, 'blue')
466 self.assertEqual(e3_elist.enumerators[2].name, 'green')
467
468 def test_typedef(self):
469 # without typedef, error
470 s1 = """
471 node k;
472 """
473 self.assertRaises(ParseError, self.parse, s1)
474
475 # now with typedef, works
476 s2 = """
477 typedef void* node;
478 node k;
479 """
480 ps2 = self.parse(s2)
481 self.assertEqual(expand_decl(ps2.ext[0]),
482 ['Typedef', 'node',
483 ['PtrDecl',
484 ['TypeDecl', ['IdentifierType', ['void']]]]])
485
486 self.assertEqual(expand_decl(ps2.ext[1]),
487 ['Decl', 'k',
488 ['TypeDecl', ['IdentifierType', ['node']]]])
489
490 s3 = """
491 typedef int T;
492 typedef T *pT;
493
494 pT aa, bb;
495 """
496 ps3 = self.parse(s3)
497 self.assertEqual(expand_decl(ps3.ext[3]),
498 ['Decl', 'bb',
499 ['TypeDecl', ['IdentifierType', ['pT']]]])
500
501 s4 = '''
502 typedef char* __builtin_va_list;
503 typedef __builtin_va_list __gnuc_va_list;
504 '''
505 ps4 = self.parse(s4)
506 self.assertEqual(expand_decl(ps4.ext[1]),
507 ['Typedef', '__gnuc_va_list',
508 ['TypeDecl',
509 ['IdentifierType', ['__builtin_va_list']]]])
510
511 s5 = '''typedef struct tagHash Hash;'''
512 ps5 = self.parse(s5)
513 self.assertEqual(expand_decl(ps5.ext[0]),
514 ['Typedef', 'Hash', ['TypeDecl', ['Struct', 'tagHash', []]]])
515
516 def test_struct_union(self):
517 s1 = """
518 struct {
519 int id;
520 char* name;
521 } joe;
522 """
523
524 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
525 ['Decl', 'joe',
526 ['TypeDecl', ['Struct', None,
527 [ ['Decl', 'id',
528 ['TypeDecl',
529 ['IdentifierType', ['int']]]],
530 ['Decl', 'name',
531 ['PtrDecl',
532 ['TypeDecl',
533 ['IdentifierType', ['char']]]]]]]]])
534
535 s2 = """
536 struct node p;
537 """
538 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
539 ['Decl', 'p',
540 ['TypeDecl', ['Struct', 'node', []]]])
541
542 s21 = """
543 union pri ra;
544 """
545 self.assertEqual(expand_decl(self.parse(s21).ext[0]),
546 ['Decl', 'ra',
547 ['TypeDecl', ['Union', 'pri', []]]])
548
549 s3 = """
550 struct node* p;
551 """
552 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
553 ['Decl', 'p',
554 ['PtrDecl',
555 ['TypeDecl', ['Struct', 'node', []]]]])
556
557 s4 = """
558 struct node;
559 """
560 self.assertEqual(expand_decl(self.parse(s4).ext[0]),
561 ['Decl', None,
562 ['Struct', 'node', []]])
563
564 s5 = """
565 union
566 {
567 struct
568 {
569 int type;
570 } n;
571
572 struct
573 {
574 int type;
575 int intnode;
576 } ni;
577 } u;
578 """
579 self.assertEqual(expand_decl(self.parse(s5).ext[0]),
580 ['Decl', 'u',
581 ['TypeDecl',
582 ['Union', None,
583 [['Decl', 'n',
584 ['TypeDecl',
585 ['Struct', None,
586 [['Decl', 'type',
587 ['TypeDecl', ['IdentifierType', ['int']]]]]]]],
588 ['Decl', 'ni',
589 ['TypeDecl',
590 ['Struct', None,
591 [['Decl', 'type',
592 ['TypeDecl', ['IdentifierType', ['int']]]],
593 ['Decl', 'intnode',
594 ['TypeDecl', ['IdentifierType', ['int']]]]]]]]]]]])
595
596 s6 = """
597 typedef struct foo_tag
598 {
599 void* data;
600 } foo, *pfoo;
601 """
602 s6_ast = self.parse(s6)
603
604 self.assertEqual(expand_decl(s6_ast.ext[0]),
605 ['Typedef', 'foo',
606 ['TypeDecl',
607 ['Struct', 'foo_tag',
608 [['Decl', 'data',
609 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]])
610
611 self.assertEqual(expand_decl(s6_ast.ext[1]),
612 ['Typedef', 'pfoo',
613 ['PtrDecl',
614 ['TypeDecl',
615 ['Struct', 'foo_tag',
616 [['Decl', 'data',
617 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]]])
618
619 s7 = r"""
620 struct _on_exit_args {
621 void * _fnargs[32];
622 void * _dso_handle[32];
623
624 long _fntypes;
625 #line 77 "D:\eli\cpp_stuff\libc_include/sys/reent.h"
626
627 long _is_cxa;
628 };
629 """
630
631 s7_ast = self.parse(s7, filename='test.c')
632 self.assert_coord(s7_ast.ext[0].type.decls[2], 6, 'test.c')
633 self.assert_coord(s7_ast.ext[0].type.decls[3], 78,
634 r'D:\eli\cpp_stuff\libc_include/sys/reent.h')
635
636 s8 = """
637 typedef enum tagReturnCode {SUCCESS, FAIL} ReturnCode;
638
639 typedef struct tagEntry
640 {
641 char* key;
642 char* value;
643 } Entry;
644
645
646 typedef struct tagNode
647 {
648 Entry* entry;
649
650 struct tagNode* next;
651 } Node;
652
653 typedef struct tagHash
654 {
655 unsigned int table_size;
656
657 Node** heads;
658
659 } Hash;
660 """
661 s8_ast = self.parse(s8)
662 self.assertEqual(expand_decl(s8_ast.ext[3]),
663 ['Typedef', 'Hash',
664 ['TypeDecl', ['Struct', 'tagHash',
665 [['Decl', 'table_size',
666 ['TypeDecl', ['IdentifierType', ['int', 'unsigned']]]],
667 ['Decl', 'heads',
668 ['PtrDecl', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['Node']]]]]]]]]])
669
eli.bendersky697ecc52011-02-10 07:05:13 +0200670 def test_anonymous_struct_union(self):
671 s1 = """
672 union
673 {
674 union
675 {
676 int i;
677 long l;
678 };
679
680 struct
681 {
682 int type;
683 int intnode;
684 };
685 } u;
686 """
687
688 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
689 ['Decl', 'u',
690 ['TypeDecl',
691 ['Union', None,
692 [['Decl', None,
693 ['Union', None,
694 [['Decl', 'i',
695 ['TypeDecl',
696 ['IdentifierType', ['int']]]],
697 ['Decl', 'l',
698 ['TypeDecl',
699 ['IdentifierType', ['long']]]]]]],
700 ['Decl', None,
701 ['Struct', None,
702 [['Decl', 'type',
703 ['TypeDecl',
704 ['IdentifierType', ['int']]]],
705 ['Decl', 'intnode',
706 ['TypeDecl',
707 ['IdentifierType', ['int']]]]]]]]]]])
708
709 s2 = """
710 struct
711 {
712 int i;
713 union
714 {
715 int id;
716 char* name;
717 };
718 float f;
719 } joe;
720 """
721
722 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
723 ['Decl', 'joe',
724 ['TypeDecl',
725 ['Struct', None,
726 [['Decl', 'i',
727 ['TypeDecl',
728 ['IdentifierType', ['int']]]],
729 ['Decl', None,
730 ['Union', None,
731 [['Decl', 'id',
732 ['TypeDecl',
733 ['IdentifierType', ['int']]]],
734 ['Decl', 'name',
735 ['PtrDecl',
736 ['TypeDecl',
737 ['IdentifierType', ['char']]]]]]]],
738 ['Decl', 'f',
739 ['TypeDecl',
740 ['IdentifierType', ['float']]]]]]]])
741
742 # ISO/IEC 9899:201x Commitee Draft 2010-11-16, N1539
743 # section 6.7.2.1, par. 19, example 1
744 s3 = """
745 struct v {
746 union {
747 struct { int i, j; };
748 struct { long k, l; } w;
749 };
750 int m;
751 } v1;
752 """
753
754 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
755 ['Decl', 'v1',
756 ['TypeDecl',
757 ['Struct', 'v',
758 [['Decl', None,
759 ['Union', None,
760 [['Decl', None,
761 ['Struct', None,
762 [['Decl', 'i',
763 ['TypeDecl',
764 ['IdentifierType', ['int']]]],
765 ['Decl', 'j',
766 ['TypeDecl',
767 ['IdentifierType', ['int']]]]]]],
768 ['Decl', 'w',
769 ['TypeDecl',
770 ['Struct', None,
771 [['Decl', 'k',
772 ['TypeDecl',
773 ['IdentifierType', ['long']]]],
774 ['Decl', 'l',
775 ['TypeDecl',
776 ['IdentifierType', ['long']]]]]]]]]]],
777 ['Decl', 'm',
778 ['TypeDecl',
779 ['IdentifierType', ['int']]]]]]]])
780
eli.benderskydce29a02011-02-10 07:55:00 +0200781 s4 = """
782 struct v {
783 int i;
784 float;
785 } v2;"""
eli.bendersky6b011792011-06-22 17:50:56 +0300786 # just make sure this doesn't raise ParseError
787 self.parse(s4)
eli.benderskydce29a02011-02-10 07:55:00 +0200788
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200789 def test_struct_bitfields(self):
eli.bendersky38ed9a92010-10-09 09:29:59 +0200790 # a struct with two bitfields, one unnamed
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200791 s1 = """
792 struct {
793 int k:6;
794 int :2;
795 } joe;
796 """
797
798 parsed_struct = self.parse(s1).ext[0]
799
eli.bendersky38ed9a92010-10-09 09:29:59 +0200800 # We can see here the name of the decl for the unnamed bitfield is
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200801 # None, but expand_decl doesn't show bitfield widths
802 # ...
803 self.assertEqual(expand_decl(parsed_struct),
804 ['Decl', 'joe',
805 ['TypeDecl', ['Struct', None,
806 [ ['Decl', 'k',
807 ['TypeDecl',
808 ['IdentifierType', ['int']]]],
809 ['Decl', None,
810 ['TypeDecl',
811 ['IdentifierType', ['int']]]]]]]])
812
813 # ...
814 # so we test them manually
815 self.assertEqual(parsed_struct.type.type.decls[0].bitsize.value, '6')
816 self.assertEqual(parsed_struct.type.type.decls[1].bitsize.value, '2')
817
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300818 def test_tags_namespace(self):
819 """ Tests that the tags of structs/unions/enums reside in a separate namespace and
820 can be named after existing types.
821 """
822 s1 = """
823 typedef int tagEntry;
824
825 struct tagEntry
826 {
827 char* key;
828 char* value;
829 } Entry;
830 """
831
832 s1_ast = self.parse(s1)
833 self.assertEqual(expand_decl(s1_ast.ext[1]),
834 ['Decl', 'Entry',
835 ['TypeDecl', ['Struct', 'tagEntry',
836 [['Decl', 'key',
837 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
838 ['Decl', 'value',
839 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
840
841 s2 = """
842 struct tagEntry;
843
844 typedef struct tagEntry tagEntry;
845
846 struct tagEntry
847 {
848 char* key;
849 char* value;
850 } Entry;
851 """
852
853 s2_ast = self.parse(s2)
854 self.assertEqual(expand_decl(s2_ast.ext[2]),
855 ['Decl', 'Entry',
856 ['TypeDecl', ['Struct', 'tagEntry',
857 [['Decl', 'key',
858 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
859 ['Decl', 'value',
860 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
861
862 s3 = """
863 typedef int mytag;
864
865 enum mytag {ABC, CDE};
866 enum mytag joe;
867 """
868
869 s3_type = self.parse(s3).ext[1].type
870
871 self.assertTrue(isinstance(s3_type, Enum))
872 self.assertEqual(s3_type.name, 'mytag')
873
874 def test_multi_decls(self):
875 d1 = 'int a, b;'
876
877 self.assertEqual(self.get_decl(d1, 0),
878 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
879 self.assertEqual(self.get_decl(d1, 1),
880 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['int']]]])
881
882 d2 = 'char* p, notp, ar[4];'
883 self.assertEqual(self.get_decl(d2, 0),
884 ['Decl', 'p',
885 ['PtrDecl',
886 ['TypeDecl', ['IdentifierType', ['char']]]]])
887 self.assertEqual(self.get_decl(d2, 1),
888 ['Decl', 'notp', ['TypeDecl', ['IdentifierType', ['char']]]])
889 self.assertEqual(self.get_decl(d2, 2),
890 ['Decl', 'ar',
891 ['ArrayDecl', '4',
892 ['TypeDecl', ['IdentifierType', ['char']]]]])
893
894 def test_invalid_multiple_types_error(self):
895 bad = [
896 'int enum {ab, cd} fubr;',
897 'enum kid char brbr;']
898
899 for b in bad:
900 self.assertRaises(ParseError, self.parse, b)
901
902 def test_decl_inits(self):
903 d1 = 'int a = 16;'
eli.benderskyf890a862010-10-30 12:13:23 +0200904 #~ self.parse(d1).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300905 self.assertEqual(self.get_decl(d1),
906 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
907 self.assertEqual(self.get_decl_init(d1),
908 ['Constant', 'int', '16'])
909
910 d2 = 'long ar[] = {7, 8, 9};'
eli.benderskyf890a862010-10-30 12:13:23 +0200911 #~ self.parse(d2).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300912 self.assertEqual(self.get_decl(d2),
913 ['Decl', 'ar',
914 ['ArrayDecl', '',
915 ['TypeDecl', ['IdentifierType', ['long']]]]])
916 self.assertEqual(self.get_decl_init(d2),
917 [ ['Constant', 'int', '7'],
918 ['Constant', 'int', '8'],
eli.benderskyf890a862010-10-30 12:13:23 +0200919 ['Constant', 'int', '9']])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300920
921 d3 = 'char p = j;'
922 self.assertEqual(self.get_decl(d3),
923 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['char']]]])
924 self.assertEqual(self.get_decl_init(d3),
925 ['ID', 'j'])
926
927 d4 = "char x = 'c', *p = {0, 1, 2, {4, 5}, 6};"
928 self.assertEqual(self.get_decl(d4, 0),
929 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['char']]]])
930 self.assertEqual(self.get_decl_init(d4, 0),
931 ['Constant', 'char', "'c'"])
932 self.assertEqual(self.get_decl(d4, 1),
933 ['Decl', 'p',
934 ['PtrDecl',
935 ['TypeDecl', ['IdentifierType', ['char']]]]])
eli.benderskyf890a862010-10-30 12:13:23 +0200936
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300937 self.assertEqual(self.get_decl_init(d4, 1),
938 [ ['Constant', 'int', '0'],
939 ['Constant', 'int', '1'],
940 ['Constant', 'int', '2'],
eli.benderskyf890a862010-10-30 12:13:23 +0200941 [['Constant', 'int', '4'],
942 ['Constant', 'int', '5']],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300943 ['Constant', 'int', '6']])
eli.benderskyf890a862010-10-30 12:13:23 +0200944
945 def test_decl_named_inits(self):
946 d1 = 'int a = {.k = 16};'
947 self.assertEqual(self.get_decl_init(d1),
948 [( [['ID', 'k']],
949 ['Constant', 'int', '16'])])
950
951 d2 = 'int a = { [0].a = {1}, [1].a[0] = 2 };'
952 self.assertEqual(self.get_decl_init(d2),
953 [
954 ([['Constant', 'int', '0'], ['ID', 'a']],
955 [['Constant', 'int', '1']]),
956 ([['Constant', 'int', '1'], ['ID', 'a'], ['Constant', 'int', '0']],
957 ['Constant', 'int', '2'])])
958
959 d3 = 'int a = { .a = 1, .c = 3, 4, .b = 5};'
960 self.assertEqual(self.get_decl_init(d3),
961 [
962 ([['ID', 'a']], ['Constant', 'int', '1']),
963 ([['ID', 'c']], ['Constant', 'int', '3']),
964 ['Constant', 'int', '4'],
965 ([['ID', 'b']], ['Constant', 'int', '5'])])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300966
967 def test_function_definitions(self):
968 def parse_fdef(str):
969 return self.parse(str).ext[0]
970
971 def fdef_decl(fdef):
972 return expand_decl(fdef.decl)
973
974 f1 = parse_fdef('''
975 int factorial(int p)
976 {
977 return 3;
978 }
979 ''')
980
981 self.assertEqual(fdef_decl(f1),
982 ['Decl', 'factorial',
983 ['FuncDecl',
984 [['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]]],
985 ['TypeDecl', ['IdentifierType', ['int']]]]])
986
eli.benderskyef29ff92010-10-29 16:25:43 +0200987 self.assertEqual(type(f1.body.block_items[0]), Return)
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300988
989 f2 = parse_fdef('''
990 char* zzz(int p, char* c)
991 {
992 int a;
993 char b;
994
995 a = b + 2;
996 return 3;
997 }
998 ''')
999
1000 self.assertEqual(fdef_decl(f2),
1001 ['Decl', 'zzz',
1002 ['FuncDecl',
1003 [ ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]],
1004 ['Decl', 'c', ['PtrDecl',
1005 ['TypeDecl', ['IdentifierType', ['char']]]]]],
1006 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
1007
eli.benderskyef29ff92010-10-29 16:25:43 +02001008 self.assertEqual(list(map(type, f2.body.block_items)),
1009 [Decl, Decl, Assignment, Return])
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001010
1011 f3 = parse_fdef('''
1012 char* zzz(p, c)
1013 long p, *c;
1014 {
1015 int a;
1016 char b;
1017
1018 a = b + 2;
1019 return 3;
1020 }
1021 ''')
1022
1023 self.assertEqual(fdef_decl(f3),
1024 ['Decl', 'zzz',
1025 ['FuncDecl',
1026 [ ['ID', 'p'],
1027 ['ID', 'c']],
1028 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
1029
eli.benderskyef29ff92010-10-29 16:25:43 +02001030 self.assertEqual(list(map(type, f3.body.block_items)),
1031 [Decl, Decl, Assignment, Return])
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001032
1033 self.assertEqual(expand_decl(f3.param_decls[0]),
1034 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['long']]]])
1035 self.assertEqual(expand_decl(f3.param_decls[1]),
1036 ['Decl', 'c', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['long']]]]])
1037
eli.bendersky71540662010-07-03 12:58:52 +02001038 def test_unified_string_literals(self):
1039 # simple string, for reference
1040 d1 = self.get_decl_init('char* s = "hello";')
1041 self.assertEqual(d1, ['Constant', 'string', '"hello"'])
1042
1043 d2 = self.get_decl_init('char* s = "hello" " world";')
1044 self.assertEqual(d2, ['Constant', 'string', '"hello world"'])
1045
1046 # the test case from issue 6
1047 d3 = self.parse(r'''
1048 int main() {
1049 fprintf(stderr,
1050 "Wrong Params?\n"
1051 "Usage:\n"
1052 "%s <binary_file_path>\n",
1053 argv[0]
1054 );
1055 }
1056 ''')
1057
1058 self.assertEqual(
eli.benderskyef29ff92010-10-29 16:25:43 +02001059 d3.ext[0].body.block_items[0].args.exprs[1].value,
eli.bendersky71540662010-07-03 12:58:52 +02001060 r'"Wrong Params?\nUsage:\n%s <binary_file_path>\n"')
eli.bendersky4a89f112010-07-05 06:02:03 +02001061
1062 d4 = self.get_decl_init('char* s = "" "foobar";')
1063 self.assertEqual(d4, ['Constant', 'string', '"foobar"'])
1064
1065 d5 = self.get_decl_init(r'char* s = "foo\"" "bar";')
1066 self.assertEqual(d5, ['Constant', 'string', r'"foo\"bar"'])
eli.bendersky71540662010-07-03 12:58:52 +02001067
eli.bendersky79d5cf62010-10-29 13:33:52 +02001068 def test_inline_specifier(self):
1069 ps2 = self.parse('static inline void inlinefoo(void);')
1070 self.assertEqual(ps2.ext[0].funcspec, ['inline'])
eli.bendersky2e907fa2010-10-29 15:51:07 +02001071
1072 # variable length array
1073 def test_vla(self):
1074 ps2 = self.parse(r'''
1075 int main() {
1076 int size;
1077 int var[size = 5];
1078
1079 int var2[*];
1080 }
1081 ''')
eli.benderskyef29ff92010-10-29 16:25:43 +02001082 self.failUnless(isinstance(ps2.ext[0].body.block_items[1].type.dim, Assignment))
1083 self.failUnless(isinstance(ps2.ext[0].body.block_items[2].type.dim, ID))
eli.bendersky79d5cf62010-10-29 13:33:52 +02001084
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001085
eli.bendersky85d2e732011-05-20 19:47:26 +03001086class TestCParser_whole_code(TestCParser_base):
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001087 """ Testing of parsing whole chunks of code.
1088
1089 Since I don't want to rely on the structure of ASTs too
1090 much, most of these tests are implemented with visitors.
1091 """
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001092 # A simple helper visitor that lists the values of all the
1093 # Constant nodes it sees.
1094 #
1095 class ConstantVisitor(NodeVisitor):
1096 def __init__(self):
1097 self.values = []
1098
1099 def visit_Constant(self, node):
1100 self.values.append(node.value)
1101
1102 # This visitor counts the amount of references to the ID
1103 # with the name provided to it in the constructor.
1104 #
1105 class IDNameCounter(NodeVisitor):
1106 def __init__(self, name):
1107 self.name = name
1108 self.nrefs = 0
1109
1110 def visit_ID(self, node):
1111 if node.name == self.name:
1112 self.nrefs += 1
1113
1114 # Counts the amount of nodes of a given class
1115 #
1116 class NodeKlassCounter(NodeVisitor):
1117 def __init__(self, node_klass):
1118 self.klass = node_klass
1119 self.n = 0
1120
1121 def generic_visit(self, node):
1122 if node.__class__ == self.klass:
1123 self.n += 1
1124
1125 NodeVisitor.generic_visit(self, node)
1126
1127 def assert_all_Constants(self, code, constants):
1128 """ Asserts that the list of all Constant values (by
1129 'preorder' appearance) in the chunk of code is as
1130 given.
1131 """
eli.benderskyed890492010-06-25 08:25:55 +03001132 if isinstance(code, str):
1133 parsed = self.parse(code)
1134 else:
1135 parsed = code
1136
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001137 cv = self.ConstantVisitor()
1138 cv.visit(parsed)
1139 self.assertEqual(cv.values, constants)
1140
1141 def assert_num_ID_refs(self, code, name, num):
1142 """ Asserts the number of references to the ID with
1143 the given name.
1144 """
1145 if isinstance(code, str):
1146 parsed = self.parse(code)
1147 else:
1148 parsed = code
1149
1150 iv = self.IDNameCounter(name)
1151 iv.visit(parsed)
1152 self.assertEqual(iv.nrefs, num)
1153
1154 def assert_num_klass_nodes(self, code, klass, num):
1155 """ Asserts the amount of klass nodes in the code.
1156 """
1157 if isinstance(code, str):
1158 parsed = self.parse(code)
1159 else:
1160 parsed = code
1161
1162 cv = self.NodeKlassCounter(klass)
1163 cv.visit(parsed)
1164 self.assertEqual(cv.n, num)
1165
1166 def test_expressions(self):
1167 e1 = '''int k = (r + 10.0) >> 6 + 8 << (3 & 0x14);'''
1168 self.assert_all_Constants(e1, ['10.0', '6', '8', '3', '0x14'])
1169
1170 e2 = r'''char n = '\n', *prefix = "st_";'''
1171 self.assert_all_Constants(e2, [r"'\n'", '"st_"'])
1172
1173 def test_statements(self):
1174 s1 = r'''
1175 void foo(){
1176 if (sp == 1)
1177 if (optind >= argc ||
1178 argv[optind][0] != '-' || argv[optind][1] == '\0')
1179 return -1;
1180 else if (strcmp(argv[optind], "--") == 0) {
1181 optind++;
1182 return -1;
1183 }
1184 }
1185 '''
1186
1187 self.assert_all_Constants(s1,
1188 ['1', '0', r"'-'", '1', r"'\0'", '1', r'"--"', '0', '1'])
1189
1190 ps1 = self.parse(s1)
1191 self.assert_num_ID_refs(ps1, 'argv', 3)
1192 self.assert_num_ID_refs(ps1, 'optind', 5)
1193
1194 self.assert_num_klass_nodes(ps1, If, 3)
1195 self.assert_num_klass_nodes(ps1, Return, 2)
1196 self.assert_num_klass_nodes(ps1, FuncCall, 1) # strcmp
1197 self.assert_num_klass_nodes(ps1, BinaryOp, 7)
1198
1199 # In the following code, Hash and Node were defined as
1200 # int to pacify the parser that sees they're used as
1201 # types
1202 #
1203 s2 = r'''
1204 typedef int Hash, Node;
1205
1206 void HashDestroy(Hash* hash)
1207 {
1208 unsigned int i;
1209
1210 if (hash == NULL)
1211 return;
1212
1213 for (i = 0; i < hash->table_size; ++i)
1214 {
1215 Node* temp = hash->heads[i];
1216
1217 while (temp != NULL)
1218 {
1219 Node* temp2 = temp;
1220
1221 free(temp->entry->key);
1222 free(temp->entry->value);
1223 free(temp->entry);
1224
1225 temp = temp->next;
1226
1227 free(temp2);
1228 }
1229 }
1230
1231 free(hash->heads);
1232 hash->heads = NULL;
1233
1234 free(hash);
1235 }
1236 '''
1237
1238 ps2 = self.parse(s2)
1239 self.assert_num_klass_nodes(ps2, FuncCall, 6)
1240 self.assert_num_klass_nodes(ps2, FuncDef, 1)
1241 self.assert_num_klass_nodes(ps2, For, 1)
1242 self.assert_num_klass_nodes(ps2, While, 1)
1243 self.assert_num_klass_nodes(ps2, StructRef, 10)
1244
1245 # declarations don't count
1246 self.assert_num_ID_refs(ps2, 'hash', 6)
1247 self.assert_num_ID_refs(ps2, 'i', 4)
eli.benderskyed890492010-06-25 08:25:55 +03001248
1249 s3 = r'''
1250 void x(void) {
1251 int a, b;
1252 if (a < b)
1253 do {
1254 a = 0;
1255 } while (0);
1256 else if (a == b) {
1257 a = 1;
1258 }
1259 }
1260 '''
1261
1262 ps3 = self.parse(s3)
1263 self.assert_num_klass_nodes(ps3, DoWhile, 1)
1264 self.assert_num_ID_refs(ps3, 'a', 4)
1265 self.assert_all_Constants(ps3, ['0', '0', '1'])
eli.bendersky145890d2010-10-29 12:02:32 +02001266
1267 def test_for_statement(self):
1268 s2 = r'''
1269 void x(void)
1270 {
1271 int i;
1272 for (i = 0; i < 5; ++i) {
1273 x = 50;
1274 }
1275 }
1276 '''
1277 ps2 = self.parse(s2)
1278 self.assert_num_klass_nodes(ps2, For, 1)
1279 # here there are 3 refs to 'i' since the declaration doesn't count as
1280 # a ref in the visitor
1281 #
1282 self.assert_num_ID_refs(ps2, 'i', 3)
eli.benderskyed890492010-06-25 08:25:55 +03001283
eli.bendersky145890d2010-10-29 12:02:32 +02001284 s3 = r'''
1285 void x(void)
1286 {
1287 for (int i = 0; i < 5; ++i) {
1288 x = 50;
1289 }
1290 }
1291 '''
1292 ps3 = self.parse(s3)
eli.bendersky145890d2010-10-29 12:02:32 +02001293 self.assert_num_klass_nodes(ps3, For, 1)
1294 # here there are 2 refs to 'i' since the declaration doesn't count as
1295 # a ref in the visitor
1296 #
1297 self.assert_num_ID_refs(ps3, 'i', 2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001298
1299 def test_whole_file(self):
1300 # See how pycparser handles a whole, real C file.
1301 #
1302 filename = 'c_files/memmgr_with_h.c'
1303 code = open(filename, 'rU').read()
1304 p = self.parse(code)
1305
1306 self.assert_num_klass_nodes(p, FuncDef, 5)
1307
1308 # each FuncDef also has a FuncDecl. 4 declarations
1309 # + 5 definitions, overall 9
1310 self.assert_num_klass_nodes(p, FuncDecl, 9)
1311
1312 self.assert_num_klass_nodes(p, Typedef, 4)
1313
1314 self.assertEqual(p.ext[4].coord.line, 88)
1315 self.assertEqual(p.ext[4].coord.file, "./memmgr.h")
1316
1317 self.assertEqual(p.ext[6].coord.line, 10)
1318 self.assertEqual(p.ext[6].coord.file, "memmgr.c")
1319
1320 def test_whole_file_with_stdio(self):
1321 # Parse a whole file with stdio.h included by cpp
1322 #
1323 filename = 'c_files/cppd_with_stdio_h.c'
1324 code = open(filename, 'rU').read()
1325 p = self.parse(code)
1326
1327 self.failUnless(isinstance(p.ext[0], Typedef))
1328 self.assertEqual(p.ext[0].coord.line, 213)
1329 self.assertEqual(p.ext[0].coord.file, "D:\eli\cpp_stuff\libc_include/stddef.h")
1330
1331 self.failUnless(isinstance(p.ext[-1], FuncDef))
1332 self.assertEqual(p.ext[-1].coord.line, 15)
1333 self.assertEqual(p.ext[-1].coord.file, "example_c_file.c")
1334
1335 self.failUnless(isinstance(p.ext[-8], Typedef))
1336 self.failUnless(isinstance(p.ext[-8].type, TypeDecl))
1337 self.assertEqual(p.ext[-8].name, 'cookie_io_functions_t')
eli.bendersky85d2e732011-05-20 19:47:26 +03001338
1339
1340class TestCParser_typenames(TestCParser_base):
1341 """ Test issues related to the typedef-name problem.
1342 """
1343 def test_innerscope_typedef(self):
1344 # should fail since TT is not a type in bar
1345 s1 = r'''
1346 void foo() {
1347 typedef char TT;
1348 TT x;
1349 }
1350 void bar() {
1351 TT y;
1352 }
1353 '''
1354 self.assertRaises(ParseError, self.parse, s1)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001355
eli.bendersky85d2e732011-05-20 19:47:26 +03001356 # should succeed since TT is not a type in bar
1357 s2 = r'''
1358 void foo() {
1359 typedef char TT;
1360 TT x;
1361 }
1362 void bar() {
1363 unsigned TT;
1364 }
1365 '''
1366 self.failUnless(isinstance(self.parse(s2), FileAST))
1367
1368
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001369
1370if __name__ == '__main__':
1371 #~ suite = unittest.TestLoader().loadTestsFromNames(
1372 #~ ['test_c_parser.TestCParser_fundamentals.test_typedef'])
1373
1374 #~ suite = unittest.TestLoader().loadTestsFromNames(
1375 #~ ['test_c_parser.TestCParser_whole_code.test_whole_file_with_stdio'])
1376
1377 #~ suite = unittest.TestLoader().loadTestsFromTestCase(
1378 #~ TestCParser_whole_code)
1379
1380 #~ unittest.TextTestRunner(verbosity=2).run(suite)
1381 unittest.main()