blob: fd85c0d4628140d5cdf375c9799438b00d4b074d [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.
1012
1013 Empty structs do NOT follow C99 (See 6.2.5-20 of the C99 standard).
1014 This is nevertheless supported by some compilers (clang, gcc),
1015 especially when using FORTIFY code.
1016 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]
1024
1025 self.assertEqual(expand_decl(parsed_struct),
1026 ['Decl', None, ['Struct', 'foo', []]]
1027 )
1028
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001029 def test_tags_namespace(self):
1030 """ Tests that the tags of structs/unions/enums reside in a separate namespace and
1031 can be named after existing types.
1032 """
1033 s1 = """
1034 typedef int tagEntry;
1035
1036 struct tagEntry
1037 {
1038 char* key;
1039 char* value;
1040 } Entry;
1041 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001042
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001043 s1_ast = self.parse(s1)
1044 self.assertEqual(expand_decl(s1_ast.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001045 ['Decl', 'Entry',
1046 ['TypeDecl', ['Struct', 'tagEntry',
1047 [['Decl', 'key',
1048 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
1049 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001050 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001051
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001052 s2 = """
1053 struct tagEntry;
1054
1055 typedef struct tagEntry tagEntry;
1056
1057 struct tagEntry
1058 {
1059 char* key;
1060 char* value;
1061 } Entry;
1062 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001063
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001064 s2_ast = self.parse(s2)
1065 self.assertEqual(expand_decl(s2_ast.ext[2]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001066 ['Decl', 'Entry',
1067 ['TypeDecl', ['Struct', 'tagEntry',
1068 [['Decl', 'key',
1069 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
1070 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001071 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001072
1073 s3 = """
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001074 typedef int mytag;
1075
1076 enum mytag {ABC, CDE};
1077 enum mytag joe;
1078 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001079
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001080 s3_type = self.parse(s3).ext[1].type
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001081
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001082 self.assertTrue(isinstance(s3_type, Enum))
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001083 self.assertEqual(s3_type.name, 'mytag')
1084
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001085 def test_multi_decls(self):
1086 d1 = 'int a, b;'
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001087
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001088 self.assertEqual(self.get_decl(d1, 0),
1089 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
1090 self.assertEqual(self.get_decl(d1, 1),
1091 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['int']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001092
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001093 d2 = 'char* p, notp, ar[4];'
1094 self.assertEqual(self.get_decl(d2, 0),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001095 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001096 ['PtrDecl',
1097 ['TypeDecl', ['IdentifierType', ['char']]]]])
1098 self.assertEqual(self.get_decl(d2, 1),
1099 ['Decl', 'notp', ['TypeDecl', ['IdentifierType', ['char']]]])
1100 self.assertEqual(self.get_decl(d2, 2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001101 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001102 ['ArrayDecl', '4', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001103 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001104
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001105 def test_invalid_multiple_types_error(self):
1106 bad = [
1107 'int enum {ab, cd} fubr;',
1108 'enum kid char brbr;']
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001109
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001110 for b in bad:
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001111 self.assertRaises(ParseError, self.parse, b)
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001112
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001113 def test_duplicate_typedef(self):
1114 """ Tests that redeclarations of existing types are parsed correctly.
1115 This is non-standard, but allowed by many compilers.
1116 """
1117 d1 = '''
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001118 typedef int numbertype;
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001119 typedef int numbertype;
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001120 '''
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001121
1122 self.assertEqual(self.get_decl(d1, 0),
1123 ['Typedef', 'numbertype',
1124 ['TypeDecl', ['IdentifierType', ['int']]]])
1125 self.assertEqual(self.get_decl(d1, 1),
1126 ['Typedef', 'numbertype',
1127 ['TypeDecl', ['IdentifierType', ['int']]]])
1128
1129 d2 = '''
1130 typedef int (*funcptr)(int x);
1131 typedef int (*funcptr)(int x);
1132 '''
1133 self.assertEqual(self.get_decl(d2, 0),
1134 ['Typedef', 'funcptr',
1135 ['PtrDecl', ['FuncDecl',
1136 [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]],
1137 ['TypeDecl', ['IdentifierType', ['int']]]]]])
1138 self.assertEqual(self.get_decl(d2, 1),
1139 ['Typedef', 'funcptr',
1140 ['PtrDecl', ['FuncDecl',
1141 [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]],
1142 ['TypeDecl', ['IdentifierType', ['int']]]]]])
1143
1144 d3 = '''
1145 typedef int numberarray[5];
1146 typedef int numberarray[5];
1147 '''
1148 self.assertEqual(self.get_decl(d3, 0),
1149 ['Typedef', 'numberarray',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001150 ['ArrayDecl', '5', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001151 ['TypeDecl', ['IdentifierType', ['int']]]]])
1152 self.assertEqual(self.get_decl(d3, 1),
1153 ['Typedef', 'numberarray',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001154 ['ArrayDecl', '5', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001155 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001156
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001157 def test_decl_inits(self):
1158 d1 = 'int a = 16;'
eli.benderskyf890a862010-10-30 12:13:23 +02001159 #~ self.parse(d1).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001160 self.assertEqual(self.get_decl(d1),
1161 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
1162 self.assertEqual(self.get_decl_init(d1),
1163 ['Constant', 'int', '16'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001164
Eli Bendersky3b1b08d2012-06-15 12:37:54 +03001165 d1_1 = 'float f = 0xEF.56p1;'
1166 self.assertEqual(self.get_decl_init(d1_1),
1167 ['Constant', 'float', '0xEF.56p1'])
1168
Konstanty Bialkowski3bdbfdc2015-04-19 20:09:21 +10001169 d1_2 = 'int bitmask = 0b1001010;'
1170 self.assertEqual(self.get_decl_init(d1_2),
1171 ['Constant', 'int', '0b1001010'])
1172
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001173 d2 = 'long ar[] = {7, 8, 9};'
1174 self.assertEqual(self.get_decl(d2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001175 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001176 ['ArrayDecl', '', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001177 ['TypeDecl', ['IdentifierType', ['long']]]]])
1178 self.assertEqual(self.get_decl_init(d2),
1179 [ ['Constant', 'int', '7'],
1180 ['Constant', 'int', '8'],
eli.benderskyf890a862010-10-30 12:13:23 +02001181 ['Constant', 'int', '9']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001182
Eli Benderskyc830da82015-05-10 07:56:41 -07001183 d21 = 'long ar[4] = {};'
1184 self.assertEqual(self.get_decl_init(d21), [])
1185
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001186 d3 = 'char p = j;'
1187 self.assertEqual(self.get_decl(d3),
1188 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['char']]]])
1189 self.assertEqual(self.get_decl_init(d3),
1190 ['ID', 'j'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001191
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001192 d4 = "char x = 'c', *p = {0, 1, 2, {4, 5}, 6};"
1193 self.assertEqual(self.get_decl(d4, 0),
1194 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['char']]]])
1195 self.assertEqual(self.get_decl_init(d4, 0),
1196 ['Constant', 'char', "'c'"])
1197 self.assertEqual(self.get_decl(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001198 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001199 ['PtrDecl',
1200 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001201
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001202 self.assertEqual(self.get_decl_init(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001203 [ ['Constant', 'int', '0'],
1204 ['Constant', 'int', '1'],
1205 ['Constant', 'int', '2'],
1206 [['Constant', 'int', '4'],
1207 ['Constant', 'int', '5']],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001208 ['Constant', 'int', '6']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001209
eli.benderskyf890a862010-10-30 12:13:23 +02001210 def test_decl_named_inits(self):
1211 d1 = 'int a = {.k = 16};'
1212 self.assertEqual(self.get_decl_init(d1),
1213 [( [['ID', 'k']],
1214 ['Constant', 'int', '16'])])
1215
1216 d2 = 'int a = { [0].a = {1}, [1].a[0] = 2 };'
1217 self.assertEqual(self.get_decl_init(d2),
1218 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001219 ([['Constant', 'int', '0'], ['ID', 'a']],
1220 [['Constant', 'int', '1']]),
1221 ([['Constant', 'int', '1'], ['ID', 'a'], ['Constant', 'int', '0']],
eli.benderskyf890a862010-10-30 12:13:23 +02001222 ['Constant', 'int', '2'])])
1223
1224 d3 = 'int a = { .a = 1, .c = 3, 4, .b = 5};'
1225 self.assertEqual(self.get_decl_init(d3),
1226 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001227 ([['ID', 'a']], ['Constant', 'int', '1']),
1228 ([['ID', 'c']], ['Constant', 'int', '3']),
1229 ['Constant', 'int', '4'],
eli.benderskyf890a862010-10-30 12:13:23 +02001230 ([['ID', 'b']], ['Constant', 'int', '5'])])
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001231
1232 def test_function_definitions(self):
1233 def parse_fdef(str):
1234 return self.parse(str).ext[0]
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001235
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001236 def fdef_decl(fdef):
1237 return expand_decl(fdef.decl)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001238
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001239 f1 = parse_fdef('''
1240 int factorial(int p)
1241 {
1242 return 3;
1243 }
1244 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001245
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001246 self.assertEqual(fdef_decl(f1),
1247 ['Decl', 'factorial',
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001248 ['FuncDecl',
1249 [['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001250 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001251
eli.benderskyef29ff92010-10-29 16:25:43 +02001252 self.assertEqual(type(f1.body.block_items[0]), Return)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001253
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001254 f2 = parse_fdef('''
1255 char* zzz(int p, char* c)
1256 {
1257 int a;
1258 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001259
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001260 a = b + 2;
1261 return 3;
1262 }
1263 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001264
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001265 self.assertEqual(fdef_decl(f2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001266 ['Decl', 'zzz',
1267 ['FuncDecl',
1268 [ ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]],
1269 ['Decl', 'c', ['PtrDecl',
1270 ['TypeDecl', ['IdentifierType', ['char']]]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001271 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001272
1273 self.assertEqual(list(map(type, f2.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001274 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001275
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001276 f3 = parse_fdef('''
1277 char* zzz(p, c)
1278 long p, *c;
1279 {
1280 int a;
1281 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001282
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001283 a = b + 2;
1284 return 3;
1285 }
1286 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001287
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001288 self.assertEqual(fdef_decl(f3),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001289 ['Decl', 'zzz',
1290 ['FuncDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001291 [ ['ID', 'p'],
1292 ['ID', 'c']],
1293 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001294
1295 self.assertEqual(list(map(type, f3.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001296 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001297
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001298 self.assertEqual(expand_decl(f3.param_decls[0]),
1299 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['long']]]])
1300 self.assertEqual(expand_decl(f3.param_decls[1]),
1301 ['Decl', 'c', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['long']]]]])
1302
Sye van der Veen51a46ec2013-06-10 12:56:15 -04001303 # function return values and parameters may not have type information
1304 f4 = parse_fdef('''
1305 que(p)
1306 {
1307 return 3;
1308 }
1309 ''')
1310
1311 self.assertEqual(fdef_decl(f4),
1312 ['Decl', 'que',
1313 ['FuncDecl',
1314 [['ID', 'p']],
1315 ['TypeDecl', ['IdentifierType', ['int']]]]])
1316
eli.bendersky71540662010-07-03 12:58:52 +02001317 def test_unified_string_literals(self):
1318 # simple string, for reference
1319 d1 = self.get_decl_init('char* s = "hello";')
1320 self.assertEqual(d1, ['Constant', 'string', '"hello"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001321
eli.bendersky71540662010-07-03 12:58:52 +02001322 d2 = self.get_decl_init('char* s = "hello" " world";')
1323 self.assertEqual(d2, ['Constant', 'string', '"hello world"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001324
eli.bendersky71540662010-07-03 12:58:52 +02001325 # the test case from issue 6
1326 d3 = self.parse(r'''
1327 int main() {
1328 fprintf(stderr,
1329 "Wrong Params?\n"
1330 "Usage:\n"
1331 "%s <binary_file_path>\n",
1332 argv[0]
1333 );
1334 }
1335 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001336
eli.bendersky71540662010-07-03 12:58:52 +02001337 self.assertEqual(
eli.benderskyef29ff92010-10-29 16:25:43 +02001338 d3.ext[0].body.block_items[0].args.exprs[1].value,
eli.bendersky71540662010-07-03 12:58:52 +02001339 r'"Wrong Params?\nUsage:\n%s <binary_file_path>\n"')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001340
eli.bendersky4a89f112010-07-05 06:02:03 +02001341 d4 = self.get_decl_init('char* s = "" "foobar";')
1342 self.assertEqual(d4, ['Constant', 'string', '"foobar"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001343
eli.bendersky4a89f112010-07-05 06:02:03 +02001344 d5 = self.get_decl_init(r'char* s = "foo\"" "bar";')
1345 self.assertEqual(d5, ['Constant', 'string', r'"foo\"bar"'])
eli.bendersky71540662010-07-03 12:58:52 +02001346
Eli Benderskyc9f1a382014-03-15 14:12:00 -07001347 def test_unified_wstring_literals(self):
1348 d1 = self.get_decl_init('char* s = L"hello" L"world";')
1349 self.assertEqual(d1, ['Constant', 'string', 'L"helloworld"'])
1350
1351 d2 = self.get_decl_init('char* s = L"hello " L"world" L" and I";')
1352 self.assertEqual(d2, ['Constant', 'string', 'L"hello world and I"'])
1353
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001354 def test_inline_specifier(self):
eli.bendersky79d5cf62010-10-29 13:33:52 +02001355 ps2 = self.parse('static inline void inlinefoo(void);')
1356 self.assertEqual(ps2.ext[0].funcspec, ['inline'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001357
eli.bendersky2e907fa2010-10-29 15:51:07 +02001358 # variable length array
1359 def test_vla(self):
1360 ps2 = self.parse(r'''
1361 int main() {
1362 int size;
1363 int var[size = 5];
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001364
eli.bendersky2e907fa2010-10-29 15:51:07 +02001365 int var2[*];
1366 }
1367 ''')
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001368 self.assertTrue(isinstance(ps2.ext[0].body.block_items[1].type.dim, Assignment))
1369 self.assertTrue(isinstance(ps2.ext[0].body.block_items[2].type.dim, ID))
eli.bendersky79d5cf62010-10-29 13:33:52 +02001370
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001371 def test_pragma(self):
1372 s1 = r'''
1373 #pragma bar
1374 void main() {
1375 #pragma foo
1376 for(;;) {}
Julian Hammer8a174062015-12-14 14:48:16 +01001377 #pragma
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001378 }
ldoreec233182017-11-22 14:52:53 +01001379 struct s {
1380 #pragma baz
1381 } s;
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001382 '''
1383 s1_ast = self.parse(s1)
1384 self.assertTrue(isinstance(s1_ast.ext[0], Pragma))
1385 self.assertEqual(s1_ast.ext[0].string, 'bar')
Julian Hammer8a174062015-12-14 14:48:16 +01001386 self.assertEqual(s1_ast.ext[0].coord.line, 2)
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001387
1388 self.assertTrue(isinstance(s1_ast.ext[1].body.block_items[0], Pragma))
1389 self.assertEqual(s1_ast.ext[1].body.block_items[0].string, 'foo')
Julian Hammer8a174062015-12-14 14:48:16 +01001390 self.assertEqual(s1_ast.ext[1].body.block_items[0].coord.line, 4)
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001391
Julian Hammer8a174062015-12-14 14:48:16 +01001392 self.assertTrue(isinstance(s1_ast.ext[1].body.block_items[2], Pragma))
1393 self.assertEqual(s1_ast.ext[1].body.block_items[2].string, '')
1394 self.assertEqual(s1_ast.ext[1].body.block_items[2].coord.line, 6)
ldoreec233182017-11-22 14:52:53 +01001395
1396 self.assertTrue(isinstance(s1_ast.ext[2].type.type.decls[0], Pragma))
1397 self.assertEqual(s1_ast.ext[2].type.type.decls[0].string, 'baz')
1398 self.assertEqual(s1_ast.ext[2].type.type.decls[0].coord.line, 9)
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001399
dbluhm7af2fb92018-03-03 06:18:26 -07001400 def test_pragmacomp_or_statement(self):
1401 s1 = r'''
1402 void main() {
1403 int sum = 0;
1404 for (int i; i < 3; i++)
1405 #pragma omp critical
1406 sum += 1;
1407
1408 while(sum < 10)
1409 #pragma omp critical
1410 sum += 1;
1411
1412 mylabel:
1413 #pragma foo
1414 sum += 10;
1415
1416 if (sum > 10)
1417 #pragma bar
1418 sum = 10;
1419
1420 switch (sum)
1421 case 10:
1422 #pragma foo
1423 sum = 20;
1424 }
1425 '''
1426 s1_ast = self.parse(s1)
1427 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[1], For))
1428 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[1].stmt, Compound))
1429 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[1].stmt.block_items[0], Pragma))
1430 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[1].stmt.block_items[1], Assignment))
1431 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[2], While))
1432 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[2].stmt, Compound))
1433 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[2].stmt.block_items[0], Pragma))
1434 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[2].stmt.block_items[1], Assignment))
1435 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[3], Label))
1436 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[3].stmt, Compound))
1437 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[3].stmt.block_items[0], Pragma))
1438 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[3].stmt.block_items[1], Assignment))
1439 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[4], If))
1440 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[4].iftrue, Compound))
1441 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[4].iftrue.block_items[0], Pragma))
1442 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[4].iftrue.block_items[1], Assignment))
1443 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[5], Switch))
1444 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[5].stmt.stmts[0], Compound))
1445 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[5].stmt.stmts[0].block_items[0], Pragma))
1446 self.assertTrue(isinstance(s1_ast.ext[0].body.block_items[5].stmt.stmts[0].block_items[1], Assignment))
1447
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001448
eli.bendersky85d2e732011-05-20 19:47:26 +03001449class TestCParser_whole_code(TestCParser_base):
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001450 """ Testing of parsing whole chunks of code.
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001451
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001452 Since I don't want to rely on the structure of ASTs too
1453 much, most of these tests are implemented with visitors.
1454 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001455 # A simple helper visitor that lists the values of all the
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001456 # Constant nodes it sees.
1457 #
1458 class ConstantVisitor(NodeVisitor):
1459 def __init__(self):
1460 self.values = []
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001461
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001462 def visit_Constant(self, node):
1463 self.values.append(node.value)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001464
1465 # This visitor counts the amount of references to the ID
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001466 # with the name provided to it in the constructor.
1467 #
1468 class IDNameCounter(NodeVisitor):
1469 def __init__(self, name):
1470 self.name = name
1471 self.nrefs = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001472
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001473 def visit_ID(self, node):
1474 if node.name == self.name:
1475 self.nrefs += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001476
1477 # Counts the amount of nodes of a given class
1478 #
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001479 class NodeKlassCounter(NodeVisitor):
1480 def __init__(self, node_klass):
1481 self.klass = node_klass
1482 self.n = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001483
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001484 def generic_visit(self, node):
1485 if node.__class__ == self.klass:
1486 self.n += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001487
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001488 NodeVisitor.generic_visit(self, node)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001489
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001490 def assert_all_Constants(self, code, constants):
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001491 """ Asserts that the list of all Constant values (by
1492 'preorder' appearance) in the chunk of code is as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001493 given.
1494 """
eli.benderskyed890492010-06-25 08:25:55 +03001495 if isinstance(code, str):
1496 parsed = self.parse(code)
1497 else:
1498 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001499
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001500 cv = self.ConstantVisitor()
1501 cv.visit(parsed)
1502 self.assertEqual(cv.values, constants)
1503
1504 def assert_num_ID_refs(self, code, name, num):
1505 """ Asserts the number of references to the ID with
1506 the given name.
1507 """
1508 if isinstance(code, str):
1509 parsed = self.parse(code)
1510 else:
1511 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001512
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001513 iv = self.IDNameCounter(name)
1514 iv.visit(parsed)
1515 self.assertEqual(iv.nrefs, num)
1516
1517 def assert_num_klass_nodes(self, code, klass, num):
1518 """ Asserts the amount of klass nodes in the code.
1519 """
1520 if isinstance(code, str):
1521 parsed = self.parse(code)
1522 else:
1523 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001524
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001525 cv = self.NodeKlassCounter(klass)
1526 cv.visit(parsed)
1527 self.assertEqual(cv.n, num)
1528
1529 def test_expressions(self):
1530 e1 = '''int k = (r + 10.0) >> 6 + 8 << (3 & 0x14);'''
1531 self.assert_all_Constants(e1, ['10.0', '6', '8', '3', '0x14'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001532
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001533 e2 = r'''char n = '\n', *prefix = "st_";'''
1534 self.assert_all_Constants(e2, [r"'\n'", '"st_"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001535
Eli Bendersky09e22a62013-07-02 06:00:36 -07001536 s1 = r'''int main() {
1537 int i = 5, j = 6, k = 1;
1538 if ((i=j && k == 1) || k > j)
1539 printf("Hello, world\n");
1540 return 0;
1541 }'''
1542 ps1 = self.parse(s1)
1543 self.assert_all_Constants(ps1,
1544 ['5', '6', '1', '1', '"Hello, world\\n"', '0'])
1545 self.assert_num_ID_refs(ps1, 'i', 1)
1546 self.assert_num_ID_refs(ps1, 'j', 2)
1547
1548
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001549 def test_statements(self):
1550 s1 = r'''
1551 void foo(){
1552 if (sp == 1)
1553 if (optind >= argc ||
1554 argv[optind][0] != '-' || argv[optind][1] == '\0')
1555 return -1;
1556 else if (strcmp(argv[optind], "--") == 0) {
1557 optind++;
1558 return -1;
1559 }
1560 }
1561 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001562
1563 self.assert_all_Constants(s1,
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001564 ['1', '0', r"'-'", '1', r"'\0'", '1', r'"--"', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001565
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001566 ps1 = self.parse(s1)
1567 self.assert_num_ID_refs(ps1, 'argv', 3)
1568 self.assert_num_ID_refs(ps1, 'optind', 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001569
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001570 self.assert_num_klass_nodes(ps1, If, 3)
1571 self.assert_num_klass_nodes(ps1, Return, 2)
1572 self.assert_num_klass_nodes(ps1, FuncCall, 1) # strcmp
1573 self.assert_num_klass_nodes(ps1, BinaryOp, 7)
1574
1575 # In the following code, Hash and Node were defined as
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001576 # int to pacify the parser that sees they're used as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001577 # types
1578 #
1579 s2 = r'''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001580 typedef int Hash, Node;
1581
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001582 void HashDestroy(Hash* hash)
1583 {
1584 unsigned int i;
1585
1586 if (hash == NULL)
1587 return;
1588
1589 for (i = 0; i < hash->table_size; ++i)
1590 {
1591 Node* temp = hash->heads[i];
1592
1593 while (temp != NULL)
1594 {
1595 Node* temp2 = temp;
1596
1597 free(temp->entry->key);
1598 free(temp->entry->value);
1599 free(temp->entry);
1600
1601 temp = temp->next;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001602
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001603 free(temp2);
1604 }
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001605 }
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001606
1607 free(hash->heads);
1608 hash->heads = NULL;
1609
1610 free(hash);
1611 }
1612 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001613
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001614 ps2 = self.parse(s2)
1615 self.assert_num_klass_nodes(ps2, FuncCall, 6)
1616 self.assert_num_klass_nodes(ps2, FuncDef, 1)
1617 self.assert_num_klass_nodes(ps2, For, 1)
1618 self.assert_num_klass_nodes(ps2, While, 1)
1619 self.assert_num_klass_nodes(ps2, StructRef, 10)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001620
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001621 # declarations don't count
1622 self.assert_num_ID_refs(ps2, 'hash', 6)
1623 self.assert_num_ID_refs(ps2, 'i', 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001624
eli.benderskyed890492010-06-25 08:25:55 +03001625 s3 = r'''
1626 void x(void) {
1627 int a, b;
1628 if (a < b)
1629 do {
1630 a = 0;
1631 } while (0);
1632 else if (a == b) {
1633 a = 1;
1634 }
1635 }
1636 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001637
eli.benderskyed890492010-06-25 08:25:55 +03001638 ps3 = self.parse(s3)
1639 self.assert_num_klass_nodes(ps3, DoWhile, 1)
1640 self.assert_num_ID_refs(ps3, 'a', 4)
1641 self.assert_all_Constants(ps3, ['0', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001642
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001643 def test_empty_statements(self):
eli.bendersky91c0aa32011-10-16 05:50:43 +02001644 s1 = r'''
1645 void foo(void){
1646 ;
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001647 return;;
1648
1649 ;
eli.bendersky91c0aa32011-10-16 05:50:43 +02001650 }
1651 '''
1652 ps1 = self.parse(s1)
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001653 self.assert_num_klass_nodes(ps1, EmptyStatement, 3)
eli.bendersky91c0aa32011-10-16 05:50:43 +02001654 self.assert_num_klass_nodes(ps1, Return, 1)
serpilliere471442f2017-03-10 15:02:00 +01001655 self.assert_coord(ps1.ext[0].body.block_items[0], 3)
1656 self.assert_coord(ps1.ext[0].body.block_items[1], 4)
1657 self.assert_coord(ps1.ext[0].body.block_items[2], 4)
1658 self.assert_coord(ps1.ext[0].body.block_items[3], 6)
eli.bendersky145890d2010-10-29 12:02:32 +02001659
Ben5cd3fd62012-02-03 06:02:40 +02001660 def test_switch_statement(self):
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001661 def assert_case_node(node, const_value):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001662 self.assertTrue(isinstance(node, Case))
1663 self.assertTrue(isinstance(node.expr, Constant))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001664 self.assertEqual(node.expr.value, const_value)
1665
1666 def assert_default_node(node):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001667 self.assertTrue(isinstance(node, Default))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001668
Ben5cd3fd62012-02-03 06:02:40 +02001669 s1 = r'''
1670 int foo(void) {
1671 switch (myvar) {
1672 case 10:
1673 k = 10;
1674 p = k + 1;
1675 return 10;
1676 case 20:
1677 case 30:
1678 return 20;
1679 default:
1680 break;
1681 }
1682 return 0;
1683 }
1684 '''
1685 ps1 = self.parse(s1)
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001686 switch = ps1.ext[0].body.block_items[0]
1687
1688 block = switch.stmt.block_items
1689 assert_case_node(block[0], '10')
1690 self.assertEqual(len(block[0].stmts), 3)
1691 assert_case_node(block[1], '20')
1692 self.assertEqual(len(block[1].stmts), 0)
1693 assert_case_node(block[2], '30')
1694 self.assertEqual(len(block[2].stmts), 1)
1695 assert_default_node(block[3])
1696
1697 s2 = r'''
1698 int foo(void) {
1699 switch (myvar) {
1700 default:
1701 joe = moe;
1702 return 10;
1703 case 10:
1704 case 20:
1705 case 30:
1706 case 40:
1707 break;
1708 }
1709 return 0;
1710 }
1711 '''
1712 ps2 = self.parse(s2)
1713 switch = ps2.ext[0].body.block_items[0]
1714
1715 block = switch.stmt.block_items
1716 assert_default_node(block[0])
1717 self.assertEqual(len(block[0].stmts), 2)
1718 assert_case_node(block[1], '10')
1719 self.assertEqual(len(block[1].stmts), 0)
1720 assert_case_node(block[2], '20')
1721 self.assertEqual(len(block[1].stmts), 0)
1722 assert_case_node(block[3], '30')
1723 self.assertEqual(len(block[1].stmts), 0)
1724 assert_case_node(block[4], '40')
1725 self.assertEqual(len(block[4].stmts), 1)
Ben5cd3fd62012-02-03 06:02:40 +02001726
eli.bendersky145890d2010-10-29 12:02:32 +02001727 def test_for_statement(self):
1728 s2 = r'''
1729 void x(void)
1730 {
1731 int i;
1732 for (i = 0; i < 5; ++i) {
1733 x = 50;
1734 }
1735 }
1736 '''
1737 ps2 = self.parse(s2)
1738 self.assert_num_klass_nodes(ps2, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001739 # here there are 3 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001740 # a ref in the visitor
1741 #
1742 self.assert_num_ID_refs(ps2, 'i', 3)
Eli Bendersky4476d092012-12-25 14:07:57 -08001743
eli.bendersky145890d2010-10-29 12:02:32 +02001744 s3 = r'''
1745 void x(void)
1746 {
1747 for (int i = 0; i < 5; ++i) {
1748 x = 50;
1749 }
1750 }
1751 '''
1752 ps3 = self.parse(s3)
eli.bendersky145890d2010-10-29 12:02:32 +02001753 self.assert_num_klass_nodes(ps3, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001754 # here there are 2 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001755 # a ref in the visitor
1756 #
1757 self.assert_num_ID_refs(ps3, 'i', 2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001758
Eli Bendersky4476d092012-12-25 14:07:57 -08001759 s4 = r'''
1760 void x(void) {
1761 for (int i = 0;;)
1762 i;
1763 }
1764 '''
1765 ps4 = self.parse(s4)
1766 self.assert_num_ID_refs(ps4, 'i', 1)
1767
Eli Benderskyd0973782012-01-19 08:09:33 +02001768 def _open_c_file(self, name):
1769 """ Find a c file by name, taking into account the current dir can be
1770 in a couple of typical places
1771 """
Stefano Riveraebaf5922013-08-08 09:45:26 +02001772 testdir = os.path.dirname(__file__)
1773 name = os.path.join(testdir, 'c_files', name)
1774 assert os.path.exists(name)
1775 return open(name, 'rU')
Eli Benderskyd0973782012-01-19 08:09:33 +02001776
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001777 def test_whole_file(self):
1778 # See how pycparser handles a whole, real C file.
1779 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001780 with self._open_c_file('memmgr_with_h.c') as f:
1781 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001782 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001783
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001784 self.assert_num_klass_nodes(p, FuncDef, 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001785
1786 # each FuncDef also has a FuncDecl. 4 declarations
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001787 # + 5 definitions, overall 9
1788 self.assert_num_klass_nodes(p, FuncDecl, 9)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001789
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001790 self.assert_num_klass_nodes(p, Typedef, 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001791
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001792 self.assertEqual(p.ext[4].coord.line, 88)
1793 self.assertEqual(p.ext[4].coord.file, "./memmgr.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001794
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001795 self.assertEqual(p.ext[6].coord.line, 10)
1796 self.assertEqual(p.ext[6].coord.file, "memmgr.c")
1797
1798 def test_whole_file_with_stdio(self):
1799 # Parse a whole file with stdio.h included by cpp
1800 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001801 with self._open_c_file('cppd_with_stdio_h.c') as f:
1802 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001803 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001804
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001805 self.assertTrue(isinstance(p.ext[0], Typedef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001806 self.assertEqual(p.ext[0].coord.line, 213)
Ville Skyttä2129f5f2017-03-05 04:52:22 +02001807 self.assertEqual(p.ext[0].coord.file, r"D:\eli\cpp_stuff\libc_include/stddef.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001808
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001809 self.assertTrue(isinstance(p.ext[-1], FuncDef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001810 self.assertEqual(p.ext[-1].coord.line, 15)
1811 self.assertEqual(p.ext[-1].coord.file, "example_c_file.c")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001812
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001813 self.assertTrue(isinstance(p.ext[-8], Typedef))
1814 self.assertTrue(isinstance(p.ext[-8].type, TypeDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001815 self.assertEqual(p.ext[-8].name, 'cookie_io_functions_t')
eli.bendersky85d2e732011-05-20 19:47:26 +03001816
1817
1818class TestCParser_typenames(TestCParser_base):
1819 """ Test issues related to the typedef-name problem.
1820 """
1821 def test_innerscope_typedef(self):
1822 # should fail since TT is not a type in bar
1823 s1 = r'''
1824 void foo() {
1825 typedef char TT;
1826 TT x;
1827 }
1828 void bar() {
1829 TT y;
1830 }
1831 '''
1832 self.assertRaises(ParseError, self.parse, s1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001833
eli.bendersky85d2e732011-05-20 19:47:26 +03001834 # should succeed since TT is not a type in bar
1835 s2 = r'''
1836 void foo() {
1837 typedef char TT;
1838 TT x;
1839 }
1840 void bar() {
1841 unsigned TT;
1842 }
1843 '''
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001844 self.assertTrue(isinstance(self.parse(s2), FileAST))
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001845
Nate Bogdanowicz14b8a7e2017-02-22 08:54:05 -05001846 def test_ambiguous_parameters(self):
1847 # From ISO/IEC 9899:TC2, 6.7.5.3.11:
1848 # "If, in a parameter declaration, an identifier can be treated either
1849 # as a typedef name or as a parameter name, it shall be taken as a
1850 # typedef name."
1851
1852 # foo takes an int named aa
1853 # bar takes a function taking a TT
1854 s1 = r'''
1855 typedef char TT;
1856 int foo(int (aa));
1857 int bar(int (TT));
1858 '''
1859 s1_ast = self.parse(s1)
1860 self.assertEqual(expand_decl(s1_ast.ext[1].type.args.params[0]),
1861 ['Decl', 'aa', ['TypeDecl', ['IdentifierType', ['int']]]])
1862 self.assertEqual(expand_decl(s1_ast.ext[2].type.args.params[0]),
1863 ['Typename', ['FuncDecl',
1864 [['Typename', ['TypeDecl', ['IdentifierType', ['TT']]]]],
1865 ['TypeDecl', ['IdentifierType', ['int']]]]])
1866
1867 # foo takes a function taking a char
1868 # bar takes a function taking a function taking a char
1869 s2 = r'''
1870 typedef char TT;
1871 int foo(int (aa (char)));
1872 int bar(int (TT (char)));
1873 '''
1874 s2_ast = self.parse(s2)
1875 self.assertEqual(expand_decl(s2_ast.ext[1].type.args.params[0]),
1876 ['Decl', 'aa', ['FuncDecl',
1877 [['Typename', ['TypeDecl', ['IdentifierType', ['char']]]]],
1878 ['TypeDecl', ['IdentifierType', ['int']]]]])
1879 self.assertEqual(expand_decl(s2_ast.ext[2].type.args.params[0]),
1880 ['Typename', ['FuncDecl',
1881 [['Typename', ['FuncDecl',
1882 [['Typename', ['TypeDecl', ['IdentifierType', ['char']]]]],
1883 ['TypeDecl', ['IdentifierType', ['TT']]]]]],
1884 ['TypeDecl', ['IdentifierType', ['int']]]]])
1885
1886
1887 # foo takes an int array named aa
1888 # bar takes a function taking a TT array
1889 s3 = r'''
1890 typedef char TT;
1891 int foo(int (aa[]));
1892 int bar(int (TT[]));
1893 '''
1894 s3_ast = self.parse(s3)
1895 self.assertEqual(expand_decl(s3_ast.ext[1].type.args.params[0]),
1896 ['Decl', 'aa', ['ArrayDecl', '', [], ['TypeDecl', ['IdentifierType', ['int']]]]])
1897 self.assertEqual(expand_decl(s3_ast.ext[2].type.args.params[0]),
1898 ['Typename', ['FuncDecl',
1899 [['Typename', ['ArrayDecl', '', [], ['TypeDecl', ['IdentifierType', ['TT']]]]]],
1900 ['TypeDecl', ['IdentifierType', ['int']]]]])
1901
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001902 def test_innerscope_reuse_typedef_name(self):
1903 # identifiers can be reused in inner scopes; the original should be
1904 # restored at the end of the block
1905 s1 = r'''
1906 typedef char TT;
1907 void foo(void) {
1908 unsigned TT;
1909 TT = 10;
1910 }
1911 TT x = 5;
1912 '''
1913 s1_ast = self.parse(s1)
1914 self.assertEqual(expand_decl(s1_ast.ext[1].body.block_items[0]),
1915 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
Eli Bendersky3877c4c2013-07-13 06:54:04 -07001916 self.assertEqual(expand_decl(s1_ast.ext[2]),
1917 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['TT']]]])
eli.bendersky85d2e732011-05-20 19:47:26 +03001918
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001919 # this should be recognized even with an initializer
1920 s2 = r'''
1921 typedef char TT;
1922 void foo(void) {
1923 unsigned TT = 10;
1924 }
1925 '''
1926 s2_ast = self.parse(s2)
1927 self.assertEqual(expand_decl(s2_ast.ext[1].body.block_items[0]),
1928 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1929
1930 # before the second local variable, TT is a type; after, it's a
1931 # variable
1932 s3 = r'''
1933 typedef char TT;
1934 void foo(void) {
1935 TT tt = sizeof(TT);
1936 unsigned TT = 10;
1937 }
1938 '''
1939 s3_ast = self.parse(s3)
1940 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[0]),
1941 ['Decl', 'tt', ['TypeDecl', ['IdentifierType', ['TT']]]])
1942 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[1]),
1943 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1944
1945 # a variable and its type can even share the same name
1946 s4 = r'''
1947 typedef char TT;
1948 void foo(void) {
1949 TT TT = sizeof(TT);
1950 unsigned uu = TT * 2;
1951 }
1952 '''
1953 s4_ast = self.parse(s4)
1954 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[0]),
1955 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['TT']]]])
1956 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[1]),
1957 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1958
1959 # ensure an error is raised if a type, redeclared as a variable, is
1960 # used as a type
1961 s5 = r'''
1962 typedef char TT;
1963 void foo(void) {
1964 unsigned TT = 10;
1965 TT erroneous = 20;
1966 }
1967 '''
1968 self.assertRaises(ParseError, self.parse, s5)
1969
Nate Bogdanowicz14b8a7e2017-02-22 08:54:05 -05001970 # reusing a type name should work with multiple declarators
1971 s6 = r'''
1972 typedef char TT;
1973 void foo(void) {
1974 unsigned TT, uu;
1975 }
1976 '''
1977 s6_ast = self.parse(s6)
1978 items = s6_ast.ext[1].body.block_items
1979 self.assertEqual(expand_decl(items[0]),
1980 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1981 self.assertEqual(expand_decl(items[1]),
1982 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1983
1984 # reusing a type name should work after a pointer
1985 s7 = r'''
1986 typedef char TT;
1987 void foo(void) {
1988 unsigned * TT;
1989 }
1990 '''
1991 s7_ast = self.parse(s7)
1992 items = s7_ast.ext[1].body.block_items
1993 self.assertEqual(expand_decl(items[0]),
1994 ['Decl', 'TT', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['unsigned']]]]])
1995
1996 # redefine a name in the middle of a multi-declarator declaration
1997 s8 = r'''
1998 typedef char TT;
1999 void foo(void) {
2000 int tt = sizeof(TT), TT, uu = sizeof(TT);
2001 int uu = sizeof(tt);
2002 }
2003 '''
2004 s8_ast = self.parse(s8)
2005 items = s8_ast.ext[1].body.block_items
2006 self.assertEqual(expand_decl(items[0]),
2007 ['Decl', 'tt', ['TypeDecl', ['IdentifierType', ['int']]]])
2008 self.assertEqual(expand_decl(items[1]),
2009 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['int']]]])
2010 self.assertEqual(expand_decl(items[2]),
2011 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['int']]]])
2012
2013 # Don't test this until we have support for it
2014 # self.assertEqual(expand_init(items[0].init),
2015 # ['UnaryOp', 'sizeof', ['Typename', ['TypeDecl', ['IdentifierType', ['TT']]]]])
2016 # self.assertEqual(expand_init(items[2].init),
2017 # ['UnaryOp', 'sizeof', ['ID', 'TT']])
2018
Sye van der Veen9ec6c422013-07-11 09:10:38 -04002019 def test_parameter_reuse_typedef_name(self):
2020 # identifiers can be reused as parameter names; parameter name scope
2021 # begins and ends with the function body; it's important that TT is
Eli Bendersky4d969b32013-07-13 06:07:07 -07002022 # used immediately before the LBRACE or after the RBRACE, to test
2023 # a corner case
Sye van der Veen9ec6c422013-07-11 09:10:38 -04002024 s1 = r'''
2025 typedef char TT;
2026 void foo(unsigned TT, TT bar) {
2027 TT = 10;
2028 }
2029 TT x = 5;
2030 '''
2031 s1_ast = self.parse(s1)
2032 self.assertEqual(expand_decl(s1_ast.ext[1].decl),
2033 ['Decl', 'foo',
2034 ['FuncDecl',
2035 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
2036 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
2037 ['TypeDecl', ['IdentifierType', ['void']]]]])
2038
2039 # the scope of a parameter name in a function declaration ends at the
2040 # end of the declaration...so it is effectively never used; it's
2041 # important that TT is used immediately after the declaration, to
2042 # test a corner case
2043 s2 = r'''
2044 typedef char TT;
2045 void foo(unsigned TT, TT bar);
2046 TT x = 5;
2047 '''
2048 s2_ast = self.parse(s2)
2049 self.assertEqual(expand_decl(s2_ast.ext[1]),
2050 ['Decl', 'foo',
2051 ['FuncDecl',
2052 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
2053 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
2054 ['TypeDecl', ['IdentifierType', ['void']]]]])
2055
2056 # ensure an error is raised if a type, redeclared as a parameter, is
2057 # used as a type
2058 s3 = r'''
2059 typedef char TT;
2060 void foo(unsigned TT, TT bar) {
2061 TT erroneous = 20;
2062 }
2063 '''
2064 self.assertRaises(ParseError, self.parse, s3)
2065
2066 def test_nested_function_decls(self):
2067 # parameter names of nested function declarations must not escape into
2068 # the top-level function _definition's_ scope; the following must
2069 # succeed because TT is still a typedef inside foo's body
2070 s1 = r'''
2071 typedef char TT;
2072 void foo(unsigned bar(int TT)) {
2073 TT x = 10;
2074 }
2075 '''
2076 self.assertTrue(isinstance(self.parse(s1), FileAST))
2077
2078 def test_samescope_reuse_name(self):
2079 # a typedef name cannot be reused as an object name in the same scope
2080 s1 = r'''
2081 typedef char TT;
2082 char TT = 5;
2083 '''
2084 self.assertRaises(ParseError, self.parse, s1)
2085
2086 # ...and vice-versa
2087 s2 = r'''
2088 char TT = 5;
2089 typedef char TT;
2090 '''
2091 self.assertRaises(ParseError, self.parse, s2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03002092
Julian Hammerdb9f2da2015-10-12 15:52:12 +02002093
Eli Bendersky3921e8e2010-05-21 09:05:39 +03002094if __name__ == '__main__':
2095 #~ suite = unittest.TestLoader().loadTestsFromNames(
2096 #~ ['test_c_parser.TestCParser_fundamentals.test_typedef'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08002097
Eli Bendersky3921e8e2010-05-21 09:05:39 +03002098 #~ unittest.TextTestRunner(verbosity=2).run(suite)
2099 unittest.main()