blob: ab6143f3a31a0ca796bcfef7aba14f5602468382 [file] [log] [blame]
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001#!/usr/bin/env python
2
3import pprint
4import re
Eli Benderskyd0973782012-01-19 08:09:33 +02005import os, sys
Eli Bendersky3921e8e2010-05-21 09:05:39 +03006import unittest
7
Eli Bendersky3877c4c2013-07-13 06:54:04 -07008sys.path[0:0] = ['.', '..']
Eli Bendersky3921e8e2010-05-21 09:05:39 +03009
10from pycparser import c_parser
11from pycparser.c_ast import *
12from pycparser.c_parser import CParser, Coord, ParseError
13
Eli Bendersky3921e8e2010-05-21 09:05:39 +030014_c_parser = c_parser.CParser(
15 lex_optimize=False,
Eli Bendersky86f2eee2013-01-18 06:04:01 -080016 yacc_debug=True,
Eli Bendersky3921e8e2010-05-21 09:05:39 +030017 yacc_optimize=False,
18 yacctab='yacctab')
19
20
21def expand_decl(decl):
22 """ Converts the declaration into a nested list.
23 """
24 typ = type(decl)
Eli Bendersky86f2eee2013-01-18 06:04:01 -080025
Eli Bendersky3921e8e2010-05-21 09:05:39 +030026 if typ == TypeDecl:
27 return ['TypeDecl', expand_decl(decl.type)]
28 elif typ == IdentifierType:
29 return ['IdentifierType', decl.names]
30 elif typ == ID:
31 return ['ID', decl.name]
32 elif typ in [Struct, Union]:
33 decls = [expand_decl(d) for d in decl.decls or []]
34 return [typ.__name__, decl.name, decls]
Eli Bendersky86f2eee2013-01-18 06:04:01 -080035 else:
Eli Bendersky3921e8e2010-05-21 09:05:39 +030036 nested = expand_decl(decl.type)
Eli Bendersky86f2eee2013-01-18 06:04:01 -080037
Eli Bendersky3921e8e2010-05-21 09:05:39 +030038 if typ == Decl:
39 if decl.quals:
40 return ['Decl', decl.quals, decl.name, nested]
41 else:
42 return ['Decl', decl.name, nested]
43 elif typ == Typename: # for function parameters
44 if decl.quals:
45 return ['Typename', decl.quals, nested]
46 else:
47 return ['Typename', nested]
48 elif typ == ArrayDecl:
49 dimval = decl.dim.value if decl.dim else ''
Eli Bendersky8aad3182014-01-25 06:30:53 -080050 return ['ArrayDecl', dimval, decl.dim_quals, nested]
Eli Bendersky3921e8e2010-05-21 09:05:39 +030051 elif typ == PtrDecl:
Eli Benderskyb17da152015-04-21 14:35:18 -070052 if decl.quals:
53 return ['PtrDecl', decl.quals, nested]
54 else:
55 return ['PtrDecl', nested]
Eli Bendersky3921e8e2010-05-21 09:05:39 +030056 elif typ == Typedef:
57 return ['Typedef', decl.name, nested]
58 elif typ == FuncDecl:
59 if decl.args:
60 params = [expand_decl(param) for param in decl.args.params]
61 else:
62 params = []
63 return ['FuncDecl', params, nested]
Eli Bendersky86f2eee2013-01-18 06:04:01 -080064
Eli Bendersky3921e8e2010-05-21 09:05:39 +030065
66def expand_init(init):
67 """ Converts an initialization into a nested list
68 """
69 typ = type(init)
Eli Bendersky86f2eee2013-01-18 06:04:01 -080070
eli.benderskyf890a862010-10-30 12:13:23 +020071 if typ == NamedInitializer:
72 des = [expand_init(dp) for dp in init.name]
73 return (des, expand_init(init.expr))
Eli Bendersky293ea912012-12-25 14:52:48 -080074 elif typ in (InitList, ExprList):
eli.benderskyf890a862010-10-30 12:13:23 +020075 return [expand_init(expr) for expr in init.exprs]
76 elif typ == Constant:
Eli Bendersky3921e8e2010-05-21 09:05:39 +030077 return ['Constant', init.type, init.value]
78 elif typ == ID:
79 return ['ID', init.name]
Nate Bogdanowicz14b8a7e2017-02-22 08:54:05 -050080 elif typ == UnaryOp:
81 return ['UnaryOp', init.op, expand_decl(init.expr)]
Eli Bendersky3921e8e2010-05-21 09:05:39 +030082
83
eli.bendersky85d2e732011-05-20 19:47:26 +030084class TestCParser_base(unittest.TestCase):
Eli Bendersky3921e8e2010-05-21 09:05:39 +030085 def parse(self, txt, filename=''):
86 return self.cparser.parse(txt, filename)
Eli Bendersky86f2eee2013-01-18 06:04:01 -080087
Eli Bendersky3921e8e2010-05-21 09:05:39 +030088 def setUp(self):
89 self.cparser = _c_parser
Eli Bendersky86f2eee2013-01-18 06:04:01 -080090
serpilliere471442f2017-03-10 15:02:00 +010091 def assert_coord(self, node, line, column=None, file=None):
Eli Benderskyb77d6c02016-10-11 20:33:53 -070092 self.assertEqual(node.coord.line, line)
serpilliere471442f2017-03-10 15:02:00 +010093 if column is not None:
94 self.assertEqual(node.coord.column, column)
Eli Benderskyb77d6c02016-10-11 20:33:53 -070095 if file:
96 self.assertEqual(node.coord.file, file)
97
eli.bendersky85d2e732011-05-20 19:47:26 +030098
serpilliere471442f2017-03-10 15:02:00 +010099
eli.bendersky85d2e732011-05-20 19:47:26 +0300100class TestCParser_fundamentals(TestCParser_base):
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300101 def get_decl(self, txt, index=0):
102 """ Given a source and an index returns the expanded
103 declaration at that index.
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800104
105 FileAST holds a list of 'external declarations'.
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300106 index is the offset of the desired declaration in that
107 list.
108 """
109 t = self.parse(txt).ext[index]
110 return expand_decl(t)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800111
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300112 def get_decl_init(self, txt, index=0):
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800113 """ Returns the expanded initializer of the declaration
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300114 at index.
115 """
116 t = self.parse(txt).ext[index]
117 return expand_init(t.init)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800118
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300119 def test_FileAST(self):
120 t = self.parse('int a; char c;')
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300121 self.assertTrue(isinstance(t, FileAST))
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300122 self.assertEqual(len(t.ext), 2)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800123
eli.bendersky43cf0b22011-10-19 05:56:15 +0200124 # empty file
125 t2 = self.parse('')
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300126 self.assertTrue(isinstance(t2, FileAST))
eli.bendersky43cf0b22011-10-19 05:56:15 +0200127 self.assertEqual(len(t2.ext), 0)
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300128
eli.bendersky38165b72011-02-04 08:13:39 +0200129 def test_empty_toplevel_decl(self):
130 code = 'int foo;;'
131 t = self.parse(code)
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300132 self.assertTrue(isinstance(t, FileAST))
eli.bendersky38165b72011-02-04 08:13:39 +0200133 self.assertEqual(len(t.ext), 1)
134 self.assertEqual(self.get_decl(code),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800135 ['Decl', 'foo',
eli.bendersky38165b72011-02-04 08:13:39 +0200136 ['TypeDecl', ['IdentifierType', ['int']]]])
137
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300138 def test_coords(self):
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800139 """ Tests the "coordinates" of parsed elements - file
serpilliere471442f2017-03-10 15:02:00 +0100140 name, line and column numbers, with modification
141 insterted by #line directives.
eli.bendersky38165b72011-02-04 08:13:39 +0200142 """
serpilliere471442f2017-03-10 15:02:00 +0100143 self.assert_coord(self.parse('int a;').ext[0], 1, 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800144
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300145 t1 = """
146 int a;
147 int b;\n\n
148 int c;
149 """
150 f1 = self.parse(t1, filename='test.c')
serpilliere471442f2017-03-10 15:02:00 +0100151 self.assert_coord(f1.ext[0], 2, 13, 'test.c')
152 self.assert_coord(f1.ext[1], 3, 13, 'test.c')
153 self.assert_coord(f1.ext[2], 6, 13, 'test.c')
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300154
155 t1_1 = '''
156 int main() {
157 k = p;
158 printf("%d", b);
159 return 0;
160 }'''
161 f1_1 = self.parse(t1_1, filename='test.c')
serpilliere471442f2017-03-10 15:02:00 +0100162 self.assert_coord(f1_1.ext[0].body.block_items[0], 3, 13, 'test.c')
163 self.assert_coord(f1_1.ext[0].body.block_items[1], 4, 13, 'test.c')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800164
eli.benderskyfc96e5e2011-03-04 09:51:23 +0200165 t1_2 = '''
166 int main () {
167 int p = (int) k;
168 }'''
169 f1_2 = self.parse(t1_2, filename='test.c')
170 # make sure that the Cast has a coord (issue 23)
serpilliere471442f2017-03-10 15:02:00 +0100171 self.assert_coord(f1_2.ext[0].body.block_items[0].init, 3, 21, file='test.c')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800172
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300173 t2 = """
174 #line 99
175 int c;
176 """
serpilliere471442f2017-03-10 15:02:00 +0100177 self.assert_coord(self.parse(t2).ext[0], 99, 13)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800178
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300179 t3 = """
180 int dsf;
181 char p;
182 #line 3000 "in.h"
183 char d;
184 """
185 f3 = self.parse(t3, filename='test.c')
serpilliere471442f2017-03-10 15:02:00 +0100186 self.assert_coord(f3.ext[0], 2, 13, 'test.c')
187 self.assert_coord(f3.ext[1], 3, 14, 'test.c')
188 self.assert_coord(f3.ext[2], 3000, 14, 'in.h')
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300189
190 t4 = """
191 #line 20 "restore.h"
192 int maydler(char);
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800193
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300194 #line 30 "includes/daween.ph"
195 long j, k;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800196
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300197 #line 50000
198 char* ro;
199 """
200 f4 = self.parse(t4, filename='myb.c')
serpilliere471442f2017-03-10 15:02:00 +0100201 self.assert_coord(f4.ext[0], 20, 13, 'restore.h')
202 self.assert_coord(f4.ext[1], 30, 14, 'includes/daween.ph')
203 self.assert_coord(f4.ext[2], 30, 17, 'includes/daween.ph')
204 self.assert_coord(f4.ext[3], 50000, 13, 'includes/daween.ph')
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300205
206 t5 = """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800207 int
208 #line 99
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300209 c;
210 """
serpilliere471442f2017-03-10 15:02:00 +0100211 self.assert_coord(self.parse(t5).ext[0], 99, 9)
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300212
Eli Bendersky203b9672012-06-15 10:11:24 +0300213 # coord for ellipsis
214 t6 = """
215 int foo(int j,
216 ...) {
217 }"""
218 f6 = self.parse(t6, filename='z.c')
serpilliere471442f2017-03-10 15:02:00 +0100219 self.assert_coord(self.parse(t6).ext[0].decl.type.args.params[1], 3, 17)
Eli Bendersky203b9672012-06-15 10:11:24 +0300220
Eli Bendersky8e5d3a92014-03-15 14:06:00 -0700221 def test_forloop_coord(self):
222 t = '''\
223 void foo() {
224 for(int z=0; z<4;
225 z++){}
226 }
227 '''
228 s = self.parse(t, filename='f.c')
229 forloop = s.ext[0].body.block_items[0]
serpilliere471442f2017-03-10 15:02:00 +0100230 self.assert_coord(forloop.init, 2, 13, 'f.c')
231 self.assert_coord(forloop.cond, 2, 26, 'f.c')
232 self.assert_coord(forloop.next, 3, 17, 'f.c')
Eli Bendersky8e5d3a92014-03-15 14:06:00 -0700233
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300234 def test_simple_decls(self):
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800235 self.assertEqual(self.get_decl('int a;'),
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300236 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
237
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800238 self.assertEqual(self.get_decl('unsigned int a;'),
Eli Bendersky68497c22012-01-19 06:04:58 +0200239 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['unsigned', 'int']]]])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300240
eli.benderskyaffe0322011-09-24 06:16:55 +0300241 self.assertEqual(self.get_decl('_Bool a;'),
242 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['_Bool']]]])
243
Eli Benderskyf4d73462012-01-19 05:56:27 +0200244 self.assertEqual(self.get_decl('float _Complex fcc;'),
Eli Bendersky68497c22012-01-19 06:04:58 +0200245 ['Decl', 'fcc', ['TypeDecl', ['IdentifierType', ['float', '_Complex']]]])
Eli Benderskyf4d73462012-01-19 05:56:27 +0200246
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800247 self.assertEqual(self.get_decl('char* string;'),
248 ['Decl', 'string',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300249 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]])
250
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800251 self.assertEqual(self.get_decl('long ar[15];'),
252 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800253 ['ArrayDecl', '15', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300254 ['TypeDecl', ['IdentifierType', ['long']]]]])
eli.bendersky98f45372010-10-30 09:46:29 +0200255
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800256 self.assertEqual(self.get_decl('long long ar[15];'),
257 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800258 ['ArrayDecl', '15', [],
eli.benderskyf890a862010-10-30 12:13:23 +0200259 ['TypeDecl', ['IdentifierType', ['long', 'long']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800260
261 self.assertEqual(self.get_decl('unsigned ar[];'),
262 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800263 ['ArrayDecl', '', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300264 ['TypeDecl', ['IdentifierType', ['unsigned']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800265
266 self.assertEqual(self.get_decl('int strlen(char* s);'),
267 ['Decl', 'strlen',
268 ['FuncDecl',
269 [['Decl', 's',
270 ['PtrDecl',
271 ['TypeDecl', ['IdentifierType', ['char']]]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300272 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800273
274 self.assertEqual(self.get_decl('int strcmp(char* s1, char* s2);'),
275 ['Decl', 'strcmp',
276 ['FuncDecl',
277 [ ['Decl', 's1',
278 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
279 ['Decl', 's2',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300280 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800281 ],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300282 ['TypeDecl', ['IdentifierType', ['int']]]]])
283
Sye van der Veen51a46ec2013-06-10 12:56:15 -0400284 # function return values and parameters may not have type information
Eli Bendersky09e22a62013-07-02 06:00:36 -0700285 self.assertEqual(self.get_decl('extern foobar(foo, bar);'),
286 ['Decl', 'foobar',
287 ['FuncDecl',
Sye van der Veen51a46ec2013-06-10 12:56:15 -0400288 [ ['ID', 'foo'],
289 ['ID', 'bar']
Eli Bendersky09e22a62013-07-02 06:00:36 -0700290 ],
Sye van der Veen51a46ec2013-06-10 12:56:15 -0400291 ['TypeDecl', ['IdentifierType', ['int']]]]])
292
Manuel Jacob0a15d7d2017-01-12 15:46:05 +0100293 def test_int128(self):
294 self.assertEqual(self.get_decl('__int128 a;'),
295 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['__int128']]]])
296
297
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300298 def test_nested_decls(self): # the fun begins
299 self.assertEqual(self.get_decl('char** ar2D;'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800300 ['Decl', 'ar2D',
301 ['PtrDecl', ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300302 ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800303
304 self.assertEqual(self.get_decl('int (*a)[1][2];'),
305 ['Decl', 'a',
306 ['PtrDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800307 ['ArrayDecl', '1', [],
308 ['ArrayDecl', '2', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300309 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
310
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800311 self.assertEqual(self.get_decl('int *a[1][2];'),
312 ['Decl', 'a',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800313 ['ArrayDecl', '1', [],
314 ['ArrayDecl', '2', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300315 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['int']]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800316
Eli Benderskyb17da152015-04-21 14:35:18 -0700317 self.assertEqual(self.get_decl('char* const* p;'),
318 ['Decl', 'p',
319 ['PtrDecl', ['PtrDecl', ['const'],
320 ['TypeDecl', ['IdentifierType', ['char']]]]]])
321
322 self.assertEqual(self.get_decl('char* * const p;'),
323 ['Decl', 'p',
324 ['PtrDecl', ['const'], ['PtrDecl',
325 ['TypeDecl', ['IdentifierType', ['char']]]]]])
326
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300327 self.assertEqual(self.get_decl('char ***ar3D[40];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800328 ['Decl', 'ar3D',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800329 ['ArrayDecl', '40', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800330 ['PtrDecl', ['PtrDecl', ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300331 ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800332
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300333 self.assertEqual(self.get_decl('char (***ar3D)[40];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800334 ['Decl', 'ar3D',
335 ['PtrDecl', ['PtrDecl', ['PtrDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800336 ['ArrayDecl', '40', [], ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800337
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300338 self.assertEqual(self.get_decl('int (*x[4])(char, int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800339 ['Decl', 'x',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800340 ['ArrayDecl', '4', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800341 ['PtrDecl',
342 ['FuncDecl',
343 [ ['Typename', ['TypeDecl', ['IdentifierType', ['char']]]],
344 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300345 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800346
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300347 self.assertEqual(self.get_decl('char *(*(**foo [][8])())[];'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800348 ['Decl', 'foo',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800349 ['ArrayDecl', '', [],
350 ['ArrayDecl', '8', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800351 ['PtrDecl', ['PtrDecl',
352 ['FuncDecl',
353 [],
354 ['PtrDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800355 ['ArrayDecl', '', [],
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800356 ['PtrDecl',
357 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300358 ['IdentifierType', ['char']]]]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800359
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300360 # explore named and unnamed function pointer parameters,
361 # with and without qualifiers
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800362
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300363 # unnamed w/o quals
364 self.assertEqual(self.get_decl('int (*k)(int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800365 ['Decl', 'k',
366 ['PtrDecl',
367 ['FuncDecl',
368 [['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300369 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800370
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300371 # unnamed w/ quals
372 self.assertEqual(self.get_decl('int (*k)(const int);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800373 ['Decl', 'k',
374 ['PtrDecl',
375 ['FuncDecl',
376 [['Typename', ['const'], ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300377 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800378
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300379 # named w/o quals
380 self.assertEqual(self.get_decl('int (*k)(int q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800381 ['Decl', 'k',
382 ['PtrDecl',
383 ['FuncDecl',
384 [['Decl', 'q', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300385 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800386
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300387 # named w/ quals
388 self.assertEqual(self.get_decl('int (*k)(const volatile int q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800389 ['Decl', 'k',
390 ['PtrDecl',
391 ['FuncDecl',
392 [['Decl', ['const', 'volatile'], 'q',
393 ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300394 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800395
eli.bendersky79d5cf62010-10-29 13:33:52 +0200396 # restrict qualifier
397 self.assertEqual(self.get_decl('int (*k)(restrict int* q);'),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800398 ['Decl', 'k',
399 ['PtrDecl',
400 ['FuncDecl',
401 [['Decl', ['restrict'], 'q',
eli.bendersky79d5cf62010-10-29 13:33:52 +0200402 ['PtrDecl',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800403 ['TypeDecl', ['IdentifierType', ['int']]]]]],
eli.bendersky79d5cf62010-10-29 13:33:52 +0200404 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800405
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800406 def test_func_decls_with_array_dim_qualifiers(self):
407 self.assertEqual(self.get_decl('int zz(int p[static 10]);'),
408 ['Decl', 'zz',
409 ['FuncDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800410 [['Decl', 'p', ['ArrayDecl', '10', ['static'],
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800411 ['TypeDecl', ['IdentifierType', ['int']]]]]],
412 ['TypeDecl', ['IdentifierType', ['int']]]]])
413
414 self.assertEqual(self.get_decl('int zz(int p[const 10]);'),
415 ['Decl', 'zz',
416 ['FuncDecl',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800417 [['Decl', 'p', ['ArrayDecl', '10', ['const'],
Eli Benderskye7c55cf2014-01-25 06:15:43 -0800418 ['TypeDecl', ['IdentifierType', ['int']]]]]],
419 ['TypeDecl', ['IdentifierType', ['int']]]]])
420
necase4a6afa02014-12-19 16:38:37 -0600421 self.assertEqual(self.get_decl('int zz(int p[restrict][5]);'),
422 ['Decl', 'zz',
423 ['FuncDecl',
424 [['Decl', 'p', ['ArrayDecl', '', ['restrict'],
425 ['ArrayDecl', '5', [],
426 ['TypeDecl', ['IdentifierType', ['int']]]]]]],
427 ['TypeDecl', ['IdentifierType', ['int']]]]])
428
429 self.assertEqual(self.get_decl('int zz(int p[const restrict static 10][5]);'),
430 ['Decl', 'zz',
431 ['FuncDecl',
432 [['Decl', 'p', ['ArrayDecl', '10', ['const', 'restrict', 'static'],
433 ['ArrayDecl', '5', [],
434 ['TypeDecl', ['IdentifierType', ['int']]]]]]],
435 ['TypeDecl', ['IdentifierType', ['int']]]]])
436
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300437 def test_qualifiers_storage_specifiers(self):
438 def assert_qs(txt, index, quals, storage):
439 d = self.parse(txt).ext[index]
440 self.assertEqual(d.quals, quals)
441 self.assertEqual(d.storage, storage)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800442
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300443 assert_qs("extern int p;", 0, [], ['extern'])
444 assert_qs("const long p = 6;", 0, ['const'], [])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800445
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300446 d1 = "static const int p, q, r;"
447 for i in range(3):
448 assert_qs(d1, i, ['const'], ['static'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800449
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300450 d2 = "static char * const p;"
451 assert_qs(d2, 0, [], ['static'])
452 pdecl = self.parse(d2).ext[0].type
Eli Benderskya1da7fd2012-07-06 15:48:57 +0300453 self.assertTrue(isinstance(pdecl, PtrDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300454 self.assertEqual(pdecl.quals, ['const'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800455
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300456 def test_sizeof(self):
457 e = """
458 void foo()
459 {
460 int a = sizeof k;
461 int b = sizeof(int);
eli.benderskyc51e1d32011-02-04 08:52:33 +0200462 int c = sizeof(int**);;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800463
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300464 char* p = "just to make sure this parses w/o error...";
465 int d = sizeof(int());
466 }
467 """
468 compound = self.parse(e).ext[0].body
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800469
eli.benderskyef29ff92010-10-29 16:25:43 +0200470 s1 = compound.block_items[0].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300471 self.assertTrue(isinstance(s1, UnaryOp))
472 self.assertEqual(s1.op, 'sizeof')
473 self.assertTrue(isinstance(s1.expr, ID))
474 self.assertEqual(s1.expr.name, 'k')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800475
eli.benderskyef29ff92010-10-29 16:25:43 +0200476 s2 = compound.block_items[1].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300477 self.assertEqual(expand_decl(s2.expr),
478 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800479
eli.benderskyef29ff92010-10-29 16:25:43 +0200480 s3 = compound.block_items[2].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300481 self.assertEqual(expand_decl(s3.expr),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800482 ['Typename',
483 ['PtrDecl',
484 ['PtrDecl',
485 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300486 ['IdentifierType', ['int']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800487
Eli Benderskye59395b2015-05-09 15:20:46 -0700488 def test_offsetof(self):
489 e = """
490 void foo() {
491 int a = offsetof(struct S, p);
492 a.b = offsetof(struct sockaddr, sp) + strlen(bar);
ksero749650a2016-09-09 07:31:09 +0200493 int a = offsetof(struct S, p.q.r);
494 int a = offsetof(struct S, p[5].q[4][5]);
Eli Benderskye59395b2015-05-09 15:20:46 -0700495 }
496 """
497 compound = self.parse(e).ext[0].body
498 s1 = compound.block_items[0].init
Eli Benderskya71ec1b2015-05-10 06:31:20 -0700499 self.assertTrue(isinstance(s1, FuncCall))
500 self.assertTrue(isinstance(s1.name, ID))
Eli Benderskye59395b2015-05-09 15:20:46 -0700501 self.assertEqual(s1.name.name, 'offsetof')
Eli Benderskya71ec1b2015-05-10 06:31:20 -0700502 self.assertTrue(isinstance(s1.args.exprs[0], Typename))
503 self.assertTrue(isinstance(s1.args.exprs[1], ID))
ksero749650a2016-09-09 07:31:09 +0200504 s3 = compound.block_items[2].init
505 self.assertTrue(isinstance(s3.args.exprs[1], StructRef))
506 s4 = compound.block_items[3].init
507 self.assertTrue(isinstance(s4.args.exprs[1], ArrayRef))
Eli Benderskye59395b2015-05-09 15:20:46 -0700508
Eli Benderskydbf9be22016-10-11 20:44:32 -0700509 def test_compound_statement(self):
510 e = """
511 void foo() {
512 }
513 """
514 compound = self.parse(e).ext[0].body
515 self.assertTrue(isinstance(compound, Compound))
serpilliere471442f2017-03-10 15:02:00 +0100516 self.assert_coord(compound, 2)
Eli Benderskydbf9be22016-10-11 20:44:32 -0700517
eli.bendersky9f481562010-10-30 15:50:47 +0200518 # The C99 compound literal feature
519 #
eli.benderskyf890a862010-10-30 12:13:23 +0200520 def test_compound_literals(self):
eli.bendersky9f481562010-10-30 15:50:47 +0200521 ps1 = self.parse(r'''
eli.benderskyf890a862010-10-30 12:13:23 +0200522 void foo() {
eli.bendersky9f481562010-10-30 15:50:47 +0200523 p = (long long){k};
524 tc = (struct jk){.a = {1, 2}, .b[0] = t};
525 }''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800526
eli.bendersky9f481562010-10-30 15:50:47 +0200527 compound = ps1.ext[0].body.block_items[0].rvalue
528 self.assertEqual(expand_decl(compound.type),
529 ['Typename', ['TypeDecl', ['IdentifierType', ['long', 'long']]]])
530 self.assertEqual(expand_init(compound.init),
531 [['ID', 'k']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800532
533 compound = ps1.ext[0].body.block_items[1].rvalue
eli.bendersky9f481562010-10-30 15:50:47 +0200534 self.assertEqual(expand_decl(compound.type),
535 ['Typename', ['TypeDecl', ['Struct', 'jk', []]]])
536 self.assertEqual(expand_init(compound.init),
537 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800538 ([['ID', 'a']], [['Constant', 'int', '1'], ['Constant', 'int', '2']]),
eli.bendersky9f481562010-10-30 15:50:47 +0200539 ([['ID', 'b'], ['Constant', 'int', '0']], ['ID', 't'])])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800540
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300541 def test_enums(self):
542 e1 = "enum mycolor op;"
543 e1_type = self.parse(e1).ext[0].type.type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800544
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300545 self.assertTrue(isinstance(e1_type, Enum))
546 self.assertEqual(e1_type.name, 'mycolor')
547 self.assertEqual(e1_type.values, None)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800548
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300549 e2 = "enum mysize {large=20, small, medium} shoes;"
550 e2_type = self.parse(e2).ext[0].type.type
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800551
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300552 self.assertTrue(isinstance(e2_type, Enum))
553 self.assertEqual(e2_type.name, 'mysize')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800554
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300555 e2_elist = e2_type.values
556 self.assertTrue(isinstance(e2_elist, EnumeratorList))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800557
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300558 for e2_eval in e2_elist.enumerators:
559 self.assertTrue(isinstance(e2_eval, Enumerator))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800560
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300561 self.assertEqual(e2_elist.enumerators[0].name, 'large')
562 self.assertEqual(e2_elist.enumerators[0].value.value, '20')
563 self.assertEqual(e2_elist.enumerators[2].name, 'medium')
564 self.assertEqual(e2_elist.enumerators[2].value, None)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800565
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300566 # enum with trailing comma (C99 feature)
567 e3 = """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800568 enum
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300569 {
570 red,
571 blue,
572 green,
573 } color;
574 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800575
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300576 e3_type = self.parse(e3).ext[0].type.type
577 self.assertTrue(isinstance(e3_type, Enum))
578 e3_elist = e3_type.values
579 self.assertTrue(isinstance(e3_elist, EnumeratorList))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800580
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300581 for e3_eval in e3_elist.enumerators:
582 self.assertTrue(isinstance(e3_eval, Enumerator))
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800583
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300584 self.assertEqual(e3_elist.enumerators[0].name, 'red')
585 self.assertEqual(e3_elist.enumerators[0].value, None)
586 self.assertEqual(e3_elist.enumerators[1].name, 'blue')
587 self.assertEqual(e3_elist.enumerators[2].name, 'green')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800588
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300589 def test_typedef(self):
590 # without typedef, error
591 s1 = """
592 node k;
593 """
594 self.assertRaises(ParseError, self.parse, s1)
595
596 # now with typedef, works
597 s2 = """
598 typedef void* node;
599 node k;
600 """
601 ps2 = self.parse(s2)
602 self.assertEqual(expand_decl(ps2.ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800603 ['Typedef', 'node',
604 ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300605 ['TypeDecl', ['IdentifierType', ['void']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800606
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300607 self.assertEqual(expand_decl(ps2.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800608 ['Decl', 'k',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300609 ['TypeDecl', ['IdentifierType', ['node']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800610
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300611 s3 = """
612 typedef int T;
613 typedef T *pT;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800614
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300615 pT aa, bb;
616 """
617 ps3 = self.parse(s3)
618 self.assertEqual(expand_decl(ps3.ext[3]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800619 ['Decl', 'bb',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300620 ['TypeDecl', ['IdentifierType', ['pT']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800621
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300622 s4 = '''
623 typedef char* __builtin_va_list;
624 typedef __builtin_va_list __gnuc_va_list;
625 '''
626 ps4 = self.parse(s4)
627 self.assertEqual(expand_decl(ps4.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800628 ['Typedef', '__gnuc_va_list',
629 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300630 ['IdentifierType', ['__builtin_va_list']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800631
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300632 s5 = '''typedef struct tagHash Hash;'''
633 ps5 = self.parse(s5)
634 self.assertEqual(expand_decl(ps5.ext[0]),
635 ['Typedef', 'Hash', ['TypeDecl', ['Struct', 'tagHash', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800636
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300637 def test_struct_union(self):
638 s1 = """
639 struct {
640 int id;
641 char* name;
642 } joe;
643 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800644
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300645 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800646 ['Decl', 'joe',
647 ['TypeDecl', ['Struct', None,
648 [ ['Decl', 'id',
649 ['TypeDecl',
650 ['IdentifierType', ['int']]]],
651 ['Decl', 'name',
652 ['PtrDecl',
653 ['TypeDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300654 ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800655
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300656 s2 = """
657 struct node p;
658 """
659 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800660 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300661 ['TypeDecl', ['Struct', 'node', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800662
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300663 s21 = """
664 union pri ra;
665 """
666 self.assertEqual(expand_decl(self.parse(s21).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800667 ['Decl', 'ra',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300668 ['TypeDecl', ['Union', 'pri', []]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800669
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300670 s3 = """
671 struct node* p;
672 """
673 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800674 ['Decl', 'p',
675 ['PtrDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300676 ['TypeDecl', ['Struct', 'node', []]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800677
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300678 s4 = """
679 struct node;
680 """
681 self.assertEqual(expand_decl(self.parse(s4).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800682 ['Decl', None,
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300683 ['Struct', 'node', []]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800684
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300685 s5 = """
686 union
687 {
688 struct
689 {
690 int type;
691 } n;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800692
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300693 struct
694 {
695 int type;
696 int intnode;
697 } ni;
698 } u;
699 """
700 self.assertEqual(expand_decl(self.parse(s5).ext[0]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800701 ['Decl', 'u',
702 ['TypeDecl',
703 ['Union', None,
704 [['Decl', 'n',
705 ['TypeDecl',
706 ['Struct', None,
707 [['Decl', 'type',
708 ['TypeDecl', ['IdentifierType', ['int']]]]]]]],
709 ['Decl', 'ni',
710 ['TypeDecl',
711 ['Struct', None,
712 [['Decl', 'type',
713 ['TypeDecl', ['IdentifierType', ['int']]]],
714 ['Decl', 'intnode',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300715 ['TypeDecl', ['IdentifierType', ['int']]]]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800716
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300717 s6 = """
718 typedef struct foo_tag
719 {
720 void* data;
721 } foo, *pfoo;
722 """
723 s6_ast = self.parse(s6)
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800724
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300725 self.assertEqual(expand_decl(s6_ast.ext[0]),
726 ['Typedef', 'foo',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800727 ['TypeDecl',
728 ['Struct', 'foo_tag',
729 [['Decl', 'data',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300730 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800731
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300732 self.assertEqual(expand_decl(s6_ast.ext[1]),
733 ['Typedef', 'pfoo',
734 ['PtrDecl',
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800735 ['TypeDecl',
736 ['Struct', 'foo_tag',
737 [['Decl', 'data',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300738 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800739
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300740 s7 = r"""
741 struct _on_exit_args {
742 void * _fnargs[32];
743 void * _dso_handle[32];
744
745 long _fntypes;
746 #line 77 "D:\eli\cpp_stuff\libc_include/sys/reent.h"
747
748 long _is_cxa;
749 };
750 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800751
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300752 s7_ast = self.parse(s7, filename='test.c')
serpilliere471442f2017-03-10 15:02:00 +0100753 self.assert_coord(s7_ast.ext[0].type.decls[2], 6, 22, 'test.c')
754 self.assert_coord(s7_ast.ext[0].type.decls[3], 78, 22,
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300755 r'D:\eli\cpp_stuff\libc_include/sys/reent.h')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800756
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300757 s8 = """
758 typedef enum tagReturnCode {SUCCESS, FAIL} ReturnCode;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800759
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300760 typedef struct tagEntry
761 {
762 char* key;
763 char* value;
764 } Entry;
765
766
767 typedef struct tagNode
768 {
769 Entry* entry;
770
771 struct tagNode* next;
772 } Node;
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800773
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300774 typedef struct tagHash
775 {
776 unsigned int table_size;
777
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800778 Node** heads;
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300779
780 } Hash;
781 """
782 s8_ast = self.parse(s8)
783 self.assertEqual(expand_decl(s8_ast.ext[3]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800784 ['Typedef', 'Hash',
785 ['TypeDecl', ['Struct', 'tagHash',
786 [['Decl', 'table_size',
787 ['TypeDecl', ['IdentifierType', ['unsigned', 'int']]]],
788 ['Decl', 'heads',
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300789 ['PtrDecl', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['Node']]]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800790
Eli Bendersky95e3b762016-03-19 05:21:59 -0700791 def test_struct_with_extra_semis_inside(self):
792 s1 = """
793 struct {
794 int a;;
795 } foo;
796 """
797 s1_ast = self.parse(s1)
798 self.assertEqual(expand_decl(s1_ast.ext[0]),
799 ['Decl', 'foo',
800 ['TypeDecl', ['Struct', None,
801 [['Decl', 'a',
802 ['TypeDecl', ['IdentifierType', ['int']]]]]]]])
803
804 s2 = """
805 struct {
806 int a;;;;
807 float b, c;
808 ;;
809 char d;
810 } foo;
811 """
812 s2_ast = self.parse(s2)
813 self.assertEqual(expand_decl(s2_ast.ext[0]),
814 ['Decl', 'foo',
815 ['TypeDecl', ['Struct', None,
816 [['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]],
817 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['float']]]],
818 ['Decl', 'c', ['TypeDecl', ['IdentifierType', ['float']]]],
819 ['Decl', 'd',
820 ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
821
eli.bendersky697ecc52011-02-10 07:05:13 +0200822 def test_anonymous_struct_union(self):
823 s1 = """
824 union
825 {
826 union
827 {
828 int i;
829 long l;
830 };
831
832 struct
833 {
834 int type;
835 int intnode;
836 };
837 } u;
838 """
839
840 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
841 ['Decl', 'u',
842 ['TypeDecl',
843 ['Union', None,
844 [['Decl', None,
845 ['Union', None,
846 [['Decl', 'i',
847 ['TypeDecl',
848 ['IdentifierType', ['int']]]],
849 ['Decl', 'l',
850 ['TypeDecl',
851 ['IdentifierType', ['long']]]]]]],
852 ['Decl', None,
853 ['Struct', None,
854 [['Decl', 'type',
855 ['TypeDecl',
856 ['IdentifierType', ['int']]]],
857 ['Decl', 'intnode',
858 ['TypeDecl',
859 ['IdentifierType', ['int']]]]]]]]]]])
860
861 s2 = """
862 struct
863 {
864 int i;
865 union
866 {
867 int id;
868 char* name;
869 };
870 float f;
871 } joe;
872 """
873
874 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
875 ['Decl', 'joe',
876 ['TypeDecl',
877 ['Struct', None,
878 [['Decl', 'i',
879 ['TypeDecl',
880 ['IdentifierType', ['int']]]],
881 ['Decl', None,
882 ['Union', None,
883 [['Decl', 'id',
884 ['TypeDecl',
885 ['IdentifierType', ['int']]]],
886 ['Decl', 'name',
887 ['PtrDecl',
888 ['TypeDecl',
889 ['IdentifierType', ['char']]]]]]]],
890 ['Decl', 'f',
891 ['TypeDecl',
892 ['IdentifierType', ['float']]]]]]]])
893
894 # ISO/IEC 9899:201x Commitee Draft 2010-11-16, N1539
895 # section 6.7.2.1, par. 19, example 1
896 s3 = """
897 struct v {
898 union {
899 struct { int i, j; };
900 struct { long k, l; } w;
901 };
902 int m;
903 } v1;
904 """
905
906 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
907 ['Decl', 'v1',
908 ['TypeDecl',
909 ['Struct', 'v',
910 [['Decl', None,
911 ['Union', None,
912 [['Decl', None,
913 ['Struct', None,
914 [['Decl', 'i',
915 ['TypeDecl',
916 ['IdentifierType', ['int']]]],
917 ['Decl', 'j',
918 ['TypeDecl',
919 ['IdentifierType', ['int']]]]]]],
920 ['Decl', 'w',
921 ['TypeDecl',
922 ['Struct', None,
923 [['Decl', 'k',
924 ['TypeDecl',
925 ['IdentifierType', ['long']]]],
926 ['Decl', 'l',
927 ['TypeDecl',
928 ['IdentifierType', ['long']]]]]]]]]]],
929 ['Decl', 'm',
930 ['TypeDecl',
931 ['IdentifierType', ['int']]]]]]]])
932
eli.benderskydce29a02011-02-10 07:55:00 +0200933 s4 = """
934 struct v {
935 int i;
936 float;
937 } v2;"""
eli.bendersky6b011792011-06-22 17:50:56 +0300938 # just make sure this doesn't raise ParseError
939 self.parse(s4)
eli.benderskydce29a02011-02-10 07:55:00 +0200940
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400941 def test_struct_members_namespace(self):
Eli Bendersky4d969b32013-07-13 06:07:07 -0700942 """ Tests that structure/union member names reside in a separate
943 namespace and can be named after existing types.
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400944 """
945 s1 = """
946 typedef int Name;
947 typedef Name NameArray[10];
948
949 struct {
950 Name Name;
951 Name NameArray[3];
952 } sye;
953
954 void main(void)
955 {
956 sye.Name = 1;
957 }
958 """
959
960 s1_ast = self.parse(s1)
961 self.assertEqual(expand_decl(s1_ast.ext[2]),
962 ['Decl', 'sye',
963 ['TypeDecl', ['Struct', None,
964 [ ['Decl', 'Name',
965 ['TypeDecl',
966 ['IdentifierType', ['Name']]]],
967 ['Decl', 'NameArray',
Eli Bendersky8aad3182014-01-25 06:30:53 -0800968 ['ArrayDecl', '3', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -0400969 ['TypeDecl', ['IdentifierType', ['Name']]]]]]]]])
970 self.assertEqual(s1_ast.ext[3].body.block_items[0].lvalue.field.name, 'Name')
971
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200972 def test_struct_bitfields(self):
eli.bendersky38ed9a92010-10-09 09:29:59 +0200973 # a struct with two bitfields, one unnamed
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200974 s1 = """
975 struct {
976 int k:6;
977 int :2;
978 } joe;
979 """
980
981 parsed_struct = self.parse(s1).ext[0]
982
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800983 # We can see here the name of the decl for the unnamed bitfield is
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200984 # None, but expand_decl doesn't show bitfield widths
985 # ...
986 self.assertEqual(expand_decl(parsed_struct),
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800987 ['Decl', 'joe',
988 ['TypeDecl', ['Struct', None,
989 [ ['Decl', 'k',
990 ['TypeDecl',
991 ['IdentifierType', ['int']]]],
992 ['Decl', None,
993 ['TypeDecl',
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200994 ['IdentifierType', ['int']]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800995
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200996 # ...
997 # so we test them manually
998 self.assertEqual(parsed_struct.type.type.decls[0].bitsize.value, '6')
Eli Bendersky86f2eee2013-01-18 06:04:01 -0800999 self.assertEqual(parsed_struct.type.type.decls[1].bitsize.value, '2')
1000
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001001 def test_tags_namespace(self):
1002 """ Tests that the tags of structs/unions/enums reside in a separate namespace and
1003 can be named after existing types.
1004 """
1005 s1 = """
1006 typedef int tagEntry;
1007
1008 struct tagEntry
1009 {
1010 char* key;
1011 char* value;
1012 } Entry;
1013 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001014
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001015 s1_ast = self.parse(s1)
1016 self.assertEqual(expand_decl(s1_ast.ext[1]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001017 ['Decl', 'Entry',
1018 ['TypeDecl', ['Struct', 'tagEntry',
1019 [['Decl', 'key',
1020 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
1021 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001022 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001023
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001024 s2 = """
1025 struct tagEntry;
1026
1027 typedef struct tagEntry tagEntry;
1028
1029 struct tagEntry
1030 {
1031 char* key;
1032 char* value;
1033 } Entry;
1034 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001035
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001036 s2_ast = self.parse(s2)
1037 self.assertEqual(expand_decl(s2_ast.ext[2]),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001038 ['Decl', 'Entry',
1039 ['TypeDecl', ['Struct', 'tagEntry',
1040 [['Decl', 'key',
1041 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
1042 ['Decl', 'value',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001043 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001044
1045 s3 = """
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001046 typedef int mytag;
1047
1048 enum mytag {ABC, CDE};
1049 enum mytag joe;
1050 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001051
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001052 s3_type = self.parse(s3).ext[1].type
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001053
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001054 self.assertTrue(isinstance(s3_type, Enum))
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001055 self.assertEqual(s3_type.name, 'mytag')
1056
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001057 def test_multi_decls(self):
1058 d1 = 'int a, b;'
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001059
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001060 self.assertEqual(self.get_decl(d1, 0),
1061 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
1062 self.assertEqual(self.get_decl(d1, 1),
1063 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['int']]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001064
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001065 d2 = 'char* p, notp, ar[4];'
1066 self.assertEqual(self.get_decl(d2, 0),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001067 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001068 ['PtrDecl',
1069 ['TypeDecl', ['IdentifierType', ['char']]]]])
1070 self.assertEqual(self.get_decl(d2, 1),
1071 ['Decl', 'notp', ['TypeDecl', ['IdentifierType', ['char']]]])
1072 self.assertEqual(self.get_decl(d2, 2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001073 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001074 ['ArrayDecl', '4', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001075 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001076
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001077 def test_invalid_multiple_types_error(self):
1078 bad = [
1079 'int enum {ab, cd} fubr;',
1080 'enum kid char brbr;']
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001081
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001082 for b in bad:
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001083 self.assertRaises(ParseError, self.parse, b)
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001084
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001085 def test_duplicate_typedef(self):
1086 """ Tests that redeclarations of existing types are parsed correctly.
1087 This is non-standard, but allowed by many compilers.
1088 """
1089 d1 = '''
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001090 typedef int numbertype;
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001091 typedef int numbertype;
Eli Bendersky9dadc3f2012-07-06 15:53:53 +03001092 '''
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001093
1094 self.assertEqual(self.get_decl(d1, 0),
1095 ['Typedef', 'numbertype',
1096 ['TypeDecl', ['IdentifierType', ['int']]]])
1097 self.assertEqual(self.get_decl(d1, 1),
1098 ['Typedef', 'numbertype',
1099 ['TypeDecl', ['IdentifierType', ['int']]]])
1100
1101 d2 = '''
1102 typedef int (*funcptr)(int x);
1103 typedef int (*funcptr)(int x);
1104 '''
1105 self.assertEqual(self.get_decl(d2, 0),
1106 ['Typedef', 'funcptr',
1107 ['PtrDecl', ['FuncDecl',
1108 [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]],
1109 ['TypeDecl', ['IdentifierType', ['int']]]]]])
1110 self.assertEqual(self.get_decl(d2, 1),
1111 ['Typedef', 'funcptr',
1112 ['PtrDecl', ['FuncDecl',
1113 [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]],
1114 ['TypeDecl', ['IdentifierType', ['int']]]]]])
1115
1116 d3 = '''
1117 typedef int numberarray[5];
1118 typedef int numberarray[5];
1119 '''
1120 self.assertEqual(self.get_decl(d3, 0),
1121 ['Typedef', 'numberarray',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001122 ['ArrayDecl', '5', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001123 ['TypeDecl', ['IdentifierType', ['int']]]]])
1124 self.assertEqual(self.get_decl(d3, 1),
1125 ['Typedef', 'numberarray',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001126 ['ArrayDecl', '5', [],
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001127 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001128
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001129 def test_decl_inits(self):
1130 d1 = 'int a = 16;'
eli.benderskyf890a862010-10-30 12:13:23 +02001131 #~ self.parse(d1).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001132 self.assertEqual(self.get_decl(d1),
1133 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
1134 self.assertEqual(self.get_decl_init(d1),
1135 ['Constant', 'int', '16'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001136
Eli Bendersky3b1b08d2012-06-15 12:37:54 +03001137 d1_1 = 'float f = 0xEF.56p1;'
1138 self.assertEqual(self.get_decl_init(d1_1),
1139 ['Constant', 'float', '0xEF.56p1'])
1140
Konstanty Bialkowski3bdbfdc2015-04-19 20:09:21 +10001141 d1_2 = 'int bitmask = 0b1001010;'
1142 self.assertEqual(self.get_decl_init(d1_2),
1143 ['Constant', 'int', '0b1001010'])
1144
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001145 d2 = 'long ar[] = {7, 8, 9};'
1146 self.assertEqual(self.get_decl(d2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001147 ['Decl', 'ar',
Eli Bendersky8aad3182014-01-25 06:30:53 -08001148 ['ArrayDecl', '', [],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001149 ['TypeDecl', ['IdentifierType', ['long']]]]])
1150 self.assertEqual(self.get_decl_init(d2),
1151 [ ['Constant', 'int', '7'],
1152 ['Constant', 'int', '8'],
eli.benderskyf890a862010-10-30 12:13:23 +02001153 ['Constant', 'int', '9']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001154
Eli Benderskyc830da82015-05-10 07:56:41 -07001155 d21 = 'long ar[4] = {};'
1156 self.assertEqual(self.get_decl_init(d21), [])
1157
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001158 d3 = 'char p = j;'
1159 self.assertEqual(self.get_decl(d3),
1160 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['char']]]])
1161 self.assertEqual(self.get_decl_init(d3),
1162 ['ID', 'j'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001163
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001164 d4 = "char x = 'c', *p = {0, 1, 2, {4, 5}, 6};"
1165 self.assertEqual(self.get_decl(d4, 0),
1166 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['char']]]])
1167 self.assertEqual(self.get_decl_init(d4, 0),
1168 ['Constant', 'char', "'c'"])
1169 self.assertEqual(self.get_decl(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001170 ['Decl', 'p',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001171 ['PtrDecl',
1172 ['TypeDecl', ['IdentifierType', ['char']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001173
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001174 self.assertEqual(self.get_decl_init(d4, 1),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001175 [ ['Constant', 'int', '0'],
1176 ['Constant', 'int', '1'],
1177 ['Constant', 'int', '2'],
1178 [['Constant', 'int', '4'],
1179 ['Constant', 'int', '5']],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001180 ['Constant', 'int', '6']])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001181
eli.benderskyf890a862010-10-30 12:13:23 +02001182 def test_decl_named_inits(self):
1183 d1 = 'int a = {.k = 16};'
1184 self.assertEqual(self.get_decl_init(d1),
1185 [( [['ID', 'k']],
1186 ['Constant', 'int', '16'])])
1187
1188 d2 = 'int a = { [0].a = {1}, [1].a[0] = 2 };'
1189 self.assertEqual(self.get_decl_init(d2),
1190 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001191 ([['Constant', 'int', '0'], ['ID', 'a']],
1192 [['Constant', 'int', '1']]),
1193 ([['Constant', 'int', '1'], ['ID', 'a'], ['Constant', 'int', '0']],
eli.benderskyf890a862010-10-30 12:13:23 +02001194 ['Constant', 'int', '2'])])
1195
1196 d3 = 'int a = { .a = 1, .c = 3, 4, .b = 5};'
1197 self.assertEqual(self.get_decl_init(d3),
1198 [
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001199 ([['ID', 'a']], ['Constant', 'int', '1']),
1200 ([['ID', 'c']], ['Constant', 'int', '3']),
1201 ['Constant', 'int', '4'],
eli.benderskyf890a862010-10-30 12:13:23 +02001202 ([['ID', 'b']], ['Constant', 'int', '5'])])
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001203
1204 def test_function_definitions(self):
1205 def parse_fdef(str):
1206 return self.parse(str).ext[0]
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001207
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001208 def fdef_decl(fdef):
1209 return expand_decl(fdef.decl)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001210
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001211 f1 = parse_fdef('''
1212 int factorial(int p)
1213 {
1214 return 3;
1215 }
1216 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001217
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001218 self.assertEqual(fdef_decl(f1),
1219 ['Decl', 'factorial',
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001220 ['FuncDecl',
1221 [['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001222 ['TypeDecl', ['IdentifierType', ['int']]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001223
eli.benderskyef29ff92010-10-29 16:25:43 +02001224 self.assertEqual(type(f1.body.block_items[0]), Return)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001225
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001226 f2 = parse_fdef('''
1227 char* zzz(int p, char* c)
1228 {
1229 int a;
1230 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001231
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001232 a = b + 2;
1233 return 3;
1234 }
1235 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001236
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001237 self.assertEqual(fdef_decl(f2),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001238 ['Decl', 'zzz',
1239 ['FuncDecl',
1240 [ ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]],
1241 ['Decl', 'c', ['PtrDecl',
1242 ['TypeDecl', ['IdentifierType', ['char']]]]]],
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001243 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001244
1245 self.assertEqual(list(map(type, f2.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001246 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001247
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001248 f3 = parse_fdef('''
1249 char* zzz(p, c)
1250 long p, *c;
1251 {
1252 int a;
1253 char b;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001254
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001255 a = b + 2;
1256 return 3;
1257 }
1258 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001259
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001260 self.assertEqual(fdef_decl(f3),
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001261 ['Decl', 'zzz',
1262 ['FuncDecl',
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001263 [ ['ID', 'p'],
1264 ['ID', 'c']],
1265 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001266
1267 self.assertEqual(list(map(type, f3.body.block_items)),
eli.benderskyef29ff92010-10-29 16:25:43 +02001268 [Decl, Decl, Assignment, Return])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001269
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001270 self.assertEqual(expand_decl(f3.param_decls[0]),
1271 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['long']]]])
1272 self.assertEqual(expand_decl(f3.param_decls[1]),
1273 ['Decl', 'c', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['long']]]]])
1274
Sye van der Veen51a46ec2013-06-10 12:56:15 -04001275 # function return values and parameters may not have type information
1276 f4 = parse_fdef('''
1277 que(p)
1278 {
1279 return 3;
1280 }
1281 ''')
1282
1283 self.assertEqual(fdef_decl(f4),
1284 ['Decl', 'que',
1285 ['FuncDecl',
1286 [['ID', 'p']],
1287 ['TypeDecl', ['IdentifierType', ['int']]]]])
1288
eli.bendersky71540662010-07-03 12:58:52 +02001289 def test_unified_string_literals(self):
1290 # simple string, for reference
1291 d1 = self.get_decl_init('char* s = "hello";')
1292 self.assertEqual(d1, ['Constant', 'string', '"hello"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001293
eli.bendersky71540662010-07-03 12:58:52 +02001294 d2 = self.get_decl_init('char* s = "hello" " world";')
1295 self.assertEqual(d2, ['Constant', 'string', '"hello world"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001296
eli.bendersky71540662010-07-03 12:58:52 +02001297 # the test case from issue 6
1298 d3 = self.parse(r'''
1299 int main() {
1300 fprintf(stderr,
1301 "Wrong Params?\n"
1302 "Usage:\n"
1303 "%s <binary_file_path>\n",
1304 argv[0]
1305 );
1306 }
1307 ''')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001308
eli.bendersky71540662010-07-03 12:58:52 +02001309 self.assertEqual(
eli.benderskyef29ff92010-10-29 16:25:43 +02001310 d3.ext[0].body.block_items[0].args.exprs[1].value,
eli.bendersky71540662010-07-03 12:58:52 +02001311 r'"Wrong Params?\nUsage:\n%s <binary_file_path>\n"')
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001312
eli.bendersky4a89f112010-07-05 06:02:03 +02001313 d4 = self.get_decl_init('char* s = "" "foobar";')
1314 self.assertEqual(d4, ['Constant', 'string', '"foobar"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001315
eli.bendersky4a89f112010-07-05 06:02:03 +02001316 d5 = self.get_decl_init(r'char* s = "foo\"" "bar";')
1317 self.assertEqual(d5, ['Constant', 'string', r'"foo\"bar"'])
eli.bendersky71540662010-07-03 12:58:52 +02001318
Eli Benderskyc9f1a382014-03-15 14:12:00 -07001319 def test_unified_wstring_literals(self):
1320 d1 = self.get_decl_init('char* s = L"hello" L"world";')
1321 self.assertEqual(d1, ['Constant', 'string', 'L"helloworld"'])
1322
1323 d2 = self.get_decl_init('char* s = L"hello " L"world" L" and I";')
1324 self.assertEqual(d2, ['Constant', 'string', 'L"hello world and I"'])
1325
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001326 def test_inline_specifier(self):
eli.bendersky79d5cf62010-10-29 13:33:52 +02001327 ps2 = self.parse('static inline void inlinefoo(void);')
1328 self.assertEqual(ps2.ext[0].funcspec, ['inline'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001329
eli.bendersky2e907fa2010-10-29 15:51:07 +02001330 # variable length array
1331 def test_vla(self):
1332 ps2 = self.parse(r'''
1333 int main() {
1334 int size;
1335 int var[size = 5];
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001336
eli.bendersky2e907fa2010-10-29 15:51:07 +02001337 int var2[*];
1338 }
1339 ''')
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001340 self.assertTrue(isinstance(ps2.ext[0].body.block_items[1].type.dim, Assignment))
1341 self.assertTrue(isinstance(ps2.ext[0].body.block_items[2].type.dim, ID))
eli.bendersky79d5cf62010-10-29 13:33:52 +02001342
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001343 def test_pragma(self):
1344 s1 = r'''
1345 #pragma bar
1346 void main() {
1347 #pragma foo
1348 for(;;) {}
Julian Hammer8a174062015-12-14 14:48:16 +01001349 #pragma
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001350 }
ldoreec233182017-11-22 14:52:53 +01001351 struct s {
1352 #pragma baz
1353 } s;
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001354 '''
1355 s1_ast = self.parse(s1)
1356 self.assertTrue(isinstance(s1_ast.ext[0], Pragma))
1357 self.assertEqual(s1_ast.ext[0].string, 'bar')
Julian Hammer8a174062015-12-14 14:48:16 +01001358 self.assertEqual(s1_ast.ext[0].coord.line, 2)
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001359
1360 self.assertTrue(isinstance(s1_ast.ext[1].body.block_items[0], Pragma))
1361 self.assertEqual(s1_ast.ext[1].body.block_items[0].string, 'foo')
Julian Hammer8a174062015-12-14 14:48:16 +01001362 self.assertEqual(s1_ast.ext[1].body.block_items[0].coord.line, 4)
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001363
Julian Hammer8a174062015-12-14 14:48:16 +01001364 self.assertTrue(isinstance(s1_ast.ext[1].body.block_items[2], Pragma))
1365 self.assertEqual(s1_ast.ext[1].body.block_items[2].string, '')
1366 self.assertEqual(s1_ast.ext[1].body.block_items[2].coord.line, 6)
ldoreec233182017-11-22 14:52:53 +01001367
1368 self.assertTrue(isinstance(s1_ast.ext[2].type.type.decls[0], Pragma))
1369 self.assertEqual(s1_ast.ext[2].type.type.decls[0].string, 'baz')
1370 self.assertEqual(s1_ast.ext[2].type.type.decls[0].coord.line, 9)
Julian Hammerdb9f2da2015-10-12 15:52:12 +02001371
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001372
eli.bendersky85d2e732011-05-20 19:47:26 +03001373class TestCParser_whole_code(TestCParser_base):
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001374 """ Testing of parsing whole chunks of code.
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001375
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001376 Since I don't want to rely on the structure of ASTs too
1377 much, most of these tests are implemented with visitors.
1378 """
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001379 # A simple helper visitor that lists the values of all the
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001380 # Constant nodes it sees.
1381 #
1382 class ConstantVisitor(NodeVisitor):
1383 def __init__(self):
1384 self.values = []
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001385
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001386 def visit_Constant(self, node):
1387 self.values.append(node.value)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001388
1389 # This visitor counts the amount of references to the ID
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001390 # with the name provided to it in the constructor.
1391 #
1392 class IDNameCounter(NodeVisitor):
1393 def __init__(self, name):
1394 self.name = name
1395 self.nrefs = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001396
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001397 def visit_ID(self, node):
1398 if node.name == self.name:
1399 self.nrefs += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001400
1401 # Counts the amount of nodes of a given class
1402 #
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001403 class NodeKlassCounter(NodeVisitor):
1404 def __init__(self, node_klass):
1405 self.klass = node_klass
1406 self.n = 0
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001407
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001408 def generic_visit(self, node):
1409 if node.__class__ == self.klass:
1410 self.n += 1
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001411
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001412 NodeVisitor.generic_visit(self, node)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001413
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001414 def assert_all_Constants(self, code, constants):
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001415 """ Asserts that the list of all Constant values (by
1416 'preorder' appearance) in the chunk of code is as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001417 given.
1418 """
eli.benderskyed890492010-06-25 08:25:55 +03001419 if isinstance(code, str):
1420 parsed = self.parse(code)
1421 else:
1422 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001423
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001424 cv = self.ConstantVisitor()
1425 cv.visit(parsed)
1426 self.assertEqual(cv.values, constants)
1427
1428 def assert_num_ID_refs(self, code, name, num):
1429 """ Asserts the number of references to the ID with
1430 the given name.
1431 """
1432 if isinstance(code, str):
1433 parsed = self.parse(code)
1434 else:
1435 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001436
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001437 iv = self.IDNameCounter(name)
1438 iv.visit(parsed)
1439 self.assertEqual(iv.nrefs, num)
1440
1441 def assert_num_klass_nodes(self, code, klass, num):
1442 """ Asserts the amount of klass nodes in the code.
1443 """
1444 if isinstance(code, str):
1445 parsed = self.parse(code)
1446 else:
1447 parsed = code
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001448
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001449 cv = self.NodeKlassCounter(klass)
1450 cv.visit(parsed)
1451 self.assertEqual(cv.n, num)
1452
1453 def test_expressions(self):
1454 e1 = '''int k = (r + 10.0) >> 6 + 8 << (3 & 0x14);'''
1455 self.assert_all_Constants(e1, ['10.0', '6', '8', '3', '0x14'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001456
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001457 e2 = r'''char n = '\n', *prefix = "st_";'''
1458 self.assert_all_Constants(e2, [r"'\n'", '"st_"'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001459
Eli Bendersky09e22a62013-07-02 06:00:36 -07001460 s1 = r'''int main() {
1461 int i = 5, j = 6, k = 1;
1462 if ((i=j && k == 1) || k > j)
1463 printf("Hello, world\n");
1464 return 0;
1465 }'''
1466 ps1 = self.parse(s1)
1467 self.assert_all_Constants(ps1,
1468 ['5', '6', '1', '1', '"Hello, world\\n"', '0'])
1469 self.assert_num_ID_refs(ps1, 'i', 1)
1470 self.assert_num_ID_refs(ps1, 'j', 2)
1471
1472
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001473 def test_statements(self):
1474 s1 = r'''
1475 void foo(){
1476 if (sp == 1)
1477 if (optind >= argc ||
1478 argv[optind][0] != '-' || argv[optind][1] == '\0')
1479 return -1;
1480 else if (strcmp(argv[optind], "--") == 0) {
1481 optind++;
1482 return -1;
1483 }
1484 }
1485 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001486
1487 self.assert_all_Constants(s1,
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001488 ['1', '0', r"'-'", '1', r"'\0'", '1', r'"--"', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001489
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001490 ps1 = self.parse(s1)
1491 self.assert_num_ID_refs(ps1, 'argv', 3)
1492 self.assert_num_ID_refs(ps1, 'optind', 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001493
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001494 self.assert_num_klass_nodes(ps1, If, 3)
1495 self.assert_num_klass_nodes(ps1, Return, 2)
1496 self.assert_num_klass_nodes(ps1, FuncCall, 1) # strcmp
1497 self.assert_num_klass_nodes(ps1, BinaryOp, 7)
1498
1499 # In the following code, Hash and Node were defined as
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001500 # int to pacify the parser that sees they're used as
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001501 # types
1502 #
1503 s2 = r'''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001504 typedef int Hash, Node;
1505
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001506 void HashDestroy(Hash* hash)
1507 {
1508 unsigned int i;
1509
1510 if (hash == NULL)
1511 return;
1512
1513 for (i = 0; i < hash->table_size; ++i)
1514 {
1515 Node* temp = hash->heads[i];
1516
1517 while (temp != NULL)
1518 {
1519 Node* temp2 = temp;
1520
1521 free(temp->entry->key);
1522 free(temp->entry->value);
1523 free(temp->entry);
1524
1525 temp = temp->next;
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001526
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001527 free(temp2);
1528 }
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001529 }
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001530
1531 free(hash->heads);
1532 hash->heads = NULL;
1533
1534 free(hash);
1535 }
1536 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001537
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001538 ps2 = self.parse(s2)
1539 self.assert_num_klass_nodes(ps2, FuncCall, 6)
1540 self.assert_num_klass_nodes(ps2, FuncDef, 1)
1541 self.assert_num_klass_nodes(ps2, For, 1)
1542 self.assert_num_klass_nodes(ps2, While, 1)
1543 self.assert_num_klass_nodes(ps2, StructRef, 10)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001544
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001545 # declarations don't count
1546 self.assert_num_ID_refs(ps2, 'hash', 6)
1547 self.assert_num_ID_refs(ps2, 'i', 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001548
eli.benderskyed890492010-06-25 08:25:55 +03001549 s3 = r'''
1550 void x(void) {
1551 int a, b;
1552 if (a < b)
1553 do {
1554 a = 0;
1555 } while (0);
1556 else if (a == b) {
1557 a = 1;
1558 }
1559 }
1560 '''
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001561
eli.benderskyed890492010-06-25 08:25:55 +03001562 ps3 = self.parse(s3)
1563 self.assert_num_klass_nodes(ps3, DoWhile, 1)
1564 self.assert_num_ID_refs(ps3, 'a', 4)
1565 self.assert_all_Constants(ps3, ['0', '0', '1'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001566
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001567 def test_empty_statements(self):
eli.bendersky91c0aa32011-10-16 05:50:43 +02001568 s1 = r'''
1569 void foo(void){
1570 ;
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001571 return;;
1572
1573 ;
eli.bendersky91c0aa32011-10-16 05:50:43 +02001574 }
1575 '''
1576 ps1 = self.parse(s1)
Eli Benderskyb77d6c02016-10-11 20:33:53 -07001577 self.assert_num_klass_nodes(ps1, EmptyStatement, 3)
eli.bendersky91c0aa32011-10-16 05:50:43 +02001578 self.assert_num_klass_nodes(ps1, Return, 1)
serpilliere471442f2017-03-10 15:02:00 +01001579 self.assert_coord(ps1.ext[0].body.block_items[0], 3)
1580 self.assert_coord(ps1.ext[0].body.block_items[1], 4)
1581 self.assert_coord(ps1.ext[0].body.block_items[2], 4)
1582 self.assert_coord(ps1.ext[0].body.block_items[3], 6)
eli.bendersky145890d2010-10-29 12:02:32 +02001583
Ben5cd3fd62012-02-03 06:02:40 +02001584 def test_switch_statement(self):
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001585 def assert_case_node(node, const_value):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001586 self.assertTrue(isinstance(node, Case))
1587 self.assertTrue(isinstance(node.expr, Constant))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001588 self.assertEqual(node.expr.value, const_value)
1589
1590 def assert_default_node(node):
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001591 self.assertTrue(isinstance(node, Default))
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001592
Ben5cd3fd62012-02-03 06:02:40 +02001593 s1 = r'''
1594 int foo(void) {
1595 switch (myvar) {
1596 case 10:
1597 k = 10;
1598 p = k + 1;
1599 return 10;
1600 case 20:
1601 case 30:
1602 return 20;
1603 default:
1604 break;
1605 }
1606 return 0;
1607 }
1608 '''
1609 ps1 = self.parse(s1)
Eli Bendersky12f0c9d2012-02-03 11:22:25 +02001610 switch = ps1.ext[0].body.block_items[0]
1611
1612 block = switch.stmt.block_items
1613 assert_case_node(block[0], '10')
1614 self.assertEqual(len(block[0].stmts), 3)
1615 assert_case_node(block[1], '20')
1616 self.assertEqual(len(block[1].stmts), 0)
1617 assert_case_node(block[2], '30')
1618 self.assertEqual(len(block[2].stmts), 1)
1619 assert_default_node(block[3])
1620
1621 s2 = r'''
1622 int foo(void) {
1623 switch (myvar) {
1624 default:
1625 joe = moe;
1626 return 10;
1627 case 10:
1628 case 20:
1629 case 30:
1630 case 40:
1631 break;
1632 }
1633 return 0;
1634 }
1635 '''
1636 ps2 = self.parse(s2)
1637 switch = ps2.ext[0].body.block_items[0]
1638
1639 block = switch.stmt.block_items
1640 assert_default_node(block[0])
1641 self.assertEqual(len(block[0].stmts), 2)
1642 assert_case_node(block[1], '10')
1643 self.assertEqual(len(block[1].stmts), 0)
1644 assert_case_node(block[2], '20')
1645 self.assertEqual(len(block[1].stmts), 0)
1646 assert_case_node(block[3], '30')
1647 self.assertEqual(len(block[1].stmts), 0)
1648 assert_case_node(block[4], '40')
1649 self.assertEqual(len(block[4].stmts), 1)
Ben5cd3fd62012-02-03 06:02:40 +02001650
eli.bendersky145890d2010-10-29 12:02:32 +02001651 def test_for_statement(self):
1652 s2 = r'''
1653 void x(void)
1654 {
1655 int i;
1656 for (i = 0; i < 5; ++i) {
1657 x = 50;
1658 }
1659 }
1660 '''
1661 ps2 = self.parse(s2)
1662 self.assert_num_klass_nodes(ps2, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001663 # here there are 3 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001664 # a ref in the visitor
1665 #
1666 self.assert_num_ID_refs(ps2, 'i', 3)
Eli Bendersky4476d092012-12-25 14:07:57 -08001667
eli.bendersky145890d2010-10-29 12:02:32 +02001668 s3 = r'''
1669 void x(void)
1670 {
1671 for (int i = 0; i < 5; ++i) {
1672 x = 50;
1673 }
1674 }
1675 '''
1676 ps3 = self.parse(s3)
eli.bendersky145890d2010-10-29 12:02:32 +02001677 self.assert_num_klass_nodes(ps3, For, 1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001678 # here there are 2 refs to 'i' since the declaration doesn't count as
eli.bendersky145890d2010-10-29 12:02:32 +02001679 # a ref in the visitor
1680 #
1681 self.assert_num_ID_refs(ps3, 'i', 2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001682
Eli Bendersky4476d092012-12-25 14:07:57 -08001683 s4 = r'''
1684 void x(void) {
1685 for (int i = 0;;)
1686 i;
1687 }
1688 '''
1689 ps4 = self.parse(s4)
1690 self.assert_num_ID_refs(ps4, 'i', 1)
1691
Eli Benderskyd0973782012-01-19 08:09:33 +02001692 def _open_c_file(self, name):
1693 """ Find a c file by name, taking into account the current dir can be
1694 in a couple of typical places
1695 """
Stefano Riveraebaf5922013-08-08 09:45:26 +02001696 testdir = os.path.dirname(__file__)
1697 name = os.path.join(testdir, 'c_files', name)
1698 assert os.path.exists(name)
1699 return open(name, 'rU')
Eli Benderskyd0973782012-01-19 08:09:33 +02001700
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001701 def test_whole_file(self):
1702 # See how pycparser handles a whole, real C file.
1703 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001704 with self._open_c_file('memmgr_with_h.c') as f:
1705 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001706 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001707
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001708 self.assert_num_klass_nodes(p, FuncDef, 5)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001709
1710 # each FuncDef also has a FuncDecl. 4 declarations
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001711 # + 5 definitions, overall 9
1712 self.assert_num_klass_nodes(p, FuncDecl, 9)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001713
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001714 self.assert_num_klass_nodes(p, Typedef, 4)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001715
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001716 self.assertEqual(p.ext[4].coord.line, 88)
1717 self.assertEqual(p.ext[4].coord.file, "./memmgr.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001718
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001719 self.assertEqual(p.ext[6].coord.line, 10)
1720 self.assertEqual(p.ext[6].coord.file, "memmgr.c")
1721
1722 def test_whole_file_with_stdio(self):
1723 # Parse a whole file with stdio.h included by cpp
1724 #
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001725 with self._open_c_file('cppd_with_stdio_h.c') as f:
1726 code = f.read()
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001727 p = self.parse(code)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001728
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001729 self.assertTrue(isinstance(p.ext[0], Typedef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001730 self.assertEqual(p.ext[0].coord.line, 213)
Ville Skyttä2129f5f2017-03-05 04:52:22 +02001731 self.assertEqual(p.ext[0].coord.file, r"D:\eli\cpp_stuff\libc_include/stddef.h")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001732
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001733 self.assertTrue(isinstance(p.ext[-1], FuncDef))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001734 self.assertEqual(p.ext[-1].coord.line, 15)
1735 self.assertEqual(p.ext[-1].coord.file, "example_c_file.c")
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001736
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001737 self.assertTrue(isinstance(p.ext[-8], Typedef))
1738 self.assertTrue(isinstance(p.ext[-8].type, TypeDecl))
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001739 self.assertEqual(p.ext[-8].name, 'cookie_io_functions_t')
eli.bendersky85d2e732011-05-20 19:47:26 +03001740
1741
1742class TestCParser_typenames(TestCParser_base):
1743 """ Test issues related to the typedef-name problem.
1744 """
1745 def test_innerscope_typedef(self):
1746 # should fail since TT is not a type in bar
1747 s1 = r'''
1748 void foo() {
1749 typedef char TT;
1750 TT x;
1751 }
1752 void bar() {
1753 TT y;
1754 }
1755 '''
1756 self.assertRaises(ParseError, self.parse, s1)
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001757
eli.bendersky85d2e732011-05-20 19:47:26 +03001758 # should succeed since TT is not a type in bar
1759 s2 = r'''
1760 void foo() {
1761 typedef char TT;
1762 TT x;
1763 }
1764 void bar() {
1765 unsigned TT;
1766 }
1767 '''
Eli Benderskya1da7fd2012-07-06 15:48:57 +03001768 self.assertTrue(isinstance(self.parse(s2), FileAST))
Eli Bendersky86f2eee2013-01-18 06:04:01 -08001769
Nate Bogdanowicz14b8a7e2017-02-22 08:54:05 -05001770 def test_ambiguous_parameters(self):
1771 # From ISO/IEC 9899:TC2, 6.7.5.3.11:
1772 # "If, in a parameter declaration, an identifier can be treated either
1773 # as a typedef name or as a parameter name, it shall be taken as a
1774 # typedef name."
1775
1776 # foo takes an int named aa
1777 # bar takes a function taking a TT
1778 s1 = r'''
1779 typedef char TT;
1780 int foo(int (aa));
1781 int bar(int (TT));
1782 '''
1783 s1_ast = self.parse(s1)
1784 self.assertEqual(expand_decl(s1_ast.ext[1].type.args.params[0]),
1785 ['Decl', 'aa', ['TypeDecl', ['IdentifierType', ['int']]]])
1786 self.assertEqual(expand_decl(s1_ast.ext[2].type.args.params[0]),
1787 ['Typename', ['FuncDecl',
1788 [['Typename', ['TypeDecl', ['IdentifierType', ['TT']]]]],
1789 ['TypeDecl', ['IdentifierType', ['int']]]]])
1790
1791 # foo takes a function taking a char
1792 # bar takes a function taking a function taking a char
1793 s2 = r'''
1794 typedef char TT;
1795 int foo(int (aa (char)));
1796 int bar(int (TT (char)));
1797 '''
1798 s2_ast = self.parse(s2)
1799 self.assertEqual(expand_decl(s2_ast.ext[1].type.args.params[0]),
1800 ['Decl', 'aa', ['FuncDecl',
1801 [['Typename', ['TypeDecl', ['IdentifierType', ['char']]]]],
1802 ['TypeDecl', ['IdentifierType', ['int']]]]])
1803 self.assertEqual(expand_decl(s2_ast.ext[2].type.args.params[0]),
1804 ['Typename', ['FuncDecl',
1805 [['Typename', ['FuncDecl',
1806 [['Typename', ['TypeDecl', ['IdentifierType', ['char']]]]],
1807 ['TypeDecl', ['IdentifierType', ['TT']]]]]],
1808 ['TypeDecl', ['IdentifierType', ['int']]]]])
1809
1810
1811 # foo takes an int array named aa
1812 # bar takes a function taking a TT array
1813 s3 = r'''
1814 typedef char TT;
1815 int foo(int (aa[]));
1816 int bar(int (TT[]));
1817 '''
1818 s3_ast = self.parse(s3)
1819 self.assertEqual(expand_decl(s3_ast.ext[1].type.args.params[0]),
1820 ['Decl', 'aa', ['ArrayDecl', '', [], ['TypeDecl', ['IdentifierType', ['int']]]]])
1821 self.assertEqual(expand_decl(s3_ast.ext[2].type.args.params[0]),
1822 ['Typename', ['FuncDecl',
1823 [['Typename', ['ArrayDecl', '', [], ['TypeDecl', ['IdentifierType', ['TT']]]]]],
1824 ['TypeDecl', ['IdentifierType', ['int']]]]])
1825
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001826 def test_innerscope_reuse_typedef_name(self):
1827 # identifiers can be reused in inner scopes; the original should be
1828 # restored at the end of the block
1829 s1 = r'''
1830 typedef char TT;
1831 void foo(void) {
1832 unsigned TT;
1833 TT = 10;
1834 }
1835 TT x = 5;
1836 '''
1837 s1_ast = self.parse(s1)
1838 self.assertEqual(expand_decl(s1_ast.ext[1].body.block_items[0]),
1839 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
Eli Bendersky3877c4c2013-07-13 06:54:04 -07001840 self.assertEqual(expand_decl(s1_ast.ext[2]),
1841 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['TT']]]])
eli.bendersky85d2e732011-05-20 19:47:26 +03001842
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001843 # this should be recognized even with an initializer
1844 s2 = r'''
1845 typedef char TT;
1846 void foo(void) {
1847 unsigned TT = 10;
1848 }
1849 '''
1850 s2_ast = self.parse(s2)
1851 self.assertEqual(expand_decl(s2_ast.ext[1].body.block_items[0]),
1852 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1853
1854 # before the second local variable, TT is a type; after, it's a
1855 # variable
1856 s3 = r'''
1857 typedef char TT;
1858 void foo(void) {
1859 TT tt = sizeof(TT);
1860 unsigned TT = 10;
1861 }
1862 '''
1863 s3_ast = self.parse(s3)
1864 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[0]),
1865 ['Decl', 'tt', ['TypeDecl', ['IdentifierType', ['TT']]]])
1866 self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[1]),
1867 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1868
1869 # a variable and its type can even share the same name
1870 s4 = r'''
1871 typedef char TT;
1872 void foo(void) {
1873 TT TT = sizeof(TT);
1874 unsigned uu = TT * 2;
1875 }
1876 '''
1877 s4_ast = self.parse(s4)
1878 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[0]),
1879 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['TT']]]])
1880 self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[1]),
1881 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1882
1883 # ensure an error is raised if a type, redeclared as a variable, is
1884 # used as a type
1885 s5 = r'''
1886 typedef char TT;
1887 void foo(void) {
1888 unsigned TT = 10;
1889 TT erroneous = 20;
1890 }
1891 '''
1892 self.assertRaises(ParseError, self.parse, s5)
1893
Nate Bogdanowicz14b8a7e2017-02-22 08:54:05 -05001894 # reusing a type name should work with multiple declarators
1895 s6 = r'''
1896 typedef char TT;
1897 void foo(void) {
1898 unsigned TT, uu;
1899 }
1900 '''
1901 s6_ast = self.parse(s6)
1902 items = s6_ast.ext[1].body.block_items
1903 self.assertEqual(expand_decl(items[0]),
1904 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1905 self.assertEqual(expand_decl(items[1]),
1906 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
1907
1908 # reusing a type name should work after a pointer
1909 s7 = r'''
1910 typedef char TT;
1911 void foo(void) {
1912 unsigned * TT;
1913 }
1914 '''
1915 s7_ast = self.parse(s7)
1916 items = s7_ast.ext[1].body.block_items
1917 self.assertEqual(expand_decl(items[0]),
1918 ['Decl', 'TT', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['unsigned']]]]])
1919
1920 # redefine a name in the middle of a multi-declarator declaration
1921 s8 = r'''
1922 typedef char TT;
1923 void foo(void) {
1924 int tt = sizeof(TT), TT, uu = sizeof(TT);
1925 int uu = sizeof(tt);
1926 }
1927 '''
1928 s8_ast = self.parse(s8)
1929 items = s8_ast.ext[1].body.block_items
1930 self.assertEqual(expand_decl(items[0]),
1931 ['Decl', 'tt', ['TypeDecl', ['IdentifierType', ['int']]]])
1932 self.assertEqual(expand_decl(items[1]),
1933 ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['int']]]])
1934 self.assertEqual(expand_decl(items[2]),
1935 ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['int']]]])
1936
1937 # Don't test this until we have support for it
1938 # self.assertEqual(expand_init(items[0].init),
1939 # ['UnaryOp', 'sizeof', ['Typename', ['TypeDecl', ['IdentifierType', ['TT']]]]])
1940 # self.assertEqual(expand_init(items[2].init),
1941 # ['UnaryOp', 'sizeof', ['ID', 'TT']])
1942
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001943 def test_parameter_reuse_typedef_name(self):
1944 # identifiers can be reused as parameter names; parameter name scope
1945 # begins and ends with the function body; it's important that TT is
Eli Bendersky4d969b32013-07-13 06:07:07 -07001946 # used immediately before the LBRACE or after the RBRACE, to test
1947 # a corner case
Sye van der Veen9ec6c422013-07-11 09:10:38 -04001948 s1 = r'''
1949 typedef char TT;
1950 void foo(unsigned TT, TT bar) {
1951 TT = 10;
1952 }
1953 TT x = 5;
1954 '''
1955 s1_ast = self.parse(s1)
1956 self.assertEqual(expand_decl(s1_ast.ext[1].decl),
1957 ['Decl', 'foo',
1958 ['FuncDecl',
1959 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
1960 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
1961 ['TypeDecl', ['IdentifierType', ['void']]]]])
1962
1963 # the scope of a parameter name in a function declaration ends at the
1964 # end of the declaration...so it is effectively never used; it's
1965 # important that TT is used immediately after the declaration, to
1966 # test a corner case
1967 s2 = r'''
1968 typedef char TT;
1969 void foo(unsigned TT, TT bar);
1970 TT x = 5;
1971 '''
1972 s2_ast = self.parse(s2)
1973 self.assertEqual(expand_decl(s2_ast.ext[1]),
1974 ['Decl', 'foo',
1975 ['FuncDecl',
1976 [ ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
1977 ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
1978 ['TypeDecl', ['IdentifierType', ['void']]]]])
1979
1980 # ensure an error is raised if a type, redeclared as a parameter, is
1981 # used as a type
1982 s3 = r'''
1983 typedef char TT;
1984 void foo(unsigned TT, TT bar) {
1985 TT erroneous = 20;
1986 }
1987 '''
1988 self.assertRaises(ParseError, self.parse, s3)
1989
1990 def test_nested_function_decls(self):
1991 # parameter names of nested function declarations must not escape into
1992 # the top-level function _definition's_ scope; the following must
1993 # succeed because TT is still a typedef inside foo's body
1994 s1 = r'''
1995 typedef char TT;
1996 void foo(unsigned bar(int TT)) {
1997 TT x = 10;
1998 }
1999 '''
2000 self.assertTrue(isinstance(self.parse(s1), FileAST))
2001
2002 def test_samescope_reuse_name(self):
2003 # a typedef name cannot be reused as an object name in the same scope
2004 s1 = r'''
2005 typedef char TT;
2006 char TT = 5;
2007 '''
2008 self.assertRaises(ParseError, self.parse, s1)
2009
2010 # ...and vice-versa
2011 s2 = r'''
2012 char TT = 5;
2013 typedef char TT;
2014 '''
2015 self.assertRaises(ParseError, self.parse, s2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03002016
Julian Hammerdb9f2da2015-10-12 15:52:12 +02002017
Eli Bendersky3921e8e2010-05-21 09:05:39 +03002018if __name__ == '__main__':
2019 #~ suite = unittest.TestLoader().loadTestsFromNames(
2020 #~ ['test_c_parser.TestCParser_fundamentals.test_typedef'])
Eli Bendersky86f2eee2013-01-18 06:04:01 -08002021
Eli Bendersky3921e8e2010-05-21 09:05:39 +03002022 #~ unittest.TextTestRunner(verbosity=2).run(suite)
2023 unittest.main()