blob: 75f66366d118e9e1369267e39012adb5c9065a61 [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)
eli.bendersky43cf0b22011-10-19 05:56:15 +0200110
111 # empty file
112 t2 = self.parse('')
113 self.failUnless(isinstance(t2, FileAST))
114 self.assertEqual(len(t2.ext), 0)
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300115
eli.bendersky38165b72011-02-04 08:13:39 +0200116 def test_empty_toplevel_decl(self):
117 code = 'int foo;;'
118 t = self.parse(code)
119 self.failUnless(isinstance(t, FileAST))
120 self.assertEqual(len(t.ext), 1)
121 self.assertEqual(self.get_decl(code),
122 ['Decl', 'foo',
123 ['TypeDecl', ['IdentifierType', ['int']]]])
124
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300125 def assert_coord(self, node, line, file=None):
126 self.assertEqual(node.coord.line, line)
127 if file:
128 self.assertEqual(node.coord.file, file)
129
130 def test_coords(self):
eli.bendersky38165b72011-02-04 08:13:39 +0200131 """ Tests the "coordinates" of parsed elements - file
132 name and line numbers, with modification insterted by
133 #line directives.
134 """
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300135 self.assert_coord(self.parse('int a;').ext[0], 1)
136
137 t1 = """
138 int a;
139 int b;\n\n
140 int c;
141 """
142 f1 = self.parse(t1, filename='test.c')
143 self.assert_coord(f1.ext[0], 2, 'test.c')
144 self.assert_coord(f1.ext[1], 3, 'test.c')
145 self.assert_coord(f1.ext[2], 6, 'test.c')
146
147 t1_1 = '''
148 int main() {
149 k = p;
150 printf("%d", b);
151 return 0;
152 }'''
153 f1_1 = self.parse(t1_1, filename='test.c')
eli.benderskyef29ff92010-10-29 16:25:43 +0200154 self.assert_coord(f1_1.ext[0].body.block_items[0], 3, 'test.c')
155 self.assert_coord(f1_1.ext[0].body.block_items[1], 4, 'test.c')
eli.benderskyfc96e5e2011-03-04 09:51:23 +0200156
157 t1_2 = '''
158 int main () {
159 int p = (int) k;
160 }'''
161 f1_2 = self.parse(t1_2, filename='test.c')
162 # make sure that the Cast has a coord (issue 23)
163 self.assert_coord(f1_2.ext[0].body.block_items[0].init, 3, 'test.c')
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300164
165 t2 = """
166 #line 99
167 int c;
168 """
169 self.assert_coord(self.parse(t2).ext[0], 99)
170
171 t3 = """
172 int dsf;
173 char p;
174 #line 3000 "in.h"
175 char d;
176 """
177 f3 = self.parse(t3, filename='test.c')
178 self.assert_coord(f3.ext[0], 2, 'test.c')
179 self.assert_coord(f3.ext[1], 3, 'test.c')
180 self.assert_coord(f3.ext[2], 3000, 'in.h')
181
182 t4 = """
183 #line 20 "restore.h"
184 int maydler(char);
185
186 #line 30 "includes/daween.ph"
187 long j, k;
188
189 #line 50000
190 char* ro;
191 """
192 f4 = self.parse(t4, filename='myb.c')
193 self.assert_coord(f4.ext[0], 20, 'restore.h')
194 self.assert_coord(f4.ext[1], 30, 'includes/daween.ph')
195 self.assert_coord(f4.ext[2], 30, 'includes/daween.ph')
196 self.assert_coord(f4.ext[3], 50000, 'includes/daween.ph')
197
198 t5 = """
199 int
200 #line 99
201 c;
202 """
203 self.assert_coord(self.parse(t5).ext[0], 99)
204
205 def test_simple_decls(self):
206 self.assertEqual(self.get_decl('int a;'),
207 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
208
209 self.assertEqual(self.get_decl('unsigned int a;'),
210 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int', 'unsigned']]]])
211
eli.benderskyaffe0322011-09-24 06:16:55 +0300212 self.assertEqual(self.get_decl('_Bool a;'),
213 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['_Bool']]]])
214
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300215 self.assertEqual(self.get_decl('char* string;'),
216 ['Decl', 'string',
217 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]])
218
219 self.assertEqual(self.get_decl('long ar[15];'),
220 ['Decl', 'ar',
221 ['ArrayDecl', '15',
222 ['TypeDecl', ['IdentifierType', ['long']]]]])
eli.bendersky98f45372010-10-30 09:46:29 +0200223
224 self.assertEqual(self.get_decl('long long ar[15];'),
225 ['Decl', 'ar',
226 ['ArrayDecl', '15',
eli.benderskyf890a862010-10-30 12:13:23 +0200227 ['TypeDecl', ['IdentifierType', ['long', 'long']]]]])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300228
229 self.assertEqual(self.get_decl('unsigned ar[];'),
230 ['Decl', 'ar',
231 ['ArrayDecl', '',
232 ['TypeDecl', ['IdentifierType', ['unsigned']]]]])
233
234 self.assertEqual(self.get_decl('int strlen(char* s);'),
235 ['Decl', 'strlen',
236 ['FuncDecl',
237 [['Decl', 's',
238 ['PtrDecl',
239 ['TypeDecl', ['IdentifierType', ['char']]]]]],
240 ['TypeDecl', ['IdentifierType', ['int']]]]])
241
242 self.assertEqual(self.get_decl('int strcmp(char* s1, char* s2);'),
243 ['Decl', 'strcmp',
244 ['FuncDecl',
245 [ ['Decl', 's1',
246 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
247 ['Decl', 's2',
248 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]
249 ],
250 ['TypeDecl', ['IdentifierType', ['int']]]]])
251
252 def test_nested_decls(self): # the fun begins
253 self.assertEqual(self.get_decl('char** ar2D;'),
254 ['Decl', 'ar2D',
255 ['PtrDecl', ['PtrDecl',
256 ['TypeDecl', ['IdentifierType', ['char']]]]]])
257
258 self.assertEqual(self.get_decl('int (*a)[1][2];'),
259 ['Decl', 'a',
260 ['PtrDecl',
261 ['ArrayDecl', '1',
262 ['ArrayDecl', '2',
263 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
264
265 self.assertEqual(self.get_decl('int *a[1][2];'),
266 ['Decl', 'a',
267 ['ArrayDecl', '1',
268 ['ArrayDecl', '2',
269 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['int']]]]]]])
270
271 self.assertEqual(self.get_decl('char ***ar3D[40];'),
272 ['Decl', 'ar3D',
273 ['ArrayDecl', '40',
274 ['PtrDecl', ['PtrDecl', ['PtrDecl',
275 ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
276
277 self.assertEqual(self.get_decl('char (***ar3D)[40];'),
278 ['Decl', 'ar3D',
279 ['PtrDecl', ['PtrDecl', ['PtrDecl',
280 ['ArrayDecl', '40', ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
281
282 self.assertEqual(self.get_decl('int (*x[4])(char, int);'),
283 ['Decl', 'x',
284 ['ArrayDecl', '4',
285 ['PtrDecl',
286 ['FuncDecl',
287 [ ['Typename', ['TypeDecl', ['IdentifierType', ['char']]]],
288 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
289 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
290
291 self.assertEqual(self.get_decl('char *(*(**foo [][8])())[];'),
292 ['Decl', 'foo',
293 ['ArrayDecl', '',
294 ['ArrayDecl', '8',
295 ['PtrDecl', ['PtrDecl',
296 ['FuncDecl',
297 [],
298 ['PtrDecl',
299 ['ArrayDecl', '',
300 ['PtrDecl',
301 ['TypeDecl',
302 ['IdentifierType', ['char']]]]]]]]]]]])
303
304 # explore named and unnamed function pointer parameters,
305 # with and without qualifiers
306 #
307
308 # unnamed w/o quals
309 self.assertEqual(self.get_decl('int (*k)(int);'),
310 ['Decl', 'k',
311 ['PtrDecl',
312 ['FuncDecl',
313 [['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
314 ['TypeDecl', ['IdentifierType', ['int']]]]]])
315
316 # unnamed w/ quals
317 self.assertEqual(self.get_decl('int (*k)(const int);'),
318 ['Decl', 'k',
319 ['PtrDecl',
320 ['FuncDecl',
321 [['Typename', ['const'], ['TypeDecl', ['IdentifierType', ['int']]]]],
322 ['TypeDecl', ['IdentifierType', ['int']]]]]])
323
324 # named w/o quals
325 self.assertEqual(self.get_decl('int (*k)(int q);'),
326 ['Decl', 'k',
327 ['PtrDecl',
328 ['FuncDecl',
329 [['Decl', 'q', ['TypeDecl', ['IdentifierType', ['int']]]]],
330 ['TypeDecl', ['IdentifierType', ['int']]]]]])
331
332 # named w/ quals
333 self.assertEqual(self.get_decl('int (*k)(const volatile int q);'),
334 ['Decl', 'k',
335 ['PtrDecl',
336 ['FuncDecl',
337 [['Decl', ['volatile', 'const'], 'q',
338 ['TypeDecl', ['IdentifierType', ['int']]]]],
339 ['TypeDecl', ['IdentifierType', ['int']]]]]])
340
eli.bendersky79d5cf62010-10-29 13:33:52 +0200341 # restrict qualifier
342 self.assertEqual(self.get_decl('int (*k)(restrict int* q);'),
343 ['Decl', 'k',
344 ['PtrDecl',
345 ['FuncDecl',
346 [['Decl', ['restrict'], 'q',
347 ['PtrDecl',
348 ['TypeDecl', ['IdentifierType', ['int']]]]]],
349 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300350
351 def test_qualifiers_storage_specifiers(self):
352 def assert_qs(txt, index, quals, storage):
353 d = self.parse(txt).ext[index]
354 self.assertEqual(d.quals, quals)
355 self.assertEqual(d.storage, storage)
356
357 assert_qs("extern int p;", 0, [], ['extern'])
358 assert_qs("const long p = 6;", 0, ['const'], [])
359
360 d1 = "static const int p, q, r;"
361 for i in range(3):
362 assert_qs(d1, i, ['const'], ['static'])
363
364 d2 = "static char * const p;"
365 assert_qs(d2, 0, [], ['static'])
366 pdecl = self.parse(d2).ext[0].type
367 self.failUnless(isinstance(pdecl, PtrDecl))
368 self.assertEqual(pdecl.quals, ['const'])
369
370 def test_sizeof(self):
371 e = """
372 void foo()
373 {
374 int a = sizeof k;
375 int b = sizeof(int);
eli.benderskyc51e1d32011-02-04 08:52:33 +0200376 int c = sizeof(int**);;
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300377
378 char* p = "just to make sure this parses w/o error...";
379 int d = sizeof(int());
380 }
381 """
382 compound = self.parse(e).ext[0].body
383
eli.benderskyef29ff92010-10-29 16:25:43 +0200384 s1 = compound.block_items[0].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300385 self.assertTrue(isinstance(s1, UnaryOp))
386 self.assertEqual(s1.op, 'sizeof')
387 self.assertTrue(isinstance(s1.expr, ID))
388 self.assertEqual(s1.expr.name, 'k')
389
eli.benderskyef29ff92010-10-29 16:25:43 +0200390 s2 = compound.block_items[1].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300391 self.assertEqual(expand_decl(s2.expr),
392 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]])
393
eli.benderskyef29ff92010-10-29 16:25:43 +0200394 s3 = compound.block_items[2].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300395 self.assertEqual(expand_decl(s3.expr),
396 ['Typename',
397 ['PtrDecl',
398 ['PtrDecl',
399 ['TypeDecl',
400 ['IdentifierType', ['int']]]]]])
401
eli.bendersky9f481562010-10-30 15:50:47 +0200402 # The C99 compound literal feature
403 #
eli.benderskyf890a862010-10-30 12:13:23 +0200404 def test_compound_literals(self):
eli.bendersky9f481562010-10-30 15:50:47 +0200405 ps1 = self.parse(r'''
eli.benderskyf890a862010-10-30 12:13:23 +0200406 void foo() {
eli.bendersky9f481562010-10-30 15:50:47 +0200407 p = (long long){k};
408 tc = (struct jk){.a = {1, 2}, .b[0] = t};
409 }''')
eli.benderskyf890a862010-10-30 12:13:23 +0200410
eli.bendersky9f481562010-10-30 15:50:47 +0200411 compound = ps1.ext[0].body.block_items[0].rvalue
412 self.assertEqual(expand_decl(compound.type),
413 ['Typename', ['TypeDecl', ['IdentifierType', ['long', 'long']]]])
414 self.assertEqual(expand_init(compound.init),
415 [['ID', 'k']])
416
417 compound = ps1.ext[0].body.block_items[1].rvalue
418 self.assertEqual(expand_decl(compound.type),
419 ['Typename', ['TypeDecl', ['Struct', 'jk', []]]])
420 self.assertEqual(expand_init(compound.init),
421 [
422 ([['ID', 'a']], [['Constant', 'int', '1'], ['Constant', 'int', '2']]),
423 ([['ID', 'b'], ['Constant', 'int', '0']], ['ID', 't'])])
eli.benderskyf890a862010-10-30 12:13:23 +0200424
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300425 def test_enums(self):
426 e1 = "enum mycolor op;"
427 e1_type = self.parse(e1).ext[0].type.type
428
429 self.assertTrue(isinstance(e1_type, Enum))
430 self.assertEqual(e1_type.name, 'mycolor')
431 self.assertEqual(e1_type.values, None)
432
433 e2 = "enum mysize {large=20, small, medium} shoes;"
434 e2_type = self.parse(e2).ext[0].type.type
435
436 self.assertTrue(isinstance(e2_type, Enum))
437 self.assertEqual(e2_type.name, 'mysize')
438
439 e2_elist = e2_type.values
440 self.assertTrue(isinstance(e2_elist, EnumeratorList))
441
442 for e2_eval in e2_elist.enumerators:
443 self.assertTrue(isinstance(e2_eval, Enumerator))
444
445 self.assertEqual(e2_elist.enumerators[0].name, 'large')
446 self.assertEqual(e2_elist.enumerators[0].value.value, '20')
447 self.assertEqual(e2_elist.enumerators[2].name, 'medium')
448 self.assertEqual(e2_elist.enumerators[2].value, None)
449
450 # enum with trailing comma (C99 feature)
451 e3 = """
452 enum
453 {
454 red,
455 blue,
456 green,
457 } color;
458 """
459
460 e3_type = self.parse(e3).ext[0].type.type
461 self.assertTrue(isinstance(e3_type, Enum))
462 e3_elist = e3_type.values
463 self.assertTrue(isinstance(e3_elist, EnumeratorList))
464
465 for e3_eval in e3_elist.enumerators:
466 self.assertTrue(isinstance(e3_eval, Enumerator))
467
468 self.assertEqual(e3_elist.enumerators[0].name, 'red')
469 self.assertEqual(e3_elist.enumerators[0].value, None)
470 self.assertEqual(e3_elist.enumerators[1].name, 'blue')
471 self.assertEqual(e3_elist.enumerators[2].name, 'green')
472
473 def test_typedef(self):
474 # without typedef, error
475 s1 = """
476 node k;
477 """
478 self.assertRaises(ParseError, self.parse, s1)
479
480 # now with typedef, works
481 s2 = """
482 typedef void* node;
483 node k;
484 """
485 ps2 = self.parse(s2)
486 self.assertEqual(expand_decl(ps2.ext[0]),
487 ['Typedef', 'node',
488 ['PtrDecl',
489 ['TypeDecl', ['IdentifierType', ['void']]]]])
490
491 self.assertEqual(expand_decl(ps2.ext[1]),
492 ['Decl', 'k',
493 ['TypeDecl', ['IdentifierType', ['node']]]])
494
495 s3 = """
496 typedef int T;
497 typedef T *pT;
498
499 pT aa, bb;
500 """
501 ps3 = self.parse(s3)
502 self.assertEqual(expand_decl(ps3.ext[3]),
503 ['Decl', 'bb',
504 ['TypeDecl', ['IdentifierType', ['pT']]]])
505
506 s4 = '''
507 typedef char* __builtin_va_list;
508 typedef __builtin_va_list __gnuc_va_list;
509 '''
510 ps4 = self.parse(s4)
511 self.assertEqual(expand_decl(ps4.ext[1]),
512 ['Typedef', '__gnuc_va_list',
513 ['TypeDecl',
514 ['IdentifierType', ['__builtin_va_list']]]])
515
516 s5 = '''typedef struct tagHash Hash;'''
517 ps5 = self.parse(s5)
518 self.assertEqual(expand_decl(ps5.ext[0]),
519 ['Typedef', 'Hash', ['TypeDecl', ['Struct', 'tagHash', []]]])
520
521 def test_struct_union(self):
522 s1 = """
523 struct {
524 int id;
525 char* name;
526 } joe;
527 """
528
529 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
530 ['Decl', 'joe',
531 ['TypeDecl', ['Struct', None,
532 [ ['Decl', 'id',
533 ['TypeDecl',
534 ['IdentifierType', ['int']]]],
535 ['Decl', 'name',
536 ['PtrDecl',
537 ['TypeDecl',
538 ['IdentifierType', ['char']]]]]]]]])
539
540 s2 = """
541 struct node p;
542 """
543 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
544 ['Decl', 'p',
545 ['TypeDecl', ['Struct', 'node', []]]])
546
547 s21 = """
548 union pri ra;
549 """
550 self.assertEqual(expand_decl(self.parse(s21).ext[0]),
551 ['Decl', 'ra',
552 ['TypeDecl', ['Union', 'pri', []]]])
553
554 s3 = """
555 struct node* p;
556 """
557 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
558 ['Decl', 'p',
559 ['PtrDecl',
560 ['TypeDecl', ['Struct', 'node', []]]]])
561
562 s4 = """
563 struct node;
564 """
565 self.assertEqual(expand_decl(self.parse(s4).ext[0]),
566 ['Decl', None,
567 ['Struct', 'node', []]])
568
569 s5 = """
570 union
571 {
572 struct
573 {
574 int type;
575 } n;
576
577 struct
578 {
579 int type;
580 int intnode;
581 } ni;
582 } u;
583 """
584 self.assertEqual(expand_decl(self.parse(s5).ext[0]),
585 ['Decl', 'u',
586 ['TypeDecl',
587 ['Union', None,
588 [['Decl', 'n',
589 ['TypeDecl',
590 ['Struct', None,
591 [['Decl', 'type',
592 ['TypeDecl', ['IdentifierType', ['int']]]]]]]],
593 ['Decl', 'ni',
594 ['TypeDecl',
595 ['Struct', None,
596 [['Decl', 'type',
597 ['TypeDecl', ['IdentifierType', ['int']]]],
598 ['Decl', 'intnode',
599 ['TypeDecl', ['IdentifierType', ['int']]]]]]]]]]]])
600
601 s6 = """
602 typedef struct foo_tag
603 {
604 void* data;
605 } foo, *pfoo;
606 """
607 s6_ast = self.parse(s6)
608
609 self.assertEqual(expand_decl(s6_ast.ext[0]),
610 ['Typedef', 'foo',
611 ['TypeDecl',
612 ['Struct', 'foo_tag',
613 [['Decl', 'data',
614 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]])
615
616 self.assertEqual(expand_decl(s6_ast.ext[1]),
617 ['Typedef', 'pfoo',
618 ['PtrDecl',
619 ['TypeDecl',
620 ['Struct', 'foo_tag',
621 [['Decl', 'data',
622 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]]])
623
624 s7 = r"""
625 struct _on_exit_args {
626 void * _fnargs[32];
627 void * _dso_handle[32];
628
629 long _fntypes;
630 #line 77 "D:\eli\cpp_stuff\libc_include/sys/reent.h"
631
632 long _is_cxa;
633 };
634 """
635
636 s7_ast = self.parse(s7, filename='test.c')
637 self.assert_coord(s7_ast.ext[0].type.decls[2], 6, 'test.c')
638 self.assert_coord(s7_ast.ext[0].type.decls[3], 78,
639 r'D:\eli\cpp_stuff\libc_include/sys/reent.h')
640
641 s8 = """
642 typedef enum tagReturnCode {SUCCESS, FAIL} ReturnCode;
643
644 typedef struct tagEntry
645 {
646 char* key;
647 char* value;
648 } Entry;
649
650
651 typedef struct tagNode
652 {
653 Entry* entry;
654
655 struct tagNode* next;
656 } Node;
657
658 typedef struct tagHash
659 {
660 unsigned int table_size;
661
662 Node** heads;
663
664 } Hash;
665 """
666 s8_ast = self.parse(s8)
667 self.assertEqual(expand_decl(s8_ast.ext[3]),
668 ['Typedef', 'Hash',
669 ['TypeDecl', ['Struct', 'tagHash',
670 [['Decl', 'table_size',
671 ['TypeDecl', ['IdentifierType', ['int', 'unsigned']]]],
672 ['Decl', 'heads',
673 ['PtrDecl', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['Node']]]]]]]]]])
674
eli.bendersky697ecc52011-02-10 07:05:13 +0200675 def test_anonymous_struct_union(self):
676 s1 = """
677 union
678 {
679 union
680 {
681 int i;
682 long l;
683 };
684
685 struct
686 {
687 int type;
688 int intnode;
689 };
690 } u;
691 """
692
693 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
694 ['Decl', 'u',
695 ['TypeDecl',
696 ['Union', None,
697 [['Decl', None,
698 ['Union', None,
699 [['Decl', 'i',
700 ['TypeDecl',
701 ['IdentifierType', ['int']]]],
702 ['Decl', 'l',
703 ['TypeDecl',
704 ['IdentifierType', ['long']]]]]]],
705 ['Decl', None,
706 ['Struct', None,
707 [['Decl', 'type',
708 ['TypeDecl',
709 ['IdentifierType', ['int']]]],
710 ['Decl', 'intnode',
711 ['TypeDecl',
712 ['IdentifierType', ['int']]]]]]]]]]])
713
714 s2 = """
715 struct
716 {
717 int i;
718 union
719 {
720 int id;
721 char* name;
722 };
723 float f;
724 } joe;
725 """
726
727 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
728 ['Decl', 'joe',
729 ['TypeDecl',
730 ['Struct', None,
731 [['Decl', 'i',
732 ['TypeDecl',
733 ['IdentifierType', ['int']]]],
734 ['Decl', None,
735 ['Union', None,
736 [['Decl', 'id',
737 ['TypeDecl',
738 ['IdentifierType', ['int']]]],
739 ['Decl', 'name',
740 ['PtrDecl',
741 ['TypeDecl',
742 ['IdentifierType', ['char']]]]]]]],
743 ['Decl', 'f',
744 ['TypeDecl',
745 ['IdentifierType', ['float']]]]]]]])
746
747 # ISO/IEC 9899:201x Commitee Draft 2010-11-16, N1539
748 # section 6.7.2.1, par. 19, example 1
749 s3 = """
750 struct v {
751 union {
752 struct { int i, j; };
753 struct { long k, l; } w;
754 };
755 int m;
756 } v1;
757 """
758
759 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
760 ['Decl', 'v1',
761 ['TypeDecl',
762 ['Struct', 'v',
763 [['Decl', None,
764 ['Union', None,
765 [['Decl', None,
766 ['Struct', None,
767 [['Decl', 'i',
768 ['TypeDecl',
769 ['IdentifierType', ['int']]]],
770 ['Decl', 'j',
771 ['TypeDecl',
772 ['IdentifierType', ['int']]]]]]],
773 ['Decl', 'w',
774 ['TypeDecl',
775 ['Struct', None,
776 [['Decl', 'k',
777 ['TypeDecl',
778 ['IdentifierType', ['long']]]],
779 ['Decl', 'l',
780 ['TypeDecl',
781 ['IdentifierType', ['long']]]]]]]]]]],
782 ['Decl', 'm',
783 ['TypeDecl',
784 ['IdentifierType', ['int']]]]]]]])
785
eli.benderskydce29a02011-02-10 07:55:00 +0200786 s4 = """
787 struct v {
788 int i;
789 float;
790 } v2;"""
eli.bendersky6b011792011-06-22 17:50:56 +0300791 # just make sure this doesn't raise ParseError
792 self.parse(s4)
eli.benderskydce29a02011-02-10 07:55:00 +0200793
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200794 def test_struct_bitfields(self):
eli.bendersky38ed9a92010-10-09 09:29:59 +0200795 # a struct with two bitfields, one unnamed
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200796 s1 = """
797 struct {
798 int k:6;
799 int :2;
800 } joe;
801 """
802
803 parsed_struct = self.parse(s1).ext[0]
804
eli.bendersky38ed9a92010-10-09 09:29:59 +0200805 # We can see here the name of the decl for the unnamed bitfield is
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200806 # None, but expand_decl doesn't show bitfield widths
807 # ...
808 self.assertEqual(expand_decl(parsed_struct),
809 ['Decl', 'joe',
810 ['TypeDecl', ['Struct', None,
811 [ ['Decl', 'k',
812 ['TypeDecl',
813 ['IdentifierType', ['int']]]],
814 ['Decl', None,
815 ['TypeDecl',
816 ['IdentifierType', ['int']]]]]]]])
817
818 # ...
819 # so we test them manually
820 self.assertEqual(parsed_struct.type.type.decls[0].bitsize.value, '6')
821 self.assertEqual(parsed_struct.type.type.decls[1].bitsize.value, '2')
822
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300823 def test_tags_namespace(self):
824 """ Tests that the tags of structs/unions/enums reside in a separate namespace and
825 can be named after existing types.
826 """
827 s1 = """
828 typedef int tagEntry;
829
830 struct tagEntry
831 {
832 char* key;
833 char* value;
834 } Entry;
835 """
836
837 s1_ast = self.parse(s1)
838 self.assertEqual(expand_decl(s1_ast.ext[1]),
839 ['Decl', 'Entry',
840 ['TypeDecl', ['Struct', 'tagEntry',
841 [['Decl', 'key',
842 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
843 ['Decl', 'value',
844 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
845
846 s2 = """
847 struct tagEntry;
848
849 typedef struct tagEntry tagEntry;
850
851 struct tagEntry
852 {
853 char* key;
854 char* value;
855 } Entry;
856 """
857
858 s2_ast = self.parse(s2)
859 self.assertEqual(expand_decl(s2_ast.ext[2]),
860 ['Decl', 'Entry',
861 ['TypeDecl', ['Struct', 'tagEntry',
862 [['Decl', 'key',
863 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
864 ['Decl', 'value',
865 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
866
867 s3 = """
868 typedef int mytag;
869
870 enum mytag {ABC, CDE};
871 enum mytag joe;
872 """
873
874 s3_type = self.parse(s3).ext[1].type
875
876 self.assertTrue(isinstance(s3_type, Enum))
877 self.assertEqual(s3_type.name, 'mytag')
878
879 def test_multi_decls(self):
880 d1 = 'int a, b;'
881
882 self.assertEqual(self.get_decl(d1, 0),
883 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
884 self.assertEqual(self.get_decl(d1, 1),
885 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['int']]]])
886
887 d2 = 'char* p, notp, ar[4];'
888 self.assertEqual(self.get_decl(d2, 0),
889 ['Decl', 'p',
890 ['PtrDecl',
891 ['TypeDecl', ['IdentifierType', ['char']]]]])
892 self.assertEqual(self.get_decl(d2, 1),
893 ['Decl', 'notp', ['TypeDecl', ['IdentifierType', ['char']]]])
894 self.assertEqual(self.get_decl(d2, 2),
895 ['Decl', 'ar',
896 ['ArrayDecl', '4',
897 ['TypeDecl', ['IdentifierType', ['char']]]]])
898
899 def test_invalid_multiple_types_error(self):
900 bad = [
901 'int enum {ab, cd} fubr;',
902 'enum kid char brbr;']
903
904 for b in bad:
905 self.assertRaises(ParseError, self.parse, b)
906
907 def test_decl_inits(self):
908 d1 = 'int a = 16;'
eli.benderskyf890a862010-10-30 12:13:23 +0200909 #~ self.parse(d1).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300910 self.assertEqual(self.get_decl(d1),
911 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
912 self.assertEqual(self.get_decl_init(d1),
913 ['Constant', 'int', '16'])
914
915 d2 = 'long ar[] = {7, 8, 9};'
eli.benderskyf890a862010-10-30 12:13:23 +0200916 #~ self.parse(d2).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300917 self.assertEqual(self.get_decl(d2),
918 ['Decl', 'ar',
919 ['ArrayDecl', '',
920 ['TypeDecl', ['IdentifierType', ['long']]]]])
921 self.assertEqual(self.get_decl_init(d2),
922 [ ['Constant', 'int', '7'],
923 ['Constant', 'int', '8'],
eli.benderskyf890a862010-10-30 12:13:23 +0200924 ['Constant', 'int', '9']])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300925
926 d3 = 'char p = j;'
927 self.assertEqual(self.get_decl(d3),
928 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['char']]]])
929 self.assertEqual(self.get_decl_init(d3),
930 ['ID', 'j'])
931
932 d4 = "char x = 'c', *p = {0, 1, 2, {4, 5}, 6};"
933 self.assertEqual(self.get_decl(d4, 0),
934 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['char']]]])
935 self.assertEqual(self.get_decl_init(d4, 0),
936 ['Constant', 'char', "'c'"])
937 self.assertEqual(self.get_decl(d4, 1),
938 ['Decl', 'p',
939 ['PtrDecl',
940 ['TypeDecl', ['IdentifierType', ['char']]]]])
eli.benderskyf890a862010-10-30 12:13:23 +0200941
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300942 self.assertEqual(self.get_decl_init(d4, 1),
943 [ ['Constant', 'int', '0'],
944 ['Constant', 'int', '1'],
945 ['Constant', 'int', '2'],
eli.benderskyf890a862010-10-30 12:13:23 +0200946 [['Constant', 'int', '4'],
947 ['Constant', 'int', '5']],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300948 ['Constant', 'int', '6']])
eli.benderskyf890a862010-10-30 12:13:23 +0200949
950 def test_decl_named_inits(self):
951 d1 = 'int a = {.k = 16};'
952 self.assertEqual(self.get_decl_init(d1),
953 [( [['ID', 'k']],
954 ['Constant', 'int', '16'])])
955
956 d2 = 'int a = { [0].a = {1}, [1].a[0] = 2 };'
957 self.assertEqual(self.get_decl_init(d2),
958 [
959 ([['Constant', 'int', '0'], ['ID', 'a']],
960 [['Constant', 'int', '1']]),
961 ([['Constant', 'int', '1'], ['ID', 'a'], ['Constant', 'int', '0']],
962 ['Constant', 'int', '2'])])
963
964 d3 = 'int a = { .a = 1, .c = 3, 4, .b = 5};'
965 self.assertEqual(self.get_decl_init(d3),
966 [
967 ([['ID', 'a']], ['Constant', 'int', '1']),
968 ([['ID', 'c']], ['Constant', 'int', '3']),
969 ['Constant', 'int', '4'],
970 ([['ID', 'b']], ['Constant', 'int', '5'])])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300971
972 def test_function_definitions(self):
973 def parse_fdef(str):
974 return self.parse(str).ext[0]
975
976 def fdef_decl(fdef):
977 return expand_decl(fdef.decl)
978
979 f1 = parse_fdef('''
980 int factorial(int p)
981 {
982 return 3;
983 }
984 ''')
985
986 self.assertEqual(fdef_decl(f1),
987 ['Decl', 'factorial',
988 ['FuncDecl',
989 [['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]]],
990 ['TypeDecl', ['IdentifierType', ['int']]]]])
991
eli.benderskyef29ff92010-10-29 16:25:43 +0200992 self.assertEqual(type(f1.body.block_items[0]), Return)
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300993
994 f2 = parse_fdef('''
995 char* zzz(int p, char* c)
996 {
997 int a;
998 char b;
999
1000 a = b + 2;
1001 return 3;
1002 }
1003 ''')
1004
1005 self.assertEqual(fdef_decl(f2),
1006 ['Decl', 'zzz',
1007 ['FuncDecl',
1008 [ ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]],
1009 ['Decl', 'c', ['PtrDecl',
1010 ['TypeDecl', ['IdentifierType', ['char']]]]]],
1011 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
1012
eli.benderskyef29ff92010-10-29 16:25:43 +02001013 self.assertEqual(list(map(type, f2.body.block_items)),
1014 [Decl, Decl, Assignment, Return])
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001015
1016 f3 = parse_fdef('''
1017 char* zzz(p, c)
1018 long p, *c;
1019 {
1020 int a;
1021 char b;
1022
1023 a = b + 2;
1024 return 3;
1025 }
1026 ''')
1027
1028 self.assertEqual(fdef_decl(f3),
1029 ['Decl', 'zzz',
1030 ['FuncDecl',
1031 [ ['ID', 'p'],
1032 ['ID', 'c']],
1033 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
1034
eli.benderskyef29ff92010-10-29 16:25:43 +02001035 self.assertEqual(list(map(type, f3.body.block_items)),
1036 [Decl, Decl, Assignment, Return])
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001037
1038 self.assertEqual(expand_decl(f3.param_decls[0]),
1039 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['long']]]])
1040 self.assertEqual(expand_decl(f3.param_decls[1]),
1041 ['Decl', 'c', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['long']]]]])
1042
eli.bendersky71540662010-07-03 12:58:52 +02001043 def test_unified_string_literals(self):
1044 # simple string, for reference
1045 d1 = self.get_decl_init('char* s = "hello";')
1046 self.assertEqual(d1, ['Constant', 'string', '"hello"'])
1047
1048 d2 = self.get_decl_init('char* s = "hello" " world";')
1049 self.assertEqual(d2, ['Constant', 'string', '"hello world"'])
1050
1051 # the test case from issue 6
1052 d3 = self.parse(r'''
1053 int main() {
1054 fprintf(stderr,
1055 "Wrong Params?\n"
1056 "Usage:\n"
1057 "%s <binary_file_path>\n",
1058 argv[0]
1059 );
1060 }
1061 ''')
1062
1063 self.assertEqual(
eli.benderskyef29ff92010-10-29 16:25:43 +02001064 d3.ext[0].body.block_items[0].args.exprs[1].value,
eli.bendersky71540662010-07-03 12:58:52 +02001065 r'"Wrong Params?\nUsage:\n%s <binary_file_path>\n"')
eli.bendersky4a89f112010-07-05 06:02:03 +02001066
1067 d4 = self.get_decl_init('char* s = "" "foobar";')
1068 self.assertEqual(d4, ['Constant', 'string', '"foobar"'])
1069
1070 d5 = self.get_decl_init(r'char* s = "foo\"" "bar";')
1071 self.assertEqual(d5, ['Constant', 'string', r'"foo\"bar"'])
eli.bendersky71540662010-07-03 12:58:52 +02001072
eli.bendersky79d5cf62010-10-29 13:33:52 +02001073 def test_inline_specifier(self):
1074 ps2 = self.parse('static inline void inlinefoo(void);')
1075 self.assertEqual(ps2.ext[0].funcspec, ['inline'])
eli.bendersky2e907fa2010-10-29 15:51:07 +02001076
1077 # variable length array
1078 def test_vla(self):
1079 ps2 = self.parse(r'''
1080 int main() {
1081 int size;
1082 int var[size = 5];
1083
1084 int var2[*];
1085 }
1086 ''')
eli.benderskyef29ff92010-10-29 16:25:43 +02001087 self.failUnless(isinstance(ps2.ext[0].body.block_items[1].type.dim, Assignment))
1088 self.failUnless(isinstance(ps2.ext[0].body.block_items[2].type.dim, ID))
eli.bendersky79d5cf62010-10-29 13:33:52 +02001089
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001090
eli.bendersky85d2e732011-05-20 19:47:26 +03001091class TestCParser_whole_code(TestCParser_base):
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001092 """ Testing of parsing whole chunks of code.
1093
1094 Since I don't want to rely on the structure of ASTs too
1095 much, most of these tests are implemented with visitors.
1096 """
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001097 # A simple helper visitor that lists the values of all the
1098 # Constant nodes it sees.
1099 #
1100 class ConstantVisitor(NodeVisitor):
1101 def __init__(self):
1102 self.values = []
1103
1104 def visit_Constant(self, node):
1105 self.values.append(node.value)
1106
1107 # This visitor counts the amount of references to the ID
1108 # with the name provided to it in the constructor.
1109 #
1110 class IDNameCounter(NodeVisitor):
1111 def __init__(self, name):
1112 self.name = name
1113 self.nrefs = 0
1114
1115 def visit_ID(self, node):
1116 if node.name == self.name:
1117 self.nrefs += 1
1118
1119 # Counts the amount of nodes of a given class
1120 #
1121 class NodeKlassCounter(NodeVisitor):
1122 def __init__(self, node_klass):
1123 self.klass = node_klass
1124 self.n = 0
1125
1126 def generic_visit(self, node):
1127 if node.__class__ == self.klass:
1128 self.n += 1
1129
1130 NodeVisitor.generic_visit(self, node)
1131
1132 def assert_all_Constants(self, code, constants):
1133 """ Asserts that the list of all Constant values (by
1134 'preorder' appearance) in the chunk of code is as
1135 given.
1136 """
eli.benderskyed890492010-06-25 08:25:55 +03001137 if isinstance(code, str):
1138 parsed = self.parse(code)
1139 else:
1140 parsed = code
1141
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001142 cv = self.ConstantVisitor()
1143 cv.visit(parsed)
1144 self.assertEqual(cv.values, constants)
1145
1146 def assert_num_ID_refs(self, code, name, num):
1147 """ Asserts the number of references to the ID with
1148 the given name.
1149 """
1150 if isinstance(code, str):
1151 parsed = self.parse(code)
1152 else:
1153 parsed = code
1154
1155 iv = self.IDNameCounter(name)
1156 iv.visit(parsed)
1157 self.assertEqual(iv.nrefs, num)
1158
1159 def assert_num_klass_nodes(self, code, klass, num):
1160 """ Asserts the amount of klass nodes in the code.
1161 """
1162 if isinstance(code, str):
1163 parsed = self.parse(code)
1164 else:
1165 parsed = code
1166
1167 cv = self.NodeKlassCounter(klass)
1168 cv.visit(parsed)
1169 self.assertEqual(cv.n, num)
1170
1171 def test_expressions(self):
1172 e1 = '''int k = (r + 10.0) >> 6 + 8 << (3 & 0x14);'''
1173 self.assert_all_Constants(e1, ['10.0', '6', '8', '3', '0x14'])
1174
1175 e2 = r'''char n = '\n', *prefix = "st_";'''
1176 self.assert_all_Constants(e2, [r"'\n'", '"st_"'])
1177
1178 def test_statements(self):
1179 s1 = r'''
1180 void foo(){
1181 if (sp == 1)
1182 if (optind >= argc ||
1183 argv[optind][0] != '-' || argv[optind][1] == '\0')
1184 return -1;
1185 else if (strcmp(argv[optind], "--") == 0) {
1186 optind++;
1187 return -1;
1188 }
1189 }
1190 '''
1191
1192 self.assert_all_Constants(s1,
1193 ['1', '0', r"'-'", '1', r"'\0'", '1', r'"--"', '0', '1'])
1194
1195 ps1 = self.parse(s1)
1196 self.assert_num_ID_refs(ps1, 'argv', 3)
1197 self.assert_num_ID_refs(ps1, 'optind', 5)
1198
1199 self.assert_num_klass_nodes(ps1, If, 3)
1200 self.assert_num_klass_nodes(ps1, Return, 2)
1201 self.assert_num_klass_nodes(ps1, FuncCall, 1) # strcmp
1202 self.assert_num_klass_nodes(ps1, BinaryOp, 7)
1203
1204 # In the following code, Hash and Node were defined as
1205 # int to pacify the parser that sees they're used as
1206 # types
1207 #
1208 s2 = r'''
1209 typedef int Hash, Node;
1210
1211 void HashDestroy(Hash* hash)
1212 {
1213 unsigned int i;
1214
1215 if (hash == NULL)
1216 return;
1217
1218 for (i = 0; i < hash->table_size; ++i)
1219 {
1220 Node* temp = hash->heads[i];
1221
1222 while (temp != NULL)
1223 {
1224 Node* temp2 = temp;
1225
1226 free(temp->entry->key);
1227 free(temp->entry->value);
1228 free(temp->entry);
1229
1230 temp = temp->next;
1231
1232 free(temp2);
1233 }
1234 }
1235
1236 free(hash->heads);
1237 hash->heads = NULL;
1238
1239 free(hash);
1240 }
1241 '''
1242
1243 ps2 = self.parse(s2)
1244 self.assert_num_klass_nodes(ps2, FuncCall, 6)
1245 self.assert_num_klass_nodes(ps2, FuncDef, 1)
1246 self.assert_num_klass_nodes(ps2, For, 1)
1247 self.assert_num_klass_nodes(ps2, While, 1)
1248 self.assert_num_klass_nodes(ps2, StructRef, 10)
1249
1250 # declarations don't count
1251 self.assert_num_ID_refs(ps2, 'hash', 6)
1252 self.assert_num_ID_refs(ps2, 'i', 4)
eli.benderskyed890492010-06-25 08:25:55 +03001253
1254 s3 = r'''
1255 void x(void) {
1256 int a, b;
1257 if (a < b)
1258 do {
1259 a = 0;
1260 } while (0);
1261 else if (a == b) {
1262 a = 1;
1263 }
1264 }
1265 '''
1266
1267 ps3 = self.parse(s3)
1268 self.assert_num_klass_nodes(ps3, DoWhile, 1)
1269 self.assert_num_ID_refs(ps3, 'a', 4)
1270 self.assert_all_Constants(ps3, ['0', '0', '1'])
eli.bendersky91c0aa32011-10-16 05:50:43 +02001271
1272 def test_empty_statement(self):
1273 s1 = r'''
1274 void foo(void){
1275 ;
1276 return;
1277 }
1278 '''
1279 ps1 = self.parse(s1)
1280 self.assert_num_klass_nodes(ps1, EmptyStatement, 1)
1281 self.assert_num_klass_nodes(ps1, Return, 1)
eli.bendersky145890d2010-10-29 12:02:32 +02001282
1283 def test_for_statement(self):
1284 s2 = r'''
1285 void x(void)
1286 {
1287 int i;
1288 for (i = 0; i < 5; ++i) {
1289 x = 50;
1290 }
1291 }
1292 '''
1293 ps2 = self.parse(s2)
1294 self.assert_num_klass_nodes(ps2, For, 1)
1295 # here there are 3 refs to 'i' since the declaration doesn't count as
1296 # a ref in the visitor
1297 #
1298 self.assert_num_ID_refs(ps2, 'i', 3)
eli.benderskyed890492010-06-25 08:25:55 +03001299
eli.bendersky145890d2010-10-29 12:02:32 +02001300 s3 = r'''
1301 void x(void)
1302 {
1303 for (int i = 0; i < 5; ++i) {
1304 x = 50;
1305 }
1306 }
1307 '''
1308 ps3 = self.parse(s3)
eli.bendersky145890d2010-10-29 12:02:32 +02001309 self.assert_num_klass_nodes(ps3, For, 1)
1310 # here there are 2 refs to 'i' since the declaration doesn't count as
1311 # a ref in the visitor
1312 #
1313 self.assert_num_ID_refs(ps3, 'i', 2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001314
1315 def test_whole_file(self):
1316 # See how pycparser handles a whole, real C file.
1317 #
1318 filename = 'c_files/memmgr_with_h.c'
1319 code = open(filename, 'rU').read()
1320 p = self.parse(code)
1321
1322 self.assert_num_klass_nodes(p, FuncDef, 5)
1323
1324 # each FuncDef also has a FuncDecl. 4 declarations
1325 # + 5 definitions, overall 9
1326 self.assert_num_klass_nodes(p, FuncDecl, 9)
1327
1328 self.assert_num_klass_nodes(p, Typedef, 4)
1329
1330 self.assertEqual(p.ext[4].coord.line, 88)
1331 self.assertEqual(p.ext[4].coord.file, "./memmgr.h")
1332
1333 self.assertEqual(p.ext[6].coord.line, 10)
1334 self.assertEqual(p.ext[6].coord.file, "memmgr.c")
1335
1336 def test_whole_file_with_stdio(self):
1337 # Parse a whole file with stdio.h included by cpp
1338 #
1339 filename = 'c_files/cppd_with_stdio_h.c'
1340 code = open(filename, 'rU').read()
1341 p = self.parse(code)
1342
1343 self.failUnless(isinstance(p.ext[0], Typedef))
1344 self.assertEqual(p.ext[0].coord.line, 213)
1345 self.assertEqual(p.ext[0].coord.file, "D:\eli\cpp_stuff\libc_include/stddef.h")
1346
1347 self.failUnless(isinstance(p.ext[-1], FuncDef))
1348 self.assertEqual(p.ext[-1].coord.line, 15)
1349 self.assertEqual(p.ext[-1].coord.file, "example_c_file.c")
1350
1351 self.failUnless(isinstance(p.ext[-8], Typedef))
1352 self.failUnless(isinstance(p.ext[-8].type, TypeDecl))
1353 self.assertEqual(p.ext[-8].name, 'cookie_io_functions_t')
eli.bendersky85d2e732011-05-20 19:47:26 +03001354
1355
1356class TestCParser_typenames(TestCParser_base):
1357 """ Test issues related to the typedef-name problem.
1358 """
1359 def test_innerscope_typedef(self):
1360 # should fail since TT is not a type in bar
1361 s1 = r'''
1362 void foo() {
1363 typedef char TT;
1364 TT x;
1365 }
1366 void bar() {
1367 TT y;
1368 }
1369 '''
1370 self.assertRaises(ParseError, self.parse, s1)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001371
eli.bendersky85d2e732011-05-20 19:47:26 +03001372 # should succeed since TT is not a type in bar
1373 s2 = r'''
1374 void foo() {
1375 typedef char TT;
1376 TT x;
1377 }
1378 void bar() {
1379 unsigned TT;
1380 }
1381 '''
1382 self.failUnless(isinstance(self.parse(s2), FileAST))
1383
1384
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001385
1386if __name__ == '__main__':
1387 #~ suite = unittest.TestLoader().loadTestsFromNames(
1388 #~ ['test_c_parser.TestCParser_fundamentals.test_typedef'])
1389
1390 #~ suite = unittest.TestLoader().loadTestsFromNames(
1391 #~ ['test_c_parser.TestCParser_whole_code.test_whole_file_with_stdio'])
1392
1393 #~ suite = unittest.TestLoader().loadTestsFromTestCase(
1394 #~ TestCParser_whole_code)
1395
1396 #~ unittest.TextTestRunner(verbosity=2).run(suite)
1397 unittest.main()