blob: e32c49d0a50099d926657a6335d6caa8acf518a7 [file] [log] [blame]
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001#!/usr/bin/env python
2
3import pprint
4import re
Eli Benderskyd0973782012-01-19 08:09:33 +02005import os, sys
Eli Bendersky3921e8e2010-05-21 09:05:39 +03006import unittest
7
Eli Bendersky3877c4c2013-07-13 06:54:04 -07008sys.path[0:0] = ['.', '..']
Eli Bendersky3921e8e2010-05-21 09:05:39 +03009
10from pycparser import c_parser
11from pycparser.c_ast import *
12from pycparser.c_parser import CParser, Coord, ParseError
13
Eli Bendersky3921e8e2010-05-21 09:05:39 +030014_c_parser = c_parser.CParser(
15 lex_optimize=False,
Eli Bendersky86f2eee2013-01-18 06:04:01 -080016 yacc_debug=True,
Eli Bendersky3921e8e2010-05-21 09:05:39 +030017 yacc_optimize=False,
18 yacctab='yacctab')
19
20
21def expand_decl(decl):
22 """ Converts the declaration into a nested list.
23 """
24 typ = type(decl)
Eli Bendersky86f2eee2013-01-18 06:04:01 -080025
Eli Bendersky3921e8e2010-05-21 09:05:39 +030026 if typ == TypeDecl:
27 return ['TypeDecl', expand_decl(decl.type)]
28 elif typ == IdentifierType:
29 return ['IdentifierType', decl.names]
30 elif typ == ID:
31 return ['ID', decl.name]
32 elif typ in [Struct, Union]:
33 decls = [expand_decl(d) for d in decl.decls or []]
34 return [typ.__name__, decl.name, decls]
Eli Bendersky86f2eee2013-01-18 06:04:01 -080035 else:
Eli Bendersky3921e8e2010-05-21 09:05:39 +030036 nested = expand_decl(decl.type)
Eli Bendersky86f2eee2013-01-18 06:04:01 -080037
Eli Bendersky3921e8e2010-05-21 09:05:39 +030038 if typ == Decl:
39 if decl.quals:
40 return ['Decl', decl.quals, decl.name, nested]
41 else:
42 return ['Decl', decl.name, nested]
43 elif typ == Typename: # for function parameters
44 if decl.quals:
45 return ['Typename', decl.quals, nested]
46 else:
47 return ['Typename', nested]
48 elif typ == ArrayDecl:
49 dimval = decl.dim.value if decl.dim else ''
Eli Bendersky8aad3182014-01-25 06:30:53 -080050 return ['ArrayDecl', dimval, decl.dim_quals, nested]
Eli Bendersky3921e8e2010-05-21 09:05:39 +030051 elif typ == PtrDecl:
Eli Benderskyb17da152015-04-21 14:35:18 -070052 if decl.quals:
53 return ['PtrDecl', decl.quals, nested]
54 else:
55 return ['PtrDecl', nested]
Eli Bendersky3921e8e2010-05-21 09:05:39 +030056 elif typ == Typedef:
57 return ['Typedef', decl.name, nested]
58 elif typ == FuncDecl:
59 if decl.args:
60 params = [expand_decl(param) for param in decl.args.params]
61 else:
62 params = []
63 return ['FuncDecl', params, nested]
Eli Bendersky86f2eee2013-01-18 06:04:01 -080064
Eli Bendersky3921e8e2010-05-21 09:05:39 +030065
66def expand_init(init):
67 """ Converts an initialization into a nested list
68 """
69 typ = type(init)
Eli Bendersky86f2eee2013-01-18 06:04:01 -080070
eli.benderskyf890a862010-10-30 12:13:23 +020071 if typ == NamedInitializer:
72 des = [expand_init(dp) for dp in init.name]
73 return (des, expand_init(init.expr))
Eli Bendersky293ea912012-12-25 14:52:48 -080074 elif typ in (InitList, ExprList):
eli.benderskyf890a862010-10-30 12:13:23 +020075 return [expand_init(expr) for expr in init.exprs]
76 elif typ == Constant:
Eli Bendersky3921e8e2010-05-21 09:05:39 +030077 return ['Constant', init.type, init.value]
78 elif typ == ID:
79 return ['ID', init.name]
Eli Bendersky3921e8e2010-05-21 09:05:39 +030080
81
eli.bendersky85d2e732011-05-20 19:47:26 +030082class TestCParser_base(unittest.TestCase):
Eli Bendersky3921e8e2010-05-21 09:05:39 +030083 def parse(self, txt, filename=''):
84 return self.cparser.parse(txt, filename)
Eli Bendersky86f2eee2013-01-18 06:04:01 -080085
Eli Bendersky3921e8e2010-05-21 09:05:39 +030086 def setUp(self):
87 self.cparser = _c_parser
Eli Bendersky86f2eee2013-01-18 06:04:01 -080088
Eli Benderskyb77d6c02016-10-11 20:33:53 -070089 def assert_coord(self, node, line, file=None):
90 self.assertEqual(node.coord.line, line)
91 if file:
92 self.assertEqual(node.coord.file, file)
93
eli.bendersky85d2e732011-05-20 19:47:26 +030094
95class TestCParser_fundamentals(TestCParser_base):
Eli Bendersky3921e8e2010-05-21 09:05:39 +030096 def get_decl(self, txt, index=0):
97 """ Given a source and an index returns the expanded
98 declaration at that index.
Eli Bendersky86f2eee2013-01-18 06:04:01 -080099
100 FileAST holds a list of 'external declarations'.
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300101 index is the offset of the desired declaration in that
102 list.
103 """
104 t = self.parse(txt).ext[index]
105 return expand_decl(t)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800106
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300107 def get_decl_init(self, txt, index=0):
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800108 """ Returns the expanded initializer of the declaration
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300109 at index.
110 """
111 t = self.parse(txt).ext[index]
112 return expand_init(t.init)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800113
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300114 def test_FileAST(self):
115 t = self.parse('int a; char c;')
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300116 self.assertTrue(isinstance(t, FileAST))
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300117 self.assertEqual(len(t.ext), 2)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800118
eli.bendersky43cf0b22011-10-19 05:56:15 +0200119 # empty file
120 t2 = self.parse('')
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300121 self.assertTrue(isinstance(t2, FileAST))
eli.bendersky43cf0b22011-10-19 05:56:15 +0200122 self.assertEqual(len(t2.ext), 0)
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300123
eli.bendersky38165b72011-02-04 08:13:39 +0200124 def test_empty_toplevel_decl(self):
125 code = 'int foo;;'
126 t = self.parse(code)
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300127 self.assertTrue(isinstance(t, FileAST))
eli.bendersky38165b72011-02-04 08:13:39 +0200128 self.assertEqual(len(t.ext), 1)
129 self.assertEqual(self.get_decl(code),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800130 ['Decl', 'foo',
eli.bendersky38165b72011-02-04 08:13:39 +0200131 ['TypeDecl', ['IdentifierType', ['int']]]])
132
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300133 def test_coords(self):
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800134 """ Tests the "coordinates" of parsed elements - file
eli.bendersky38165b72011-02-04 08:13:39 +0200135 name and line numbers, with modification insterted by
136 #line directives.
137 """
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300138 self.assert_coord(self.parse('int a;').ext[0], 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800139
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300140 t1 = """
141 int a;
142 int b;\n\n
143 int c;
144 """
145 f1 = self.parse(t1, filename='test.c')
146 self.assert_coord(f1.ext[0], 2, 'test.c')
147 self.assert_coord(f1.ext[1], 3, 'test.c')
148 self.assert_coord(f1.ext[2], 6, 'test.c')
149
150 t1_1 = '''
151 int main() {
152 k = p;
153 printf("%d", b);
154 return 0;
155 }'''
156 f1_1 = self.parse(t1_1, filename='test.c')
eli.benderskyef29ff92010-10-29 16:25:43 +0200157 self.assert_coord(f1_1.ext[0].body.block_items[0], 3, 'test.c')
158 self.assert_coord(f1_1.ext[0].body.block_items[1], 4, 'test.c')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800159
eli.benderskyfc96e5e2011-03-04 09:51:23 +0200160 t1_2 = '''
161 int main () {
162 int p = (int) k;
163 }'''
164 f1_2 = self.parse(t1_2, filename='test.c')
165 # make sure that the Cast has a coord (issue 23)
166 self.assert_coord(f1_2.ext[0].body.block_items[0].init, 3, 'test.c')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800167
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300168 t2 = """
169 #line 99
170 int c;
171 """
172 self.assert_coord(self.parse(t2).ext[0], 99)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800173
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300174 t3 = """
175 int dsf;
176 char p;
177 #line 3000 "in.h"
178 char d;
179 """
180 f3 = self.parse(t3, filename='test.c')
181 self.assert_coord(f3.ext[0], 2, 'test.c')
182 self.assert_coord(f3.ext[1], 3, 'test.c')
183 self.assert_coord(f3.ext[2], 3000, 'in.h')
184
185 t4 = """
186 #line 20 "restore.h"
187 int maydler(char);
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800188
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300189 #line 30 "includes/daween.ph"
190 long j, k;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800191
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300192 #line 50000
193 char* ro;
194 """
195 f4 = self.parse(t4, filename='myb.c')
196 self.assert_coord(f4.ext[0], 20, 'restore.h')
197 self.assert_coord(f4.ext[1], 30, 'includes/daween.ph')
198 self.assert_coord(f4.ext[2], 30, 'includes/daween.ph')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800199 self.assert_coord(f4.ext[3], 50000, 'includes/daween.ph')
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300200
201 t5 = """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800202 int
203 #line 99
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300204 c;
205 """
206 self.assert_coord(self.parse(t5).ext[0], 99)
207
Eli Bendersky203b9672012-06-15 10:11:24 +0300208 # coord for ellipsis
209 t6 = """
210 int foo(int j,
211 ...) {
212 }"""
213 f6 = self.parse(t6, filename='z.c')
214 self.assert_coord(self.parse(t6).ext[0].decl.type.args.params[1], 3)
215
Eli Bendersky8e5d3a92014-03-15 14:06:00 -0700216 def test_forloop_coord(self):
217 t = '''\
218 void foo() {
219 for(int z=0; z<4;
220 z++){}
221 }
222 '''
223 s = self.parse(t, filename='f.c')
224 forloop = s.ext[0].body.block_items[0]
225 self.assert_coord(forloop.init, 2, 'f.c')
226 self.assert_coord(forloop.cond, 2, 'f.c')
227 self.assert_coord(forloop.next, 3, 'f.c')
228
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300229 def test_simple_decls(self):
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800230 self.assertEqual(self.get_decl('int a;'),
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300231 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
232
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800233 self.assertEqual(self.get_decl('unsigned int a;'),
Eli Bendersky68497c22012-01-19 06:04:58 +0200234 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['unsigned', 'int']]]])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300235
eli.benderskyaffe0322011-09-24 06:16:55 +0300236 self.assertEqual(self.get_decl('_Bool a;'),
237 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['_Bool']]]])
238
Eli Benderskyf4d73462012-01-19 05:56:27 +0200239 self.assertEqual(self.get_decl('float _Complex fcc;'),
Eli Bendersky68497c22012-01-19 06:04:58 +0200240 ['Decl', 'fcc', ['TypeDecl', ['IdentifierType', ['float', '_Complex']]]])
Eli Benderskyf4d73462012-01-19 05:56:27 +0200241
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800242 self.assertEqual(self.get_decl('char* string;'),
243 ['Decl', 'string',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300244 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]])
245
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800246 self.assertEqual(self.get_decl('long ar[15];'),
247 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800248 ['ArrayDecl', '15', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300249 ['TypeDecl', ['IdentifierType', ['long']]]]])
eli.bendersky98f45372010-10-30 09:46:29 +0200250
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800251 self.assertEqual(self.get_decl('long long ar[15];'),
252 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800253 ['ArrayDecl', '15', [],
eli.benderskyf890a862010-10-30 12:13:23 +0200254 ['TypeDecl', ['IdentifierType', ['long', 'long']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800255
256 self.assertEqual(self.get_decl('unsigned ar[];'),
257 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800258 ['ArrayDecl', '', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300259 ['TypeDecl', ['IdentifierType', ['unsigned']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800260
261 self.assertEqual(self.get_decl('int strlen(char* s);'),
262 ['Decl', 'strlen',
263 ['FuncDecl',
264 [['Decl', 's',
265 ['PtrDecl',
266 ['TypeDecl', ['IdentifierType', ['char']]]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300267 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800268
269 self.assertEqual(self.get_decl('int strcmp(char* s1, char* s2);'),
270 ['Decl', 'strcmp',
271 ['FuncDecl',
272 [ ['Decl', 's1',
273 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
274 ['Decl', 's2',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300275 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800276 ],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300277 ['TypeDecl', ['IdentifierType', ['int']]]]])
278
Sye van der Veen51a46ec2013-06-10 12:56:15 -0400279 # function return values and parameters may not have type information
Eli Bendersky09e22a62013-07-02 06:00:36 -0700280 self.assertEqual(self.get_decl('extern foobar(foo, bar);'),
281 ['Decl', 'foobar',
282 ['FuncDecl',
Sye van der Veen51a46ec2013-06-10 12:56:15 -0400283 [ ['ID', 'foo'],
284 ['ID', 'bar']
Eli Bendersky09e22a62013-07-02 06:00:36 -0700285 ],
Sye van der Veen51a46ec2013-06-10 12:56:15 -0400286 ['TypeDecl', ['IdentifierType', ['int']]]]])
287
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300288 def test_nested_decls(self): # the fun begins
289 self.assertEqual(self.get_decl('char** ar2D;'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800290 ['Decl', 'ar2D',
291 ['PtrDecl', ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300292 ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800293
294 self.assertEqual(self.get_decl('int (*a)[1][2];'),
295 ['Decl', 'a',
296 ['PtrDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800297 ['ArrayDecl', '1', [],
298 ['ArrayDecl', '2', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300299 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
300
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800301 self.assertEqual(self.get_decl('int *a[1][2];'),
302 ['Decl', 'a',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800303 ['ArrayDecl', '1', [],
304 ['ArrayDecl', '2', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300305 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['int']]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800306
Eli Benderskyb17da152015-04-21 14:35:18 -0700307 self.assertEqual(self.get_decl('char* const* p;'),
308 ['Decl', 'p',
309 ['PtrDecl', ['PtrDecl', ['const'],
310 ['TypeDecl', ['IdentifierType', ['char']]]]]])
311
312 self.assertEqual(self.get_decl('char* * const p;'),
313 ['Decl', 'p',
314 ['PtrDecl', ['const'], ['PtrDecl',
315 ['TypeDecl', ['IdentifierType', ['char']]]]]])
316
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300317 self.assertEqual(self.get_decl('char ***ar3D[40];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800318 ['Decl', 'ar3D',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800319 ['ArrayDecl', '40', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800320 ['PtrDecl', ['PtrDecl', ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300321 ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800322
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300323 self.assertEqual(self.get_decl('char (***ar3D)[40];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800324 ['Decl', 'ar3D',
325 ['PtrDecl', ['PtrDecl', ['PtrDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800326 ['ArrayDecl', '40', [], ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800327
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300328 self.assertEqual(self.get_decl('int (*x[4])(char, int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800329 ['Decl', 'x',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800330 ['ArrayDecl', '4', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800331 ['PtrDecl',
332 ['FuncDecl',
333 [ ['Typename', ['TypeDecl', ['IdentifierType', ['char']]]],
334 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300335 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800336
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300337 self.assertEqual(self.get_decl('char *(*(**foo [][8])())[];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800338 ['Decl', 'foo',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800339 ['ArrayDecl', '', [],
340 ['ArrayDecl', '8', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800341 ['PtrDecl', ['PtrDecl',
342 ['FuncDecl',
343 [],
344 ['PtrDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800345 ['ArrayDecl', '', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800346 ['PtrDecl',
347 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300348 ['IdentifierType', ['char']]]]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800349
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300350 # explore named and unnamed function pointer parameters,
351 # with and without qualifiers
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800352
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300353 # unnamed w/o quals
354 self.assertEqual(self.get_decl('int (*k)(int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800355 ['Decl', 'k',
356 ['PtrDecl',
357 ['FuncDecl',
358 [['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300359 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800360
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300361 # unnamed w/ quals
362 self.assertEqual(self.get_decl('int (*k)(const int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800363 ['Decl', 'k',
364 ['PtrDecl',
365 ['FuncDecl',
366 [['Typename', ['const'], ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300367 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800368
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300369 # named w/o quals
370 self.assertEqual(self.get_decl('int (*k)(int q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800371 ['Decl', 'k',
372 ['PtrDecl',
373 ['FuncDecl',
374 [['Decl', 'q', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300375 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800376
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300377 # named w/ quals
378 self.assertEqual(self.get_decl('int (*k)(const volatile int q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800379 ['Decl', 'k',
380 ['PtrDecl',
381 ['FuncDecl',
382 [['Decl', ['const', 'volatile'], 'q',
383 ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300384 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800385
eli.bendersky79d5cf62010-10-29 13:33:52 +0200386 # restrict qualifier
387 self.assertEqual(self.get_decl('int (*k)(restrict int* q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800388 ['Decl', 'k',
389 ['PtrDecl',
390 ['FuncDecl',
391 [['Decl', ['restrict'], 'q',
eli.bendersky79d5cf62010-10-29 13:33:52 +0200392 ['PtrDecl',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800393 ['TypeDecl', ['IdentifierType', ['int']]]]]],
eli.bendersky79d5cf62010-10-29 13:33:52 +0200394 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800395
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800396 def test_func_decls_with_array_dim_qualifiers(self):
397 self.assertEqual(self.get_decl('int zz(int p[static 10]);'),
398 ['Decl', 'zz',
399 ['FuncDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800400 [['Decl', 'p', ['ArrayDecl', '10', ['static'],
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800401 ['TypeDecl', ['IdentifierType', ['int']]]]]],
402 ['TypeDecl', ['IdentifierType', ['int']]]]])
403
404 self.assertEqual(self.get_decl('int zz(int p[const 10]);'),
405 ['Decl', 'zz',
406 ['FuncDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800407 [['Decl', 'p', ['ArrayDecl', '10', ['const'],
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800408 ['TypeDecl', ['IdentifierType', ['int']]]]]],
409 ['TypeDecl', ['IdentifierType', ['int']]]]])
410
necase4a6afa02014-12-19 16:38:37 -0600411 self.assertEqual(self.get_decl('int zz(int p[restrict][5]);'),
412 ['Decl', 'zz',
413 ['FuncDecl',
414 [['Decl', 'p', ['ArrayDecl', '', ['restrict'],
415 ['ArrayDecl', '5', [],
416 ['TypeDecl', ['IdentifierType', ['int']]]]]]],
417 ['TypeDecl', ['IdentifierType', ['int']]]]])
418
419 self.assertEqual(self.get_decl('int zz(int p[const restrict static 10][5]);'),
420 ['Decl', 'zz',
421 ['FuncDecl',
422 [['Decl', 'p', ['ArrayDecl', '10', ['const', 'restrict', 'static'],
423 ['ArrayDecl', '5', [],
424 ['TypeDecl', ['IdentifierType', ['int']]]]]]],
425 ['TypeDecl', ['IdentifierType', ['int']]]]])
426
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300427 def test_qualifiers_storage_specifiers(self):
428 def assert_qs(txt, index, quals, storage):
429 d = self.parse(txt).ext[index]
430 self.assertEqual(d.quals, quals)
431 self.assertEqual(d.storage, storage)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800432
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300433 assert_qs("extern int p;", 0, [], ['extern'])
434 assert_qs("const long p = 6;", 0, ['const'], [])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800435
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300436 d1 = "static const int p, q, r;"
437 for i in range(3):
438 assert_qs(d1, i, ['const'], ['static'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800439
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300440 d2 = "static char * const p;"
441 assert_qs(d2, 0, [], ['static'])
442 pdecl = self.parse(d2).ext[0].type
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300443 self.assertTrue(isinstance(pdecl, PtrDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300444 self.assertEqual(pdecl.quals, ['const'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800445
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300446 def test_sizeof(self):
447 e = """
448 void foo()
449 {
450 int a = sizeof k;
451 int b = sizeof(int);
eli.benderskyc51e1d32011-02-04 08:52:33 +0200452 int c = sizeof(int**);;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800453
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300454 char* p = "just to make sure this parses w/o error...";
455 int d = sizeof(int());
456 }
457 """
458 compound = self.parse(e).ext[0].body
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800459
eli.benderskyef29ff92010-10-29 16:25:43 +0200460 s1 = compound.block_items[0].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300461 self.assertTrue(isinstance(s1, UnaryOp))
462 self.assertEqual(s1.op, 'sizeof')
463 self.assertTrue(isinstance(s1.expr, ID))
464 self.assertEqual(s1.expr.name, 'k')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800465
eli.benderskyef29ff92010-10-29 16:25:43 +0200466 s2 = compound.block_items[1].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300467 self.assertEqual(expand_decl(s2.expr),
468 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800469
eli.benderskyef29ff92010-10-29 16:25:43 +0200470 s3 = compound.block_items[2].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300471 self.assertEqual(expand_decl(s3.expr),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800472 ['Typename',
473 ['PtrDecl',
474 ['PtrDecl',
475 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300476 ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800477
Eli Benderskye59395b2015-05-09 15:20:46 -0700478 def test_offsetof(self):
479 e = """
480 void foo() {
481 int a = offsetof(struct S, p);
482 a.b = offsetof(struct sockaddr, sp) + strlen(bar);
ksero749650a2016-09-09 07:31:09 +0200483 int a = offsetof(struct S, p.q.r);
484 int a = offsetof(struct S, p[5].q[4][5]);
Eli Benderskye59395b2015-05-09 15:20:46 -0700485 }
486 """
487 compound = self.parse(e).ext[0].body
488 s1 = compound.block_items[0].init
Eli Benderskya71ec1b2015-05-10 06:31:20 -0700489 self.assertTrue(isinstance(s1, FuncCall))
490 self.assertTrue(isinstance(s1.name, ID))
Eli Benderskye59395b2015-05-09 15:20:46 -0700491 self.assertEqual(s1.name.name, 'offsetof')
Eli Benderskya71ec1b2015-05-10 06:31:20 -0700492 self.assertTrue(isinstance(s1.args.exprs[0], Typename))
493 self.assertTrue(isinstance(s1.args.exprs[1], ID))
ksero749650a2016-09-09 07:31:09 +0200494 s3 = compound.block_items[2].init
495 self.assertTrue(isinstance(s3.args.exprs[1], StructRef))
496 s4 = compound.block_items[3].init
497 self.assertTrue(isinstance(s4.args.exprs[1], ArrayRef))
Eli Benderskye59395b2015-05-09 15:20:46 -0700498
Eli Benderskydbf9be22016-10-11 20:44:32 -0700499 def test_compound_statement(self):
500 e = """
501 void foo() {
502 }
503 """
504 compound = self.parse(e).ext[0].body
505 self.assertTrue(isinstance(compound, Compound))
506 self.assert_coord(compound, 2, '')
507
eli.bendersky9f481562010-10-30 15:50:47 +0200508 # The C99 compound literal feature
509 #
eli.benderskyf890a862010-10-30 12:13:23 +0200510 def test_compound_literals(self):
eli.bendersky9f481562010-10-30 15:50:47 +0200511 ps1 = self.parse(r'''
eli.benderskyf890a862010-10-30 12:13:23 +0200512 void foo() {
eli.bendersky9f481562010-10-30 15:50:47 +0200513 p = (long long){k};
514 tc = (struct jk){.a = {1, 2}, .b[0] = t};
515 }''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800516
eli.bendersky9f481562010-10-30 15:50:47 +0200517 compound = ps1.ext[0].body.block_items[0].rvalue
518 self.assertEqual(expand_decl(compound.type),
519 ['Typename', ['TypeDecl', ['IdentifierType', ['long', 'long']]]])
520 self.assertEqual(expand_init(compound.init),
521 [['ID', 'k']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800522
523 compound = ps1.ext[0].body.block_items[1].rvalue
eli.bendersky9f481562010-10-30 15:50:47 +0200524 self.assertEqual(expand_decl(compound.type),
525 ['Typename', ['TypeDecl', ['Struct', 'jk', []]]])
526 self.assertEqual(expand_init(compound.init),
527 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800528 ([['ID', 'a']], [['Constant', 'int', '1'], ['Constant', 'int', '2']]),
eli.bendersky9f481562010-10-30 15:50:47 +0200529 ([['ID', 'b'], ['Constant', 'int', '0']], ['ID', 't'])])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800530
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300531 def test_enums(self):
532 e1 = "enum mycolor op;"
533 e1_type = self.parse(e1).ext[0].type.type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800534
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300535 self.assertTrue(isinstance(e1_type, Enum))
536 self.assertEqual(e1_type.name, 'mycolor')
537 self.assertEqual(e1_type.values, None)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800538
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300539 e2 = "enum mysize {large=20, small, medium} shoes;"
540 e2_type = self.parse(e2).ext[0].type.type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800541
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300542 self.assertTrue(isinstance(e2_type, Enum))
543 self.assertEqual(e2_type.name, 'mysize')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800544
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300545 e2_elist = e2_type.values
546 self.assertTrue(isinstance(e2_elist, EnumeratorList))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800547
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300548 for e2_eval in e2_elist.enumerators:
549 self.assertTrue(isinstance(e2_eval, Enumerator))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800550
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300551 self.assertEqual(e2_elist.enumerators[0].name, 'large')
552 self.assertEqual(e2_elist.enumerators[0].value.value, '20')
553 self.assertEqual(e2_elist.enumerators[2].name, 'medium')
554 self.assertEqual(e2_elist.enumerators[2].value, None)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800555
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300556 # enum with trailing comma (C99 feature)
557 e3 = """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800558 enum
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300559 {
560 red,
561 blue,
562 green,
563 } color;
564 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800565
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300566 e3_type = self.parse(e3).ext[0].type.type
567 self.assertTrue(isinstance(e3_type, Enum))
568 e3_elist = e3_type.values
569 self.assertTrue(isinstance(e3_elist, EnumeratorList))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800570
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300571 for e3_eval in e3_elist.enumerators:
572 self.assertTrue(isinstance(e3_eval, Enumerator))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800573
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300574 self.assertEqual(e3_elist.enumerators[0].name, 'red')
575 self.assertEqual(e3_elist.enumerators[0].value, None)
576 self.assertEqual(e3_elist.enumerators[1].name, 'blue')
577 self.assertEqual(e3_elist.enumerators[2].name, 'green')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800578
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300579 def test_typedef(self):
580 # without typedef, error
581 s1 = """
582 node k;
583 """
584 self.assertRaises(ParseError, self.parse, s1)
585
586 # now with typedef, works
587 s2 = """
588 typedef void* node;
589 node k;
590 """
591 ps2 = self.parse(s2)
592 self.assertEqual(expand_decl(ps2.ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800593 ['Typedef', 'node',
594 ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300595 ['TypeDecl', ['IdentifierType', ['void']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800596
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300597 self.assertEqual(expand_decl(ps2.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800598 ['Decl', 'k',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300599 ['TypeDecl', ['IdentifierType', ['node']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800600
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300601 s3 = """
602 typedef int T;
603 typedef T *pT;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800604
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300605 pT aa, bb;
606 """
607 ps3 = self.parse(s3)
608 self.assertEqual(expand_decl(ps3.ext[3]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800609 ['Decl', 'bb',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300610 ['TypeDecl', ['IdentifierType', ['pT']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800611
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300612 s4 = '''
613 typedef char* __builtin_va_list;
614 typedef __builtin_va_list __gnuc_va_list;
615 '''
616 ps4 = self.parse(s4)
617 self.assertEqual(expand_decl(ps4.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800618 ['Typedef', '__gnuc_va_list',
619 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300620 ['IdentifierType', ['__builtin_va_list']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800621
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300622 s5 = '''typedef struct tagHash Hash;'''
623 ps5 = self.parse(s5)
624 self.assertEqual(expand_decl(ps5.ext[0]),
625 ['Typedef', 'Hash', ['TypeDecl', ['Struct', 'tagHash', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800626
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300627 def test_struct_union(self):
628 s1 = """
629 struct {
630 int id;
631 char* name;
632 } joe;
633 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800634
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300635 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800636 ['Decl', 'joe',
637 ['TypeDecl', ['Struct', None,
638 [ ['Decl', 'id',
639 ['TypeDecl',
640 ['IdentifierType', ['int']]]],
641 ['Decl', 'name',
642 ['PtrDecl',
643 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300644 ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800645
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300646 s2 = """
647 struct node p;
648 """
649 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800650 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300651 ['TypeDecl', ['Struct', 'node', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800652
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300653 s21 = """
654 union pri ra;
655 """
656 self.assertEqual(expand_decl(self.parse(s21).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800657 ['Decl', 'ra',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300658 ['TypeDecl', ['Union', 'pri', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800659
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300660 s3 = """
661 struct node* p;
662 """
663 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800664 ['Decl', 'p',
665 ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300666 ['TypeDecl', ['Struct', 'node', []]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800667
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300668 s4 = """
669 struct node;
670 """
671 self.assertEqual(expand_decl(self.parse(s4).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800672 ['Decl', None,
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300673 ['Struct', 'node', []]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800674
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300675 s5 = """
676 union
677 {
678 struct
679 {
680 int type;
681 } n;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800682
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300683 struct
684 {
685 int type;
686 int intnode;
687 } ni;
688 } u;
689 """
690 self.assertEqual(expand_decl(self.parse(s5).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800691 ['Decl', 'u',
692 ['TypeDecl',
693 ['Union', None,
694 [['Decl', 'n',
695 ['TypeDecl',
696 ['Struct', None,
697 [['Decl', 'type',
698 ['TypeDecl', ['IdentifierType', ['int']]]]]]]],
699 ['Decl', 'ni',
700 ['TypeDecl',
701 ['Struct', None,
702 [['Decl', 'type',
703 ['TypeDecl', ['IdentifierType', ['int']]]],
704 ['Decl', 'intnode',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300705 ['TypeDecl', ['IdentifierType', ['int']]]]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800706
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300707 s6 = """
708 typedef struct foo_tag
709 {
710 void* data;
711 } foo, *pfoo;
712 """
713 s6_ast = self.parse(s6)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800714
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300715 self.assertEqual(expand_decl(s6_ast.ext[0]),
716 ['Typedef', 'foo',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800717 ['TypeDecl',
718 ['Struct', 'foo_tag',
719 [['Decl', 'data',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300720 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800721
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300722 self.assertEqual(expand_decl(s6_ast.ext[1]),
723 ['Typedef', 'pfoo',
724 ['PtrDecl',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800725 ['TypeDecl',
726 ['Struct', 'foo_tag',
727 [['Decl', 'data',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300728 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800729
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300730 s7 = r"""
731 struct _on_exit_args {
732 void * _fnargs[32];
733 void * _dso_handle[32];
734
735 long _fntypes;
736 #line 77 "D:\eli\cpp_stuff\libc_include/sys/reent.h"
737
738 long _is_cxa;
739 };
740 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800741
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300742 s7_ast = self.parse(s7, filename='test.c')
743 self.assert_coord(s7_ast.ext[0].type.decls[2], 6, 'test.c')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800744 self.assert_coord(s7_ast.ext[0].type.decls[3], 78,
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300745 r'D:\eli\cpp_stuff\libc_include/sys/reent.h')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800746
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300747 s8 = """
748 typedef enum tagReturnCode {SUCCESS, FAIL} ReturnCode;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800749
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300750 typedef struct tagEntry
751 {
752 char* key;
753 char* value;
754 } Entry;
755
756
757 typedef struct tagNode
758 {
759 Entry* entry;
760
761 struct tagNode* next;
762 } Node;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800763
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300764 typedef struct tagHash
765 {
766 unsigned int table_size;
767
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800768 Node** heads;
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300769
770 } Hash;
771 """
772 s8_ast = self.parse(s8)
773 self.assertEqual(expand_decl(s8_ast.ext[3]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800774 ['Typedef', 'Hash',
775 ['TypeDecl', ['Struct', 'tagHash',
776 [['Decl', 'table_size',
777 ['TypeDecl', ['IdentifierType', ['unsigned', 'int']]]],
778 ['Decl', 'heads',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300779 ['PtrDecl', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['Node']]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800780
Eli Bendersky95e3b762016-03-19 05:21:59 -0700781 def test_struct_with_extra_semis_inside(self):
782 s1 = """
783 struct {
784 int a;;
785 } foo;
786 """
787 s1_ast = self.parse(s1)
788 self.assertEqual(expand_decl(s1_ast.ext[0]),
789 ['Decl', 'foo',
790 ['TypeDecl', ['Struct', None,
791 [['Decl', 'a',
792 ['TypeDecl', ['IdentifierType', ['int']]]]]]]])
793
794 s2 = """
795 struct {
796 int a;;;;
797 float b, c;
798 ;;
799 char d;
800 } foo;
801 """
802 s2_ast = self.parse(s2)
803 self.assertEqual(expand_decl(s2_ast.ext[0]),
804 ['Decl', 'foo',
805 ['TypeDecl', ['Struct', None,
806 [['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]],
807 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['float']]]],
808 ['Decl', 'c', ['TypeDecl', ['IdentifierType', ['float']]]],
809 ['Decl', 'd',
810 ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
811
eli.bendersky697ecc52011-02-10 07:05:13 +0200812 def test_anonymous_struct_union(self):
813 s1 = """
814 union
815 {
816 union
817 {
818 int i;
819 long l;
820 };
821
822 struct
823 {
824 int type;
825 int intnode;
826 };
827 } u;
828 """
829
830 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
831 ['Decl', 'u',
832 ['TypeDecl',
833 ['Union', None,
834 [['Decl', None,
835 ['Union', None,
836 [['Decl', 'i',
837 ['TypeDecl',
838 ['IdentifierType', ['int']]]],
839 ['Decl', 'l',
840 ['TypeDecl',
841 ['IdentifierType', ['long']]]]]]],
842 ['Decl', None,
843 ['Struct', None,
844 [['Decl', 'type',
845 ['TypeDecl',
846 ['IdentifierType', ['int']]]],
847 ['Decl', 'intnode',
848 ['TypeDecl',
849 ['IdentifierType', ['int']]]]]]]]]]])
850
851 s2 = """
852 struct
853 {
854 int i;
855 union
856 {
857 int id;
858 char* name;
859 };
860 float f;
861 } joe;
862 """
863
864 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
865 ['Decl', 'joe',
866 ['TypeDecl',
867 ['Struct', None,
868 [['Decl', 'i',
869 ['TypeDecl',
870 ['IdentifierType', ['int']]]],
871 ['Decl', None,
872 ['Union', None,
873 [['Decl', 'id',
874 ['TypeDecl',
875 ['IdentifierType', ['int']]]],
876 ['Decl', 'name',
877 ['PtrDecl',
878 ['TypeDecl',
879 ['IdentifierType', ['char']]]]]]]],
880 ['Decl', 'f',
881 ['TypeDecl',
882 ['IdentifierType', ['float']]]]]]]])
883
884 # ISO/IEC 9899:201x Commitee Draft 2010-11-16, N1539
885 # section 6.7.2.1, par. 19, example 1
886 s3 = """
887 struct v {
888 union {
889 struct { int i, j; };
890 struct { long k, l; } w;
891 };
892 int m;
893 } v1;
894 """
895
896 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
897 ['Decl', 'v1',
898 ['TypeDecl',
899 ['Struct', 'v',
900 [['Decl', None,
901 ['Union', None,
902 [['Decl', None,
903 ['Struct', None,
904 [['Decl', 'i',
905 ['TypeDecl',
906 ['IdentifierType', ['int']]]],
907 ['Decl', 'j',
908 ['TypeDecl',
909 ['IdentifierType', ['int']]]]]]],
910 ['Decl', 'w',
911 ['TypeDecl',
912 ['Struct', None,
913 [['Decl', 'k',
914 ['TypeDecl',
915 ['IdentifierType', ['long']]]],
916 ['Decl', 'l',
917 ['TypeDecl',
918 ['IdentifierType', ['long']]]]]]]]]]],
919 ['Decl', 'm',
920 ['TypeDecl',
921 ['IdentifierType', ['int']]]]]]]])
922
eli.benderskydce29a02011-02-10 07:55:00 +0200923 s4 = """
924 struct v {
925 int i;
926 float;
927 } v2;"""
eli.bendersky6b011792011-06-22 17:50:56 +0300928 # just make sure this doesn't raise ParseError
929 self.parse(s4)
eli.benderskydce29a02011-02-10 07:55:00 +0200930
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400931 def test_struct_members_namespace(self):
Eli Bendersky4d969b32013-07-13 06:07:07 -0700932 """ Tests that structure/union member names reside in a separate
933 namespace and can be named after existing types.
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400934 """
935 s1 = """
936 typedef int Name;
937 typedef Name NameArray[10];
938
939 struct {
940 Name Name;
941 Name NameArray[3];
942 } sye;
943
944 void main(void)
945 {
946 sye.Name = 1;
947 }
948 """
949
950 s1_ast = self.parse(s1)
951 self.assertEqual(expand_decl(s1_ast.ext[2]),
952 ['Decl', 'sye',
953 ['TypeDecl', ['Struct', None,
954 [ ['Decl', 'Name',
955 ['TypeDecl',
956 ['IdentifierType', ['Name']]]],
957 ['Decl', 'NameArray',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800958 ['ArrayDecl', '3', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400959 ['TypeDecl', ['IdentifierType', ['Name']]]]]]]]])
960 self.assertEqual(s1_ast.ext[3].body.block_items[0].lvalue.field.name, 'Name')
961
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200962 def test_struct_bitfields(self):
eli.bendersky38ed9a92010-10-09 09:29:59 +0200963 # a struct with two bitfields, one unnamed
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200964 s1 = """
965 struct {
966 int k:6;
967 int :2;
968 } joe;
969 """
970
971 parsed_struct = self.parse(s1).ext[0]
972
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800973 # We can see here the name of the decl for the unnamed bitfield is
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200974 # None, but expand_decl doesn't show bitfield widths
975 # ...
976 self.assertEqual(expand_decl(parsed_struct),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800977 ['Decl', 'joe',
978 ['TypeDecl', ['Struct', None,
979 [ ['Decl', 'k',
980 ['TypeDecl',
981 ['IdentifierType', ['int']]]],
982 ['Decl', None,
983 ['TypeDecl',
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200984 ['IdentifierType', ['int']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800985
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200986 # ...
987 # so we test them manually
988 self.assertEqual(parsed_struct.type.type.decls[0].bitsize.value, '6')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800989 self.assertEqual(parsed_struct.type.type.decls[1].bitsize.value, '2')
990
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300991 def test_tags_namespace(self):
992 """ Tests that the tags of structs/unions/enums reside in a separate namespace and
993 can be named after existing types.
994 """
995 s1 = """
996 typedef int tagEntry;
997
998 struct tagEntry
999 {
1000 char* key;
1001 char* value;
1002 } Entry;
1003 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001004
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001005 s1_ast = self.parse(s1)
1006 self.assertEqual(expand_decl(s1_ast.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001007 ['Decl', 'Entry',
1008 ['TypeDecl', ['Struct', 'tagEntry',
1009 [['Decl', 'key',
1010 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
1011 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001012 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001013
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001014 s2 = """
1015 struct tagEntry;
1016
1017 typedef struct tagEntry tagEntry;
1018
1019 struct tagEntry
1020 {
1021 char* key;
1022 char* value;
1023 } Entry;
1024 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001025
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001026 s2_ast = self.parse(s2)
1027 self.assertEqual(expand_decl(s2_ast.ext[2]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001028 ['Decl', 'Entry',
1029 ['TypeDecl', ['Struct', 'tagEntry',
1030 [['Decl', 'key',
1031 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
1032 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001033 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001034
1035 s3 = """
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001036 typedef int mytag;
1037
1038 enum mytag {ABC, CDE};
1039 enum mytag joe;
1040 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001041
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001042 s3_type = self.parse(s3).ext[1].type
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001043
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001044 self.assertTrue(isinstance(s3_type, Enum))
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001045 self.assertEqual(s3_type.name, 'mytag')
1046
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001047 def test_multi_decls(self):
1048 d1 = 'int a, b;'
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001049
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001050 self.assertEqual(self.get_decl(d1, 0),
1051 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
1052 self.assertEqual(self.get_decl(d1, 1),
1053 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['int']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001054
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001055 d2 = 'char* p, notp, ar[4];'
1056 self.assertEqual(self.get_decl(d2, 0),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001057 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001058 ['PtrDecl',
1059 ['TypeDecl', ['IdentifierType', ['char']]]]])
1060 self.assertEqual(self.get_decl(d2, 1),
1061 ['Decl', 'notp', ['TypeDecl', ['IdentifierType', ['char']]]])
1062 self.assertEqual(self.get_decl(d2, 2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001063 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001064 ['ArrayDecl', '4', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001065 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001066
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001067 def test_invalid_multiple_types_error(self):
1068 bad = [
1069 'int enum {ab, cd} fubr;',
1070 'enum kid char brbr;']
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001071
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001072 for b in bad:
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001073 self.assertRaises(ParseError, self.parse, b)
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001074
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001075 def test_duplicate_typedef(self):
1076 """ Tests that redeclarations of existing types are parsed correctly.
1077 This is non-standard, but allowed by many compilers.
1078 """
1079 d1 = '''
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001080 typedef int numbertype;
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001081 typedef int numbertype;
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001082 '''
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001083
1084 self.assertEqual(self.get_decl(d1, 0),
1085 ['Typedef', 'numbertype',
1086 ['TypeDecl', ['IdentifierType', ['int']]]])
1087 self.assertEqual(self.get_decl(d1, 1),
1088 ['Typedef', 'numbertype',
1089 ['TypeDecl', ['IdentifierType', ['int']]]])
1090
1091 d2 = '''
1092 typedef int (*funcptr)(int x);
1093 typedef int (*funcptr)(int x);
1094 '''
1095 self.assertEqual(self.get_decl(d2, 0),
1096 ['Typedef', 'funcptr',
1097 ['PtrDecl', ['FuncDecl',
1098 [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]],
1099 ['TypeDecl', ['IdentifierType', ['int']]]]]])
1100 self.assertEqual(self.get_decl(d2, 1),
1101 ['Typedef', 'funcptr',
1102 ['PtrDecl', ['FuncDecl',
1103 [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]],
1104 ['TypeDecl', ['IdentifierType', ['int']]]]]])
1105
1106 d3 = '''
1107 typedef int numberarray[5];
1108 typedef int numberarray[5];
1109 '''
1110 self.assertEqual(self.get_decl(d3, 0),
1111 ['Typedef', 'numberarray',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001112 ['ArrayDecl', '5', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001113 ['TypeDecl', ['IdentifierType', ['int']]]]])
1114 self.assertEqual(self.get_decl(d3, 1),
1115 ['Typedef', 'numberarray',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001116 ['ArrayDecl', '5', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001117 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001118
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001119 def test_decl_inits(self):
1120 d1 = 'int a = 16;'
eli.benderskyf890a862010-10-30 12:13:23 +02001121 #~ self.parse(d1).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001122 self.assertEqual(self.get_decl(d1),
1123 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
1124 self.assertEqual(self.get_decl_init(d1),
1125 ['Constant', 'int', '16'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001126
Eli Bendersky3b1b08d2012-06-15 12:37:54 +03001127 d1_1 = 'float f = 0xEF.56p1;'
1128 self.assertEqual(self.get_decl_init(d1_1),
1129 ['Constant', 'float', '0xEF.56p1'])
1130
Konstanty Bialkowski3bdbfdc2015-04-19 20:09:21 +10001131 d1_2 = 'int bitmask = 0b1001010;'
1132 self.assertEqual(self.get_decl_init(d1_2),
1133 ['Constant', 'int', '0b1001010'])
1134
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001135 d2 = 'long ar[] = {7, 8, 9};'
1136 self.assertEqual(self.get_decl(d2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001137 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001138 ['ArrayDecl', '', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001139 ['TypeDecl', ['IdentifierType', ['long']]]]])
1140 self.assertEqual(self.get_decl_init(d2),
1141 [ ['Constant', 'int', '7'],
1142 ['Constant', 'int', '8'],
eli.benderskyf890a862010-10-30 12:13:23 +02001143 ['Constant', 'int', '9']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001144
Eli Benderskyc830da82015-05-10 07:56:41 -07001145 d21 = 'long ar[4] = {};'
1146 self.assertEqual(self.get_decl_init(d21), [])
1147
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001148 d3 = 'char p = j;'
1149 self.assertEqual(self.get_decl(d3),
1150 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['char']]]])
1151 self.assertEqual(self.get_decl_init(d3),
1152 ['ID', 'j'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001153
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001154 d4 = "char x = 'c', *p = {0, 1, 2, {4, 5}, 6};"
1155 self.assertEqual(self.get_decl(d4, 0),
1156 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['char']]]])
1157 self.assertEqual(self.get_decl_init(d4, 0),
1158 ['Constant', 'char', "'c'"])
1159 self.assertEqual(self.get_decl(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001160 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001161 ['PtrDecl',
1162 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001163
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001164 self.assertEqual(self.get_decl_init(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001165 [ ['Constant', 'int', '0'],
1166 ['Constant', 'int', '1'],
1167 ['Constant', 'int', '2'],
1168 [['Constant', 'int', '4'],
1169 ['Constant', 'int', '5']],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001170 ['Constant', 'int', '6']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001171
eli.benderskyf890a862010-10-30 12:13:23 +02001172 def test_decl_named_inits(self):
1173 d1 = 'int a = {.k = 16};'
1174 self.assertEqual(self.get_decl_init(d1),
1175 [( [['ID', 'k']],
1176 ['Constant', 'int', '16'])])
1177
1178 d2 = 'int a = { [0].a = {1}, [1].a[0] = 2 };'
1179 self.assertEqual(self.get_decl_init(d2),
1180 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001181 ([['Constant', 'int', '0'], ['ID', 'a']],
1182 [['Constant', 'int', '1']]),
1183 ([['Constant', 'int', '1'], ['ID', 'a'], ['Constant', 'int', '0']],
eli.benderskyf890a862010-10-30 12:13:23 +02001184 ['Constant', 'int', '2'])])
1185
1186 d3 = 'int a = { .a = 1, .c = 3, 4, .b = 5};'
1187 self.assertEqual(self.get_decl_init(d3),
1188 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001189 ([['ID', 'a']], ['Constant', 'int', '1']),
1190 ([['ID', 'c']], ['Constant', 'int', '3']),
1191 ['Constant', 'int', '4'],
eli.benderskyf890a862010-10-30 12:13:23 +02001192 ([['ID', 'b']], ['Constant', 'int', '5'])])
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001193
1194 def test_function_definitions(self):
1195 def parse_fdef(str):
1196 return self.parse(str).ext[0]
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001197
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001198 def fdef_decl(fdef):
1199 return expand_decl(fdef.decl)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001200
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001201 f1 = parse_fdef('''
1202 int factorial(int p)
1203 {
1204 return 3;
1205 }
1206 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001207
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001208 self.assertEqual(fdef_decl(f1),
1209 ['Decl', 'factorial',
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001210 ['FuncDecl',
1211 [['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001212 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001213
eli.benderskyef29ff92010-10-29 16:25:43 +02001214 self.assertEqual(type(f1.body.block_items[0]), Return)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001215
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001216 f2 = parse_fdef('''
1217 char* zzz(int p, char* c)
1218 {
1219 int a;
1220 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001221
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001222 a = b + 2;
1223 return 3;
1224 }
1225 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001226
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001227 self.assertEqual(fdef_decl(f2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001228 ['Decl', 'zzz',
1229 ['FuncDecl',
1230 [ ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]],
1231 ['Decl', 'c', ['PtrDecl',
1232 ['TypeDecl', ['IdentifierType', ['char']]]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001233 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001234
1235 self.assertEqual(list(map(type, f2.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001236 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001237
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001238 f3 = parse_fdef('''
1239 char* zzz(p, c)
1240 long p, *c;
1241 {
1242 int a;
1243 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001244
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001245 a = b + 2;
1246 return 3;
1247 }
1248 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001249
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001250 self.assertEqual(fdef_decl(f3),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001251 ['Decl', 'zzz',
1252 ['FuncDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001253 [ ['ID', 'p'],
1254 ['ID', 'c']],
1255 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001256
1257 self.assertEqual(list(map(type, f3.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001258 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001259
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001260 self.assertEqual(expand_decl(f3.param_decls[0]),
1261 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['long']]]])
1262 self.assertEqual(expand_decl(f3.param_decls[1]),
1263 ['Decl', 'c', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['long']]]]])
1264
Sye van der Veen51a46ec2013-06-10 12:56:15 -04001265 # function return values and parameters may not have type information
1266 f4 = parse_fdef('''
1267 que(p)
1268 {
1269 return 3;
1270 }
1271 ''')
1272
1273 self.assertEqual(fdef_decl(f4),
1274 ['Decl', 'que',
1275 ['FuncDecl',
1276 [['ID', 'p']],
1277 ['TypeDecl', ['IdentifierType', ['int']]]]])
1278
eli.bendersky71540662010-07-03 12:58:52 +02001279 def test_unified_string_literals(self):
1280 # simple string, for reference
1281 d1 = self.get_decl_init('char* s = "hello";')
1282 self.assertEqual(d1, ['Constant', 'string', '"hello"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001283
eli.bendersky71540662010-07-03 12:58:52 +02001284 d2 = self.get_decl_init('char* s = "hello" " world";')
1285 self.assertEqual(d2, ['Constant', 'string', '"hello world"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001286
eli.bendersky71540662010-07-03 12:58:52 +02001287 # the test case from issue 6
1288 d3 = self.parse(r'''
1289 int main() {
1290 fprintf(stderr,
1291 "Wrong Params?\n"
1292 "Usage:\n"
1293 "%s <binary_file_path>\n",
1294 argv[0]
1295 );
1296 }
1297 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001298
eli.bendersky71540662010-07-03 12:58:52 +02001299 self.assertEqual(
eli.benderskyef29ff92010-10-29 16:25:43 +02001300 d3.ext[0].body.block_items[0].args.exprs[1].value,
eli.bendersky71540662010-07-03 12:58:52 +02001301 r'"Wrong Params?\nUsage:\n%s <binary_file_path>\n"')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001302
eli.bendersky4a89f112010-07-05 06:02:03 +02001303 d4 = self.get_decl_init('char* s = "" "foobar";')
1304 self.assertEqual(d4, ['Constant', 'string', '"foobar"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001305
eli.bendersky4a89f112010-07-05 06:02:03 +02001306 d5 = self.get_decl_init(r'char* s = "foo\"" "bar";')
1307 self.assertEqual(d5, ['Constant', 'string', r'"foo\"bar"'])
eli.bendersky71540662010-07-03 12:58:52 +02001308
Eli Benderskyc9f1a382014-03-15 14:12:00 -07001309 def test_unified_wstring_literals(self):
1310 d1 = self.get_decl_init('char* s = L"hello" L"world";')
1311 self.assertEqual(d1, ['Constant', 'string', 'L"helloworld"'])
1312
1313 d2 = self.get_decl_init('char* s = L"hello " L"world" L" and I";')
1314 self.assertEqual(d2, ['Constant', 'string', 'L"hello world and I"'])
1315
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001316 def test_inline_specifier(self):
eli.bendersky79d5cf62010-10-29 13:33:52 +02001317 ps2 = self.parse('static inline void inlinefoo(void);')
1318 self.assertEqual(ps2.ext[0].funcspec, ['inline'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001319
eli.bendersky2e907fa2010-10-29 15:51:07 +02001320 # variable length array
1321 def test_vla(self):
1322 ps2 = self.parse(r'''
1323 int main() {
1324 int size;
1325 int var[size = 5];
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001326
eli.bendersky2e907fa2010-10-29 15:51:07 +02001327 int var2[*];
1328 }
1329 ''')
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001330 self.assertTrue(isinstance(ps2.ext[0].body.block_items[1].type.dim, Assignment))
1331 self.assertTrue(isinstance(ps2.ext[0].body.block_items[2].type.dim, ID))
eli.bendersky79d5cf62010-10-29 13:33:52 +02001332
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001333 def test_pragma(self):
1334 s1 = r'''
1335 #pragma bar
1336 void main() {
1337 #pragma foo
1338 for(;;) {}
Julian Hammer8a174062015-12-14 14:48:16 +01001339 #pragma
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001340 }
1341 '''
1342 s1_ast = self.parse(s1)
1343 self.assertTrue(isinstance(s1_ast.ext[0], Pragma))
1344 self.assertEqual(s1_ast.ext[0].string, 'bar')
Julian Hammer8a174062015-12-14 14:48:16 +01001345 self.assertEqual(s1_ast.ext[0].coord.line, 2)
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001346
1347 self.assertTrue(isinstance(s1_ast.ext[1].body.block_items[0], Pragma))
1348 self.assertEqual(s1_ast.ext[1].body.block_items[0].string, 'foo')
Julian Hammer8a174062015-12-14 14:48:16 +01001349 self.assertEqual(s1_ast.ext[1].body.block_items[0].coord.line, 4)
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001350
Julian Hammer8a174062015-12-14 14:48:16 +01001351 self.assertTrue(isinstance(s1_ast.ext[1].body.block_items[2], Pragma))
1352 self.assertEqual(s1_ast.ext[1].body.block_items[2].string, '')
1353 self.assertEqual(s1_ast.ext[1].body.block_items[2].coord.line, 6)
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001354
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001355
eli.bendersky85d2e732011-05-20 19:47:26 +03001356class TestCParser_whole_code(TestCParser_base):
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001357 """ Testing of parsing whole chunks of code.
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001358
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001359 Since I don't want to rely on the structure of ASTs too
1360 much, most of these tests are implemented with visitors.
1361 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001362 # A simple helper visitor that lists the values of all the
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001363 # Constant nodes it sees.
1364 #
1365 class ConstantVisitor(NodeVisitor):
1366 def __init__(self):
1367 self.values = []
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001368
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001369 def visit_Constant(self, node):
1370 self.values.append(node.value)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001371
1372 # This visitor counts the amount of references to the ID
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001373 # with the name provided to it in the constructor.
1374 #
1375 class IDNameCounter(NodeVisitor):
1376 def __init__(self, name):
1377 self.name = name
1378 self.nrefs = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001379
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001380 def visit_ID(self, node):
1381 if node.name == self.name:
1382 self.nrefs += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001383
1384 # Counts the amount of nodes of a given class
1385 #
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001386 class NodeKlassCounter(NodeVisitor):
1387 def __init__(self, node_klass):
1388 self.klass = node_klass
1389 self.n = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001390
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001391 def generic_visit(self, node):
1392 if node.__class__ == self.klass:
1393 self.n += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001394
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001395 NodeVisitor.generic_visit(self, node)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001396
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001397 def assert_all_Constants(self, code, constants):
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001398 """ Asserts that the list of all Constant values (by
1399 'preorder' appearance) in the chunk of code is as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001400 given.
1401 """
eli.benderskyed890492010-06-25 08:25:55 +03001402 if isinstance(code, str):
1403 parsed = self.parse(code)
1404 else:
1405 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001406
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001407 cv = self.ConstantVisitor()
1408 cv.visit(parsed)
1409 self.assertEqual(cv.values, constants)
1410
1411 def assert_num_ID_refs(self, code, name, num):
1412 """ Asserts the number of references to the ID with
1413 the given name.
1414 """
1415 if isinstance(code, str):
1416 parsed = self.parse(code)
1417 else:
1418 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001419
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001420 iv = self.IDNameCounter(name)
1421 iv.visit(parsed)
1422 self.assertEqual(iv.nrefs, num)
1423
1424 def assert_num_klass_nodes(self, code, klass, num):
1425 """ Asserts the amount of klass nodes in the code.
1426 """
1427 if isinstance(code, str):
1428 parsed = self.parse(code)
1429 else:
1430 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001431
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001432 cv = self.NodeKlassCounter(klass)
1433 cv.visit(parsed)
1434 self.assertEqual(cv.n, num)
1435
1436 def test_expressions(self):
1437 e1 = '''int k = (r + 10.0) >> 6 + 8 << (3 & 0x14);'''
1438 self.assert_all_Constants(e1, ['10.0', '6', '8', '3', '0x14'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001439
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001440 e2 = r'''char n = '\n', *prefix = "st_";'''
1441 self.assert_all_Constants(e2, [r"'\n'", '"st_"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001442
Eli Bendersky09e22a62013-07-02 06:00:36 -07001443 s1 = r'''int main() {
1444 int i = 5, j = 6, k = 1;
1445 if ((i=j && k == 1) || k > j)
1446 printf("Hello, world\n");
1447 return 0;
1448 }'''
1449 ps1 = self.parse(s1)
1450 self.assert_all_Constants(ps1,
1451 ['5', '6', '1', '1', '"Hello, world\\n"', '0'])
1452 self.assert_num_ID_refs(ps1, 'i', 1)
1453 self.assert_num_ID_refs(ps1, 'j', 2)
1454
1455
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001456 def test_statements(self):
1457 s1 = r'''
1458 void foo(){
1459 if (sp == 1)
1460 if (optind >= argc ||
1461 argv[optind][0] != '-' || argv[optind][1] == '\0')
1462 return -1;
1463 else if (strcmp(argv[optind], "--") == 0) {
1464 optind++;
1465 return -1;
1466 }
1467 }
1468 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001469
1470 self.assert_all_Constants(s1,
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001471 ['1', '0', r"'-'", '1', r"'\0'", '1', r'"--"', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001472
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001473 ps1 = self.parse(s1)
1474 self.assert_num_ID_refs(ps1, 'argv', 3)
1475 self.assert_num_ID_refs(ps1, 'optind', 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001476
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001477 self.assert_num_klass_nodes(ps1, If, 3)
1478 self.assert_num_klass_nodes(ps1, Return, 2)
1479 self.assert_num_klass_nodes(ps1, FuncCall, 1) # strcmp
1480 self.assert_num_klass_nodes(ps1, BinaryOp, 7)
1481
1482 # In the following code, Hash and Node were defined as
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001483 # int to pacify the parser that sees they're used as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001484 # types
1485 #
1486 s2 = r'''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001487 typedef int Hash, Node;
1488
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001489 void HashDestroy(Hash* hash)
1490 {
1491 unsigned int i;
1492
1493 if (hash == NULL)
1494 return;
1495
1496 for (i = 0; i < hash->table_size; ++i)
1497 {
1498 Node* temp = hash->heads[i];
1499
1500 while (temp != NULL)
1501 {
1502 Node* temp2 = temp;
1503
1504 free(temp->entry->key);
1505 free(temp->entry->value);
1506 free(temp->entry);
1507
1508 temp = temp->next;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001509
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001510 free(temp2);
1511 }
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001512 }
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001513
1514 free(hash->heads);
1515 hash->heads = NULL;
1516
1517 free(hash);
1518 }
1519 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001520
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001521 ps2 = self.parse(s2)
1522 self.assert_num_klass_nodes(ps2, FuncCall, 6)
1523 self.assert_num_klass_nodes(ps2, FuncDef, 1)
1524 self.assert_num_klass_nodes(ps2, For, 1)
1525 self.assert_num_klass_nodes(ps2, While, 1)
1526 self.assert_num_klass_nodes(ps2, StructRef, 10)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001527
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001528 # declarations don't count
1529 self.assert_num_ID_refs(ps2, 'hash', 6)
1530 self.assert_num_ID_refs(ps2, 'i', 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001531
eli.benderskyed890492010-06-25 08:25:55 +03001532 s3 = r'''
1533 void x(void) {
1534 int a, b;
1535 if (a < b)
1536 do {
1537 a = 0;
1538 } while (0);
1539 else if (a == b) {
1540 a = 1;
1541 }
1542 }
1543 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001544
eli.benderskyed890492010-06-25 08:25:55 +03001545 ps3 = self.parse(s3)
1546 self.assert_num_klass_nodes(ps3, DoWhile, 1)
1547 self.assert_num_ID_refs(ps3, 'a', 4)
1548 self.assert_all_Constants(ps3, ['0', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001549
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001550 def test_empty_statements(self):
eli.bendersky91c0aa32011-10-16 05:50:43 +02001551 s1 = r'''
1552 void foo(void){
1553 ;
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001554 return;;
1555
1556 ;
eli.bendersky91c0aa32011-10-16 05:50:43 +02001557 }
1558 '''
1559 ps1 = self.parse(s1)
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001560 self.assert_num_klass_nodes(ps1, EmptyStatement, 3)
eli.bendersky91c0aa32011-10-16 05:50:43 +02001561 self.assert_num_klass_nodes(ps1, Return, 1)
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001562 self.assert_coord(ps1.ext[0].body.block_items[0], 3, '')
1563 self.assert_coord(ps1.ext[0].body.block_items[1], 4, '')
1564 self.assert_coord(ps1.ext[0].body.block_items[2], 4, '')
1565 self.assert_coord(ps1.ext[0].body.block_items[3], 6, '')
eli.bendersky145890d2010-10-29 12:02:32 +02001566
Ben5cd3fd62012-02-03 06:02:40 +02001567 def test_switch_statement(self):
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001568 def assert_case_node(node, const_value):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001569 self.assertTrue(isinstance(node, Case))
1570 self.assertTrue(isinstance(node.expr, Constant))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001571 self.assertEqual(node.expr.value, const_value)
1572
1573 def assert_default_node(node):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001574 self.assertTrue(isinstance(node, Default))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001575
Ben5cd3fd62012-02-03 06:02:40 +02001576 s1 = r'''
1577 int foo(void) {
1578 switch (myvar) {
1579 case 10:
1580 k = 10;
1581 p = k + 1;
1582 return 10;
1583 case 20:
1584 case 30:
1585 return 20;
1586 default:
1587 break;
1588 }
1589 return 0;
1590 }
1591 '''
1592 ps1 = self.parse(s1)
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001593 switch = ps1.ext[0].body.block_items[0]
1594
1595 block = switch.stmt.block_items
1596 assert_case_node(block[0], '10')
1597 self.assertEqual(len(block[0].stmts), 3)
1598 assert_case_node(block[1], '20')
1599 self.assertEqual(len(block[1].stmts), 0)
1600 assert_case_node(block[2], '30')
1601 self.assertEqual(len(block[2].stmts), 1)
1602 assert_default_node(block[3])
1603
1604 s2 = r'''
1605 int foo(void) {
1606 switch (myvar) {
1607 default:
1608 joe = moe;
1609 return 10;
1610 case 10:
1611 case 20:
1612 case 30:
1613 case 40:
1614 break;
1615 }
1616 return 0;
1617 }
1618 '''
1619 ps2 = self.parse(s2)
1620 switch = ps2.ext[0].body.block_items[0]
1621
1622 block = switch.stmt.block_items
1623 assert_default_node(block[0])
1624 self.assertEqual(len(block[0].stmts), 2)
1625 assert_case_node(block[1], '10')
1626 self.assertEqual(len(block[1].stmts), 0)
1627 assert_case_node(block[2], '20')
1628 self.assertEqual(len(block[1].stmts), 0)
1629 assert_case_node(block[3], '30')
1630 self.assertEqual(len(block[1].stmts), 0)
1631 assert_case_node(block[4], '40')
1632 self.assertEqual(len(block[4].stmts), 1)
Ben5cd3fd62012-02-03 06:02:40 +02001633
eli.bendersky145890d2010-10-29 12:02:32 +02001634 def test_for_statement(self):
1635 s2 = r'''
1636 void x(void)
1637 {
1638 int i;
1639 for (i = 0; i < 5; ++i) {
1640 x = 50;
1641 }
1642 }
1643 '''
1644 ps2 = self.parse(s2)
1645 self.assert_num_klass_nodes(ps2, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001646 # here there are 3 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001647 # a ref in the visitor
1648 #
1649 self.assert_num_ID_refs(ps2, 'i', 3)
Eli Bendersky4476d092012-12-25 14:07:57 -08001650
eli.bendersky145890d2010-10-29 12:02:32 +02001651 s3 = r'''
1652 void x(void)
1653 {
1654 for (int i = 0; i < 5; ++i) {
1655 x = 50;
1656 }
1657 }
1658 '''
1659 ps3 = self.parse(s3)
eli.bendersky145890d2010-10-29 12:02:32 +02001660 self.assert_num_klass_nodes(ps3, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001661 # here there are 2 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001662 # a ref in the visitor
1663 #
1664 self.assert_num_ID_refs(ps3, 'i', 2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001665
Eli Bendersky4476d092012-12-25 14:07:57 -08001666 s4 = r'''
1667 void x(void) {
1668 for (int i = 0;;)
1669 i;
1670 }
1671 '''
1672 ps4 = self.parse(s4)
1673 self.assert_num_ID_refs(ps4, 'i', 1)
1674
Eli Benderskyd0973782012-01-19 08:09:33 +02001675 def _open_c_file(self, name):
1676 """ Find a c file by name, taking into account the current dir can be
1677 in a couple of typical places
1678 """
Stefano Riveraebaf5922013-08-08 09:45:26 +02001679 testdir = os.path.dirname(__file__)
1680 name = os.path.join(testdir, 'c_files', name)
1681 assert os.path.exists(name)
1682 return open(name, 'rU')
Eli Benderskyd0973782012-01-19 08:09:33 +02001683
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001684 def test_whole_file(self):
1685 # See how pycparser handles a whole, real C file.
1686 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001687 with self._open_c_file('memmgr_with_h.c') as f:
1688 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001689 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001690
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001691 self.assert_num_klass_nodes(p, FuncDef, 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001692
1693 # each FuncDef also has a FuncDecl. 4 declarations
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001694 # + 5 definitions, overall 9
1695 self.assert_num_klass_nodes(p, FuncDecl, 9)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001696
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001697 self.assert_num_klass_nodes(p, Typedef, 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001698
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001699 self.assertEqual(p.ext[4].coord.line, 88)
1700 self.assertEqual(p.ext[4].coord.file, "./memmgr.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001701
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001702 self.assertEqual(p.ext[6].coord.line, 10)
1703 self.assertEqual(p.ext[6].coord.file, "memmgr.c")
1704
1705 def test_whole_file_with_stdio(self):
1706 # Parse a whole file with stdio.h included by cpp
1707 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001708 with self._open_c_file('cppd_with_stdio_h.c') as f:
1709 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001710 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001711
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001712 self.assertTrue(isinstance(p.ext[0], Typedef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001713 self.assertEqual(p.ext[0].coord.line, 213)
1714 self.assertEqual(p.ext[0].coord.file, "D:\eli\cpp_stuff\libc_include/stddef.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001715
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001716 self.assertTrue(isinstance(p.ext[-1], FuncDef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001717 self.assertEqual(p.ext[-1].coord.line, 15)
1718 self.assertEqual(p.ext[-1].coord.file, "example_c_file.c")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001719
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001720 self.assertTrue(isinstance(p.ext[-8], Typedef))
1721 self.assertTrue(isinstance(p.ext[-8].type, TypeDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001722 self.assertEqual(p.ext[-8].name, 'cookie_io_functions_t')
eli.bendersky85d2e732011-05-20 19:47:26 +03001723
1724
1725class TestCParser_typenames(TestCParser_base):
1726 """ Test issues related to the typedef-name problem.
1727 """
1728 def test_innerscope_typedef(self):
1729 # should fail since TT is not a type in bar
1730 s1 = r'''
1731 void foo() {
1732 typedef char TT;
1733 TT x;
1734 }
1735 void bar() {
1736 TT y;
1737 }
1738 '''
1739 self.assertRaises(ParseError, self.parse, s1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001740
eli.bendersky85d2e732011-05-20 19:47:26 +03001741 # should succeed since TT is not a type in bar
1742 s2 = r'''
1743 void foo() {
1744 typedef char TT;
1745 TT x;
1746 }
1747 void bar() {
1748 unsigned TT;
1749 }
1750 '''
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001751 self.assertTrue(isinstance(self.parse(s2), FileAST))
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001752
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001753 def test_innerscope_reuse_typedef_name(self):
1754 # identifiers can be reused in inner scopes; the original should be
1755 # restored at the end of the block
1756 s1 = r'''
1757 typedef char TT;
1758 void foo(void) {
1759 unsigned TT;
1760 TT = 10;
1761 }
1762 TT x = 5;
1763 '''
1764 s1_ast = self.parse(s1)
1765 self.assertEqual(expand_decl(s1_ast.ext[1].body.block_items[0]),
1766 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
Eli Bendersky3877c4c2013-07-13 06:54:04 -07001767 self.assertEqual(expand_decl(s1_ast.ext[2]),
1768 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['TT']]]])
eli.bendersky85d2e732011-05-20 19:47:26 +03001769
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001770 # this should be recognized even with an initializer
1771 s2 = r'''
1772 typedef char TT;
1773 void foo(void) {
1774 unsigned TT = 10;
1775 }
1776 '''
1777 s2_ast = self.parse(s2)
1778 self.assertEqual(expand_decl(s2_ast.ext[1].body.block_items[0]),
1779 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1780
1781 # before the second local variable, TT is a type; after, it's a
1782 # variable
1783 s3 = r'''
1784 typedef char TT;
1785 void foo(void) {
1786 TT tt = sizeof(TT);
1787 unsigned TT = 10;
1788 }
1789 '''
1790 s3_ast = self.parse(s3)
1791 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[0]),
1792 ['Decl', 'tt', ['TypeDecl', ['IdentifierType', ['TT']]]])
1793 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[1]),
1794 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1795
1796 # a variable and its type can even share the same name
1797 s4 = r'''
1798 typedef char TT;
1799 void foo(void) {
1800 TT TT = sizeof(TT);
1801 unsigned uu = TT * 2;
1802 }
1803 '''
1804 s4_ast = self.parse(s4)
1805 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[0]),
1806 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['TT']]]])
1807 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[1]),
1808 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1809
1810 # ensure an error is raised if a type, redeclared as a variable, is
1811 # used as a type
1812 s5 = r'''
1813 typedef char TT;
1814 void foo(void) {
1815 unsigned TT = 10;
1816 TT erroneous = 20;
1817 }
1818 '''
1819 self.assertRaises(ParseError, self.parse, s5)
1820
1821 def test_parameter_reuse_typedef_name(self):
1822 # identifiers can be reused as parameter names; parameter name scope
1823 # begins and ends with the function body; it's important that TT is
Eli Bendersky4d969b32013-07-13 06:07:07 -07001824 # used immediately before the LBRACE or after the RBRACE, to test
1825 # a corner case
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001826 s1 = r'''
1827 typedef char TT;
1828 void foo(unsigned TT, TT bar) {
1829 TT = 10;
1830 }
1831 TT x = 5;
1832 '''
1833 s1_ast = self.parse(s1)
1834 self.assertEqual(expand_decl(s1_ast.ext[1].decl),
1835 ['Decl', 'foo',
1836 ['FuncDecl',
1837 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
1838 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
1839 ['TypeDecl', ['IdentifierType', ['void']]]]])
1840
1841 # the scope of a parameter name in a function declaration ends at the
1842 # end of the declaration...so it is effectively never used; it's
1843 # important that TT is used immediately after the declaration, to
1844 # test a corner case
1845 s2 = r'''
1846 typedef char TT;
1847 void foo(unsigned TT, TT bar);
1848 TT x = 5;
1849 '''
1850 s2_ast = self.parse(s2)
1851 self.assertEqual(expand_decl(s2_ast.ext[1]),
1852 ['Decl', 'foo',
1853 ['FuncDecl',
1854 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
1855 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
1856 ['TypeDecl', ['IdentifierType', ['void']]]]])
1857
1858 # ensure an error is raised if a type, redeclared as a parameter, is
1859 # used as a type
1860 s3 = r'''
1861 typedef char TT;
1862 void foo(unsigned TT, TT bar) {
1863 TT erroneous = 20;
1864 }
1865 '''
1866 self.assertRaises(ParseError, self.parse, s3)
1867
1868 def test_nested_function_decls(self):
1869 # parameter names of nested function declarations must not escape into
1870 # the top-level function _definition's_ scope; the following must
1871 # succeed because TT is still a typedef inside foo's body
1872 s1 = r'''
1873 typedef char TT;
1874 void foo(unsigned bar(int TT)) {
1875 TT x = 10;
1876 }
1877 '''
1878 self.assertTrue(isinstance(self.parse(s1), FileAST))
1879
1880 def test_samescope_reuse_name(self):
1881 # a typedef name cannot be reused as an object name in the same scope
1882 s1 = r'''
1883 typedef char TT;
1884 char TT = 5;
1885 '''
1886 self.assertRaises(ParseError, self.parse, s1)
1887
1888 # ...and vice-versa
1889 s2 = r'''
1890 char TT = 5;
1891 typedef char TT;
1892 '''
1893 self.assertRaises(ParseError, self.parse, s2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001894
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001895
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001896if __name__ == '__main__':
1897 #~ suite = unittest.TestLoader().loadTestsFromNames(
1898 #~ ['test_c_parser.TestCParser_fundamentals.test_typedef'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001899
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001900 #~ unittest.TextTestRunner(verbosity=2).run(suite)
1901 unittest.main()