blob: bae764c03acf91be2f5ea56affd393ccaf863c08 [file] [log] [blame]
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001#!/usr/bin/env python
2
3import pprint
4import re
Eli Benderskyd0973782012-01-19 08:09:33 +02005import os, sys
Eli Bendersky3921e8e2010-05-21 09:05:39 +03006import 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,
Eli Bendersky86f2eee2013-01-18 06:04:01 -080016 yacc_debug=True,
Eli Bendersky3921e8e2010-05-21 09:05:39 +030017 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)
Eli Bendersky86f2eee2013-01-18 06:04:01 -080025
Eli Bendersky3921e8e2010-05-21 09:05:39 +030026 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]
Eli Bendersky86f2eee2013-01-18 06:04:01 -080035 else:
Eli Bendersky3921e8e2010-05-21 09:05:39 +030036 nested = expand_decl(decl.type)
Eli Bendersky86f2eee2013-01-18 06:04:01 -080037
Eli Bendersky3921e8e2010-05-21 09:05:39 +030038 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]
Eli Bendersky86f2eee2013-01-18 06:04:01 -080061
Eli Bendersky3921e8e2010-05-21 09:05:39 +030062
63def expand_init(init):
64 """ Converts an initialization into a nested list
65 """
66 typ = type(init)
Eli Bendersky86f2eee2013-01-18 06:04:01 -080067
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))
Eli Bendersky293ea912012-12-25 14:52:48 -080071 elif typ in (InitList, ExprList):
eli.benderskyf890a862010-10-30 12:13:23 +020072 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)
Eli Bendersky86f2eee2013-01-18 06:04:01 -080082
Eli Bendersky3921e8e2010-05-21 09:05:39 +030083 def setUp(self):
84 self.cparser = _c_parser
Eli Bendersky86f2eee2013-01-18 06:04:01 -080085
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.
Eli Bendersky86f2eee2013-01-18 06:04:01 -080091
92 FileAST holds a list of 'external declarations'.
Eli Bendersky3921e8e2010-05-21 09:05:39 +030093 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)
Eli Bendersky86f2eee2013-01-18 06:04:01 -080098
Eli Bendersky3921e8e2010-05-21 09:05:39 +030099 def get_decl_init(self, txt, index=0):
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800100 """ Returns the expanded initializer of the declaration
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300101 at index.
102 """
103 t = self.parse(txt).ext[index]
104 return expand_init(t.init)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800105
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300106 def test_FileAST(self):
107 t = self.parse('int a; char c;')
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300108 self.assertTrue(isinstance(t, FileAST))
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300109 self.assertEqual(len(t.ext), 2)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800110
eli.bendersky43cf0b22011-10-19 05:56:15 +0200111 # empty file
112 t2 = self.parse('')
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300113 self.assertTrue(isinstance(t2, FileAST))
eli.bendersky43cf0b22011-10-19 05:56:15 +0200114 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)
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300119 self.assertTrue(isinstance(t, FileAST))
eli.bendersky38165b72011-02-04 08:13:39 +0200120 self.assertEqual(len(t.ext), 1)
121 self.assertEqual(self.get_decl(code),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800122 ['Decl', 'foo',
eli.bendersky38165b72011-02-04 08:13:39 +0200123 ['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 Bendersky86f2eee2013-01-18 06:04:01 -0800131 """ Tests the "coordinates" of parsed elements - file
eli.bendersky38165b72011-02-04 08:13:39 +0200132 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)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800136
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300137 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 Bendersky86f2eee2013-01-18 06:04:01 -0800156
eli.benderskyfc96e5e2011-03-04 09:51:23 +0200157 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 Bendersky86f2eee2013-01-18 06:04:01 -0800164
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300165 t2 = """
166 #line 99
167 int c;
168 """
169 self.assert_coord(self.parse(t2).ext[0], 99)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800170
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300171 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);
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800185
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300186 #line 30 "includes/daween.ph"
187 long j, k;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800188
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300189 #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')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800196 self.assert_coord(f4.ext[3], 50000, 'includes/daween.ph')
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300197
198 t5 = """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800199 int
200 #line 99
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300201 c;
202 """
203 self.assert_coord(self.parse(t5).ext[0], 99)
204
Eli Bendersky203b9672012-06-15 10:11:24 +0300205 # coord for ellipsis
206 t6 = """
207 int foo(int j,
208 ...) {
209 }"""
210 f6 = self.parse(t6, filename='z.c')
211 self.assert_coord(self.parse(t6).ext[0].decl.type.args.params[1], 3)
212
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300213 def test_simple_decls(self):
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800214 self.assertEqual(self.get_decl('int a;'),
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300215 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
216
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800217 self.assertEqual(self.get_decl('unsigned int a;'),
Eli Bendersky68497c22012-01-19 06:04:58 +0200218 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['unsigned', 'int']]]])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300219
eli.benderskyaffe0322011-09-24 06:16:55 +0300220 self.assertEqual(self.get_decl('_Bool a;'),
221 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['_Bool']]]])
222
Eli Benderskyf4d73462012-01-19 05:56:27 +0200223 self.assertEqual(self.get_decl('float _Complex fcc;'),
Eli Bendersky68497c22012-01-19 06:04:58 +0200224 ['Decl', 'fcc', ['TypeDecl', ['IdentifierType', ['float', '_Complex']]]])
Eli Benderskyf4d73462012-01-19 05:56:27 +0200225
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800226 self.assertEqual(self.get_decl('char* string;'),
227 ['Decl', 'string',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300228 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]])
229
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800230 self.assertEqual(self.get_decl('long ar[15];'),
231 ['Decl', 'ar',
232 ['ArrayDecl', '15',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300233 ['TypeDecl', ['IdentifierType', ['long']]]]])
eli.bendersky98f45372010-10-30 09:46:29 +0200234
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800235 self.assertEqual(self.get_decl('long long ar[15];'),
236 ['Decl', 'ar',
237 ['ArrayDecl', '15',
eli.benderskyf890a862010-10-30 12:13:23 +0200238 ['TypeDecl', ['IdentifierType', ['long', 'long']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800239
240 self.assertEqual(self.get_decl('unsigned ar[];'),
241 ['Decl', 'ar',
242 ['ArrayDecl', '',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300243 ['TypeDecl', ['IdentifierType', ['unsigned']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800244
245 self.assertEqual(self.get_decl('int strlen(char* s);'),
246 ['Decl', 'strlen',
247 ['FuncDecl',
248 [['Decl', 's',
249 ['PtrDecl',
250 ['TypeDecl', ['IdentifierType', ['char']]]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300251 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800252
253 self.assertEqual(self.get_decl('int strcmp(char* s1, char* s2);'),
254 ['Decl', 'strcmp',
255 ['FuncDecl',
256 [ ['Decl', 's1',
257 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
258 ['Decl', 's2',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300259 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800260 ],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300261 ['TypeDecl', ['IdentifierType', ['int']]]]])
262
Sye van der Veen51a46ec2013-06-10 12:56:15 -0400263 # function return values and parameters may not have type information
264 self.assertEqual(self.get_decl('extern foobar(foo, bar);'),
265 ['Decl', 'foobar',
266 ['FuncDecl',
267 [ ['ID', 'foo'],
268 ['ID', 'bar']
269 ],
270 ['TypeDecl', ['IdentifierType', ['int']]]]])
271
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300272 def test_nested_decls(self): # the fun begins
273 self.assertEqual(self.get_decl('char** ar2D;'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800274 ['Decl', 'ar2D',
275 ['PtrDecl', ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300276 ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800277
278 self.assertEqual(self.get_decl('int (*a)[1][2];'),
279 ['Decl', 'a',
280 ['PtrDecl',
281 ['ArrayDecl', '1',
282 ['ArrayDecl', '2',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300283 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
284
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800285 self.assertEqual(self.get_decl('int *a[1][2];'),
286 ['Decl', 'a',
287 ['ArrayDecl', '1',
288 ['ArrayDecl', '2',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300289 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['int']]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800290
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300291 self.assertEqual(self.get_decl('char ***ar3D[40];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800292 ['Decl', 'ar3D',
293 ['ArrayDecl', '40',
294 ['PtrDecl', ['PtrDecl', ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300295 ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800296
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300297 self.assertEqual(self.get_decl('char (***ar3D)[40];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800298 ['Decl', 'ar3D',
299 ['PtrDecl', ['PtrDecl', ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300300 ['ArrayDecl', '40', ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800301
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300302 self.assertEqual(self.get_decl('int (*x[4])(char, int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800303 ['Decl', 'x',
304 ['ArrayDecl', '4',
305 ['PtrDecl',
306 ['FuncDecl',
307 [ ['Typename', ['TypeDecl', ['IdentifierType', ['char']]]],
308 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300309 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800310
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300311 self.assertEqual(self.get_decl('char *(*(**foo [][8])())[];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800312 ['Decl', 'foo',
313 ['ArrayDecl', '',
314 ['ArrayDecl', '8',
315 ['PtrDecl', ['PtrDecl',
316 ['FuncDecl',
317 [],
318 ['PtrDecl',
319 ['ArrayDecl', '',
320 ['PtrDecl',
321 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300322 ['IdentifierType', ['char']]]]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800323
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300324 # explore named and unnamed function pointer parameters,
325 # with and without qualifiers
326 #
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800327
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300328 # unnamed w/o quals
329 self.assertEqual(self.get_decl('int (*k)(int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800330 ['Decl', 'k',
331 ['PtrDecl',
332 ['FuncDecl',
333 [['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300334 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800335
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300336 # unnamed w/ quals
337 self.assertEqual(self.get_decl('int (*k)(const int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800338 ['Decl', 'k',
339 ['PtrDecl',
340 ['FuncDecl',
341 [['Typename', ['const'], ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300342 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800343
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300344 # named w/o quals
345 self.assertEqual(self.get_decl('int (*k)(int q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800346 ['Decl', 'k',
347 ['PtrDecl',
348 ['FuncDecl',
349 [['Decl', 'q', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300350 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800351
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300352 # named w/ quals
353 self.assertEqual(self.get_decl('int (*k)(const volatile int q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800354 ['Decl', 'k',
355 ['PtrDecl',
356 ['FuncDecl',
357 [['Decl', ['const', 'volatile'], 'q',
358 ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300359 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800360
eli.bendersky79d5cf62010-10-29 13:33:52 +0200361 # restrict qualifier
362 self.assertEqual(self.get_decl('int (*k)(restrict int* q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800363 ['Decl', 'k',
364 ['PtrDecl',
365 ['FuncDecl',
366 [['Decl', ['restrict'], 'q',
eli.bendersky79d5cf62010-10-29 13:33:52 +0200367 ['PtrDecl',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800368 ['TypeDecl', ['IdentifierType', ['int']]]]]],
eli.bendersky79d5cf62010-10-29 13:33:52 +0200369 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800370
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300371 def test_qualifiers_storage_specifiers(self):
372 def assert_qs(txt, index, quals, storage):
373 d = self.parse(txt).ext[index]
374 self.assertEqual(d.quals, quals)
375 self.assertEqual(d.storage, storage)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800376
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300377 assert_qs("extern int p;", 0, [], ['extern'])
378 assert_qs("const long p = 6;", 0, ['const'], [])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800379
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300380 d1 = "static const int p, q, r;"
381 for i in range(3):
382 assert_qs(d1, i, ['const'], ['static'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800383
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300384 d2 = "static char * const p;"
385 assert_qs(d2, 0, [], ['static'])
386 pdecl = self.parse(d2).ext[0].type
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300387 self.assertTrue(isinstance(pdecl, PtrDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300388 self.assertEqual(pdecl.quals, ['const'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800389
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300390 def test_sizeof(self):
391 e = """
392 void foo()
393 {
394 int a = sizeof k;
395 int b = sizeof(int);
eli.benderskyc51e1d32011-02-04 08:52:33 +0200396 int c = sizeof(int**);;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800397
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300398 char* p = "just to make sure this parses w/o error...";
399 int d = sizeof(int());
400 }
401 """
402 compound = self.parse(e).ext[0].body
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800403
eli.benderskyef29ff92010-10-29 16:25:43 +0200404 s1 = compound.block_items[0].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300405 self.assertTrue(isinstance(s1, UnaryOp))
406 self.assertEqual(s1.op, 'sizeof')
407 self.assertTrue(isinstance(s1.expr, ID))
408 self.assertEqual(s1.expr.name, 'k')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800409
eli.benderskyef29ff92010-10-29 16:25:43 +0200410 s2 = compound.block_items[1].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300411 self.assertEqual(expand_decl(s2.expr),
412 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800413
eli.benderskyef29ff92010-10-29 16:25:43 +0200414 s3 = compound.block_items[2].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300415 self.assertEqual(expand_decl(s3.expr),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800416 ['Typename',
417 ['PtrDecl',
418 ['PtrDecl',
419 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300420 ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800421
eli.bendersky9f481562010-10-30 15:50:47 +0200422 # The C99 compound literal feature
423 #
eli.benderskyf890a862010-10-30 12:13:23 +0200424 def test_compound_literals(self):
eli.bendersky9f481562010-10-30 15:50:47 +0200425 ps1 = self.parse(r'''
eli.benderskyf890a862010-10-30 12:13:23 +0200426 void foo() {
eli.bendersky9f481562010-10-30 15:50:47 +0200427 p = (long long){k};
428 tc = (struct jk){.a = {1, 2}, .b[0] = t};
429 }''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800430
eli.bendersky9f481562010-10-30 15:50:47 +0200431 compound = ps1.ext[0].body.block_items[0].rvalue
432 self.assertEqual(expand_decl(compound.type),
433 ['Typename', ['TypeDecl', ['IdentifierType', ['long', 'long']]]])
434 self.assertEqual(expand_init(compound.init),
435 [['ID', 'k']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800436
437 compound = ps1.ext[0].body.block_items[1].rvalue
eli.bendersky9f481562010-10-30 15:50:47 +0200438 self.assertEqual(expand_decl(compound.type),
439 ['Typename', ['TypeDecl', ['Struct', 'jk', []]]])
440 self.assertEqual(expand_init(compound.init),
441 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800442 ([['ID', 'a']], [['Constant', 'int', '1'], ['Constant', 'int', '2']]),
eli.bendersky9f481562010-10-30 15:50:47 +0200443 ([['ID', 'b'], ['Constant', 'int', '0']], ['ID', 't'])])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800444
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300445 def test_enums(self):
446 e1 = "enum mycolor op;"
447 e1_type = self.parse(e1).ext[0].type.type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800448
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300449 self.assertTrue(isinstance(e1_type, Enum))
450 self.assertEqual(e1_type.name, 'mycolor')
451 self.assertEqual(e1_type.values, None)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800452
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300453 e2 = "enum mysize {large=20, small, medium} shoes;"
454 e2_type = self.parse(e2).ext[0].type.type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800455
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300456 self.assertTrue(isinstance(e2_type, Enum))
457 self.assertEqual(e2_type.name, 'mysize')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800458
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300459 e2_elist = e2_type.values
460 self.assertTrue(isinstance(e2_elist, EnumeratorList))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800461
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300462 for e2_eval in e2_elist.enumerators:
463 self.assertTrue(isinstance(e2_eval, Enumerator))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800464
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300465 self.assertEqual(e2_elist.enumerators[0].name, 'large')
466 self.assertEqual(e2_elist.enumerators[0].value.value, '20')
467 self.assertEqual(e2_elist.enumerators[2].name, 'medium')
468 self.assertEqual(e2_elist.enumerators[2].value, None)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800469
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300470 # enum with trailing comma (C99 feature)
471 e3 = """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800472 enum
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300473 {
474 red,
475 blue,
476 green,
477 } color;
478 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800479
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300480 e3_type = self.parse(e3).ext[0].type.type
481 self.assertTrue(isinstance(e3_type, Enum))
482 e3_elist = e3_type.values
483 self.assertTrue(isinstance(e3_elist, EnumeratorList))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800484
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300485 for e3_eval in e3_elist.enumerators:
486 self.assertTrue(isinstance(e3_eval, Enumerator))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800487
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300488 self.assertEqual(e3_elist.enumerators[0].name, 'red')
489 self.assertEqual(e3_elist.enumerators[0].value, None)
490 self.assertEqual(e3_elist.enumerators[1].name, 'blue')
491 self.assertEqual(e3_elist.enumerators[2].name, 'green')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800492
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300493 def test_typedef(self):
494 # without typedef, error
495 s1 = """
496 node k;
497 """
498 self.assertRaises(ParseError, self.parse, s1)
499
500 # now with typedef, works
501 s2 = """
502 typedef void* node;
503 node k;
504 """
505 ps2 = self.parse(s2)
506 self.assertEqual(expand_decl(ps2.ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800507 ['Typedef', 'node',
508 ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300509 ['TypeDecl', ['IdentifierType', ['void']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800510
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300511 self.assertEqual(expand_decl(ps2.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800512 ['Decl', 'k',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300513 ['TypeDecl', ['IdentifierType', ['node']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800514
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300515 s3 = """
516 typedef int T;
517 typedef T *pT;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800518
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300519 pT aa, bb;
520 """
521 ps3 = self.parse(s3)
522 self.assertEqual(expand_decl(ps3.ext[3]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800523 ['Decl', 'bb',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300524 ['TypeDecl', ['IdentifierType', ['pT']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800525
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300526 s4 = '''
527 typedef char* __builtin_va_list;
528 typedef __builtin_va_list __gnuc_va_list;
529 '''
530 ps4 = self.parse(s4)
531 self.assertEqual(expand_decl(ps4.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800532 ['Typedef', '__gnuc_va_list',
533 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300534 ['IdentifierType', ['__builtin_va_list']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800535
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300536 s5 = '''typedef struct tagHash Hash;'''
537 ps5 = self.parse(s5)
538 self.assertEqual(expand_decl(ps5.ext[0]),
539 ['Typedef', 'Hash', ['TypeDecl', ['Struct', 'tagHash', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800540
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300541 def test_struct_union(self):
542 s1 = """
543 struct {
544 int id;
545 char* name;
546 } joe;
547 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800548
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300549 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800550 ['Decl', 'joe',
551 ['TypeDecl', ['Struct', None,
552 [ ['Decl', 'id',
553 ['TypeDecl',
554 ['IdentifierType', ['int']]]],
555 ['Decl', 'name',
556 ['PtrDecl',
557 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300558 ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800559
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300560 s2 = """
561 struct node p;
562 """
563 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800564 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300565 ['TypeDecl', ['Struct', 'node', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800566
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300567 s21 = """
568 union pri ra;
569 """
570 self.assertEqual(expand_decl(self.parse(s21).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800571 ['Decl', 'ra',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300572 ['TypeDecl', ['Union', 'pri', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800573
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300574 s3 = """
575 struct node* p;
576 """
577 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800578 ['Decl', 'p',
579 ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300580 ['TypeDecl', ['Struct', 'node', []]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800581
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300582 s4 = """
583 struct node;
584 """
585 self.assertEqual(expand_decl(self.parse(s4).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800586 ['Decl', None,
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300587 ['Struct', 'node', []]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800588
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300589 s5 = """
590 union
591 {
592 struct
593 {
594 int type;
595 } n;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800596
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300597 struct
598 {
599 int type;
600 int intnode;
601 } ni;
602 } u;
603 """
604 self.assertEqual(expand_decl(self.parse(s5).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800605 ['Decl', 'u',
606 ['TypeDecl',
607 ['Union', None,
608 [['Decl', 'n',
609 ['TypeDecl',
610 ['Struct', None,
611 [['Decl', 'type',
612 ['TypeDecl', ['IdentifierType', ['int']]]]]]]],
613 ['Decl', 'ni',
614 ['TypeDecl',
615 ['Struct', None,
616 [['Decl', 'type',
617 ['TypeDecl', ['IdentifierType', ['int']]]],
618 ['Decl', 'intnode',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300619 ['TypeDecl', ['IdentifierType', ['int']]]]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800620
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300621 s6 = """
622 typedef struct foo_tag
623 {
624 void* data;
625 } foo, *pfoo;
626 """
627 s6_ast = self.parse(s6)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800628
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300629 self.assertEqual(expand_decl(s6_ast.ext[0]),
630 ['Typedef', 'foo',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800631 ['TypeDecl',
632 ['Struct', 'foo_tag',
633 [['Decl', 'data',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300634 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800635
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300636 self.assertEqual(expand_decl(s6_ast.ext[1]),
637 ['Typedef', 'pfoo',
638 ['PtrDecl',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800639 ['TypeDecl',
640 ['Struct', 'foo_tag',
641 [['Decl', 'data',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300642 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800643
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300644 s7 = r"""
645 struct _on_exit_args {
646 void * _fnargs[32];
647 void * _dso_handle[32];
648
649 long _fntypes;
650 #line 77 "D:\eli\cpp_stuff\libc_include/sys/reent.h"
651
652 long _is_cxa;
653 };
654 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800655
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300656 s7_ast = self.parse(s7, filename='test.c')
657 self.assert_coord(s7_ast.ext[0].type.decls[2], 6, 'test.c')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800658 self.assert_coord(s7_ast.ext[0].type.decls[3], 78,
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300659 r'D:\eli\cpp_stuff\libc_include/sys/reent.h')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800660
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300661 s8 = """
662 typedef enum tagReturnCode {SUCCESS, FAIL} ReturnCode;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800663
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300664 typedef struct tagEntry
665 {
666 char* key;
667 char* value;
668 } Entry;
669
670
671 typedef struct tagNode
672 {
673 Entry* entry;
674
675 struct tagNode* next;
676 } Node;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800677
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300678 typedef struct tagHash
679 {
680 unsigned int table_size;
681
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800682 Node** heads;
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300683
684 } Hash;
685 """
686 s8_ast = self.parse(s8)
687 self.assertEqual(expand_decl(s8_ast.ext[3]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800688 ['Typedef', 'Hash',
689 ['TypeDecl', ['Struct', 'tagHash',
690 [['Decl', 'table_size',
691 ['TypeDecl', ['IdentifierType', ['unsigned', 'int']]]],
692 ['Decl', 'heads',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300693 ['PtrDecl', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['Node']]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800694
eli.bendersky697ecc52011-02-10 07:05:13 +0200695 def test_anonymous_struct_union(self):
696 s1 = """
697 union
698 {
699 union
700 {
701 int i;
702 long l;
703 };
704
705 struct
706 {
707 int type;
708 int intnode;
709 };
710 } u;
711 """
712
713 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
714 ['Decl', 'u',
715 ['TypeDecl',
716 ['Union', None,
717 [['Decl', None,
718 ['Union', None,
719 [['Decl', 'i',
720 ['TypeDecl',
721 ['IdentifierType', ['int']]]],
722 ['Decl', 'l',
723 ['TypeDecl',
724 ['IdentifierType', ['long']]]]]]],
725 ['Decl', None,
726 ['Struct', None,
727 [['Decl', 'type',
728 ['TypeDecl',
729 ['IdentifierType', ['int']]]],
730 ['Decl', 'intnode',
731 ['TypeDecl',
732 ['IdentifierType', ['int']]]]]]]]]]])
733
734 s2 = """
735 struct
736 {
737 int i;
738 union
739 {
740 int id;
741 char* name;
742 };
743 float f;
744 } joe;
745 """
746
747 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
748 ['Decl', 'joe',
749 ['TypeDecl',
750 ['Struct', None,
751 [['Decl', 'i',
752 ['TypeDecl',
753 ['IdentifierType', ['int']]]],
754 ['Decl', None,
755 ['Union', None,
756 [['Decl', 'id',
757 ['TypeDecl',
758 ['IdentifierType', ['int']]]],
759 ['Decl', 'name',
760 ['PtrDecl',
761 ['TypeDecl',
762 ['IdentifierType', ['char']]]]]]]],
763 ['Decl', 'f',
764 ['TypeDecl',
765 ['IdentifierType', ['float']]]]]]]])
766
767 # ISO/IEC 9899:201x Commitee Draft 2010-11-16, N1539
768 # section 6.7.2.1, par. 19, example 1
769 s3 = """
770 struct v {
771 union {
772 struct { int i, j; };
773 struct { long k, l; } w;
774 };
775 int m;
776 } v1;
777 """
778
779 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
780 ['Decl', 'v1',
781 ['TypeDecl',
782 ['Struct', 'v',
783 [['Decl', None,
784 ['Union', None,
785 [['Decl', None,
786 ['Struct', None,
787 [['Decl', 'i',
788 ['TypeDecl',
789 ['IdentifierType', ['int']]]],
790 ['Decl', 'j',
791 ['TypeDecl',
792 ['IdentifierType', ['int']]]]]]],
793 ['Decl', 'w',
794 ['TypeDecl',
795 ['Struct', None,
796 [['Decl', 'k',
797 ['TypeDecl',
798 ['IdentifierType', ['long']]]],
799 ['Decl', 'l',
800 ['TypeDecl',
801 ['IdentifierType', ['long']]]]]]]]]]],
802 ['Decl', 'm',
803 ['TypeDecl',
804 ['IdentifierType', ['int']]]]]]]])
805
eli.benderskydce29a02011-02-10 07:55:00 +0200806 s4 = """
807 struct v {
808 int i;
809 float;
810 } v2;"""
eli.bendersky6b011792011-06-22 17:50:56 +0300811 # just make sure this doesn't raise ParseError
812 self.parse(s4)
eli.benderskydce29a02011-02-10 07:55:00 +0200813
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200814 def test_struct_bitfields(self):
eli.bendersky38ed9a92010-10-09 09:29:59 +0200815 # a struct with two bitfields, one unnamed
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200816 s1 = """
817 struct {
818 int k:6;
819 int :2;
820 } joe;
821 """
822
823 parsed_struct = self.parse(s1).ext[0]
824
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800825 # We can see here the name of the decl for the unnamed bitfield is
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200826 # None, but expand_decl doesn't show bitfield widths
827 # ...
828 self.assertEqual(expand_decl(parsed_struct),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800829 ['Decl', 'joe',
830 ['TypeDecl', ['Struct', None,
831 [ ['Decl', 'k',
832 ['TypeDecl',
833 ['IdentifierType', ['int']]]],
834 ['Decl', None,
835 ['TypeDecl',
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200836 ['IdentifierType', ['int']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800837
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200838 # ...
839 # so we test them manually
840 self.assertEqual(parsed_struct.type.type.decls[0].bitsize.value, '6')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800841 self.assertEqual(parsed_struct.type.type.decls[1].bitsize.value, '2')
842
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300843 def test_tags_namespace(self):
844 """ Tests that the tags of structs/unions/enums reside in a separate namespace and
845 can be named after existing types.
846 """
847 s1 = """
848 typedef int tagEntry;
849
850 struct tagEntry
851 {
852 char* key;
853 char* value;
854 } Entry;
855 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800856
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300857 s1_ast = self.parse(s1)
858 self.assertEqual(expand_decl(s1_ast.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800859 ['Decl', 'Entry',
860 ['TypeDecl', ['Struct', 'tagEntry',
861 [['Decl', 'key',
862 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
863 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300864 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800865
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300866 s2 = """
867 struct tagEntry;
868
869 typedef struct tagEntry tagEntry;
870
871 struct tagEntry
872 {
873 char* key;
874 char* value;
875 } Entry;
876 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800877
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300878 s2_ast = self.parse(s2)
879 self.assertEqual(expand_decl(s2_ast.ext[2]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800880 ['Decl', 'Entry',
881 ['TypeDecl', ['Struct', 'tagEntry',
882 [['Decl', 'key',
883 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
884 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300885 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800886
887 s3 = """
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300888 typedef int mytag;
889
890 enum mytag {ABC, CDE};
891 enum mytag joe;
892 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800893
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300894 s3_type = self.parse(s3).ext[1].type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800895
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300896 self.assertTrue(isinstance(s3_type, Enum))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800897 self.assertEqual(s3_type.name, 'mytag')
898
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300899 def test_multi_decls(self):
900 d1 = 'int a, b;'
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800901
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300902 self.assertEqual(self.get_decl(d1, 0),
903 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
904 self.assertEqual(self.get_decl(d1, 1),
905 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['int']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800906
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300907 d2 = 'char* p, notp, ar[4];'
908 self.assertEqual(self.get_decl(d2, 0),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800909 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300910 ['PtrDecl',
911 ['TypeDecl', ['IdentifierType', ['char']]]]])
912 self.assertEqual(self.get_decl(d2, 1),
913 ['Decl', 'notp', ['TypeDecl', ['IdentifierType', ['char']]]])
914 self.assertEqual(self.get_decl(d2, 2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800915 ['Decl', 'ar',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300916 ['ArrayDecl', '4',
917 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800918
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300919 def test_invalid_multiple_types_error(self):
920 bad = [
921 'int enum {ab, cd} fubr;',
922 'enum kid char brbr;']
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800923
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300924 for b in bad:
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800925 self.assertRaises(ParseError, self.parse, b)
Eli Bendersky9dadc3f2012-07-06 15:53:53 +0300926
927 # Issue 60
928 badcode1 = '''
929 typedef int numbertype;
930 typedef char numbertype;
931 '''
932 try:
933 self.parse(badcode1)
934 except ParseError as err:
935 self.assertTrue(':3' in str(err))
936 else:
937 self.fail('Expected fail with ParseError')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800938
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300939 def test_decl_inits(self):
940 d1 = 'int a = 16;'
eli.benderskyf890a862010-10-30 12:13:23 +0200941 #~ self.parse(d1).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300942 self.assertEqual(self.get_decl(d1),
943 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
944 self.assertEqual(self.get_decl_init(d1),
945 ['Constant', 'int', '16'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800946
Eli Bendersky3b1b08d2012-06-15 12:37:54 +0300947 d1_1 = 'float f = 0xEF.56p1;'
948 self.assertEqual(self.get_decl_init(d1_1),
949 ['Constant', 'float', '0xEF.56p1'])
950
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300951 d2 = 'long ar[] = {7, 8, 9};'
eli.benderskyf890a862010-10-30 12:13:23 +0200952 #~ self.parse(d2).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300953 self.assertEqual(self.get_decl(d2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800954 ['Decl', 'ar',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300955 ['ArrayDecl', '',
956 ['TypeDecl', ['IdentifierType', ['long']]]]])
957 self.assertEqual(self.get_decl_init(d2),
958 [ ['Constant', 'int', '7'],
959 ['Constant', 'int', '8'],
eli.benderskyf890a862010-10-30 12:13:23 +0200960 ['Constant', 'int', '9']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800961
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300962 d3 = 'char p = j;'
963 self.assertEqual(self.get_decl(d3),
964 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['char']]]])
965 self.assertEqual(self.get_decl_init(d3),
966 ['ID', 'j'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800967
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300968 d4 = "char x = 'c', *p = {0, 1, 2, {4, 5}, 6};"
969 self.assertEqual(self.get_decl(d4, 0),
970 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['char']]]])
971 self.assertEqual(self.get_decl_init(d4, 0),
972 ['Constant', 'char', "'c'"])
973 self.assertEqual(self.get_decl(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800974 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300975 ['PtrDecl',
976 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800977
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300978 self.assertEqual(self.get_decl_init(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800979 [ ['Constant', 'int', '0'],
980 ['Constant', 'int', '1'],
981 ['Constant', 'int', '2'],
982 [['Constant', 'int', '4'],
983 ['Constant', 'int', '5']],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300984 ['Constant', 'int', '6']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800985
eli.benderskyf890a862010-10-30 12:13:23 +0200986 def test_decl_named_inits(self):
987 d1 = 'int a = {.k = 16};'
988 self.assertEqual(self.get_decl_init(d1),
989 [( [['ID', 'k']],
990 ['Constant', 'int', '16'])])
991
992 d2 = 'int a = { [0].a = {1}, [1].a[0] = 2 };'
993 self.assertEqual(self.get_decl_init(d2),
994 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800995 ([['Constant', 'int', '0'], ['ID', 'a']],
996 [['Constant', 'int', '1']]),
997 ([['Constant', 'int', '1'], ['ID', 'a'], ['Constant', 'int', '0']],
eli.benderskyf890a862010-10-30 12:13:23 +0200998 ['Constant', 'int', '2'])])
999
1000 d3 = 'int a = { .a = 1, .c = 3, 4, .b = 5};'
1001 self.assertEqual(self.get_decl_init(d3),
1002 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001003 ([['ID', 'a']], ['Constant', 'int', '1']),
1004 ([['ID', 'c']], ['Constant', 'int', '3']),
1005 ['Constant', 'int', '4'],
eli.benderskyf890a862010-10-30 12:13:23 +02001006 ([['ID', 'b']], ['Constant', 'int', '5'])])
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001007
1008 def test_function_definitions(self):
1009 def parse_fdef(str):
1010 return self.parse(str).ext[0]
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001011
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001012 def fdef_decl(fdef):
1013 return expand_decl(fdef.decl)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001014
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001015 f1 = parse_fdef('''
1016 int factorial(int p)
1017 {
1018 return 3;
1019 }
1020 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001021
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001022 self.assertEqual(fdef_decl(f1),
1023 ['Decl', 'factorial',
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001024 ['FuncDecl',
1025 [['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001026 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001027
eli.benderskyef29ff92010-10-29 16:25:43 +02001028 self.assertEqual(type(f1.body.block_items[0]), Return)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001029
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001030 f2 = parse_fdef('''
1031 char* zzz(int p, char* c)
1032 {
1033 int a;
1034 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001035
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001036 a = b + 2;
1037 return 3;
1038 }
1039 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001040
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001041 self.assertEqual(fdef_decl(f2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001042 ['Decl', 'zzz',
1043 ['FuncDecl',
1044 [ ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]],
1045 ['Decl', 'c', ['PtrDecl',
1046 ['TypeDecl', ['IdentifierType', ['char']]]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001047 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001048
1049 self.assertEqual(list(map(type, f2.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001050 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001051
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001052 f3 = parse_fdef('''
1053 char* zzz(p, c)
1054 long p, *c;
1055 {
1056 int a;
1057 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001058
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001059 a = b + 2;
1060 return 3;
1061 }
1062 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001063
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001064 self.assertEqual(fdef_decl(f3),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001065 ['Decl', 'zzz',
1066 ['FuncDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001067 [ ['ID', 'p'],
1068 ['ID', 'c']],
1069 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001070
1071 self.assertEqual(list(map(type, f3.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001072 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001073
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001074 self.assertEqual(expand_decl(f3.param_decls[0]),
1075 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['long']]]])
1076 self.assertEqual(expand_decl(f3.param_decls[1]),
1077 ['Decl', 'c', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['long']]]]])
1078
Sye van der Veen51a46ec2013-06-10 12:56:15 -04001079 # function return values and parameters may not have type information
1080 f4 = parse_fdef('''
1081 que(p)
1082 {
1083 return 3;
1084 }
1085 ''')
1086
1087 self.assertEqual(fdef_decl(f4),
1088 ['Decl', 'que',
1089 ['FuncDecl',
1090 [['ID', 'p']],
1091 ['TypeDecl', ['IdentifierType', ['int']]]]])
1092
eli.bendersky71540662010-07-03 12:58:52 +02001093 def test_unified_string_literals(self):
1094 # simple string, for reference
1095 d1 = self.get_decl_init('char* s = "hello";')
1096 self.assertEqual(d1, ['Constant', 'string', '"hello"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001097
eli.bendersky71540662010-07-03 12:58:52 +02001098 d2 = self.get_decl_init('char* s = "hello" " world";')
1099 self.assertEqual(d2, ['Constant', 'string', '"hello world"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001100
eli.bendersky71540662010-07-03 12:58:52 +02001101 # the test case from issue 6
1102 d3 = self.parse(r'''
1103 int main() {
1104 fprintf(stderr,
1105 "Wrong Params?\n"
1106 "Usage:\n"
1107 "%s <binary_file_path>\n",
1108 argv[0]
1109 );
1110 }
1111 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001112
eli.bendersky71540662010-07-03 12:58:52 +02001113 self.assertEqual(
eli.benderskyef29ff92010-10-29 16:25:43 +02001114 d3.ext[0].body.block_items[0].args.exprs[1].value,
eli.bendersky71540662010-07-03 12:58:52 +02001115 r'"Wrong Params?\nUsage:\n%s <binary_file_path>\n"')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001116
eli.bendersky4a89f112010-07-05 06:02:03 +02001117 d4 = self.get_decl_init('char* s = "" "foobar";')
1118 self.assertEqual(d4, ['Constant', 'string', '"foobar"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001119
eli.bendersky4a89f112010-07-05 06:02:03 +02001120 d5 = self.get_decl_init(r'char* s = "foo\"" "bar";')
1121 self.assertEqual(d5, ['Constant', 'string', r'"foo\"bar"'])
eli.bendersky71540662010-07-03 12:58:52 +02001122
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001123 def test_inline_specifier(self):
eli.bendersky79d5cf62010-10-29 13:33:52 +02001124 ps2 = self.parse('static inline void inlinefoo(void);')
1125 self.assertEqual(ps2.ext[0].funcspec, ['inline'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001126
eli.bendersky2e907fa2010-10-29 15:51:07 +02001127 # variable length array
1128 def test_vla(self):
1129 ps2 = self.parse(r'''
1130 int main() {
1131 int size;
1132 int var[size = 5];
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001133
eli.bendersky2e907fa2010-10-29 15:51:07 +02001134 int var2[*];
1135 }
1136 ''')
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001137 self.assertTrue(isinstance(ps2.ext[0].body.block_items[1].type.dim, Assignment))
1138 self.assertTrue(isinstance(ps2.ext[0].body.block_items[2].type.dim, ID))
eli.bendersky79d5cf62010-10-29 13:33:52 +02001139
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001140
eli.bendersky85d2e732011-05-20 19:47:26 +03001141class TestCParser_whole_code(TestCParser_base):
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001142 """ Testing of parsing whole chunks of code.
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001143
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001144 Since I don't want to rely on the structure of ASTs too
1145 much, most of these tests are implemented with visitors.
1146 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001147 # A simple helper visitor that lists the values of all the
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001148 # Constant nodes it sees.
1149 #
1150 class ConstantVisitor(NodeVisitor):
1151 def __init__(self):
1152 self.values = []
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001153
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001154 def visit_Constant(self, node):
1155 self.values.append(node.value)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001156
1157 # This visitor counts the amount of references to the ID
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001158 # with the name provided to it in the constructor.
1159 #
1160 class IDNameCounter(NodeVisitor):
1161 def __init__(self, name):
1162 self.name = name
1163 self.nrefs = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001164
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001165 def visit_ID(self, node):
1166 if node.name == self.name:
1167 self.nrefs += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001168
1169 # Counts the amount of nodes of a given class
1170 #
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001171 class NodeKlassCounter(NodeVisitor):
1172 def __init__(self, node_klass):
1173 self.klass = node_klass
1174 self.n = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001175
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001176 def generic_visit(self, node):
1177 if node.__class__ == self.klass:
1178 self.n += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001179
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001180 NodeVisitor.generic_visit(self, node)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001181
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001182 def assert_all_Constants(self, code, constants):
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001183 """ Asserts that the list of all Constant values (by
1184 'preorder' appearance) in the chunk of code is as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001185 given.
1186 """
eli.benderskyed890492010-06-25 08:25:55 +03001187 if isinstance(code, str):
1188 parsed = self.parse(code)
1189 else:
1190 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001191
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001192 cv = self.ConstantVisitor()
1193 cv.visit(parsed)
1194 self.assertEqual(cv.values, constants)
1195
1196 def assert_num_ID_refs(self, code, name, num):
1197 """ Asserts the number of references to the ID with
1198 the given name.
1199 """
1200 if isinstance(code, str):
1201 parsed = self.parse(code)
1202 else:
1203 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001204
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001205 iv = self.IDNameCounter(name)
1206 iv.visit(parsed)
1207 self.assertEqual(iv.nrefs, num)
1208
1209 def assert_num_klass_nodes(self, code, klass, num):
1210 """ Asserts the amount of klass nodes in the code.
1211 """
1212 if isinstance(code, str):
1213 parsed = self.parse(code)
1214 else:
1215 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001216
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001217 cv = self.NodeKlassCounter(klass)
1218 cv.visit(parsed)
1219 self.assertEqual(cv.n, num)
1220
1221 def test_expressions(self):
1222 e1 = '''int k = (r + 10.0) >> 6 + 8 << (3 & 0x14);'''
1223 self.assert_all_Constants(e1, ['10.0', '6', '8', '3', '0x14'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001224
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001225 e2 = r'''char n = '\n', *prefix = "st_";'''
1226 self.assert_all_Constants(e2, [r"'\n'", '"st_"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001227
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001228 def test_statements(self):
1229 s1 = r'''
1230 void foo(){
1231 if (sp == 1)
1232 if (optind >= argc ||
1233 argv[optind][0] != '-' || argv[optind][1] == '\0')
1234 return -1;
1235 else if (strcmp(argv[optind], "--") == 0) {
1236 optind++;
1237 return -1;
1238 }
1239 }
1240 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001241
1242 self.assert_all_Constants(s1,
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001243 ['1', '0', r"'-'", '1', r"'\0'", '1', r'"--"', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001244
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001245 ps1 = self.parse(s1)
1246 self.assert_num_ID_refs(ps1, 'argv', 3)
1247 self.assert_num_ID_refs(ps1, 'optind', 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001248
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001249 self.assert_num_klass_nodes(ps1, If, 3)
1250 self.assert_num_klass_nodes(ps1, Return, 2)
1251 self.assert_num_klass_nodes(ps1, FuncCall, 1) # strcmp
1252 self.assert_num_klass_nodes(ps1, BinaryOp, 7)
1253
1254 # In the following code, Hash and Node were defined as
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001255 # int to pacify the parser that sees they're used as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001256 # types
1257 #
1258 s2 = r'''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001259 typedef int Hash, Node;
1260
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001261 void HashDestroy(Hash* hash)
1262 {
1263 unsigned int i;
1264
1265 if (hash == NULL)
1266 return;
1267
1268 for (i = 0; i < hash->table_size; ++i)
1269 {
1270 Node* temp = hash->heads[i];
1271
1272 while (temp != NULL)
1273 {
1274 Node* temp2 = temp;
1275
1276 free(temp->entry->key);
1277 free(temp->entry->value);
1278 free(temp->entry);
1279
1280 temp = temp->next;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001281
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001282 free(temp2);
1283 }
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001284 }
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001285
1286 free(hash->heads);
1287 hash->heads = NULL;
1288
1289 free(hash);
1290 }
1291 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001292
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001293 ps2 = self.parse(s2)
1294 self.assert_num_klass_nodes(ps2, FuncCall, 6)
1295 self.assert_num_klass_nodes(ps2, FuncDef, 1)
1296 self.assert_num_klass_nodes(ps2, For, 1)
1297 self.assert_num_klass_nodes(ps2, While, 1)
1298 self.assert_num_klass_nodes(ps2, StructRef, 10)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001299
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001300 # declarations don't count
1301 self.assert_num_ID_refs(ps2, 'hash', 6)
1302 self.assert_num_ID_refs(ps2, 'i', 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001303
eli.benderskyed890492010-06-25 08:25:55 +03001304 s3 = r'''
1305 void x(void) {
1306 int a, b;
1307 if (a < b)
1308 do {
1309 a = 0;
1310 } while (0);
1311 else if (a == b) {
1312 a = 1;
1313 }
1314 }
1315 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001316
eli.benderskyed890492010-06-25 08:25:55 +03001317 ps3 = self.parse(s3)
1318 self.assert_num_klass_nodes(ps3, DoWhile, 1)
1319 self.assert_num_ID_refs(ps3, 'a', 4)
1320 self.assert_all_Constants(ps3, ['0', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001321
eli.bendersky91c0aa32011-10-16 05:50:43 +02001322 def test_empty_statement(self):
1323 s1 = r'''
1324 void foo(void){
1325 ;
1326 return;
1327 }
1328 '''
1329 ps1 = self.parse(s1)
1330 self.assert_num_klass_nodes(ps1, EmptyStatement, 1)
1331 self.assert_num_klass_nodes(ps1, Return, 1)
eli.bendersky145890d2010-10-29 12:02:32 +02001332
Ben5cd3fd62012-02-03 06:02:40 +02001333 def test_switch_statement(self):
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001334 def assert_case_node(node, const_value):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001335 self.assertTrue(isinstance(node, Case))
1336 self.assertTrue(isinstance(node.expr, Constant))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001337 self.assertEqual(node.expr.value, const_value)
1338
1339 def assert_default_node(node):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001340 self.assertTrue(isinstance(node, Default))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001341
Ben5cd3fd62012-02-03 06:02:40 +02001342 s1 = r'''
1343 int foo(void) {
1344 switch (myvar) {
1345 case 10:
1346 k = 10;
1347 p = k + 1;
1348 return 10;
1349 case 20:
1350 case 30:
1351 return 20;
1352 default:
1353 break;
1354 }
1355 return 0;
1356 }
1357 '''
1358 ps1 = self.parse(s1)
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001359 switch = ps1.ext[0].body.block_items[0]
1360
1361 block = switch.stmt.block_items
1362 assert_case_node(block[0], '10')
1363 self.assertEqual(len(block[0].stmts), 3)
1364 assert_case_node(block[1], '20')
1365 self.assertEqual(len(block[1].stmts), 0)
1366 assert_case_node(block[2], '30')
1367 self.assertEqual(len(block[2].stmts), 1)
1368 assert_default_node(block[3])
1369
1370 s2 = r'''
1371 int foo(void) {
1372 switch (myvar) {
1373 default:
1374 joe = moe;
1375 return 10;
1376 case 10:
1377 case 20:
1378 case 30:
1379 case 40:
1380 break;
1381 }
1382 return 0;
1383 }
1384 '''
1385 ps2 = self.parse(s2)
1386 switch = ps2.ext[0].body.block_items[0]
1387
1388 block = switch.stmt.block_items
1389 assert_default_node(block[0])
1390 self.assertEqual(len(block[0].stmts), 2)
1391 assert_case_node(block[1], '10')
1392 self.assertEqual(len(block[1].stmts), 0)
1393 assert_case_node(block[2], '20')
1394 self.assertEqual(len(block[1].stmts), 0)
1395 assert_case_node(block[3], '30')
1396 self.assertEqual(len(block[1].stmts), 0)
1397 assert_case_node(block[4], '40')
1398 self.assertEqual(len(block[4].stmts), 1)
Ben5cd3fd62012-02-03 06:02:40 +02001399
eli.bendersky145890d2010-10-29 12:02:32 +02001400 def test_for_statement(self):
1401 s2 = r'''
1402 void x(void)
1403 {
1404 int i;
1405 for (i = 0; i < 5; ++i) {
1406 x = 50;
1407 }
1408 }
1409 '''
1410 ps2 = self.parse(s2)
1411 self.assert_num_klass_nodes(ps2, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001412 # here there are 3 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001413 # a ref in the visitor
1414 #
1415 self.assert_num_ID_refs(ps2, 'i', 3)
Eli Bendersky4476d092012-12-25 14:07:57 -08001416
eli.bendersky145890d2010-10-29 12:02:32 +02001417 s3 = r'''
1418 void x(void)
1419 {
1420 for (int i = 0; i < 5; ++i) {
1421 x = 50;
1422 }
1423 }
1424 '''
1425 ps3 = self.parse(s3)
eli.bendersky145890d2010-10-29 12:02:32 +02001426 self.assert_num_klass_nodes(ps3, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001427 # here there are 2 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001428 # a ref in the visitor
1429 #
1430 self.assert_num_ID_refs(ps3, 'i', 2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001431
Eli Bendersky4476d092012-12-25 14:07:57 -08001432 s4 = r'''
1433 void x(void) {
1434 for (int i = 0;;)
1435 i;
1436 }
1437 '''
1438 ps4 = self.parse(s4)
1439 self.assert_num_ID_refs(ps4, 'i', 1)
1440
Eli Benderskyd0973782012-01-19 08:09:33 +02001441 def _open_c_file(self, name):
1442 """ Find a c file by name, taking into account the current dir can be
1443 in a couple of typical places
1444 """
1445 fullnames = [
1446 os.path.join('c_files', name),
1447 os.path.join('tests', 'c_files', name)]
1448 for fullname in fullnames:
1449 if os.path.exists(fullname):
1450 return open(fullname, 'rU')
1451 assert False, "Unreachable"
1452
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001453 def test_whole_file(self):
1454 # See how pycparser handles a whole, real C file.
1455 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001456 with self._open_c_file('memmgr_with_h.c') as f:
1457 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001458 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001459
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001460 self.assert_num_klass_nodes(p, FuncDef, 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001461
1462 # each FuncDef also has a FuncDecl. 4 declarations
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001463 # + 5 definitions, overall 9
1464 self.assert_num_klass_nodes(p, FuncDecl, 9)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001465
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001466 self.assert_num_klass_nodes(p, Typedef, 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001467
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001468 self.assertEqual(p.ext[4].coord.line, 88)
1469 self.assertEqual(p.ext[4].coord.file, "./memmgr.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001470
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001471 self.assertEqual(p.ext[6].coord.line, 10)
1472 self.assertEqual(p.ext[6].coord.file, "memmgr.c")
1473
1474 def test_whole_file_with_stdio(self):
1475 # Parse a whole file with stdio.h included by cpp
1476 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001477 with self._open_c_file('cppd_with_stdio_h.c') as f:
1478 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001479 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001480
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001481 self.assertTrue(isinstance(p.ext[0], Typedef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001482 self.assertEqual(p.ext[0].coord.line, 213)
1483 self.assertEqual(p.ext[0].coord.file, "D:\eli\cpp_stuff\libc_include/stddef.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001484
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001485 self.assertTrue(isinstance(p.ext[-1], FuncDef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001486 self.assertEqual(p.ext[-1].coord.line, 15)
1487 self.assertEqual(p.ext[-1].coord.file, "example_c_file.c")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001488
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001489 self.assertTrue(isinstance(p.ext[-8], Typedef))
1490 self.assertTrue(isinstance(p.ext[-8].type, TypeDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001491 self.assertEqual(p.ext[-8].name, 'cookie_io_functions_t')
eli.bendersky85d2e732011-05-20 19:47:26 +03001492
1493
1494class TestCParser_typenames(TestCParser_base):
1495 """ Test issues related to the typedef-name problem.
1496 """
1497 def test_innerscope_typedef(self):
1498 # should fail since TT is not a type in bar
1499 s1 = r'''
1500 void foo() {
1501 typedef char TT;
1502 TT x;
1503 }
1504 void bar() {
1505 TT y;
1506 }
1507 '''
1508 self.assertRaises(ParseError, self.parse, s1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001509
eli.bendersky85d2e732011-05-20 19:47:26 +03001510 # should succeed since TT is not a type in bar
1511 s2 = r'''
1512 void foo() {
1513 typedef char TT;
1514 TT x;
1515 }
1516 void bar() {
1517 unsigned TT;
1518 }
1519 '''
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001520 self.assertTrue(isinstance(self.parse(s2), FileAST))
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001521
eli.bendersky85d2e732011-05-20 19:47:26 +03001522
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001523
1524if __name__ == '__main__':
1525 #~ suite = unittest.TestLoader().loadTestsFromNames(
1526 #~ ['test_c_parser.TestCParser_fundamentals.test_typedef'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001527
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001528 #~ suite = unittest.TestLoader().loadTestsFromNames(
1529 #~ ['test_c_parser.TestCParser_whole_code.test_whole_file_with_stdio'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001530
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001531 #~ suite = unittest.TestLoader().loadTestsFromTestCase(
1532 #~ TestCParser_whole_code)
1533
1534 #~ unittest.TextTestRunner(verbosity=2).run(suite)
1535 unittest.main()