sunrpc: Suppress GCC -Os warning on user2netname
[glibc.git] / support / tst-glibcpp.py
bloba2db1916ccfce3c30675ea1a2c886c173156a54f
1 #! /usr/bin/python3
2 # Tests for scripts/glibcpp.py
3 # Copyright (C) 2022 Free Software Foundation, Inc.
4 # This file is part of the GNU C Library.
6 # The GNU C Library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation; either
9 # version 2.1 of the License, or (at your option) any later version.
11 # The GNU C Library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # Lesser General Public License for more details.
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with the GNU C Library; if not, see
18 # <https://www.gnu.org/licenses/>.
20 import inspect
21 import sys
23 import glibcpp
25 # Error counter.
26 errors = 0
28 class TokenizerErrors:
29 """Used as the error reporter during tokenization."""
31 def __init__(self):
32 self.errors = []
34 def error(self, token, message):
35 self.errors.append((token, message))
37 def check_macro_definitions(source, expected):
38 reporter = TokenizerErrors()
39 tokens = glibcpp.tokenize_c(source, reporter)
41 actual = []
42 for md in glibcpp.macro_definitions(tokens):
43 if md.function:
44 md_name = '{}({})'.format(md.name, ','.join(md.args_lowered))
45 else:
46 md_name = md.name
47 actual.append((md_name, md.body_lowered))
49 if actual != expected or reporter.errors:
50 global errors
51 errors += 1
52 # Obtain python source line information.
53 frame = inspect.stack(2)[1]
54 print('{}:{}: error: macro definition mismatch, actual definitions:'
55 .format(frame[1], frame[2]))
56 for md in actual:
57 print('note: {} {!r}'.format(md[0], md[1]))
59 if reporter.errors:
60 for err in reporter.errors:
61 print('note: tokenizer error: {}: {}'.format(
62 err[0].line, err[1]))
64 def check_macro_eval(source, expected, expected_errors=''):
65 reporter = TokenizerErrors()
66 tokens = list(glibcpp.tokenize_c(source, reporter))
68 if reporter.errors:
69 # Obtain python source line information.
70 frame = inspect.stack(2)[1]
71 for err in reporter.errors:
72 print('{}:{}: tokenizer error: {}: {}'.format(
73 frame[1], frame[2], err[0].line, err[1]))
74 return
76 class EvalReporter:
77 """Used as the error reporter during evaluation."""
79 def __init__(self):
80 self.lines = []
82 def error(self, line, message):
83 self.lines.append('{}: error: {}\n'.format(line, message))
85 def note(self, line, message):
86 self.lines.append('{}: note: {}\n'.format(line, message))
88 reporter = EvalReporter()
89 actual = glibcpp.macro_eval(glibcpp.macro_definitions(tokens), reporter)
90 actual_errors = ''.join(reporter.lines)
91 if actual != expected or actual_errors != expected_errors:
92 global errors
93 errors += 1
94 # Obtain python source line information.
95 frame = inspect.stack(2)[1]
96 print('{}:{}: error: macro evaluation mismatch, actual results:'
97 .format(frame[1], frame[2]))
98 for k, v in actual.items():
99 print(' {}: {!r}'.format(k, v))
100 for msg in reporter.lines:
101 sys.stdout.write(' | ' + msg)
103 # Individual test cases follow.
105 check_macro_definitions('', [])
106 check_macro_definitions('int main()\n{\n{\n', [])
107 check_macro_definitions("""
108 #define A 1
109 #define B 2 /* ignored */
110 #define C 3 // also ignored
111 #define D \
113 #define STRING "string"
114 #define FUNCLIKE(a, b) (a + b)
115 #define FUNCLIKE2(a, b) (a + \
117 """, [('A', ['1']),
118 ('B', ['2']),
119 ('C', ['3']),
120 ('D', ['4']),
121 ('STRING', ['"string"']),
122 ('FUNCLIKE(a,b)', list('(a+b)')),
123 ('FUNCLIKE2(a,b)', list('(a+b)')),
125 check_macro_definitions('#define MACRO', [('MACRO', [])])
126 check_macro_definitions('#define MACRO\n', [('MACRO', [])])
127 check_macro_definitions('#define MACRO()', [('MACRO()', [])])
128 check_macro_definitions('#define MACRO()\n', [('MACRO()', [])])
130 check_macro_eval('#define A 1', {'A': 1})
131 check_macro_eval('#define A (1)', {'A': 1})
132 check_macro_eval('#define A (1 + 1)', {'A': 2})
133 check_macro_eval('#define A (1U << 31)', {'A': 1 << 31})
134 check_macro_eval('''\
135 #define A (B + 1)
136 #define B 10
137 #define F(x) ignored
138 #define C "not ignored"
139 ''', {
140 'A': 11,
141 'B': 10,
142 'C': '"not ignored"',
145 # Checking for evaluation errors.
146 check_macro_eval('''\
147 #define A 1
148 #define A 2
149 ''', {
150 'A': 1,
151 }, '''\
152 2: error: macro A redefined
153 1: note: location of previous definition
154 ''')
156 check_macro_eval('''\
157 #define A A
158 #define B 1
159 ''', {
160 'A': None,
161 'B': 1,
162 }, '''\
163 1: error: macro definition A refers to itself
164 ''')
166 check_macro_eval('''\
167 #define A B
168 #define B A
169 ''', {
170 'A': None,
171 'B': None,
172 }, '''\
173 1: error: macro definition A refers to itself
174 2: note: evaluated from B
175 ''')
177 check_macro_eval('''\
178 #define A B
179 #define B C
180 #define C A
181 ''', {
182 'A': None,
183 'B': None,
184 'C': None,
185 }, '''\
186 1: error: macro definition A refers to itself
187 3: note: evaluated from C
188 2: note: evaluated from B
189 ''')
191 check_macro_eval('''\
192 #define A 1 +
193 ''', {
194 'A': None,
195 }, '''\
196 1: error: uninterpretable macro token sequence: 1 +
197 ''')
199 check_macro_eval('''\
200 #define A 3*5
201 ''', {
202 'A': None,
203 }, '''\
204 1: error: uninterpretable macro token sequence: 3 * 5
205 ''')
207 check_macro_eval('''\
208 #define A 3 + 5
209 ''', {
210 'A': 8,
211 }, '''\
212 1: error: missing parentheses around + expression
213 1: note: in definition of macro A
214 ''')
216 if errors:
217 sys.exit(1)