blob: 61c36422b6326348b8415f7b5d3b96a29ba09fbe [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
Konstanty Bialkowski3bdbfdc2015-04-19 20:09:21 +10001058 d1_2 = 'int bitmask = 0b1001010;'
1059 self.assertEqual(self.get_decl_init(d1_2),
1060 ['Constant', 'int', '0b1001010'])
1061
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001062 d2 = 'long ar[] = {7, 8, 9};'
eli.benderskyf890a862010-10-30 12:13:23 +02001063 #~ self.parse(d2).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001064 self.assertEqual(self.get_decl(d2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001065 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001066 ['ArrayDecl', '', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001067 ['TypeDecl', ['IdentifierType', ['long']]]]])
1068 self.assertEqual(self.get_decl_init(d2),
1069 [ ['Constant', 'int', '7'],
1070 ['Constant', 'int', '8'],
eli.benderskyf890a862010-10-30 12:13:23 +02001071 ['Constant', 'int', '9']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001072
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001073 d3 = 'char p = j;'
1074 self.assertEqual(self.get_decl(d3),
1075 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['char']]]])
1076 self.assertEqual(self.get_decl_init(d3),
1077 ['ID', 'j'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001078
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001079 d4 = "char x = 'c', *p = {0, 1, 2, {4, 5}, 6};"
1080 self.assertEqual(self.get_decl(d4, 0),
1081 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['char']]]])
1082 self.assertEqual(self.get_decl_init(d4, 0),
1083 ['Constant', 'char', "'c'"])
1084 self.assertEqual(self.get_decl(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001085 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001086 ['PtrDecl',
1087 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001088
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001089 self.assertEqual(self.get_decl_init(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001090 [ ['Constant', 'int', '0'],
1091 ['Constant', 'int', '1'],
1092 ['Constant', 'int', '2'],
1093 [['Constant', 'int', '4'],
1094 ['Constant', 'int', '5']],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001095 ['Constant', 'int', '6']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001096
eli.benderskyf890a862010-10-30 12:13:23 +02001097 def test_decl_named_inits(self):
1098 d1 = 'int a = {.k = 16};'
1099 self.assertEqual(self.get_decl_init(d1),
1100 [( [['ID', 'k']],
1101 ['Constant', 'int', '16'])])
1102
1103 d2 = 'int a = { [0].a = {1}, [1].a[0] = 2 };'
1104 self.assertEqual(self.get_decl_init(d2),
1105 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001106 ([['Constant', 'int', '0'], ['ID', 'a']],
1107 [['Constant', 'int', '1']]),
1108 ([['Constant', 'int', '1'], ['ID', 'a'], ['Constant', 'int', '0']],
eli.benderskyf890a862010-10-30 12:13:23 +02001109 ['Constant', 'int', '2'])])
1110
1111 d3 = 'int a = { .a = 1, .c = 3, 4, .b = 5};'
1112 self.assertEqual(self.get_decl_init(d3),
1113 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001114 ([['ID', 'a']], ['Constant', 'int', '1']),
1115 ([['ID', 'c']], ['Constant', 'int', '3']),
1116 ['Constant', 'int', '4'],
eli.benderskyf890a862010-10-30 12:13:23 +02001117 ([['ID', 'b']], ['Constant', 'int', '5'])])
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001118
1119 def test_function_definitions(self):
1120 def parse_fdef(str):
1121 return self.parse(str).ext[0]
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001122
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001123 def fdef_decl(fdef):
1124 return expand_decl(fdef.decl)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001125
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001126 f1 = parse_fdef('''
1127 int factorial(int p)
1128 {
1129 return 3;
1130 }
1131 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001132
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001133 self.assertEqual(fdef_decl(f1),
1134 ['Decl', 'factorial',
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001135 ['FuncDecl',
1136 [['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001137 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001138
eli.benderskyef29ff92010-10-29 16:25:43 +02001139 self.assertEqual(type(f1.body.block_items[0]), Return)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001140
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001141 f2 = parse_fdef('''
1142 char* zzz(int p, char* c)
1143 {
1144 int a;
1145 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001146
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001147 a = b + 2;
1148 return 3;
1149 }
1150 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001151
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001152 self.assertEqual(fdef_decl(f2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001153 ['Decl', 'zzz',
1154 ['FuncDecl',
1155 [ ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]],
1156 ['Decl', 'c', ['PtrDecl',
1157 ['TypeDecl', ['IdentifierType', ['char']]]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001158 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001159
1160 self.assertEqual(list(map(type, f2.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001161 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001162
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001163 f3 = parse_fdef('''
1164 char* zzz(p, c)
1165 long p, *c;
1166 {
1167 int a;
1168 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001169
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001170 a = b + 2;
1171 return 3;
1172 }
1173 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001174
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001175 self.assertEqual(fdef_decl(f3),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001176 ['Decl', 'zzz',
1177 ['FuncDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001178 [ ['ID', 'p'],
1179 ['ID', 'c']],
1180 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001181
1182 self.assertEqual(list(map(type, f3.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001183 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001184
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001185 self.assertEqual(expand_decl(f3.param_decls[0]),
1186 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['long']]]])
1187 self.assertEqual(expand_decl(f3.param_decls[1]),
1188 ['Decl', 'c', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['long']]]]])
1189
Sye van der Veen51a46ec2013-06-10 12:56:15 -04001190 # function return values and parameters may not have type information
1191 f4 = parse_fdef('''
1192 que(p)
1193 {
1194 return 3;
1195 }
1196 ''')
1197
1198 self.assertEqual(fdef_decl(f4),
1199 ['Decl', 'que',
1200 ['FuncDecl',
1201 [['ID', 'p']],
1202 ['TypeDecl', ['IdentifierType', ['int']]]]])
1203
eli.bendersky71540662010-07-03 12:58:52 +02001204 def test_unified_string_literals(self):
1205 # simple string, for reference
1206 d1 = self.get_decl_init('char* s = "hello";')
1207 self.assertEqual(d1, ['Constant', 'string', '"hello"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001208
eli.bendersky71540662010-07-03 12:58:52 +02001209 d2 = self.get_decl_init('char* s = "hello" " world";')
1210 self.assertEqual(d2, ['Constant', 'string', '"hello world"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001211
eli.bendersky71540662010-07-03 12:58:52 +02001212 # the test case from issue 6
1213 d3 = self.parse(r'''
1214 int main() {
1215 fprintf(stderr,
1216 "Wrong Params?\n"
1217 "Usage:\n"
1218 "%s <binary_file_path>\n",
1219 argv[0]
1220 );
1221 }
1222 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001223
eli.bendersky71540662010-07-03 12:58:52 +02001224 self.assertEqual(
eli.benderskyef29ff92010-10-29 16:25:43 +02001225 d3.ext[0].body.block_items[0].args.exprs[1].value,
eli.bendersky71540662010-07-03 12:58:52 +02001226 r'"Wrong Params?\nUsage:\n%s <binary_file_path>\n"')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001227
eli.bendersky4a89f112010-07-05 06:02:03 +02001228 d4 = self.get_decl_init('char* s = "" "foobar";')
1229 self.assertEqual(d4, ['Constant', 'string', '"foobar"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001230
eli.bendersky4a89f112010-07-05 06:02:03 +02001231 d5 = self.get_decl_init(r'char* s = "foo\"" "bar";')
1232 self.assertEqual(d5, ['Constant', 'string', r'"foo\"bar"'])
eli.bendersky71540662010-07-03 12:58:52 +02001233
Eli Benderskyc9f1a382014-03-15 14:12:00 -07001234 def test_unified_wstring_literals(self):
1235 d1 = self.get_decl_init('char* s = L"hello" L"world";')
1236 self.assertEqual(d1, ['Constant', 'string', 'L"helloworld"'])
1237
1238 d2 = self.get_decl_init('char* s = L"hello " L"world" L" and I";')
1239 self.assertEqual(d2, ['Constant', 'string', 'L"hello world and I"'])
1240
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001241 def test_inline_specifier(self):
eli.bendersky79d5cf62010-10-29 13:33:52 +02001242 ps2 = self.parse('static inline void inlinefoo(void);')
1243 self.assertEqual(ps2.ext[0].funcspec, ['inline'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001244
eli.bendersky2e907fa2010-10-29 15:51:07 +02001245 # variable length array
1246 def test_vla(self):
1247 ps2 = self.parse(r'''
1248 int main() {
1249 int size;
1250 int var[size = 5];
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001251
eli.bendersky2e907fa2010-10-29 15:51:07 +02001252 int var2[*];
1253 }
1254 ''')
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001255 self.assertTrue(isinstance(ps2.ext[0].body.block_items[1].type.dim, Assignment))
1256 self.assertTrue(isinstance(ps2.ext[0].body.block_items[2].type.dim, ID))
eli.bendersky79d5cf62010-10-29 13:33:52 +02001257
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001258
eli.bendersky85d2e732011-05-20 19:47:26 +03001259class TestCParser_whole_code(TestCParser_base):
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001260 """ Testing of parsing whole chunks of code.
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001261
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001262 Since I don't want to rely on the structure of ASTs too
1263 much, most of these tests are implemented with visitors.
1264 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001265 # A simple helper visitor that lists the values of all the
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001266 # Constant nodes it sees.
1267 #
1268 class ConstantVisitor(NodeVisitor):
1269 def __init__(self):
1270 self.values = []
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001271
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001272 def visit_Constant(self, node):
1273 self.values.append(node.value)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001274
1275 # This visitor counts the amount of references to the ID
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001276 # with the name provided to it in the constructor.
1277 #
1278 class IDNameCounter(NodeVisitor):
1279 def __init__(self, name):
1280 self.name = name
1281 self.nrefs = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001282
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001283 def visit_ID(self, node):
1284 if node.name == self.name:
1285 self.nrefs += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001286
1287 # Counts the amount of nodes of a given class
1288 #
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001289 class NodeKlassCounter(NodeVisitor):
1290 def __init__(self, node_klass):
1291 self.klass = node_klass
1292 self.n = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001293
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001294 def generic_visit(self, node):
1295 if node.__class__ == self.klass:
1296 self.n += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001297
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001298 NodeVisitor.generic_visit(self, node)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001299
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001300 def assert_all_Constants(self, code, constants):
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001301 """ Asserts that the list of all Constant values (by
1302 'preorder' appearance) in the chunk of code is as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001303 given.
1304 """
eli.benderskyed890492010-06-25 08:25:55 +03001305 if isinstance(code, str):
1306 parsed = self.parse(code)
1307 else:
1308 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001309
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001310 cv = self.ConstantVisitor()
1311 cv.visit(parsed)
1312 self.assertEqual(cv.values, constants)
1313
1314 def assert_num_ID_refs(self, code, name, num):
1315 """ Asserts the number of references to the ID with
1316 the given name.
1317 """
1318 if isinstance(code, str):
1319 parsed = self.parse(code)
1320 else:
1321 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001322
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001323 iv = self.IDNameCounter(name)
1324 iv.visit(parsed)
1325 self.assertEqual(iv.nrefs, num)
1326
1327 def assert_num_klass_nodes(self, code, klass, num):
1328 """ Asserts the amount of klass nodes in the code.
1329 """
1330 if isinstance(code, str):
1331 parsed = self.parse(code)
1332 else:
1333 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001334
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001335 cv = self.NodeKlassCounter(klass)
1336 cv.visit(parsed)
1337 self.assertEqual(cv.n, num)
1338
1339 def test_expressions(self):
1340 e1 = '''int k = (r + 10.0) >> 6 + 8 << (3 & 0x14);'''
1341 self.assert_all_Constants(e1, ['10.0', '6', '8', '3', '0x14'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001342
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001343 e2 = r'''char n = '\n', *prefix = "st_";'''
1344 self.assert_all_Constants(e2, [r"'\n'", '"st_"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001345
Eli Bendersky09e22a62013-07-02 06:00:36 -07001346 s1 = r'''int main() {
1347 int i = 5, j = 6, k = 1;
1348 if ((i=j && k == 1) || k > j)
1349 printf("Hello, world\n");
1350 return 0;
1351 }'''
1352 ps1 = self.parse(s1)
1353 self.assert_all_Constants(ps1,
1354 ['5', '6', '1', '1', '"Hello, world\\n"', '0'])
1355 self.assert_num_ID_refs(ps1, 'i', 1)
1356 self.assert_num_ID_refs(ps1, 'j', 2)
1357
1358
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001359 def test_statements(self):
1360 s1 = r'''
1361 void foo(){
1362 if (sp == 1)
1363 if (optind >= argc ||
1364 argv[optind][0] != '-' || argv[optind][1] == '\0')
1365 return -1;
1366 else if (strcmp(argv[optind], "--") == 0) {
1367 optind++;
1368 return -1;
1369 }
1370 }
1371 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001372
1373 self.assert_all_Constants(s1,
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001374 ['1', '0', r"'-'", '1', r"'\0'", '1', r'"--"', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001375
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001376 ps1 = self.parse(s1)
1377 self.assert_num_ID_refs(ps1, 'argv', 3)
1378 self.assert_num_ID_refs(ps1, 'optind', 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001379
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001380 self.assert_num_klass_nodes(ps1, If, 3)
1381 self.assert_num_klass_nodes(ps1, Return, 2)
1382 self.assert_num_klass_nodes(ps1, FuncCall, 1) # strcmp
1383 self.assert_num_klass_nodes(ps1, BinaryOp, 7)
1384
1385 # In the following code, Hash and Node were defined as
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001386 # int to pacify the parser that sees they're used as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001387 # types
1388 #
1389 s2 = r'''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001390 typedef int Hash, Node;
1391
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001392 void HashDestroy(Hash* hash)
1393 {
1394 unsigned int i;
1395
1396 if (hash == NULL)
1397 return;
1398
1399 for (i = 0; i < hash->table_size; ++i)
1400 {
1401 Node* temp = hash->heads[i];
1402
1403 while (temp != NULL)
1404 {
1405 Node* temp2 = temp;
1406
1407 free(temp->entry->key);
1408 free(temp->entry->value);
1409 free(temp->entry);
1410
1411 temp = temp->next;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001412
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001413 free(temp2);
1414 }
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001415 }
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001416
1417 free(hash->heads);
1418 hash->heads = NULL;
1419
1420 free(hash);
1421 }
1422 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001423
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001424 ps2 = self.parse(s2)
1425 self.assert_num_klass_nodes(ps2, FuncCall, 6)
1426 self.assert_num_klass_nodes(ps2, FuncDef, 1)
1427 self.assert_num_klass_nodes(ps2, For, 1)
1428 self.assert_num_klass_nodes(ps2, While, 1)
1429 self.assert_num_klass_nodes(ps2, StructRef, 10)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001430
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001431 # declarations don't count
1432 self.assert_num_ID_refs(ps2, 'hash', 6)
1433 self.assert_num_ID_refs(ps2, 'i', 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001434
eli.benderskyed890492010-06-25 08:25:55 +03001435 s3 = r'''
1436 void x(void) {
1437 int a, b;
1438 if (a < b)
1439 do {
1440 a = 0;
1441 } while (0);
1442 else if (a == b) {
1443 a = 1;
1444 }
1445 }
1446 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001447
eli.benderskyed890492010-06-25 08:25:55 +03001448 ps3 = self.parse(s3)
1449 self.assert_num_klass_nodes(ps3, DoWhile, 1)
1450 self.assert_num_ID_refs(ps3, 'a', 4)
1451 self.assert_all_Constants(ps3, ['0', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001452
eli.bendersky91c0aa32011-10-16 05:50:43 +02001453 def test_empty_statement(self):
1454 s1 = r'''
1455 void foo(void){
1456 ;
1457 return;
1458 }
1459 '''
1460 ps1 = self.parse(s1)
1461 self.assert_num_klass_nodes(ps1, EmptyStatement, 1)
1462 self.assert_num_klass_nodes(ps1, Return, 1)
eli.bendersky145890d2010-10-29 12:02:32 +02001463
Ben5cd3fd62012-02-03 06:02:40 +02001464 def test_switch_statement(self):
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001465 def assert_case_node(node, const_value):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001466 self.assertTrue(isinstance(node, Case))
1467 self.assertTrue(isinstance(node.expr, Constant))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001468 self.assertEqual(node.expr.value, const_value)
1469
1470 def assert_default_node(node):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001471 self.assertTrue(isinstance(node, Default))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001472
Ben5cd3fd62012-02-03 06:02:40 +02001473 s1 = r'''
1474 int foo(void) {
1475 switch (myvar) {
1476 case 10:
1477 k = 10;
1478 p = k + 1;
1479 return 10;
1480 case 20:
1481 case 30:
1482 return 20;
1483 default:
1484 break;
1485 }
1486 return 0;
1487 }
1488 '''
1489 ps1 = self.parse(s1)
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001490 switch = ps1.ext[0].body.block_items[0]
1491
1492 block = switch.stmt.block_items
1493 assert_case_node(block[0], '10')
1494 self.assertEqual(len(block[0].stmts), 3)
1495 assert_case_node(block[1], '20')
1496 self.assertEqual(len(block[1].stmts), 0)
1497 assert_case_node(block[2], '30')
1498 self.assertEqual(len(block[2].stmts), 1)
1499 assert_default_node(block[3])
1500
1501 s2 = r'''
1502 int foo(void) {
1503 switch (myvar) {
1504 default:
1505 joe = moe;
1506 return 10;
1507 case 10:
1508 case 20:
1509 case 30:
1510 case 40:
1511 break;
1512 }
1513 return 0;
1514 }
1515 '''
1516 ps2 = self.parse(s2)
1517 switch = ps2.ext[0].body.block_items[0]
1518
1519 block = switch.stmt.block_items
1520 assert_default_node(block[0])
1521 self.assertEqual(len(block[0].stmts), 2)
1522 assert_case_node(block[1], '10')
1523 self.assertEqual(len(block[1].stmts), 0)
1524 assert_case_node(block[2], '20')
1525 self.assertEqual(len(block[1].stmts), 0)
1526 assert_case_node(block[3], '30')
1527 self.assertEqual(len(block[1].stmts), 0)
1528 assert_case_node(block[4], '40')
1529 self.assertEqual(len(block[4].stmts), 1)
Ben5cd3fd62012-02-03 06:02:40 +02001530
eli.bendersky145890d2010-10-29 12:02:32 +02001531 def test_for_statement(self):
1532 s2 = r'''
1533 void x(void)
1534 {
1535 int i;
1536 for (i = 0; i < 5; ++i) {
1537 x = 50;
1538 }
1539 }
1540 '''
1541 ps2 = self.parse(s2)
1542 self.assert_num_klass_nodes(ps2, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001543 # here there are 3 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001544 # a ref in the visitor
1545 #
1546 self.assert_num_ID_refs(ps2, 'i', 3)
Eli Bendersky4476d092012-12-25 14:07:57 -08001547
eli.bendersky145890d2010-10-29 12:02:32 +02001548 s3 = r'''
1549 void x(void)
1550 {
1551 for (int i = 0; i < 5; ++i) {
1552 x = 50;
1553 }
1554 }
1555 '''
1556 ps3 = self.parse(s3)
eli.bendersky145890d2010-10-29 12:02:32 +02001557 self.assert_num_klass_nodes(ps3, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001558 # here there are 2 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001559 # a ref in the visitor
1560 #
1561 self.assert_num_ID_refs(ps3, 'i', 2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001562
Eli Bendersky4476d092012-12-25 14:07:57 -08001563 s4 = r'''
1564 void x(void) {
1565 for (int i = 0;;)
1566 i;
1567 }
1568 '''
1569 ps4 = self.parse(s4)
1570 self.assert_num_ID_refs(ps4, 'i', 1)
1571
Eli Benderskyd0973782012-01-19 08:09:33 +02001572 def _open_c_file(self, name):
1573 """ Find a c file by name, taking into account the current dir can be
1574 in a couple of typical places
1575 """
Stefano Riveraebaf5922013-08-08 09:45:26 +02001576 testdir = os.path.dirname(__file__)
1577 name = os.path.join(testdir, 'c_files', name)
1578 assert os.path.exists(name)
1579 return open(name, 'rU')
Eli Benderskyd0973782012-01-19 08:09:33 +02001580
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001581 def test_whole_file(self):
1582 # See how pycparser handles a whole, real C file.
1583 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001584 with self._open_c_file('memmgr_with_h.c') as f:
1585 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001586 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001587
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001588 self.assert_num_klass_nodes(p, FuncDef, 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001589
1590 # each FuncDef also has a FuncDecl. 4 declarations
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001591 # + 5 definitions, overall 9
1592 self.assert_num_klass_nodes(p, FuncDecl, 9)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001593
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001594 self.assert_num_klass_nodes(p, Typedef, 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001595
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001596 self.assertEqual(p.ext[4].coord.line, 88)
1597 self.assertEqual(p.ext[4].coord.file, "./memmgr.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001598
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001599 self.assertEqual(p.ext[6].coord.line, 10)
1600 self.assertEqual(p.ext[6].coord.file, "memmgr.c")
1601
1602 def test_whole_file_with_stdio(self):
1603 # Parse a whole file with stdio.h included by cpp
1604 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001605 with self._open_c_file('cppd_with_stdio_h.c') as f:
1606 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001607 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001608
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001609 self.assertTrue(isinstance(p.ext[0], Typedef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001610 self.assertEqual(p.ext[0].coord.line, 213)
1611 self.assertEqual(p.ext[0].coord.file, "D:\eli\cpp_stuff\libc_include/stddef.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001612
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001613 self.assertTrue(isinstance(p.ext[-1], FuncDef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001614 self.assertEqual(p.ext[-1].coord.line, 15)
1615 self.assertEqual(p.ext[-1].coord.file, "example_c_file.c")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001616
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001617 self.assertTrue(isinstance(p.ext[-8], Typedef))
1618 self.assertTrue(isinstance(p.ext[-8].type, TypeDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001619 self.assertEqual(p.ext[-8].name, 'cookie_io_functions_t')
eli.bendersky85d2e732011-05-20 19:47:26 +03001620
1621
1622class TestCParser_typenames(TestCParser_base):
1623 """ Test issues related to the typedef-name problem.
1624 """
1625 def test_innerscope_typedef(self):
1626 # should fail since TT is not a type in bar
1627 s1 = r'''
1628 void foo() {
1629 typedef char TT;
1630 TT x;
1631 }
1632 void bar() {
1633 TT y;
1634 }
1635 '''
1636 self.assertRaises(ParseError, self.parse, s1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001637
eli.bendersky85d2e732011-05-20 19:47:26 +03001638 # should succeed since TT is not a type in bar
1639 s2 = r'''
1640 void foo() {
1641 typedef char TT;
1642 TT x;
1643 }
1644 void bar() {
1645 unsigned TT;
1646 }
1647 '''
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001648 self.assertTrue(isinstance(self.parse(s2), FileAST))
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001649
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001650 def test_innerscope_reuse_typedef_name(self):
1651 # identifiers can be reused in inner scopes; the original should be
1652 # restored at the end of the block
1653 s1 = r'''
1654 typedef char TT;
1655 void foo(void) {
1656 unsigned TT;
1657 TT = 10;
1658 }
1659 TT x = 5;
1660 '''
1661 s1_ast = self.parse(s1)
1662 self.assertEqual(expand_decl(s1_ast.ext[1].body.block_items[0]),
1663 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
Eli Bendersky3877c4c2013-07-13 06:54:04 -07001664 self.assertEqual(expand_decl(s1_ast.ext[2]),
1665 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['TT']]]])
eli.bendersky85d2e732011-05-20 19:47:26 +03001666
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001667 # this should be recognized even with an initializer
1668 s2 = r'''
1669 typedef char TT;
1670 void foo(void) {
1671 unsigned TT = 10;
1672 }
1673 '''
1674 s2_ast = self.parse(s2)
1675 self.assertEqual(expand_decl(s2_ast.ext[1].body.block_items[0]),
1676 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1677
1678 # before the second local variable, TT is a type; after, it's a
1679 # variable
1680 s3 = r'''
1681 typedef char TT;
1682 void foo(void) {
1683 TT tt = sizeof(TT);
1684 unsigned TT = 10;
1685 }
1686 '''
1687 s3_ast = self.parse(s3)
1688 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[0]),
1689 ['Decl', 'tt', ['TypeDecl', ['IdentifierType', ['TT']]]])
1690 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[1]),
1691 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1692
1693 # a variable and its type can even share the same name
1694 s4 = r'''
1695 typedef char TT;
1696 void foo(void) {
1697 TT TT = sizeof(TT);
1698 unsigned uu = TT * 2;
1699 }
1700 '''
1701 s4_ast = self.parse(s4)
1702 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[0]),
1703 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['TT']]]])
1704 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[1]),
1705 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1706
1707 # ensure an error is raised if a type, redeclared as a variable, is
1708 # used as a type
1709 s5 = r'''
1710 typedef char TT;
1711 void foo(void) {
1712 unsigned TT = 10;
1713 TT erroneous = 20;
1714 }
1715 '''
1716 self.assertRaises(ParseError, self.parse, s5)
1717
1718 def test_parameter_reuse_typedef_name(self):
1719 # identifiers can be reused as parameter names; parameter name scope
1720 # begins and ends with the function body; it's important that TT is
Eli Bendersky4d969b32013-07-13 06:07:07 -07001721 # used immediately before the LBRACE or after the RBRACE, to test
1722 # a corner case
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001723 s1 = r'''
1724 typedef char TT;
1725 void foo(unsigned TT, TT bar) {
1726 TT = 10;
1727 }
1728 TT x = 5;
1729 '''
1730 s1_ast = self.parse(s1)
1731 self.assertEqual(expand_decl(s1_ast.ext[1].decl),
1732 ['Decl', 'foo',
1733 ['FuncDecl',
1734 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
1735 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
1736 ['TypeDecl', ['IdentifierType', ['void']]]]])
1737
1738 # the scope of a parameter name in a function declaration ends at the
1739 # end of the declaration...so it is effectively never used; it's
1740 # important that TT is used immediately after the declaration, to
1741 # test a corner case
1742 s2 = r'''
1743 typedef char TT;
1744 void foo(unsigned TT, TT bar);
1745 TT x = 5;
1746 '''
1747 s2_ast = self.parse(s2)
1748 self.assertEqual(expand_decl(s2_ast.ext[1]),
1749 ['Decl', 'foo',
1750 ['FuncDecl',
1751 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
1752 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
1753 ['TypeDecl', ['IdentifierType', ['void']]]]])
1754
1755 # ensure an error is raised if a type, redeclared as a parameter, is
1756 # used as a type
1757 s3 = r'''
1758 typedef char TT;
1759 void foo(unsigned TT, TT bar) {
1760 TT erroneous = 20;
1761 }
1762 '''
1763 self.assertRaises(ParseError, self.parse, s3)
1764
1765 def test_nested_function_decls(self):
1766 # parameter names of nested function declarations must not escape into
1767 # the top-level function _definition's_ scope; the following must
1768 # succeed because TT is still a typedef inside foo's body
1769 s1 = r'''
1770 typedef char TT;
1771 void foo(unsigned bar(int TT)) {
1772 TT x = 10;
1773 }
1774 '''
1775 self.assertTrue(isinstance(self.parse(s1), FileAST))
1776
1777 def test_samescope_reuse_name(self):
1778 # a typedef name cannot be reused as an object name in the same scope
1779 s1 = r'''
1780 typedef char TT;
1781 char TT = 5;
1782 '''
1783 self.assertRaises(ParseError, self.parse, s1)
1784
1785 # ...and vice-versa
1786 s2 = r'''
1787 char TT = 5;
1788 typedef char TT;
1789 '''
1790 self.assertRaises(ParseError, self.parse, s2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001791
1792if __name__ == '__main__':
1793 #~ suite = unittest.TestLoader().loadTestsFromNames(
1794 #~ ['test_c_parser.TestCParser_fundamentals.test_typedef'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001795
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001796 #~ unittest.TextTestRunner(verbosity=2).run(suite)
1797 unittest.main()