blob: e1ceec3082a90dfd4bfc7a20a3760ab38357d9fe [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
263 def test_nested_decls(self): # the fun begins
264 self.assertEqual(self.get_decl('char** ar2D;'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800265 ['Decl', 'ar2D',
266 ['PtrDecl', ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300267 ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800268
269 self.assertEqual(self.get_decl('int (*a)[1][2];'),
270 ['Decl', 'a',
271 ['PtrDecl',
272 ['ArrayDecl', '1',
273 ['ArrayDecl', '2',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300274 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
275
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800276 self.assertEqual(self.get_decl('int *a[1][2];'),
277 ['Decl', 'a',
278 ['ArrayDecl', '1',
279 ['ArrayDecl', '2',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300280 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['int']]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800281
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300282 self.assertEqual(self.get_decl('char ***ar3D[40];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800283 ['Decl', 'ar3D',
284 ['ArrayDecl', '40',
285 ['PtrDecl', ['PtrDecl', ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300286 ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800287
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300288 self.assertEqual(self.get_decl('char (***ar3D)[40];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800289 ['Decl', 'ar3D',
290 ['PtrDecl', ['PtrDecl', ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300291 ['ArrayDecl', '40', ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800292
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300293 self.assertEqual(self.get_decl('int (*x[4])(char, int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800294 ['Decl', 'x',
295 ['ArrayDecl', '4',
296 ['PtrDecl',
297 ['FuncDecl',
298 [ ['Typename', ['TypeDecl', ['IdentifierType', ['char']]]],
299 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300300 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800301
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300302 self.assertEqual(self.get_decl('char *(*(**foo [][8])())[];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800303 ['Decl', 'foo',
304 ['ArrayDecl', '',
305 ['ArrayDecl', '8',
306 ['PtrDecl', ['PtrDecl',
307 ['FuncDecl',
308 [],
309 ['PtrDecl',
310 ['ArrayDecl', '',
311 ['PtrDecl',
312 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300313 ['IdentifierType', ['char']]]]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800314
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300315 # explore named and unnamed function pointer parameters,
316 # with and without qualifiers
317 #
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800318
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300319 # unnamed w/o quals
320 self.assertEqual(self.get_decl('int (*k)(int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800321 ['Decl', 'k',
322 ['PtrDecl',
323 ['FuncDecl',
324 [['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300325 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800326
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300327 # unnamed w/ quals
328 self.assertEqual(self.get_decl('int (*k)(const int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800329 ['Decl', 'k',
330 ['PtrDecl',
331 ['FuncDecl',
332 [['Typename', ['const'], ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300333 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800334
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300335 # named w/o quals
336 self.assertEqual(self.get_decl('int (*k)(int q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800337 ['Decl', 'k',
338 ['PtrDecl',
339 ['FuncDecl',
340 [['Decl', 'q', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300341 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800342
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300343 # named w/ quals
344 self.assertEqual(self.get_decl('int (*k)(const volatile int q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800345 ['Decl', 'k',
346 ['PtrDecl',
347 ['FuncDecl',
348 [['Decl', ['const', 'volatile'], 'q',
349 ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300350 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800351
eli.bendersky79d5cf62010-10-29 13:33:52 +0200352 # restrict qualifier
353 self.assertEqual(self.get_decl('int (*k)(restrict int* q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800354 ['Decl', 'k',
355 ['PtrDecl',
356 ['FuncDecl',
357 [['Decl', ['restrict'], 'q',
eli.bendersky79d5cf62010-10-29 13:33:52 +0200358 ['PtrDecl',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800359 ['TypeDecl', ['IdentifierType', ['int']]]]]],
eli.bendersky79d5cf62010-10-29 13:33:52 +0200360 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800361
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300362 def test_qualifiers_storage_specifiers(self):
363 def assert_qs(txt, index, quals, storage):
364 d = self.parse(txt).ext[index]
365 self.assertEqual(d.quals, quals)
366 self.assertEqual(d.storage, storage)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800367
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300368 assert_qs("extern int p;", 0, [], ['extern'])
369 assert_qs("const long p = 6;", 0, ['const'], [])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800370
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300371 d1 = "static const int p, q, r;"
372 for i in range(3):
373 assert_qs(d1, i, ['const'], ['static'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800374
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300375 d2 = "static char * const p;"
376 assert_qs(d2, 0, [], ['static'])
377 pdecl = self.parse(d2).ext[0].type
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300378 self.assertTrue(isinstance(pdecl, PtrDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300379 self.assertEqual(pdecl.quals, ['const'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800380
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300381 def test_sizeof(self):
382 e = """
383 void foo()
384 {
385 int a = sizeof k;
386 int b = sizeof(int);
eli.benderskyc51e1d32011-02-04 08:52:33 +0200387 int c = sizeof(int**);;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800388
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300389 char* p = "just to make sure this parses w/o error...";
390 int d = sizeof(int());
391 }
392 """
393 compound = self.parse(e).ext[0].body
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800394
eli.benderskyef29ff92010-10-29 16:25:43 +0200395 s1 = compound.block_items[0].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300396 self.assertTrue(isinstance(s1, UnaryOp))
397 self.assertEqual(s1.op, 'sizeof')
398 self.assertTrue(isinstance(s1.expr, ID))
399 self.assertEqual(s1.expr.name, 'k')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800400
eli.benderskyef29ff92010-10-29 16:25:43 +0200401 s2 = compound.block_items[1].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300402 self.assertEqual(expand_decl(s2.expr),
403 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800404
eli.benderskyef29ff92010-10-29 16:25:43 +0200405 s3 = compound.block_items[2].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300406 self.assertEqual(expand_decl(s3.expr),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800407 ['Typename',
408 ['PtrDecl',
409 ['PtrDecl',
410 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300411 ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800412
eli.bendersky9f481562010-10-30 15:50:47 +0200413 # The C99 compound literal feature
414 #
eli.benderskyf890a862010-10-30 12:13:23 +0200415 def test_compound_literals(self):
eli.bendersky9f481562010-10-30 15:50:47 +0200416 ps1 = self.parse(r'''
eli.benderskyf890a862010-10-30 12:13:23 +0200417 void foo() {
eli.bendersky9f481562010-10-30 15:50:47 +0200418 p = (long long){k};
419 tc = (struct jk){.a = {1, 2}, .b[0] = t};
420 }''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800421
eli.bendersky9f481562010-10-30 15:50:47 +0200422 compound = ps1.ext[0].body.block_items[0].rvalue
423 self.assertEqual(expand_decl(compound.type),
424 ['Typename', ['TypeDecl', ['IdentifierType', ['long', 'long']]]])
425 self.assertEqual(expand_init(compound.init),
426 [['ID', 'k']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800427
428 compound = ps1.ext[0].body.block_items[1].rvalue
eli.bendersky9f481562010-10-30 15:50:47 +0200429 self.assertEqual(expand_decl(compound.type),
430 ['Typename', ['TypeDecl', ['Struct', 'jk', []]]])
431 self.assertEqual(expand_init(compound.init),
432 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800433 ([['ID', 'a']], [['Constant', 'int', '1'], ['Constant', 'int', '2']]),
eli.bendersky9f481562010-10-30 15:50:47 +0200434 ([['ID', 'b'], ['Constant', 'int', '0']], ['ID', 't'])])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800435
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300436 def test_enums(self):
437 e1 = "enum mycolor op;"
438 e1_type = self.parse(e1).ext[0].type.type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800439
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300440 self.assertTrue(isinstance(e1_type, Enum))
441 self.assertEqual(e1_type.name, 'mycolor')
442 self.assertEqual(e1_type.values, None)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800443
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300444 e2 = "enum mysize {large=20, small, medium} shoes;"
445 e2_type = self.parse(e2).ext[0].type.type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800446
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300447 self.assertTrue(isinstance(e2_type, Enum))
448 self.assertEqual(e2_type.name, 'mysize')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800449
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300450 e2_elist = e2_type.values
451 self.assertTrue(isinstance(e2_elist, EnumeratorList))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800452
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300453 for e2_eval in e2_elist.enumerators:
454 self.assertTrue(isinstance(e2_eval, Enumerator))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800455
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300456 self.assertEqual(e2_elist.enumerators[0].name, 'large')
457 self.assertEqual(e2_elist.enumerators[0].value.value, '20')
458 self.assertEqual(e2_elist.enumerators[2].name, 'medium')
459 self.assertEqual(e2_elist.enumerators[2].value, None)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800460
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300461 # enum with trailing comma (C99 feature)
462 e3 = """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800463 enum
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300464 {
465 red,
466 blue,
467 green,
468 } color;
469 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800470
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300471 e3_type = self.parse(e3).ext[0].type.type
472 self.assertTrue(isinstance(e3_type, Enum))
473 e3_elist = e3_type.values
474 self.assertTrue(isinstance(e3_elist, EnumeratorList))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800475
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300476 for e3_eval in e3_elist.enumerators:
477 self.assertTrue(isinstance(e3_eval, Enumerator))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800478
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300479 self.assertEqual(e3_elist.enumerators[0].name, 'red')
480 self.assertEqual(e3_elist.enumerators[0].value, None)
481 self.assertEqual(e3_elist.enumerators[1].name, 'blue')
482 self.assertEqual(e3_elist.enumerators[2].name, 'green')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800483
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300484 def test_typedef(self):
485 # without typedef, error
486 s1 = """
487 node k;
488 """
489 self.assertRaises(ParseError, self.parse, s1)
490
491 # now with typedef, works
492 s2 = """
493 typedef void* node;
494 node k;
495 """
496 ps2 = self.parse(s2)
497 self.assertEqual(expand_decl(ps2.ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800498 ['Typedef', 'node',
499 ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300500 ['TypeDecl', ['IdentifierType', ['void']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800501
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300502 self.assertEqual(expand_decl(ps2.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800503 ['Decl', 'k',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300504 ['TypeDecl', ['IdentifierType', ['node']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800505
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300506 s3 = """
507 typedef int T;
508 typedef T *pT;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800509
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300510 pT aa, bb;
511 """
512 ps3 = self.parse(s3)
513 self.assertEqual(expand_decl(ps3.ext[3]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800514 ['Decl', 'bb',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300515 ['TypeDecl', ['IdentifierType', ['pT']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800516
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300517 s4 = '''
518 typedef char* __builtin_va_list;
519 typedef __builtin_va_list __gnuc_va_list;
520 '''
521 ps4 = self.parse(s4)
522 self.assertEqual(expand_decl(ps4.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800523 ['Typedef', '__gnuc_va_list',
524 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300525 ['IdentifierType', ['__builtin_va_list']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800526
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300527 s5 = '''typedef struct tagHash Hash;'''
528 ps5 = self.parse(s5)
529 self.assertEqual(expand_decl(ps5.ext[0]),
530 ['Typedef', 'Hash', ['TypeDecl', ['Struct', 'tagHash', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800531
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300532 def test_struct_union(self):
533 s1 = """
534 struct {
535 int id;
536 char* name;
537 } joe;
538 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800539
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300540 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800541 ['Decl', 'joe',
542 ['TypeDecl', ['Struct', None,
543 [ ['Decl', 'id',
544 ['TypeDecl',
545 ['IdentifierType', ['int']]]],
546 ['Decl', 'name',
547 ['PtrDecl',
548 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300549 ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800550
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300551 s2 = """
552 struct node p;
553 """
554 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800555 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300556 ['TypeDecl', ['Struct', 'node', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800557
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300558 s21 = """
559 union pri ra;
560 """
561 self.assertEqual(expand_decl(self.parse(s21).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800562 ['Decl', 'ra',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300563 ['TypeDecl', ['Union', 'pri', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800564
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300565 s3 = """
566 struct node* p;
567 """
568 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800569 ['Decl', 'p',
570 ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300571 ['TypeDecl', ['Struct', 'node', []]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800572
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300573 s4 = """
574 struct node;
575 """
576 self.assertEqual(expand_decl(self.parse(s4).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800577 ['Decl', None,
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300578 ['Struct', 'node', []]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800579
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300580 s5 = """
581 union
582 {
583 struct
584 {
585 int type;
586 } n;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800587
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300588 struct
589 {
590 int type;
591 int intnode;
592 } ni;
593 } u;
594 """
595 self.assertEqual(expand_decl(self.parse(s5).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800596 ['Decl', 'u',
597 ['TypeDecl',
598 ['Union', None,
599 [['Decl', 'n',
600 ['TypeDecl',
601 ['Struct', None,
602 [['Decl', 'type',
603 ['TypeDecl', ['IdentifierType', ['int']]]]]]]],
604 ['Decl', 'ni',
605 ['TypeDecl',
606 ['Struct', None,
607 [['Decl', 'type',
608 ['TypeDecl', ['IdentifierType', ['int']]]],
609 ['Decl', 'intnode',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300610 ['TypeDecl', ['IdentifierType', ['int']]]]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800611
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300612 s6 = """
613 typedef struct foo_tag
614 {
615 void* data;
616 } foo, *pfoo;
617 """
618 s6_ast = self.parse(s6)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800619
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300620 self.assertEqual(expand_decl(s6_ast.ext[0]),
621 ['Typedef', 'foo',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800622 ['TypeDecl',
623 ['Struct', 'foo_tag',
624 [['Decl', 'data',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300625 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800626
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300627 self.assertEqual(expand_decl(s6_ast.ext[1]),
628 ['Typedef', 'pfoo',
629 ['PtrDecl',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800630 ['TypeDecl',
631 ['Struct', 'foo_tag',
632 [['Decl', 'data',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300633 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800634
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300635 s7 = r"""
636 struct _on_exit_args {
637 void * _fnargs[32];
638 void * _dso_handle[32];
639
640 long _fntypes;
641 #line 77 "D:\eli\cpp_stuff\libc_include/sys/reent.h"
642
643 long _is_cxa;
644 };
645 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800646
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300647 s7_ast = self.parse(s7, filename='test.c')
648 self.assert_coord(s7_ast.ext[0].type.decls[2], 6, 'test.c')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800649 self.assert_coord(s7_ast.ext[0].type.decls[3], 78,
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300650 r'D:\eli\cpp_stuff\libc_include/sys/reent.h')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800651
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300652 s8 = """
653 typedef enum tagReturnCode {SUCCESS, FAIL} ReturnCode;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800654
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300655 typedef struct tagEntry
656 {
657 char* key;
658 char* value;
659 } Entry;
660
661
662 typedef struct tagNode
663 {
664 Entry* entry;
665
666 struct tagNode* next;
667 } Node;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800668
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300669 typedef struct tagHash
670 {
671 unsigned int table_size;
672
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800673 Node** heads;
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300674
675 } Hash;
676 """
677 s8_ast = self.parse(s8)
678 self.assertEqual(expand_decl(s8_ast.ext[3]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800679 ['Typedef', 'Hash',
680 ['TypeDecl', ['Struct', 'tagHash',
681 [['Decl', 'table_size',
682 ['TypeDecl', ['IdentifierType', ['unsigned', 'int']]]],
683 ['Decl', 'heads',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300684 ['PtrDecl', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['Node']]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800685
eli.bendersky697ecc52011-02-10 07:05:13 +0200686 def test_anonymous_struct_union(self):
687 s1 = """
688 union
689 {
690 union
691 {
692 int i;
693 long l;
694 };
695
696 struct
697 {
698 int type;
699 int intnode;
700 };
701 } u;
702 """
703
704 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
705 ['Decl', 'u',
706 ['TypeDecl',
707 ['Union', None,
708 [['Decl', None,
709 ['Union', None,
710 [['Decl', 'i',
711 ['TypeDecl',
712 ['IdentifierType', ['int']]]],
713 ['Decl', 'l',
714 ['TypeDecl',
715 ['IdentifierType', ['long']]]]]]],
716 ['Decl', None,
717 ['Struct', None,
718 [['Decl', 'type',
719 ['TypeDecl',
720 ['IdentifierType', ['int']]]],
721 ['Decl', 'intnode',
722 ['TypeDecl',
723 ['IdentifierType', ['int']]]]]]]]]]])
724
725 s2 = """
726 struct
727 {
728 int i;
729 union
730 {
731 int id;
732 char* name;
733 };
734 float f;
735 } joe;
736 """
737
738 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
739 ['Decl', 'joe',
740 ['TypeDecl',
741 ['Struct', None,
742 [['Decl', 'i',
743 ['TypeDecl',
744 ['IdentifierType', ['int']]]],
745 ['Decl', None,
746 ['Union', None,
747 [['Decl', 'id',
748 ['TypeDecl',
749 ['IdentifierType', ['int']]]],
750 ['Decl', 'name',
751 ['PtrDecl',
752 ['TypeDecl',
753 ['IdentifierType', ['char']]]]]]]],
754 ['Decl', 'f',
755 ['TypeDecl',
756 ['IdentifierType', ['float']]]]]]]])
757
758 # ISO/IEC 9899:201x Commitee Draft 2010-11-16, N1539
759 # section 6.7.2.1, par. 19, example 1
760 s3 = """
761 struct v {
762 union {
763 struct { int i, j; };
764 struct { long k, l; } w;
765 };
766 int m;
767 } v1;
768 """
769
770 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
771 ['Decl', 'v1',
772 ['TypeDecl',
773 ['Struct', 'v',
774 [['Decl', None,
775 ['Union', None,
776 [['Decl', None,
777 ['Struct', None,
778 [['Decl', 'i',
779 ['TypeDecl',
780 ['IdentifierType', ['int']]]],
781 ['Decl', 'j',
782 ['TypeDecl',
783 ['IdentifierType', ['int']]]]]]],
784 ['Decl', 'w',
785 ['TypeDecl',
786 ['Struct', None,
787 [['Decl', 'k',
788 ['TypeDecl',
789 ['IdentifierType', ['long']]]],
790 ['Decl', 'l',
791 ['TypeDecl',
792 ['IdentifierType', ['long']]]]]]]]]]],
793 ['Decl', 'm',
794 ['TypeDecl',
795 ['IdentifierType', ['int']]]]]]]])
796
eli.benderskydce29a02011-02-10 07:55:00 +0200797 s4 = """
798 struct v {
799 int i;
800 float;
801 } v2;"""
eli.bendersky6b011792011-06-22 17:50:56 +0300802 # just make sure this doesn't raise ParseError
803 self.parse(s4)
eli.benderskydce29a02011-02-10 07:55:00 +0200804
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200805 def test_struct_bitfields(self):
eli.bendersky38ed9a92010-10-09 09:29:59 +0200806 # a struct with two bitfields, one unnamed
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200807 s1 = """
808 struct {
809 int k:6;
810 int :2;
811 } joe;
812 """
813
814 parsed_struct = self.parse(s1).ext[0]
815
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800816 # We can see here the name of the decl for the unnamed bitfield is
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200817 # None, but expand_decl doesn't show bitfield widths
818 # ...
819 self.assertEqual(expand_decl(parsed_struct),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800820 ['Decl', 'joe',
821 ['TypeDecl', ['Struct', None,
822 [ ['Decl', 'k',
823 ['TypeDecl',
824 ['IdentifierType', ['int']]]],
825 ['Decl', None,
826 ['TypeDecl',
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200827 ['IdentifierType', ['int']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800828
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200829 # ...
830 # so we test them manually
831 self.assertEqual(parsed_struct.type.type.decls[0].bitsize.value, '6')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800832 self.assertEqual(parsed_struct.type.type.decls[1].bitsize.value, '2')
833
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300834 def test_tags_namespace(self):
835 """ Tests that the tags of structs/unions/enums reside in a separate namespace and
836 can be named after existing types.
837 """
838 s1 = """
839 typedef int tagEntry;
840
841 struct tagEntry
842 {
843 char* key;
844 char* value;
845 } Entry;
846 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800847
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300848 s1_ast = self.parse(s1)
849 self.assertEqual(expand_decl(s1_ast.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800850 ['Decl', 'Entry',
851 ['TypeDecl', ['Struct', 'tagEntry',
852 [['Decl', 'key',
853 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
854 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300855 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800856
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300857 s2 = """
858 struct tagEntry;
859
860 typedef struct tagEntry tagEntry;
861
862 struct tagEntry
863 {
864 char* key;
865 char* value;
866 } Entry;
867 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800868
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300869 s2_ast = self.parse(s2)
870 self.assertEqual(expand_decl(s2_ast.ext[2]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800871 ['Decl', 'Entry',
872 ['TypeDecl', ['Struct', 'tagEntry',
873 [['Decl', 'key',
874 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
875 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300876 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800877
878 s3 = """
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300879 typedef int mytag;
880
881 enum mytag {ABC, CDE};
882 enum mytag joe;
883 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800884
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300885 s3_type = self.parse(s3).ext[1].type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800886
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300887 self.assertTrue(isinstance(s3_type, Enum))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800888 self.assertEqual(s3_type.name, 'mytag')
889
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300890 def test_multi_decls(self):
891 d1 = 'int a, b;'
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800892
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300893 self.assertEqual(self.get_decl(d1, 0),
894 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
895 self.assertEqual(self.get_decl(d1, 1),
896 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['int']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800897
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300898 d2 = 'char* p, notp, ar[4];'
899 self.assertEqual(self.get_decl(d2, 0),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800900 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300901 ['PtrDecl',
902 ['TypeDecl', ['IdentifierType', ['char']]]]])
903 self.assertEqual(self.get_decl(d2, 1),
904 ['Decl', 'notp', ['TypeDecl', ['IdentifierType', ['char']]]])
905 self.assertEqual(self.get_decl(d2, 2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800906 ['Decl', 'ar',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300907 ['ArrayDecl', '4',
908 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800909
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300910 def test_invalid_multiple_types_error(self):
911 bad = [
912 'int enum {ab, cd} fubr;',
913 'enum kid char brbr;']
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800914
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300915 for b in bad:
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800916 self.assertRaises(ParseError, self.parse, b)
Eli Bendersky9dadc3f2012-07-06 15:53:53 +0300917
918 # Issue 60
919 badcode1 = '''
920 typedef int numbertype;
921 typedef char numbertype;
922 '''
923 try:
924 self.parse(badcode1)
925 except ParseError as err:
926 self.assertTrue(':3' in str(err))
927 else:
928 self.fail('Expected fail with ParseError')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800929
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300930 def test_decl_inits(self):
931 d1 = 'int a = 16;'
eli.benderskyf890a862010-10-30 12:13:23 +0200932 #~ self.parse(d1).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300933 self.assertEqual(self.get_decl(d1),
934 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
935 self.assertEqual(self.get_decl_init(d1),
936 ['Constant', 'int', '16'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800937
Eli Bendersky3b1b08d2012-06-15 12:37:54 +0300938 d1_1 = 'float f = 0xEF.56p1;'
939 self.assertEqual(self.get_decl_init(d1_1),
940 ['Constant', 'float', '0xEF.56p1'])
941
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300942 d2 = 'long ar[] = {7, 8, 9};'
eli.benderskyf890a862010-10-30 12:13:23 +0200943 #~ self.parse(d2).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300944 self.assertEqual(self.get_decl(d2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800945 ['Decl', 'ar',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300946 ['ArrayDecl', '',
947 ['TypeDecl', ['IdentifierType', ['long']]]]])
948 self.assertEqual(self.get_decl_init(d2),
949 [ ['Constant', 'int', '7'],
950 ['Constant', 'int', '8'],
eli.benderskyf890a862010-10-30 12:13:23 +0200951 ['Constant', 'int', '9']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800952
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300953 d3 = 'char p = j;'
954 self.assertEqual(self.get_decl(d3),
955 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['char']]]])
956 self.assertEqual(self.get_decl_init(d3),
957 ['ID', 'j'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800958
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300959 d4 = "char x = 'c', *p = {0, 1, 2, {4, 5}, 6};"
960 self.assertEqual(self.get_decl(d4, 0),
961 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['char']]]])
962 self.assertEqual(self.get_decl_init(d4, 0),
963 ['Constant', 'char', "'c'"])
964 self.assertEqual(self.get_decl(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800965 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300966 ['PtrDecl',
967 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800968
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300969 self.assertEqual(self.get_decl_init(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800970 [ ['Constant', 'int', '0'],
971 ['Constant', 'int', '1'],
972 ['Constant', 'int', '2'],
973 [['Constant', 'int', '4'],
974 ['Constant', 'int', '5']],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300975 ['Constant', 'int', '6']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800976
eli.benderskyf890a862010-10-30 12:13:23 +0200977 def test_decl_named_inits(self):
978 d1 = 'int a = {.k = 16};'
979 self.assertEqual(self.get_decl_init(d1),
980 [( [['ID', 'k']],
981 ['Constant', 'int', '16'])])
982
983 d2 = 'int a = { [0].a = {1}, [1].a[0] = 2 };'
984 self.assertEqual(self.get_decl_init(d2),
985 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800986 ([['Constant', 'int', '0'], ['ID', 'a']],
987 [['Constant', 'int', '1']]),
988 ([['Constant', 'int', '1'], ['ID', 'a'], ['Constant', 'int', '0']],
eli.benderskyf890a862010-10-30 12:13:23 +0200989 ['Constant', 'int', '2'])])
990
991 d3 = 'int a = { .a = 1, .c = 3, 4, .b = 5};'
992 self.assertEqual(self.get_decl_init(d3),
993 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800994 ([['ID', 'a']], ['Constant', 'int', '1']),
995 ([['ID', 'c']], ['Constant', 'int', '3']),
996 ['Constant', 'int', '4'],
eli.benderskyf890a862010-10-30 12:13:23 +0200997 ([['ID', 'b']], ['Constant', 'int', '5'])])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300998
999 def test_function_definitions(self):
1000 def parse_fdef(str):
1001 return self.parse(str).ext[0]
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001002
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001003 def fdef_decl(fdef):
1004 return expand_decl(fdef.decl)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001005
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001006 f1 = parse_fdef('''
1007 int factorial(int p)
1008 {
1009 return 3;
1010 }
1011 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001012
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001013 self.assertEqual(fdef_decl(f1),
1014 ['Decl', 'factorial',
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001015 ['FuncDecl',
1016 [['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001017 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001018
eli.benderskyef29ff92010-10-29 16:25:43 +02001019 self.assertEqual(type(f1.body.block_items[0]), Return)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001020
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001021 f2 = parse_fdef('''
1022 char* zzz(int p, char* c)
1023 {
1024 int a;
1025 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001026
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001027 a = b + 2;
1028 return 3;
1029 }
1030 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001031
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001032 self.assertEqual(fdef_decl(f2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001033 ['Decl', 'zzz',
1034 ['FuncDecl',
1035 [ ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]],
1036 ['Decl', 'c', ['PtrDecl',
1037 ['TypeDecl', ['IdentifierType', ['char']]]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001038 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001039
1040 self.assertEqual(list(map(type, f2.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001041 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001042
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001043 f3 = parse_fdef('''
1044 char* zzz(p, c)
1045 long p, *c;
1046 {
1047 int a;
1048 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001049
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001050 a = b + 2;
1051 return 3;
1052 }
1053 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001054
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001055 self.assertEqual(fdef_decl(f3),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001056 ['Decl', 'zzz',
1057 ['FuncDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001058 [ ['ID', 'p'],
1059 ['ID', 'c']],
1060 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001061
1062 self.assertEqual(list(map(type, f3.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001063 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001064
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001065 self.assertEqual(expand_decl(f3.param_decls[0]),
1066 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['long']]]])
1067 self.assertEqual(expand_decl(f3.param_decls[1]),
1068 ['Decl', 'c', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['long']]]]])
1069
eli.bendersky71540662010-07-03 12:58:52 +02001070 def test_unified_string_literals(self):
1071 # simple string, for reference
1072 d1 = self.get_decl_init('char* s = "hello";')
1073 self.assertEqual(d1, ['Constant', 'string', '"hello"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001074
eli.bendersky71540662010-07-03 12:58:52 +02001075 d2 = self.get_decl_init('char* s = "hello" " world";')
1076 self.assertEqual(d2, ['Constant', 'string', '"hello world"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001077
eli.bendersky71540662010-07-03 12:58:52 +02001078 # the test case from issue 6
1079 d3 = self.parse(r'''
1080 int main() {
1081 fprintf(stderr,
1082 "Wrong Params?\n"
1083 "Usage:\n"
1084 "%s <binary_file_path>\n",
1085 argv[0]
1086 );
1087 }
1088 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001089
eli.bendersky71540662010-07-03 12:58:52 +02001090 self.assertEqual(
eli.benderskyef29ff92010-10-29 16:25:43 +02001091 d3.ext[0].body.block_items[0].args.exprs[1].value,
eli.bendersky71540662010-07-03 12:58:52 +02001092 r'"Wrong Params?\nUsage:\n%s <binary_file_path>\n"')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001093
eli.bendersky4a89f112010-07-05 06:02:03 +02001094 d4 = self.get_decl_init('char* s = "" "foobar";')
1095 self.assertEqual(d4, ['Constant', 'string', '"foobar"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001096
eli.bendersky4a89f112010-07-05 06:02:03 +02001097 d5 = self.get_decl_init(r'char* s = "foo\"" "bar";')
1098 self.assertEqual(d5, ['Constant', 'string', r'"foo\"bar"'])
eli.bendersky71540662010-07-03 12:58:52 +02001099
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001100 def test_inline_specifier(self):
eli.bendersky79d5cf62010-10-29 13:33:52 +02001101 ps2 = self.parse('static inline void inlinefoo(void);')
1102 self.assertEqual(ps2.ext[0].funcspec, ['inline'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001103
eli.bendersky2e907fa2010-10-29 15:51:07 +02001104 # variable length array
1105 def test_vla(self):
1106 ps2 = self.parse(r'''
1107 int main() {
1108 int size;
1109 int var[size = 5];
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001110
eli.bendersky2e907fa2010-10-29 15:51:07 +02001111 int var2[*];
1112 }
1113 ''')
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001114 self.assertTrue(isinstance(ps2.ext[0].body.block_items[1].type.dim, Assignment))
1115 self.assertTrue(isinstance(ps2.ext[0].body.block_items[2].type.dim, ID))
eli.bendersky79d5cf62010-10-29 13:33:52 +02001116
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001117
eli.bendersky85d2e732011-05-20 19:47:26 +03001118class TestCParser_whole_code(TestCParser_base):
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001119 """ Testing of parsing whole chunks of code.
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001120
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001121 Since I don't want to rely on the structure of ASTs too
1122 much, most of these tests are implemented with visitors.
1123 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001124 # A simple helper visitor that lists the values of all the
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001125 # Constant nodes it sees.
1126 #
1127 class ConstantVisitor(NodeVisitor):
1128 def __init__(self):
1129 self.values = []
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001130
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001131 def visit_Constant(self, node):
1132 self.values.append(node.value)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001133
1134 # This visitor counts the amount of references to the ID
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001135 # with the name provided to it in the constructor.
1136 #
1137 class IDNameCounter(NodeVisitor):
1138 def __init__(self, name):
1139 self.name = name
1140 self.nrefs = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001141
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001142 def visit_ID(self, node):
1143 if node.name == self.name:
1144 self.nrefs += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001145
1146 # Counts the amount of nodes of a given class
1147 #
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001148 class NodeKlassCounter(NodeVisitor):
1149 def __init__(self, node_klass):
1150 self.klass = node_klass
1151 self.n = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001152
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001153 def generic_visit(self, node):
1154 if node.__class__ == self.klass:
1155 self.n += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001156
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001157 NodeVisitor.generic_visit(self, node)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001158
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001159 def assert_all_Constants(self, code, constants):
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001160 """ Asserts that the list of all Constant values (by
1161 'preorder' appearance) in the chunk of code is as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001162 given.
1163 """
eli.benderskyed890492010-06-25 08:25:55 +03001164 if isinstance(code, str):
1165 parsed = self.parse(code)
1166 else:
1167 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001168
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001169 cv = self.ConstantVisitor()
1170 cv.visit(parsed)
1171 self.assertEqual(cv.values, constants)
1172
1173 def assert_num_ID_refs(self, code, name, num):
1174 """ Asserts the number of references to the ID with
1175 the given name.
1176 """
1177 if isinstance(code, str):
1178 parsed = self.parse(code)
1179 else:
1180 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001181
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001182 iv = self.IDNameCounter(name)
1183 iv.visit(parsed)
1184 self.assertEqual(iv.nrefs, num)
1185
1186 def assert_num_klass_nodes(self, code, klass, num):
1187 """ Asserts the amount of klass nodes in the code.
1188 """
1189 if isinstance(code, str):
1190 parsed = self.parse(code)
1191 else:
1192 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001193
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001194 cv = self.NodeKlassCounter(klass)
1195 cv.visit(parsed)
1196 self.assertEqual(cv.n, num)
1197
1198 def test_expressions(self):
1199 e1 = '''int k = (r + 10.0) >> 6 + 8 << (3 & 0x14);'''
1200 self.assert_all_Constants(e1, ['10.0', '6', '8', '3', '0x14'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001201
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001202 e2 = r'''char n = '\n', *prefix = "st_";'''
1203 self.assert_all_Constants(e2, [r"'\n'", '"st_"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001204
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001205 def test_statements(self):
1206 s1 = r'''
1207 void foo(){
1208 if (sp == 1)
1209 if (optind >= argc ||
1210 argv[optind][0] != '-' || argv[optind][1] == '\0')
1211 return -1;
1212 else if (strcmp(argv[optind], "--") == 0) {
1213 optind++;
1214 return -1;
1215 }
1216 }
1217 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001218
1219 self.assert_all_Constants(s1,
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001220 ['1', '0', r"'-'", '1', r"'\0'", '1', r'"--"', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001221
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001222 ps1 = self.parse(s1)
1223 self.assert_num_ID_refs(ps1, 'argv', 3)
1224 self.assert_num_ID_refs(ps1, 'optind', 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001225
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001226 self.assert_num_klass_nodes(ps1, If, 3)
1227 self.assert_num_klass_nodes(ps1, Return, 2)
1228 self.assert_num_klass_nodes(ps1, FuncCall, 1) # strcmp
1229 self.assert_num_klass_nodes(ps1, BinaryOp, 7)
1230
1231 # In the following code, Hash and Node were defined as
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001232 # int to pacify the parser that sees they're used as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001233 # types
1234 #
1235 s2 = r'''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001236 typedef int Hash, Node;
1237
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001238 void HashDestroy(Hash* hash)
1239 {
1240 unsigned int i;
1241
1242 if (hash == NULL)
1243 return;
1244
1245 for (i = 0; i < hash->table_size; ++i)
1246 {
1247 Node* temp = hash->heads[i];
1248
1249 while (temp != NULL)
1250 {
1251 Node* temp2 = temp;
1252
1253 free(temp->entry->key);
1254 free(temp->entry->value);
1255 free(temp->entry);
1256
1257 temp = temp->next;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001258
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001259 free(temp2);
1260 }
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001261 }
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001262
1263 free(hash->heads);
1264 hash->heads = NULL;
1265
1266 free(hash);
1267 }
1268 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001269
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001270 ps2 = self.parse(s2)
1271 self.assert_num_klass_nodes(ps2, FuncCall, 6)
1272 self.assert_num_klass_nodes(ps2, FuncDef, 1)
1273 self.assert_num_klass_nodes(ps2, For, 1)
1274 self.assert_num_klass_nodes(ps2, While, 1)
1275 self.assert_num_klass_nodes(ps2, StructRef, 10)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001276
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001277 # declarations don't count
1278 self.assert_num_ID_refs(ps2, 'hash', 6)
1279 self.assert_num_ID_refs(ps2, 'i', 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001280
eli.benderskyed890492010-06-25 08:25:55 +03001281 s3 = r'''
1282 void x(void) {
1283 int a, b;
1284 if (a < b)
1285 do {
1286 a = 0;
1287 } while (0);
1288 else if (a == b) {
1289 a = 1;
1290 }
1291 }
1292 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001293
eli.benderskyed890492010-06-25 08:25:55 +03001294 ps3 = self.parse(s3)
1295 self.assert_num_klass_nodes(ps3, DoWhile, 1)
1296 self.assert_num_ID_refs(ps3, 'a', 4)
1297 self.assert_all_Constants(ps3, ['0', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001298
eli.bendersky91c0aa32011-10-16 05:50:43 +02001299 def test_empty_statement(self):
1300 s1 = r'''
1301 void foo(void){
1302 ;
1303 return;
1304 }
1305 '''
1306 ps1 = self.parse(s1)
1307 self.assert_num_klass_nodes(ps1, EmptyStatement, 1)
1308 self.assert_num_klass_nodes(ps1, Return, 1)
eli.bendersky145890d2010-10-29 12:02:32 +02001309
Ben5cd3fd62012-02-03 06:02:40 +02001310 def test_switch_statement(self):
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001311 def assert_case_node(node, const_value):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001312 self.assertTrue(isinstance(node, Case))
1313 self.assertTrue(isinstance(node.expr, Constant))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001314 self.assertEqual(node.expr.value, const_value)
1315
1316 def assert_default_node(node):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001317 self.assertTrue(isinstance(node, Default))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001318
Ben5cd3fd62012-02-03 06:02:40 +02001319 s1 = r'''
1320 int foo(void) {
1321 switch (myvar) {
1322 case 10:
1323 k = 10;
1324 p = k + 1;
1325 return 10;
1326 case 20:
1327 case 30:
1328 return 20;
1329 default:
1330 break;
1331 }
1332 return 0;
1333 }
1334 '''
1335 ps1 = self.parse(s1)
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001336 switch = ps1.ext[0].body.block_items[0]
1337
1338 block = switch.stmt.block_items
1339 assert_case_node(block[0], '10')
1340 self.assertEqual(len(block[0].stmts), 3)
1341 assert_case_node(block[1], '20')
1342 self.assertEqual(len(block[1].stmts), 0)
1343 assert_case_node(block[2], '30')
1344 self.assertEqual(len(block[2].stmts), 1)
1345 assert_default_node(block[3])
1346
1347 s2 = r'''
1348 int foo(void) {
1349 switch (myvar) {
1350 default:
1351 joe = moe;
1352 return 10;
1353 case 10:
1354 case 20:
1355 case 30:
1356 case 40:
1357 break;
1358 }
1359 return 0;
1360 }
1361 '''
1362 ps2 = self.parse(s2)
1363 switch = ps2.ext[0].body.block_items[0]
1364
1365 block = switch.stmt.block_items
1366 assert_default_node(block[0])
1367 self.assertEqual(len(block[0].stmts), 2)
1368 assert_case_node(block[1], '10')
1369 self.assertEqual(len(block[1].stmts), 0)
1370 assert_case_node(block[2], '20')
1371 self.assertEqual(len(block[1].stmts), 0)
1372 assert_case_node(block[3], '30')
1373 self.assertEqual(len(block[1].stmts), 0)
1374 assert_case_node(block[4], '40')
1375 self.assertEqual(len(block[4].stmts), 1)
Ben5cd3fd62012-02-03 06:02:40 +02001376
eli.bendersky145890d2010-10-29 12:02:32 +02001377 def test_for_statement(self):
1378 s2 = r'''
1379 void x(void)
1380 {
1381 int i;
1382 for (i = 0; i < 5; ++i) {
1383 x = 50;
1384 }
1385 }
1386 '''
1387 ps2 = self.parse(s2)
1388 self.assert_num_klass_nodes(ps2, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001389 # here there are 3 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001390 # a ref in the visitor
1391 #
1392 self.assert_num_ID_refs(ps2, 'i', 3)
Eli Bendersky4476d092012-12-25 14:07:57 -08001393
eli.bendersky145890d2010-10-29 12:02:32 +02001394 s3 = r'''
1395 void x(void)
1396 {
1397 for (int i = 0; i < 5; ++i) {
1398 x = 50;
1399 }
1400 }
1401 '''
1402 ps3 = self.parse(s3)
eli.bendersky145890d2010-10-29 12:02:32 +02001403 self.assert_num_klass_nodes(ps3, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001404 # here there are 2 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001405 # a ref in the visitor
1406 #
1407 self.assert_num_ID_refs(ps3, 'i', 2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001408
Eli Bendersky4476d092012-12-25 14:07:57 -08001409 s4 = r'''
1410 void x(void) {
1411 for (int i = 0;;)
1412 i;
1413 }
1414 '''
1415 ps4 = self.parse(s4)
1416 self.assert_num_ID_refs(ps4, 'i', 1)
1417
Eli Benderskyd0973782012-01-19 08:09:33 +02001418 def _open_c_file(self, name):
1419 """ Find a c file by name, taking into account the current dir can be
1420 in a couple of typical places
1421 """
1422 fullnames = [
1423 os.path.join('c_files', name),
1424 os.path.join('tests', 'c_files', name)]
1425 for fullname in fullnames:
1426 if os.path.exists(fullname):
1427 return open(fullname, 'rU')
1428 assert False, "Unreachable"
1429
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001430 def test_whole_file(self):
1431 # See how pycparser handles a whole, real C file.
1432 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001433 with self._open_c_file('memmgr_with_h.c') as f:
1434 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001435 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001436
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001437 self.assert_num_klass_nodes(p, FuncDef, 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001438
1439 # each FuncDef also has a FuncDecl. 4 declarations
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001440 # + 5 definitions, overall 9
1441 self.assert_num_klass_nodes(p, FuncDecl, 9)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001442
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001443 self.assert_num_klass_nodes(p, Typedef, 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001444
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001445 self.assertEqual(p.ext[4].coord.line, 88)
1446 self.assertEqual(p.ext[4].coord.file, "./memmgr.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001447
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001448 self.assertEqual(p.ext[6].coord.line, 10)
1449 self.assertEqual(p.ext[6].coord.file, "memmgr.c")
1450
1451 def test_whole_file_with_stdio(self):
1452 # Parse a whole file with stdio.h included by cpp
1453 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001454 with self._open_c_file('cppd_with_stdio_h.c') as f:
1455 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001456 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001457
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001458 self.assertTrue(isinstance(p.ext[0], Typedef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001459 self.assertEqual(p.ext[0].coord.line, 213)
1460 self.assertEqual(p.ext[0].coord.file, "D:\eli\cpp_stuff\libc_include/stddef.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001461
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001462 self.assertTrue(isinstance(p.ext[-1], FuncDef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001463 self.assertEqual(p.ext[-1].coord.line, 15)
1464 self.assertEqual(p.ext[-1].coord.file, "example_c_file.c")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001465
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001466 self.assertTrue(isinstance(p.ext[-8], Typedef))
1467 self.assertTrue(isinstance(p.ext[-8].type, TypeDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001468 self.assertEqual(p.ext[-8].name, 'cookie_io_functions_t')
eli.bendersky85d2e732011-05-20 19:47:26 +03001469
1470
1471class TestCParser_typenames(TestCParser_base):
1472 """ Test issues related to the typedef-name problem.
1473 """
1474 def test_innerscope_typedef(self):
1475 # should fail since TT is not a type in bar
1476 s1 = r'''
1477 void foo() {
1478 typedef char TT;
1479 TT x;
1480 }
1481 void bar() {
1482 TT y;
1483 }
1484 '''
1485 self.assertRaises(ParseError, self.parse, s1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001486
eli.bendersky85d2e732011-05-20 19:47:26 +03001487 # should succeed since TT is not a type in bar
1488 s2 = r'''
1489 void foo() {
1490 typedef char TT;
1491 TT x;
1492 }
1493 void bar() {
1494 unsigned TT;
1495 }
1496 '''
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001497 self.assertTrue(isinstance(self.parse(s2), FileAST))
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001498
eli.bendersky85d2e732011-05-20 19:47:26 +03001499
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001500
1501if __name__ == '__main__':
1502 #~ suite = unittest.TestLoader().loadTestsFromNames(
1503 #~ ['test_c_parser.TestCParser_fundamentals.test_typedef'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001504
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001505 #~ suite = unittest.TestLoader().loadTestsFromNames(
1506 #~ ['test_c_parser.TestCParser_whole_code.test_whole_file_with_stdio'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001507
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001508 #~ suite = unittest.TestLoader().loadTestsFromTestCase(
1509 #~ TestCParser_whole_code)
1510
1511 #~ unittest.TextTestRunner(verbosity=2).run(suite)
1512 unittest.main()