blob: 5c7d723d71495aec548dc47e8a6c83a6e905ad8c [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:
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 Bendersky8e5d3a92014-03-15 14:06:00 -0700213 def test_forloop_coord(self):
214 t = '''\
215 void foo() {
216 for(int z=0; z<4;
217 z++){}
218 }
219 '''
220 s = self.parse(t, filename='f.c')
221 forloop = s.ext[0].body.block_items[0]
222 self.assert_coord(forloop.init, 2, 'f.c')
223 self.assert_coord(forloop.cond, 2, 'f.c')
224 self.assert_coord(forloop.next, 3, 'f.c')
225
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300226 def test_simple_decls(self):
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800227 self.assertEqual(self.get_decl('int a;'),
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300228 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
229
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800230 self.assertEqual(self.get_decl('unsigned int a;'),
Eli Bendersky68497c22012-01-19 06:04:58 +0200231 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['unsigned', 'int']]]])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300232
eli.benderskyaffe0322011-09-24 06:16:55 +0300233 self.assertEqual(self.get_decl('_Bool a;'),
234 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['_Bool']]]])
235
Eli Benderskyf4d73462012-01-19 05:56:27 +0200236 self.assertEqual(self.get_decl('float _Complex fcc;'),
Eli Bendersky68497c22012-01-19 06:04:58 +0200237 ['Decl', 'fcc', ['TypeDecl', ['IdentifierType', ['float', '_Complex']]]])
Eli Benderskyf4d73462012-01-19 05:56:27 +0200238
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800239 self.assertEqual(self.get_decl('char* string;'),
240 ['Decl', 'string',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300241 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]])
242
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800243 self.assertEqual(self.get_decl('long ar[15];'),
244 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800245 ['ArrayDecl', '15', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300246 ['TypeDecl', ['IdentifierType', ['long']]]]])
eli.bendersky98f45372010-10-30 09:46:29 +0200247
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800248 self.assertEqual(self.get_decl('long long ar[15];'),
249 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800250 ['ArrayDecl', '15', [],
eli.benderskyf890a862010-10-30 12:13:23 +0200251 ['TypeDecl', ['IdentifierType', ['long', 'long']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800252
253 self.assertEqual(self.get_decl('unsigned ar[];'),
254 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800255 ['ArrayDecl', '', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300256 ['TypeDecl', ['IdentifierType', ['unsigned']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800257
258 self.assertEqual(self.get_decl('int strlen(char* s);'),
259 ['Decl', 'strlen',
260 ['FuncDecl',
261 [['Decl', 's',
262 ['PtrDecl',
263 ['TypeDecl', ['IdentifierType', ['char']]]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300264 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800265
266 self.assertEqual(self.get_decl('int strcmp(char* s1, char* s2);'),
267 ['Decl', 'strcmp',
268 ['FuncDecl',
269 [ ['Decl', 's1',
270 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
271 ['Decl', 's2',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300272 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800273 ],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300274 ['TypeDecl', ['IdentifierType', ['int']]]]])
275
Sye van der Veen51a46ec2013-06-10 12:56:15 -0400276 # function return values and parameters may not have type information
Eli Bendersky09e22a62013-07-02 06:00:36 -0700277 self.assertEqual(self.get_decl('extern foobar(foo, bar);'),
278 ['Decl', 'foobar',
279 ['FuncDecl',
Sye van der Veen51a46ec2013-06-10 12:56:15 -0400280 [ ['ID', 'foo'],
281 ['ID', 'bar']
Eli Bendersky09e22a62013-07-02 06:00:36 -0700282 ],
Sye van der Veen51a46ec2013-06-10 12:56:15 -0400283 ['TypeDecl', ['IdentifierType', ['int']]]]])
284
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300285 def test_nested_decls(self): # the fun begins
286 self.assertEqual(self.get_decl('char** ar2D;'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800287 ['Decl', 'ar2D',
288 ['PtrDecl', ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300289 ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800290
291 self.assertEqual(self.get_decl('int (*a)[1][2];'),
292 ['Decl', 'a',
293 ['PtrDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800294 ['ArrayDecl', '1', [],
295 ['ArrayDecl', '2', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300296 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
297
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800298 self.assertEqual(self.get_decl('int *a[1][2];'),
299 ['Decl', 'a',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800300 ['ArrayDecl', '1', [],
301 ['ArrayDecl', '2', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300302 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['int']]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800303
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300304 self.assertEqual(self.get_decl('char ***ar3D[40];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800305 ['Decl', 'ar3D',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800306 ['ArrayDecl', '40', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800307 ['PtrDecl', ['PtrDecl', ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300308 ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800309
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300310 self.assertEqual(self.get_decl('char (***ar3D)[40];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800311 ['Decl', 'ar3D',
312 ['PtrDecl', ['PtrDecl', ['PtrDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800313 ['ArrayDecl', '40', [], ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800314
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300315 self.assertEqual(self.get_decl('int (*x[4])(char, int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800316 ['Decl', 'x',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800317 ['ArrayDecl', '4', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800318 ['PtrDecl',
319 ['FuncDecl',
320 [ ['Typename', ['TypeDecl', ['IdentifierType', ['char']]]],
321 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300322 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800323
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300324 self.assertEqual(self.get_decl('char *(*(**foo [][8])())[];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800325 ['Decl', 'foo',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800326 ['ArrayDecl', '', [],
327 ['ArrayDecl', '8', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800328 ['PtrDecl', ['PtrDecl',
329 ['FuncDecl',
330 [],
331 ['PtrDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800332 ['ArrayDecl', '', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800333 ['PtrDecl',
334 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300335 ['IdentifierType', ['char']]]]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800336
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300337 # explore named and unnamed function pointer parameters,
338 # with and without qualifiers
339 #
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800340
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300341 # unnamed w/o quals
342 self.assertEqual(self.get_decl('int (*k)(int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800343 ['Decl', 'k',
344 ['PtrDecl',
345 ['FuncDecl',
346 [['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300347 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800348
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300349 # unnamed w/ quals
350 self.assertEqual(self.get_decl('int (*k)(const int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800351 ['Decl', 'k',
352 ['PtrDecl',
353 ['FuncDecl',
354 [['Typename', ['const'], ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300355 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800356
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300357 # named w/o quals
358 self.assertEqual(self.get_decl('int (*k)(int q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800359 ['Decl', 'k',
360 ['PtrDecl',
361 ['FuncDecl',
362 [['Decl', 'q', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300363 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800364
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300365 # named w/ quals
366 self.assertEqual(self.get_decl('int (*k)(const volatile int q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800367 ['Decl', 'k',
368 ['PtrDecl',
369 ['FuncDecl',
370 [['Decl', ['const', 'volatile'], 'q',
371 ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300372 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800373
eli.bendersky79d5cf62010-10-29 13:33:52 +0200374 # restrict qualifier
375 self.assertEqual(self.get_decl('int (*k)(restrict int* q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800376 ['Decl', 'k',
377 ['PtrDecl',
378 ['FuncDecl',
379 [['Decl', ['restrict'], 'q',
eli.bendersky79d5cf62010-10-29 13:33:52 +0200380 ['PtrDecl',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800381 ['TypeDecl', ['IdentifierType', ['int']]]]]],
eli.bendersky79d5cf62010-10-29 13:33:52 +0200382 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800383
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800384 def test_func_decls_with_array_dim_qualifiers(self):
385 self.assertEqual(self.get_decl('int zz(int p[static 10]);'),
386 ['Decl', 'zz',
387 ['FuncDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800388 [['Decl', 'p', ['ArrayDecl', '10', ['static'],
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800389 ['TypeDecl', ['IdentifierType', ['int']]]]]],
390 ['TypeDecl', ['IdentifierType', ['int']]]]])
391
392 self.assertEqual(self.get_decl('int zz(int p[const 10]);'),
393 ['Decl', 'zz',
394 ['FuncDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800395 [['Decl', 'p', ['ArrayDecl', '10', ['const'],
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800396 ['TypeDecl', ['IdentifierType', ['int']]]]]],
397 ['TypeDecl', ['IdentifierType', ['int']]]]])
398
necase4a6afa02014-12-19 16:38:37 -0600399 self.assertEqual(self.get_decl('int zz(int p[restrict][5]);'),
400 ['Decl', 'zz',
401 ['FuncDecl',
402 [['Decl', 'p', ['ArrayDecl', '', ['restrict'],
403 ['ArrayDecl', '5', [],
404 ['TypeDecl', ['IdentifierType', ['int']]]]]]],
405 ['TypeDecl', ['IdentifierType', ['int']]]]])
406
407 self.assertEqual(self.get_decl('int zz(int p[const restrict static 10][5]);'),
408 ['Decl', 'zz',
409 ['FuncDecl',
410 [['Decl', 'p', ['ArrayDecl', '10', ['const', 'restrict', 'static'],
411 ['ArrayDecl', '5', [],
412 ['TypeDecl', ['IdentifierType', ['int']]]]]]],
413 ['TypeDecl', ['IdentifierType', ['int']]]]])
414
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300415 def test_qualifiers_storage_specifiers(self):
416 def assert_qs(txt, index, quals, storage):
417 d = self.parse(txt).ext[index]
418 self.assertEqual(d.quals, quals)
419 self.assertEqual(d.storage, storage)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800420
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300421 assert_qs("extern int p;", 0, [], ['extern'])
422 assert_qs("const long p = 6;", 0, ['const'], [])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800423
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300424 d1 = "static const int p, q, r;"
425 for i in range(3):
426 assert_qs(d1, i, ['const'], ['static'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800427
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300428 d2 = "static char * const p;"
429 assert_qs(d2, 0, [], ['static'])
430 pdecl = self.parse(d2).ext[0].type
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300431 self.assertTrue(isinstance(pdecl, PtrDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300432 self.assertEqual(pdecl.quals, ['const'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800433
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300434 def test_sizeof(self):
435 e = """
436 void foo()
437 {
438 int a = sizeof k;
439 int b = sizeof(int);
eli.benderskyc51e1d32011-02-04 08:52:33 +0200440 int c = sizeof(int**);;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800441
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300442 char* p = "just to make sure this parses w/o error...";
443 int d = sizeof(int());
444 }
445 """
446 compound = self.parse(e).ext[0].body
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800447
eli.benderskyef29ff92010-10-29 16:25:43 +0200448 s1 = compound.block_items[0].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300449 self.assertTrue(isinstance(s1, UnaryOp))
450 self.assertEqual(s1.op, 'sizeof')
451 self.assertTrue(isinstance(s1.expr, ID))
452 self.assertEqual(s1.expr.name, 'k')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800453
eli.benderskyef29ff92010-10-29 16:25:43 +0200454 s2 = compound.block_items[1].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300455 self.assertEqual(expand_decl(s2.expr),
456 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800457
eli.benderskyef29ff92010-10-29 16:25:43 +0200458 s3 = compound.block_items[2].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300459 self.assertEqual(expand_decl(s3.expr),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800460 ['Typename',
461 ['PtrDecl',
462 ['PtrDecl',
463 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300464 ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800465
eli.bendersky9f481562010-10-30 15:50:47 +0200466 # The C99 compound literal feature
467 #
eli.benderskyf890a862010-10-30 12:13:23 +0200468 def test_compound_literals(self):
eli.bendersky9f481562010-10-30 15:50:47 +0200469 ps1 = self.parse(r'''
eli.benderskyf890a862010-10-30 12:13:23 +0200470 void foo() {
eli.bendersky9f481562010-10-30 15:50:47 +0200471 p = (long long){k};
472 tc = (struct jk){.a = {1, 2}, .b[0] = t};
473 }''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800474
eli.bendersky9f481562010-10-30 15:50:47 +0200475 compound = ps1.ext[0].body.block_items[0].rvalue
476 self.assertEqual(expand_decl(compound.type),
477 ['Typename', ['TypeDecl', ['IdentifierType', ['long', 'long']]]])
478 self.assertEqual(expand_init(compound.init),
479 [['ID', 'k']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800480
481 compound = ps1.ext[0].body.block_items[1].rvalue
eli.bendersky9f481562010-10-30 15:50:47 +0200482 self.assertEqual(expand_decl(compound.type),
483 ['Typename', ['TypeDecl', ['Struct', 'jk', []]]])
484 self.assertEqual(expand_init(compound.init),
485 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800486 ([['ID', 'a']], [['Constant', 'int', '1'], ['Constant', 'int', '2']]),
eli.bendersky9f481562010-10-30 15:50:47 +0200487 ([['ID', 'b'], ['Constant', 'int', '0']], ['ID', 't'])])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800488
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300489 def test_enums(self):
490 e1 = "enum mycolor op;"
491 e1_type = self.parse(e1).ext[0].type.type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800492
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300493 self.assertTrue(isinstance(e1_type, Enum))
494 self.assertEqual(e1_type.name, 'mycolor')
495 self.assertEqual(e1_type.values, None)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800496
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300497 e2 = "enum mysize {large=20, small, medium} shoes;"
498 e2_type = self.parse(e2).ext[0].type.type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800499
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300500 self.assertTrue(isinstance(e2_type, Enum))
501 self.assertEqual(e2_type.name, 'mysize')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800502
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300503 e2_elist = e2_type.values
504 self.assertTrue(isinstance(e2_elist, EnumeratorList))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800505
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300506 for e2_eval in e2_elist.enumerators:
507 self.assertTrue(isinstance(e2_eval, Enumerator))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800508
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300509 self.assertEqual(e2_elist.enumerators[0].name, 'large')
510 self.assertEqual(e2_elist.enumerators[0].value.value, '20')
511 self.assertEqual(e2_elist.enumerators[2].name, 'medium')
512 self.assertEqual(e2_elist.enumerators[2].value, None)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800513
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300514 # enum with trailing comma (C99 feature)
515 e3 = """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800516 enum
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300517 {
518 red,
519 blue,
520 green,
521 } color;
522 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800523
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300524 e3_type = self.parse(e3).ext[0].type.type
525 self.assertTrue(isinstance(e3_type, Enum))
526 e3_elist = e3_type.values
527 self.assertTrue(isinstance(e3_elist, EnumeratorList))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800528
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300529 for e3_eval in e3_elist.enumerators:
530 self.assertTrue(isinstance(e3_eval, Enumerator))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800531
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300532 self.assertEqual(e3_elist.enumerators[0].name, 'red')
533 self.assertEqual(e3_elist.enumerators[0].value, None)
534 self.assertEqual(e3_elist.enumerators[1].name, 'blue')
535 self.assertEqual(e3_elist.enumerators[2].name, 'green')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800536
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300537 def test_typedef(self):
538 # without typedef, error
539 s1 = """
540 node k;
541 """
542 self.assertRaises(ParseError, self.parse, s1)
543
544 # now with typedef, works
545 s2 = """
546 typedef void* node;
547 node k;
548 """
549 ps2 = self.parse(s2)
550 self.assertEqual(expand_decl(ps2.ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800551 ['Typedef', 'node',
552 ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300553 ['TypeDecl', ['IdentifierType', ['void']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800554
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300555 self.assertEqual(expand_decl(ps2.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800556 ['Decl', 'k',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300557 ['TypeDecl', ['IdentifierType', ['node']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800558
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300559 s3 = """
560 typedef int T;
561 typedef T *pT;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800562
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300563 pT aa, bb;
564 """
565 ps3 = self.parse(s3)
566 self.assertEqual(expand_decl(ps3.ext[3]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800567 ['Decl', 'bb',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300568 ['TypeDecl', ['IdentifierType', ['pT']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800569
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300570 s4 = '''
571 typedef char* __builtin_va_list;
572 typedef __builtin_va_list __gnuc_va_list;
573 '''
574 ps4 = self.parse(s4)
575 self.assertEqual(expand_decl(ps4.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800576 ['Typedef', '__gnuc_va_list',
577 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300578 ['IdentifierType', ['__builtin_va_list']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800579
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300580 s5 = '''typedef struct tagHash Hash;'''
581 ps5 = self.parse(s5)
582 self.assertEqual(expand_decl(ps5.ext[0]),
583 ['Typedef', 'Hash', ['TypeDecl', ['Struct', 'tagHash', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800584
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300585 def test_struct_union(self):
586 s1 = """
587 struct {
588 int id;
589 char* name;
590 } joe;
591 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800592
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300593 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800594 ['Decl', 'joe',
595 ['TypeDecl', ['Struct', None,
596 [ ['Decl', 'id',
597 ['TypeDecl',
598 ['IdentifierType', ['int']]]],
599 ['Decl', 'name',
600 ['PtrDecl',
601 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300602 ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800603
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300604 s2 = """
605 struct node p;
606 """
607 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800608 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300609 ['TypeDecl', ['Struct', 'node', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800610
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300611 s21 = """
612 union pri ra;
613 """
614 self.assertEqual(expand_decl(self.parse(s21).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800615 ['Decl', 'ra',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300616 ['TypeDecl', ['Union', 'pri', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800617
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300618 s3 = """
619 struct node* p;
620 """
621 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800622 ['Decl', 'p',
623 ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300624 ['TypeDecl', ['Struct', 'node', []]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800625
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300626 s4 = """
627 struct node;
628 """
629 self.assertEqual(expand_decl(self.parse(s4).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800630 ['Decl', None,
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300631 ['Struct', 'node', []]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800632
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300633 s5 = """
634 union
635 {
636 struct
637 {
638 int type;
639 } n;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800640
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300641 struct
642 {
643 int type;
644 int intnode;
645 } ni;
646 } u;
647 """
648 self.assertEqual(expand_decl(self.parse(s5).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800649 ['Decl', 'u',
650 ['TypeDecl',
651 ['Union', None,
652 [['Decl', 'n',
653 ['TypeDecl',
654 ['Struct', None,
655 [['Decl', 'type',
656 ['TypeDecl', ['IdentifierType', ['int']]]]]]]],
657 ['Decl', 'ni',
658 ['TypeDecl',
659 ['Struct', None,
660 [['Decl', 'type',
661 ['TypeDecl', ['IdentifierType', ['int']]]],
662 ['Decl', 'intnode',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300663 ['TypeDecl', ['IdentifierType', ['int']]]]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800664
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300665 s6 = """
666 typedef struct foo_tag
667 {
668 void* data;
669 } foo, *pfoo;
670 """
671 s6_ast = self.parse(s6)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800672
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300673 self.assertEqual(expand_decl(s6_ast.ext[0]),
674 ['Typedef', 'foo',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800675 ['TypeDecl',
676 ['Struct', 'foo_tag',
677 [['Decl', 'data',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300678 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800679
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300680 self.assertEqual(expand_decl(s6_ast.ext[1]),
681 ['Typedef', 'pfoo',
682 ['PtrDecl',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800683 ['TypeDecl',
684 ['Struct', 'foo_tag',
685 [['Decl', 'data',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300686 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800687
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300688 s7 = r"""
689 struct _on_exit_args {
690 void * _fnargs[32];
691 void * _dso_handle[32];
692
693 long _fntypes;
694 #line 77 "D:\eli\cpp_stuff\libc_include/sys/reent.h"
695
696 long _is_cxa;
697 };
698 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800699
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300700 s7_ast = self.parse(s7, filename='test.c')
701 self.assert_coord(s7_ast.ext[0].type.decls[2], 6, 'test.c')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800702 self.assert_coord(s7_ast.ext[0].type.decls[3], 78,
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300703 r'D:\eli\cpp_stuff\libc_include/sys/reent.h')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800704
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300705 s8 = """
706 typedef enum tagReturnCode {SUCCESS, FAIL} ReturnCode;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800707
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300708 typedef struct tagEntry
709 {
710 char* key;
711 char* value;
712 } Entry;
713
714
715 typedef struct tagNode
716 {
717 Entry* entry;
718
719 struct tagNode* next;
720 } Node;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800721
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300722 typedef struct tagHash
723 {
724 unsigned int table_size;
725
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800726 Node** heads;
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300727
728 } Hash;
729 """
730 s8_ast = self.parse(s8)
731 self.assertEqual(expand_decl(s8_ast.ext[3]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800732 ['Typedef', 'Hash',
733 ['TypeDecl', ['Struct', 'tagHash',
734 [['Decl', 'table_size',
735 ['TypeDecl', ['IdentifierType', ['unsigned', 'int']]]],
736 ['Decl', 'heads',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300737 ['PtrDecl', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['Node']]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800738
eli.bendersky697ecc52011-02-10 07:05:13 +0200739 def test_anonymous_struct_union(self):
740 s1 = """
741 union
742 {
743 union
744 {
745 int i;
746 long l;
747 };
748
749 struct
750 {
751 int type;
752 int intnode;
753 };
754 } u;
755 """
756
757 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
758 ['Decl', 'u',
759 ['TypeDecl',
760 ['Union', None,
761 [['Decl', None,
762 ['Union', None,
763 [['Decl', 'i',
764 ['TypeDecl',
765 ['IdentifierType', ['int']]]],
766 ['Decl', 'l',
767 ['TypeDecl',
768 ['IdentifierType', ['long']]]]]]],
769 ['Decl', None,
770 ['Struct', None,
771 [['Decl', 'type',
772 ['TypeDecl',
773 ['IdentifierType', ['int']]]],
774 ['Decl', 'intnode',
775 ['TypeDecl',
776 ['IdentifierType', ['int']]]]]]]]]]])
777
778 s2 = """
779 struct
780 {
781 int i;
782 union
783 {
784 int id;
785 char* name;
786 };
787 float f;
788 } joe;
789 """
790
791 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
792 ['Decl', 'joe',
793 ['TypeDecl',
794 ['Struct', None,
795 [['Decl', 'i',
796 ['TypeDecl',
797 ['IdentifierType', ['int']]]],
798 ['Decl', None,
799 ['Union', None,
800 [['Decl', 'id',
801 ['TypeDecl',
802 ['IdentifierType', ['int']]]],
803 ['Decl', 'name',
804 ['PtrDecl',
805 ['TypeDecl',
806 ['IdentifierType', ['char']]]]]]]],
807 ['Decl', 'f',
808 ['TypeDecl',
809 ['IdentifierType', ['float']]]]]]]])
810
811 # ISO/IEC 9899:201x Commitee Draft 2010-11-16, N1539
812 # section 6.7.2.1, par. 19, example 1
813 s3 = """
814 struct v {
815 union {
816 struct { int i, j; };
817 struct { long k, l; } w;
818 };
819 int m;
820 } v1;
821 """
822
823 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
824 ['Decl', 'v1',
825 ['TypeDecl',
826 ['Struct', 'v',
827 [['Decl', None,
828 ['Union', None,
829 [['Decl', None,
830 ['Struct', None,
831 [['Decl', 'i',
832 ['TypeDecl',
833 ['IdentifierType', ['int']]]],
834 ['Decl', 'j',
835 ['TypeDecl',
836 ['IdentifierType', ['int']]]]]]],
837 ['Decl', 'w',
838 ['TypeDecl',
839 ['Struct', None,
840 [['Decl', 'k',
841 ['TypeDecl',
842 ['IdentifierType', ['long']]]],
843 ['Decl', 'l',
844 ['TypeDecl',
845 ['IdentifierType', ['long']]]]]]]]]]],
846 ['Decl', 'm',
847 ['TypeDecl',
848 ['IdentifierType', ['int']]]]]]]])
849
eli.benderskydce29a02011-02-10 07:55:00 +0200850 s4 = """
851 struct v {
852 int i;
853 float;
854 } v2;"""
eli.bendersky6b011792011-06-22 17:50:56 +0300855 # just make sure this doesn't raise ParseError
856 self.parse(s4)
eli.benderskydce29a02011-02-10 07:55:00 +0200857
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400858 def test_struct_members_namespace(self):
Eli Bendersky4d969b32013-07-13 06:07:07 -0700859 """ Tests that structure/union member names reside in a separate
860 namespace and can be named after existing types.
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400861 """
862 s1 = """
863 typedef int Name;
864 typedef Name NameArray[10];
865
866 struct {
867 Name Name;
868 Name NameArray[3];
869 } sye;
870
871 void main(void)
872 {
873 sye.Name = 1;
874 }
875 """
876
877 s1_ast = self.parse(s1)
878 self.assertEqual(expand_decl(s1_ast.ext[2]),
879 ['Decl', 'sye',
880 ['TypeDecl', ['Struct', None,
881 [ ['Decl', 'Name',
882 ['TypeDecl',
883 ['IdentifierType', ['Name']]]],
884 ['Decl', 'NameArray',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800885 ['ArrayDecl', '3', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400886 ['TypeDecl', ['IdentifierType', ['Name']]]]]]]]])
887 self.assertEqual(s1_ast.ext[3].body.block_items[0].lvalue.field.name, 'Name')
888
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200889 def test_struct_bitfields(self):
eli.bendersky38ed9a92010-10-09 09:29:59 +0200890 # a struct with two bitfields, one unnamed
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200891 s1 = """
892 struct {
893 int k:6;
894 int :2;
895 } joe;
896 """
897
898 parsed_struct = self.parse(s1).ext[0]
899
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800900 # We can see here the name of the decl for the unnamed bitfield is
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200901 # None, but expand_decl doesn't show bitfield widths
902 # ...
903 self.assertEqual(expand_decl(parsed_struct),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800904 ['Decl', 'joe',
905 ['TypeDecl', ['Struct', None,
906 [ ['Decl', 'k',
907 ['TypeDecl',
908 ['IdentifierType', ['int']]]],
909 ['Decl', None,
910 ['TypeDecl',
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200911 ['IdentifierType', ['int']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800912
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200913 # ...
914 # so we test them manually
915 self.assertEqual(parsed_struct.type.type.decls[0].bitsize.value, '6')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800916 self.assertEqual(parsed_struct.type.type.decls[1].bitsize.value, '2')
917
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300918 def test_tags_namespace(self):
919 """ Tests that the tags of structs/unions/enums reside in a separate namespace and
920 can be named after existing types.
921 """
922 s1 = """
923 typedef int tagEntry;
924
925 struct tagEntry
926 {
927 char* key;
928 char* value;
929 } Entry;
930 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800931
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300932 s1_ast = self.parse(s1)
933 self.assertEqual(expand_decl(s1_ast.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800934 ['Decl', 'Entry',
935 ['TypeDecl', ['Struct', 'tagEntry',
936 [['Decl', 'key',
937 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
938 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300939 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800940
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300941 s2 = """
942 struct tagEntry;
943
944 typedef struct tagEntry tagEntry;
945
946 struct tagEntry
947 {
948 char* key;
949 char* value;
950 } Entry;
951 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800952
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300953 s2_ast = self.parse(s2)
954 self.assertEqual(expand_decl(s2_ast.ext[2]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800955 ['Decl', 'Entry',
956 ['TypeDecl', ['Struct', 'tagEntry',
957 [['Decl', 'key',
958 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
959 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300960 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800961
962 s3 = """
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300963 typedef int mytag;
964
965 enum mytag {ABC, CDE};
966 enum mytag joe;
967 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800968
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300969 s3_type = self.parse(s3).ext[1].type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800970
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300971 self.assertTrue(isinstance(s3_type, Enum))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800972 self.assertEqual(s3_type.name, 'mytag')
973
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300974 def test_multi_decls(self):
975 d1 = 'int a, b;'
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800976
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300977 self.assertEqual(self.get_decl(d1, 0),
978 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
979 self.assertEqual(self.get_decl(d1, 1),
980 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['int']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800981
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300982 d2 = 'char* p, notp, ar[4];'
983 self.assertEqual(self.get_decl(d2, 0),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800984 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300985 ['PtrDecl',
986 ['TypeDecl', ['IdentifierType', ['char']]]]])
987 self.assertEqual(self.get_decl(d2, 1),
988 ['Decl', 'notp', ['TypeDecl', ['IdentifierType', ['char']]]])
989 self.assertEqual(self.get_decl(d2, 2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800990 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800991 ['ArrayDecl', '4', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300992 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800993
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300994 def test_invalid_multiple_types_error(self):
995 bad = [
996 'int enum {ab, cd} fubr;',
997 'enum kid char brbr;']
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800998
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300999 for b in bad:
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001000 self.assertRaises(ParseError, self.parse, b)
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001001
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001002 def test_duplicate_typedef(self):
1003 """ Tests that redeclarations of existing types are parsed correctly.
1004 This is non-standard, but allowed by many compilers.
1005 """
1006 d1 = '''
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001007 typedef int numbertype;
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001008 typedef int numbertype;
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001009 '''
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001010
1011 self.assertEqual(self.get_decl(d1, 0),
1012 ['Typedef', 'numbertype',
1013 ['TypeDecl', ['IdentifierType', ['int']]]])
1014 self.assertEqual(self.get_decl(d1, 1),
1015 ['Typedef', 'numbertype',
1016 ['TypeDecl', ['IdentifierType', ['int']]]])
1017
1018 d2 = '''
1019 typedef int (*funcptr)(int x);
1020 typedef int (*funcptr)(int x);
1021 '''
1022 self.assertEqual(self.get_decl(d2, 0),
1023 ['Typedef', 'funcptr',
1024 ['PtrDecl', ['FuncDecl',
1025 [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]],
1026 ['TypeDecl', ['IdentifierType', ['int']]]]]])
1027 self.assertEqual(self.get_decl(d2, 1),
1028 ['Typedef', 'funcptr',
1029 ['PtrDecl', ['FuncDecl',
1030 [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]],
1031 ['TypeDecl', ['IdentifierType', ['int']]]]]])
1032
1033 d3 = '''
1034 typedef int numberarray[5];
1035 typedef int numberarray[5];
1036 '''
1037 self.assertEqual(self.get_decl(d3, 0),
1038 ['Typedef', 'numberarray',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001039 ['ArrayDecl', '5', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001040 ['TypeDecl', ['IdentifierType', ['int']]]]])
1041 self.assertEqual(self.get_decl(d3, 1),
1042 ['Typedef', 'numberarray',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001043 ['ArrayDecl', '5', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001044 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001045
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001046 def test_decl_inits(self):
1047 d1 = 'int a = 16;'
eli.benderskyf890a862010-10-30 12:13:23 +02001048 #~ self.parse(d1).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001049 self.assertEqual(self.get_decl(d1),
1050 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
1051 self.assertEqual(self.get_decl_init(d1),
1052 ['Constant', 'int', '16'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001053
Eli Bendersky3b1b08d2012-06-15 12:37:54 +03001054 d1_1 = 'float f = 0xEF.56p1;'
1055 self.assertEqual(self.get_decl_init(d1_1),
1056 ['Constant', 'float', '0xEF.56p1'])
1057
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001058 d2 = 'long ar[] = {7, 8, 9};'
eli.benderskyf890a862010-10-30 12:13:23 +02001059 #~ self.parse(d2).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001060 self.assertEqual(self.get_decl(d2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001061 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001062 ['ArrayDecl', '', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001063 ['TypeDecl', ['IdentifierType', ['long']]]]])
1064 self.assertEqual(self.get_decl_init(d2),
1065 [ ['Constant', 'int', '7'],
1066 ['Constant', 'int', '8'],
eli.benderskyf890a862010-10-30 12:13:23 +02001067 ['Constant', 'int', '9']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001068
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001069 d3 = 'char p = j;'
1070 self.assertEqual(self.get_decl(d3),
1071 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['char']]]])
1072 self.assertEqual(self.get_decl_init(d3),
1073 ['ID', 'j'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001074
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001075 d4 = "char x = 'c', *p = {0, 1, 2, {4, 5}, 6};"
1076 self.assertEqual(self.get_decl(d4, 0),
1077 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['char']]]])
1078 self.assertEqual(self.get_decl_init(d4, 0),
1079 ['Constant', 'char', "'c'"])
1080 self.assertEqual(self.get_decl(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001081 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001082 ['PtrDecl',
1083 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001084
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001085 self.assertEqual(self.get_decl_init(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001086 [ ['Constant', 'int', '0'],
1087 ['Constant', 'int', '1'],
1088 ['Constant', 'int', '2'],
1089 [['Constant', 'int', '4'],
1090 ['Constant', 'int', '5']],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001091 ['Constant', 'int', '6']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001092
eli.benderskyf890a862010-10-30 12:13:23 +02001093 def test_decl_named_inits(self):
1094 d1 = 'int a = {.k = 16};'
1095 self.assertEqual(self.get_decl_init(d1),
1096 [( [['ID', 'k']],
1097 ['Constant', 'int', '16'])])
1098
1099 d2 = 'int a = { [0].a = {1}, [1].a[0] = 2 };'
1100 self.assertEqual(self.get_decl_init(d2),
1101 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001102 ([['Constant', 'int', '0'], ['ID', 'a']],
1103 [['Constant', 'int', '1']]),
1104 ([['Constant', 'int', '1'], ['ID', 'a'], ['Constant', 'int', '0']],
eli.benderskyf890a862010-10-30 12:13:23 +02001105 ['Constant', 'int', '2'])])
1106
1107 d3 = 'int a = { .a = 1, .c = 3, 4, .b = 5};'
1108 self.assertEqual(self.get_decl_init(d3),
1109 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001110 ([['ID', 'a']], ['Constant', 'int', '1']),
1111 ([['ID', 'c']], ['Constant', 'int', '3']),
1112 ['Constant', 'int', '4'],
eli.benderskyf890a862010-10-30 12:13:23 +02001113 ([['ID', 'b']], ['Constant', 'int', '5'])])
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001114
1115 def test_function_definitions(self):
1116 def parse_fdef(str):
1117 return self.parse(str).ext[0]
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001118
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001119 def fdef_decl(fdef):
1120 return expand_decl(fdef.decl)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001121
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001122 f1 = parse_fdef('''
1123 int factorial(int p)
1124 {
1125 return 3;
1126 }
1127 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001128
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001129 self.assertEqual(fdef_decl(f1),
1130 ['Decl', 'factorial',
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001131 ['FuncDecl',
1132 [['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001133 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001134
eli.benderskyef29ff92010-10-29 16:25:43 +02001135 self.assertEqual(type(f1.body.block_items[0]), Return)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001136
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001137 f2 = parse_fdef('''
1138 char* zzz(int p, char* c)
1139 {
1140 int a;
1141 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001142
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001143 a = b + 2;
1144 return 3;
1145 }
1146 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001147
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001148 self.assertEqual(fdef_decl(f2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001149 ['Decl', 'zzz',
1150 ['FuncDecl',
1151 [ ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]],
1152 ['Decl', 'c', ['PtrDecl',
1153 ['TypeDecl', ['IdentifierType', ['char']]]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001154 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001155
1156 self.assertEqual(list(map(type, f2.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001157 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001158
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001159 f3 = parse_fdef('''
1160 char* zzz(p, c)
1161 long p, *c;
1162 {
1163 int a;
1164 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001165
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001166 a = b + 2;
1167 return 3;
1168 }
1169 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001170
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001171 self.assertEqual(fdef_decl(f3),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001172 ['Decl', 'zzz',
1173 ['FuncDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001174 [ ['ID', 'p'],
1175 ['ID', 'c']],
1176 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001177
1178 self.assertEqual(list(map(type, f3.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001179 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001180
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001181 self.assertEqual(expand_decl(f3.param_decls[0]),
1182 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['long']]]])
1183 self.assertEqual(expand_decl(f3.param_decls[1]),
1184 ['Decl', 'c', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['long']]]]])
1185
Sye van der Veen51a46ec2013-06-10 12:56:15 -04001186 # function return values and parameters may not have type information
1187 f4 = parse_fdef('''
1188 que(p)
1189 {
1190 return 3;
1191 }
1192 ''')
1193
1194 self.assertEqual(fdef_decl(f4),
1195 ['Decl', 'que',
1196 ['FuncDecl',
1197 [['ID', 'p']],
1198 ['TypeDecl', ['IdentifierType', ['int']]]]])
1199
eli.bendersky71540662010-07-03 12:58:52 +02001200 def test_unified_string_literals(self):
1201 # simple string, for reference
1202 d1 = self.get_decl_init('char* s = "hello";')
1203 self.assertEqual(d1, ['Constant', 'string', '"hello"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001204
eli.bendersky71540662010-07-03 12:58:52 +02001205 d2 = self.get_decl_init('char* s = "hello" " world";')
1206 self.assertEqual(d2, ['Constant', 'string', '"hello world"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001207
eli.bendersky71540662010-07-03 12:58:52 +02001208 # the test case from issue 6
1209 d3 = self.parse(r'''
1210 int main() {
1211 fprintf(stderr,
1212 "Wrong Params?\n"
1213 "Usage:\n"
1214 "%s <binary_file_path>\n",
1215 argv[0]
1216 );
1217 }
1218 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001219
eli.bendersky71540662010-07-03 12:58:52 +02001220 self.assertEqual(
eli.benderskyef29ff92010-10-29 16:25:43 +02001221 d3.ext[0].body.block_items[0].args.exprs[1].value,
eli.bendersky71540662010-07-03 12:58:52 +02001222 r'"Wrong Params?\nUsage:\n%s <binary_file_path>\n"')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001223
eli.bendersky4a89f112010-07-05 06:02:03 +02001224 d4 = self.get_decl_init('char* s = "" "foobar";')
1225 self.assertEqual(d4, ['Constant', 'string', '"foobar"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001226
eli.bendersky4a89f112010-07-05 06:02:03 +02001227 d5 = self.get_decl_init(r'char* s = "foo\"" "bar";')
1228 self.assertEqual(d5, ['Constant', 'string', r'"foo\"bar"'])
eli.bendersky71540662010-07-03 12:58:52 +02001229
Eli Benderskyc9f1a382014-03-15 14:12:00 -07001230 def test_unified_wstring_literals(self):
1231 d1 = self.get_decl_init('char* s = L"hello" L"world";')
1232 self.assertEqual(d1, ['Constant', 'string', 'L"helloworld"'])
1233
1234 d2 = self.get_decl_init('char* s = L"hello " L"world" L" and I";')
1235 self.assertEqual(d2, ['Constant', 'string', 'L"hello world and I"'])
1236
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001237 def test_inline_specifier(self):
eli.bendersky79d5cf62010-10-29 13:33:52 +02001238 ps2 = self.parse('static inline void inlinefoo(void);')
1239 self.assertEqual(ps2.ext[0].funcspec, ['inline'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001240
eli.bendersky2e907fa2010-10-29 15:51:07 +02001241 # variable length array
1242 def test_vla(self):
1243 ps2 = self.parse(r'''
1244 int main() {
1245 int size;
1246 int var[size = 5];
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001247
eli.bendersky2e907fa2010-10-29 15:51:07 +02001248 int var2[*];
1249 }
1250 ''')
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001251 self.assertTrue(isinstance(ps2.ext[0].body.block_items[1].type.dim, Assignment))
1252 self.assertTrue(isinstance(ps2.ext[0].body.block_items[2].type.dim, ID))
eli.bendersky79d5cf62010-10-29 13:33:52 +02001253
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001254
eli.bendersky85d2e732011-05-20 19:47:26 +03001255class TestCParser_whole_code(TestCParser_base):
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001256 """ Testing of parsing whole chunks of code.
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001257
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001258 Since I don't want to rely on the structure of ASTs too
1259 much, most of these tests are implemented with visitors.
1260 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001261 # A simple helper visitor that lists the values of all the
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001262 # Constant nodes it sees.
1263 #
1264 class ConstantVisitor(NodeVisitor):
1265 def __init__(self):
1266 self.values = []
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001267
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001268 def visit_Constant(self, node):
1269 self.values.append(node.value)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001270
1271 # This visitor counts the amount of references to the ID
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001272 # with the name provided to it in the constructor.
1273 #
1274 class IDNameCounter(NodeVisitor):
1275 def __init__(self, name):
1276 self.name = name
1277 self.nrefs = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001278
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001279 def visit_ID(self, node):
1280 if node.name == self.name:
1281 self.nrefs += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001282
1283 # Counts the amount of nodes of a given class
1284 #
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001285 class NodeKlassCounter(NodeVisitor):
1286 def __init__(self, node_klass):
1287 self.klass = node_klass
1288 self.n = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001289
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001290 def generic_visit(self, node):
1291 if node.__class__ == self.klass:
1292 self.n += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001293
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001294 NodeVisitor.generic_visit(self, node)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001295
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001296 def assert_all_Constants(self, code, constants):
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001297 """ Asserts that the list of all Constant values (by
1298 'preorder' appearance) in the chunk of code is as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001299 given.
1300 """
eli.benderskyed890492010-06-25 08:25:55 +03001301 if isinstance(code, str):
1302 parsed = self.parse(code)
1303 else:
1304 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001305
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001306 cv = self.ConstantVisitor()
1307 cv.visit(parsed)
1308 self.assertEqual(cv.values, constants)
1309
1310 def assert_num_ID_refs(self, code, name, num):
1311 """ Asserts the number of references to the ID with
1312 the given name.
1313 """
1314 if isinstance(code, str):
1315 parsed = self.parse(code)
1316 else:
1317 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001318
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001319 iv = self.IDNameCounter(name)
1320 iv.visit(parsed)
1321 self.assertEqual(iv.nrefs, num)
1322
1323 def assert_num_klass_nodes(self, code, klass, num):
1324 """ Asserts the amount of klass nodes in the code.
1325 """
1326 if isinstance(code, str):
1327 parsed = self.parse(code)
1328 else:
1329 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001330
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001331 cv = self.NodeKlassCounter(klass)
1332 cv.visit(parsed)
1333 self.assertEqual(cv.n, num)
1334
1335 def test_expressions(self):
1336 e1 = '''int k = (r + 10.0) >> 6 + 8 << (3 & 0x14);'''
1337 self.assert_all_Constants(e1, ['10.0', '6', '8', '3', '0x14'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001338
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001339 e2 = r'''char n = '\n', *prefix = "st_";'''
1340 self.assert_all_Constants(e2, [r"'\n'", '"st_"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001341
Eli Bendersky09e22a62013-07-02 06:00:36 -07001342 s1 = r'''int main() {
1343 int i = 5, j = 6, k = 1;
1344 if ((i=j && k == 1) || k > j)
1345 printf("Hello, world\n");
1346 return 0;
1347 }'''
1348 ps1 = self.parse(s1)
1349 self.assert_all_Constants(ps1,
1350 ['5', '6', '1', '1', '"Hello, world\\n"', '0'])
1351 self.assert_num_ID_refs(ps1, 'i', 1)
1352 self.assert_num_ID_refs(ps1, 'j', 2)
1353
1354
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001355 def test_statements(self):
1356 s1 = r'''
1357 void foo(){
1358 if (sp == 1)
1359 if (optind >= argc ||
1360 argv[optind][0] != '-' || argv[optind][1] == '\0')
1361 return -1;
1362 else if (strcmp(argv[optind], "--") == 0) {
1363 optind++;
1364 return -1;
1365 }
1366 }
1367 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001368
1369 self.assert_all_Constants(s1,
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001370 ['1', '0', r"'-'", '1', r"'\0'", '1', r'"--"', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001371
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001372 ps1 = self.parse(s1)
1373 self.assert_num_ID_refs(ps1, 'argv', 3)
1374 self.assert_num_ID_refs(ps1, 'optind', 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001375
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001376 self.assert_num_klass_nodes(ps1, If, 3)
1377 self.assert_num_klass_nodes(ps1, Return, 2)
1378 self.assert_num_klass_nodes(ps1, FuncCall, 1) # strcmp
1379 self.assert_num_klass_nodes(ps1, BinaryOp, 7)
1380
1381 # In the following code, Hash and Node were defined as
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001382 # int to pacify the parser that sees they're used as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001383 # types
1384 #
1385 s2 = r'''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001386 typedef int Hash, Node;
1387
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001388 void HashDestroy(Hash* hash)
1389 {
1390 unsigned int i;
1391
1392 if (hash == NULL)
1393 return;
1394
1395 for (i = 0; i < hash->table_size; ++i)
1396 {
1397 Node* temp = hash->heads[i];
1398
1399 while (temp != NULL)
1400 {
1401 Node* temp2 = temp;
1402
1403 free(temp->entry->key);
1404 free(temp->entry->value);
1405 free(temp->entry);
1406
1407 temp = temp->next;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001408
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001409 free(temp2);
1410 }
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001411 }
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001412
1413 free(hash->heads);
1414 hash->heads = NULL;
1415
1416 free(hash);
1417 }
1418 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001419
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001420 ps2 = self.parse(s2)
1421 self.assert_num_klass_nodes(ps2, FuncCall, 6)
1422 self.assert_num_klass_nodes(ps2, FuncDef, 1)
1423 self.assert_num_klass_nodes(ps2, For, 1)
1424 self.assert_num_klass_nodes(ps2, While, 1)
1425 self.assert_num_klass_nodes(ps2, StructRef, 10)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001426
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001427 # declarations don't count
1428 self.assert_num_ID_refs(ps2, 'hash', 6)
1429 self.assert_num_ID_refs(ps2, 'i', 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001430
eli.benderskyed890492010-06-25 08:25:55 +03001431 s3 = r'''
1432 void x(void) {
1433 int a, b;
1434 if (a < b)
1435 do {
1436 a = 0;
1437 } while (0);
1438 else if (a == b) {
1439 a = 1;
1440 }
1441 }
1442 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001443
eli.benderskyed890492010-06-25 08:25:55 +03001444 ps3 = self.parse(s3)
1445 self.assert_num_klass_nodes(ps3, DoWhile, 1)
1446 self.assert_num_ID_refs(ps3, 'a', 4)
1447 self.assert_all_Constants(ps3, ['0', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001448
eli.bendersky91c0aa32011-10-16 05:50:43 +02001449 def test_empty_statement(self):
1450 s1 = r'''
1451 void foo(void){
1452 ;
1453 return;
1454 }
1455 '''
1456 ps1 = self.parse(s1)
1457 self.assert_num_klass_nodes(ps1, EmptyStatement, 1)
1458 self.assert_num_klass_nodes(ps1, Return, 1)
eli.bendersky145890d2010-10-29 12:02:32 +02001459
Ben5cd3fd62012-02-03 06:02:40 +02001460 def test_switch_statement(self):
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001461 def assert_case_node(node, const_value):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001462 self.assertTrue(isinstance(node, Case))
1463 self.assertTrue(isinstance(node.expr, Constant))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001464 self.assertEqual(node.expr.value, const_value)
1465
1466 def assert_default_node(node):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001467 self.assertTrue(isinstance(node, Default))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001468
Ben5cd3fd62012-02-03 06:02:40 +02001469 s1 = r'''
1470 int foo(void) {
1471 switch (myvar) {
1472 case 10:
1473 k = 10;
1474 p = k + 1;
1475 return 10;
1476 case 20:
1477 case 30:
1478 return 20;
1479 default:
1480 break;
1481 }
1482 return 0;
1483 }
1484 '''
1485 ps1 = self.parse(s1)
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001486 switch = ps1.ext[0].body.block_items[0]
1487
1488 block = switch.stmt.block_items
1489 assert_case_node(block[0], '10')
1490 self.assertEqual(len(block[0].stmts), 3)
1491 assert_case_node(block[1], '20')
1492 self.assertEqual(len(block[1].stmts), 0)
1493 assert_case_node(block[2], '30')
1494 self.assertEqual(len(block[2].stmts), 1)
1495 assert_default_node(block[3])
1496
1497 s2 = r'''
1498 int foo(void) {
1499 switch (myvar) {
1500 default:
1501 joe = moe;
1502 return 10;
1503 case 10:
1504 case 20:
1505 case 30:
1506 case 40:
1507 break;
1508 }
1509 return 0;
1510 }
1511 '''
1512 ps2 = self.parse(s2)
1513 switch = ps2.ext[0].body.block_items[0]
1514
1515 block = switch.stmt.block_items
1516 assert_default_node(block[0])
1517 self.assertEqual(len(block[0].stmts), 2)
1518 assert_case_node(block[1], '10')
1519 self.assertEqual(len(block[1].stmts), 0)
1520 assert_case_node(block[2], '20')
1521 self.assertEqual(len(block[1].stmts), 0)
1522 assert_case_node(block[3], '30')
1523 self.assertEqual(len(block[1].stmts), 0)
1524 assert_case_node(block[4], '40')
1525 self.assertEqual(len(block[4].stmts), 1)
Ben5cd3fd62012-02-03 06:02:40 +02001526
eli.bendersky145890d2010-10-29 12:02:32 +02001527 def test_for_statement(self):
1528 s2 = r'''
1529 void x(void)
1530 {
1531 int i;
1532 for (i = 0; i < 5; ++i) {
1533 x = 50;
1534 }
1535 }
1536 '''
1537 ps2 = self.parse(s2)
1538 self.assert_num_klass_nodes(ps2, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001539 # here there are 3 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001540 # a ref in the visitor
1541 #
1542 self.assert_num_ID_refs(ps2, 'i', 3)
Eli Bendersky4476d092012-12-25 14:07:57 -08001543
eli.bendersky145890d2010-10-29 12:02:32 +02001544 s3 = r'''
1545 void x(void)
1546 {
1547 for (int i = 0; i < 5; ++i) {
1548 x = 50;
1549 }
1550 }
1551 '''
1552 ps3 = self.parse(s3)
eli.bendersky145890d2010-10-29 12:02:32 +02001553 self.assert_num_klass_nodes(ps3, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001554 # here there are 2 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001555 # a ref in the visitor
1556 #
1557 self.assert_num_ID_refs(ps3, 'i', 2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001558
Eli Bendersky4476d092012-12-25 14:07:57 -08001559 s4 = r'''
1560 void x(void) {
1561 for (int i = 0;;)
1562 i;
1563 }
1564 '''
1565 ps4 = self.parse(s4)
1566 self.assert_num_ID_refs(ps4, 'i', 1)
1567
Eli Benderskyd0973782012-01-19 08:09:33 +02001568 def _open_c_file(self, name):
1569 """ Find a c file by name, taking into account the current dir can be
1570 in a couple of typical places
1571 """
Stefano Riveraebaf5922013-08-08 09:45:26 +02001572 testdir = os.path.dirname(__file__)
1573 name = os.path.join(testdir, 'c_files', name)
1574 assert os.path.exists(name)
1575 return open(name, 'rU')
Eli Benderskyd0973782012-01-19 08:09:33 +02001576
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001577 def test_whole_file(self):
1578 # See how pycparser handles a whole, real C file.
1579 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001580 with self._open_c_file('memmgr_with_h.c') as f:
1581 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001582 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001583
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001584 self.assert_num_klass_nodes(p, FuncDef, 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001585
1586 # each FuncDef also has a FuncDecl. 4 declarations
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001587 # + 5 definitions, overall 9
1588 self.assert_num_klass_nodes(p, FuncDecl, 9)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001589
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001590 self.assert_num_klass_nodes(p, Typedef, 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001591
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001592 self.assertEqual(p.ext[4].coord.line, 88)
1593 self.assertEqual(p.ext[4].coord.file, "./memmgr.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001594
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001595 self.assertEqual(p.ext[6].coord.line, 10)
1596 self.assertEqual(p.ext[6].coord.file, "memmgr.c")
1597
1598 def test_whole_file_with_stdio(self):
1599 # Parse a whole file with stdio.h included by cpp
1600 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001601 with self._open_c_file('cppd_with_stdio_h.c') as f:
1602 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001603 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001604
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001605 self.assertTrue(isinstance(p.ext[0], Typedef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001606 self.assertEqual(p.ext[0].coord.line, 213)
1607 self.assertEqual(p.ext[0].coord.file, "D:\eli\cpp_stuff\libc_include/stddef.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001608
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001609 self.assertTrue(isinstance(p.ext[-1], FuncDef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001610 self.assertEqual(p.ext[-1].coord.line, 15)
1611 self.assertEqual(p.ext[-1].coord.file, "example_c_file.c")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001612
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001613 self.assertTrue(isinstance(p.ext[-8], Typedef))
1614 self.assertTrue(isinstance(p.ext[-8].type, TypeDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001615 self.assertEqual(p.ext[-8].name, 'cookie_io_functions_t')
eli.bendersky85d2e732011-05-20 19:47:26 +03001616
1617
1618class TestCParser_typenames(TestCParser_base):
1619 """ Test issues related to the typedef-name problem.
1620 """
1621 def test_innerscope_typedef(self):
1622 # should fail since TT is not a type in bar
1623 s1 = r'''
1624 void foo() {
1625 typedef char TT;
1626 TT x;
1627 }
1628 void bar() {
1629 TT y;
1630 }
1631 '''
1632 self.assertRaises(ParseError, self.parse, s1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001633
eli.bendersky85d2e732011-05-20 19:47:26 +03001634 # should succeed since TT is not a type in bar
1635 s2 = r'''
1636 void foo() {
1637 typedef char TT;
1638 TT x;
1639 }
1640 void bar() {
1641 unsigned TT;
1642 }
1643 '''
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001644 self.assertTrue(isinstance(self.parse(s2), FileAST))
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001645
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001646 def test_innerscope_reuse_typedef_name(self):
1647 # identifiers can be reused in inner scopes; the original should be
1648 # restored at the end of the block
1649 s1 = r'''
1650 typedef char TT;
1651 void foo(void) {
1652 unsigned TT;
1653 TT = 10;
1654 }
1655 TT x = 5;
1656 '''
1657 s1_ast = self.parse(s1)
1658 self.assertEqual(expand_decl(s1_ast.ext[1].body.block_items[0]),
1659 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
Eli Bendersky3877c4c2013-07-13 06:54:04 -07001660 self.assertEqual(expand_decl(s1_ast.ext[2]),
1661 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['TT']]]])
eli.bendersky85d2e732011-05-20 19:47:26 +03001662
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001663 # this should be recognized even with an initializer
1664 s2 = r'''
1665 typedef char TT;
1666 void foo(void) {
1667 unsigned TT = 10;
1668 }
1669 '''
1670 s2_ast = self.parse(s2)
1671 self.assertEqual(expand_decl(s2_ast.ext[1].body.block_items[0]),
1672 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1673
1674 # before the second local variable, TT is a type; after, it's a
1675 # variable
1676 s3 = r'''
1677 typedef char TT;
1678 void foo(void) {
1679 TT tt = sizeof(TT);
1680 unsigned TT = 10;
1681 }
1682 '''
1683 s3_ast = self.parse(s3)
1684 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[0]),
1685 ['Decl', 'tt', ['TypeDecl', ['IdentifierType', ['TT']]]])
1686 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[1]),
1687 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1688
1689 # a variable and its type can even share the same name
1690 s4 = r'''
1691 typedef char TT;
1692 void foo(void) {
1693 TT TT = sizeof(TT);
1694 unsigned uu = TT * 2;
1695 }
1696 '''
1697 s4_ast = self.parse(s4)
1698 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[0]),
1699 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['TT']]]])
1700 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[1]),
1701 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1702
1703 # ensure an error is raised if a type, redeclared as a variable, is
1704 # used as a type
1705 s5 = r'''
1706 typedef char TT;
1707 void foo(void) {
1708 unsigned TT = 10;
1709 TT erroneous = 20;
1710 }
1711 '''
1712 self.assertRaises(ParseError, self.parse, s5)
1713
1714 def test_parameter_reuse_typedef_name(self):
1715 # identifiers can be reused as parameter names; parameter name scope
1716 # begins and ends with the function body; it's important that TT is
Eli Bendersky4d969b32013-07-13 06:07:07 -07001717 # used immediately before the LBRACE or after the RBRACE, to test
1718 # a corner case
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001719 s1 = r'''
1720 typedef char TT;
1721 void foo(unsigned TT, TT bar) {
1722 TT = 10;
1723 }
1724 TT x = 5;
1725 '''
1726 s1_ast = self.parse(s1)
1727 self.assertEqual(expand_decl(s1_ast.ext[1].decl),
1728 ['Decl', 'foo',
1729 ['FuncDecl',
1730 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
1731 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
1732 ['TypeDecl', ['IdentifierType', ['void']]]]])
1733
1734 # the scope of a parameter name in a function declaration ends at the
1735 # end of the declaration...so it is effectively never used; it's
1736 # important that TT is used immediately after the declaration, to
1737 # test a corner case
1738 s2 = r'''
1739 typedef char TT;
1740 void foo(unsigned TT, TT bar);
1741 TT x = 5;
1742 '''
1743 s2_ast = self.parse(s2)
1744 self.assertEqual(expand_decl(s2_ast.ext[1]),
1745 ['Decl', 'foo',
1746 ['FuncDecl',
1747 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
1748 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
1749 ['TypeDecl', ['IdentifierType', ['void']]]]])
1750
1751 # ensure an error is raised if a type, redeclared as a parameter, is
1752 # used as a type
1753 s3 = r'''
1754 typedef char TT;
1755 void foo(unsigned TT, TT bar) {
1756 TT erroneous = 20;
1757 }
1758 '''
1759 self.assertRaises(ParseError, self.parse, s3)
1760
1761 def test_nested_function_decls(self):
1762 # parameter names of nested function declarations must not escape into
1763 # the top-level function _definition's_ scope; the following must
1764 # succeed because TT is still a typedef inside foo's body
1765 s1 = r'''
1766 typedef char TT;
1767 void foo(unsigned bar(int TT)) {
1768 TT x = 10;
1769 }
1770 '''
1771 self.assertTrue(isinstance(self.parse(s1), FileAST))
1772
1773 def test_samescope_reuse_name(self):
1774 # a typedef name cannot be reused as an object name in the same scope
1775 s1 = r'''
1776 typedef char TT;
1777 char TT = 5;
1778 '''
1779 self.assertRaises(ParseError, self.parse, s1)
1780
1781 # ...and vice-versa
1782 s2 = r'''
1783 char TT = 5;
1784 typedef char TT;
1785 '''
1786 self.assertRaises(ParseError, self.parse, s2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001787
1788if __name__ == '__main__':
1789 #~ suite = unittest.TestLoader().loadTestsFromNames(
1790 #~ ['test_c_parser.TestCParser_fundamentals.test_typedef'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001791
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001792 #~ unittest.TextTestRunner(verbosity=2).run(suite)
1793 unittest.main()