blob: d461cb176ec218805a196679b38426ebef330c7c [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 Benderskycecb6382018-06-15 05:36:02 -0700396 self.assertEqual(self.get_decl('int (*k)(const volatile int* q);'),
397 ['Decl', 'k',
398 ['PtrDecl',
399 ['FuncDecl',
400 [['Decl', ['const', 'volatile'], 'q',
401 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['int']]]]]],
402 ['TypeDecl', ['IdentifierType', ['int']]]]]])
403
eli.bendersky79d5cf62010-10-29 13:33:52 +0200404 # restrict qualifier
405 self.assertEqual(self.get_decl('int (*k)(restrict int* q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800406 ['Decl', 'k',
407 ['PtrDecl',
408 ['FuncDecl',
409 [['Decl', ['restrict'], 'q',
eli.bendersky79d5cf62010-10-29 13:33:52 +0200410 ['PtrDecl',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800411 ['TypeDecl', ['IdentifierType', ['int']]]]]],
eli.bendersky79d5cf62010-10-29 13:33:52 +0200412 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800413
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800414 def test_func_decls_with_array_dim_qualifiers(self):
415 self.assertEqual(self.get_decl('int zz(int p[static 10]);'),
416 ['Decl', 'zz',
417 ['FuncDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800418 [['Decl', 'p', ['ArrayDecl', '10', ['static'],
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800419 ['TypeDecl', ['IdentifierType', ['int']]]]]],
420 ['TypeDecl', ['IdentifierType', ['int']]]]])
421
422 self.assertEqual(self.get_decl('int zz(int p[const 10]);'),
423 ['Decl', 'zz',
424 ['FuncDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800425 [['Decl', 'p', ['ArrayDecl', '10', ['const'],
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800426 ['TypeDecl', ['IdentifierType', ['int']]]]]],
427 ['TypeDecl', ['IdentifierType', ['int']]]]])
428
necase4a6afa02014-12-19 16:38:37 -0600429 self.assertEqual(self.get_decl('int zz(int p[restrict][5]);'),
430 ['Decl', 'zz',
431 ['FuncDecl',
432 [['Decl', 'p', ['ArrayDecl', '', ['restrict'],
433 ['ArrayDecl', '5', [],
434 ['TypeDecl', ['IdentifierType', ['int']]]]]]],
435 ['TypeDecl', ['IdentifierType', ['int']]]]])
436
437 self.assertEqual(self.get_decl('int zz(int p[const restrict static 10][5]);'),
438 ['Decl', 'zz',
439 ['FuncDecl',
440 [['Decl', 'p', ['ArrayDecl', '10', ['const', 'restrict', 'static'],
441 ['ArrayDecl', '5', [],
442 ['TypeDecl', ['IdentifierType', ['int']]]]]]],
443 ['TypeDecl', ['IdentifierType', ['int']]]]])
444
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300445 def test_qualifiers_storage_specifiers(self):
446 def assert_qs(txt, index, quals, storage):
447 d = self.parse(txt).ext[index]
448 self.assertEqual(d.quals, quals)
449 self.assertEqual(d.storage, storage)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800450
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300451 assert_qs("extern int p;", 0, [], ['extern'])
452 assert_qs("const long p = 6;", 0, ['const'], [])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800453
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300454 d1 = "static const int p, q, r;"
455 for i in range(3):
456 assert_qs(d1, i, ['const'], ['static'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800457
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300458 d2 = "static char * const p;"
459 assert_qs(d2, 0, [], ['static'])
460 pdecl = self.parse(d2).ext[0].type
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300461 self.assertTrue(isinstance(pdecl, PtrDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300462 self.assertEqual(pdecl.quals, ['const'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800463
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300464 def test_sizeof(self):
465 e = """
466 void foo()
467 {
468 int a = sizeof k;
469 int b = sizeof(int);
eli.benderskyc51e1d32011-02-04 08:52:33 +0200470 int c = sizeof(int**);;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800471
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300472 char* p = "just to make sure this parses w/o error...";
473 int d = sizeof(int());
474 }
475 """
476 compound = self.parse(e).ext[0].body
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800477
eli.benderskyef29ff92010-10-29 16:25:43 +0200478 s1 = compound.block_items[0].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300479 self.assertTrue(isinstance(s1, UnaryOp))
480 self.assertEqual(s1.op, 'sizeof')
481 self.assertTrue(isinstance(s1.expr, ID))
482 self.assertEqual(s1.expr.name, 'k')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800483
eli.benderskyef29ff92010-10-29 16:25:43 +0200484 s2 = compound.block_items[1].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300485 self.assertEqual(expand_decl(s2.expr),
486 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800487
eli.benderskyef29ff92010-10-29 16:25:43 +0200488 s3 = compound.block_items[2].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300489 self.assertEqual(expand_decl(s3.expr),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800490 ['Typename',
491 ['PtrDecl',
492 ['PtrDecl',
493 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300494 ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800495
Eli Benderskye59395b2015-05-09 15:20:46 -0700496 def test_offsetof(self):
497 e = """
498 void foo() {
499 int a = offsetof(struct S, p);
500 a.b = offsetof(struct sockaddr, sp) + strlen(bar);
ksero749650a2016-09-09 07:31:09 +0200501 int a = offsetof(struct S, p.q.r);
502 int a = offsetof(struct S, p[5].q[4][5]);
Eli Benderskye59395b2015-05-09 15:20:46 -0700503 }
504 """
505 compound = self.parse(e).ext[0].body
506 s1 = compound.block_items[0].init
Eli Benderskya71ec1b2015-05-10 06:31:20 -0700507 self.assertTrue(isinstance(s1, FuncCall))
508 self.assertTrue(isinstance(s1.name, ID))
Eli Benderskye59395b2015-05-09 15:20:46 -0700509 self.assertEqual(s1.name.name, 'offsetof')
Eli Benderskya71ec1b2015-05-10 06:31:20 -0700510 self.assertTrue(isinstance(s1.args.exprs[0], Typename))
511 self.assertTrue(isinstance(s1.args.exprs[1], ID))
ksero749650a2016-09-09 07:31:09 +0200512 s3 = compound.block_items[2].init
513 self.assertTrue(isinstance(s3.args.exprs[1], StructRef))
514 s4 = compound.block_items[3].init
515 self.assertTrue(isinstance(s4.args.exprs[1], ArrayRef))
Eli Benderskye59395b2015-05-09 15:20:46 -0700516
Eli Benderskydbf9be22016-10-11 20:44:32 -0700517 def test_compound_statement(self):
518 e = """
519 void foo() {
520 }
521 """
522 compound = self.parse(e).ext[0].body
523 self.assertTrue(isinstance(compound, Compound))
serpilliere471442f2017-03-10 15:02:00 +0100524 self.assert_coord(compound, 2)
Eli Benderskydbf9be22016-10-11 20:44:32 -0700525
eli.bendersky9f481562010-10-30 15:50:47 +0200526 # The C99 compound literal feature
527 #
eli.benderskyf890a862010-10-30 12:13:23 +0200528 def test_compound_literals(self):
eli.bendersky9f481562010-10-30 15:50:47 +0200529 ps1 = self.parse(r'''
eli.benderskyf890a862010-10-30 12:13:23 +0200530 void foo() {
eli.bendersky9f481562010-10-30 15:50:47 +0200531 p = (long long){k};
532 tc = (struct jk){.a = {1, 2}, .b[0] = t};
533 }''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800534
eli.bendersky9f481562010-10-30 15:50:47 +0200535 compound = ps1.ext[0].body.block_items[0].rvalue
536 self.assertEqual(expand_decl(compound.type),
537 ['Typename', ['TypeDecl', ['IdentifierType', ['long', 'long']]]])
538 self.assertEqual(expand_init(compound.init),
539 [['ID', 'k']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800540
541 compound = ps1.ext[0].body.block_items[1].rvalue
eli.bendersky9f481562010-10-30 15:50:47 +0200542 self.assertEqual(expand_decl(compound.type),
543 ['Typename', ['TypeDecl', ['Struct', 'jk', []]]])
544 self.assertEqual(expand_init(compound.init),
545 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800546 ([['ID', 'a']], [['Constant', 'int', '1'], ['Constant', 'int', '2']]),
eli.bendersky9f481562010-10-30 15:50:47 +0200547 ([['ID', 'b'], ['Constant', 'int', '0']], ['ID', 't'])])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800548
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300549 def test_enums(self):
550 e1 = "enum mycolor op;"
551 e1_type = self.parse(e1).ext[0].type.type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800552
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300553 self.assertTrue(isinstance(e1_type, Enum))
554 self.assertEqual(e1_type.name, 'mycolor')
555 self.assertEqual(e1_type.values, None)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800556
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300557 e2 = "enum mysize {large=20, small, medium} shoes;"
558 e2_type = self.parse(e2).ext[0].type.type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800559
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300560 self.assertTrue(isinstance(e2_type, Enum))
561 self.assertEqual(e2_type.name, 'mysize')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800562
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300563 e2_elist = e2_type.values
564 self.assertTrue(isinstance(e2_elist, EnumeratorList))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800565
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300566 for e2_eval in e2_elist.enumerators:
567 self.assertTrue(isinstance(e2_eval, Enumerator))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800568
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300569 self.assertEqual(e2_elist.enumerators[0].name, 'large')
570 self.assertEqual(e2_elist.enumerators[0].value.value, '20')
571 self.assertEqual(e2_elist.enumerators[2].name, 'medium')
572 self.assertEqual(e2_elist.enumerators[2].value, None)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800573
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300574 # enum with trailing comma (C99 feature)
575 e3 = """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800576 enum
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300577 {
578 red,
579 blue,
580 green,
581 } color;
582 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800583
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300584 e3_type = self.parse(e3).ext[0].type.type
585 self.assertTrue(isinstance(e3_type, Enum))
586 e3_elist = e3_type.values
587 self.assertTrue(isinstance(e3_elist, EnumeratorList))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800588
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300589 for e3_eval in e3_elist.enumerators:
590 self.assertTrue(isinstance(e3_eval, Enumerator))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800591
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300592 self.assertEqual(e3_elist.enumerators[0].name, 'red')
593 self.assertEqual(e3_elist.enumerators[0].value, None)
594 self.assertEqual(e3_elist.enumerators[1].name, 'blue')
595 self.assertEqual(e3_elist.enumerators[2].name, 'green')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800596
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300597 def test_typedef(self):
598 # without typedef, error
599 s1 = """
600 node k;
601 """
602 self.assertRaises(ParseError, self.parse, s1)
603
604 # now with typedef, works
605 s2 = """
606 typedef void* node;
607 node k;
608 """
609 ps2 = self.parse(s2)
610 self.assertEqual(expand_decl(ps2.ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800611 ['Typedef', 'node',
612 ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300613 ['TypeDecl', ['IdentifierType', ['void']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800614
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300615 self.assertEqual(expand_decl(ps2.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800616 ['Decl', 'k',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300617 ['TypeDecl', ['IdentifierType', ['node']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800618
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300619 s3 = """
620 typedef int T;
621 typedef T *pT;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800622
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300623 pT aa, bb;
624 """
625 ps3 = self.parse(s3)
626 self.assertEqual(expand_decl(ps3.ext[3]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800627 ['Decl', 'bb',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300628 ['TypeDecl', ['IdentifierType', ['pT']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800629
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300630 s4 = '''
631 typedef char* __builtin_va_list;
632 typedef __builtin_va_list __gnuc_va_list;
633 '''
634 ps4 = self.parse(s4)
635 self.assertEqual(expand_decl(ps4.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800636 ['Typedef', '__gnuc_va_list',
637 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300638 ['IdentifierType', ['__builtin_va_list']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800639
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300640 s5 = '''typedef struct tagHash Hash;'''
641 ps5 = self.parse(s5)
642 self.assertEqual(expand_decl(ps5.ext[0]),
643 ['Typedef', 'Hash', ['TypeDecl', ['Struct', 'tagHash', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800644
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300645 def test_struct_union(self):
646 s1 = """
647 struct {
648 int id;
649 char* name;
650 } joe;
651 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800652
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300653 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800654 ['Decl', 'joe',
655 ['TypeDecl', ['Struct', None,
656 [ ['Decl', 'id',
657 ['TypeDecl',
658 ['IdentifierType', ['int']]]],
659 ['Decl', 'name',
660 ['PtrDecl',
661 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300662 ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800663
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300664 s2 = """
665 struct node p;
666 """
667 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800668 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300669 ['TypeDecl', ['Struct', 'node', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800670
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300671 s21 = """
672 union pri ra;
673 """
674 self.assertEqual(expand_decl(self.parse(s21).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800675 ['Decl', 'ra',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300676 ['TypeDecl', ['Union', 'pri', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800677
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300678 s3 = """
679 struct node* p;
680 """
681 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800682 ['Decl', 'p',
683 ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300684 ['TypeDecl', ['Struct', 'node', []]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800685
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300686 s4 = """
687 struct node;
688 """
689 self.assertEqual(expand_decl(self.parse(s4).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800690 ['Decl', None,
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300691 ['Struct', 'node', []]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800692
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300693 s5 = """
694 union
695 {
696 struct
697 {
698 int type;
699 } n;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800700
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300701 struct
702 {
703 int type;
704 int intnode;
705 } ni;
706 } u;
707 """
708 self.assertEqual(expand_decl(self.parse(s5).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800709 ['Decl', 'u',
710 ['TypeDecl',
711 ['Union', None,
712 [['Decl', 'n',
713 ['TypeDecl',
714 ['Struct', None,
715 [['Decl', 'type',
716 ['TypeDecl', ['IdentifierType', ['int']]]]]]]],
717 ['Decl', 'ni',
718 ['TypeDecl',
719 ['Struct', None,
720 [['Decl', 'type',
721 ['TypeDecl', ['IdentifierType', ['int']]]],
722 ['Decl', 'intnode',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300723 ['TypeDecl', ['IdentifierType', ['int']]]]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800724
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300725 s6 = """
726 typedef struct foo_tag
727 {
728 void* data;
729 } foo, *pfoo;
730 """
731 s6_ast = self.parse(s6)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800732
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300733 self.assertEqual(expand_decl(s6_ast.ext[0]),
734 ['Typedef', 'foo',
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 self.assertEqual(expand_decl(s6_ast.ext[1]),
741 ['Typedef', 'pfoo',
742 ['PtrDecl',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800743 ['TypeDecl',
744 ['Struct', 'foo_tag',
745 [['Decl', 'data',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300746 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800747
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300748 s7 = r"""
749 struct _on_exit_args {
750 void * _fnargs[32];
751 void * _dso_handle[32];
752
753 long _fntypes;
754 #line 77 "D:\eli\cpp_stuff\libc_include/sys/reent.h"
755
756 long _is_cxa;
757 };
758 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800759
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300760 s7_ast = self.parse(s7, filename='test.c')
serpilliere471442f2017-03-10 15:02:00 +0100761 self.assert_coord(s7_ast.ext[0].type.decls[2], 6, 22, 'test.c')
762 self.assert_coord(s7_ast.ext[0].type.decls[3], 78, 22,
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300763 r'D:\eli\cpp_stuff\libc_include/sys/reent.h')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800764
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300765 s8 = """
766 typedef enum tagReturnCode {SUCCESS, FAIL} ReturnCode;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800767
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300768 typedef struct tagEntry
769 {
770 char* key;
771 char* value;
772 } Entry;
773
774
775 typedef struct tagNode
776 {
777 Entry* entry;
778
779 struct tagNode* next;
780 } Node;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800781
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300782 typedef struct tagHash
783 {
784 unsigned int table_size;
785
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800786 Node** heads;
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300787
788 } Hash;
789 """
790 s8_ast = self.parse(s8)
791 self.assertEqual(expand_decl(s8_ast.ext[3]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800792 ['Typedef', 'Hash',
793 ['TypeDecl', ['Struct', 'tagHash',
794 [['Decl', 'table_size',
795 ['TypeDecl', ['IdentifierType', ['unsigned', 'int']]]],
796 ['Decl', 'heads',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300797 ['PtrDecl', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['Node']]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800798
Eli Bendersky95e3b762016-03-19 05:21:59 -0700799 def test_struct_with_extra_semis_inside(self):
800 s1 = """
801 struct {
802 int a;;
803 } foo;
804 """
805 s1_ast = self.parse(s1)
806 self.assertEqual(expand_decl(s1_ast.ext[0]),
807 ['Decl', 'foo',
808 ['TypeDecl', ['Struct', None,
809 [['Decl', 'a',
810 ['TypeDecl', ['IdentifierType', ['int']]]]]]]])
811
812 s2 = """
813 struct {
814 int a;;;;
815 float b, c;
816 ;;
817 char d;
818 } foo;
819 """
820 s2_ast = self.parse(s2)
821 self.assertEqual(expand_decl(s2_ast.ext[0]),
822 ['Decl', 'foo',
823 ['TypeDecl', ['Struct', None,
824 [['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]],
825 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['float']]]],
826 ['Decl', 'c', ['TypeDecl', ['IdentifierType', ['float']]]],
827 ['Decl', 'd',
828 ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
829
eli.bendersky697ecc52011-02-10 07:05:13 +0200830 def test_anonymous_struct_union(self):
831 s1 = """
832 union
833 {
834 union
835 {
836 int i;
837 long l;
838 };
839
840 struct
841 {
842 int type;
843 int intnode;
844 };
845 } u;
846 """
847
848 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
849 ['Decl', 'u',
850 ['TypeDecl',
851 ['Union', None,
852 [['Decl', None,
853 ['Union', None,
854 [['Decl', 'i',
855 ['TypeDecl',
856 ['IdentifierType', ['int']]]],
857 ['Decl', 'l',
858 ['TypeDecl',
859 ['IdentifierType', ['long']]]]]]],
860 ['Decl', None,
861 ['Struct', None,
862 [['Decl', 'type',
863 ['TypeDecl',
864 ['IdentifierType', ['int']]]],
865 ['Decl', 'intnode',
866 ['TypeDecl',
867 ['IdentifierType', ['int']]]]]]]]]]])
868
869 s2 = """
870 struct
871 {
872 int i;
873 union
874 {
875 int id;
876 char* name;
877 };
878 float f;
879 } joe;
880 """
881
882 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
883 ['Decl', 'joe',
884 ['TypeDecl',
885 ['Struct', None,
886 [['Decl', 'i',
887 ['TypeDecl',
888 ['IdentifierType', ['int']]]],
889 ['Decl', None,
890 ['Union', None,
891 [['Decl', 'id',
892 ['TypeDecl',
893 ['IdentifierType', ['int']]]],
894 ['Decl', 'name',
895 ['PtrDecl',
896 ['TypeDecl',
897 ['IdentifierType', ['char']]]]]]]],
898 ['Decl', 'f',
899 ['TypeDecl',
900 ['IdentifierType', ['float']]]]]]]])
901
902 # ISO/IEC 9899:201x Commitee Draft 2010-11-16, N1539
903 # section 6.7.2.1, par. 19, example 1
904 s3 = """
905 struct v {
906 union {
907 struct { int i, j; };
908 struct { long k, l; } w;
909 };
910 int m;
911 } v1;
912 """
913
914 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
915 ['Decl', 'v1',
916 ['TypeDecl',
917 ['Struct', 'v',
918 [['Decl', None,
919 ['Union', None,
920 [['Decl', None,
921 ['Struct', None,
922 [['Decl', 'i',
923 ['TypeDecl',
924 ['IdentifierType', ['int']]]],
925 ['Decl', 'j',
926 ['TypeDecl',
927 ['IdentifierType', ['int']]]]]]],
928 ['Decl', 'w',
929 ['TypeDecl',
930 ['Struct', None,
931 [['Decl', 'k',
932 ['TypeDecl',
933 ['IdentifierType', ['long']]]],
934 ['Decl', 'l',
935 ['TypeDecl',
936 ['IdentifierType', ['long']]]]]]]]]]],
937 ['Decl', 'm',
938 ['TypeDecl',
939 ['IdentifierType', ['int']]]]]]]])
940
eli.benderskydce29a02011-02-10 07:55:00 +0200941 s4 = """
942 struct v {
943 int i;
944 float;
945 } v2;"""
eli.bendersky6b011792011-06-22 17:50:56 +0300946 # just make sure this doesn't raise ParseError
947 self.parse(s4)
eli.benderskydce29a02011-02-10 07:55:00 +0200948
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400949 def test_struct_members_namespace(self):
Eli Bendersky4d969b32013-07-13 06:07:07 -0700950 """ Tests that structure/union member names reside in a separate
951 namespace and can be named after existing types.
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400952 """
953 s1 = """
954 typedef int Name;
955 typedef Name NameArray[10];
956
957 struct {
958 Name Name;
959 Name NameArray[3];
960 } sye;
961
962 void main(void)
963 {
964 sye.Name = 1;
965 }
966 """
967
968 s1_ast = self.parse(s1)
969 self.assertEqual(expand_decl(s1_ast.ext[2]),
970 ['Decl', 'sye',
971 ['TypeDecl', ['Struct', None,
972 [ ['Decl', 'Name',
973 ['TypeDecl',
974 ['IdentifierType', ['Name']]]],
975 ['Decl', 'NameArray',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800976 ['ArrayDecl', '3', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400977 ['TypeDecl', ['IdentifierType', ['Name']]]]]]]]])
978 self.assertEqual(s1_ast.ext[3].body.block_items[0].lvalue.field.name, 'Name')
979
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200980 def test_struct_bitfields(self):
eli.bendersky38ed9a92010-10-09 09:29:59 +0200981 # a struct with two bitfields, one unnamed
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200982 s1 = """
983 struct {
984 int k:6;
985 int :2;
986 } joe;
987 """
988
989 parsed_struct = self.parse(s1).ext[0]
990
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800991 # We can see here the name of the decl for the unnamed bitfield is
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200992 # None, but expand_decl doesn't show bitfield widths
993 # ...
994 self.assertEqual(expand_decl(parsed_struct),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800995 ['Decl', 'joe',
996 ['TypeDecl', ['Struct', None,
997 [ ['Decl', 'k',
998 ['TypeDecl',
999 ['IdentifierType', ['int']]]],
1000 ['Decl', None,
1001 ['TypeDecl',
eli.bendersky0e0a71f2010-10-09 08:32:00 +02001002 ['IdentifierType', ['int']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001003
eli.bendersky0e0a71f2010-10-09 08:32:00 +02001004 # ...
1005 # so we test them manually
1006 self.assertEqual(parsed_struct.type.type.decls[0].bitsize.value, '6')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001007 self.assertEqual(parsed_struct.type.type.decls[1].bitsize.value, '2')
1008
ldore81a12ca2018-04-28 05:09:24 +02001009 def test_struct_empty(self):
1010 """
1011 Tests that parsing an empty struct works.
Eli Bendersky8ff80882018-07-25 05:36:22 -07001012
ldore81a12ca2018-04-28 05:09:24 +02001013 Empty structs do NOT follow C99 (See 6.2.5-20 of the C99 standard).
Eli Bendersky8ff80882018-07-25 05:36:22 -07001014 This is nevertheless supported by some compilers (clang, gcc),
1015 especially when using FORTIFY code.
ldore81a12ca2018-04-28 05:09:24 +02001016 Some compilers (visual) will fail to compile with an error.
1017 """
1018 # an empty struct. This is NOT C99 compliant
1019 s1 = """
1020 struct foo { };
1021 """
1022
1023 parsed_struct = self.parse(s1).ext[0]
ldore81a12ca2018-04-28 05:09:24 +02001024 self.assertEqual(expand_decl(parsed_struct),
Eli Bendersky92f65b62018-07-25 05:48:56 -07001025 ['Decl', None, ['Struct', 'foo', []]])
1026
1027 s2 = """struct { } foo;"""
1028 parsed_struct = self.parse(s2).ext[0]
1029 self.assertEqual(expand_decl(parsed_struct),
1030 ['Decl', 'foo', ['TypeDecl', ['Struct', None, []]]])
1031
1032 s3 = """union { } foo;"""
1033 parsed_struct = self.parse(s3).ext[0]
1034 self.assertEqual(expand_decl(parsed_struct),
1035 ['Decl', 'foo', ['TypeDecl', ['Union', None, []]]])
ldore81a12ca2018-04-28 05:09:24 +02001036
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001037 def test_tags_namespace(self):
1038 """ Tests that the tags of structs/unions/enums reside in a separate namespace and
1039 can be named after existing types.
1040 """
1041 s1 = """
1042 typedef int tagEntry;
1043
1044 struct tagEntry
1045 {
1046 char* key;
1047 char* value;
1048 } Entry;
1049 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001050
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001051 s1_ast = self.parse(s1)
1052 self.assertEqual(expand_decl(s1_ast.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001053 ['Decl', 'Entry',
1054 ['TypeDecl', ['Struct', 'tagEntry',
1055 [['Decl', 'key',
1056 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
1057 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001058 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001059
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001060 s2 = """
1061 struct tagEntry;
1062
1063 typedef struct tagEntry tagEntry;
1064
1065 struct tagEntry
1066 {
1067 char* key;
1068 char* value;
1069 } Entry;
1070 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001071
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001072 s2_ast = self.parse(s2)
1073 self.assertEqual(expand_decl(s2_ast.ext[2]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001074 ['Decl', 'Entry',
1075 ['TypeDecl', ['Struct', 'tagEntry',
1076 [['Decl', 'key',
1077 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
1078 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001079 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001080
1081 s3 = """
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001082 typedef int mytag;
1083
1084 enum mytag {ABC, CDE};
1085 enum mytag joe;
1086 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001087
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001088 s3_type = self.parse(s3).ext[1].type
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001089
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001090 self.assertTrue(isinstance(s3_type, Enum))
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001091 self.assertEqual(s3_type.name, 'mytag')
1092
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001093 def test_multi_decls(self):
1094 d1 = 'int a, b;'
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001095
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001096 self.assertEqual(self.get_decl(d1, 0),
1097 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
1098 self.assertEqual(self.get_decl(d1, 1),
1099 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['int']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001100
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001101 d2 = 'char* p, notp, ar[4];'
1102 self.assertEqual(self.get_decl(d2, 0),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001103 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001104 ['PtrDecl',
1105 ['TypeDecl', ['IdentifierType', ['char']]]]])
1106 self.assertEqual(self.get_decl(d2, 1),
1107 ['Decl', 'notp', ['TypeDecl', ['IdentifierType', ['char']]]])
1108 self.assertEqual(self.get_decl(d2, 2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001109 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001110 ['ArrayDecl', '4', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001111 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001112
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001113 def test_invalid_multiple_types_error(self):
1114 bad = [
1115 'int enum {ab, cd} fubr;',
1116 'enum kid char brbr;']
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001117
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001118 for b in bad:
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001119 self.assertRaises(ParseError, self.parse, b)
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001120
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001121 def test_duplicate_typedef(self):
1122 """ Tests that redeclarations of existing types are parsed correctly.
1123 This is non-standard, but allowed by many compilers.
1124 """
1125 d1 = '''
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001126 typedef int numbertype;
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001127 typedef int numbertype;
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001128 '''
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001129
1130 self.assertEqual(self.get_decl(d1, 0),
1131 ['Typedef', 'numbertype',
1132 ['TypeDecl', ['IdentifierType', ['int']]]])
1133 self.assertEqual(self.get_decl(d1, 1),
1134 ['Typedef', 'numbertype',
1135 ['TypeDecl', ['IdentifierType', ['int']]]])
1136
1137 d2 = '''
1138 typedef int (*funcptr)(int x);
1139 typedef int (*funcptr)(int x);
1140 '''
1141 self.assertEqual(self.get_decl(d2, 0),
1142 ['Typedef', 'funcptr',
1143 ['PtrDecl', ['FuncDecl',
1144 [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]],
1145 ['TypeDecl', ['IdentifierType', ['int']]]]]])
1146 self.assertEqual(self.get_decl(d2, 1),
1147 ['Typedef', 'funcptr',
1148 ['PtrDecl', ['FuncDecl',
1149 [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]],
1150 ['TypeDecl', ['IdentifierType', ['int']]]]]])
1151
1152 d3 = '''
1153 typedef int numberarray[5];
1154 typedef int numberarray[5];
1155 '''
1156 self.assertEqual(self.get_decl(d3, 0),
1157 ['Typedef', 'numberarray',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001158 ['ArrayDecl', '5', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001159 ['TypeDecl', ['IdentifierType', ['int']]]]])
1160 self.assertEqual(self.get_decl(d3, 1),
1161 ['Typedef', 'numberarray',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001162 ['ArrayDecl', '5', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001163 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001164
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001165 def test_decl_inits(self):
1166 d1 = 'int a = 16;'
eli.benderskyf890a862010-10-30 12:13:23 +02001167 #~ self.parse(d1).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001168 self.assertEqual(self.get_decl(d1),
1169 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
1170 self.assertEqual(self.get_decl_init(d1),
1171 ['Constant', 'int', '16'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001172
Eli Bendersky3b1b08d2012-06-15 12:37:54 +03001173 d1_1 = 'float f = 0xEF.56p1;'
1174 self.assertEqual(self.get_decl_init(d1_1),
1175 ['Constant', 'float', '0xEF.56p1'])
1176
Konstanty Bialkowski3bdbfdc2015-04-19 20:09:21 +10001177 d1_2 = 'int bitmask = 0b1001010;'
1178 self.assertEqual(self.get_decl_init(d1_2),
1179 ['Constant', 'int', '0b1001010'])
1180
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001181 d2 = 'long ar[] = {7, 8, 9};'
1182 self.assertEqual(self.get_decl(d2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001183 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001184 ['ArrayDecl', '', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001185 ['TypeDecl', ['IdentifierType', ['long']]]]])
1186 self.assertEqual(self.get_decl_init(d2),
1187 [ ['Constant', 'int', '7'],
1188 ['Constant', 'int', '8'],
eli.benderskyf890a862010-10-30 12:13:23 +02001189 ['Constant', 'int', '9']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001190
Eli Benderskyc830da82015-05-10 07:56:41 -07001191 d21 = 'long ar[4] = {};'
1192 self.assertEqual(self.get_decl_init(d21), [])
1193
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001194 d3 = 'char p = j;'
1195 self.assertEqual(self.get_decl(d3),
1196 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['char']]]])
1197 self.assertEqual(self.get_decl_init(d3),
1198 ['ID', 'j'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001199
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001200 d4 = "char x = 'c', *p = {0, 1, 2, {4, 5}, 6};"
1201 self.assertEqual(self.get_decl(d4, 0),
1202 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['char']]]])
1203 self.assertEqual(self.get_decl_init(d4, 0),
1204 ['Constant', 'char', "'c'"])
1205 self.assertEqual(self.get_decl(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001206 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001207 ['PtrDecl',
1208 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001209
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001210 self.assertEqual(self.get_decl_init(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001211 [ ['Constant', 'int', '0'],
1212 ['Constant', 'int', '1'],
1213 ['Constant', 'int', '2'],
1214 [['Constant', 'int', '4'],
1215 ['Constant', 'int', '5']],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001216 ['Constant', 'int', '6']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001217
eli.benderskyf890a862010-10-30 12:13:23 +02001218 def test_decl_named_inits(self):
1219 d1 = 'int a = {.k = 16};'
1220 self.assertEqual(self.get_decl_init(d1),
1221 [( [['ID', 'k']],
1222 ['Constant', 'int', '16'])])
1223
1224 d2 = 'int a = { [0].a = {1}, [1].a[0] = 2 };'
1225 self.assertEqual(self.get_decl_init(d2),
1226 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001227 ([['Constant', 'int', '0'], ['ID', 'a']],
1228 [['Constant', 'int', '1']]),
1229 ([['Constant', 'int', '1'], ['ID', 'a'], ['Constant', 'int', '0']],
eli.benderskyf890a862010-10-30 12:13:23 +02001230 ['Constant', 'int', '2'])])
1231
1232 d3 = 'int a = { .a = 1, .c = 3, 4, .b = 5};'
1233 self.assertEqual(self.get_decl_init(d3),
1234 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001235 ([['ID', 'a']], ['Constant', 'int', '1']),
1236 ([['ID', 'c']], ['Constant', 'int', '3']),
1237 ['Constant', 'int', '4'],
eli.benderskyf890a862010-10-30 12:13:23 +02001238 ([['ID', 'b']], ['Constant', 'int', '5'])])
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001239
1240 def test_function_definitions(self):
1241 def parse_fdef(str):
1242 return self.parse(str).ext[0]
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001243
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001244 def fdef_decl(fdef):
1245 return expand_decl(fdef.decl)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001246
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001247 f1 = parse_fdef('''
1248 int factorial(int p)
1249 {
1250 return 3;
1251 }
1252 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001253
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001254 self.assertEqual(fdef_decl(f1),
1255 ['Decl', 'factorial',
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001256 ['FuncDecl',
1257 [['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001258 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001259
eli.benderskyef29ff92010-10-29 16:25:43 +02001260 self.assertEqual(type(f1.body.block_items[0]), Return)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001261
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001262 f2 = parse_fdef('''
1263 char* zzz(int p, char* c)
1264 {
1265 int a;
1266 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001267
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001268 a = b + 2;
1269 return 3;
1270 }
1271 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001272
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001273 self.assertEqual(fdef_decl(f2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001274 ['Decl', 'zzz',
1275 ['FuncDecl',
1276 [ ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]],
1277 ['Decl', 'c', ['PtrDecl',
1278 ['TypeDecl', ['IdentifierType', ['char']]]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001279 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001280
1281 self.assertEqual(list(map(type, f2.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001282 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001283
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001284 f3 = parse_fdef('''
1285 char* zzz(p, c)
1286 long p, *c;
1287 {
1288 int a;
1289 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001290
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001291 a = b + 2;
1292 return 3;
1293 }
1294 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001295
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001296 self.assertEqual(fdef_decl(f3),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001297 ['Decl', 'zzz',
1298 ['FuncDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001299 [ ['ID', 'p'],
1300 ['ID', 'c']],
1301 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001302
1303 self.assertEqual(list(map(type, f3.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001304 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001305
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001306 self.assertEqual(expand_decl(f3.param_decls[0]),
1307 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['long']]]])
1308 self.assertEqual(expand_decl(f3.param_decls[1]),
1309 ['Decl', 'c', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['long']]]]])
1310
Sye van der Veen51a46ec2013-06-10 12:56:15 -04001311 # function return values and parameters may not have type information
1312 f4 = parse_fdef('''
1313 que(p)
1314 {
1315 return 3;
1316 }
1317 ''')
1318
1319 self.assertEqual(fdef_decl(f4),
1320 ['Decl', 'que',
1321 ['FuncDecl',
1322 [['ID', 'p']],
1323 ['TypeDecl', ['IdentifierType', ['int']]]]])
1324
eli.bendersky71540662010-07-03 12:58:52 +02001325 def test_unified_string_literals(self):
1326 # simple string, for reference
1327 d1 = self.get_decl_init('char* s = "hello";')
1328 self.assertEqual(d1, ['Constant', 'string', '"hello"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001329
eli.bendersky71540662010-07-03 12:58:52 +02001330 d2 = self.get_decl_init('char* s = "hello" " world";')
1331 self.assertEqual(d2, ['Constant', 'string', '"hello world"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001332
eli.bendersky71540662010-07-03 12:58:52 +02001333 # the test case from issue 6
1334 d3 = self.parse(r'''
1335 int main() {
1336 fprintf(stderr,
1337 "Wrong Params?\n"
1338 "Usage:\n"
1339 "%s <binary_file_path>\n",
1340 argv[0]
1341 );
1342 }
1343 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001344
eli.bendersky71540662010-07-03 12:58:52 +02001345 self.assertEqual(
eli.benderskyef29ff92010-10-29 16:25:43 +02001346 d3.ext[0].body.block_items[0].args.exprs[1].value,
eli.bendersky71540662010-07-03 12:58:52 +02001347 r'"Wrong Params?\nUsage:\n%s <binary_file_path>\n"')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001348
eli.bendersky4a89f112010-07-05 06:02:03 +02001349 d4 = self.get_decl_init('char* s = "" "foobar";')
1350 self.assertEqual(d4, ['Constant', 'string', '"foobar"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001351
eli.bendersky4a89f112010-07-05 06:02:03 +02001352 d5 = self.get_decl_init(r'char* s = "foo\"" "bar";')
1353 self.assertEqual(d5, ['Constant', 'string', r'"foo\"bar"'])
eli.bendersky71540662010-07-03 12:58:52 +02001354
Eli Benderskyc9f1a382014-03-15 14:12:00 -07001355 def test_unified_wstring_literals(self):
1356 d1 = self.get_decl_init('char* s = L"hello" L"world";')
1357 self.assertEqual(d1, ['Constant', 'string', 'L"helloworld"'])
1358
1359 d2 = self.get_decl_init('char* s = L"hello " L"world" L" and I";')
1360 self.assertEqual(d2, ['Constant', 'string', 'L"hello world and I"'])
1361
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001362 def test_inline_specifier(self):
eli.bendersky79d5cf62010-10-29 13:33:52 +02001363 ps2 = self.parse('static inline void inlinefoo(void);')
1364 self.assertEqual(ps2.ext[0].funcspec, ['inline'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001365
eli.bendersky2e907fa2010-10-29 15:51:07 +02001366 # variable length array
1367 def test_vla(self):
1368 ps2 = self.parse(r'''
1369 int main() {
1370 int size;
1371 int var[size = 5];
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001372
eli.bendersky2e907fa2010-10-29 15:51:07 +02001373 int var2[*];
1374 }
1375 ''')
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001376 self.assertTrue(isinstance(ps2.ext[0].body.block_items[1].type.dim, Assignment))
1377 self.assertTrue(isinstance(ps2.ext[0].body.block_items[2].type.dim, ID))
eli.bendersky79d5cf62010-10-29 13:33:52 +02001378
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001379 def test_pragma(self):
1380 s1 = r'''
1381 #pragma bar
1382 void main() {
1383 #pragma foo
1384 for(;;) {}
Julian Hammer8a174062015-12-14 14:48:16 +01001385 #pragma
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001386 }
ldoreec233182017-11-22 14:52:53 +01001387 struct s {
1388 #pragma baz
1389 } s;
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001390 '''
1391 s1_ast = self.parse(s1)
1392 self.assertTrue(isinstance(s1_ast.ext[0], Pragma))
1393 self.assertEqual(s1_ast.ext[0].string, 'bar')
Julian Hammer8a174062015-12-14 14:48:16 +01001394 self.assertEqual(s1_ast.ext[0].coord.line, 2)
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001395
1396 self.assertTrue(isinstance(s1_ast.ext[1].body.block_items[0], Pragma))
1397 self.assertEqual(s1_ast.ext[1].body.block_items[0].string, 'foo')
Julian Hammer8a174062015-12-14 14:48:16 +01001398 self.assertEqual(s1_ast.ext[1].body.block_items[0].coord.line, 4)
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001399
Julian Hammer8a174062015-12-14 14:48:16 +01001400 self.assertTrue(isinstance(s1_ast.ext[1].body.block_items[2], Pragma))
1401 self.assertEqual(s1_ast.ext[1].body.block_items[2].string, '')
1402 self.assertEqual(s1_ast.ext[1].body.block_items[2].coord.line, 6)
Eli Bendersky8ff80882018-07-25 05:36:22 -07001403
ldoreec233182017-11-22 14:52:53 +01001404 self.assertTrue(isinstance(s1_ast.ext[2].type.type.decls[0], Pragma))
1405 self.assertEqual(s1_ast.ext[2].type.type.decls[0].string, 'baz')
1406 self.assertEqual(s1_ast.ext[2].type.type.decls[0].coord.line, 9)
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001407
dbluhm7af2fb92018-03-03 06:18:26 -07001408 def test_pragmacomp_or_statement(self):
1409 s1 = r'''
1410 void main() {
1411 int sum = 0;
1412 for (int i; i < 3; i++)
1413 #pragma omp critical
1414 sum += 1;
1415
1416 while(sum < 10)
1417 #pragma omp critical
1418 sum += 1;
1419
1420 mylabel:
1421 #pragma foo
1422 sum += 10;
1423
1424 if (sum > 10)
1425 #pragma bar
1426 sum = 10;
1427
1428 switch (sum)
1429 case 10:
1430 #pragma foo
1431 sum = 20;
1432 }
1433 '''
1434 s1_ast = self.parse(s1)
1435 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[1], For))
1436 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[1].stmt, Compound))
1437 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[1].stmt.block_items[0], Pragma))
1438 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[1].stmt.block_items[1], Assignment))
1439 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[2], While))
1440 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[2].stmt, Compound))
1441 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[2].stmt.block_items[0], Pragma))
1442 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[2].stmt.block_items[1], Assignment))
1443 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[3], Label))
1444 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[3].stmt, Compound))
1445 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[3].stmt.block_items[0], Pragma))
1446 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[3].stmt.block_items[1], Assignment))
1447 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[4], If))
1448 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[4].iftrue, Compound))
1449 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[4].iftrue.block_items[0], Pragma))
1450 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[4].iftrue.block_items[1], Assignment))
1451 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[5], Switch))
1452 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[5].stmt.stmts[0], Compound))
1453 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[5].stmt.stmts[0].block_items[0], Pragma))
1454 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[5].stmt.stmts[0].block_items[1], Assignment))
1455
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001456
eli.bendersky85d2e732011-05-20 19:47:26 +03001457class TestCParser_whole_code(TestCParser_base):
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001458 """ Testing of parsing whole chunks of code.
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001459
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001460 Since I don't want to rely on the structure of ASTs too
1461 much, most of these tests are implemented with visitors.
1462 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001463 # A simple helper visitor that lists the values of all the
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001464 # Constant nodes it sees.
1465 #
1466 class ConstantVisitor(NodeVisitor):
1467 def __init__(self):
1468 self.values = []
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001469
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001470 def visit_Constant(self, node):
1471 self.values.append(node.value)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001472
1473 # This visitor counts the amount of references to the ID
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001474 # with the name provided to it in the constructor.
1475 #
1476 class IDNameCounter(NodeVisitor):
1477 def __init__(self, name):
1478 self.name = name
1479 self.nrefs = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001480
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001481 def visit_ID(self, node):
1482 if node.name == self.name:
1483 self.nrefs += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001484
1485 # Counts the amount of nodes of a given class
1486 #
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001487 class NodeKlassCounter(NodeVisitor):
1488 def __init__(self, node_klass):
1489 self.klass = node_klass
1490 self.n = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001491
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001492 def generic_visit(self, node):
1493 if node.__class__ == self.klass:
1494 self.n += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001495
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001496 NodeVisitor.generic_visit(self, node)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001497
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001498 def assert_all_Constants(self, code, constants):
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001499 """ Asserts that the list of all Constant values (by
1500 'preorder' appearance) in the chunk of code is as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001501 given.
1502 """
eli.benderskyed890492010-06-25 08:25:55 +03001503 if isinstance(code, str):
1504 parsed = self.parse(code)
1505 else:
1506 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001507
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001508 cv = self.ConstantVisitor()
1509 cv.visit(parsed)
1510 self.assertEqual(cv.values, constants)
1511
1512 def assert_num_ID_refs(self, code, name, num):
1513 """ Asserts the number of references to the ID with
1514 the given name.
1515 """
1516 if isinstance(code, str):
1517 parsed = self.parse(code)
1518 else:
1519 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001520
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001521 iv = self.IDNameCounter(name)
1522 iv.visit(parsed)
1523 self.assertEqual(iv.nrefs, num)
1524
1525 def assert_num_klass_nodes(self, code, klass, num):
1526 """ Asserts the amount of klass nodes in the code.
1527 """
1528 if isinstance(code, str):
1529 parsed = self.parse(code)
1530 else:
1531 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001532
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001533 cv = self.NodeKlassCounter(klass)
1534 cv.visit(parsed)
1535 self.assertEqual(cv.n, num)
1536
1537 def test_expressions(self):
1538 e1 = '''int k = (r + 10.0) >> 6 + 8 << (3 & 0x14);'''
1539 self.assert_all_Constants(e1, ['10.0', '6', '8', '3', '0x14'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001540
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001541 e2 = r'''char n = '\n', *prefix = "st_";'''
1542 self.assert_all_Constants(e2, [r"'\n'", '"st_"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001543
Eli Bendersky09e22a62013-07-02 06:00:36 -07001544 s1 = r'''int main() {
1545 int i = 5, j = 6, k = 1;
1546 if ((i=j && k == 1) || k > j)
1547 printf("Hello, world\n");
1548 return 0;
1549 }'''
1550 ps1 = self.parse(s1)
1551 self.assert_all_Constants(ps1,
1552 ['5', '6', '1', '1', '"Hello, world\\n"', '0'])
1553 self.assert_num_ID_refs(ps1, 'i', 1)
1554 self.assert_num_ID_refs(ps1, 'j', 2)
1555
1556
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001557 def test_statements(self):
1558 s1 = r'''
1559 void foo(){
1560 if (sp == 1)
1561 if (optind >= argc ||
1562 argv[optind][0] != '-' || argv[optind][1] == '\0')
1563 return -1;
1564 else if (strcmp(argv[optind], "--") == 0) {
1565 optind++;
1566 return -1;
1567 }
1568 }
1569 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001570
1571 self.assert_all_Constants(s1,
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001572 ['1', '0', r"'-'", '1', r"'\0'", '1', r'"--"', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001573
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001574 ps1 = self.parse(s1)
1575 self.assert_num_ID_refs(ps1, 'argv', 3)
1576 self.assert_num_ID_refs(ps1, 'optind', 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001577
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001578 self.assert_num_klass_nodes(ps1, If, 3)
1579 self.assert_num_klass_nodes(ps1, Return, 2)
1580 self.assert_num_klass_nodes(ps1, FuncCall, 1) # strcmp
1581 self.assert_num_klass_nodes(ps1, BinaryOp, 7)
1582
1583 # In the following code, Hash and Node were defined as
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001584 # int to pacify the parser that sees they're used as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001585 # types
1586 #
1587 s2 = r'''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001588 typedef int Hash, Node;
1589
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001590 void HashDestroy(Hash* hash)
1591 {
1592 unsigned int i;
1593
1594 if (hash == NULL)
1595 return;
1596
1597 for (i = 0; i < hash->table_size; ++i)
1598 {
1599 Node* temp = hash->heads[i];
1600
1601 while (temp != NULL)
1602 {
1603 Node* temp2 = temp;
1604
1605 free(temp->entry->key);
1606 free(temp->entry->value);
1607 free(temp->entry);
1608
1609 temp = temp->next;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001610
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001611 free(temp2);
1612 }
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001613 }
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001614
1615 free(hash->heads);
1616 hash->heads = NULL;
1617
1618 free(hash);
1619 }
1620 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001621
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001622 ps2 = self.parse(s2)
1623 self.assert_num_klass_nodes(ps2, FuncCall, 6)
1624 self.assert_num_klass_nodes(ps2, FuncDef, 1)
1625 self.assert_num_klass_nodes(ps2, For, 1)
1626 self.assert_num_klass_nodes(ps2, While, 1)
1627 self.assert_num_klass_nodes(ps2, StructRef, 10)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001628
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001629 # declarations don't count
1630 self.assert_num_ID_refs(ps2, 'hash', 6)
1631 self.assert_num_ID_refs(ps2, 'i', 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001632
eli.benderskyed890492010-06-25 08:25:55 +03001633 s3 = r'''
1634 void x(void) {
1635 int a, b;
1636 if (a < b)
1637 do {
1638 a = 0;
1639 } while (0);
1640 else if (a == b) {
1641 a = 1;
1642 }
1643 }
1644 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001645
eli.benderskyed890492010-06-25 08:25:55 +03001646 ps3 = self.parse(s3)
1647 self.assert_num_klass_nodes(ps3, DoWhile, 1)
1648 self.assert_num_ID_refs(ps3, 'a', 4)
1649 self.assert_all_Constants(ps3, ['0', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001650
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001651 def test_empty_statements(self):
eli.bendersky91c0aa32011-10-16 05:50:43 +02001652 s1 = r'''
1653 void foo(void){
1654 ;
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001655 return;;
1656
1657 ;
eli.bendersky91c0aa32011-10-16 05:50:43 +02001658 }
1659 '''
1660 ps1 = self.parse(s1)
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001661 self.assert_num_klass_nodes(ps1, EmptyStatement, 3)
eli.bendersky91c0aa32011-10-16 05:50:43 +02001662 self.assert_num_klass_nodes(ps1, Return, 1)
serpilliere471442f2017-03-10 15:02:00 +01001663 self.assert_coord(ps1.ext[0].body.block_items[0], 3)
1664 self.assert_coord(ps1.ext[0].body.block_items[1], 4)
1665 self.assert_coord(ps1.ext[0].body.block_items[2], 4)
1666 self.assert_coord(ps1.ext[0].body.block_items[3], 6)
eli.bendersky145890d2010-10-29 12:02:32 +02001667
Ben5cd3fd62012-02-03 06:02:40 +02001668 def test_switch_statement(self):
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001669 def assert_case_node(node, const_value):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001670 self.assertTrue(isinstance(node, Case))
1671 self.assertTrue(isinstance(node.expr, Constant))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001672 self.assertEqual(node.expr.value, const_value)
1673
1674 def assert_default_node(node):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001675 self.assertTrue(isinstance(node, Default))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001676
Ben5cd3fd62012-02-03 06:02:40 +02001677 s1 = r'''
1678 int foo(void) {
1679 switch (myvar) {
1680 case 10:
1681 k = 10;
1682 p = k + 1;
1683 return 10;
1684 case 20:
1685 case 30:
1686 return 20;
1687 default:
1688 break;
1689 }
1690 return 0;
1691 }
1692 '''
1693 ps1 = self.parse(s1)
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001694 switch = ps1.ext[0].body.block_items[0]
1695
1696 block = switch.stmt.block_items
1697 assert_case_node(block[0], '10')
1698 self.assertEqual(len(block[0].stmts), 3)
1699 assert_case_node(block[1], '20')
1700 self.assertEqual(len(block[1].stmts), 0)
1701 assert_case_node(block[2], '30')
1702 self.assertEqual(len(block[2].stmts), 1)
1703 assert_default_node(block[3])
1704
1705 s2 = r'''
1706 int foo(void) {
1707 switch (myvar) {
1708 default:
1709 joe = moe;
1710 return 10;
1711 case 10:
1712 case 20:
1713 case 30:
1714 case 40:
1715 break;
1716 }
1717 return 0;
1718 }
1719 '''
1720 ps2 = self.parse(s2)
1721 switch = ps2.ext[0].body.block_items[0]
1722
1723 block = switch.stmt.block_items
1724 assert_default_node(block[0])
1725 self.assertEqual(len(block[0].stmts), 2)
1726 assert_case_node(block[1], '10')
1727 self.assertEqual(len(block[1].stmts), 0)
1728 assert_case_node(block[2], '20')
1729 self.assertEqual(len(block[1].stmts), 0)
1730 assert_case_node(block[3], '30')
1731 self.assertEqual(len(block[1].stmts), 0)
1732 assert_case_node(block[4], '40')
1733 self.assertEqual(len(block[4].stmts), 1)
Ben5cd3fd62012-02-03 06:02:40 +02001734
eli.bendersky145890d2010-10-29 12:02:32 +02001735 def test_for_statement(self):
1736 s2 = r'''
1737 void x(void)
1738 {
1739 int i;
1740 for (i = 0; i < 5; ++i) {
1741 x = 50;
1742 }
1743 }
1744 '''
1745 ps2 = self.parse(s2)
1746 self.assert_num_klass_nodes(ps2, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001747 # here there are 3 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001748 # a ref in the visitor
1749 #
1750 self.assert_num_ID_refs(ps2, 'i', 3)
Eli Bendersky4476d092012-12-25 14:07:57 -08001751
eli.bendersky145890d2010-10-29 12:02:32 +02001752 s3 = r'''
1753 void x(void)
1754 {
1755 for (int i = 0; i < 5; ++i) {
1756 x = 50;
1757 }
1758 }
1759 '''
1760 ps3 = self.parse(s3)
eli.bendersky145890d2010-10-29 12:02:32 +02001761 self.assert_num_klass_nodes(ps3, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001762 # here there are 2 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001763 # a ref in the visitor
1764 #
1765 self.assert_num_ID_refs(ps3, 'i', 2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001766
Eli Bendersky4476d092012-12-25 14:07:57 -08001767 s4 = r'''
1768 void x(void) {
1769 for (int i = 0;;)
1770 i;
1771 }
1772 '''
1773 ps4 = self.parse(s4)
1774 self.assert_num_ID_refs(ps4, 'i', 1)
1775
Eli Benderskyd0973782012-01-19 08:09:33 +02001776 def _open_c_file(self, name):
1777 """ Find a c file by name, taking into account the current dir can be
1778 in a couple of typical places
1779 """
Stefano Riveraebaf5922013-08-08 09:45:26 +02001780 testdir = os.path.dirname(__file__)
1781 name = os.path.join(testdir, 'c_files', name)
1782 assert os.path.exists(name)
1783 return open(name, 'rU')
Eli Benderskyd0973782012-01-19 08:09:33 +02001784
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001785 def test_whole_file(self):
1786 # See how pycparser handles a whole, real C file.
1787 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001788 with self._open_c_file('memmgr_with_h.c') as f:
1789 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001790 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001791
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001792 self.assert_num_klass_nodes(p, FuncDef, 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001793
1794 # each FuncDef also has a FuncDecl. 4 declarations
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001795 # + 5 definitions, overall 9
1796 self.assert_num_klass_nodes(p, FuncDecl, 9)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001797
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001798 self.assert_num_klass_nodes(p, Typedef, 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001799
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001800 self.assertEqual(p.ext[4].coord.line, 88)
1801 self.assertEqual(p.ext[4].coord.file, "./memmgr.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001802
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001803 self.assertEqual(p.ext[6].coord.line, 10)
1804 self.assertEqual(p.ext[6].coord.file, "memmgr.c")
1805
1806 def test_whole_file_with_stdio(self):
1807 # Parse a whole file with stdio.h included by cpp
1808 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001809 with self._open_c_file('cppd_with_stdio_h.c') as f:
1810 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001811 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001812
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001813 self.assertTrue(isinstance(p.ext[0], Typedef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001814 self.assertEqual(p.ext[0].coord.line, 213)
Ville Skyttä2129f5f2017-03-05 04:52:22 +02001815 self.assertEqual(p.ext[0].coord.file, r"D:\eli\cpp_stuff\libc_include/stddef.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001816
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001817 self.assertTrue(isinstance(p.ext[-1], FuncDef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001818 self.assertEqual(p.ext[-1].coord.line, 15)
1819 self.assertEqual(p.ext[-1].coord.file, "example_c_file.c")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001820
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001821 self.assertTrue(isinstance(p.ext[-8], Typedef))
1822 self.assertTrue(isinstance(p.ext[-8].type, TypeDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001823 self.assertEqual(p.ext[-8].name, 'cookie_io_functions_t')
eli.bendersky85d2e732011-05-20 19:47:26 +03001824
1825
1826class TestCParser_typenames(TestCParser_base):
1827 """ Test issues related to the typedef-name problem.
1828 """
1829 def test_innerscope_typedef(self):
1830 # should fail since TT is not a type in bar
1831 s1 = r'''
1832 void foo() {
1833 typedef char TT;
1834 TT x;
1835 }
1836 void bar() {
1837 TT y;
1838 }
1839 '''
1840 self.assertRaises(ParseError, self.parse, s1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001841
eli.bendersky85d2e732011-05-20 19:47:26 +03001842 # should succeed since TT is not a type in bar
1843 s2 = r'''
1844 void foo() {
1845 typedef char TT;
1846 TT x;
1847 }
1848 void bar() {
1849 unsigned TT;
1850 }
1851 '''
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001852 self.assertTrue(isinstance(self.parse(s2), FileAST))
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001853
Nate Bogdanowicz14b8a7e2017-02-22 08:54:05 -05001854 def test_ambiguous_parameters(self):
1855 # From ISO/IEC 9899:TC2, 6.7.5.3.11:
1856 # "If, in a parameter declaration, an identifier can be treated either
1857 # as a typedef name or as a parameter name, it shall be taken as a
1858 # typedef name."
1859
1860 # foo takes an int named aa
1861 # bar takes a function taking a TT
1862 s1 = r'''
1863 typedef char TT;
1864 int foo(int (aa));
1865 int bar(int (TT));
1866 '''
1867 s1_ast = self.parse(s1)
1868 self.assertEqual(expand_decl(s1_ast.ext[1].type.args.params[0]),
1869 ['Decl', 'aa', ['TypeDecl', ['IdentifierType', ['int']]]])
1870 self.assertEqual(expand_decl(s1_ast.ext[2].type.args.params[0]),
1871 ['Typename', ['FuncDecl',
1872 [['Typename', ['TypeDecl', ['IdentifierType', ['TT']]]]],
1873 ['TypeDecl', ['IdentifierType', ['int']]]]])
1874
1875 # foo takes a function taking a char
1876 # bar takes a function taking a function taking a char
1877 s2 = r'''
1878 typedef char TT;
1879 int foo(int (aa (char)));
1880 int bar(int (TT (char)));
1881 '''
1882 s2_ast = self.parse(s2)
1883 self.assertEqual(expand_decl(s2_ast.ext[1].type.args.params[0]),
1884 ['Decl', 'aa', ['FuncDecl',
1885 [['Typename', ['TypeDecl', ['IdentifierType', ['char']]]]],
1886 ['TypeDecl', ['IdentifierType', ['int']]]]])
1887 self.assertEqual(expand_decl(s2_ast.ext[2].type.args.params[0]),
1888 ['Typename', ['FuncDecl',
1889 [['Typename', ['FuncDecl',
1890 [['Typename', ['TypeDecl', ['IdentifierType', ['char']]]]],
1891 ['TypeDecl', ['IdentifierType', ['TT']]]]]],
1892 ['TypeDecl', ['IdentifierType', ['int']]]]])
1893
1894
1895 # foo takes an int array named aa
1896 # bar takes a function taking a TT array
1897 s3 = r'''
1898 typedef char TT;
1899 int foo(int (aa[]));
1900 int bar(int (TT[]));
1901 '''
1902 s3_ast = self.parse(s3)
1903 self.assertEqual(expand_decl(s3_ast.ext[1].type.args.params[0]),
1904 ['Decl', 'aa', ['ArrayDecl', '', [], ['TypeDecl', ['IdentifierType', ['int']]]]])
1905 self.assertEqual(expand_decl(s3_ast.ext[2].type.args.params[0]),
1906 ['Typename', ['FuncDecl',
1907 [['Typename', ['ArrayDecl', '', [], ['TypeDecl', ['IdentifierType', ['TT']]]]]],
1908 ['TypeDecl', ['IdentifierType', ['int']]]]])
1909
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001910 def test_innerscope_reuse_typedef_name(self):
1911 # identifiers can be reused in inner scopes; the original should be
1912 # restored at the end of the block
1913 s1 = r'''
1914 typedef char TT;
1915 void foo(void) {
1916 unsigned TT;
1917 TT = 10;
1918 }
1919 TT x = 5;
1920 '''
1921 s1_ast = self.parse(s1)
1922 self.assertEqual(expand_decl(s1_ast.ext[1].body.block_items[0]),
1923 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
Eli Bendersky3877c4c2013-07-13 06:54:04 -07001924 self.assertEqual(expand_decl(s1_ast.ext[2]),
1925 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['TT']]]])
eli.bendersky85d2e732011-05-20 19:47:26 +03001926
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001927 # this should be recognized even with an initializer
1928 s2 = r'''
1929 typedef char TT;
1930 void foo(void) {
1931 unsigned TT = 10;
1932 }
1933 '''
1934 s2_ast = self.parse(s2)
1935 self.assertEqual(expand_decl(s2_ast.ext[1].body.block_items[0]),
1936 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1937
1938 # before the second local variable, TT is a type; after, it's a
1939 # variable
1940 s3 = r'''
1941 typedef char TT;
1942 void foo(void) {
1943 TT tt = sizeof(TT);
1944 unsigned TT = 10;
1945 }
1946 '''
1947 s3_ast = self.parse(s3)
1948 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[0]),
1949 ['Decl', 'tt', ['TypeDecl', ['IdentifierType', ['TT']]]])
1950 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[1]),
1951 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1952
1953 # a variable and its type can even share the same name
1954 s4 = r'''
1955 typedef char TT;
1956 void foo(void) {
1957 TT TT = sizeof(TT);
1958 unsigned uu = TT * 2;
1959 }
1960 '''
1961 s4_ast = self.parse(s4)
1962 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[0]),
1963 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['TT']]]])
1964 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[1]),
1965 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1966
1967 # ensure an error is raised if a type, redeclared as a variable, is
1968 # used as a type
1969 s5 = r'''
1970 typedef char TT;
1971 void foo(void) {
1972 unsigned TT = 10;
1973 TT erroneous = 20;
1974 }
1975 '''
1976 self.assertRaises(ParseError, self.parse, s5)
1977
Nate Bogdanowicz14b8a7e2017-02-22 08:54:05 -05001978 # reusing a type name should work with multiple declarators
1979 s6 = r'''
1980 typedef char TT;
1981 void foo(void) {
1982 unsigned TT, uu;
1983 }
1984 '''
1985 s6_ast = self.parse(s6)
1986 items = s6_ast.ext[1].body.block_items
1987 self.assertEqual(expand_decl(items[0]),
1988 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1989 self.assertEqual(expand_decl(items[1]),
1990 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1991
1992 # reusing a type name should work after a pointer
1993 s7 = r'''
1994 typedef char TT;
1995 void foo(void) {
1996 unsigned * TT;
1997 }
1998 '''
1999 s7_ast = self.parse(s7)
2000 items = s7_ast.ext[1].body.block_items
2001 self.assertEqual(expand_decl(items[0]),
2002 ['Decl', 'TT', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['unsigned']]]]])
2003
2004 # redefine a name in the middle of a multi-declarator declaration
2005 s8 = r'''
2006 typedef char TT;
2007 void foo(void) {
2008 int tt = sizeof(TT), TT, uu = sizeof(TT);
2009 int uu = sizeof(tt);
2010 }
2011 '''
2012 s8_ast = self.parse(s8)
2013 items = s8_ast.ext[1].body.block_items
2014 self.assertEqual(expand_decl(items[0]),
2015 ['Decl', 'tt', ['TypeDecl', ['IdentifierType', ['int']]]])
2016 self.assertEqual(expand_decl(items[1]),
2017 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['int']]]])
2018 self.assertEqual(expand_decl(items[2]),
2019 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['int']]]])
2020
2021 # Don't test this until we have support for it
2022 # self.assertEqual(expand_init(items[0].init),
2023 # ['UnaryOp', 'sizeof', ['Typename', ['TypeDecl', ['IdentifierType', ['TT']]]]])
2024 # self.assertEqual(expand_init(items[2].init),
2025 # ['UnaryOp', 'sizeof', ['ID', 'TT']])
2026
Sye van der Veen9ec6c422013-07-11 09:10:38 -04002027 def test_parameter_reuse_typedef_name(self):
2028 # identifiers can be reused as parameter names; parameter name scope
2029 # begins and ends with the function body; it's important that TT is
Eli Bendersky4d969b32013-07-13 06:07:07 -07002030 # used immediately before the LBRACE or after the RBRACE, to test
2031 # a corner case
Sye van der Veen9ec6c422013-07-11 09:10:38 -04002032 s1 = r'''
2033 typedef char TT;
2034 void foo(unsigned TT, TT bar) {
2035 TT = 10;
2036 }
2037 TT x = 5;
2038 '''
2039 s1_ast = self.parse(s1)
2040 self.assertEqual(expand_decl(s1_ast.ext[1].decl),
2041 ['Decl', 'foo',
2042 ['FuncDecl',
2043 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
2044 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
2045 ['TypeDecl', ['IdentifierType', ['void']]]]])
2046
2047 # the scope of a parameter name in a function declaration ends at the
2048 # end of the declaration...so it is effectively never used; it's
2049 # important that TT is used immediately after the declaration, to
2050 # test a corner case
2051 s2 = r'''
2052 typedef char TT;
2053 void foo(unsigned TT, TT bar);
2054 TT x = 5;
2055 '''
2056 s2_ast = self.parse(s2)
2057 self.assertEqual(expand_decl(s2_ast.ext[1]),
2058 ['Decl', 'foo',
2059 ['FuncDecl',
2060 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
2061 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
2062 ['TypeDecl', ['IdentifierType', ['void']]]]])
2063
2064 # ensure an error is raised if a type, redeclared as a parameter, is
2065 # used as a type
2066 s3 = r'''
2067 typedef char TT;
2068 void foo(unsigned TT, TT bar) {
2069 TT erroneous = 20;
2070 }
2071 '''
2072 self.assertRaises(ParseError, self.parse, s3)
2073
2074 def test_nested_function_decls(self):
2075 # parameter names of nested function declarations must not escape into
2076 # the top-level function _definition's_ scope; the following must
2077 # succeed because TT is still a typedef inside foo's body
2078 s1 = r'''
2079 typedef char TT;
2080 void foo(unsigned bar(int TT)) {
2081 TT x = 10;
2082 }
2083 '''
2084 self.assertTrue(isinstance(self.parse(s1), FileAST))
2085
2086 def test_samescope_reuse_name(self):
2087 # a typedef name cannot be reused as an object name in the same scope
2088 s1 = r'''
2089 typedef char TT;
2090 char TT = 5;
2091 '''
2092 self.assertRaises(ParseError, self.parse, s1)
2093
2094 # ...and vice-versa
2095 s2 = r'''
2096 char TT = 5;
2097 typedef char TT;
2098 '''
2099 self.assertRaises(ParseError, self.parse, s2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03002100
Julian Hammerdb9f2da2015-10-12 15:52:12 +02002101
Eli Bendersky3921e8e2010-05-21 09:05:39 +03002102if __name__ == '__main__':
2103 #~ suite = unittest.TestLoader().loadTestsFromNames(
2104 #~ ['test_c_parser.TestCParser_fundamentals.test_typedef'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08002105
Eli Bendersky3921e8e2010-05-21 09:05:39 +03002106 #~ unittest.TextTestRunner(verbosity=2).run(suite)
2107 unittest.main()