blob: 95ae865e1870c284f3947cb6730d72638789d124 [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
Eli Bendersky3877c4c2013-07-13 06:54:04 -07008sys.path[0:0] = ['.', '..']
Eli Bendersky3921e8e2010-05-21 09:05:39 +03009
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 ''
Eli Bendersky8aad3182014-01-25 06:30:53 -080050 return ['ArrayDecl', dimval, decl.dim_quals, nested]
Eli Bendersky3921e8e2010-05-21 09:05:39 +030051 elif typ == PtrDecl:
Eli Benderskyb17da152015-04-21 14:35:18 -070052 if decl.quals:
53 return ['PtrDecl', decl.quals, nested]
54 else:
55 return ['PtrDecl', nested]
Eli Bendersky3921e8e2010-05-21 09:05:39 +030056 elif typ == Typedef:
57 return ['Typedef', decl.name, nested]
58 elif typ == FuncDecl:
59 if decl.args:
60 params = [expand_decl(param) for param in decl.args.params]
61 else:
62 params = []
63 return ['FuncDecl', params, nested]
Eli Bendersky86f2eee2013-01-18 06:04:01 -080064
Eli Bendersky3921e8e2010-05-21 09:05:39 +030065
66def expand_init(init):
67 """ Converts an initialization into a nested list
68 """
69 typ = type(init)
Eli Bendersky86f2eee2013-01-18 06:04:01 -080070
eli.benderskyf890a862010-10-30 12:13:23 +020071 if typ == NamedInitializer:
72 des = [expand_init(dp) for dp in init.name]
73 return (des, expand_init(init.expr))
Eli Bendersky293ea912012-12-25 14:52:48 -080074 elif typ in (InitList, ExprList):
eli.benderskyf890a862010-10-30 12:13:23 +020075 return [expand_init(expr) for expr in init.exprs]
76 elif typ == Constant:
Eli Bendersky3921e8e2010-05-21 09:05:39 +030077 return ['Constant', init.type, init.value]
78 elif typ == ID:
79 return ['ID', init.name]
Nate Bogdanowicz14b8a7e2017-02-22 08:54:05 -050080 elif typ == UnaryOp:
81 return ['UnaryOp', init.op, expand_decl(init.expr)]
Eli Bendersky3921e8e2010-05-21 09:05:39 +030082
83
eli.bendersky85d2e732011-05-20 19:47:26 +030084class TestCParser_base(unittest.TestCase):
Eli Bendersky3921e8e2010-05-21 09:05:39 +030085 def parse(self, txt, filename=''):
86 return self.cparser.parse(txt, filename)
Eli Bendersky86f2eee2013-01-18 06:04:01 -080087
Eli Bendersky3921e8e2010-05-21 09:05:39 +030088 def setUp(self):
89 self.cparser = _c_parser
Eli Bendersky86f2eee2013-01-18 06:04:01 -080090
Eli Benderskyb77d6c02016-10-11 20:33:53 -070091 def assert_coord(self, node, line, file=None):
92 self.assertEqual(node.coord.line, line)
93 if file:
94 self.assertEqual(node.coord.file, file)
95
eli.bendersky85d2e732011-05-20 19:47:26 +030096
97class TestCParser_fundamentals(TestCParser_base):
Eli Bendersky3921e8e2010-05-21 09:05:39 +030098 def get_decl(self, txt, index=0):
99 """ Given a source and an index returns the expanded
100 declaration at that index.
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800101
102 FileAST holds a list of 'external declarations'.
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300103 index is the offset of the desired declaration in that
104 list.
105 """
106 t = self.parse(txt).ext[index]
107 return expand_decl(t)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800108
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300109 def get_decl_init(self, txt, index=0):
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800110 """ Returns the expanded initializer of the declaration
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300111 at index.
112 """
113 t = self.parse(txt).ext[index]
114 return expand_init(t.init)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800115
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300116 def test_FileAST(self):
117 t = self.parse('int a; char c;')
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300118 self.assertTrue(isinstance(t, FileAST))
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300119 self.assertEqual(len(t.ext), 2)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800120
eli.bendersky43cf0b22011-10-19 05:56:15 +0200121 # empty file
122 t2 = self.parse('')
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300123 self.assertTrue(isinstance(t2, FileAST))
eli.bendersky43cf0b22011-10-19 05:56:15 +0200124 self.assertEqual(len(t2.ext), 0)
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300125
eli.bendersky38165b72011-02-04 08:13:39 +0200126 def test_empty_toplevel_decl(self):
127 code = 'int foo;;'
128 t = self.parse(code)
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300129 self.assertTrue(isinstance(t, FileAST))
eli.bendersky38165b72011-02-04 08:13:39 +0200130 self.assertEqual(len(t.ext), 1)
131 self.assertEqual(self.get_decl(code),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800132 ['Decl', 'foo',
eli.bendersky38165b72011-02-04 08:13:39 +0200133 ['TypeDecl', ['IdentifierType', ['int']]]])
134
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300135 def test_coords(self):
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800136 """ Tests the "coordinates" of parsed elements - file
eli.bendersky38165b72011-02-04 08:13:39 +0200137 name and line numbers, with modification insterted by
138 #line directives.
139 """
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300140 self.assert_coord(self.parse('int a;').ext[0], 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800141
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300142 t1 = """
143 int a;
144 int b;\n\n
145 int c;
146 """
147 f1 = self.parse(t1, filename='test.c')
148 self.assert_coord(f1.ext[0], 2, 'test.c')
149 self.assert_coord(f1.ext[1], 3, 'test.c')
150 self.assert_coord(f1.ext[2], 6, 'test.c')
151
152 t1_1 = '''
153 int main() {
154 k = p;
155 printf("%d", b);
156 return 0;
157 }'''
158 f1_1 = self.parse(t1_1, filename='test.c')
eli.benderskyef29ff92010-10-29 16:25:43 +0200159 self.assert_coord(f1_1.ext[0].body.block_items[0], 3, 'test.c')
160 self.assert_coord(f1_1.ext[0].body.block_items[1], 4, 'test.c')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800161
eli.benderskyfc96e5e2011-03-04 09:51:23 +0200162 t1_2 = '''
163 int main () {
164 int p = (int) k;
165 }'''
166 f1_2 = self.parse(t1_2, filename='test.c')
167 # make sure that the Cast has a coord (issue 23)
168 self.assert_coord(f1_2.ext[0].body.block_items[0].init, 3, 'test.c')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800169
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300170 t2 = """
171 #line 99
172 int c;
173 """
174 self.assert_coord(self.parse(t2).ext[0], 99)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800175
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300176 t3 = """
177 int dsf;
178 char p;
179 #line 3000 "in.h"
180 char d;
181 """
182 f3 = self.parse(t3, filename='test.c')
183 self.assert_coord(f3.ext[0], 2, 'test.c')
184 self.assert_coord(f3.ext[1], 3, 'test.c')
185 self.assert_coord(f3.ext[2], 3000, 'in.h')
186
187 t4 = """
188 #line 20 "restore.h"
189 int maydler(char);
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800190
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300191 #line 30 "includes/daween.ph"
192 long j, k;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800193
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300194 #line 50000
195 char* ro;
196 """
197 f4 = self.parse(t4, filename='myb.c')
198 self.assert_coord(f4.ext[0], 20, 'restore.h')
199 self.assert_coord(f4.ext[1], 30, 'includes/daween.ph')
200 self.assert_coord(f4.ext[2], 30, 'includes/daween.ph')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800201 self.assert_coord(f4.ext[3], 50000, 'includes/daween.ph')
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300202
203 t5 = """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800204 int
205 #line 99
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300206 c;
207 """
208 self.assert_coord(self.parse(t5).ext[0], 99)
209
Eli Bendersky203b9672012-06-15 10:11:24 +0300210 # coord for ellipsis
211 t6 = """
212 int foo(int j,
213 ...) {
214 }"""
215 f6 = self.parse(t6, filename='z.c')
216 self.assert_coord(self.parse(t6).ext[0].decl.type.args.params[1], 3)
217
Eli Bendersky8e5d3a92014-03-15 14:06:00 -0700218 def test_forloop_coord(self):
219 t = '''\
220 void foo() {
221 for(int z=0; z<4;
222 z++){}
223 }
224 '''
225 s = self.parse(t, filename='f.c')
226 forloop = s.ext[0].body.block_items[0]
227 self.assert_coord(forloop.init, 2, 'f.c')
228 self.assert_coord(forloop.cond, 2, 'f.c')
229 self.assert_coord(forloop.next, 3, 'f.c')
230
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300231 def test_simple_decls(self):
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800232 self.assertEqual(self.get_decl('int a;'),
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300233 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
234
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800235 self.assertEqual(self.get_decl('unsigned int a;'),
Eli Bendersky68497c22012-01-19 06:04:58 +0200236 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['unsigned', 'int']]]])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300237
eli.benderskyaffe0322011-09-24 06:16:55 +0300238 self.assertEqual(self.get_decl('_Bool a;'),
239 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['_Bool']]]])
240
Eli Benderskyf4d73462012-01-19 05:56:27 +0200241 self.assertEqual(self.get_decl('float _Complex fcc;'),
Eli Bendersky68497c22012-01-19 06:04:58 +0200242 ['Decl', 'fcc', ['TypeDecl', ['IdentifierType', ['float', '_Complex']]]])
Eli Benderskyf4d73462012-01-19 05:56:27 +0200243
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800244 self.assertEqual(self.get_decl('char* string;'),
245 ['Decl', 'string',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300246 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]])
247
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800248 self.assertEqual(self.get_decl('long ar[15];'),
249 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800250 ['ArrayDecl', '15', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300251 ['TypeDecl', ['IdentifierType', ['long']]]]])
eli.bendersky98f45372010-10-30 09:46:29 +0200252
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800253 self.assertEqual(self.get_decl('long long ar[15];'),
254 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800255 ['ArrayDecl', '15', [],
eli.benderskyf890a862010-10-30 12:13:23 +0200256 ['TypeDecl', ['IdentifierType', ['long', 'long']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800257
258 self.assertEqual(self.get_decl('unsigned ar[];'),
259 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800260 ['ArrayDecl', '', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300261 ['TypeDecl', ['IdentifierType', ['unsigned']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800262
263 self.assertEqual(self.get_decl('int strlen(char* s);'),
264 ['Decl', 'strlen',
265 ['FuncDecl',
266 [['Decl', 's',
267 ['PtrDecl',
268 ['TypeDecl', ['IdentifierType', ['char']]]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300269 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800270
271 self.assertEqual(self.get_decl('int strcmp(char* s1, char* s2);'),
272 ['Decl', 'strcmp',
273 ['FuncDecl',
274 [ ['Decl', 's1',
275 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
276 ['Decl', 's2',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300277 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800278 ],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300279 ['TypeDecl', ['IdentifierType', ['int']]]]])
280
Sye van der Veen51a46ec2013-06-10 12:56:15 -0400281 # function return values and parameters may not have type information
Eli Bendersky09e22a62013-07-02 06:00:36 -0700282 self.assertEqual(self.get_decl('extern foobar(foo, bar);'),
283 ['Decl', 'foobar',
284 ['FuncDecl',
Sye van der Veen51a46ec2013-06-10 12:56:15 -0400285 [ ['ID', 'foo'],
286 ['ID', 'bar']
Eli Bendersky09e22a62013-07-02 06:00:36 -0700287 ],
Sye van der Veen51a46ec2013-06-10 12:56:15 -0400288 ['TypeDecl', ['IdentifierType', ['int']]]]])
289
Manuel Jacob0a15d7d2017-01-12 15:46:05 +0100290 def test_int128(self):
291 self.assertEqual(self.get_decl('__int128 a;'),
292 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['__int128']]]])
293
294
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300295 def test_nested_decls(self): # the fun begins
296 self.assertEqual(self.get_decl('char** ar2D;'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800297 ['Decl', 'ar2D',
298 ['PtrDecl', ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300299 ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800300
301 self.assertEqual(self.get_decl('int (*a)[1][2];'),
302 ['Decl', 'a',
303 ['PtrDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800304 ['ArrayDecl', '1', [],
305 ['ArrayDecl', '2', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300306 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
307
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800308 self.assertEqual(self.get_decl('int *a[1][2];'),
309 ['Decl', 'a',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800310 ['ArrayDecl', '1', [],
311 ['ArrayDecl', '2', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300312 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['int']]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800313
Eli Benderskyb17da152015-04-21 14:35:18 -0700314 self.assertEqual(self.get_decl('char* const* p;'),
315 ['Decl', 'p',
316 ['PtrDecl', ['PtrDecl', ['const'],
317 ['TypeDecl', ['IdentifierType', ['char']]]]]])
318
319 self.assertEqual(self.get_decl('char* * const p;'),
320 ['Decl', 'p',
321 ['PtrDecl', ['const'], ['PtrDecl',
322 ['TypeDecl', ['IdentifierType', ['char']]]]]])
323
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300324 self.assertEqual(self.get_decl('char ***ar3D[40];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800325 ['Decl', 'ar3D',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800326 ['ArrayDecl', '40', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800327 ['PtrDecl', ['PtrDecl', ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300328 ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800329
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300330 self.assertEqual(self.get_decl('char (***ar3D)[40];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800331 ['Decl', 'ar3D',
332 ['PtrDecl', ['PtrDecl', ['PtrDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800333 ['ArrayDecl', '40', [], ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800334
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300335 self.assertEqual(self.get_decl('int (*x[4])(char, int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800336 ['Decl', 'x',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800337 ['ArrayDecl', '4', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800338 ['PtrDecl',
339 ['FuncDecl',
340 [ ['Typename', ['TypeDecl', ['IdentifierType', ['char']]]],
341 ['Typename', ['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 self.assertEqual(self.get_decl('char *(*(**foo [][8])())[];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800345 ['Decl', 'foo',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800346 ['ArrayDecl', '', [],
347 ['ArrayDecl', '8', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800348 ['PtrDecl', ['PtrDecl',
349 ['FuncDecl',
350 [],
351 ['PtrDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800352 ['ArrayDecl', '', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800353 ['PtrDecl',
354 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300355 ['IdentifierType', ['char']]]]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800356
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300357 # explore named and unnamed function pointer parameters,
358 # with and without qualifiers
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800359
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300360 # unnamed w/o quals
361 self.assertEqual(self.get_decl('int (*k)(int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800362 ['Decl', 'k',
363 ['PtrDecl',
364 ['FuncDecl',
365 [['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300366 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800367
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300368 # unnamed w/ quals
369 self.assertEqual(self.get_decl('int (*k)(const int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800370 ['Decl', 'k',
371 ['PtrDecl',
372 ['FuncDecl',
373 [['Typename', ['const'], ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300374 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800375
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300376 # named w/o quals
377 self.assertEqual(self.get_decl('int (*k)(int q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800378 ['Decl', 'k',
379 ['PtrDecl',
380 ['FuncDecl',
381 [['Decl', 'q', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300382 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800383
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300384 # named w/ quals
385 self.assertEqual(self.get_decl('int (*k)(const volatile int q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800386 ['Decl', 'k',
387 ['PtrDecl',
388 ['FuncDecl',
389 [['Decl', ['const', 'volatile'], 'q',
390 ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300391 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800392
eli.bendersky79d5cf62010-10-29 13:33:52 +0200393 # restrict qualifier
394 self.assertEqual(self.get_decl('int (*k)(restrict int* q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800395 ['Decl', 'k',
396 ['PtrDecl',
397 ['FuncDecl',
398 [['Decl', ['restrict'], 'q',
eli.bendersky79d5cf62010-10-29 13:33:52 +0200399 ['PtrDecl',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800400 ['TypeDecl', ['IdentifierType', ['int']]]]]],
eli.bendersky79d5cf62010-10-29 13:33:52 +0200401 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800402
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800403 def test_func_decls_with_array_dim_qualifiers(self):
404 self.assertEqual(self.get_decl('int zz(int p[static 10]);'),
405 ['Decl', 'zz',
406 ['FuncDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800407 [['Decl', 'p', ['ArrayDecl', '10', ['static'],
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800408 ['TypeDecl', ['IdentifierType', ['int']]]]]],
409 ['TypeDecl', ['IdentifierType', ['int']]]]])
410
411 self.assertEqual(self.get_decl('int zz(int p[const 10]);'),
412 ['Decl', 'zz',
413 ['FuncDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800414 [['Decl', 'p', ['ArrayDecl', '10', ['const'],
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800415 ['TypeDecl', ['IdentifierType', ['int']]]]]],
416 ['TypeDecl', ['IdentifierType', ['int']]]]])
417
necase4a6afa02014-12-19 16:38:37 -0600418 self.assertEqual(self.get_decl('int zz(int p[restrict][5]);'),
419 ['Decl', 'zz',
420 ['FuncDecl',
421 [['Decl', 'p', ['ArrayDecl', '', ['restrict'],
422 ['ArrayDecl', '5', [],
423 ['TypeDecl', ['IdentifierType', ['int']]]]]]],
424 ['TypeDecl', ['IdentifierType', ['int']]]]])
425
426 self.assertEqual(self.get_decl('int zz(int p[const restrict static 10][5]);'),
427 ['Decl', 'zz',
428 ['FuncDecl',
429 [['Decl', 'p', ['ArrayDecl', '10', ['const', 'restrict', 'static'],
430 ['ArrayDecl', '5', [],
431 ['TypeDecl', ['IdentifierType', ['int']]]]]]],
432 ['TypeDecl', ['IdentifierType', ['int']]]]])
433
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300434 def test_qualifiers_storage_specifiers(self):
435 def assert_qs(txt, index, quals, storage):
436 d = self.parse(txt).ext[index]
437 self.assertEqual(d.quals, quals)
438 self.assertEqual(d.storage, storage)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800439
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300440 assert_qs("extern int p;", 0, [], ['extern'])
441 assert_qs("const long p = 6;", 0, ['const'], [])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800442
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300443 d1 = "static const int p, q, r;"
444 for i in range(3):
445 assert_qs(d1, i, ['const'], ['static'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800446
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300447 d2 = "static char * const p;"
448 assert_qs(d2, 0, [], ['static'])
449 pdecl = self.parse(d2).ext[0].type
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300450 self.assertTrue(isinstance(pdecl, PtrDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300451 self.assertEqual(pdecl.quals, ['const'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800452
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300453 def test_sizeof(self):
454 e = """
455 void foo()
456 {
457 int a = sizeof k;
458 int b = sizeof(int);
eli.benderskyc51e1d32011-02-04 08:52:33 +0200459 int c = sizeof(int**);;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800460
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300461 char* p = "just to make sure this parses w/o error...";
462 int d = sizeof(int());
463 }
464 """
465 compound = self.parse(e).ext[0].body
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800466
eli.benderskyef29ff92010-10-29 16:25:43 +0200467 s1 = compound.block_items[0].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300468 self.assertTrue(isinstance(s1, UnaryOp))
469 self.assertEqual(s1.op, 'sizeof')
470 self.assertTrue(isinstance(s1.expr, ID))
471 self.assertEqual(s1.expr.name, 'k')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800472
eli.benderskyef29ff92010-10-29 16:25:43 +0200473 s2 = compound.block_items[1].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300474 self.assertEqual(expand_decl(s2.expr),
475 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800476
eli.benderskyef29ff92010-10-29 16:25:43 +0200477 s3 = compound.block_items[2].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300478 self.assertEqual(expand_decl(s3.expr),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800479 ['Typename',
480 ['PtrDecl',
481 ['PtrDecl',
482 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300483 ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800484
Eli Benderskye59395b2015-05-09 15:20:46 -0700485 def test_offsetof(self):
486 e = """
487 void foo() {
488 int a = offsetof(struct S, p);
489 a.b = offsetof(struct sockaddr, sp) + strlen(bar);
ksero749650a2016-09-09 07:31:09 +0200490 int a = offsetof(struct S, p.q.r);
491 int a = offsetof(struct S, p[5].q[4][5]);
Eli Benderskye59395b2015-05-09 15:20:46 -0700492 }
493 """
494 compound = self.parse(e).ext[0].body
495 s1 = compound.block_items[0].init
Eli Benderskya71ec1b2015-05-10 06:31:20 -0700496 self.assertTrue(isinstance(s1, FuncCall))
497 self.assertTrue(isinstance(s1.name, ID))
Eli Benderskye59395b2015-05-09 15:20:46 -0700498 self.assertEqual(s1.name.name, 'offsetof')
Eli Benderskya71ec1b2015-05-10 06:31:20 -0700499 self.assertTrue(isinstance(s1.args.exprs[0], Typename))
500 self.assertTrue(isinstance(s1.args.exprs[1], ID))
ksero749650a2016-09-09 07:31:09 +0200501 s3 = compound.block_items[2].init
502 self.assertTrue(isinstance(s3.args.exprs[1], StructRef))
503 s4 = compound.block_items[3].init
504 self.assertTrue(isinstance(s4.args.exprs[1], ArrayRef))
Eli Benderskye59395b2015-05-09 15:20:46 -0700505
Eli Benderskydbf9be22016-10-11 20:44:32 -0700506 def test_compound_statement(self):
507 e = """
508 void foo() {
509 }
510 """
511 compound = self.parse(e).ext[0].body
512 self.assertTrue(isinstance(compound, Compound))
513 self.assert_coord(compound, 2, '')
514
eli.bendersky9f481562010-10-30 15:50:47 +0200515 # The C99 compound literal feature
516 #
eli.benderskyf890a862010-10-30 12:13:23 +0200517 def test_compound_literals(self):
eli.bendersky9f481562010-10-30 15:50:47 +0200518 ps1 = self.parse(r'''
eli.benderskyf890a862010-10-30 12:13:23 +0200519 void foo() {
eli.bendersky9f481562010-10-30 15:50:47 +0200520 p = (long long){k};
521 tc = (struct jk){.a = {1, 2}, .b[0] = t};
522 }''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800523
eli.bendersky9f481562010-10-30 15:50:47 +0200524 compound = ps1.ext[0].body.block_items[0].rvalue
525 self.assertEqual(expand_decl(compound.type),
526 ['Typename', ['TypeDecl', ['IdentifierType', ['long', 'long']]]])
527 self.assertEqual(expand_init(compound.init),
528 [['ID', 'k']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800529
530 compound = ps1.ext[0].body.block_items[1].rvalue
eli.bendersky9f481562010-10-30 15:50:47 +0200531 self.assertEqual(expand_decl(compound.type),
532 ['Typename', ['TypeDecl', ['Struct', 'jk', []]]])
533 self.assertEqual(expand_init(compound.init),
534 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800535 ([['ID', 'a']], [['Constant', 'int', '1'], ['Constant', 'int', '2']]),
eli.bendersky9f481562010-10-30 15:50:47 +0200536 ([['ID', 'b'], ['Constant', 'int', '0']], ['ID', 't'])])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800537
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300538 def test_enums(self):
539 e1 = "enum mycolor op;"
540 e1_type = self.parse(e1).ext[0].type.type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800541
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300542 self.assertTrue(isinstance(e1_type, Enum))
543 self.assertEqual(e1_type.name, 'mycolor')
544 self.assertEqual(e1_type.values, None)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800545
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300546 e2 = "enum mysize {large=20, small, medium} shoes;"
547 e2_type = self.parse(e2).ext[0].type.type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800548
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300549 self.assertTrue(isinstance(e2_type, Enum))
550 self.assertEqual(e2_type.name, 'mysize')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800551
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300552 e2_elist = e2_type.values
553 self.assertTrue(isinstance(e2_elist, EnumeratorList))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800554
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300555 for e2_eval in e2_elist.enumerators:
556 self.assertTrue(isinstance(e2_eval, Enumerator))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800557
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300558 self.assertEqual(e2_elist.enumerators[0].name, 'large')
559 self.assertEqual(e2_elist.enumerators[0].value.value, '20')
560 self.assertEqual(e2_elist.enumerators[2].name, 'medium')
561 self.assertEqual(e2_elist.enumerators[2].value, None)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800562
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300563 # enum with trailing comma (C99 feature)
564 e3 = """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800565 enum
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300566 {
567 red,
568 blue,
569 green,
570 } color;
571 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800572
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300573 e3_type = self.parse(e3).ext[0].type.type
574 self.assertTrue(isinstance(e3_type, Enum))
575 e3_elist = e3_type.values
576 self.assertTrue(isinstance(e3_elist, EnumeratorList))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800577
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300578 for e3_eval in e3_elist.enumerators:
579 self.assertTrue(isinstance(e3_eval, Enumerator))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800580
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300581 self.assertEqual(e3_elist.enumerators[0].name, 'red')
582 self.assertEqual(e3_elist.enumerators[0].value, None)
583 self.assertEqual(e3_elist.enumerators[1].name, 'blue')
584 self.assertEqual(e3_elist.enumerators[2].name, 'green')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800585
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300586 def test_typedef(self):
587 # without typedef, error
588 s1 = """
589 node k;
590 """
591 self.assertRaises(ParseError, self.parse, s1)
592
593 # now with typedef, works
594 s2 = """
595 typedef void* node;
596 node k;
597 """
598 ps2 = self.parse(s2)
599 self.assertEqual(expand_decl(ps2.ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800600 ['Typedef', 'node',
601 ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300602 ['TypeDecl', ['IdentifierType', ['void']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800603
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300604 self.assertEqual(expand_decl(ps2.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800605 ['Decl', 'k',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300606 ['TypeDecl', ['IdentifierType', ['node']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800607
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300608 s3 = """
609 typedef int T;
610 typedef T *pT;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800611
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300612 pT aa, bb;
613 """
614 ps3 = self.parse(s3)
615 self.assertEqual(expand_decl(ps3.ext[3]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800616 ['Decl', 'bb',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300617 ['TypeDecl', ['IdentifierType', ['pT']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800618
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300619 s4 = '''
620 typedef char* __builtin_va_list;
621 typedef __builtin_va_list __gnuc_va_list;
622 '''
623 ps4 = self.parse(s4)
624 self.assertEqual(expand_decl(ps4.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800625 ['Typedef', '__gnuc_va_list',
626 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300627 ['IdentifierType', ['__builtin_va_list']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800628
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300629 s5 = '''typedef struct tagHash Hash;'''
630 ps5 = self.parse(s5)
631 self.assertEqual(expand_decl(ps5.ext[0]),
632 ['Typedef', 'Hash', ['TypeDecl', ['Struct', 'tagHash', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800633
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300634 def test_struct_union(self):
635 s1 = """
636 struct {
637 int id;
638 char* name;
639 } joe;
640 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800641
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300642 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800643 ['Decl', 'joe',
644 ['TypeDecl', ['Struct', None,
645 [ ['Decl', 'id',
646 ['TypeDecl',
647 ['IdentifierType', ['int']]]],
648 ['Decl', 'name',
649 ['PtrDecl',
650 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300651 ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800652
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300653 s2 = """
654 struct node p;
655 """
656 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800657 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300658 ['TypeDecl', ['Struct', 'node', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800659
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300660 s21 = """
661 union pri ra;
662 """
663 self.assertEqual(expand_decl(self.parse(s21).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800664 ['Decl', 'ra',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300665 ['TypeDecl', ['Union', 'pri', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800666
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300667 s3 = """
668 struct node* p;
669 """
670 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800671 ['Decl', 'p',
672 ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300673 ['TypeDecl', ['Struct', 'node', []]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800674
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300675 s4 = """
676 struct node;
677 """
678 self.assertEqual(expand_decl(self.parse(s4).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800679 ['Decl', None,
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300680 ['Struct', 'node', []]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800681
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300682 s5 = """
683 union
684 {
685 struct
686 {
687 int type;
688 } n;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800689
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300690 struct
691 {
692 int type;
693 int intnode;
694 } ni;
695 } u;
696 """
697 self.assertEqual(expand_decl(self.parse(s5).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800698 ['Decl', 'u',
699 ['TypeDecl',
700 ['Union', None,
701 [['Decl', 'n',
702 ['TypeDecl',
703 ['Struct', None,
704 [['Decl', 'type',
705 ['TypeDecl', ['IdentifierType', ['int']]]]]]]],
706 ['Decl', 'ni',
707 ['TypeDecl',
708 ['Struct', None,
709 [['Decl', 'type',
710 ['TypeDecl', ['IdentifierType', ['int']]]],
711 ['Decl', 'intnode',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300712 ['TypeDecl', ['IdentifierType', ['int']]]]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800713
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300714 s6 = """
715 typedef struct foo_tag
716 {
717 void* data;
718 } foo, *pfoo;
719 """
720 s6_ast = self.parse(s6)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800721
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300722 self.assertEqual(expand_decl(s6_ast.ext[0]),
723 ['Typedef', 'foo',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800724 ['TypeDecl',
725 ['Struct', 'foo_tag',
726 [['Decl', 'data',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300727 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800728
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300729 self.assertEqual(expand_decl(s6_ast.ext[1]),
730 ['Typedef', 'pfoo',
731 ['PtrDecl',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800732 ['TypeDecl',
733 ['Struct', 'foo_tag',
734 [['Decl', 'data',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300735 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800736
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300737 s7 = r"""
738 struct _on_exit_args {
739 void * _fnargs[32];
740 void * _dso_handle[32];
741
742 long _fntypes;
743 #line 77 "D:\eli\cpp_stuff\libc_include/sys/reent.h"
744
745 long _is_cxa;
746 };
747 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800748
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300749 s7_ast = self.parse(s7, filename='test.c')
750 self.assert_coord(s7_ast.ext[0].type.decls[2], 6, 'test.c')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800751 self.assert_coord(s7_ast.ext[0].type.decls[3], 78,
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300752 r'D:\eli\cpp_stuff\libc_include/sys/reent.h')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800753
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300754 s8 = """
755 typedef enum tagReturnCode {SUCCESS, FAIL} ReturnCode;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800756
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300757 typedef struct tagEntry
758 {
759 char* key;
760 char* value;
761 } Entry;
762
763
764 typedef struct tagNode
765 {
766 Entry* entry;
767
768 struct tagNode* next;
769 } Node;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800770
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300771 typedef struct tagHash
772 {
773 unsigned int table_size;
774
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800775 Node** heads;
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300776
777 } Hash;
778 """
779 s8_ast = self.parse(s8)
780 self.assertEqual(expand_decl(s8_ast.ext[3]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800781 ['Typedef', 'Hash',
782 ['TypeDecl', ['Struct', 'tagHash',
783 [['Decl', 'table_size',
784 ['TypeDecl', ['IdentifierType', ['unsigned', 'int']]]],
785 ['Decl', 'heads',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300786 ['PtrDecl', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['Node']]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800787
Eli Bendersky95e3b762016-03-19 05:21:59 -0700788 def test_struct_with_extra_semis_inside(self):
789 s1 = """
790 struct {
791 int a;;
792 } foo;
793 """
794 s1_ast = self.parse(s1)
795 self.assertEqual(expand_decl(s1_ast.ext[0]),
796 ['Decl', 'foo',
797 ['TypeDecl', ['Struct', None,
798 [['Decl', 'a',
799 ['TypeDecl', ['IdentifierType', ['int']]]]]]]])
800
801 s2 = """
802 struct {
803 int a;;;;
804 float b, c;
805 ;;
806 char d;
807 } foo;
808 """
809 s2_ast = self.parse(s2)
810 self.assertEqual(expand_decl(s2_ast.ext[0]),
811 ['Decl', 'foo',
812 ['TypeDecl', ['Struct', None,
813 [['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]],
814 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['float']]]],
815 ['Decl', 'c', ['TypeDecl', ['IdentifierType', ['float']]]],
816 ['Decl', 'd',
817 ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
818
eli.bendersky697ecc52011-02-10 07:05:13 +0200819 def test_anonymous_struct_union(self):
820 s1 = """
821 union
822 {
823 union
824 {
825 int i;
826 long l;
827 };
828
829 struct
830 {
831 int type;
832 int intnode;
833 };
834 } u;
835 """
836
837 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
838 ['Decl', 'u',
839 ['TypeDecl',
840 ['Union', None,
841 [['Decl', None,
842 ['Union', None,
843 [['Decl', 'i',
844 ['TypeDecl',
845 ['IdentifierType', ['int']]]],
846 ['Decl', 'l',
847 ['TypeDecl',
848 ['IdentifierType', ['long']]]]]]],
849 ['Decl', None,
850 ['Struct', None,
851 [['Decl', 'type',
852 ['TypeDecl',
853 ['IdentifierType', ['int']]]],
854 ['Decl', 'intnode',
855 ['TypeDecl',
856 ['IdentifierType', ['int']]]]]]]]]]])
857
858 s2 = """
859 struct
860 {
861 int i;
862 union
863 {
864 int id;
865 char* name;
866 };
867 float f;
868 } joe;
869 """
870
871 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
872 ['Decl', 'joe',
873 ['TypeDecl',
874 ['Struct', None,
875 [['Decl', 'i',
876 ['TypeDecl',
877 ['IdentifierType', ['int']]]],
878 ['Decl', None,
879 ['Union', None,
880 [['Decl', 'id',
881 ['TypeDecl',
882 ['IdentifierType', ['int']]]],
883 ['Decl', 'name',
884 ['PtrDecl',
885 ['TypeDecl',
886 ['IdentifierType', ['char']]]]]]]],
887 ['Decl', 'f',
888 ['TypeDecl',
889 ['IdentifierType', ['float']]]]]]]])
890
891 # ISO/IEC 9899:201x Commitee Draft 2010-11-16, N1539
892 # section 6.7.2.1, par. 19, example 1
893 s3 = """
894 struct v {
895 union {
896 struct { int i, j; };
897 struct { long k, l; } w;
898 };
899 int m;
900 } v1;
901 """
902
903 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
904 ['Decl', 'v1',
905 ['TypeDecl',
906 ['Struct', 'v',
907 [['Decl', None,
908 ['Union', None,
909 [['Decl', None,
910 ['Struct', None,
911 [['Decl', 'i',
912 ['TypeDecl',
913 ['IdentifierType', ['int']]]],
914 ['Decl', 'j',
915 ['TypeDecl',
916 ['IdentifierType', ['int']]]]]]],
917 ['Decl', 'w',
918 ['TypeDecl',
919 ['Struct', None,
920 [['Decl', 'k',
921 ['TypeDecl',
922 ['IdentifierType', ['long']]]],
923 ['Decl', 'l',
924 ['TypeDecl',
925 ['IdentifierType', ['long']]]]]]]]]]],
926 ['Decl', 'm',
927 ['TypeDecl',
928 ['IdentifierType', ['int']]]]]]]])
929
eli.benderskydce29a02011-02-10 07:55:00 +0200930 s4 = """
931 struct v {
932 int i;
933 float;
934 } v2;"""
eli.bendersky6b011792011-06-22 17:50:56 +0300935 # just make sure this doesn't raise ParseError
936 self.parse(s4)
eli.benderskydce29a02011-02-10 07:55:00 +0200937
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400938 def test_struct_members_namespace(self):
Eli Bendersky4d969b32013-07-13 06:07:07 -0700939 """ Tests that structure/union member names reside in a separate
940 namespace and can be named after existing types.
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400941 """
942 s1 = """
943 typedef int Name;
944 typedef Name NameArray[10];
945
946 struct {
947 Name Name;
948 Name NameArray[3];
949 } sye;
950
951 void main(void)
952 {
953 sye.Name = 1;
954 }
955 """
956
957 s1_ast = self.parse(s1)
958 self.assertEqual(expand_decl(s1_ast.ext[2]),
959 ['Decl', 'sye',
960 ['TypeDecl', ['Struct', None,
961 [ ['Decl', 'Name',
962 ['TypeDecl',
963 ['IdentifierType', ['Name']]]],
964 ['Decl', 'NameArray',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800965 ['ArrayDecl', '3', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400966 ['TypeDecl', ['IdentifierType', ['Name']]]]]]]]])
967 self.assertEqual(s1_ast.ext[3].body.block_items[0].lvalue.field.name, 'Name')
968
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200969 def test_struct_bitfields(self):
eli.bendersky38ed9a92010-10-09 09:29:59 +0200970 # a struct with two bitfields, one unnamed
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200971 s1 = """
972 struct {
973 int k:6;
974 int :2;
975 } joe;
976 """
977
978 parsed_struct = self.parse(s1).ext[0]
979
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800980 # We can see here the name of the decl for the unnamed bitfield is
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200981 # None, but expand_decl doesn't show bitfield widths
982 # ...
983 self.assertEqual(expand_decl(parsed_struct),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800984 ['Decl', 'joe',
985 ['TypeDecl', ['Struct', None,
986 [ ['Decl', 'k',
987 ['TypeDecl',
988 ['IdentifierType', ['int']]]],
989 ['Decl', None,
990 ['TypeDecl',
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200991 ['IdentifierType', ['int']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800992
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200993 # ...
994 # so we test them manually
995 self.assertEqual(parsed_struct.type.type.decls[0].bitsize.value, '6')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800996 self.assertEqual(parsed_struct.type.type.decls[1].bitsize.value, '2')
997
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300998 def test_tags_namespace(self):
999 """ Tests that the tags of structs/unions/enums reside in a separate namespace and
1000 can be named after existing types.
1001 """
1002 s1 = """
1003 typedef int tagEntry;
1004
1005 struct tagEntry
1006 {
1007 char* key;
1008 char* value;
1009 } Entry;
1010 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001011
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001012 s1_ast = self.parse(s1)
1013 self.assertEqual(expand_decl(s1_ast.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001014 ['Decl', 'Entry',
1015 ['TypeDecl', ['Struct', 'tagEntry',
1016 [['Decl', 'key',
1017 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
1018 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001019 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001020
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001021 s2 = """
1022 struct tagEntry;
1023
1024 typedef struct tagEntry tagEntry;
1025
1026 struct tagEntry
1027 {
1028 char* key;
1029 char* value;
1030 } Entry;
1031 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001032
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001033 s2_ast = self.parse(s2)
1034 self.assertEqual(expand_decl(s2_ast.ext[2]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001035 ['Decl', 'Entry',
1036 ['TypeDecl', ['Struct', 'tagEntry',
1037 [['Decl', 'key',
1038 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
1039 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001040 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001041
1042 s3 = """
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001043 typedef int mytag;
1044
1045 enum mytag {ABC, CDE};
1046 enum mytag joe;
1047 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001048
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001049 s3_type = self.parse(s3).ext[1].type
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001050
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001051 self.assertTrue(isinstance(s3_type, Enum))
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001052 self.assertEqual(s3_type.name, 'mytag')
1053
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001054 def test_multi_decls(self):
1055 d1 = 'int a, b;'
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001056
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001057 self.assertEqual(self.get_decl(d1, 0),
1058 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
1059 self.assertEqual(self.get_decl(d1, 1),
1060 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['int']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001061
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001062 d2 = 'char* p, notp, ar[4];'
1063 self.assertEqual(self.get_decl(d2, 0),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001064 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001065 ['PtrDecl',
1066 ['TypeDecl', ['IdentifierType', ['char']]]]])
1067 self.assertEqual(self.get_decl(d2, 1),
1068 ['Decl', 'notp', ['TypeDecl', ['IdentifierType', ['char']]]])
1069 self.assertEqual(self.get_decl(d2, 2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001070 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001071 ['ArrayDecl', '4', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001072 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001073
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001074 def test_invalid_multiple_types_error(self):
1075 bad = [
1076 'int enum {ab, cd} fubr;',
1077 'enum kid char brbr;']
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001078
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001079 for b in bad:
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001080 self.assertRaises(ParseError, self.parse, b)
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001081
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001082 def test_duplicate_typedef(self):
1083 """ Tests that redeclarations of existing types are parsed correctly.
1084 This is non-standard, but allowed by many compilers.
1085 """
1086 d1 = '''
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001087 typedef int numbertype;
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001088 typedef int numbertype;
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001089 '''
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001090
1091 self.assertEqual(self.get_decl(d1, 0),
1092 ['Typedef', 'numbertype',
1093 ['TypeDecl', ['IdentifierType', ['int']]]])
1094 self.assertEqual(self.get_decl(d1, 1),
1095 ['Typedef', 'numbertype',
1096 ['TypeDecl', ['IdentifierType', ['int']]]])
1097
1098 d2 = '''
1099 typedef int (*funcptr)(int x);
1100 typedef int (*funcptr)(int x);
1101 '''
1102 self.assertEqual(self.get_decl(d2, 0),
1103 ['Typedef', 'funcptr',
1104 ['PtrDecl', ['FuncDecl',
1105 [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]],
1106 ['TypeDecl', ['IdentifierType', ['int']]]]]])
1107 self.assertEqual(self.get_decl(d2, 1),
1108 ['Typedef', 'funcptr',
1109 ['PtrDecl', ['FuncDecl',
1110 [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]],
1111 ['TypeDecl', ['IdentifierType', ['int']]]]]])
1112
1113 d3 = '''
1114 typedef int numberarray[5];
1115 typedef int numberarray[5];
1116 '''
1117 self.assertEqual(self.get_decl(d3, 0),
1118 ['Typedef', 'numberarray',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001119 ['ArrayDecl', '5', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001120 ['TypeDecl', ['IdentifierType', ['int']]]]])
1121 self.assertEqual(self.get_decl(d3, 1),
1122 ['Typedef', 'numberarray',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001123 ['ArrayDecl', '5', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001124 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001125
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001126 def test_decl_inits(self):
1127 d1 = 'int a = 16;'
eli.benderskyf890a862010-10-30 12:13:23 +02001128 #~ self.parse(d1).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001129 self.assertEqual(self.get_decl(d1),
1130 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
1131 self.assertEqual(self.get_decl_init(d1),
1132 ['Constant', 'int', '16'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001133
Eli Bendersky3b1b08d2012-06-15 12:37:54 +03001134 d1_1 = 'float f = 0xEF.56p1;'
1135 self.assertEqual(self.get_decl_init(d1_1),
1136 ['Constant', 'float', '0xEF.56p1'])
1137
Konstanty Bialkowski3bdbfdc2015-04-19 20:09:21 +10001138 d1_2 = 'int bitmask = 0b1001010;'
1139 self.assertEqual(self.get_decl_init(d1_2),
1140 ['Constant', 'int', '0b1001010'])
1141
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001142 d2 = 'long ar[] = {7, 8, 9};'
1143 self.assertEqual(self.get_decl(d2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001144 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001145 ['ArrayDecl', '', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001146 ['TypeDecl', ['IdentifierType', ['long']]]]])
1147 self.assertEqual(self.get_decl_init(d2),
1148 [ ['Constant', 'int', '7'],
1149 ['Constant', 'int', '8'],
eli.benderskyf890a862010-10-30 12:13:23 +02001150 ['Constant', 'int', '9']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001151
Eli Benderskyc830da82015-05-10 07:56:41 -07001152 d21 = 'long ar[4] = {};'
1153 self.assertEqual(self.get_decl_init(d21), [])
1154
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001155 d3 = 'char p = j;'
1156 self.assertEqual(self.get_decl(d3),
1157 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['char']]]])
1158 self.assertEqual(self.get_decl_init(d3),
1159 ['ID', 'j'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001160
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001161 d4 = "char x = 'c', *p = {0, 1, 2, {4, 5}, 6};"
1162 self.assertEqual(self.get_decl(d4, 0),
1163 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['char']]]])
1164 self.assertEqual(self.get_decl_init(d4, 0),
1165 ['Constant', 'char', "'c'"])
1166 self.assertEqual(self.get_decl(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001167 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001168 ['PtrDecl',
1169 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001170
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001171 self.assertEqual(self.get_decl_init(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001172 [ ['Constant', 'int', '0'],
1173 ['Constant', 'int', '1'],
1174 ['Constant', 'int', '2'],
1175 [['Constant', 'int', '4'],
1176 ['Constant', 'int', '5']],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001177 ['Constant', 'int', '6']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001178
eli.benderskyf890a862010-10-30 12:13:23 +02001179 def test_decl_named_inits(self):
1180 d1 = 'int a = {.k = 16};'
1181 self.assertEqual(self.get_decl_init(d1),
1182 [( [['ID', 'k']],
1183 ['Constant', 'int', '16'])])
1184
1185 d2 = 'int a = { [0].a = {1}, [1].a[0] = 2 };'
1186 self.assertEqual(self.get_decl_init(d2),
1187 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001188 ([['Constant', 'int', '0'], ['ID', 'a']],
1189 [['Constant', 'int', '1']]),
1190 ([['Constant', 'int', '1'], ['ID', 'a'], ['Constant', 'int', '0']],
eli.benderskyf890a862010-10-30 12:13:23 +02001191 ['Constant', 'int', '2'])])
1192
1193 d3 = 'int a = { .a = 1, .c = 3, 4, .b = 5};'
1194 self.assertEqual(self.get_decl_init(d3),
1195 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001196 ([['ID', 'a']], ['Constant', 'int', '1']),
1197 ([['ID', 'c']], ['Constant', 'int', '3']),
1198 ['Constant', 'int', '4'],
eli.benderskyf890a862010-10-30 12:13:23 +02001199 ([['ID', 'b']], ['Constant', 'int', '5'])])
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001200
1201 def test_function_definitions(self):
1202 def parse_fdef(str):
1203 return self.parse(str).ext[0]
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001204
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001205 def fdef_decl(fdef):
1206 return expand_decl(fdef.decl)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001207
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001208 f1 = parse_fdef('''
1209 int factorial(int p)
1210 {
1211 return 3;
1212 }
1213 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001214
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001215 self.assertEqual(fdef_decl(f1),
1216 ['Decl', 'factorial',
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001217 ['FuncDecl',
1218 [['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001219 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001220
eli.benderskyef29ff92010-10-29 16:25:43 +02001221 self.assertEqual(type(f1.body.block_items[0]), Return)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001222
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001223 f2 = parse_fdef('''
1224 char* zzz(int p, char* c)
1225 {
1226 int a;
1227 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001228
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001229 a = b + 2;
1230 return 3;
1231 }
1232 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001233
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001234 self.assertEqual(fdef_decl(f2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001235 ['Decl', 'zzz',
1236 ['FuncDecl',
1237 [ ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]],
1238 ['Decl', 'c', ['PtrDecl',
1239 ['TypeDecl', ['IdentifierType', ['char']]]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001240 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001241
1242 self.assertEqual(list(map(type, f2.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001243 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001244
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001245 f3 = parse_fdef('''
1246 char* zzz(p, c)
1247 long p, *c;
1248 {
1249 int a;
1250 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001251
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001252 a = b + 2;
1253 return 3;
1254 }
1255 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001256
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001257 self.assertEqual(fdef_decl(f3),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001258 ['Decl', 'zzz',
1259 ['FuncDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001260 [ ['ID', 'p'],
1261 ['ID', 'c']],
1262 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001263
1264 self.assertEqual(list(map(type, f3.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001265 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001266
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001267 self.assertEqual(expand_decl(f3.param_decls[0]),
1268 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['long']]]])
1269 self.assertEqual(expand_decl(f3.param_decls[1]),
1270 ['Decl', 'c', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['long']]]]])
1271
Sye van der Veen51a46ec2013-06-10 12:56:15 -04001272 # function return values and parameters may not have type information
1273 f4 = parse_fdef('''
1274 que(p)
1275 {
1276 return 3;
1277 }
1278 ''')
1279
1280 self.assertEqual(fdef_decl(f4),
1281 ['Decl', 'que',
1282 ['FuncDecl',
1283 [['ID', 'p']],
1284 ['TypeDecl', ['IdentifierType', ['int']]]]])
1285
eli.bendersky71540662010-07-03 12:58:52 +02001286 def test_unified_string_literals(self):
1287 # simple string, for reference
1288 d1 = self.get_decl_init('char* s = "hello";')
1289 self.assertEqual(d1, ['Constant', 'string', '"hello"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001290
eli.bendersky71540662010-07-03 12:58:52 +02001291 d2 = self.get_decl_init('char* s = "hello" " world";')
1292 self.assertEqual(d2, ['Constant', 'string', '"hello world"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001293
eli.bendersky71540662010-07-03 12:58:52 +02001294 # the test case from issue 6
1295 d3 = self.parse(r'''
1296 int main() {
1297 fprintf(stderr,
1298 "Wrong Params?\n"
1299 "Usage:\n"
1300 "%s <binary_file_path>\n",
1301 argv[0]
1302 );
1303 }
1304 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001305
eli.bendersky71540662010-07-03 12:58:52 +02001306 self.assertEqual(
eli.benderskyef29ff92010-10-29 16:25:43 +02001307 d3.ext[0].body.block_items[0].args.exprs[1].value,
eli.bendersky71540662010-07-03 12:58:52 +02001308 r'"Wrong Params?\nUsage:\n%s <binary_file_path>\n"')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001309
eli.bendersky4a89f112010-07-05 06:02:03 +02001310 d4 = self.get_decl_init('char* s = "" "foobar";')
1311 self.assertEqual(d4, ['Constant', 'string', '"foobar"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001312
eli.bendersky4a89f112010-07-05 06:02:03 +02001313 d5 = self.get_decl_init(r'char* s = "foo\"" "bar";')
1314 self.assertEqual(d5, ['Constant', 'string', r'"foo\"bar"'])
eli.bendersky71540662010-07-03 12:58:52 +02001315
Eli Benderskyc9f1a382014-03-15 14:12:00 -07001316 def test_unified_wstring_literals(self):
1317 d1 = self.get_decl_init('char* s = L"hello" L"world";')
1318 self.assertEqual(d1, ['Constant', 'string', 'L"helloworld"'])
1319
1320 d2 = self.get_decl_init('char* s = L"hello " L"world" L" and I";')
1321 self.assertEqual(d2, ['Constant', 'string', 'L"hello world and I"'])
1322
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001323 def test_inline_specifier(self):
eli.bendersky79d5cf62010-10-29 13:33:52 +02001324 ps2 = self.parse('static inline void inlinefoo(void);')
1325 self.assertEqual(ps2.ext[0].funcspec, ['inline'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001326
eli.bendersky2e907fa2010-10-29 15:51:07 +02001327 # variable length array
1328 def test_vla(self):
1329 ps2 = self.parse(r'''
1330 int main() {
1331 int size;
1332 int var[size = 5];
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001333
eli.bendersky2e907fa2010-10-29 15:51:07 +02001334 int var2[*];
1335 }
1336 ''')
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001337 self.assertTrue(isinstance(ps2.ext[0].body.block_items[1].type.dim, Assignment))
1338 self.assertTrue(isinstance(ps2.ext[0].body.block_items[2].type.dim, ID))
eli.bendersky79d5cf62010-10-29 13:33:52 +02001339
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001340 def test_pragma(self):
1341 s1 = r'''
1342 #pragma bar
1343 void main() {
1344 #pragma foo
1345 for(;;) {}
Julian Hammer8a174062015-12-14 14:48:16 +01001346 #pragma
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001347 }
1348 '''
1349 s1_ast = self.parse(s1)
1350 self.assertTrue(isinstance(s1_ast.ext[0], Pragma))
1351 self.assertEqual(s1_ast.ext[0].string, 'bar')
Julian Hammer8a174062015-12-14 14:48:16 +01001352 self.assertEqual(s1_ast.ext[0].coord.line, 2)
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001353
1354 self.assertTrue(isinstance(s1_ast.ext[1].body.block_items[0], Pragma))
1355 self.assertEqual(s1_ast.ext[1].body.block_items[0].string, 'foo')
Julian Hammer8a174062015-12-14 14:48:16 +01001356 self.assertEqual(s1_ast.ext[1].body.block_items[0].coord.line, 4)
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001357
Julian Hammer8a174062015-12-14 14:48:16 +01001358 self.assertTrue(isinstance(s1_ast.ext[1].body.block_items[2], Pragma))
1359 self.assertEqual(s1_ast.ext[1].body.block_items[2].string, '')
1360 self.assertEqual(s1_ast.ext[1].body.block_items[2].coord.line, 6)
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001361
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001362
eli.bendersky85d2e732011-05-20 19:47:26 +03001363class TestCParser_whole_code(TestCParser_base):
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001364 """ Testing of parsing whole chunks of code.
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001365
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001366 Since I don't want to rely on the structure of ASTs too
1367 much, most of these tests are implemented with visitors.
1368 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001369 # A simple helper visitor that lists the values of all the
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001370 # Constant nodes it sees.
1371 #
1372 class ConstantVisitor(NodeVisitor):
1373 def __init__(self):
1374 self.values = []
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001375
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001376 def visit_Constant(self, node):
1377 self.values.append(node.value)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001378
1379 # This visitor counts the amount of references to the ID
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001380 # with the name provided to it in the constructor.
1381 #
1382 class IDNameCounter(NodeVisitor):
1383 def __init__(self, name):
1384 self.name = name
1385 self.nrefs = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001386
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001387 def visit_ID(self, node):
1388 if node.name == self.name:
1389 self.nrefs += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001390
1391 # Counts the amount of nodes of a given class
1392 #
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001393 class NodeKlassCounter(NodeVisitor):
1394 def __init__(self, node_klass):
1395 self.klass = node_klass
1396 self.n = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001397
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001398 def generic_visit(self, node):
1399 if node.__class__ == self.klass:
1400 self.n += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001401
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001402 NodeVisitor.generic_visit(self, node)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001403
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001404 def assert_all_Constants(self, code, constants):
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001405 """ Asserts that the list of all Constant values (by
1406 'preorder' appearance) in the chunk of code is as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001407 given.
1408 """
eli.benderskyed890492010-06-25 08:25:55 +03001409 if isinstance(code, str):
1410 parsed = self.parse(code)
1411 else:
1412 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001413
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001414 cv = self.ConstantVisitor()
1415 cv.visit(parsed)
1416 self.assertEqual(cv.values, constants)
1417
1418 def assert_num_ID_refs(self, code, name, num):
1419 """ Asserts the number of references to the ID with
1420 the given name.
1421 """
1422 if isinstance(code, str):
1423 parsed = self.parse(code)
1424 else:
1425 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001426
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001427 iv = self.IDNameCounter(name)
1428 iv.visit(parsed)
1429 self.assertEqual(iv.nrefs, num)
1430
1431 def assert_num_klass_nodes(self, code, klass, num):
1432 """ Asserts the amount of klass nodes in the code.
1433 """
1434 if isinstance(code, str):
1435 parsed = self.parse(code)
1436 else:
1437 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001438
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001439 cv = self.NodeKlassCounter(klass)
1440 cv.visit(parsed)
1441 self.assertEqual(cv.n, num)
1442
1443 def test_expressions(self):
1444 e1 = '''int k = (r + 10.0) >> 6 + 8 << (3 & 0x14);'''
1445 self.assert_all_Constants(e1, ['10.0', '6', '8', '3', '0x14'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001446
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001447 e2 = r'''char n = '\n', *prefix = "st_";'''
1448 self.assert_all_Constants(e2, [r"'\n'", '"st_"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001449
Eli Bendersky09e22a62013-07-02 06:00:36 -07001450 s1 = r'''int main() {
1451 int i = 5, j = 6, k = 1;
1452 if ((i=j && k == 1) || k > j)
1453 printf("Hello, world\n");
1454 return 0;
1455 }'''
1456 ps1 = self.parse(s1)
1457 self.assert_all_Constants(ps1,
1458 ['5', '6', '1', '1', '"Hello, world\\n"', '0'])
1459 self.assert_num_ID_refs(ps1, 'i', 1)
1460 self.assert_num_ID_refs(ps1, 'j', 2)
1461
1462
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001463 def test_statements(self):
1464 s1 = r'''
1465 void foo(){
1466 if (sp == 1)
1467 if (optind >= argc ||
1468 argv[optind][0] != '-' || argv[optind][1] == '\0')
1469 return -1;
1470 else if (strcmp(argv[optind], "--") == 0) {
1471 optind++;
1472 return -1;
1473 }
1474 }
1475 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001476
1477 self.assert_all_Constants(s1,
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001478 ['1', '0', r"'-'", '1', r"'\0'", '1', r'"--"', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001479
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001480 ps1 = self.parse(s1)
1481 self.assert_num_ID_refs(ps1, 'argv', 3)
1482 self.assert_num_ID_refs(ps1, 'optind', 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001483
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001484 self.assert_num_klass_nodes(ps1, If, 3)
1485 self.assert_num_klass_nodes(ps1, Return, 2)
1486 self.assert_num_klass_nodes(ps1, FuncCall, 1) # strcmp
1487 self.assert_num_klass_nodes(ps1, BinaryOp, 7)
1488
1489 # In the following code, Hash and Node were defined as
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001490 # int to pacify the parser that sees they're used as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001491 # types
1492 #
1493 s2 = r'''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001494 typedef int Hash, Node;
1495
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001496 void HashDestroy(Hash* hash)
1497 {
1498 unsigned int i;
1499
1500 if (hash == NULL)
1501 return;
1502
1503 for (i = 0; i < hash->table_size; ++i)
1504 {
1505 Node* temp = hash->heads[i];
1506
1507 while (temp != NULL)
1508 {
1509 Node* temp2 = temp;
1510
1511 free(temp->entry->key);
1512 free(temp->entry->value);
1513 free(temp->entry);
1514
1515 temp = temp->next;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001516
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001517 free(temp2);
1518 }
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001519 }
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001520
1521 free(hash->heads);
1522 hash->heads = NULL;
1523
1524 free(hash);
1525 }
1526 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001527
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001528 ps2 = self.parse(s2)
1529 self.assert_num_klass_nodes(ps2, FuncCall, 6)
1530 self.assert_num_klass_nodes(ps2, FuncDef, 1)
1531 self.assert_num_klass_nodes(ps2, For, 1)
1532 self.assert_num_klass_nodes(ps2, While, 1)
1533 self.assert_num_klass_nodes(ps2, StructRef, 10)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001534
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001535 # declarations don't count
1536 self.assert_num_ID_refs(ps2, 'hash', 6)
1537 self.assert_num_ID_refs(ps2, 'i', 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001538
eli.benderskyed890492010-06-25 08:25:55 +03001539 s3 = r'''
1540 void x(void) {
1541 int a, b;
1542 if (a < b)
1543 do {
1544 a = 0;
1545 } while (0);
1546 else if (a == b) {
1547 a = 1;
1548 }
1549 }
1550 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001551
eli.benderskyed890492010-06-25 08:25:55 +03001552 ps3 = self.parse(s3)
1553 self.assert_num_klass_nodes(ps3, DoWhile, 1)
1554 self.assert_num_ID_refs(ps3, 'a', 4)
1555 self.assert_all_Constants(ps3, ['0', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001556
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001557 def test_empty_statements(self):
eli.bendersky91c0aa32011-10-16 05:50:43 +02001558 s1 = r'''
1559 void foo(void){
1560 ;
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001561 return;;
1562
1563 ;
eli.bendersky91c0aa32011-10-16 05:50:43 +02001564 }
1565 '''
1566 ps1 = self.parse(s1)
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001567 self.assert_num_klass_nodes(ps1, EmptyStatement, 3)
eli.bendersky91c0aa32011-10-16 05:50:43 +02001568 self.assert_num_klass_nodes(ps1, Return, 1)
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001569 self.assert_coord(ps1.ext[0].body.block_items[0], 3, '')
1570 self.assert_coord(ps1.ext[0].body.block_items[1], 4, '')
1571 self.assert_coord(ps1.ext[0].body.block_items[2], 4, '')
1572 self.assert_coord(ps1.ext[0].body.block_items[3], 6, '')
eli.bendersky145890d2010-10-29 12:02:32 +02001573
Ben5cd3fd62012-02-03 06:02:40 +02001574 def test_switch_statement(self):
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001575 def assert_case_node(node, const_value):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001576 self.assertTrue(isinstance(node, Case))
1577 self.assertTrue(isinstance(node.expr, Constant))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001578 self.assertEqual(node.expr.value, const_value)
1579
1580 def assert_default_node(node):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001581 self.assertTrue(isinstance(node, Default))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001582
Ben5cd3fd62012-02-03 06:02:40 +02001583 s1 = r'''
1584 int foo(void) {
1585 switch (myvar) {
1586 case 10:
1587 k = 10;
1588 p = k + 1;
1589 return 10;
1590 case 20:
1591 case 30:
1592 return 20;
1593 default:
1594 break;
1595 }
1596 return 0;
1597 }
1598 '''
1599 ps1 = self.parse(s1)
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001600 switch = ps1.ext[0].body.block_items[0]
1601
1602 block = switch.stmt.block_items
1603 assert_case_node(block[0], '10')
1604 self.assertEqual(len(block[0].stmts), 3)
1605 assert_case_node(block[1], '20')
1606 self.assertEqual(len(block[1].stmts), 0)
1607 assert_case_node(block[2], '30')
1608 self.assertEqual(len(block[2].stmts), 1)
1609 assert_default_node(block[3])
1610
1611 s2 = r'''
1612 int foo(void) {
1613 switch (myvar) {
1614 default:
1615 joe = moe;
1616 return 10;
1617 case 10:
1618 case 20:
1619 case 30:
1620 case 40:
1621 break;
1622 }
1623 return 0;
1624 }
1625 '''
1626 ps2 = self.parse(s2)
1627 switch = ps2.ext[0].body.block_items[0]
1628
1629 block = switch.stmt.block_items
1630 assert_default_node(block[0])
1631 self.assertEqual(len(block[0].stmts), 2)
1632 assert_case_node(block[1], '10')
1633 self.assertEqual(len(block[1].stmts), 0)
1634 assert_case_node(block[2], '20')
1635 self.assertEqual(len(block[1].stmts), 0)
1636 assert_case_node(block[3], '30')
1637 self.assertEqual(len(block[1].stmts), 0)
1638 assert_case_node(block[4], '40')
1639 self.assertEqual(len(block[4].stmts), 1)
Ben5cd3fd62012-02-03 06:02:40 +02001640
eli.bendersky145890d2010-10-29 12:02:32 +02001641 def test_for_statement(self):
1642 s2 = r'''
1643 void x(void)
1644 {
1645 int i;
1646 for (i = 0; i < 5; ++i) {
1647 x = 50;
1648 }
1649 }
1650 '''
1651 ps2 = self.parse(s2)
1652 self.assert_num_klass_nodes(ps2, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001653 # here there are 3 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001654 # a ref in the visitor
1655 #
1656 self.assert_num_ID_refs(ps2, 'i', 3)
Eli Bendersky4476d092012-12-25 14:07:57 -08001657
eli.bendersky145890d2010-10-29 12:02:32 +02001658 s3 = r'''
1659 void x(void)
1660 {
1661 for (int i = 0; i < 5; ++i) {
1662 x = 50;
1663 }
1664 }
1665 '''
1666 ps3 = self.parse(s3)
eli.bendersky145890d2010-10-29 12:02:32 +02001667 self.assert_num_klass_nodes(ps3, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001668 # here there are 2 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001669 # a ref in the visitor
1670 #
1671 self.assert_num_ID_refs(ps3, 'i', 2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001672
Eli Bendersky4476d092012-12-25 14:07:57 -08001673 s4 = r'''
1674 void x(void) {
1675 for (int i = 0;;)
1676 i;
1677 }
1678 '''
1679 ps4 = self.parse(s4)
1680 self.assert_num_ID_refs(ps4, 'i', 1)
1681
Eli Benderskyd0973782012-01-19 08:09:33 +02001682 def _open_c_file(self, name):
1683 """ Find a c file by name, taking into account the current dir can be
1684 in a couple of typical places
1685 """
Stefano Riveraebaf5922013-08-08 09:45:26 +02001686 testdir = os.path.dirname(__file__)
1687 name = os.path.join(testdir, 'c_files', name)
1688 assert os.path.exists(name)
1689 return open(name, 'rU')
Eli Benderskyd0973782012-01-19 08:09:33 +02001690
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001691 def test_whole_file(self):
1692 # See how pycparser handles a whole, real C file.
1693 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001694 with self._open_c_file('memmgr_with_h.c') as f:
1695 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001696 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001697
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001698 self.assert_num_klass_nodes(p, FuncDef, 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001699
1700 # each FuncDef also has a FuncDecl. 4 declarations
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001701 # + 5 definitions, overall 9
1702 self.assert_num_klass_nodes(p, FuncDecl, 9)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001703
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001704 self.assert_num_klass_nodes(p, Typedef, 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001705
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001706 self.assertEqual(p.ext[4].coord.line, 88)
1707 self.assertEqual(p.ext[4].coord.file, "./memmgr.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001708
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001709 self.assertEqual(p.ext[6].coord.line, 10)
1710 self.assertEqual(p.ext[6].coord.file, "memmgr.c")
1711
1712 def test_whole_file_with_stdio(self):
1713 # Parse a whole file with stdio.h included by cpp
1714 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001715 with self._open_c_file('cppd_with_stdio_h.c') as f:
1716 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001717 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001718
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001719 self.assertTrue(isinstance(p.ext[0], Typedef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001720 self.assertEqual(p.ext[0].coord.line, 213)
1721 self.assertEqual(p.ext[0].coord.file, "D:\eli\cpp_stuff\libc_include/stddef.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001722
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001723 self.assertTrue(isinstance(p.ext[-1], FuncDef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001724 self.assertEqual(p.ext[-1].coord.line, 15)
1725 self.assertEqual(p.ext[-1].coord.file, "example_c_file.c")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001726
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001727 self.assertTrue(isinstance(p.ext[-8], Typedef))
1728 self.assertTrue(isinstance(p.ext[-8].type, TypeDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001729 self.assertEqual(p.ext[-8].name, 'cookie_io_functions_t')
eli.bendersky85d2e732011-05-20 19:47:26 +03001730
1731
1732class TestCParser_typenames(TestCParser_base):
1733 """ Test issues related to the typedef-name problem.
1734 """
1735 def test_innerscope_typedef(self):
1736 # should fail since TT is not a type in bar
1737 s1 = r'''
1738 void foo() {
1739 typedef char TT;
1740 TT x;
1741 }
1742 void bar() {
1743 TT y;
1744 }
1745 '''
1746 self.assertRaises(ParseError, self.parse, s1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001747
eli.bendersky85d2e732011-05-20 19:47:26 +03001748 # should succeed since TT is not a type in bar
1749 s2 = r'''
1750 void foo() {
1751 typedef char TT;
1752 TT x;
1753 }
1754 void bar() {
1755 unsigned TT;
1756 }
1757 '''
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001758 self.assertTrue(isinstance(self.parse(s2), FileAST))
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001759
Nate Bogdanowicz14b8a7e2017-02-22 08:54:05 -05001760 def test_ambiguous_parameters(self):
1761 # From ISO/IEC 9899:TC2, 6.7.5.3.11:
1762 # "If, in a parameter declaration, an identifier can be treated either
1763 # as a typedef name or as a parameter name, it shall be taken as a
1764 # typedef name."
1765
1766 # foo takes an int named aa
1767 # bar takes a function taking a TT
1768 s1 = r'''
1769 typedef char TT;
1770 int foo(int (aa));
1771 int bar(int (TT));
1772 '''
1773 s1_ast = self.parse(s1)
1774 self.assertEqual(expand_decl(s1_ast.ext[1].type.args.params[0]),
1775 ['Decl', 'aa', ['TypeDecl', ['IdentifierType', ['int']]]])
1776 self.assertEqual(expand_decl(s1_ast.ext[2].type.args.params[0]),
1777 ['Typename', ['FuncDecl',
1778 [['Typename', ['TypeDecl', ['IdentifierType', ['TT']]]]],
1779 ['TypeDecl', ['IdentifierType', ['int']]]]])
1780
1781 # foo takes a function taking a char
1782 # bar takes a function taking a function taking a char
1783 s2 = r'''
1784 typedef char TT;
1785 int foo(int (aa (char)));
1786 int bar(int (TT (char)));
1787 '''
1788 s2_ast = self.parse(s2)
1789 self.assertEqual(expand_decl(s2_ast.ext[1].type.args.params[0]),
1790 ['Decl', 'aa', ['FuncDecl',
1791 [['Typename', ['TypeDecl', ['IdentifierType', ['char']]]]],
1792 ['TypeDecl', ['IdentifierType', ['int']]]]])
1793 self.assertEqual(expand_decl(s2_ast.ext[2].type.args.params[0]),
1794 ['Typename', ['FuncDecl',
1795 [['Typename', ['FuncDecl',
1796 [['Typename', ['TypeDecl', ['IdentifierType', ['char']]]]],
1797 ['TypeDecl', ['IdentifierType', ['TT']]]]]],
1798 ['TypeDecl', ['IdentifierType', ['int']]]]])
1799
1800
1801 # foo takes an int array named aa
1802 # bar takes a function taking a TT array
1803 s3 = r'''
1804 typedef char TT;
1805 int foo(int (aa[]));
1806 int bar(int (TT[]));
1807 '''
1808 s3_ast = self.parse(s3)
1809 self.assertEqual(expand_decl(s3_ast.ext[1].type.args.params[0]),
1810 ['Decl', 'aa', ['ArrayDecl', '', [], ['TypeDecl', ['IdentifierType', ['int']]]]])
1811 self.assertEqual(expand_decl(s3_ast.ext[2].type.args.params[0]),
1812 ['Typename', ['FuncDecl',
1813 [['Typename', ['ArrayDecl', '', [], ['TypeDecl', ['IdentifierType', ['TT']]]]]],
1814 ['TypeDecl', ['IdentifierType', ['int']]]]])
1815
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001816 def test_innerscope_reuse_typedef_name(self):
1817 # identifiers can be reused in inner scopes; the original should be
1818 # restored at the end of the block
1819 s1 = r'''
1820 typedef char TT;
1821 void foo(void) {
1822 unsigned TT;
1823 TT = 10;
1824 }
1825 TT x = 5;
1826 '''
1827 s1_ast = self.parse(s1)
1828 self.assertEqual(expand_decl(s1_ast.ext[1].body.block_items[0]),
1829 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
Eli Bendersky3877c4c2013-07-13 06:54:04 -07001830 self.assertEqual(expand_decl(s1_ast.ext[2]),
1831 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['TT']]]])
eli.bendersky85d2e732011-05-20 19:47:26 +03001832
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001833 # this should be recognized even with an initializer
1834 s2 = r'''
1835 typedef char TT;
1836 void foo(void) {
1837 unsigned TT = 10;
1838 }
1839 '''
1840 s2_ast = self.parse(s2)
1841 self.assertEqual(expand_decl(s2_ast.ext[1].body.block_items[0]),
1842 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1843
1844 # before the second local variable, TT is a type; after, it's a
1845 # variable
1846 s3 = r'''
1847 typedef char TT;
1848 void foo(void) {
1849 TT tt = sizeof(TT);
1850 unsigned TT = 10;
1851 }
1852 '''
1853 s3_ast = self.parse(s3)
1854 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[0]),
1855 ['Decl', 'tt', ['TypeDecl', ['IdentifierType', ['TT']]]])
1856 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[1]),
1857 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1858
1859 # a variable and its type can even share the same name
1860 s4 = r'''
1861 typedef char TT;
1862 void foo(void) {
1863 TT TT = sizeof(TT);
1864 unsigned uu = TT * 2;
1865 }
1866 '''
1867 s4_ast = self.parse(s4)
1868 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[0]),
1869 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['TT']]]])
1870 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[1]),
1871 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1872
1873 # ensure an error is raised if a type, redeclared as a variable, is
1874 # used as a type
1875 s5 = r'''
1876 typedef char TT;
1877 void foo(void) {
1878 unsigned TT = 10;
1879 TT erroneous = 20;
1880 }
1881 '''
1882 self.assertRaises(ParseError, self.parse, s5)
1883
Nate Bogdanowicz14b8a7e2017-02-22 08:54:05 -05001884 # reusing a type name should work with multiple declarators
1885 s6 = r'''
1886 typedef char TT;
1887 void foo(void) {
1888 unsigned TT, uu;
1889 }
1890 '''
1891 s6_ast = self.parse(s6)
1892 items = s6_ast.ext[1].body.block_items
1893 self.assertEqual(expand_decl(items[0]),
1894 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1895 self.assertEqual(expand_decl(items[1]),
1896 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1897
1898 # reusing a type name should work after a pointer
1899 s7 = r'''
1900 typedef char TT;
1901 void foo(void) {
1902 unsigned * TT;
1903 }
1904 '''
1905 s7_ast = self.parse(s7)
1906 items = s7_ast.ext[1].body.block_items
1907 self.assertEqual(expand_decl(items[0]),
1908 ['Decl', 'TT', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['unsigned']]]]])
1909
1910 # redefine a name in the middle of a multi-declarator declaration
1911 s8 = r'''
1912 typedef char TT;
1913 void foo(void) {
1914 int tt = sizeof(TT), TT, uu = sizeof(TT);
1915 int uu = sizeof(tt);
1916 }
1917 '''
1918 s8_ast = self.parse(s8)
1919 items = s8_ast.ext[1].body.block_items
1920 self.assertEqual(expand_decl(items[0]),
1921 ['Decl', 'tt', ['TypeDecl', ['IdentifierType', ['int']]]])
1922 self.assertEqual(expand_decl(items[1]),
1923 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['int']]]])
1924 self.assertEqual(expand_decl(items[2]),
1925 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['int']]]])
1926
1927 # Don't test this until we have support for it
1928 # self.assertEqual(expand_init(items[0].init),
1929 # ['UnaryOp', 'sizeof', ['Typename', ['TypeDecl', ['IdentifierType', ['TT']]]]])
1930 # self.assertEqual(expand_init(items[2].init),
1931 # ['UnaryOp', 'sizeof', ['ID', 'TT']])
1932
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001933 def test_parameter_reuse_typedef_name(self):
1934 # identifiers can be reused as parameter names; parameter name scope
1935 # begins and ends with the function body; it's important that TT is
Eli Bendersky4d969b32013-07-13 06:07:07 -07001936 # used immediately before the LBRACE or after the RBRACE, to test
1937 # a corner case
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001938 s1 = r'''
1939 typedef char TT;
1940 void foo(unsigned TT, TT bar) {
1941 TT = 10;
1942 }
1943 TT x = 5;
1944 '''
1945 s1_ast = self.parse(s1)
1946 self.assertEqual(expand_decl(s1_ast.ext[1].decl),
1947 ['Decl', 'foo',
1948 ['FuncDecl',
1949 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
1950 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
1951 ['TypeDecl', ['IdentifierType', ['void']]]]])
1952
1953 # the scope of a parameter name in a function declaration ends at the
1954 # end of the declaration...so it is effectively never used; it's
1955 # important that TT is used immediately after the declaration, to
1956 # test a corner case
1957 s2 = r'''
1958 typedef char TT;
1959 void foo(unsigned TT, TT bar);
1960 TT x = 5;
1961 '''
1962 s2_ast = self.parse(s2)
1963 self.assertEqual(expand_decl(s2_ast.ext[1]),
1964 ['Decl', 'foo',
1965 ['FuncDecl',
1966 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
1967 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
1968 ['TypeDecl', ['IdentifierType', ['void']]]]])
1969
1970 # ensure an error is raised if a type, redeclared as a parameter, is
1971 # used as a type
1972 s3 = r'''
1973 typedef char TT;
1974 void foo(unsigned TT, TT bar) {
1975 TT erroneous = 20;
1976 }
1977 '''
1978 self.assertRaises(ParseError, self.parse, s3)
1979
1980 def test_nested_function_decls(self):
1981 # parameter names of nested function declarations must not escape into
1982 # the top-level function _definition's_ scope; the following must
1983 # succeed because TT is still a typedef inside foo's body
1984 s1 = r'''
1985 typedef char TT;
1986 void foo(unsigned bar(int TT)) {
1987 TT x = 10;
1988 }
1989 '''
1990 self.assertTrue(isinstance(self.parse(s1), FileAST))
1991
1992 def test_samescope_reuse_name(self):
1993 # a typedef name cannot be reused as an object name in the same scope
1994 s1 = r'''
1995 typedef char TT;
1996 char TT = 5;
1997 '''
1998 self.assertRaises(ParseError, self.parse, s1)
1999
2000 # ...and vice-versa
2001 s2 = r'''
2002 char TT = 5;
2003 typedef char TT;
2004 '''
2005 self.assertRaises(ParseError, self.parse, s2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03002006
Julian Hammerdb9f2da2015-10-12 15:52:12 +02002007
Eli Bendersky3921e8e2010-05-21 09:05:39 +03002008if __name__ == '__main__':
2009 #~ suite = unittest.TestLoader().loadTestsFromNames(
2010 #~ ['test_c_parser.TestCParser_fundamentals.test_typedef'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08002011
Eli Bendersky3921e8e2010-05-21 09:05:39 +03002012 #~ unittest.TextTestRunner(verbosity=2).run(suite)
2013 unittest.main()