blob: 2bd43d153c8156205f2179ea42900dc017631066 [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
Manuel Jacob0a15d7d2017-01-12 15:46:05 +0100288 def test_int128(self):
289 self.assertEqual(self.get_decl('__int128 a;'),
290 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['__int128']]]])
291
292
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300293 def test_nested_decls(self): # the fun begins
294 self.assertEqual(self.get_decl('char** ar2D;'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800295 ['Decl', 'ar2D',
296 ['PtrDecl', ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300297 ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800298
299 self.assertEqual(self.get_decl('int (*a)[1][2];'),
300 ['Decl', 'a',
301 ['PtrDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800302 ['ArrayDecl', '1', [],
303 ['ArrayDecl', '2', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300304 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
305
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800306 self.assertEqual(self.get_decl('int *a[1][2];'),
307 ['Decl', 'a',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800308 ['ArrayDecl', '1', [],
309 ['ArrayDecl', '2', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300310 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['int']]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800311
Eli Benderskyb17da152015-04-21 14:35:18 -0700312 self.assertEqual(self.get_decl('char* const* p;'),
313 ['Decl', 'p',
314 ['PtrDecl', ['PtrDecl', ['const'],
315 ['TypeDecl', ['IdentifierType', ['char']]]]]])
316
317 self.assertEqual(self.get_decl('char* * const p;'),
318 ['Decl', 'p',
319 ['PtrDecl', ['const'], ['PtrDecl',
320 ['TypeDecl', ['IdentifierType', ['char']]]]]])
321
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300322 self.assertEqual(self.get_decl('char ***ar3D[40];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800323 ['Decl', 'ar3D',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800324 ['ArrayDecl', '40', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800325 ['PtrDecl', ['PtrDecl', ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300326 ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800327
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300328 self.assertEqual(self.get_decl('char (***ar3D)[40];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800329 ['Decl', 'ar3D',
330 ['PtrDecl', ['PtrDecl', ['PtrDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800331 ['ArrayDecl', '40', [], ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800332
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300333 self.assertEqual(self.get_decl('int (*x[4])(char, int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800334 ['Decl', 'x',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800335 ['ArrayDecl', '4', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800336 ['PtrDecl',
337 ['FuncDecl',
338 [ ['Typename', ['TypeDecl', ['IdentifierType', ['char']]]],
339 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300340 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800341
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300342 self.assertEqual(self.get_decl('char *(*(**foo [][8])())[];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800343 ['Decl', 'foo',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800344 ['ArrayDecl', '', [],
345 ['ArrayDecl', '8', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800346 ['PtrDecl', ['PtrDecl',
347 ['FuncDecl',
348 [],
349 ['PtrDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800350 ['ArrayDecl', '', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800351 ['PtrDecl',
352 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300353 ['IdentifierType', ['char']]]]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800354
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300355 # explore named and unnamed function pointer parameters,
356 # with and without qualifiers
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800357
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300358 # unnamed w/o quals
359 self.assertEqual(self.get_decl('int (*k)(int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800360 ['Decl', 'k',
361 ['PtrDecl',
362 ['FuncDecl',
363 [['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300364 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800365
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300366 # unnamed w/ quals
367 self.assertEqual(self.get_decl('int (*k)(const int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800368 ['Decl', 'k',
369 ['PtrDecl',
370 ['FuncDecl',
371 [['Typename', ['const'], ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300372 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800373
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300374 # named w/o quals
375 self.assertEqual(self.get_decl('int (*k)(int q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800376 ['Decl', 'k',
377 ['PtrDecl',
378 ['FuncDecl',
379 [['Decl', 'q', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300380 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800381
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300382 # named w/ quals
383 self.assertEqual(self.get_decl('int (*k)(const volatile int q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800384 ['Decl', 'k',
385 ['PtrDecl',
386 ['FuncDecl',
387 [['Decl', ['const', 'volatile'], 'q',
388 ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300389 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800390
eli.bendersky79d5cf62010-10-29 13:33:52 +0200391 # restrict qualifier
392 self.assertEqual(self.get_decl('int (*k)(restrict int* q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800393 ['Decl', 'k',
394 ['PtrDecl',
395 ['FuncDecl',
396 [['Decl', ['restrict'], 'q',
eli.bendersky79d5cf62010-10-29 13:33:52 +0200397 ['PtrDecl',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800398 ['TypeDecl', ['IdentifierType', ['int']]]]]],
eli.bendersky79d5cf62010-10-29 13:33:52 +0200399 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800400
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800401 def test_func_decls_with_array_dim_qualifiers(self):
402 self.assertEqual(self.get_decl('int zz(int p[static 10]);'),
403 ['Decl', 'zz',
404 ['FuncDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800405 [['Decl', 'p', ['ArrayDecl', '10', ['static'],
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800406 ['TypeDecl', ['IdentifierType', ['int']]]]]],
407 ['TypeDecl', ['IdentifierType', ['int']]]]])
408
409 self.assertEqual(self.get_decl('int zz(int p[const 10]);'),
410 ['Decl', 'zz',
411 ['FuncDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800412 [['Decl', 'p', ['ArrayDecl', '10', ['const'],
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800413 ['TypeDecl', ['IdentifierType', ['int']]]]]],
414 ['TypeDecl', ['IdentifierType', ['int']]]]])
415
necase4a6afa02014-12-19 16:38:37 -0600416 self.assertEqual(self.get_decl('int zz(int p[restrict][5]);'),
417 ['Decl', 'zz',
418 ['FuncDecl',
419 [['Decl', 'p', ['ArrayDecl', '', ['restrict'],
420 ['ArrayDecl', '5', [],
421 ['TypeDecl', ['IdentifierType', ['int']]]]]]],
422 ['TypeDecl', ['IdentifierType', ['int']]]]])
423
424 self.assertEqual(self.get_decl('int zz(int p[const restrict static 10][5]);'),
425 ['Decl', 'zz',
426 ['FuncDecl',
427 [['Decl', 'p', ['ArrayDecl', '10', ['const', 'restrict', 'static'],
428 ['ArrayDecl', '5', [],
429 ['TypeDecl', ['IdentifierType', ['int']]]]]]],
430 ['TypeDecl', ['IdentifierType', ['int']]]]])
431
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300432 def test_qualifiers_storage_specifiers(self):
433 def assert_qs(txt, index, quals, storage):
434 d = self.parse(txt).ext[index]
435 self.assertEqual(d.quals, quals)
436 self.assertEqual(d.storage, storage)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800437
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300438 assert_qs("extern int p;", 0, [], ['extern'])
439 assert_qs("const long p = 6;", 0, ['const'], [])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800440
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300441 d1 = "static const int p, q, r;"
442 for i in range(3):
443 assert_qs(d1, i, ['const'], ['static'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800444
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300445 d2 = "static char * const p;"
446 assert_qs(d2, 0, [], ['static'])
447 pdecl = self.parse(d2).ext[0].type
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300448 self.assertTrue(isinstance(pdecl, PtrDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300449 self.assertEqual(pdecl.quals, ['const'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800450
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300451 def test_sizeof(self):
452 e = """
453 void foo()
454 {
455 int a = sizeof k;
456 int b = sizeof(int);
eli.benderskyc51e1d32011-02-04 08:52:33 +0200457 int c = sizeof(int**);;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800458
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300459 char* p = "just to make sure this parses w/o error...";
460 int d = sizeof(int());
461 }
462 """
463 compound = self.parse(e).ext[0].body
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800464
eli.benderskyef29ff92010-10-29 16:25:43 +0200465 s1 = compound.block_items[0].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300466 self.assertTrue(isinstance(s1, UnaryOp))
467 self.assertEqual(s1.op, 'sizeof')
468 self.assertTrue(isinstance(s1.expr, ID))
469 self.assertEqual(s1.expr.name, 'k')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800470
eli.benderskyef29ff92010-10-29 16:25:43 +0200471 s2 = compound.block_items[1].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300472 self.assertEqual(expand_decl(s2.expr),
473 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800474
eli.benderskyef29ff92010-10-29 16:25:43 +0200475 s3 = compound.block_items[2].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300476 self.assertEqual(expand_decl(s3.expr),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800477 ['Typename',
478 ['PtrDecl',
479 ['PtrDecl',
480 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300481 ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800482
Eli Benderskye59395b2015-05-09 15:20:46 -0700483 def test_offsetof(self):
484 e = """
485 void foo() {
486 int a = offsetof(struct S, p);
487 a.b = offsetof(struct sockaddr, sp) + strlen(bar);
ksero749650a2016-09-09 07:31:09 +0200488 int a = offsetof(struct S, p.q.r);
489 int a = offsetof(struct S, p[5].q[4][5]);
Eli Benderskye59395b2015-05-09 15:20:46 -0700490 }
491 """
492 compound = self.parse(e).ext[0].body
493 s1 = compound.block_items[0].init
Eli Benderskya71ec1b2015-05-10 06:31:20 -0700494 self.assertTrue(isinstance(s1, FuncCall))
495 self.assertTrue(isinstance(s1.name, ID))
Eli Benderskye59395b2015-05-09 15:20:46 -0700496 self.assertEqual(s1.name.name, 'offsetof')
Eli Benderskya71ec1b2015-05-10 06:31:20 -0700497 self.assertTrue(isinstance(s1.args.exprs[0], Typename))
498 self.assertTrue(isinstance(s1.args.exprs[1], ID))
ksero749650a2016-09-09 07:31:09 +0200499 s3 = compound.block_items[2].init
500 self.assertTrue(isinstance(s3.args.exprs[1], StructRef))
501 s4 = compound.block_items[3].init
502 self.assertTrue(isinstance(s4.args.exprs[1], ArrayRef))
Eli Benderskye59395b2015-05-09 15:20:46 -0700503
Eli Benderskydbf9be22016-10-11 20:44:32 -0700504 def test_compound_statement(self):
505 e = """
506 void foo() {
507 }
508 """
509 compound = self.parse(e).ext[0].body
510 self.assertTrue(isinstance(compound, Compound))
511 self.assert_coord(compound, 2, '')
512
eli.bendersky9f481562010-10-30 15:50:47 +0200513 # The C99 compound literal feature
514 #
eli.benderskyf890a862010-10-30 12:13:23 +0200515 def test_compound_literals(self):
eli.bendersky9f481562010-10-30 15:50:47 +0200516 ps1 = self.parse(r'''
eli.benderskyf890a862010-10-30 12:13:23 +0200517 void foo() {
eli.bendersky9f481562010-10-30 15:50:47 +0200518 p = (long long){k};
519 tc = (struct jk){.a = {1, 2}, .b[0] = t};
520 }''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800521
eli.bendersky9f481562010-10-30 15:50:47 +0200522 compound = ps1.ext[0].body.block_items[0].rvalue
523 self.assertEqual(expand_decl(compound.type),
524 ['Typename', ['TypeDecl', ['IdentifierType', ['long', 'long']]]])
525 self.assertEqual(expand_init(compound.init),
526 [['ID', 'k']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800527
528 compound = ps1.ext[0].body.block_items[1].rvalue
eli.bendersky9f481562010-10-30 15:50:47 +0200529 self.assertEqual(expand_decl(compound.type),
530 ['Typename', ['TypeDecl', ['Struct', 'jk', []]]])
531 self.assertEqual(expand_init(compound.init),
532 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800533 ([['ID', 'a']], [['Constant', 'int', '1'], ['Constant', 'int', '2']]),
eli.bendersky9f481562010-10-30 15:50:47 +0200534 ([['ID', 'b'], ['Constant', 'int', '0']], ['ID', 't'])])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800535
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300536 def test_enums(self):
537 e1 = "enum mycolor op;"
538 e1_type = self.parse(e1).ext[0].type.type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800539
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300540 self.assertTrue(isinstance(e1_type, Enum))
541 self.assertEqual(e1_type.name, 'mycolor')
542 self.assertEqual(e1_type.values, None)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800543
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300544 e2 = "enum mysize {large=20, small, medium} shoes;"
545 e2_type = self.parse(e2).ext[0].type.type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800546
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300547 self.assertTrue(isinstance(e2_type, Enum))
548 self.assertEqual(e2_type.name, 'mysize')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800549
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300550 e2_elist = e2_type.values
551 self.assertTrue(isinstance(e2_elist, EnumeratorList))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800552
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300553 for e2_eval in e2_elist.enumerators:
554 self.assertTrue(isinstance(e2_eval, Enumerator))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800555
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300556 self.assertEqual(e2_elist.enumerators[0].name, 'large')
557 self.assertEqual(e2_elist.enumerators[0].value.value, '20')
558 self.assertEqual(e2_elist.enumerators[2].name, 'medium')
559 self.assertEqual(e2_elist.enumerators[2].value, None)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800560
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300561 # enum with trailing comma (C99 feature)
562 e3 = """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800563 enum
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300564 {
565 red,
566 blue,
567 green,
568 } color;
569 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800570
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300571 e3_type = self.parse(e3).ext[0].type.type
572 self.assertTrue(isinstance(e3_type, Enum))
573 e3_elist = e3_type.values
574 self.assertTrue(isinstance(e3_elist, EnumeratorList))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800575
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300576 for e3_eval in e3_elist.enumerators:
577 self.assertTrue(isinstance(e3_eval, Enumerator))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800578
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300579 self.assertEqual(e3_elist.enumerators[0].name, 'red')
580 self.assertEqual(e3_elist.enumerators[0].value, None)
581 self.assertEqual(e3_elist.enumerators[1].name, 'blue')
582 self.assertEqual(e3_elist.enumerators[2].name, 'green')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800583
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300584 def test_typedef(self):
585 # without typedef, error
586 s1 = """
587 node k;
588 """
589 self.assertRaises(ParseError, self.parse, s1)
590
591 # now with typedef, works
592 s2 = """
593 typedef void* node;
594 node k;
595 """
596 ps2 = self.parse(s2)
597 self.assertEqual(expand_decl(ps2.ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800598 ['Typedef', 'node',
599 ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300600 ['TypeDecl', ['IdentifierType', ['void']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800601
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300602 self.assertEqual(expand_decl(ps2.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800603 ['Decl', 'k',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300604 ['TypeDecl', ['IdentifierType', ['node']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800605
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300606 s3 = """
607 typedef int T;
608 typedef T *pT;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800609
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300610 pT aa, bb;
611 """
612 ps3 = self.parse(s3)
613 self.assertEqual(expand_decl(ps3.ext[3]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800614 ['Decl', 'bb',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300615 ['TypeDecl', ['IdentifierType', ['pT']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800616
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300617 s4 = '''
618 typedef char* __builtin_va_list;
619 typedef __builtin_va_list __gnuc_va_list;
620 '''
621 ps4 = self.parse(s4)
622 self.assertEqual(expand_decl(ps4.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800623 ['Typedef', '__gnuc_va_list',
624 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300625 ['IdentifierType', ['__builtin_va_list']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800626
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300627 s5 = '''typedef struct tagHash Hash;'''
628 ps5 = self.parse(s5)
629 self.assertEqual(expand_decl(ps5.ext[0]),
630 ['Typedef', 'Hash', ['TypeDecl', ['Struct', 'tagHash', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800631
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300632 def test_struct_union(self):
633 s1 = """
634 struct {
635 int id;
636 char* name;
637 } joe;
638 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800639
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300640 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800641 ['Decl', 'joe',
642 ['TypeDecl', ['Struct', None,
643 [ ['Decl', 'id',
644 ['TypeDecl',
645 ['IdentifierType', ['int']]]],
646 ['Decl', 'name',
647 ['PtrDecl',
648 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300649 ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800650
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300651 s2 = """
652 struct node p;
653 """
654 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800655 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300656 ['TypeDecl', ['Struct', 'node', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800657
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300658 s21 = """
659 union pri ra;
660 """
661 self.assertEqual(expand_decl(self.parse(s21).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800662 ['Decl', 'ra',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300663 ['TypeDecl', ['Union', 'pri', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800664
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300665 s3 = """
666 struct node* p;
667 """
668 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800669 ['Decl', 'p',
670 ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300671 ['TypeDecl', ['Struct', 'node', []]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800672
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300673 s4 = """
674 struct node;
675 """
676 self.assertEqual(expand_decl(self.parse(s4).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800677 ['Decl', None,
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300678 ['Struct', 'node', []]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800679
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300680 s5 = """
681 union
682 {
683 struct
684 {
685 int type;
686 } n;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800687
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300688 struct
689 {
690 int type;
691 int intnode;
692 } ni;
693 } u;
694 """
695 self.assertEqual(expand_decl(self.parse(s5).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800696 ['Decl', 'u',
697 ['TypeDecl',
698 ['Union', None,
699 [['Decl', 'n',
700 ['TypeDecl',
701 ['Struct', None,
702 [['Decl', 'type',
703 ['TypeDecl', ['IdentifierType', ['int']]]]]]]],
704 ['Decl', 'ni',
705 ['TypeDecl',
706 ['Struct', None,
707 [['Decl', 'type',
708 ['TypeDecl', ['IdentifierType', ['int']]]],
709 ['Decl', 'intnode',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300710 ['TypeDecl', ['IdentifierType', ['int']]]]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800711
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300712 s6 = """
713 typedef struct foo_tag
714 {
715 void* data;
716 } foo, *pfoo;
717 """
718 s6_ast = self.parse(s6)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800719
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300720 self.assertEqual(expand_decl(s6_ast.ext[0]),
721 ['Typedef', 'foo',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800722 ['TypeDecl',
723 ['Struct', 'foo_tag',
724 [['Decl', 'data',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300725 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800726
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300727 self.assertEqual(expand_decl(s6_ast.ext[1]),
728 ['Typedef', 'pfoo',
729 ['PtrDecl',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800730 ['TypeDecl',
731 ['Struct', 'foo_tag',
732 [['Decl', 'data',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300733 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800734
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300735 s7 = r"""
736 struct _on_exit_args {
737 void * _fnargs[32];
738 void * _dso_handle[32];
739
740 long _fntypes;
741 #line 77 "D:\eli\cpp_stuff\libc_include/sys/reent.h"
742
743 long _is_cxa;
744 };
745 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800746
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300747 s7_ast = self.parse(s7, filename='test.c')
748 self.assert_coord(s7_ast.ext[0].type.decls[2], 6, 'test.c')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800749 self.assert_coord(s7_ast.ext[0].type.decls[3], 78,
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300750 r'D:\eli\cpp_stuff\libc_include/sys/reent.h')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800751
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300752 s8 = """
753 typedef enum tagReturnCode {SUCCESS, FAIL} ReturnCode;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800754
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300755 typedef struct tagEntry
756 {
757 char* key;
758 char* value;
759 } Entry;
760
761
762 typedef struct tagNode
763 {
764 Entry* entry;
765
766 struct tagNode* next;
767 } Node;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800768
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300769 typedef struct tagHash
770 {
771 unsigned int table_size;
772
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800773 Node** heads;
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300774
775 } Hash;
776 """
777 s8_ast = self.parse(s8)
778 self.assertEqual(expand_decl(s8_ast.ext[3]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800779 ['Typedef', 'Hash',
780 ['TypeDecl', ['Struct', 'tagHash',
781 [['Decl', 'table_size',
782 ['TypeDecl', ['IdentifierType', ['unsigned', 'int']]]],
783 ['Decl', 'heads',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300784 ['PtrDecl', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['Node']]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800785
Eli Bendersky95e3b762016-03-19 05:21:59 -0700786 def test_struct_with_extra_semis_inside(self):
787 s1 = """
788 struct {
789 int a;;
790 } foo;
791 """
792 s1_ast = self.parse(s1)
793 self.assertEqual(expand_decl(s1_ast.ext[0]),
794 ['Decl', 'foo',
795 ['TypeDecl', ['Struct', None,
796 [['Decl', 'a',
797 ['TypeDecl', ['IdentifierType', ['int']]]]]]]])
798
799 s2 = """
800 struct {
801 int a;;;;
802 float b, c;
803 ;;
804 char d;
805 } foo;
806 """
807 s2_ast = self.parse(s2)
808 self.assertEqual(expand_decl(s2_ast.ext[0]),
809 ['Decl', 'foo',
810 ['TypeDecl', ['Struct', None,
811 [['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]],
812 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['float']]]],
813 ['Decl', 'c', ['TypeDecl', ['IdentifierType', ['float']]]],
814 ['Decl', 'd',
815 ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
816
eli.bendersky697ecc52011-02-10 07:05:13 +0200817 def test_anonymous_struct_union(self):
818 s1 = """
819 union
820 {
821 union
822 {
823 int i;
824 long l;
825 };
826
827 struct
828 {
829 int type;
830 int intnode;
831 };
832 } u;
833 """
834
835 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
836 ['Decl', 'u',
837 ['TypeDecl',
838 ['Union', None,
839 [['Decl', None,
840 ['Union', None,
841 [['Decl', 'i',
842 ['TypeDecl',
843 ['IdentifierType', ['int']]]],
844 ['Decl', 'l',
845 ['TypeDecl',
846 ['IdentifierType', ['long']]]]]]],
847 ['Decl', None,
848 ['Struct', None,
849 [['Decl', 'type',
850 ['TypeDecl',
851 ['IdentifierType', ['int']]]],
852 ['Decl', 'intnode',
853 ['TypeDecl',
854 ['IdentifierType', ['int']]]]]]]]]]])
855
856 s2 = """
857 struct
858 {
859 int i;
860 union
861 {
862 int id;
863 char* name;
864 };
865 float f;
866 } joe;
867 """
868
869 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
870 ['Decl', 'joe',
871 ['TypeDecl',
872 ['Struct', None,
873 [['Decl', 'i',
874 ['TypeDecl',
875 ['IdentifierType', ['int']]]],
876 ['Decl', None,
877 ['Union', None,
878 [['Decl', 'id',
879 ['TypeDecl',
880 ['IdentifierType', ['int']]]],
881 ['Decl', 'name',
882 ['PtrDecl',
883 ['TypeDecl',
884 ['IdentifierType', ['char']]]]]]]],
885 ['Decl', 'f',
886 ['TypeDecl',
887 ['IdentifierType', ['float']]]]]]]])
888
889 # ISO/IEC 9899:201x Commitee Draft 2010-11-16, N1539
890 # section 6.7.2.1, par. 19, example 1
891 s3 = """
892 struct v {
893 union {
894 struct { int i, j; };
895 struct { long k, l; } w;
896 };
897 int m;
898 } v1;
899 """
900
901 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
902 ['Decl', 'v1',
903 ['TypeDecl',
904 ['Struct', 'v',
905 [['Decl', None,
906 ['Union', None,
907 [['Decl', None,
908 ['Struct', None,
909 [['Decl', 'i',
910 ['TypeDecl',
911 ['IdentifierType', ['int']]]],
912 ['Decl', 'j',
913 ['TypeDecl',
914 ['IdentifierType', ['int']]]]]]],
915 ['Decl', 'w',
916 ['TypeDecl',
917 ['Struct', None,
918 [['Decl', 'k',
919 ['TypeDecl',
920 ['IdentifierType', ['long']]]],
921 ['Decl', 'l',
922 ['TypeDecl',
923 ['IdentifierType', ['long']]]]]]]]]]],
924 ['Decl', 'm',
925 ['TypeDecl',
926 ['IdentifierType', ['int']]]]]]]])
927
eli.benderskydce29a02011-02-10 07:55:00 +0200928 s4 = """
929 struct v {
930 int i;
931 float;
932 } v2;"""
eli.bendersky6b011792011-06-22 17:50:56 +0300933 # just make sure this doesn't raise ParseError
934 self.parse(s4)
eli.benderskydce29a02011-02-10 07:55:00 +0200935
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400936 def test_struct_members_namespace(self):
Eli Bendersky4d969b32013-07-13 06:07:07 -0700937 """ Tests that structure/union member names reside in a separate
938 namespace and can be named after existing types.
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400939 """
940 s1 = """
941 typedef int Name;
942 typedef Name NameArray[10];
943
944 struct {
945 Name Name;
946 Name NameArray[3];
947 } sye;
948
949 void main(void)
950 {
951 sye.Name = 1;
952 }
953 """
954
955 s1_ast = self.parse(s1)
956 self.assertEqual(expand_decl(s1_ast.ext[2]),
957 ['Decl', 'sye',
958 ['TypeDecl', ['Struct', None,
959 [ ['Decl', 'Name',
960 ['TypeDecl',
961 ['IdentifierType', ['Name']]]],
962 ['Decl', 'NameArray',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800963 ['ArrayDecl', '3', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400964 ['TypeDecl', ['IdentifierType', ['Name']]]]]]]]])
965 self.assertEqual(s1_ast.ext[3].body.block_items[0].lvalue.field.name, 'Name')
966
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200967 def test_struct_bitfields(self):
eli.bendersky38ed9a92010-10-09 09:29:59 +0200968 # a struct with two bitfields, one unnamed
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200969 s1 = """
970 struct {
971 int k:6;
972 int :2;
973 } joe;
974 """
975
976 parsed_struct = self.parse(s1).ext[0]
977
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800978 # We can see here the name of the decl for the unnamed bitfield is
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200979 # None, but expand_decl doesn't show bitfield widths
980 # ...
981 self.assertEqual(expand_decl(parsed_struct),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800982 ['Decl', 'joe',
983 ['TypeDecl', ['Struct', None,
984 [ ['Decl', 'k',
985 ['TypeDecl',
986 ['IdentifierType', ['int']]]],
987 ['Decl', None,
988 ['TypeDecl',
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200989 ['IdentifierType', ['int']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800990
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200991 # ...
992 # so we test them manually
993 self.assertEqual(parsed_struct.type.type.decls[0].bitsize.value, '6')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800994 self.assertEqual(parsed_struct.type.type.decls[1].bitsize.value, '2')
995
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300996 def test_tags_namespace(self):
997 """ Tests that the tags of structs/unions/enums reside in a separate namespace and
998 can be named after existing types.
999 """
1000 s1 = """
1001 typedef int tagEntry;
1002
1003 struct tagEntry
1004 {
1005 char* key;
1006 char* value;
1007 } Entry;
1008 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001009
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001010 s1_ast = self.parse(s1)
1011 self.assertEqual(expand_decl(s1_ast.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001012 ['Decl', 'Entry',
1013 ['TypeDecl', ['Struct', 'tagEntry',
1014 [['Decl', 'key',
1015 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
1016 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001017 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001018
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001019 s2 = """
1020 struct tagEntry;
1021
1022 typedef struct tagEntry tagEntry;
1023
1024 struct tagEntry
1025 {
1026 char* key;
1027 char* value;
1028 } Entry;
1029 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001030
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001031 s2_ast = self.parse(s2)
1032 self.assertEqual(expand_decl(s2_ast.ext[2]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001033 ['Decl', 'Entry',
1034 ['TypeDecl', ['Struct', 'tagEntry',
1035 [['Decl', 'key',
1036 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
1037 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001038 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001039
1040 s3 = """
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001041 typedef int mytag;
1042
1043 enum mytag {ABC, CDE};
1044 enum mytag joe;
1045 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001046
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001047 s3_type = self.parse(s3).ext[1].type
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001048
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001049 self.assertTrue(isinstance(s3_type, Enum))
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001050 self.assertEqual(s3_type.name, 'mytag')
1051
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001052 def test_multi_decls(self):
1053 d1 = 'int a, b;'
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001054
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001055 self.assertEqual(self.get_decl(d1, 0),
1056 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
1057 self.assertEqual(self.get_decl(d1, 1),
1058 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['int']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001059
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001060 d2 = 'char* p, notp, ar[4];'
1061 self.assertEqual(self.get_decl(d2, 0),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001062 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001063 ['PtrDecl',
1064 ['TypeDecl', ['IdentifierType', ['char']]]]])
1065 self.assertEqual(self.get_decl(d2, 1),
1066 ['Decl', 'notp', ['TypeDecl', ['IdentifierType', ['char']]]])
1067 self.assertEqual(self.get_decl(d2, 2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001068 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001069 ['ArrayDecl', '4', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001070 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001071
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001072 def test_invalid_multiple_types_error(self):
1073 bad = [
1074 'int enum {ab, cd} fubr;',
1075 'enum kid char brbr;']
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001076
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001077 for b in bad:
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001078 self.assertRaises(ParseError, self.parse, b)
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001079
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001080 def test_duplicate_typedef(self):
1081 """ Tests that redeclarations of existing types are parsed correctly.
1082 This is non-standard, but allowed by many compilers.
1083 """
1084 d1 = '''
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001085 typedef int numbertype;
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001086 typedef int numbertype;
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001087 '''
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001088
1089 self.assertEqual(self.get_decl(d1, 0),
1090 ['Typedef', 'numbertype',
1091 ['TypeDecl', ['IdentifierType', ['int']]]])
1092 self.assertEqual(self.get_decl(d1, 1),
1093 ['Typedef', 'numbertype',
1094 ['TypeDecl', ['IdentifierType', ['int']]]])
1095
1096 d2 = '''
1097 typedef int (*funcptr)(int x);
1098 typedef int (*funcptr)(int x);
1099 '''
1100 self.assertEqual(self.get_decl(d2, 0),
1101 ['Typedef', 'funcptr',
1102 ['PtrDecl', ['FuncDecl',
1103 [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]],
1104 ['TypeDecl', ['IdentifierType', ['int']]]]]])
1105 self.assertEqual(self.get_decl(d2, 1),
1106 ['Typedef', 'funcptr',
1107 ['PtrDecl', ['FuncDecl',
1108 [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]],
1109 ['TypeDecl', ['IdentifierType', ['int']]]]]])
1110
1111 d3 = '''
1112 typedef int numberarray[5];
1113 typedef int numberarray[5];
1114 '''
1115 self.assertEqual(self.get_decl(d3, 0),
1116 ['Typedef', 'numberarray',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001117 ['ArrayDecl', '5', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001118 ['TypeDecl', ['IdentifierType', ['int']]]]])
1119 self.assertEqual(self.get_decl(d3, 1),
1120 ['Typedef', 'numberarray',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001121 ['ArrayDecl', '5', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001122 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001123
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001124 def test_decl_inits(self):
1125 d1 = 'int a = 16;'
eli.benderskyf890a862010-10-30 12:13:23 +02001126 #~ self.parse(d1).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001127 self.assertEqual(self.get_decl(d1),
1128 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
1129 self.assertEqual(self.get_decl_init(d1),
1130 ['Constant', 'int', '16'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001131
Eli Bendersky3b1b08d2012-06-15 12:37:54 +03001132 d1_1 = 'float f = 0xEF.56p1;'
1133 self.assertEqual(self.get_decl_init(d1_1),
1134 ['Constant', 'float', '0xEF.56p1'])
1135
Konstanty Bialkowski3bdbfdc2015-04-19 20:09:21 +10001136 d1_2 = 'int bitmask = 0b1001010;'
1137 self.assertEqual(self.get_decl_init(d1_2),
1138 ['Constant', 'int', '0b1001010'])
1139
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001140 d2 = 'long ar[] = {7, 8, 9};'
1141 self.assertEqual(self.get_decl(d2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001142 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001143 ['ArrayDecl', '', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001144 ['TypeDecl', ['IdentifierType', ['long']]]]])
1145 self.assertEqual(self.get_decl_init(d2),
1146 [ ['Constant', 'int', '7'],
1147 ['Constant', 'int', '8'],
eli.benderskyf890a862010-10-30 12:13:23 +02001148 ['Constant', 'int', '9']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001149
Eli Benderskyc830da82015-05-10 07:56:41 -07001150 d21 = 'long ar[4] = {};'
1151 self.assertEqual(self.get_decl_init(d21), [])
1152
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001153 d3 = 'char p = j;'
1154 self.assertEqual(self.get_decl(d3),
1155 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['char']]]])
1156 self.assertEqual(self.get_decl_init(d3),
1157 ['ID', 'j'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001158
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001159 d4 = "char x = 'c', *p = {0, 1, 2, {4, 5}, 6};"
1160 self.assertEqual(self.get_decl(d4, 0),
1161 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['char']]]])
1162 self.assertEqual(self.get_decl_init(d4, 0),
1163 ['Constant', 'char', "'c'"])
1164 self.assertEqual(self.get_decl(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001165 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001166 ['PtrDecl',
1167 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001168
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001169 self.assertEqual(self.get_decl_init(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001170 [ ['Constant', 'int', '0'],
1171 ['Constant', 'int', '1'],
1172 ['Constant', 'int', '2'],
1173 [['Constant', 'int', '4'],
1174 ['Constant', 'int', '5']],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001175 ['Constant', 'int', '6']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001176
eli.benderskyf890a862010-10-30 12:13:23 +02001177 def test_decl_named_inits(self):
1178 d1 = 'int a = {.k = 16};'
1179 self.assertEqual(self.get_decl_init(d1),
1180 [( [['ID', 'k']],
1181 ['Constant', 'int', '16'])])
1182
1183 d2 = 'int a = { [0].a = {1}, [1].a[0] = 2 };'
1184 self.assertEqual(self.get_decl_init(d2),
1185 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001186 ([['Constant', 'int', '0'], ['ID', 'a']],
1187 [['Constant', 'int', '1']]),
1188 ([['Constant', 'int', '1'], ['ID', 'a'], ['Constant', 'int', '0']],
eli.benderskyf890a862010-10-30 12:13:23 +02001189 ['Constant', 'int', '2'])])
1190
1191 d3 = 'int a = { .a = 1, .c = 3, 4, .b = 5};'
1192 self.assertEqual(self.get_decl_init(d3),
1193 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001194 ([['ID', 'a']], ['Constant', 'int', '1']),
1195 ([['ID', 'c']], ['Constant', 'int', '3']),
1196 ['Constant', 'int', '4'],
eli.benderskyf890a862010-10-30 12:13:23 +02001197 ([['ID', 'b']], ['Constant', 'int', '5'])])
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001198
1199 def test_function_definitions(self):
1200 def parse_fdef(str):
1201 return self.parse(str).ext[0]
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001202
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001203 def fdef_decl(fdef):
1204 return expand_decl(fdef.decl)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001205
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001206 f1 = parse_fdef('''
1207 int factorial(int p)
1208 {
1209 return 3;
1210 }
1211 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001212
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001213 self.assertEqual(fdef_decl(f1),
1214 ['Decl', 'factorial',
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001215 ['FuncDecl',
1216 [['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001217 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001218
eli.benderskyef29ff92010-10-29 16:25:43 +02001219 self.assertEqual(type(f1.body.block_items[0]), Return)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001220
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001221 f2 = parse_fdef('''
1222 char* zzz(int p, char* c)
1223 {
1224 int a;
1225 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001226
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001227 a = b + 2;
1228 return 3;
1229 }
1230 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001231
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001232 self.assertEqual(fdef_decl(f2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001233 ['Decl', 'zzz',
1234 ['FuncDecl',
1235 [ ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]],
1236 ['Decl', 'c', ['PtrDecl',
1237 ['TypeDecl', ['IdentifierType', ['char']]]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001238 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001239
1240 self.assertEqual(list(map(type, f2.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001241 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001242
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001243 f3 = parse_fdef('''
1244 char* zzz(p, c)
1245 long p, *c;
1246 {
1247 int a;
1248 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001249
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001250 a = b + 2;
1251 return 3;
1252 }
1253 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001254
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001255 self.assertEqual(fdef_decl(f3),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001256 ['Decl', 'zzz',
1257 ['FuncDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001258 [ ['ID', 'p'],
1259 ['ID', 'c']],
1260 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001261
1262 self.assertEqual(list(map(type, f3.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001263 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001264
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001265 self.assertEqual(expand_decl(f3.param_decls[0]),
1266 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['long']]]])
1267 self.assertEqual(expand_decl(f3.param_decls[1]),
1268 ['Decl', 'c', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['long']]]]])
1269
Sye van der Veen51a46ec2013-06-10 12:56:15 -04001270 # function return values and parameters may not have type information
1271 f4 = parse_fdef('''
1272 que(p)
1273 {
1274 return 3;
1275 }
1276 ''')
1277
1278 self.assertEqual(fdef_decl(f4),
1279 ['Decl', 'que',
1280 ['FuncDecl',
1281 [['ID', 'p']],
1282 ['TypeDecl', ['IdentifierType', ['int']]]]])
1283
eli.bendersky71540662010-07-03 12:58:52 +02001284 def test_unified_string_literals(self):
1285 # simple string, for reference
1286 d1 = self.get_decl_init('char* s = "hello";')
1287 self.assertEqual(d1, ['Constant', 'string', '"hello"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001288
eli.bendersky71540662010-07-03 12:58:52 +02001289 d2 = self.get_decl_init('char* s = "hello" " world";')
1290 self.assertEqual(d2, ['Constant', 'string', '"hello world"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001291
eli.bendersky71540662010-07-03 12:58:52 +02001292 # the test case from issue 6
1293 d3 = self.parse(r'''
1294 int main() {
1295 fprintf(stderr,
1296 "Wrong Params?\n"
1297 "Usage:\n"
1298 "%s <binary_file_path>\n",
1299 argv[0]
1300 );
1301 }
1302 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001303
eli.bendersky71540662010-07-03 12:58:52 +02001304 self.assertEqual(
eli.benderskyef29ff92010-10-29 16:25:43 +02001305 d3.ext[0].body.block_items[0].args.exprs[1].value,
eli.bendersky71540662010-07-03 12:58:52 +02001306 r'"Wrong Params?\nUsage:\n%s <binary_file_path>\n"')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001307
eli.bendersky4a89f112010-07-05 06:02:03 +02001308 d4 = self.get_decl_init('char* s = "" "foobar";')
1309 self.assertEqual(d4, ['Constant', 'string', '"foobar"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001310
eli.bendersky4a89f112010-07-05 06:02:03 +02001311 d5 = self.get_decl_init(r'char* s = "foo\"" "bar";')
1312 self.assertEqual(d5, ['Constant', 'string', r'"foo\"bar"'])
eli.bendersky71540662010-07-03 12:58:52 +02001313
Eli Benderskyc9f1a382014-03-15 14:12:00 -07001314 def test_unified_wstring_literals(self):
1315 d1 = self.get_decl_init('char* s = L"hello" L"world";')
1316 self.assertEqual(d1, ['Constant', 'string', 'L"helloworld"'])
1317
1318 d2 = self.get_decl_init('char* s = L"hello " L"world" L" and I";')
1319 self.assertEqual(d2, ['Constant', 'string', 'L"hello world and I"'])
1320
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001321 def test_inline_specifier(self):
eli.bendersky79d5cf62010-10-29 13:33:52 +02001322 ps2 = self.parse('static inline void inlinefoo(void);')
1323 self.assertEqual(ps2.ext[0].funcspec, ['inline'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001324
eli.bendersky2e907fa2010-10-29 15:51:07 +02001325 # variable length array
1326 def test_vla(self):
1327 ps2 = self.parse(r'''
1328 int main() {
1329 int size;
1330 int var[size = 5];
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001331
eli.bendersky2e907fa2010-10-29 15:51:07 +02001332 int var2[*];
1333 }
1334 ''')
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001335 self.assertTrue(isinstance(ps2.ext[0].body.block_items[1].type.dim, Assignment))
1336 self.assertTrue(isinstance(ps2.ext[0].body.block_items[2].type.dim, ID))
eli.bendersky79d5cf62010-10-29 13:33:52 +02001337
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001338 def test_pragma(self):
1339 s1 = r'''
1340 #pragma bar
1341 void main() {
1342 #pragma foo
1343 for(;;) {}
Julian Hammer8a174062015-12-14 14:48:16 +01001344 #pragma
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001345 }
1346 '''
1347 s1_ast = self.parse(s1)
1348 self.assertTrue(isinstance(s1_ast.ext[0], Pragma))
1349 self.assertEqual(s1_ast.ext[0].string, 'bar')
Julian Hammer8a174062015-12-14 14:48:16 +01001350 self.assertEqual(s1_ast.ext[0].coord.line, 2)
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001351
1352 self.assertTrue(isinstance(s1_ast.ext[1].body.block_items[0], Pragma))
1353 self.assertEqual(s1_ast.ext[1].body.block_items[0].string, 'foo')
Julian Hammer8a174062015-12-14 14:48:16 +01001354 self.assertEqual(s1_ast.ext[1].body.block_items[0].coord.line, 4)
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001355
Julian Hammer8a174062015-12-14 14:48:16 +01001356 self.assertTrue(isinstance(s1_ast.ext[1].body.block_items[2], Pragma))
1357 self.assertEqual(s1_ast.ext[1].body.block_items[2].string, '')
1358 self.assertEqual(s1_ast.ext[1].body.block_items[2].coord.line, 6)
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001359
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001360
eli.bendersky85d2e732011-05-20 19:47:26 +03001361class TestCParser_whole_code(TestCParser_base):
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001362 """ Testing of parsing whole chunks of code.
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001363
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001364 Since I don't want to rely on the structure of ASTs too
1365 much, most of these tests are implemented with visitors.
1366 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001367 # A simple helper visitor that lists the values of all the
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001368 # Constant nodes it sees.
1369 #
1370 class ConstantVisitor(NodeVisitor):
1371 def __init__(self):
1372 self.values = []
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001373
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001374 def visit_Constant(self, node):
1375 self.values.append(node.value)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001376
1377 # This visitor counts the amount of references to the ID
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001378 # with the name provided to it in the constructor.
1379 #
1380 class IDNameCounter(NodeVisitor):
1381 def __init__(self, name):
1382 self.name = name
1383 self.nrefs = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001384
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001385 def visit_ID(self, node):
1386 if node.name == self.name:
1387 self.nrefs += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001388
1389 # Counts the amount of nodes of a given class
1390 #
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001391 class NodeKlassCounter(NodeVisitor):
1392 def __init__(self, node_klass):
1393 self.klass = node_klass
1394 self.n = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001395
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001396 def generic_visit(self, node):
1397 if node.__class__ == self.klass:
1398 self.n += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001399
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001400 NodeVisitor.generic_visit(self, node)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001401
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001402 def assert_all_Constants(self, code, constants):
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001403 """ Asserts that the list of all Constant values (by
1404 'preorder' appearance) in the chunk of code is as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001405 given.
1406 """
eli.benderskyed890492010-06-25 08:25:55 +03001407 if isinstance(code, str):
1408 parsed = self.parse(code)
1409 else:
1410 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001411
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001412 cv = self.ConstantVisitor()
1413 cv.visit(parsed)
1414 self.assertEqual(cv.values, constants)
1415
1416 def assert_num_ID_refs(self, code, name, num):
1417 """ Asserts the number of references to the ID with
1418 the given name.
1419 """
1420 if isinstance(code, str):
1421 parsed = self.parse(code)
1422 else:
1423 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001424
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001425 iv = self.IDNameCounter(name)
1426 iv.visit(parsed)
1427 self.assertEqual(iv.nrefs, num)
1428
1429 def assert_num_klass_nodes(self, code, klass, num):
1430 """ Asserts the amount of klass nodes in the code.
1431 """
1432 if isinstance(code, str):
1433 parsed = self.parse(code)
1434 else:
1435 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001436
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001437 cv = self.NodeKlassCounter(klass)
1438 cv.visit(parsed)
1439 self.assertEqual(cv.n, num)
1440
1441 def test_expressions(self):
1442 e1 = '''int k = (r + 10.0) >> 6 + 8 << (3 & 0x14);'''
1443 self.assert_all_Constants(e1, ['10.0', '6', '8', '3', '0x14'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001444
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001445 e2 = r'''char n = '\n', *prefix = "st_";'''
1446 self.assert_all_Constants(e2, [r"'\n'", '"st_"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001447
Eli Bendersky09e22a62013-07-02 06:00:36 -07001448 s1 = r'''int main() {
1449 int i = 5, j = 6, k = 1;
1450 if ((i=j && k == 1) || k > j)
1451 printf("Hello, world\n");
1452 return 0;
1453 }'''
1454 ps1 = self.parse(s1)
1455 self.assert_all_Constants(ps1,
1456 ['5', '6', '1', '1', '"Hello, world\\n"', '0'])
1457 self.assert_num_ID_refs(ps1, 'i', 1)
1458 self.assert_num_ID_refs(ps1, 'j', 2)
1459
1460
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001461 def test_statements(self):
1462 s1 = r'''
1463 void foo(){
1464 if (sp == 1)
1465 if (optind >= argc ||
1466 argv[optind][0] != '-' || argv[optind][1] == '\0')
1467 return -1;
1468 else if (strcmp(argv[optind], "--") == 0) {
1469 optind++;
1470 return -1;
1471 }
1472 }
1473 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001474
1475 self.assert_all_Constants(s1,
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001476 ['1', '0', r"'-'", '1', r"'\0'", '1', r'"--"', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001477
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001478 ps1 = self.parse(s1)
1479 self.assert_num_ID_refs(ps1, 'argv', 3)
1480 self.assert_num_ID_refs(ps1, 'optind', 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001481
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001482 self.assert_num_klass_nodes(ps1, If, 3)
1483 self.assert_num_klass_nodes(ps1, Return, 2)
1484 self.assert_num_klass_nodes(ps1, FuncCall, 1) # strcmp
1485 self.assert_num_klass_nodes(ps1, BinaryOp, 7)
1486
1487 # In the following code, Hash and Node were defined as
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001488 # int to pacify the parser that sees they're used as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001489 # types
1490 #
1491 s2 = r'''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001492 typedef int Hash, Node;
1493
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001494 void HashDestroy(Hash* hash)
1495 {
1496 unsigned int i;
1497
1498 if (hash == NULL)
1499 return;
1500
1501 for (i = 0; i < hash->table_size; ++i)
1502 {
1503 Node* temp = hash->heads[i];
1504
1505 while (temp != NULL)
1506 {
1507 Node* temp2 = temp;
1508
1509 free(temp->entry->key);
1510 free(temp->entry->value);
1511 free(temp->entry);
1512
1513 temp = temp->next;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001514
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001515 free(temp2);
1516 }
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001517 }
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001518
1519 free(hash->heads);
1520 hash->heads = NULL;
1521
1522 free(hash);
1523 }
1524 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001525
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001526 ps2 = self.parse(s2)
1527 self.assert_num_klass_nodes(ps2, FuncCall, 6)
1528 self.assert_num_klass_nodes(ps2, FuncDef, 1)
1529 self.assert_num_klass_nodes(ps2, For, 1)
1530 self.assert_num_klass_nodes(ps2, While, 1)
1531 self.assert_num_klass_nodes(ps2, StructRef, 10)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001532
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001533 # declarations don't count
1534 self.assert_num_ID_refs(ps2, 'hash', 6)
1535 self.assert_num_ID_refs(ps2, 'i', 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001536
eli.benderskyed890492010-06-25 08:25:55 +03001537 s3 = r'''
1538 void x(void) {
1539 int a, b;
1540 if (a < b)
1541 do {
1542 a = 0;
1543 } while (0);
1544 else if (a == b) {
1545 a = 1;
1546 }
1547 }
1548 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001549
eli.benderskyed890492010-06-25 08:25:55 +03001550 ps3 = self.parse(s3)
1551 self.assert_num_klass_nodes(ps3, DoWhile, 1)
1552 self.assert_num_ID_refs(ps3, 'a', 4)
1553 self.assert_all_Constants(ps3, ['0', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001554
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001555 def test_empty_statements(self):
eli.bendersky91c0aa32011-10-16 05:50:43 +02001556 s1 = r'''
1557 void foo(void){
1558 ;
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001559 return;;
1560
1561 ;
eli.bendersky91c0aa32011-10-16 05:50:43 +02001562 }
1563 '''
1564 ps1 = self.parse(s1)
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001565 self.assert_num_klass_nodes(ps1, EmptyStatement, 3)
eli.bendersky91c0aa32011-10-16 05:50:43 +02001566 self.assert_num_klass_nodes(ps1, Return, 1)
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001567 self.assert_coord(ps1.ext[0].body.block_items[0], 3, '')
1568 self.assert_coord(ps1.ext[0].body.block_items[1], 4, '')
1569 self.assert_coord(ps1.ext[0].body.block_items[2], 4, '')
1570 self.assert_coord(ps1.ext[0].body.block_items[3], 6, '')
eli.bendersky145890d2010-10-29 12:02:32 +02001571
Ben5cd3fd62012-02-03 06:02:40 +02001572 def test_switch_statement(self):
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001573 def assert_case_node(node, const_value):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001574 self.assertTrue(isinstance(node, Case))
1575 self.assertTrue(isinstance(node.expr, Constant))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001576 self.assertEqual(node.expr.value, const_value)
1577
1578 def assert_default_node(node):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001579 self.assertTrue(isinstance(node, Default))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001580
Ben5cd3fd62012-02-03 06:02:40 +02001581 s1 = r'''
1582 int foo(void) {
1583 switch (myvar) {
1584 case 10:
1585 k = 10;
1586 p = k + 1;
1587 return 10;
1588 case 20:
1589 case 30:
1590 return 20;
1591 default:
1592 break;
1593 }
1594 return 0;
1595 }
1596 '''
1597 ps1 = self.parse(s1)
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001598 switch = ps1.ext[0].body.block_items[0]
1599
1600 block = switch.stmt.block_items
1601 assert_case_node(block[0], '10')
1602 self.assertEqual(len(block[0].stmts), 3)
1603 assert_case_node(block[1], '20')
1604 self.assertEqual(len(block[1].stmts), 0)
1605 assert_case_node(block[2], '30')
1606 self.assertEqual(len(block[2].stmts), 1)
1607 assert_default_node(block[3])
1608
1609 s2 = r'''
1610 int foo(void) {
1611 switch (myvar) {
1612 default:
1613 joe = moe;
1614 return 10;
1615 case 10:
1616 case 20:
1617 case 30:
1618 case 40:
1619 break;
1620 }
1621 return 0;
1622 }
1623 '''
1624 ps2 = self.parse(s2)
1625 switch = ps2.ext[0].body.block_items[0]
1626
1627 block = switch.stmt.block_items
1628 assert_default_node(block[0])
1629 self.assertEqual(len(block[0].stmts), 2)
1630 assert_case_node(block[1], '10')
1631 self.assertEqual(len(block[1].stmts), 0)
1632 assert_case_node(block[2], '20')
1633 self.assertEqual(len(block[1].stmts), 0)
1634 assert_case_node(block[3], '30')
1635 self.assertEqual(len(block[1].stmts), 0)
1636 assert_case_node(block[4], '40')
1637 self.assertEqual(len(block[4].stmts), 1)
Ben5cd3fd62012-02-03 06:02:40 +02001638
eli.bendersky145890d2010-10-29 12:02:32 +02001639 def test_for_statement(self):
1640 s2 = r'''
1641 void x(void)
1642 {
1643 int i;
1644 for (i = 0; i < 5; ++i) {
1645 x = 50;
1646 }
1647 }
1648 '''
1649 ps2 = self.parse(s2)
1650 self.assert_num_klass_nodes(ps2, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001651 # here there are 3 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001652 # a ref in the visitor
1653 #
1654 self.assert_num_ID_refs(ps2, 'i', 3)
Eli Bendersky4476d092012-12-25 14:07:57 -08001655
eli.bendersky145890d2010-10-29 12:02:32 +02001656 s3 = r'''
1657 void x(void)
1658 {
1659 for (int i = 0; i < 5; ++i) {
1660 x = 50;
1661 }
1662 }
1663 '''
1664 ps3 = self.parse(s3)
eli.bendersky145890d2010-10-29 12:02:32 +02001665 self.assert_num_klass_nodes(ps3, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001666 # here there are 2 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001667 # a ref in the visitor
1668 #
1669 self.assert_num_ID_refs(ps3, 'i', 2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001670
Eli Bendersky4476d092012-12-25 14:07:57 -08001671 s4 = r'''
1672 void x(void) {
1673 for (int i = 0;;)
1674 i;
1675 }
1676 '''
1677 ps4 = self.parse(s4)
1678 self.assert_num_ID_refs(ps4, 'i', 1)
1679
Eli Benderskyd0973782012-01-19 08:09:33 +02001680 def _open_c_file(self, name):
1681 """ Find a c file by name, taking into account the current dir can be
1682 in a couple of typical places
1683 """
Stefano Riveraebaf5922013-08-08 09:45:26 +02001684 testdir = os.path.dirname(__file__)
1685 name = os.path.join(testdir, 'c_files', name)
1686 assert os.path.exists(name)
1687 return open(name, 'rU')
Eli Benderskyd0973782012-01-19 08:09:33 +02001688
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001689 def test_whole_file(self):
1690 # See how pycparser handles a whole, real C file.
1691 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001692 with self._open_c_file('memmgr_with_h.c') as f:
1693 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001694 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001695
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001696 self.assert_num_klass_nodes(p, FuncDef, 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001697
1698 # each FuncDef also has a FuncDecl. 4 declarations
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001699 # + 5 definitions, overall 9
1700 self.assert_num_klass_nodes(p, FuncDecl, 9)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001701
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001702 self.assert_num_klass_nodes(p, Typedef, 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001703
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001704 self.assertEqual(p.ext[4].coord.line, 88)
1705 self.assertEqual(p.ext[4].coord.file, "./memmgr.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001706
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001707 self.assertEqual(p.ext[6].coord.line, 10)
1708 self.assertEqual(p.ext[6].coord.file, "memmgr.c")
1709
1710 def test_whole_file_with_stdio(self):
1711 # Parse a whole file with stdio.h included by cpp
1712 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001713 with self._open_c_file('cppd_with_stdio_h.c') as f:
1714 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001715 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001716
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001717 self.assertTrue(isinstance(p.ext[0], Typedef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001718 self.assertEqual(p.ext[0].coord.line, 213)
1719 self.assertEqual(p.ext[0].coord.file, "D:\eli\cpp_stuff\libc_include/stddef.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001720
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001721 self.assertTrue(isinstance(p.ext[-1], FuncDef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001722 self.assertEqual(p.ext[-1].coord.line, 15)
1723 self.assertEqual(p.ext[-1].coord.file, "example_c_file.c")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001724
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001725 self.assertTrue(isinstance(p.ext[-8], Typedef))
1726 self.assertTrue(isinstance(p.ext[-8].type, TypeDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001727 self.assertEqual(p.ext[-8].name, 'cookie_io_functions_t')
eli.bendersky85d2e732011-05-20 19:47:26 +03001728
1729
1730class TestCParser_typenames(TestCParser_base):
1731 """ Test issues related to the typedef-name problem.
1732 """
1733 def test_innerscope_typedef(self):
1734 # should fail since TT is not a type in bar
1735 s1 = r'''
1736 void foo() {
1737 typedef char TT;
1738 TT x;
1739 }
1740 void bar() {
1741 TT y;
1742 }
1743 '''
1744 self.assertRaises(ParseError, self.parse, s1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001745
eli.bendersky85d2e732011-05-20 19:47:26 +03001746 # should succeed since TT is not a type in bar
1747 s2 = r'''
1748 void foo() {
1749 typedef char TT;
1750 TT x;
1751 }
1752 void bar() {
1753 unsigned TT;
1754 }
1755 '''
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001756 self.assertTrue(isinstance(self.parse(s2), FileAST))
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001757
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001758 def test_innerscope_reuse_typedef_name(self):
1759 # identifiers can be reused in inner scopes; the original should be
1760 # restored at the end of the block
1761 s1 = r'''
1762 typedef char TT;
1763 void foo(void) {
1764 unsigned TT;
1765 TT = 10;
1766 }
1767 TT x = 5;
1768 '''
1769 s1_ast = self.parse(s1)
1770 self.assertEqual(expand_decl(s1_ast.ext[1].body.block_items[0]),
1771 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
Eli Bendersky3877c4c2013-07-13 06:54:04 -07001772 self.assertEqual(expand_decl(s1_ast.ext[2]),
1773 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['TT']]]])
eli.bendersky85d2e732011-05-20 19:47:26 +03001774
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001775 # this should be recognized even with an initializer
1776 s2 = r'''
1777 typedef char TT;
1778 void foo(void) {
1779 unsigned TT = 10;
1780 }
1781 '''
1782 s2_ast = self.parse(s2)
1783 self.assertEqual(expand_decl(s2_ast.ext[1].body.block_items[0]),
1784 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1785
1786 # before the second local variable, TT is a type; after, it's a
1787 # variable
1788 s3 = r'''
1789 typedef char TT;
1790 void foo(void) {
1791 TT tt = sizeof(TT);
1792 unsigned TT = 10;
1793 }
1794 '''
1795 s3_ast = self.parse(s3)
1796 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[0]),
1797 ['Decl', 'tt', ['TypeDecl', ['IdentifierType', ['TT']]]])
1798 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[1]),
1799 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1800
1801 # a variable and its type can even share the same name
1802 s4 = r'''
1803 typedef char TT;
1804 void foo(void) {
1805 TT TT = sizeof(TT);
1806 unsigned uu = TT * 2;
1807 }
1808 '''
1809 s4_ast = self.parse(s4)
1810 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[0]),
1811 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['TT']]]])
1812 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[1]),
1813 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1814
1815 # ensure an error is raised if a type, redeclared as a variable, is
1816 # used as a type
1817 s5 = r'''
1818 typedef char TT;
1819 void foo(void) {
1820 unsigned TT = 10;
1821 TT erroneous = 20;
1822 }
1823 '''
1824 self.assertRaises(ParseError, self.parse, s5)
1825
1826 def test_parameter_reuse_typedef_name(self):
1827 # identifiers can be reused as parameter names; parameter name scope
1828 # begins and ends with the function body; it's important that TT is
Eli Bendersky4d969b32013-07-13 06:07:07 -07001829 # used immediately before the LBRACE or after the RBRACE, to test
1830 # a corner case
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001831 s1 = r'''
1832 typedef char TT;
1833 void foo(unsigned TT, TT bar) {
1834 TT = 10;
1835 }
1836 TT x = 5;
1837 '''
1838 s1_ast = self.parse(s1)
1839 self.assertEqual(expand_decl(s1_ast.ext[1].decl),
1840 ['Decl', 'foo',
1841 ['FuncDecl',
1842 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
1843 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
1844 ['TypeDecl', ['IdentifierType', ['void']]]]])
1845
1846 # the scope of a parameter name in a function declaration ends at the
1847 # end of the declaration...so it is effectively never used; it's
1848 # important that TT is used immediately after the declaration, to
1849 # test a corner case
1850 s2 = r'''
1851 typedef char TT;
1852 void foo(unsigned TT, TT bar);
1853 TT x = 5;
1854 '''
1855 s2_ast = self.parse(s2)
1856 self.assertEqual(expand_decl(s2_ast.ext[1]),
1857 ['Decl', 'foo',
1858 ['FuncDecl',
1859 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
1860 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
1861 ['TypeDecl', ['IdentifierType', ['void']]]]])
1862
1863 # ensure an error is raised if a type, redeclared as a parameter, is
1864 # used as a type
1865 s3 = r'''
1866 typedef char TT;
1867 void foo(unsigned TT, TT bar) {
1868 TT erroneous = 20;
1869 }
1870 '''
1871 self.assertRaises(ParseError, self.parse, s3)
1872
1873 def test_nested_function_decls(self):
1874 # parameter names of nested function declarations must not escape into
1875 # the top-level function _definition's_ scope; the following must
1876 # succeed because TT is still a typedef inside foo's body
1877 s1 = r'''
1878 typedef char TT;
1879 void foo(unsigned bar(int TT)) {
1880 TT x = 10;
1881 }
1882 '''
1883 self.assertTrue(isinstance(self.parse(s1), FileAST))
1884
1885 def test_samescope_reuse_name(self):
1886 # a typedef name cannot be reused as an object name in the same scope
1887 s1 = r'''
1888 typedef char TT;
1889 char TT = 5;
1890 '''
1891 self.assertRaises(ParseError, self.parse, s1)
1892
1893 # ...and vice-versa
1894 s2 = r'''
1895 char TT = 5;
1896 typedef char TT;
1897 '''
1898 self.assertRaises(ParseError, self.parse, s2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001899
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001900
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001901if __name__ == '__main__':
1902 #~ suite = unittest.TestLoader().loadTestsFromNames(
1903 #~ ['test_c_parser.TestCParser_fundamentals.test_typedef'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001904
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001905 #~ unittest.TextTestRunner(verbosity=2).run(suite)
1906 unittest.main()