blob: 9dfb132fb4fd1be838e3622df144f86982cc1cf2 [file] [log] [blame]
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001#!/usr/bin/env python
2
3import pprint
4import re
Eli Benderskyd0973782012-01-19 08:09:33 +02005import os, sys
Eli Bendersky3921e8e2010-05-21 09:05:39 +03006import unittest
7
Eli Bendersky3877c4c2013-07-13 06:54:04 -07008sys.path[0:0] = ['.', '..']
Eli Bendersky3921e8e2010-05-21 09:05:39 +03009
10from pycparser import c_parser
11from pycparser.c_ast import *
12from pycparser.c_parser import CParser, Coord, ParseError
13
Eli Bendersky3921e8e2010-05-21 09:05:39 +030014_c_parser = c_parser.CParser(
15 lex_optimize=False,
Eli Bendersky86f2eee2013-01-18 06:04:01 -080016 yacc_debug=True,
Eli Bendersky3921e8e2010-05-21 09:05:39 +030017 yacc_optimize=False,
18 yacctab='yacctab')
19
20
21def expand_decl(decl):
22 """ Converts the declaration into a nested list.
23 """
24 typ = type(decl)
Eli Bendersky86f2eee2013-01-18 06:04:01 -080025
Eli Bendersky3921e8e2010-05-21 09:05:39 +030026 if typ == TypeDecl:
27 return ['TypeDecl', expand_decl(decl.type)]
28 elif typ == IdentifierType:
29 return ['IdentifierType', decl.names]
30 elif typ == ID:
31 return ['ID', decl.name]
32 elif typ in [Struct, Union]:
33 decls = [expand_decl(d) for d in decl.decls or []]
34 return [typ.__name__, decl.name, decls]
Eli Bendersky86f2eee2013-01-18 06:04:01 -080035 else:
Eli Bendersky3921e8e2010-05-21 09:05:39 +030036 nested = expand_decl(decl.type)
Eli Bendersky86f2eee2013-01-18 06:04:01 -080037
Eli Bendersky3921e8e2010-05-21 09:05:39 +030038 if typ == Decl:
39 if decl.quals:
40 return ['Decl', decl.quals, decl.name, nested]
41 else:
42 return ['Decl', decl.name, nested]
43 elif typ == Typename: # for function parameters
44 if decl.quals:
45 return ['Typename', decl.quals, nested]
46 else:
47 return ['Typename', nested]
48 elif typ == ArrayDecl:
49 dimval = decl.dim.value if decl.dim else ''
Eli Bendersky8aad3182014-01-25 06:30:53 -080050 return ['ArrayDecl', dimval, decl.dim_quals, nested]
Eli Bendersky3921e8e2010-05-21 09:05:39 +030051 elif typ == PtrDecl:
Eli Benderskyb17da152015-04-21 14:35:18 -070052 if decl.quals:
53 return ['PtrDecl', decl.quals, nested]
54 else:
55 return ['PtrDecl', nested]
Eli Bendersky3921e8e2010-05-21 09:05:39 +030056 elif typ == Typedef:
57 return ['Typedef', decl.name, nested]
58 elif typ == FuncDecl:
59 if decl.args:
60 params = [expand_decl(param) for param in decl.args.params]
61 else:
62 params = []
63 return ['FuncDecl', params, nested]
Eli Bendersky86f2eee2013-01-18 06:04:01 -080064
Eli Bendersky3921e8e2010-05-21 09:05:39 +030065
66def expand_init(init):
67 """ Converts an initialization into a nested list
68 """
69 typ = type(init)
Eli Bendersky86f2eee2013-01-18 06:04:01 -080070
eli.benderskyf890a862010-10-30 12:13:23 +020071 if typ == NamedInitializer:
72 des = [expand_init(dp) for dp in init.name]
73 return (des, expand_init(init.expr))
Eli Bendersky293ea912012-12-25 14:52:48 -080074 elif typ in (InitList, ExprList):
eli.benderskyf890a862010-10-30 12:13:23 +020075 return [expand_init(expr) for expr in init.exprs]
76 elif typ == Constant:
Eli Bendersky3921e8e2010-05-21 09:05:39 +030077 return ['Constant', init.type, init.value]
78 elif typ == ID:
79 return ['ID', init.name]
Nate Bogdanowicz14b8a7e2017-02-22 08:54:05 -050080 elif typ == UnaryOp:
81 return ['UnaryOp', init.op, expand_decl(init.expr)]
Eli Bendersky3921e8e2010-05-21 09:05:39 +030082
83
eli.bendersky85d2e732011-05-20 19:47:26 +030084class TestCParser_base(unittest.TestCase):
Eli Bendersky3921e8e2010-05-21 09:05:39 +030085 def parse(self, txt, filename=''):
86 return self.cparser.parse(txt, filename)
Eli Bendersky86f2eee2013-01-18 06:04:01 -080087
Eli Bendersky3921e8e2010-05-21 09:05:39 +030088 def setUp(self):
89 self.cparser = _c_parser
Eli Bendersky86f2eee2013-01-18 06:04:01 -080090
serpilliere471442f2017-03-10 15:02:00 +010091 def assert_coord(self, node, line, column=None, file=None):
Eli Benderskyb77d6c02016-10-11 20:33:53 -070092 self.assertEqual(node.coord.line, line)
serpilliere471442f2017-03-10 15:02:00 +010093 if column is not None:
94 self.assertEqual(node.coord.column, column)
Eli Benderskyb77d6c02016-10-11 20:33:53 -070095 if file:
96 self.assertEqual(node.coord.file, file)
97
eli.bendersky85d2e732011-05-20 19:47:26 +030098
serpilliere471442f2017-03-10 15:02:00 +010099
eli.bendersky85d2e732011-05-20 19:47:26 +0300100class TestCParser_fundamentals(TestCParser_base):
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300101 def get_decl(self, txt, index=0):
102 """ Given a source and an index returns the expanded
103 declaration at that index.
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800104
105 FileAST holds a list of 'external declarations'.
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300106 index is the offset of the desired declaration in that
107 list.
108 """
109 t = self.parse(txt).ext[index]
110 return expand_decl(t)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800111
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300112 def get_decl_init(self, txt, index=0):
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800113 """ Returns the expanded initializer of the declaration
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300114 at index.
115 """
116 t = self.parse(txt).ext[index]
117 return expand_init(t.init)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800118
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300119 def test_FileAST(self):
120 t = self.parse('int a; char c;')
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300121 self.assertTrue(isinstance(t, FileAST))
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300122 self.assertEqual(len(t.ext), 2)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800123
eli.bendersky43cf0b22011-10-19 05:56:15 +0200124 # empty file
125 t2 = self.parse('')
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300126 self.assertTrue(isinstance(t2, FileAST))
eli.bendersky43cf0b22011-10-19 05:56:15 +0200127 self.assertEqual(len(t2.ext), 0)
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300128
eli.bendersky38165b72011-02-04 08:13:39 +0200129 def test_empty_toplevel_decl(self):
130 code = 'int foo;;'
131 t = self.parse(code)
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300132 self.assertTrue(isinstance(t, FileAST))
eli.bendersky38165b72011-02-04 08:13:39 +0200133 self.assertEqual(len(t.ext), 1)
134 self.assertEqual(self.get_decl(code),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800135 ['Decl', 'foo',
eli.bendersky38165b72011-02-04 08:13:39 +0200136 ['TypeDecl', ['IdentifierType', ['int']]]])
137
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300138 def test_coords(self):
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800139 """ Tests the "coordinates" of parsed elements - file
serpilliere471442f2017-03-10 15:02:00 +0100140 name, line and column numbers, with modification
141 insterted by #line directives.
eli.bendersky38165b72011-02-04 08:13:39 +0200142 """
serpilliere471442f2017-03-10 15:02:00 +0100143 self.assert_coord(self.parse('int a;').ext[0], 1, 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800144
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300145 t1 = """
146 int a;
147 int b;\n\n
148 int c;
149 """
150 f1 = self.parse(t1, filename='test.c')
serpilliere471442f2017-03-10 15:02:00 +0100151 self.assert_coord(f1.ext[0], 2, 13, 'test.c')
152 self.assert_coord(f1.ext[1], 3, 13, 'test.c')
153 self.assert_coord(f1.ext[2], 6, 13, 'test.c')
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300154
155 t1_1 = '''
156 int main() {
157 k = p;
158 printf("%d", b);
159 return 0;
160 }'''
161 f1_1 = self.parse(t1_1, filename='test.c')
serpilliere471442f2017-03-10 15:02:00 +0100162 self.assert_coord(f1_1.ext[0].body.block_items[0], 3, 13, 'test.c')
163 self.assert_coord(f1_1.ext[0].body.block_items[1], 4, 13, 'test.c')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800164
eli.benderskyfc96e5e2011-03-04 09:51:23 +0200165 t1_2 = '''
166 int main () {
167 int p = (int) k;
168 }'''
169 f1_2 = self.parse(t1_2, filename='test.c')
170 # make sure that the Cast has a coord (issue 23)
serpilliere471442f2017-03-10 15:02:00 +0100171 self.assert_coord(f1_2.ext[0].body.block_items[0].init, 3, 21, file='test.c')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800172
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300173 t2 = """
174 #line 99
175 int c;
176 """
serpilliere471442f2017-03-10 15:02:00 +0100177 self.assert_coord(self.parse(t2).ext[0], 99, 13)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800178
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300179 t3 = """
180 int dsf;
181 char p;
182 #line 3000 "in.h"
183 char d;
184 """
185 f3 = self.parse(t3, filename='test.c')
serpilliere471442f2017-03-10 15:02:00 +0100186 self.assert_coord(f3.ext[0], 2, 13, 'test.c')
187 self.assert_coord(f3.ext[1], 3, 14, 'test.c')
188 self.assert_coord(f3.ext[2], 3000, 14, 'in.h')
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300189
190 t4 = """
191 #line 20 "restore.h"
192 int maydler(char);
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800193
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300194 #line 30 "includes/daween.ph"
195 long j, k;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800196
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300197 #line 50000
198 char* ro;
199 """
200 f4 = self.parse(t4, filename='myb.c')
serpilliere471442f2017-03-10 15:02:00 +0100201 self.assert_coord(f4.ext[0], 20, 13, 'restore.h')
202 self.assert_coord(f4.ext[1], 30, 14, 'includes/daween.ph')
203 self.assert_coord(f4.ext[2], 30, 17, 'includes/daween.ph')
204 self.assert_coord(f4.ext[3], 50000, 13, 'includes/daween.ph')
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300205
206 t5 = """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800207 int
208 #line 99
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300209 c;
210 """
serpilliere471442f2017-03-10 15:02:00 +0100211 self.assert_coord(self.parse(t5).ext[0], 99, 9)
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300212
Eli Bendersky203b9672012-06-15 10:11:24 +0300213 # coord for ellipsis
214 t6 = """
215 int foo(int j,
216 ...) {
217 }"""
218 f6 = self.parse(t6, filename='z.c')
serpilliere471442f2017-03-10 15:02:00 +0100219 self.assert_coord(self.parse(t6).ext[0].decl.type.args.params[1], 3, 17)
Eli Bendersky203b9672012-06-15 10:11:24 +0300220
Eli Bendersky8e5d3a92014-03-15 14:06:00 -0700221 def test_forloop_coord(self):
222 t = '''\
223 void foo() {
224 for(int z=0; z<4;
225 z++){}
226 }
227 '''
228 s = self.parse(t, filename='f.c')
229 forloop = s.ext[0].body.block_items[0]
serpilliere471442f2017-03-10 15:02:00 +0100230 self.assert_coord(forloop.init, 2, 13, 'f.c')
231 self.assert_coord(forloop.cond, 2, 26, 'f.c')
232 self.assert_coord(forloop.next, 3, 17, 'f.c')
Eli Bendersky8e5d3a92014-03-15 14:06:00 -0700233
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300234 def test_simple_decls(self):
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800235 self.assertEqual(self.get_decl('int a;'),
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300236 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
237
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800238 self.assertEqual(self.get_decl('unsigned int a;'),
Eli Bendersky68497c22012-01-19 06:04:58 +0200239 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['unsigned', 'int']]]])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300240
eli.benderskyaffe0322011-09-24 06:16:55 +0300241 self.assertEqual(self.get_decl('_Bool a;'),
242 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['_Bool']]]])
243
Eli Benderskyf4d73462012-01-19 05:56:27 +0200244 self.assertEqual(self.get_decl('float _Complex fcc;'),
Eli Bendersky68497c22012-01-19 06:04:58 +0200245 ['Decl', 'fcc', ['TypeDecl', ['IdentifierType', ['float', '_Complex']]]])
Eli Benderskyf4d73462012-01-19 05:56:27 +0200246
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800247 self.assertEqual(self.get_decl('char* string;'),
248 ['Decl', 'string',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300249 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]])
250
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800251 self.assertEqual(self.get_decl('long ar[15];'),
252 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800253 ['ArrayDecl', '15', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300254 ['TypeDecl', ['IdentifierType', ['long']]]]])
eli.bendersky98f45372010-10-30 09:46:29 +0200255
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800256 self.assertEqual(self.get_decl('long long ar[15];'),
257 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800258 ['ArrayDecl', '15', [],
eli.benderskyf890a862010-10-30 12:13:23 +0200259 ['TypeDecl', ['IdentifierType', ['long', 'long']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800260
261 self.assertEqual(self.get_decl('unsigned ar[];'),
262 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800263 ['ArrayDecl', '', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300264 ['TypeDecl', ['IdentifierType', ['unsigned']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800265
266 self.assertEqual(self.get_decl('int strlen(char* s);'),
267 ['Decl', 'strlen',
268 ['FuncDecl',
269 [['Decl', 's',
270 ['PtrDecl',
271 ['TypeDecl', ['IdentifierType', ['char']]]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300272 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800273
274 self.assertEqual(self.get_decl('int strcmp(char* s1, char* s2);'),
275 ['Decl', 'strcmp',
276 ['FuncDecl',
277 [ ['Decl', 's1',
278 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
279 ['Decl', 's2',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300280 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800281 ],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300282 ['TypeDecl', ['IdentifierType', ['int']]]]])
283
Sye van der Veen51a46ec2013-06-10 12:56:15 -0400284 # function return values and parameters may not have type information
Eli Bendersky09e22a62013-07-02 06:00:36 -0700285 self.assertEqual(self.get_decl('extern foobar(foo, bar);'),
286 ['Decl', 'foobar',
287 ['FuncDecl',
Sye van der Veen51a46ec2013-06-10 12:56:15 -0400288 [ ['ID', 'foo'],
289 ['ID', 'bar']
Eli Bendersky09e22a62013-07-02 06:00:36 -0700290 ],
Sye van der Veen51a46ec2013-06-10 12:56:15 -0400291 ['TypeDecl', ['IdentifierType', ['int']]]]])
292
Manuel Jacob0a15d7d2017-01-12 15:46:05 +0100293 def test_int128(self):
294 self.assertEqual(self.get_decl('__int128 a;'),
295 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['__int128']]]])
296
297
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300298 def test_nested_decls(self): # the fun begins
299 self.assertEqual(self.get_decl('char** ar2D;'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800300 ['Decl', 'ar2D',
301 ['PtrDecl', ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300302 ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800303
304 self.assertEqual(self.get_decl('int (*a)[1][2];'),
305 ['Decl', 'a',
306 ['PtrDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800307 ['ArrayDecl', '1', [],
308 ['ArrayDecl', '2', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300309 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
310
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800311 self.assertEqual(self.get_decl('int *a[1][2];'),
312 ['Decl', 'a',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800313 ['ArrayDecl', '1', [],
314 ['ArrayDecl', '2', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300315 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['int']]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800316
Eli Benderskyb17da152015-04-21 14:35:18 -0700317 self.assertEqual(self.get_decl('char* const* p;'),
318 ['Decl', 'p',
319 ['PtrDecl', ['PtrDecl', ['const'],
320 ['TypeDecl', ['IdentifierType', ['char']]]]]])
321
322 self.assertEqual(self.get_decl('char* * const p;'),
323 ['Decl', 'p',
324 ['PtrDecl', ['const'], ['PtrDecl',
325 ['TypeDecl', ['IdentifierType', ['char']]]]]])
326
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300327 self.assertEqual(self.get_decl('char ***ar3D[40];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800328 ['Decl', 'ar3D',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800329 ['ArrayDecl', '40', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800330 ['PtrDecl', ['PtrDecl', ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300331 ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800332
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300333 self.assertEqual(self.get_decl('char (***ar3D)[40];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800334 ['Decl', 'ar3D',
335 ['PtrDecl', ['PtrDecl', ['PtrDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800336 ['ArrayDecl', '40', [], ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800337
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300338 self.assertEqual(self.get_decl('int (*x[4])(char, int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800339 ['Decl', 'x',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800340 ['ArrayDecl', '4', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800341 ['PtrDecl',
342 ['FuncDecl',
343 [ ['Typename', ['TypeDecl', ['IdentifierType', ['char']]]],
344 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300345 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800346
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300347 self.assertEqual(self.get_decl('char *(*(**foo [][8])())[];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800348 ['Decl', 'foo',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800349 ['ArrayDecl', '', [],
350 ['ArrayDecl', '8', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800351 ['PtrDecl', ['PtrDecl',
352 ['FuncDecl',
353 [],
354 ['PtrDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800355 ['ArrayDecl', '', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800356 ['PtrDecl',
357 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300358 ['IdentifierType', ['char']]]]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800359
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300360 # explore named and unnamed function pointer parameters,
361 # with and without qualifiers
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800362
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300363 # unnamed w/o quals
364 self.assertEqual(self.get_decl('int (*k)(int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800365 ['Decl', 'k',
366 ['PtrDecl',
367 ['FuncDecl',
368 [['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300369 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800370
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300371 # unnamed w/ quals
372 self.assertEqual(self.get_decl('int (*k)(const int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800373 ['Decl', 'k',
374 ['PtrDecl',
375 ['FuncDecl',
376 [['Typename', ['const'], ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300377 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800378
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300379 # named w/o quals
380 self.assertEqual(self.get_decl('int (*k)(int q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800381 ['Decl', 'k',
382 ['PtrDecl',
383 ['FuncDecl',
384 [['Decl', 'q', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300385 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800386
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300387 # named w/ quals
388 self.assertEqual(self.get_decl('int (*k)(const volatile int q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800389 ['Decl', 'k',
390 ['PtrDecl',
391 ['FuncDecl',
392 [['Decl', ['const', 'volatile'], 'q',
393 ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300394 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800395
eli.bendersky79d5cf62010-10-29 13:33:52 +0200396 # restrict qualifier
397 self.assertEqual(self.get_decl('int (*k)(restrict int* q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800398 ['Decl', 'k',
399 ['PtrDecl',
400 ['FuncDecl',
401 [['Decl', ['restrict'], 'q',
eli.bendersky79d5cf62010-10-29 13:33:52 +0200402 ['PtrDecl',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800403 ['TypeDecl', ['IdentifierType', ['int']]]]]],
eli.bendersky79d5cf62010-10-29 13:33:52 +0200404 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800405
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800406 def test_func_decls_with_array_dim_qualifiers(self):
407 self.assertEqual(self.get_decl('int zz(int p[static 10]);'),
408 ['Decl', 'zz',
409 ['FuncDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800410 [['Decl', 'p', ['ArrayDecl', '10', ['static'],
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800411 ['TypeDecl', ['IdentifierType', ['int']]]]]],
412 ['TypeDecl', ['IdentifierType', ['int']]]]])
413
414 self.assertEqual(self.get_decl('int zz(int p[const 10]);'),
415 ['Decl', 'zz',
416 ['FuncDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800417 [['Decl', 'p', ['ArrayDecl', '10', ['const'],
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800418 ['TypeDecl', ['IdentifierType', ['int']]]]]],
419 ['TypeDecl', ['IdentifierType', ['int']]]]])
420
necase4a6afa02014-12-19 16:38:37 -0600421 self.assertEqual(self.get_decl('int zz(int p[restrict][5]);'),
422 ['Decl', 'zz',
423 ['FuncDecl',
424 [['Decl', 'p', ['ArrayDecl', '', ['restrict'],
425 ['ArrayDecl', '5', [],
426 ['TypeDecl', ['IdentifierType', ['int']]]]]]],
427 ['TypeDecl', ['IdentifierType', ['int']]]]])
428
429 self.assertEqual(self.get_decl('int zz(int p[const restrict static 10][5]);'),
430 ['Decl', 'zz',
431 ['FuncDecl',
432 [['Decl', 'p', ['ArrayDecl', '10', ['const', 'restrict', 'static'],
433 ['ArrayDecl', '5', [],
434 ['TypeDecl', ['IdentifierType', ['int']]]]]]],
435 ['TypeDecl', ['IdentifierType', ['int']]]]])
436
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300437 def test_qualifiers_storage_specifiers(self):
438 def assert_qs(txt, index, quals, storage):
439 d = self.parse(txt).ext[index]
440 self.assertEqual(d.quals, quals)
441 self.assertEqual(d.storage, storage)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800442
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300443 assert_qs("extern int p;", 0, [], ['extern'])
444 assert_qs("const long p = 6;", 0, ['const'], [])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800445
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300446 d1 = "static const int p, q, r;"
447 for i in range(3):
448 assert_qs(d1, i, ['const'], ['static'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800449
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300450 d2 = "static char * const p;"
451 assert_qs(d2, 0, [], ['static'])
452 pdecl = self.parse(d2).ext[0].type
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300453 self.assertTrue(isinstance(pdecl, PtrDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300454 self.assertEqual(pdecl.quals, ['const'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800455
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300456 def test_sizeof(self):
457 e = """
458 void foo()
459 {
460 int a = sizeof k;
461 int b = sizeof(int);
eli.benderskyc51e1d32011-02-04 08:52:33 +0200462 int c = sizeof(int**);;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800463
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300464 char* p = "just to make sure this parses w/o error...";
465 int d = sizeof(int());
466 }
467 """
468 compound = self.parse(e).ext[0].body
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800469
eli.benderskyef29ff92010-10-29 16:25:43 +0200470 s1 = compound.block_items[0].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300471 self.assertTrue(isinstance(s1, UnaryOp))
472 self.assertEqual(s1.op, 'sizeof')
473 self.assertTrue(isinstance(s1.expr, ID))
474 self.assertEqual(s1.expr.name, 'k')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800475
eli.benderskyef29ff92010-10-29 16:25:43 +0200476 s2 = compound.block_items[1].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300477 self.assertEqual(expand_decl(s2.expr),
478 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800479
eli.benderskyef29ff92010-10-29 16:25:43 +0200480 s3 = compound.block_items[2].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300481 self.assertEqual(expand_decl(s3.expr),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800482 ['Typename',
483 ['PtrDecl',
484 ['PtrDecl',
485 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300486 ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800487
Eli Benderskye59395b2015-05-09 15:20:46 -0700488 def test_offsetof(self):
489 e = """
490 void foo() {
491 int a = offsetof(struct S, p);
492 a.b = offsetof(struct sockaddr, sp) + strlen(bar);
ksero749650a2016-09-09 07:31:09 +0200493 int a = offsetof(struct S, p.q.r);
494 int a = offsetof(struct S, p[5].q[4][5]);
Eli Benderskye59395b2015-05-09 15:20:46 -0700495 }
496 """
497 compound = self.parse(e).ext[0].body
498 s1 = compound.block_items[0].init
Eli Benderskya71ec1b2015-05-10 06:31:20 -0700499 self.assertTrue(isinstance(s1, FuncCall))
500 self.assertTrue(isinstance(s1.name, ID))
Eli Benderskye59395b2015-05-09 15:20:46 -0700501 self.assertEqual(s1.name.name, 'offsetof')
Eli Benderskya71ec1b2015-05-10 06:31:20 -0700502 self.assertTrue(isinstance(s1.args.exprs[0], Typename))
503 self.assertTrue(isinstance(s1.args.exprs[1], ID))
ksero749650a2016-09-09 07:31:09 +0200504 s3 = compound.block_items[2].init
505 self.assertTrue(isinstance(s3.args.exprs[1], StructRef))
506 s4 = compound.block_items[3].init
507 self.assertTrue(isinstance(s4.args.exprs[1], ArrayRef))
Eli Benderskye59395b2015-05-09 15:20:46 -0700508
Eli Benderskydbf9be22016-10-11 20:44:32 -0700509 def test_compound_statement(self):
510 e = """
511 void foo() {
512 }
513 """
514 compound = self.parse(e).ext[0].body
515 self.assertTrue(isinstance(compound, Compound))
serpilliere471442f2017-03-10 15:02:00 +0100516 self.assert_coord(compound, 2)
Eli Benderskydbf9be22016-10-11 20:44:32 -0700517
eli.bendersky9f481562010-10-30 15:50:47 +0200518 # The C99 compound literal feature
519 #
eli.benderskyf890a862010-10-30 12:13:23 +0200520 def test_compound_literals(self):
eli.bendersky9f481562010-10-30 15:50:47 +0200521 ps1 = self.parse(r'''
eli.benderskyf890a862010-10-30 12:13:23 +0200522 void foo() {
eli.bendersky9f481562010-10-30 15:50:47 +0200523 p = (long long){k};
524 tc = (struct jk){.a = {1, 2}, .b[0] = t};
525 }''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800526
eli.bendersky9f481562010-10-30 15:50:47 +0200527 compound = ps1.ext[0].body.block_items[0].rvalue
528 self.assertEqual(expand_decl(compound.type),
529 ['Typename', ['TypeDecl', ['IdentifierType', ['long', 'long']]]])
530 self.assertEqual(expand_init(compound.init),
531 [['ID', 'k']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800532
533 compound = ps1.ext[0].body.block_items[1].rvalue
eli.bendersky9f481562010-10-30 15:50:47 +0200534 self.assertEqual(expand_decl(compound.type),
535 ['Typename', ['TypeDecl', ['Struct', 'jk', []]]])
536 self.assertEqual(expand_init(compound.init),
537 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800538 ([['ID', 'a']], [['Constant', 'int', '1'], ['Constant', 'int', '2']]),
eli.bendersky9f481562010-10-30 15:50:47 +0200539 ([['ID', 'b'], ['Constant', 'int', '0']], ['ID', 't'])])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800540
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300541 def test_enums(self):
542 e1 = "enum mycolor op;"
543 e1_type = self.parse(e1).ext[0].type.type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800544
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300545 self.assertTrue(isinstance(e1_type, Enum))
546 self.assertEqual(e1_type.name, 'mycolor')
547 self.assertEqual(e1_type.values, None)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800548
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300549 e2 = "enum mysize {large=20, small, medium} shoes;"
550 e2_type = self.parse(e2).ext[0].type.type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800551
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300552 self.assertTrue(isinstance(e2_type, Enum))
553 self.assertEqual(e2_type.name, 'mysize')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800554
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300555 e2_elist = e2_type.values
556 self.assertTrue(isinstance(e2_elist, EnumeratorList))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800557
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300558 for e2_eval in e2_elist.enumerators:
559 self.assertTrue(isinstance(e2_eval, Enumerator))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800560
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300561 self.assertEqual(e2_elist.enumerators[0].name, 'large')
562 self.assertEqual(e2_elist.enumerators[0].value.value, '20')
563 self.assertEqual(e2_elist.enumerators[2].name, 'medium')
564 self.assertEqual(e2_elist.enumerators[2].value, None)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800565
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300566 # enum with trailing comma (C99 feature)
567 e3 = """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800568 enum
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300569 {
570 red,
571 blue,
572 green,
573 } color;
574 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800575
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300576 e3_type = self.parse(e3).ext[0].type.type
577 self.assertTrue(isinstance(e3_type, Enum))
578 e3_elist = e3_type.values
579 self.assertTrue(isinstance(e3_elist, EnumeratorList))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800580
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300581 for e3_eval in e3_elist.enumerators:
582 self.assertTrue(isinstance(e3_eval, Enumerator))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800583
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300584 self.assertEqual(e3_elist.enumerators[0].name, 'red')
585 self.assertEqual(e3_elist.enumerators[0].value, None)
586 self.assertEqual(e3_elist.enumerators[1].name, 'blue')
587 self.assertEqual(e3_elist.enumerators[2].name, 'green')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800588
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300589 def test_typedef(self):
590 # without typedef, error
591 s1 = """
592 node k;
593 """
594 self.assertRaises(ParseError, self.parse, s1)
595
596 # now with typedef, works
597 s2 = """
598 typedef void* node;
599 node k;
600 """
601 ps2 = self.parse(s2)
602 self.assertEqual(expand_decl(ps2.ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800603 ['Typedef', 'node',
604 ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300605 ['TypeDecl', ['IdentifierType', ['void']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800606
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300607 self.assertEqual(expand_decl(ps2.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800608 ['Decl', 'k',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300609 ['TypeDecl', ['IdentifierType', ['node']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800610
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300611 s3 = """
612 typedef int T;
613 typedef T *pT;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800614
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300615 pT aa, bb;
616 """
617 ps3 = self.parse(s3)
618 self.assertEqual(expand_decl(ps3.ext[3]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800619 ['Decl', 'bb',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300620 ['TypeDecl', ['IdentifierType', ['pT']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800621
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300622 s4 = '''
623 typedef char* __builtin_va_list;
624 typedef __builtin_va_list __gnuc_va_list;
625 '''
626 ps4 = self.parse(s4)
627 self.assertEqual(expand_decl(ps4.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800628 ['Typedef', '__gnuc_va_list',
629 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300630 ['IdentifierType', ['__builtin_va_list']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800631
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300632 s5 = '''typedef struct tagHash Hash;'''
633 ps5 = self.parse(s5)
634 self.assertEqual(expand_decl(ps5.ext[0]),
635 ['Typedef', 'Hash', ['TypeDecl', ['Struct', 'tagHash', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800636
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300637 def test_struct_union(self):
638 s1 = """
639 struct {
640 int id;
641 char* name;
642 } joe;
643 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800644
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300645 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800646 ['Decl', 'joe',
647 ['TypeDecl', ['Struct', None,
648 [ ['Decl', 'id',
649 ['TypeDecl',
650 ['IdentifierType', ['int']]]],
651 ['Decl', 'name',
652 ['PtrDecl',
653 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300654 ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800655
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300656 s2 = """
657 struct node p;
658 """
659 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800660 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300661 ['TypeDecl', ['Struct', 'node', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800662
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300663 s21 = """
664 union pri ra;
665 """
666 self.assertEqual(expand_decl(self.parse(s21).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800667 ['Decl', 'ra',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300668 ['TypeDecl', ['Union', 'pri', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800669
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300670 s3 = """
671 struct node* p;
672 """
673 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800674 ['Decl', 'p',
675 ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300676 ['TypeDecl', ['Struct', 'node', []]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800677
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300678 s4 = """
679 struct node;
680 """
681 self.assertEqual(expand_decl(self.parse(s4).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800682 ['Decl', None,
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300683 ['Struct', 'node', []]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800684
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300685 s5 = """
686 union
687 {
688 struct
689 {
690 int type;
691 } n;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800692
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300693 struct
694 {
695 int type;
696 int intnode;
697 } ni;
698 } u;
699 """
700 self.assertEqual(expand_decl(self.parse(s5).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800701 ['Decl', 'u',
702 ['TypeDecl',
703 ['Union', None,
704 [['Decl', 'n',
705 ['TypeDecl',
706 ['Struct', None,
707 [['Decl', 'type',
708 ['TypeDecl', ['IdentifierType', ['int']]]]]]]],
709 ['Decl', 'ni',
710 ['TypeDecl',
711 ['Struct', None,
712 [['Decl', 'type',
713 ['TypeDecl', ['IdentifierType', ['int']]]],
714 ['Decl', 'intnode',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300715 ['TypeDecl', ['IdentifierType', ['int']]]]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800716
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300717 s6 = """
718 typedef struct foo_tag
719 {
720 void* data;
721 } foo, *pfoo;
722 """
723 s6_ast = self.parse(s6)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800724
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300725 self.assertEqual(expand_decl(s6_ast.ext[0]),
726 ['Typedef', 'foo',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800727 ['TypeDecl',
728 ['Struct', 'foo_tag',
729 [['Decl', 'data',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300730 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800731
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300732 self.assertEqual(expand_decl(s6_ast.ext[1]),
733 ['Typedef', 'pfoo',
734 ['PtrDecl',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800735 ['TypeDecl',
736 ['Struct', 'foo_tag',
737 [['Decl', 'data',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300738 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800739
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300740 s7 = r"""
741 struct _on_exit_args {
742 void * _fnargs[32];
743 void * _dso_handle[32];
744
745 long _fntypes;
746 #line 77 "D:\eli\cpp_stuff\libc_include/sys/reent.h"
747
748 long _is_cxa;
749 };
750 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800751
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300752 s7_ast = self.parse(s7, filename='test.c')
serpilliere471442f2017-03-10 15:02:00 +0100753 self.assert_coord(s7_ast.ext[0].type.decls[2], 6, 22, 'test.c')
754 self.assert_coord(s7_ast.ext[0].type.decls[3], 78, 22,
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300755 r'D:\eli\cpp_stuff\libc_include/sys/reent.h')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800756
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300757 s8 = """
758 typedef enum tagReturnCode {SUCCESS, FAIL} ReturnCode;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800759
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300760 typedef struct tagEntry
761 {
762 char* key;
763 char* value;
764 } Entry;
765
766
767 typedef struct tagNode
768 {
769 Entry* entry;
770
771 struct tagNode* next;
772 } Node;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800773
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300774 typedef struct tagHash
775 {
776 unsigned int table_size;
777
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800778 Node** heads;
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300779
780 } Hash;
781 """
782 s8_ast = self.parse(s8)
783 self.assertEqual(expand_decl(s8_ast.ext[3]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800784 ['Typedef', 'Hash',
785 ['TypeDecl', ['Struct', 'tagHash',
786 [['Decl', 'table_size',
787 ['TypeDecl', ['IdentifierType', ['unsigned', 'int']]]],
788 ['Decl', 'heads',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300789 ['PtrDecl', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['Node']]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800790
Eli Bendersky95e3b762016-03-19 05:21:59 -0700791 def test_struct_with_extra_semis_inside(self):
792 s1 = """
793 struct {
794 int a;;
795 } foo;
796 """
797 s1_ast = self.parse(s1)
798 self.assertEqual(expand_decl(s1_ast.ext[0]),
799 ['Decl', 'foo',
800 ['TypeDecl', ['Struct', None,
801 [['Decl', 'a',
802 ['TypeDecl', ['IdentifierType', ['int']]]]]]]])
803
804 s2 = """
805 struct {
806 int a;;;;
807 float b, c;
808 ;;
809 char d;
810 } foo;
811 """
812 s2_ast = self.parse(s2)
813 self.assertEqual(expand_decl(s2_ast.ext[0]),
814 ['Decl', 'foo',
815 ['TypeDecl', ['Struct', None,
816 [['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]],
817 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['float']]]],
818 ['Decl', 'c', ['TypeDecl', ['IdentifierType', ['float']]]],
819 ['Decl', 'd',
820 ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
821
eli.bendersky697ecc52011-02-10 07:05:13 +0200822 def test_anonymous_struct_union(self):
823 s1 = """
824 union
825 {
826 union
827 {
828 int i;
829 long l;
830 };
831
832 struct
833 {
834 int type;
835 int intnode;
836 };
837 } u;
838 """
839
840 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
841 ['Decl', 'u',
842 ['TypeDecl',
843 ['Union', None,
844 [['Decl', None,
845 ['Union', None,
846 [['Decl', 'i',
847 ['TypeDecl',
848 ['IdentifierType', ['int']]]],
849 ['Decl', 'l',
850 ['TypeDecl',
851 ['IdentifierType', ['long']]]]]]],
852 ['Decl', None,
853 ['Struct', None,
854 [['Decl', 'type',
855 ['TypeDecl',
856 ['IdentifierType', ['int']]]],
857 ['Decl', 'intnode',
858 ['TypeDecl',
859 ['IdentifierType', ['int']]]]]]]]]]])
860
861 s2 = """
862 struct
863 {
864 int i;
865 union
866 {
867 int id;
868 char* name;
869 };
870 float f;
871 } joe;
872 """
873
874 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
875 ['Decl', 'joe',
876 ['TypeDecl',
877 ['Struct', None,
878 [['Decl', 'i',
879 ['TypeDecl',
880 ['IdentifierType', ['int']]]],
881 ['Decl', None,
882 ['Union', None,
883 [['Decl', 'id',
884 ['TypeDecl',
885 ['IdentifierType', ['int']]]],
886 ['Decl', 'name',
887 ['PtrDecl',
888 ['TypeDecl',
889 ['IdentifierType', ['char']]]]]]]],
890 ['Decl', 'f',
891 ['TypeDecl',
892 ['IdentifierType', ['float']]]]]]]])
893
894 # ISO/IEC 9899:201x Commitee Draft 2010-11-16, N1539
895 # section 6.7.2.1, par. 19, example 1
896 s3 = """
897 struct v {
898 union {
899 struct { int i, j; };
900 struct { long k, l; } w;
901 };
902 int m;
903 } v1;
904 """
905
906 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
907 ['Decl', 'v1',
908 ['TypeDecl',
909 ['Struct', 'v',
910 [['Decl', None,
911 ['Union', None,
912 [['Decl', None,
913 ['Struct', None,
914 [['Decl', 'i',
915 ['TypeDecl',
916 ['IdentifierType', ['int']]]],
917 ['Decl', 'j',
918 ['TypeDecl',
919 ['IdentifierType', ['int']]]]]]],
920 ['Decl', 'w',
921 ['TypeDecl',
922 ['Struct', None,
923 [['Decl', 'k',
924 ['TypeDecl',
925 ['IdentifierType', ['long']]]],
926 ['Decl', 'l',
927 ['TypeDecl',
928 ['IdentifierType', ['long']]]]]]]]]]],
929 ['Decl', 'm',
930 ['TypeDecl',
931 ['IdentifierType', ['int']]]]]]]])
932
eli.benderskydce29a02011-02-10 07:55:00 +0200933 s4 = """
934 struct v {
935 int i;
936 float;
937 } v2;"""
eli.bendersky6b011792011-06-22 17:50:56 +0300938 # just make sure this doesn't raise ParseError
939 self.parse(s4)
eli.benderskydce29a02011-02-10 07:55:00 +0200940
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400941 def test_struct_members_namespace(self):
Eli Bendersky4d969b32013-07-13 06:07:07 -0700942 """ Tests that structure/union member names reside in a separate
943 namespace and can be named after existing types.
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400944 """
945 s1 = """
946 typedef int Name;
947 typedef Name NameArray[10];
948
949 struct {
950 Name Name;
951 Name NameArray[3];
952 } sye;
953
954 void main(void)
955 {
956 sye.Name = 1;
957 }
958 """
959
960 s1_ast = self.parse(s1)
961 self.assertEqual(expand_decl(s1_ast.ext[2]),
962 ['Decl', 'sye',
963 ['TypeDecl', ['Struct', None,
964 [ ['Decl', 'Name',
965 ['TypeDecl',
966 ['IdentifierType', ['Name']]]],
967 ['Decl', 'NameArray',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800968 ['ArrayDecl', '3', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400969 ['TypeDecl', ['IdentifierType', ['Name']]]]]]]]])
970 self.assertEqual(s1_ast.ext[3].body.block_items[0].lvalue.field.name, 'Name')
971
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200972 def test_struct_bitfields(self):
eli.bendersky38ed9a92010-10-09 09:29:59 +0200973 # a struct with two bitfields, one unnamed
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200974 s1 = """
975 struct {
976 int k:6;
977 int :2;
978 } joe;
979 """
980
981 parsed_struct = self.parse(s1).ext[0]
982
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800983 # We can see here the name of the decl for the unnamed bitfield is
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200984 # None, but expand_decl doesn't show bitfield widths
985 # ...
986 self.assertEqual(expand_decl(parsed_struct),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800987 ['Decl', 'joe',
988 ['TypeDecl', ['Struct', None,
989 [ ['Decl', 'k',
990 ['TypeDecl',
991 ['IdentifierType', ['int']]]],
992 ['Decl', None,
993 ['TypeDecl',
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200994 ['IdentifierType', ['int']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800995
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200996 # ...
997 # so we test them manually
998 self.assertEqual(parsed_struct.type.type.decls[0].bitsize.value, '6')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800999 self.assertEqual(parsed_struct.type.type.decls[1].bitsize.value, '2')
1000
ldore81a12ca2018-04-28 05:09:24 +02001001 def test_struct_empty(self):
1002 """
1003 Tests that parsing an empty struct works.
1004
1005 Empty structs do NOT follow C99 (See 6.2.5-20 of the C99 standard).
1006 This is nevertheless supported by some compilers (clang, gcc),
1007 especially when using FORTIFY code.
1008 Some compilers (visual) will fail to compile with an error.
1009 """
1010 # an empty struct. This is NOT C99 compliant
1011 s1 = """
1012 struct foo { };
1013 """
1014
1015 parsed_struct = self.parse(s1).ext[0]
1016
1017 self.assertEqual(expand_decl(parsed_struct),
1018 ['Decl', None, ['Struct', 'foo', []]]
1019 )
1020
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001021 def test_tags_namespace(self):
1022 """ Tests that the tags of structs/unions/enums reside in a separate namespace and
1023 can be named after existing types.
1024 """
1025 s1 = """
1026 typedef int tagEntry;
1027
1028 struct tagEntry
1029 {
1030 char* key;
1031 char* value;
1032 } Entry;
1033 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001034
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001035 s1_ast = self.parse(s1)
1036 self.assertEqual(expand_decl(s1_ast.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001037 ['Decl', 'Entry',
1038 ['TypeDecl', ['Struct', 'tagEntry',
1039 [['Decl', 'key',
1040 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
1041 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001042 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001043
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001044 s2 = """
1045 struct tagEntry;
1046
1047 typedef struct tagEntry tagEntry;
1048
1049 struct tagEntry
1050 {
1051 char* key;
1052 char* value;
1053 } Entry;
1054 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001055
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001056 s2_ast = self.parse(s2)
1057 self.assertEqual(expand_decl(s2_ast.ext[2]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001058 ['Decl', 'Entry',
1059 ['TypeDecl', ['Struct', 'tagEntry',
1060 [['Decl', 'key',
1061 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
1062 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001063 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001064
1065 s3 = """
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001066 typedef int mytag;
1067
1068 enum mytag {ABC, CDE};
1069 enum mytag joe;
1070 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001071
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001072 s3_type = self.parse(s3).ext[1].type
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001073
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001074 self.assertTrue(isinstance(s3_type, Enum))
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001075 self.assertEqual(s3_type.name, 'mytag')
1076
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001077 def test_multi_decls(self):
1078 d1 = 'int a, b;'
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001079
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001080 self.assertEqual(self.get_decl(d1, 0),
1081 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
1082 self.assertEqual(self.get_decl(d1, 1),
1083 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['int']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001084
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001085 d2 = 'char* p, notp, ar[4];'
1086 self.assertEqual(self.get_decl(d2, 0),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001087 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001088 ['PtrDecl',
1089 ['TypeDecl', ['IdentifierType', ['char']]]]])
1090 self.assertEqual(self.get_decl(d2, 1),
1091 ['Decl', 'notp', ['TypeDecl', ['IdentifierType', ['char']]]])
1092 self.assertEqual(self.get_decl(d2, 2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001093 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001094 ['ArrayDecl', '4', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001095 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001096
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001097 def test_invalid_multiple_types_error(self):
1098 bad = [
1099 'int enum {ab, cd} fubr;',
1100 'enum kid char brbr;']
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001101
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001102 for b in bad:
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001103 self.assertRaises(ParseError, self.parse, b)
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001104
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001105 def test_duplicate_typedef(self):
1106 """ Tests that redeclarations of existing types are parsed correctly.
1107 This is non-standard, but allowed by many compilers.
1108 """
1109 d1 = '''
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001110 typedef int numbertype;
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001111 typedef int numbertype;
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001112 '''
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001113
1114 self.assertEqual(self.get_decl(d1, 0),
1115 ['Typedef', 'numbertype',
1116 ['TypeDecl', ['IdentifierType', ['int']]]])
1117 self.assertEqual(self.get_decl(d1, 1),
1118 ['Typedef', 'numbertype',
1119 ['TypeDecl', ['IdentifierType', ['int']]]])
1120
1121 d2 = '''
1122 typedef int (*funcptr)(int x);
1123 typedef int (*funcptr)(int x);
1124 '''
1125 self.assertEqual(self.get_decl(d2, 0),
1126 ['Typedef', 'funcptr',
1127 ['PtrDecl', ['FuncDecl',
1128 [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]],
1129 ['TypeDecl', ['IdentifierType', ['int']]]]]])
1130 self.assertEqual(self.get_decl(d2, 1),
1131 ['Typedef', 'funcptr',
1132 ['PtrDecl', ['FuncDecl',
1133 [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]],
1134 ['TypeDecl', ['IdentifierType', ['int']]]]]])
1135
1136 d3 = '''
1137 typedef int numberarray[5];
1138 typedef int numberarray[5];
1139 '''
1140 self.assertEqual(self.get_decl(d3, 0),
1141 ['Typedef', 'numberarray',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001142 ['ArrayDecl', '5', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001143 ['TypeDecl', ['IdentifierType', ['int']]]]])
1144 self.assertEqual(self.get_decl(d3, 1),
1145 ['Typedef', 'numberarray',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001146 ['ArrayDecl', '5', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001147 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001148
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001149 def test_decl_inits(self):
1150 d1 = 'int a = 16;'
eli.benderskyf890a862010-10-30 12:13:23 +02001151 #~ self.parse(d1).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001152 self.assertEqual(self.get_decl(d1),
1153 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
1154 self.assertEqual(self.get_decl_init(d1),
1155 ['Constant', 'int', '16'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001156
Eli Bendersky3b1b08d2012-06-15 12:37:54 +03001157 d1_1 = 'float f = 0xEF.56p1;'
1158 self.assertEqual(self.get_decl_init(d1_1),
1159 ['Constant', 'float', '0xEF.56p1'])
1160
Konstanty Bialkowski3bdbfdc2015-04-19 20:09:21 +10001161 d1_2 = 'int bitmask = 0b1001010;'
1162 self.assertEqual(self.get_decl_init(d1_2),
1163 ['Constant', 'int', '0b1001010'])
1164
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001165 d2 = 'long ar[] = {7, 8, 9};'
1166 self.assertEqual(self.get_decl(d2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001167 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001168 ['ArrayDecl', '', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001169 ['TypeDecl', ['IdentifierType', ['long']]]]])
1170 self.assertEqual(self.get_decl_init(d2),
1171 [ ['Constant', 'int', '7'],
1172 ['Constant', 'int', '8'],
eli.benderskyf890a862010-10-30 12:13:23 +02001173 ['Constant', 'int', '9']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001174
Eli Benderskyc830da82015-05-10 07:56:41 -07001175 d21 = 'long ar[4] = {};'
1176 self.assertEqual(self.get_decl_init(d21), [])
1177
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001178 d3 = 'char p = j;'
1179 self.assertEqual(self.get_decl(d3),
1180 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['char']]]])
1181 self.assertEqual(self.get_decl_init(d3),
1182 ['ID', 'j'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001183
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001184 d4 = "char x = 'c', *p = {0, 1, 2, {4, 5}, 6};"
1185 self.assertEqual(self.get_decl(d4, 0),
1186 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['char']]]])
1187 self.assertEqual(self.get_decl_init(d4, 0),
1188 ['Constant', 'char', "'c'"])
1189 self.assertEqual(self.get_decl(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001190 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001191 ['PtrDecl',
1192 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001193
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001194 self.assertEqual(self.get_decl_init(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001195 [ ['Constant', 'int', '0'],
1196 ['Constant', 'int', '1'],
1197 ['Constant', 'int', '2'],
1198 [['Constant', 'int', '4'],
1199 ['Constant', 'int', '5']],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001200 ['Constant', 'int', '6']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001201
eli.benderskyf890a862010-10-30 12:13:23 +02001202 def test_decl_named_inits(self):
1203 d1 = 'int a = {.k = 16};'
1204 self.assertEqual(self.get_decl_init(d1),
1205 [( [['ID', 'k']],
1206 ['Constant', 'int', '16'])])
1207
1208 d2 = 'int a = { [0].a = {1}, [1].a[0] = 2 };'
1209 self.assertEqual(self.get_decl_init(d2),
1210 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001211 ([['Constant', 'int', '0'], ['ID', 'a']],
1212 [['Constant', 'int', '1']]),
1213 ([['Constant', 'int', '1'], ['ID', 'a'], ['Constant', 'int', '0']],
eli.benderskyf890a862010-10-30 12:13:23 +02001214 ['Constant', 'int', '2'])])
1215
1216 d3 = 'int a = { .a = 1, .c = 3, 4, .b = 5};'
1217 self.assertEqual(self.get_decl_init(d3),
1218 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001219 ([['ID', 'a']], ['Constant', 'int', '1']),
1220 ([['ID', 'c']], ['Constant', 'int', '3']),
1221 ['Constant', 'int', '4'],
eli.benderskyf890a862010-10-30 12:13:23 +02001222 ([['ID', 'b']], ['Constant', 'int', '5'])])
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001223
1224 def test_function_definitions(self):
1225 def parse_fdef(str):
1226 return self.parse(str).ext[0]
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001227
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001228 def fdef_decl(fdef):
1229 return expand_decl(fdef.decl)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001230
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001231 f1 = parse_fdef('''
1232 int factorial(int p)
1233 {
1234 return 3;
1235 }
1236 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001237
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001238 self.assertEqual(fdef_decl(f1),
1239 ['Decl', 'factorial',
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001240 ['FuncDecl',
1241 [['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001242 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001243
eli.benderskyef29ff92010-10-29 16:25:43 +02001244 self.assertEqual(type(f1.body.block_items[0]), Return)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001245
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001246 f2 = parse_fdef('''
1247 char* zzz(int p, char* c)
1248 {
1249 int a;
1250 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001251
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001252 a = b + 2;
1253 return 3;
1254 }
1255 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001256
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001257 self.assertEqual(fdef_decl(f2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001258 ['Decl', 'zzz',
1259 ['FuncDecl',
1260 [ ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]],
1261 ['Decl', 'c', ['PtrDecl',
1262 ['TypeDecl', ['IdentifierType', ['char']]]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001263 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001264
1265 self.assertEqual(list(map(type, f2.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001266 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001267
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001268 f3 = parse_fdef('''
1269 char* zzz(p, c)
1270 long p, *c;
1271 {
1272 int a;
1273 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001274
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001275 a = b + 2;
1276 return 3;
1277 }
1278 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001279
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001280 self.assertEqual(fdef_decl(f3),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001281 ['Decl', 'zzz',
1282 ['FuncDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001283 [ ['ID', 'p'],
1284 ['ID', 'c']],
1285 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001286
1287 self.assertEqual(list(map(type, f3.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001288 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001289
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001290 self.assertEqual(expand_decl(f3.param_decls[0]),
1291 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['long']]]])
1292 self.assertEqual(expand_decl(f3.param_decls[1]),
1293 ['Decl', 'c', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['long']]]]])
1294
Sye van der Veen51a46ec2013-06-10 12:56:15 -04001295 # function return values and parameters may not have type information
1296 f4 = parse_fdef('''
1297 que(p)
1298 {
1299 return 3;
1300 }
1301 ''')
1302
1303 self.assertEqual(fdef_decl(f4),
1304 ['Decl', 'que',
1305 ['FuncDecl',
1306 [['ID', 'p']],
1307 ['TypeDecl', ['IdentifierType', ['int']]]]])
1308
eli.bendersky71540662010-07-03 12:58:52 +02001309 def test_unified_string_literals(self):
1310 # simple string, for reference
1311 d1 = self.get_decl_init('char* s = "hello";')
1312 self.assertEqual(d1, ['Constant', 'string', '"hello"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001313
eli.bendersky71540662010-07-03 12:58:52 +02001314 d2 = self.get_decl_init('char* s = "hello" " world";')
1315 self.assertEqual(d2, ['Constant', 'string', '"hello world"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001316
eli.bendersky71540662010-07-03 12:58:52 +02001317 # the test case from issue 6
1318 d3 = self.parse(r'''
1319 int main() {
1320 fprintf(stderr,
1321 "Wrong Params?\n"
1322 "Usage:\n"
1323 "%s <binary_file_path>\n",
1324 argv[0]
1325 );
1326 }
1327 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001328
eli.bendersky71540662010-07-03 12:58:52 +02001329 self.assertEqual(
eli.benderskyef29ff92010-10-29 16:25:43 +02001330 d3.ext[0].body.block_items[0].args.exprs[1].value,
eli.bendersky71540662010-07-03 12:58:52 +02001331 r'"Wrong Params?\nUsage:\n%s <binary_file_path>\n"')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001332
eli.bendersky4a89f112010-07-05 06:02:03 +02001333 d4 = self.get_decl_init('char* s = "" "foobar";')
1334 self.assertEqual(d4, ['Constant', 'string', '"foobar"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001335
eli.bendersky4a89f112010-07-05 06:02:03 +02001336 d5 = self.get_decl_init(r'char* s = "foo\"" "bar";')
1337 self.assertEqual(d5, ['Constant', 'string', r'"foo\"bar"'])
eli.bendersky71540662010-07-03 12:58:52 +02001338
Eli Benderskyc9f1a382014-03-15 14:12:00 -07001339 def test_unified_wstring_literals(self):
1340 d1 = self.get_decl_init('char* s = L"hello" L"world";')
1341 self.assertEqual(d1, ['Constant', 'string', 'L"helloworld"'])
1342
1343 d2 = self.get_decl_init('char* s = L"hello " L"world" L" and I";')
1344 self.assertEqual(d2, ['Constant', 'string', 'L"hello world and I"'])
1345
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001346 def test_inline_specifier(self):
eli.bendersky79d5cf62010-10-29 13:33:52 +02001347 ps2 = self.parse('static inline void inlinefoo(void);')
1348 self.assertEqual(ps2.ext[0].funcspec, ['inline'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001349
eli.bendersky2e907fa2010-10-29 15:51:07 +02001350 # variable length array
1351 def test_vla(self):
1352 ps2 = self.parse(r'''
1353 int main() {
1354 int size;
1355 int var[size = 5];
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001356
eli.bendersky2e907fa2010-10-29 15:51:07 +02001357 int var2[*];
1358 }
1359 ''')
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001360 self.assertTrue(isinstance(ps2.ext[0].body.block_items[1].type.dim, Assignment))
1361 self.assertTrue(isinstance(ps2.ext[0].body.block_items[2].type.dim, ID))
eli.bendersky79d5cf62010-10-29 13:33:52 +02001362
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001363 def test_pragma(self):
1364 s1 = r'''
1365 #pragma bar
1366 void main() {
1367 #pragma foo
1368 for(;;) {}
Julian Hammer8a174062015-12-14 14:48:16 +01001369 #pragma
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001370 }
ldoreec233182017-11-22 14:52:53 +01001371 struct s {
1372 #pragma baz
1373 } s;
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001374 '''
1375 s1_ast = self.parse(s1)
1376 self.assertTrue(isinstance(s1_ast.ext[0], Pragma))
1377 self.assertEqual(s1_ast.ext[0].string, 'bar')
Julian Hammer8a174062015-12-14 14:48:16 +01001378 self.assertEqual(s1_ast.ext[0].coord.line, 2)
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001379
1380 self.assertTrue(isinstance(s1_ast.ext[1].body.block_items[0], Pragma))
1381 self.assertEqual(s1_ast.ext[1].body.block_items[0].string, 'foo')
Julian Hammer8a174062015-12-14 14:48:16 +01001382 self.assertEqual(s1_ast.ext[1].body.block_items[0].coord.line, 4)
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001383
Julian Hammer8a174062015-12-14 14:48:16 +01001384 self.assertTrue(isinstance(s1_ast.ext[1].body.block_items[2], Pragma))
1385 self.assertEqual(s1_ast.ext[1].body.block_items[2].string, '')
1386 self.assertEqual(s1_ast.ext[1].body.block_items[2].coord.line, 6)
ldoreec233182017-11-22 14:52:53 +01001387
1388 self.assertTrue(isinstance(s1_ast.ext[2].type.type.decls[0], Pragma))
1389 self.assertEqual(s1_ast.ext[2].type.type.decls[0].string, 'baz')
1390 self.assertEqual(s1_ast.ext[2].type.type.decls[0].coord.line, 9)
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001391
dbluhm7af2fb92018-03-03 06:18:26 -07001392 def test_pragmacomp_or_statement(self):
1393 s1 = r'''
1394 void main() {
1395 int sum = 0;
1396 for (int i; i < 3; i++)
1397 #pragma omp critical
1398 sum += 1;
1399
1400 while(sum < 10)
1401 #pragma omp critical
1402 sum += 1;
1403
1404 mylabel:
1405 #pragma foo
1406 sum += 10;
1407
1408 if (sum > 10)
1409 #pragma bar
1410 sum = 10;
1411
1412 switch (sum)
1413 case 10:
1414 #pragma foo
1415 sum = 20;
1416 }
1417 '''
1418 s1_ast = self.parse(s1)
1419 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[1], For))
1420 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[1].stmt, Compound))
1421 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[1].stmt.block_items[0], Pragma))
1422 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[1].stmt.block_items[1], Assignment))
1423 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[2], While))
1424 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[2].stmt, Compound))
1425 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[2].stmt.block_items[0], Pragma))
1426 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[2].stmt.block_items[1], Assignment))
1427 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[3], Label))
1428 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[3].stmt, Compound))
1429 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[3].stmt.block_items[0], Pragma))
1430 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[3].stmt.block_items[1], Assignment))
1431 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[4], If))
1432 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[4].iftrue, Compound))
1433 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[4].iftrue.block_items[0], Pragma))
1434 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[4].iftrue.block_items[1], Assignment))
1435 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[5], Switch))
1436 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[5].stmt.stmts[0], Compound))
1437 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[5].stmt.stmts[0].block_items[0], Pragma))
1438 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[5].stmt.stmts[0].block_items[1], Assignment))
1439
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001440
eli.bendersky85d2e732011-05-20 19:47:26 +03001441class TestCParser_whole_code(TestCParser_base):
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001442 """ Testing of parsing whole chunks of code.
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001443
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001444 Since I don't want to rely on the structure of ASTs too
1445 much, most of these tests are implemented with visitors.
1446 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001447 # A simple helper visitor that lists the values of all the
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001448 # Constant nodes it sees.
1449 #
1450 class ConstantVisitor(NodeVisitor):
1451 def __init__(self):
1452 self.values = []
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001453
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001454 def visit_Constant(self, node):
1455 self.values.append(node.value)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001456
1457 # This visitor counts the amount of references to the ID
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001458 # with the name provided to it in the constructor.
1459 #
1460 class IDNameCounter(NodeVisitor):
1461 def __init__(self, name):
1462 self.name = name
1463 self.nrefs = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001464
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001465 def visit_ID(self, node):
1466 if node.name == self.name:
1467 self.nrefs += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001468
1469 # Counts the amount of nodes of a given class
1470 #
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001471 class NodeKlassCounter(NodeVisitor):
1472 def __init__(self, node_klass):
1473 self.klass = node_klass
1474 self.n = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001475
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001476 def generic_visit(self, node):
1477 if node.__class__ == self.klass:
1478 self.n += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001479
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001480 NodeVisitor.generic_visit(self, node)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001481
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001482 def assert_all_Constants(self, code, constants):
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001483 """ Asserts that the list of all Constant values (by
1484 'preorder' appearance) in the chunk of code is as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001485 given.
1486 """
eli.benderskyed890492010-06-25 08:25:55 +03001487 if isinstance(code, str):
1488 parsed = self.parse(code)
1489 else:
1490 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001491
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001492 cv = self.ConstantVisitor()
1493 cv.visit(parsed)
1494 self.assertEqual(cv.values, constants)
1495
1496 def assert_num_ID_refs(self, code, name, num):
1497 """ Asserts the number of references to the ID with
1498 the given name.
1499 """
1500 if isinstance(code, str):
1501 parsed = self.parse(code)
1502 else:
1503 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001504
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001505 iv = self.IDNameCounter(name)
1506 iv.visit(parsed)
1507 self.assertEqual(iv.nrefs, num)
1508
1509 def assert_num_klass_nodes(self, code, klass, num):
1510 """ Asserts the amount of klass nodes in the code.
1511 """
1512 if isinstance(code, str):
1513 parsed = self.parse(code)
1514 else:
1515 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001516
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001517 cv = self.NodeKlassCounter(klass)
1518 cv.visit(parsed)
1519 self.assertEqual(cv.n, num)
1520
1521 def test_expressions(self):
1522 e1 = '''int k = (r + 10.0) >> 6 + 8 << (3 & 0x14);'''
1523 self.assert_all_Constants(e1, ['10.0', '6', '8', '3', '0x14'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001524
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001525 e2 = r'''char n = '\n', *prefix = "st_";'''
1526 self.assert_all_Constants(e2, [r"'\n'", '"st_"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001527
Eli Bendersky09e22a62013-07-02 06:00:36 -07001528 s1 = r'''int main() {
1529 int i = 5, j = 6, k = 1;
1530 if ((i=j && k == 1) || k > j)
1531 printf("Hello, world\n");
1532 return 0;
1533 }'''
1534 ps1 = self.parse(s1)
1535 self.assert_all_Constants(ps1,
1536 ['5', '6', '1', '1', '"Hello, world\\n"', '0'])
1537 self.assert_num_ID_refs(ps1, 'i', 1)
1538 self.assert_num_ID_refs(ps1, 'j', 2)
1539
1540
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001541 def test_statements(self):
1542 s1 = r'''
1543 void foo(){
1544 if (sp == 1)
1545 if (optind >= argc ||
1546 argv[optind][0] != '-' || argv[optind][1] == '\0')
1547 return -1;
1548 else if (strcmp(argv[optind], "--") == 0) {
1549 optind++;
1550 return -1;
1551 }
1552 }
1553 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001554
1555 self.assert_all_Constants(s1,
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001556 ['1', '0', r"'-'", '1', r"'\0'", '1', r'"--"', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001557
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001558 ps1 = self.parse(s1)
1559 self.assert_num_ID_refs(ps1, 'argv', 3)
1560 self.assert_num_ID_refs(ps1, 'optind', 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001561
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001562 self.assert_num_klass_nodes(ps1, If, 3)
1563 self.assert_num_klass_nodes(ps1, Return, 2)
1564 self.assert_num_klass_nodes(ps1, FuncCall, 1) # strcmp
1565 self.assert_num_klass_nodes(ps1, BinaryOp, 7)
1566
1567 # In the following code, Hash and Node were defined as
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001568 # int to pacify the parser that sees they're used as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001569 # types
1570 #
1571 s2 = r'''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001572 typedef int Hash, Node;
1573
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001574 void HashDestroy(Hash* hash)
1575 {
1576 unsigned int i;
1577
1578 if (hash == NULL)
1579 return;
1580
1581 for (i = 0; i < hash->table_size; ++i)
1582 {
1583 Node* temp = hash->heads[i];
1584
1585 while (temp != NULL)
1586 {
1587 Node* temp2 = temp;
1588
1589 free(temp->entry->key);
1590 free(temp->entry->value);
1591 free(temp->entry);
1592
1593 temp = temp->next;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001594
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001595 free(temp2);
1596 }
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001597 }
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001598
1599 free(hash->heads);
1600 hash->heads = NULL;
1601
1602 free(hash);
1603 }
1604 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001605
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001606 ps2 = self.parse(s2)
1607 self.assert_num_klass_nodes(ps2, FuncCall, 6)
1608 self.assert_num_klass_nodes(ps2, FuncDef, 1)
1609 self.assert_num_klass_nodes(ps2, For, 1)
1610 self.assert_num_klass_nodes(ps2, While, 1)
1611 self.assert_num_klass_nodes(ps2, StructRef, 10)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001612
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001613 # declarations don't count
1614 self.assert_num_ID_refs(ps2, 'hash', 6)
1615 self.assert_num_ID_refs(ps2, 'i', 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001616
eli.benderskyed890492010-06-25 08:25:55 +03001617 s3 = r'''
1618 void x(void) {
1619 int a, b;
1620 if (a < b)
1621 do {
1622 a = 0;
1623 } while (0);
1624 else if (a == b) {
1625 a = 1;
1626 }
1627 }
1628 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001629
eli.benderskyed890492010-06-25 08:25:55 +03001630 ps3 = self.parse(s3)
1631 self.assert_num_klass_nodes(ps3, DoWhile, 1)
1632 self.assert_num_ID_refs(ps3, 'a', 4)
1633 self.assert_all_Constants(ps3, ['0', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001634
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001635 def test_empty_statements(self):
eli.bendersky91c0aa32011-10-16 05:50:43 +02001636 s1 = r'''
1637 void foo(void){
1638 ;
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001639 return;;
1640
1641 ;
eli.bendersky91c0aa32011-10-16 05:50:43 +02001642 }
1643 '''
1644 ps1 = self.parse(s1)
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001645 self.assert_num_klass_nodes(ps1, EmptyStatement, 3)
eli.bendersky91c0aa32011-10-16 05:50:43 +02001646 self.assert_num_klass_nodes(ps1, Return, 1)
serpilliere471442f2017-03-10 15:02:00 +01001647 self.assert_coord(ps1.ext[0].body.block_items[0], 3)
1648 self.assert_coord(ps1.ext[0].body.block_items[1], 4)
1649 self.assert_coord(ps1.ext[0].body.block_items[2], 4)
1650 self.assert_coord(ps1.ext[0].body.block_items[3], 6)
eli.bendersky145890d2010-10-29 12:02:32 +02001651
Ben5cd3fd62012-02-03 06:02:40 +02001652 def test_switch_statement(self):
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001653 def assert_case_node(node, const_value):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001654 self.assertTrue(isinstance(node, Case))
1655 self.assertTrue(isinstance(node.expr, Constant))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001656 self.assertEqual(node.expr.value, const_value)
1657
1658 def assert_default_node(node):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001659 self.assertTrue(isinstance(node, Default))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001660
Ben5cd3fd62012-02-03 06:02:40 +02001661 s1 = r'''
1662 int foo(void) {
1663 switch (myvar) {
1664 case 10:
1665 k = 10;
1666 p = k + 1;
1667 return 10;
1668 case 20:
1669 case 30:
1670 return 20;
1671 default:
1672 break;
1673 }
1674 return 0;
1675 }
1676 '''
1677 ps1 = self.parse(s1)
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001678 switch = ps1.ext[0].body.block_items[0]
1679
1680 block = switch.stmt.block_items
1681 assert_case_node(block[0], '10')
1682 self.assertEqual(len(block[0].stmts), 3)
1683 assert_case_node(block[1], '20')
1684 self.assertEqual(len(block[1].stmts), 0)
1685 assert_case_node(block[2], '30')
1686 self.assertEqual(len(block[2].stmts), 1)
1687 assert_default_node(block[3])
1688
1689 s2 = r'''
1690 int foo(void) {
1691 switch (myvar) {
1692 default:
1693 joe = moe;
1694 return 10;
1695 case 10:
1696 case 20:
1697 case 30:
1698 case 40:
1699 break;
1700 }
1701 return 0;
1702 }
1703 '''
1704 ps2 = self.parse(s2)
1705 switch = ps2.ext[0].body.block_items[0]
1706
1707 block = switch.stmt.block_items
1708 assert_default_node(block[0])
1709 self.assertEqual(len(block[0].stmts), 2)
1710 assert_case_node(block[1], '10')
1711 self.assertEqual(len(block[1].stmts), 0)
1712 assert_case_node(block[2], '20')
1713 self.assertEqual(len(block[1].stmts), 0)
1714 assert_case_node(block[3], '30')
1715 self.assertEqual(len(block[1].stmts), 0)
1716 assert_case_node(block[4], '40')
1717 self.assertEqual(len(block[4].stmts), 1)
Ben5cd3fd62012-02-03 06:02:40 +02001718
eli.bendersky145890d2010-10-29 12:02:32 +02001719 def test_for_statement(self):
1720 s2 = r'''
1721 void x(void)
1722 {
1723 int i;
1724 for (i = 0; i < 5; ++i) {
1725 x = 50;
1726 }
1727 }
1728 '''
1729 ps2 = self.parse(s2)
1730 self.assert_num_klass_nodes(ps2, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001731 # here there are 3 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001732 # a ref in the visitor
1733 #
1734 self.assert_num_ID_refs(ps2, 'i', 3)
Eli Bendersky4476d092012-12-25 14:07:57 -08001735
eli.bendersky145890d2010-10-29 12:02:32 +02001736 s3 = r'''
1737 void x(void)
1738 {
1739 for (int i = 0; i < 5; ++i) {
1740 x = 50;
1741 }
1742 }
1743 '''
1744 ps3 = self.parse(s3)
eli.bendersky145890d2010-10-29 12:02:32 +02001745 self.assert_num_klass_nodes(ps3, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001746 # here there are 2 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001747 # a ref in the visitor
1748 #
1749 self.assert_num_ID_refs(ps3, 'i', 2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001750
Eli Bendersky4476d092012-12-25 14:07:57 -08001751 s4 = r'''
1752 void x(void) {
1753 for (int i = 0;;)
1754 i;
1755 }
1756 '''
1757 ps4 = self.parse(s4)
1758 self.assert_num_ID_refs(ps4, 'i', 1)
1759
Eli Benderskyd0973782012-01-19 08:09:33 +02001760 def _open_c_file(self, name):
1761 """ Find a c file by name, taking into account the current dir can be
1762 in a couple of typical places
1763 """
Stefano Riveraebaf5922013-08-08 09:45:26 +02001764 testdir = os.path.dirname(__file__)
1765 name = os.path.join(testdir, 'c_files', name)
1766 assert os.path.exists(name)
1767 return open(name, 'rU')
Eli Benderskyd0973782012-01-19 08:09:33 +02001768
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001769 def test_whole_file(self):
1770 # See how pycparser handles a whole, real C file.
1771 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001772 with self._open_c_file('memmgr_with_h.c') as f:
1773 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001774 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001775
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001776 self.assert_num_klass_nodes(p, FuncDef, 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001777
1778 # each FuncDef also has a FuncDecl. 4 declarations
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001779 # + 5 definitions, overall 9
1780 self.assert_num_klass_nodes(p, FuncDecl, 9)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001781
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001782 self.assert_num_klass_nodes(p, Typedef, 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001783
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001784 self.assertEqual(p.ext[4].coord.line, 88)
1785 self.assertEqual(p.ext[4].coord.file, "./memmgr.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001786
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001787 self.assertEqual(p.ext[6].coord.line, 10)
1788 self.assertEqual(p.ext[6].coord.file, "memmgr.c")
1789
1790 def test_whole_file_with_stdio(self):
1791 # Parse a whole file with stdio.h included by cpp
1792 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001793 with self._open_c_file('cppd_with_stdio_h.c') as f:
1794 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001795 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001796
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001797 self.assertTrue(isinstance(p.ext[0], Typedef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001798 self.assertEqual(p.ext[0].coord.line, 213)
Ville Skyttä2129f5f2017-03-05 04:52:22 +02001799 self.assertEqual(p.ext[0].coord.file, r"D:\eli\cpp_stuff\libc_include/stddef.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001800
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001801 self.assertTrue(isinstance(p.ext[-1], FuncDef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001802 self.assertEqual(p.ext[-1].coord.line, 15)
1803 self.assertEqual(p.ext[-1].coord.file, "example_c_file.c")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001804
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001805 self.assertTrue(isinstance(p.ext[-8], Typedef))
1806 self.assertTrue(isinstance(p.ext[-8].type, TypeDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001807 self.assertEqual(p.ext[-8].name, 'cookie_io_functions_t')
eli.bendersky85d2e732011-05-20 19:47:26 +03001808
1809
1810class TestCParser_typenames(TestCParser_base):
1811 """ Test issues related to the typedef-name problem.
1812 """
1813 def test_innerscope_typedef(self):
1814 # should fail since TT is not a type in bar
1815 s1 = r'''
1816 void foo() {
1817 typedef char TT;
1818 TT x;
1819 }
1820 void bar() {
1821 TT y;
1822 }
1823 '''
1824 self.assertRaises(ParseError, self.parse, s1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001825
eli.bendersky85d2e732011-05-20 19:47:26 +03001826 # should succeed since TT is not a type in bar
1827 s2 = r'''
1828 void foo() {
1829 typedef char TT;
1830 TT x;
1831 }
1832 void bar() {
1833 unsigned TT;
1834 }
1835 '''
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001836 self.assertTrue(isinstance(self.parse(s2), FileAST))
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001837
Nate Bogdanowicz14b8a7e2017-02-22 08:54:05 -05001838 def test_ambiguous_parameters(self):
1839 # From ISO/IEC 9899:TC2, 6.7.5.3.11:
1840 # "If, in a parameter declaration, an identifier can be treated either
1841 # as a typedef name or as a parameter name, it shall be taken as a
1842 # typedef name."
1843
1844 # foo takes an int named aa
1845 # bar takes a function taking a TT
1846 s1 = r'''
1847 typedef char TT;
1848 int foo(int (aa));
1849 int bar(int (TT));
1850 '''
1851 s1_ast = self.parse(s1)
1852 self.assertEqual(expand_decl(s1_ast.ext[1].type.args.params[0]),
1853 ['Decl', 'aa', ['TypeDecl', ['IdentifierType', ['int']]]])
1854 self.assertEqual(expand_decl(s1_ast.ext[2].type.args.params[0]),
1855 ['Typename', ['FuncDecl',
1856 [['Typename', ['TypeDecl', ['IdentifierType', ['TT']]]]],
1857 ['TypeDecl', ['IdentifierType', ['int']]]]])
1858
1859 # foo takes a function taking a char
1860 # bar takes a function taking a function taking a char
1861 s2 = r'''
1862 typedef char TT;
1863 int foo(int (aa (char)));
1864 int bar(int (TT (char)));
1865 '''
1866 s2_ast = self.parse(s2)
1867 self.assertEqual(expand_decl(s2_ast.ext[1].type.args.params[0]),
1868 ['Decl', 'aa', ['FuncDecl',
1869 [['Typename', ['TypeDecl', ['IdentifierType', ['char']]]]],
1870 ['TypeDecl', ['IdentifierType', ['int']]]]])
1871 self.assertEqual(expand_decl(s2_ast.ext[2].type.args.params[0]),
1872 ['Typename', ['FuncDecl',
1873 [['Typename', ['FuncDecl',
1874 [['Typename', ['TypeDecl', ['IdentifierType', ['char']]]]],
1875 ['TypeDecl', ['IdentifierType', ['TT']]]]]],
1876 ['TypeDecl', ['IdentifierType', ['int']]]]])
1877
1878
1879 # foo takes an int array named aa
1880 # bar takes a function taking a TT array
1881 s3 = r'''
1882 typedef char TT;
1883 int foo(int (aa[]));
1884 int bar(int (TT[]));
1885 '''
1886 s3_ast = self.parse(s3)
1887 self.assertEqual(expand_decl(s3_ast.ext[1].type.args.params[0]),
1888 ['Decl', 'aa', ['ArrayDecl', '', [], ['TypeDecl', ['IdentifierType', ['int']]]]])
1889 self.assertEqual(expand_decl(s3_ast.ext[2].type.args.params[0]),
1890 ['Typename', ['FuncDecl',
1891 [['Typename', ['ArrayDecl', '', [], ['TypeDecl', ['IdentifierType', ['TT']]]]]],
1892 ['TypeDecl', ['IdentifierType', ['int']]]]])
1893
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001894 def test_innerscope_reuse_typedef_name(self):
1895 # identifiers can be reused in inner scopes; the original should be
1896 # restored at the end of the block
1897 s1 = r'''
1898 typedef char TT;
1899 void foo(void) {
1900 unsigned TT;
1901 TT = 10;
1902 }
1903 TT x = 5;
1904 '''
1905 s1_ast = self.parse(s1)
1906 self.assertEqual(expand_decl(s1_ast.ext[1].body.block_items[0]),
1907 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
Eli Bendersky3877c4c2013-07-13 06:54:04 -07001908 self.assertEqual(expand_decl(s1_ast.ext[2]),
1909 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['TT']]]])
eli.bendersky85d2e732011-05-20 19:47:26 +03001910
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001911 # this should be recognized even with an initializer
1912 s2 = r'''
1913 typedef char TT;
1914 void foo(void) {
1915 unsigned TT = 10;
1916 }
1917 '''
1918 s2_ast = self.parse(s2)
1919 self.assertEqual(expand_decl(s2_ast.ext[1].body.block_items[0]),
1920 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1921
1922 # before the second local variable, TT is a type; after, it's a
1923 # variable
1924 s3 = r'''
1925 typedef char TT;
1926 void foo(void) {
1927 TT tt = sizeof(TT);
1928 unsigned TT = 10;
1929 }
1930 '''
1931 s3_ast = self.parse(s3)
1932 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[0]),
1933 ['Decl', 'tt', ['TypeDecl', ['IdentifierType', ['TT']]]])
1934 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[1]),
1935 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1936
1937 # a variable and its type can even share the same name
1938 s4 = r'''
1939 typedef char TT;
1940 void foo(void) {
1941 TT TT = sizeof(TT);
1942 unsigned uu = TT * 2;
1943 }
1944 '''
1945 s4_ast = self.parse(s4)
1946 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[0]),
1947 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['TT']]]])
1948 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[1]),
1949 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1950
1951 # ensure an error is raised if a type, redeclared as a variable, is
1952 # used as a type
1953 s5 = r'''
1954 typedef char TT;
1955 void foo(void) {
1956 unsigned TT = 10;
1957 TT erroneous = 20;
1958 }
1959 '''
1960 self.assertRaises(ParseError, self.parse, s5)
1961
Nate Bogdanowicz14b8a7e2017-02-22 08:54:05 -05001962 # reusing a type name should work with multiple declarators
1963 s6 = r'''
1964 typedef char TT;
1965 void foo(void) {
1966 unsigned TT, uu;
1967 }
1968 '''
1969 s6_ast = self.parse(s6)
1970 items = s6_ast.ext[1].body.block_items
1971 self.assertEqual(expand_decl(items[0]),
1972 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1973 self.assertEqual(expand_decl(items[1]),
1974 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1975
1976 # reusing a type name should work after a pointer
1977 s7 = r'''
1978 typedef char TT;
1979 void foo(void) {
1980 unsigned * TT;
1981 }
1982 '''
1983 s7_ast = self.parse(s7)
1984 items = s7_ast.ext[1].body.block_items
1985 self.assertEqual(expand_decl(items[0]),
1986 ['Decl', 'TT', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['unsigned']]]]])
1987
1988 # redefine a name in the middle of a multi-declarator declaration
1989 s8 = r'''
1990 typedef char TT;
1991 void foo(void) {
1992 int tt = sizeof(TT), TT, uu = sizeof(TT);
1993 int uu = sizeof(tt);
1994 }
1995 '''
1996 s8_ast = self.parse(s8)
1997 items = s8_ast.ext[1].body.block_items
1998 self.assertEqual(expand_decl(items[0]),
1999 ['Decl', 'tt', ['TypeDecl', ['IdentifierType', ['int']]]])
2000 self.assertEqual(expand_decl(items[1]),
2001 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['int']]]])
2002 self.assertEqual(expand_decl(items[2]),
2003 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['int']]]])
2004
2005 # Don't test this until we have support for it
2006 # self.assertEqual(expand_init(items[0].init),
2007 # ['UnaryOp', 'sizeof', ['Typename', ['TypeDecl', ['IdentifierType', ['TT']]]]])
2008 # self.assertEqual(expand_init(items[2].init),
2009 # ['UnaryOp', 'sizeof', ['ID', 'TT']])
2010
Sye van der Veen9ec6c422013-07-11 09:10:38 -04002011 def test_parameter_reuse_typedef_name(self):
2012 # identifiers can be reused as parameter names; parameter name scope
2013 # begins and ends with the function body; it's important that TT is
Eli Bendersky4d969b32013-07-13 06:07:07 -07002014 # used immediately before the LBRACE or after the RBRACE, to test
2015 # a corner case
Sye van der Veen9ec6c422013-07-11 09:10:38 -04002016 s1 = r'''
2017 typedef char TT;
2018 void foo(unsigned TT, TT bar) {
2019 TT = 10;
2020 }
2021 TT x = 5;
2022 '''
2023 s1_ast = self.parse(s1)
2024 self.assertEqual(expand_decl(s1_ast.ext[1].decl),
2025 ['Decl', 'foo',
2026 ['FuncDecl',
2027 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
2028 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
2029 ['TypeDecl', ['IdentifierType', ['void']]]]])
2030
2031 # the scope of a parameter name in a function declaration ends at the
2032 # end of the declaration...so it is effectively never used; it's
2033 # important that TT is used immediately after the declaration, to
2034 # test a corner case
2035 s2 = r'''
2036 typedef char TT;
2037 void foo(unsigned TT, TT bar);
2038 TT x = 5;
2039 '''
2040 s2_ast = self.parse(s2)
2041 self.assertEqual(expand_decl(s2_ast.ext[1]),
2042 ['Decl', 'foo',
2043 ['FuncDecl',
2044 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
2045 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
2046 ['TypeDecl', ['IdentifierType', ['void']]]]])
2047
2048 # ensure an error is raised if a type, redeclared as a parameter, is
2049 # used as a type
2050 s3 = r'''
2051 typedef char TT;
2052 void foo(unsigned TT, TT bar) {
2053 TT erroneous = 20;
2054 }
2055 '''
2056 self.assertRaises(ParseError, self.parse, s3)
2057
2058 def test_nested_function_decls(self):
2059 # parameter names of nested function declarations must not escape into
2060 # the top-level function _definition's_ scope; the following must
2061 # succeed because TT is still a typedef inside foo's body
2062 s1 = r'''
2063 typedef char TT;
2064 void foo(unsigned bar(int TT)) {
2065 TT x = 10;
2066 }
2067 '''
2068 self.assertTrue(isinstance(self.parse(s1), FileAST))
2069
2070 def test_samescope_reuse_name(self):
2071 # a typedef name cannot be reused as an object name in the same scope
2072 s1 = r'''
2073 typedef char TT;
2074 char TT = 5;
2075 '''
2076 self.assertRaises(ParseError, self.parse, s1)
2077
2078 # ...and vice-versa
2079 s2 = r'''
2080 char TT = 5;
2081 typedef char TT;
2082 '''
2083 self.assertRaises(ParseError, self.parse, s2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03002084
Julian Hammerdb9f2da2015-10-12 15:52:12 +02002085
Eli Bendersky3921e8e2010-05-21 09:05:39 +03002086if __name__ == '__main__':
2087 #~ suite = unittest.TestLoader().loadTestsFromNames(
2088 #~ ['test_c_parser.TestCParser_fundamentals.test_typedef'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08002089
Eli Bendersky3921e8e2010-05-21 09:05:39 +03002090 #~ unittest.TextTestRunner(verbosity=2).run(suite)
2091 unittest.main()