blob: 93000feda34a14d30cf0580980bb08f14a5a5991 [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
207 self.assertEqual(self.get_decl('char* string;'),
208 ['Decl', 'string',
209 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]])
210
211 self.assertEqual(self.get_decl('long ar[15];'),
212 ['Decl', 'ar',
213 ['ArrayDecl', '15',
214 ['TypeDecl', ['IdentifierType', ['long']]]]])
eli.bendersky98f45372010-10-30 09:46:29 +0200215
216 self.assertEqual(self.get_decl('long long ar[15];'),
217 ['Decl', 'ar',
218 ['ArrayDecl', '15',
eli.benderskyf890a862010-10-30 12:13:23 +0200219 ['TypeDecl', ['IdentifierType', ['long', 'long']]]]])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300220
221 self.assertEqual(self.get_decl('unsigned ar[];'),
222 ['Decl', 'ar',
223 ['ArrayDecl', '',
224 ['TypeDecl', ['IdentifierType', ['unsigned']]]]])
225
226 self.assertEqual(self.get_decl('int strlen(char* s);'),
227 ['Decl', 'strlen',
228 ['FuncDecl',
229 [['Decl', 's',
230 ['PtrDecl',
231 ['TypeDecl', ['IdentifierType', ['char']]]]]],
232 ['TypeDecl', ['IdentifierType', ['int']]]]])
233
234 self.assertEqual(self.get_decl('int strcmp(char* s1, char* s2);'),
235 ['Decl', 'strcmp',
236 ['FuncDecl',
237 [ ['Decl', 's1',
238 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
239 ['Decl', 's2',
240 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]
241 ],
242 ['TypeDecl', ['IdentifierType', ['int']]]]])
243
244 def test_nested_decls(self): # the fun begins
245 self.assertEqual(self.get_decl('char** ar2D;'),
246 ['Decl', 'ar2D',
247 ['PtrDecl', ['PtrDecl',
248 ['TypeDecl', ['IdentifierType', ['char']]]]]])
249
250 self.assertEqual(self.get_decl('int (*a)[1][2];'),
251 ['Decl', 'a',
252 ['PtrDecl',
253 ['ArrayDecl', '1',
254 ['ArrayDecl', '2',
255 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
256
257 self.assertEqual(self.get_decl('int *a[1][2];'),
258 ['Decl', 'a',
259 ['ArrayDecl', '1',
260 ['ArrayDecl', '2',
261 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['int']]]]]]])
262
263 self.assertEqual(self.get_decl('char ***ar3D[40];'),
264 ['Decl', 'ar3D',
265 ['ArrayDecl', '40',
266 ['PtrDecl', ['PtrDecl', ['PtrDecl',
267 ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
268
269 self.assertEqual(self.get_decl('char (***ar3D)[40];'),
270 ['Decl', 'ar3D',
271 ['PtrDecl', ['PtrDecl', ['PtrDecl',
272 ['ArrayDecl', '40', ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
273
274 self.assertEqual(self.get_decl('int (*x[4])(char, int);'),
275 ['Decl', 'x',
276 ['ArrayDecl', '4',
277 ['PtrDecl',
278 ['FuncDecl',
279 [ ['Typename', ['TypeDecl', ['IdentifierType', ['char']]]],
280 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
281 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
282
283 self.assertEqual(self.get_decl('char *(*(**foo [][8])())[];'),
284 ['Decl', 'foo',
285 ['ArrayDecl', '',
286 ['ArrayDecl', '8',
287 ['PtrDecl', ['PtrDecl',
288 ['FuncDecl',
289 [],
290 ['PtrDecl',
291 ['ArrayDecl', '',
292 ['PtrDecl',
293 ['TypeDecl',
294 ['IdentifierType', ['char']]]]]]]]]]]])
295
296 # explore named and unnamed function pointer parameters,
297 # with and without qualifiers
298 #
299
300 # unnamed w/o quals
301 self.assertEqual(self.get_decl('int (*k)(int);'),
302 ['Decl', 'k',
303 ['PtrDecl',
304 ['FuncDecl',
305 [['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
306 ['TypeDecl', ['IdentifierType', ['int']]]]]])
307
308 # unnamed w/ quals
309 self.assertEqual(self.get_decl('int (*k)(const int);'),
310 ['Decl', 'k',
311 ['PtrDecl',
312 ['FuncDecl',
313 [['Typename', ['const'], ['TypeDecl', ['IdentifierType', ['int']]]]],
314 ['TypeDecl', ['IdentifierType', ['int']]]]]])
315
316 # named w/o quals
317 self.assertEqual(self.get_decl('int (*k)(int q);'),
318 ['Decl', 'k',
319 ['PtrDecl',
320 ['FuncDecl',
321 [['Decl', 'q', ['TypeDecl', ['IdentifierType', ['int']]]]],
322 ['TypeDecl', ['IdentifierType', ['int']]]]]])
323
324 # named w/ quals
325 self.assertEqual(self.get_decl('int (*k)(const volatile int q);'),
326 ['Decl', 'k',
327 ['PtrDecl',
328 ['FuncDecl',
329 [['Decl', ['volatile', 'const'], 'q',
330 ['TypeDecl', ['IdentifierType', ['int']]]]],
331 ['TypeDecl', ['IdentifierType', ['int']]]]]])
332
eli.bendersky79d5cf62010-10-29 13:33:52 +0200333 # restrict qualifier
334 self.assertEqual(self.get_decl('int (*k)(restrict int* q);'),
335 ['Decl', 'k',
336 ['PtrDecl',
337 ['FuncDecl',
338 [['Decl', ['restrict'], 'q',
339 ['PtrDecl',
340 ['TypeDecl', ['IdentifierType', ['int']]]]]],
341 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300342
343 def test_qualifiers_storage_specifiers(self):
344 def assert_qs(txt, index, quals, storage):
345 d = self.parse(txt).ext[index]
346 self.assertEqual(d.quals, quals)
347 self.assertEqual(d.storage, storage)
348
349 assert_qs("extern int p;", 0, [], ['extern'])
350 assert_qs("const long p = 6;", 0, ['const'], [])
351
352 d1 = "static const int p, q, r;"
353 for i in range(3):
354 assert_qs(d1, i, ['const'], ['static'])
355
356 d2 = "static char * const p;"
357 assert_qs(d2, 0, [], ['static'])
358 pdecl = self.parse(d2).ext[0].type
359 self.failUnless(isinstance(pdecl, PtrDecl))
360 self.assertEqual(pdecl.quals, ['const'])
361
362 def test_sizeof(self):
363 e = """
364 void foo()
365 {
366 int a = sizeof k;
367 int b = sizeof(int);
eli.benderskyc51e1d32011-02-04 08:52:33 +0200368 int c = sizeof(int**);;
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300369
370 char* p = "just to make sure this parses w/o error...";
371 int d = sizeof(int());
372 }
373 """
374 compound = self.parse(e).ext[0].body
375
eli.benderskyef29ff92010-10-29 16:25:43 +0200376 s1 = compound.block_items[0].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300377 self.assertTrue(isinstance(s1, UnaryOp))
378 self.assertEqual(s1.op, 'sizeof')
379 self.assertTrue(isinstance(s1.expr, ID))
380 self.assertEqual(s1.expr.name, 'k')
381
eli.benderskyef29ff92010-10-29 16:25:43 +0200382 s2 = compound.block_items[1].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300383 self.assertEqual(expand_decl(s2.expr),
384 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]])
385
eli.benderskyef29ff92010-10-29 16:25:43 +0200386 s3 = compound.block_items[2].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300387 self.assertEqual(expand_decl(s3.expr),
388 ['Typename',
389 ['PtrDecl',
390 ['PtrDecl',
391 ['TypeDecl',
392 ['IdentifierType', ['int']]]]]])
393
eli.bendersky9f481562010-10-30 15:50:47 +0200394 # The C99 compound literal feature
395 #
eli.benderskyf890a862010-10-30 12:13:23 +0200396 def test_compound_literals(self):
eli.bendersky9f481562010-10-30 15:50:47 +0200397 ps1 = self.parse(r'''
eli.benderskyf890a862010-10-30 12:13:23 +0200398 void foo() {
eli.bendersky9f481562010-10-30 15:50:47 +0200399 p = (long long){k};
400 tc = (struct jk){.a = {1, 2}, .b[0] = t};
401 }''')
eli.benderskyf890a862010-10-30 12:13:23 +0200402
eli.bendersky9f481562010-10-30 15:50:47 +0200403 compound = ps1.ext[0].body.block_items[0].rvalue
404 self.assertEqual(expand_decl(compound.type),
405 ['Typename', ['TypeDecl', ['IdentifierType', ['long', 'long']]]])
406 self.assertEqual(expand_init(compound.init),
407 [['ID', 'k']])
408
409 compound = ps1.ext[0].body.block_items[1].rvalue
410 self.assertEqual(expand_decl(compound.type),
411 ['Typename', ['TypeDecl', ['Struct', 'jk', []]]])
412 self.assertEqual(expand_init(compound.init),
413 [
414 ([['ID', 'a']], [['Constant', 'int', '1'], ['Constant', 'int', '2']]),
415 ([['ID', 'b'], ['Constant', 'int', '0']], ['ID', 't'])])
eli.benderskyf890a862010-10-30 12:13:23 +0200416
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300417 def test_enums(self):
418 e1 = "enum mycolor op;"
419 e1_type = self.parse(e1).ext[0].type.type
420
421 self.assertTrue(isinstance(e1_type, Enum))
422 self.assertEqual(e1_type.name, 'mycolor')
423 self.assertEqual(e1_type.values, None)
424
425 e2 = "enum mysize {large=20, small, medium} shoes;"
426 e2_type = self.parse(e2).ext[0].type.type
427
428 self.assertTrue(isinstance(e2_type, Enum))
429 self.assertEqual(e2_type.name, 'mysize')
430
431 e2_elist = e2_type.values
432 self.assertTrue(isinstance(e2_elist, EnumeratorList))
433
434 for e2_eval in e2_elist.enumerators:
435 self.assertTrue(isinstance(e2_eval, Enumerator))
436
437 self.assertEqual(e2_elist.enumerators[0].name, 'large')
438 self.assertEqual(e2_elist.enumerators[0].value.value, '20')
439 self.assertEqual(e2_elist.enumerators[2].name, 'medium')
440 self.assertEqual(e2_elist.enumerators[2].value, None)
441
442 # enum with trailing comma (C99 feature)
443 e3 = """
444 enum
445 {
446 red,
447 blue,
448 green,
449 } color;
450 """
451
452 e3_type = self.parse(e3).ext[0].type.type
453 self.assertTrue(isinstance(e3_type, Enum))
454 e3_elist = e3_type.values
455 self.assertTrue(isinstance(e3_elist, EnumeratorList))
456
457 for e3_eval in e3_elist.enumerators:
458 self.assertTrue(isinstance(e3_eval, Enumerator))
459
460 self.assertEqual(e3_elist.enumerators[0].name, 'red')
461 self.assertEqual(e3_elist.enumerators[0].value, None)
462 self.assertEqual(e3_elist.enumerators[1].name, 'blue')
463 self.assertEqual(e3_elist.enumerators[2].name, 'green')
464
465 def test_typedef(self):
466 # without typedef, error
467 s1 = """
468 node k;
469 """
470 self.assertRaises(ParseError, self.parse, s1)
471
472 # now with typedef, works
473 s2 = """
474 typedef void* node;
475 node k;
476 """
477 ps2 = self.parse(s2)
478 self.assertEqual(expand_decl(ps2.ext[0]),
479 ['Typedef', 'node',
480 ['PtrDecl',
481 ['TypeDecl', ['IdentifierType', ['void']]]]])
482
483 self.assertEqual(expand_decl(ps2.ext[1]),
484 ['Decl', 'k',
485 ['TypeDecl', ['IdentifierType', ['node']]]])
486
487 s3 = """
488 typedef int T;
489 typedef T *pT;
490
491 pT aa, bb;
492 """
493 ps3 = self.parse(s3)
494 self.assertEqual(expand_decl(ps3.ext[3]),
495 ['Decl', 'bb',
496 ['TypeDecl', ['IdentifierType', ['pT']]]])
497
498 s4 = '''
499 typedef char* __builtin_va_list;
500 typedef __builtin_va_list __gnuc_va_list;
501 '''
502 ps4 = self.parse(s4)
503 self.assertEqual(expand_decl(ps4.ext[1]),
504 ['Typedef', '__gnuc_va_list',
505 ['TypeDecl',
506 ['IdentifierType', ['__builtin_va_list']]]])
507
508 s5 = '''typedef struct tagHash Hash;'''
509 ps5 = self.parse(s5)
510 self.assertEqual(expand_decl(ps5.ext[0]),
511 ['Typedef', 'Hash', ['TypeDecl', ['Struct', 'tagHash', []]]])
512
513 def test_struct_union(self):
514 s1 = """
515 struct {
516 int id;
517 char* name;
518 } joe;
519 """
520
521 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
522 ['Decl', 'joe',
523 ['TypeDecl', ['Struct', None,
524 [ ['Decl', 'id',
525 ['TypeDecl',
526 ['IdentifierType', ['int']]]],
527 ['Decl', 'name',
528 ['PtrDecl',
529 ['TypeDecl',
530 ['IdentifierType', ['char']]]]]]]]])
531
532 s2 = """
533 struct node p;
534 """
535 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
536 ['Decl', 'p',
537 ['TypeDecl', ['Struct', 'node', []]]])
538
539 s21 = """
540 union pri ra;
541 """
542 self.assertEqual(expand_decl(self.parse(s21).ext[0]),
543 ['Decl', 'ra',
544 ['TypeDecl', ['Union', 'pri', []]]])
545
546 s3 = """
547 struct node* p;
548 """
549 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
550 ['Decl', 'p',
551 ['PtrDecl',
552 ['TypeDecl', ['Struct', 'node', []]]]])
553
554 s4 = """
555 struct node;
556 """
557 self.assertEqual(expand_decl(self.parse(s4).ext[0]),
558 ['Decl', None,
559 ['Struct', 'node', []]])
560
561 s5 = """
562 union
563 {
564 struct
565 {
566 int type;
567 } n;
568
569 struct
570 {
571 int type;
572 int intnode;
573 } ni;
574 } u;
575 """
576 self.assertEqual(expand_decl(self.parse(s5).ext[0]),
577 ['Decl', 'u',
578 ['TypeDecl',
579 ['Union', None,
580 [['Decl', 'n',
581 ['TypeDecl',
582 ['Struct', None,
583 [['Decl', 'type',
584 ['TypeDecl', ['IdentifierType', ['int']]]]]]]],
585 ['Decl', 'ni',
586 ['TypeDecl',
587 ['Struct', None,
588 [['Decl', 'type',
589 ['TypeDecl', ['IdentifierType', ['int']]]],
590 ['Decl', 'intnode',
591 ['TypeDecl', ['IdentifierType', ['int']]]]]]]]]]]])
592
593 s6 = """
594 typedef struct foo_tag
595 {
596 void* data;
597 } foo, *pfoo;
598 """
599 s6_ast = self.parse(s6)
600
601 self.assertEqual(expand_decl(s6_ast.ext[0]),
602 ['Typedef', 'foo',
603 ['TypeDecl',
604 ['Struct', 'foo_tag',
605 [['Decl', 'data',
606 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]])
607
608 self.assertEqual(expand_decl(s6_ast.ext[1]),
609 ['Typedef', 'pfoo',
610 ['PtrDecl',
611 ['TypeDecl',
612 ['Struct', 'foo_tag',
613 [['Decl', 'data',
614 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]]])
615
616 s7 = r"""
617 struct _on_exit_args {
618 void * _fnargs[32];
619 void * _dso_handle[32];
620
621 long _fntypes;
622 #line 77 "D:\eli\cpp_stuff\libc_include/sys/reent.h"
623
624 long _is_cxa;
625 };
626 """
627
628 s7_ast = self.parse(s7, filename='test.c')
629 self.assert_coord(s7_ast.ext[0].type.decls[2], 6, 'test.c')
630 self.assert_coord(s7_ast.ext[0].type.decls[3], 78,
631 r'D:\eli\cpp_stuff\libc_include/sys/reent.h')
632
633 s8 = """
634 typedef enum tagReturnCode {SUCCESS, FAIL} ReturnCode;
635
636 typedef struct tagEntry
637 {
638 char* key;
639 char* value;
640 } Entry;
641
642
643 typedef struct tagNode
644 {
645 Entry* entry;
646
647 struct tagNode* next;
648 } Node;
649
650 typedef struct tagHash
651 {
652 unsigned int table_size;
653
654 Node** heads;
655
656 } Hash;
657 """
658 s8_ast = self.parse(s8)
659 self.assertEqual(expand_decl(s8_ast.ext[3]),
660 ['Typedef', 'Hash',
661 ['TypeDecl', ['Struct', 'tagHash',
662 [['Decl', 'table_size',
663 ['TypeDecl', ['IdentifierType', ['int', 'unsigned']]]],
664 ['Decl', 'heads',
665 ['PtrDecl', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['Node']]]]]]]]]])
666
eli.bendersky697ecc52011-02-10 07:05:13 +0200667 def test_anonymous_struct_union(self):
668 s1 = """
669 union
670 {
671 union
672 {
673 int i;
674 long l;
675 };
676
677 struct
678 {
679 int type;
680 int intnode;
681 };
682 } u;
683 """
684
685 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
686 ['Decl', 'u',
687 ['TypeDecl',
688 ['Union', None,
689 [['Decl', None,
690 ['Union', None,
691 [['Decl', 'i',
692 ['TypeDecl',
693 ['IdentifierType', ['int']]]],
694 ['Decl', 'l',
695 ['TypeDecl',
696 ['IdentifierType', ['long']]]]]]],
697 ['Decl', None,
698 ['Struct', None,
699 [['Decl', 'type',
700 ['TypeDecl',
701 ['IdentifierType', ['int']]]],
702 ['Decl', 'intnode',
703 ['TypeDecl',
704 ['IdentifierType', ['int']]]]]]]]]]])
705
706 s2 = """
707 struct
708 {
709 int i;
710 union
711 {
712 int id;
713 char* name;
714 };
715 float f;
716 } joe;
717 """
718
719 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
720 ['Decl', 'joe',
721 ['TypeDecl',
722 ['Struct', None,
723 [['Decl', 'i',
724 ['TypeDecl',
725 ['IdentifierType', ['int']]]],
726 ['Decl', None,
727 ['Union', None,
728 [['Decl', 'id',
729 ['TypeDecl',
730 ['IdentifierType', ['int']]]],
731 ['Decl', 'name',
732 ['PtrDecl',
733 ['TypeDecl',
734 ['IdentifierType', ['char']]]]]]]],
735 ['Decl', 'f',
736 ['TypeDecl',
737 ['IdentifierType', ['float']]]]]]]])
738
739 # ISO/IEC 9899:201x Commitee Draft 2010-11-16, N1539
740 # section 6.7.2.1, par. 19, example 1
741 s3 = """
742 struct v {
743 union {
744 struct { int i, j; };
745 struct { long k, l; } w;
746 };
747 int m;
748 } v1;
749 """
750
751 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
752 ['Decl', 'v1',
753 ['TypeDecl',
754 ['Struct', 'v',
755 [['Decl', None,
756 ['Union', None,
757 [['Decl', None,
758 ['Struct', None,
759 [['Decl', 'i',
760 ['TypeDecl',
761 ['IdentifierType', ['int']]]],
762 ['Decl', 'j',
763 ['TypeDecl',
764 ['IdentifierType', ['int']]]]]]],
765 ['Decl', 'w',
766 ['TypeDecl',
767 ['Struct', None,
768 [['Decl', 'k',
769 ['TypeDecl',
770 ['IdentifierType', ['long']]]],
771 ['Decl', 'l',
772 ['TypeDecl',
773 ['IdentifierType', ['long']]]]]]]]]]],
774 ['Decl', 'm',
775 ['TypeDecl',
776 ['IdentifierType', ['int']]]]]]]])
777
eli.benderskydce29a02011-02-10 07:55:00 +0200778 s4 = """
779 struct v {
780 int i;
781 float;
782 } v2;"""
eli.bendersky6b011792011-06-22 17:50:56 +0300783 # just make sure this doesn't raise ParseError
784 self.parse(s4)
eli.benderskydce29a02011-02-10 07:55:00 +0200785
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200786 def test_struct_bitfields(self):
eli.bendersky38ed9a92010-10-09 09:29:59 +0200787 # a struct with two bitfields, one unnamed
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200788 s1 = """
789 struct {
790 int k:6;
791 int :2;
792 } joe;
793 """
794
795 parsed_struct = self.parse(s1).ext[0]
796
eli.bendersky38ed9a92010-10-09 09:29:59 +0200797 # We can see here the name of the decl for the unnamed bitfield is
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200798 # None, but expand_decl doesn't show bitfield widths
799 # ...
800 self.assertEqual(expand_decl(parsed_struct),
801 ['Decl', 'joe',
802 ['TypeDecl', ['Struct', None,
803 [ ['Decl', 'k',
804 ['TypeDecl',
805 ['IdentifierType', ['int']]]],
806 ['Decl', None,
807 ['TypeDecl',
808 ['IdentifierType', ['int']]]]]]]])
809
810 # ...
811 # so we test them manually
812 self.assertEqual(parsed_struct.type.type.decls[0].bitsize.value, '6')
813 self.assertEqual(parsed_struct.type.type.decls[1].bitsize.value, '2')
814
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300815 def test_tags_namespace(self):
816 """ Tests that the tags of structs/unions/enums reside in a separate namespace and
817 can be named after existing types.
818 """
819 s1 = """
820 typedef int tagEntry;
821
822 struct tagEntry
823 {
824 char* key;
825 char* value;
826 } Entry;
827 """
828
829 s1_ast = self.parse(s1)
830 self.assertEqual(expand_decl(s1_ast.ext[1]),
831 ['Decl', 'Entry',
832 ['TypeDecl', ['Struct', 'tagEntry',
833 [['Decl', 'key',
834 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
835 ['Decl', 'value',
836 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
837
838 s2 = """
839 struct tagEntry;
840
841 typedef struct tagEntry tagEntry;
842
843 struct tagEntry
844 {
845 char* key;
846 char* value;
847 } Entry;
848 """
849
850 s2_ast = self.parse(s2)
851 self.assertEqual(expand_decl(s2_ast.ext[2]),
852 ['Decl', 'Entry',
853 ['TypeDecl', ['Struct', 'tagEntry',
854 [['Decl', 'key',
855 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
856 ['Decl', 'value',
857 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
858
859 s3 = """
860 typedef int mytag;
861
862 enum mytag {ABC, CDE};
863 enum mytag joe;
864 """
865
866 s3_type = self.parse(s3).ext[1].type
867
868 self.assertTrue(isinstance(s3_type, Enum))
869 self.assertEqual(s3_type.name, 'mytag')
870
871 def test_multi_decls(self):
872 d1 = 'int a, b;'
873
874 self.assertEqual(self.get_decl(d1, 0),
875 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
876 self.assertEqual(self.get_decl(d1, 1),
877 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['int']]]])
878
879 d2 = 'char* p, notp, ar[4];'
880 self.assertEqual(self.get_decl(d2, 0),
881 ['Decl', 'p',
882 ['PtrDecl',
883 ['TypeDecl', ['IdentifierType', ['char']]]]])
884 self.assertEqual(self.get_decl(d2, 1),
885 ['Decl', 'notp', ['TypeDecl', ['IdentifierType', ['char']]]])
886 self.assertEqual(self.get_decl(d2, 2),
887 ['Decl', 'ar',
888 ['ArrayDecl', '4',
889 ['TypeDecl', ['IdentifierType', ['char']]]]])
890
891 def test_invalid_multiple_types_error(self):
892 bad = [
893 'int enum {ab, cd} fubr;',
894 'enum kid char brbr;']
895
896 for b in bad:
897 self.assertRaises(ParseError, self.parse, b)
898
899 def test_decl_inits(self):
900 d1 = 'int a = 16;'
eli.benderskyf890a862010-10-30 12:13:23 +0200901 #~ self.parse(d1).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300902 self.assertEqual(self.get_decl(d1),
903 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
904 self.assertEqual(self.get_decl_init(d1),
905 ['Constant', 'int', '16'])
906
907 d2 = 'long ar[] = {7, 8, 9};'
eli.benderskyf890a862010-10-30 12:13:23 +0200908 #~ self.parse(d2).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300909 self.assertEqual(self.get_decl(d2),
910 ['Decl', 'ar',
911 ['ArrayDecl', '',
912 ['TypeDecl', ['IdentifierType', ['long']]]]])
913 self.assertEqual(self.get_decl_init(d2),
914 [ ['Constant', 'int', '7'],
915 ['Constant', 'int', '8'],
eli.benderskyf890a862010-10-30 12:13:23 +0200916 ['Constant', 'int', '9']])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300917
918 d3 = 'char p = j;'
919 self.assertEqual(self.get_decl(d3),
920 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['char']]]])
921 self.assertEqual(self.get_decl_init(d3),
922 ['ID', 'j'])
923
924 d4 = "char x = 'c', *p = {0, 1, 2, {4, 5}, 6};"
925 self.assertEqual(self.get_decl(d4, 0),
926 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['char']]]])
927 self.assertEqual(self.get_decl_init(d4, 0),
928 ['Constant', 'char', "'c'"])
929 self.assertEqual(self.get_decl(d4, 1),
930 ['Decl', 'p',
931 ['PtrDecl',
932 ['TypeDecl', ['IdentifierType', ['char']]]]])
eli.benderskyf890a862010-10-30 12:13:23 +0200933
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300934 self.assertEqual(self.get_decl_init(d4, 1),
935 [ ['Constant', 'int', '0'],
936 ['Constant', 'int', '1'],
937 ['Constant', 'int', '2'],
eli.benderskyf890a862010-10-30 12:13:23 +0200938 [['Constant', 'int', '4'],
939 ['Constant', 'int', '5']],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300940 ['Constant', 'int', '6']])
eli.benderskyf890a862010-10-30 12:13:23 +0200941
942 def test_decl_named_inits(self):
943 d1 = 'int a = {.k = 16};'
944 self.assertEqual(self.get_decl_init(d1),
945 [( [['ID', 'k']],
946 ['Constant', 'int', '16'])])
947
948 d2 = 'int a = { [0].a = {1}, [1].a[0] = 2 };'
949 self.assertEqual(self.get_decl_init(d2),
950 [
951 ([['Constant', 'int', '0'], ['ID', 'a']],
952 [['Constant', 'int', '1']]),
953 ([['Constant', 'int', '1'], ['ID', 'a'], ['Constant', 'int', '0']],
954 ['Constant', 'int', '2'])])
955
956 d3 = 'int a = { .a = 1, .c = 3, 4, .b = 5};'
957 self.assertEqual(self.get_decl_init(d3),
958 [
959 ([['ID', 'a']], ['Constant', 'int', '1']),
960 ([['ID', 'c']], ['Constant', 'int', '3']),
961 ['Constant', 'int', '4'],
962 ([['ID', 'b']], ['Constant', 'int', '5'])])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300963
964 def test_function_definitions(self):
965 def parse_fdef(str):
966 return self.parse(str).ext[0]
967
968 def fdef_decl(fdef):
969 return expand_decl(fdef.decl)
970
971 f1 = parse_fdef('''
972 int factorial(int p)
973 {
974 return 3;
975 }
976 ''')
977
978 self.assertEqual(fdef_decl(f1),
979 ['Decl', 'factorial',
980 ['FuncDecl',
981 [['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]]],
982 ['TypeDecl', ['IdentifierType', ['int']]]]])
983
eli.benderskyef29ff92010-10-29 16:25:43 +0200984 self.assertEqual(type(f1.body.block_items[0]), Return)
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300985
986 f2 = parse_fdef('''
987 char* zzz(int p, char* c)
988 {
989 int a;
990 char b;
991
992 a = b + 2;
993 return 3;
994 }
995 ''')
996
997 self.assertEqual(fdef_decl(f2),
998 ['Decl', 'zzz',
999 ['FuncDecl',
1000 [ ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]],
1001 ['Decl', 'c', ['PtrDecl',
1002 ['TypeDecl', ['IdentifierType', ['char']]]]]],
1003 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
1004
eli.benderskyef29ff92010-10-29 16:25:43 +02001005 self.assertEqual(list(map(type, f2.body.block_items)),
1006 [Decl, Decl, Assignment, Return])
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001007
1008 f3 = parse_fdef('''
1009 char* zzz(p, c)
1010 long p, *c;
1011 {
1012 int a;
1013 char b;
1014
1015 a = b + 2;
1016 return 3;
1017 }
1018 ''')
1019
1020 self.assertEqual(fdef_decl(f3),
1021 ['Decl', 'zzz',
1022 ['FuncDecl',
1023 [ ['ID', 'p'],
1024 ['ID', 'c']],
1025 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
1026
eli.benderskyef29ff92010-10-29 16:25:43 +02001027 self.assertEqual(list(map(type, f3.body.block_items)),
1028 [Decl, Decl, Assignment, Return])
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001029
1030 self.assertEqual(expand_decl(f3.param_decls[0]),
1031 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['long']]]])
1032 self.assertEqual(expand_decl(f3.param_decls[1]),
1033 ['Decl', 'c', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['long']]]]])
1034
eli.bendersky71540662010-07-03 12:58:52 +02001035 def test_unified_string_literals(self):
1036 # simple string, for reference
1037 d1 = self.get_decl_init('char* s = "hello";')
1038 self.assertEqual(d1, ['Constant', 'string', '"hello"'])
1039
1040 d2 = self.get_decl_init('char* s = "hello" " world";')
1041 self.assertEqual(d2, ['Constant', 'string', '"hello world"'])
1042
1043 # the test case from issue 6
1044 d3 = self.parse(r'''
1045 int main() {
1046 fprintf(stderr,
1047 "Wrong Params?\n"
1048 "Usage:\n"
1049 "%s <binary_file_path>\n",
1050 argv[0]
1051 );
1052 }
1053 ''')
1054
1055 self.assertEqual(
eli.benderskyef29ff92010-10-29 16:25:43 +02001056 d3.ext[0].body.block_items[0].args.exprs[1].value,
eli.bendersky71540662010-07-03 12:58:52 +02001057 r'"Wrong Params?\nUsage:\n%s <binary_file_path>\n"')
eli.bendersky4a89f112010-07-05 06:02:03 +02001058
1059 d4 = self.get_decl_init('char* s = "" "foobar";')
1060 self.assertEqual(d4, ['Constant', 'string', '"foobar"'])
1061
1062 d5 = self.get_decl_init(r'char* s = "foo\"" "bar";')
1063 self.assertEqual(d5, ['Constant', 'string', r'"foo\"bar"'])
eli.bendersky71540662010-07-03 12:58:52 +02001064
eli.bendersky79d5cf62010-10-29 13:33:52 +02001065 def test_inline_specifier(self):
1066 ps2 = self.parse('static inline void inlinefoo(void);')
1067 self.assertEqual(ps2.ext[0].funcspec, ['inline'])
eli.bendersky2e907fa2010-10-29 15:51:07 +02001068
1069 # variable length array
1070 def test_vla(self):
1071 ps2 = self.parse(r'''
1072 int main() {
1073 int size;
1074 int var[size = 5];
1075
1076 int var2[*];
1077 }
1078 ''')
eli.benderskyef29ff92010-10-29 16:25:43 +02001079 self.failUnless(isinstance(ps2.ext[0].body.block_items[1].type.dim, Assignment))
1080 self.failUnless(isinstance(ps2.ext[0].body.block_items[2].type.dim, ID))
eli.bendersky79d5cf62010-10-29 13:33:52 +02001081
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001082
eli.bendersky85d2e732011-05-20 19:47:26 +03001083class TestCParser_whole_code(TestCParser_base):
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001084 """ Testing of parsing whole chunks of code.
1085
1086 Since I don't want to rely on the structure of ASTs too
1087 much, most of these tests are implemented with visitors.
1088 """
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001089 # A simple helper visitor that lists the values of all the
1090 # Constant nodes it sees.
1091 #
1092 class ConstantVisitor(NodeVisitor):
1093 def __init__(self):
1094 self.values = []
1095
1096 def visit_Constant(self, node):
1097 self.values.append(node.value)
1098
1099 # This visitor counts the amount of references to the ID
1100 # with the name provided to it in the constructor.
1101 #
1102 class IDNameCounter(NodeVisitor):
1103 def __init__(self, name):
1104 self.name = name
1105 self.nrefs = 0
1106
1107 def visit_ID(self, node):
1108 if node.name == self.name:
1109 self.nrefs += 1
1110
1111 # Counts the amount of nodes of a given class
1112 #
1113 class NodeKlassCounter(NodeVisitor):
1114 def __init__(self, node_klass):
1115 self.klass = node_klass
1116 self.n = 0
1117
1118 def generic_visit(self, node):
1119 if node.__class__ == self.klass:
1120 self.n += 1
1121
1122 NodeVisitor.generic_visit(self, node)
1123
1124 def assert_all_Constants(self, code, constants):
1125 """ Asserts that the list of all Constant values (by
1126 'preorder' appearance) in the chunk of code is as
1127 given.
1128 """
eli.benderskyed890492010-06-25 08:25:55 +03001129 if isinstance(code, str):
1130 parsed = self.parse(code)
1131 else:
1132 parsed = code
1133
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001134 cv = self.ConstantVisitor()
1135 cv.visit(parsed)
1136 self.assertEqual(cv.values, constants)
1137
1138 def assert_num_ID_refs(self, code, name, num):
1139 """ Asserts the number of references to the ID with
1140 the given name.
1141 """
1142 if isinstance(code, str):
1143 parsed = self.parse(code)
1144 else:
1145 parsed = code
1146
1147 iv = self.IDNameCounter(name)
1148 iv.visit(parsed)
1149 self.assertEqual(iv.nrefs, num)
1150
1151 def assert_num_klass_nodes(self, code, klass, num):
1152 """ Asserts the amount of klass nodes in the code.
1153 """
1154 if isinstance(code, str):
1155 parsed = self.parse(code)
1156 else:
1157 parsed = code
1158
1159 cv = self.NodeKlassCounter(klass)
1160 cv.visit(parsed)
1161 self.assertEqual(cv.n, num)
1162
1163 def test_expressions(self):
1164 e1 = '''int k = (r + 10.0) >> 6 + 8 << (3 & 0x14);'''
1165 self.assert_all_Constants(e1, ['10.0', '6', '8', '3', '0x14'])
1166
1167 e2 = r'''char n = '\n', *prefix = "st_";'''
1168 self.assert_all_Constants(e2, [r"'\n'", '"st_"'])
1169
1170 def test_statements(self):
1171 s1 = r'''
1172 void foo(){
1173 if (sp == 1)
1174 if (optind >= argc ||
1175 argv[optind][0] != '-' || argv[optind][1] == '\0')
1176 return -1;
1177 else if (strcmp(argv[optind], "--") == 0) {
1178 optind++;
1179 return -1;
1180 }
1181 }
1182 '''
1183
1184 self.assert_all_Constants(s1,
1185 ['1', '0', r"'-'", '1', r"'\0'", '1', r'"--"', '0', '1'])
1186
1187 ps1 = self.parse(s1)
1188 self.assert_num_ID_refs(ps1, 'argv', 3)
1189 self.assert_num_ID_refs(ps1, 'optind', 5)
1190
1191 self.assert_num_klass_nodes(ps1, If, 3)
1192 self.assert_num_klass_nodes(ps1, Return, 2)
1193 self.assert_num_klass_nodes(ps1, FuncCall, 1) # strcmp
1194 self.assert_num_klass_nodes(ps1, BinaryOp, 7)
1195
1196 # In the following code, Hash and Node were defined as
1197 # int to pacify the parser that sees they're used as
1198 # types
1199 #
1200 s2 = r'''
1201 typedef int Hash, Node;
1202
1203 void HashDestroy(Hash* hash)
1204 {
1205 unsigned int i;
1206
1207 if (hash == NULL)
1208 return;
1209
1210 for (i = 0; i < hash->table_size; ++i)
1211 {
1212 Node* temp = hash->heads[i];
1213
1214 while (temp != NULL)
1215 {
1216 Node* temp2 = temp;
1217
1218 free(temp->entry->key);
1219 free(temp->entry->value);
1220 free(temp->entry);
1221
1222 temp = temp->next;
1223
1224 free(temp2);
1225 }
1226 }
1227
1228 free(hash->heads);
1229 hash->heads = NULL;
1230
1231 free(hash);
1232 }
1233 '''
1234
1235 ps2 = self.parse(s2)
1236 self.assert_num_klass_nodes(ps2, FuncCall, 6)
1237 self.assert_num_klass_nodes(ps2, FuncDef, 1)
1238 self.assert_num_klass_nodes(ps2, For, 1)
1239 self.assert_num_klass_nodes(ps2, While, 1)
1240 self.assert_num_klass_nodes(ps2, StructRef, 10)
1241
1242 # declarations don't count
1243 self.assert_num_ID_refs(ps2, 'hash', 6)
1244 self.assert_num_ID_refs(ps2, 'i', 4)
eli.benderskyed890492010-06-25 08:25:55 +03001245
1246 s3 = r'''
1247 void x(void) {
1248 int a, b;
1249 if (a < b)
1250 do {
1251 a = 0;
1252 } while (0);
1253 else if (a == b) {
1254 a = 1;
1255 }
1256 }
1257 '''
1258
1259 ps3 = self.parse(s3)
1260 self.assert_num_klass_nodes(ps3, DoWhile, 1)
1261 self.assert_num_ID_refs(ps3, 'a', 4)
1262 self.assert_all_Constants(ps3, ['0', '0', '1'])
eli.bendersky145890d2010-10-29 12:02:32 +02001263
1264 def test_for_statement(self):
1265 s2 = r'''
1266 void x(void)
1267 {
1268 int i;
1269 for (i = 0; i < 5; ++i) {
1270 x = 50;
1271 }
1272 }
1273 '''
1274 ps2 = self.parse(s2)
1275 self.assert_num_klass_nodes(ps2, For, 1)
1276 # here there are 3 refs to 'i' since the declaration doesn't count as
1277 # a ref in the visitor
1278 #
1279 self.assert_num_ID_refs(ps2, 'i', 3)
eli.benderskyed890492010-06-25 08:25:55 +03001280
eli.bendersky145890d2010-10-29 12:02:32 +02001281 s3 = r'''
1282 void x(void)
1283 {
1284 for (int i = 0; i < 5; ++i) {
1285 x = 50;
1286 }
1287 }
1288 '''
1289 ps3 = self.parse(s3)
eli.bendersky145890d2010-10-29 12:02:32 +02001290 self.assert_num_klass_nodes(ps3, For, 1)
1291 # here there are 2 refs to 'i' since the declaration doesn't count as
1292 # a ref in the visitor
1293 #
1294 self.assert_num_ID_refs(ps3, 'i', 2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001295
1296 def test_whole_file(self):
1297 # See how pycparser handles a whole, real C file.
1298 #
1299 filename = 'c_files/memmgr_with_h.c'
1300 code = open(filename, 'rU').read()
1301 p = self.parse(code)
1302
1303 self.assert_num_klass_nodes(p, FuncDef, 5)
1304
1305 # each FuncDef also has a FuncDecl. 4 declarations
1306 # + 5 definitions, overall 9
1307 self.assert_num_klass_nodes(p, FuncDecl, 9)
1308
1309 self.assert_num_klass_nodes(p, Typedef, 4)
1310
1311 self.assertEqual(p.ext[4].coord.line, 88)
1312 self.assertEqual(p.ext[4].coord.file, "./memmgr.h")
1313
1314 self.assertEqual(p.ext[6].coord.line, 10)
1315 self.assertEqual(p.ext[6].coord.file, "memmgr.c")
1316
1317 def test_whole_file_with_stdio(self):
1318 # Parse a whole file with stdio.h included by cpp
1319 #
1320 filename = 'c_files/cppd_with_stdio_h.c'
1321 code = open(filename, 'rU').read()
1322 p = self.parse(code)
1323
1324 self.failUnless(isinstance(p.ext[0], Typedef))
1325 self.assertEqual(p.ext[0].coord.line, 213)
1326 self.assertEqual(p.ext[0].coord.file, "D:\eli\cpp_stuff\libc_include/stddef.h")
1327
1328 self.failUnless(isinstance(p.ext[-1], FuncDef))
1329 self.assertEqual(p.ext[-1].coord.line, 15)
1330 self.assertEqual(p.ext[-1].coord.file, "example_c_file.c")
1331
1332 self.failUnless(isinstance(p.ext[-8], Typedef))
1333 self.failUnless(isinstance(p.ext[-8].type, TypeDecl))
1334 self.assertEqual(p.ext[-8].name, 'cookie_io_functions_t')
eli.bendersky85d2e732011-05-20 19:47:26 +03001335
1336
1337class TestCParser_typenames(TestCParser_base):
1338 """ Test issues related to the typedef-name problem.
1339 """
1340 def test_innerscope_typedef(self):
1341 # should fail since TT is not a type in bar
1342 s1 = r'''
1343 void foo() {
1344 typedef char TT;
1345 TT x;
1346 }
1347 void bar() {
1348 TT y;
1349 }
1350 '''
1351 self.assertRaises(ParseError, self.parse, s1)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001352
eli.bendersky85d2e732011-05-20 19:47:26 +03001353 # should succeed since TT is not a type in bar
1354 s2 = r'''
1355 void foo() {
1356 typedef char TT;
1357 TT x;
1358 }
1359 void bar() {
1360 unsigned TT;
1361 }
1362 '''
1363 self.failUnless(isinstance(self.parse(s2), FileAST))
1364
1365
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001366
1367if __name__ == '__main__':
1368 #~ suite = unittest.TestLoader().loadTestsFromNames(
1369 #~ ['test_c_parser.TestCParser_fundamentals.test_typedef'])
1370
1371 #~ suite = unittest.TestLoader().loadTestsFromNames(
1372 #~ ['test_c_parser.TestCParser_whole_code.test_whole_file_with_stdio'])
1373
1374 #~ suite = unittest.TestLoader().loadTestsFromTestCase(
1375 #~ TestCParser_whole_code)
1376
1377 #~ unittest.TextTestRunner(verbosity=2).run(suite)
1378 unittest.main()