2 # Tests for scripts/glibcpp.py
3 # Copyright (C) 2022-2024 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/>.
28 class TokenizerErrors
:
29 """Used as the error reporter during tokenization."""
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
)
42 for md
in glibcpp
.macro_definitions(tokens
):
44 md_name
= '{}({})'.format(md
.name
, ','.join(md
.args_lowered
))
47 actual
.append((md_name
, md
.body_lowered
))
49 if actual
!= expected
or reporter
.errors
:
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]))
57 print('note: {} {!r}'.format(md
[0], md
[1]))
60 for err
in reporter
.errors
:
61 print('note: tokenizer error: {}: {}'.format(
64 def check_macro_eval(source
, expected
, expected_errors
=''):
65 reporter
= TokenizerErrors()
66 tokens
= list(glibcpp
.tokenize_c(source
, reporter
))
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]))
77 """Used as the error reporter during evaluation."""
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
:
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("""
109 #define B 2 /* ignored */
110 #define C 3 // also ignored
113 #define STRING "string"
114 #define FUNCLIKE(a, b) (a + b)
115 #define FUNCLIKE2(a, b) (a + \
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('#define A (1 | 2)', {'A': 1 |
2})
135 check_macro_eval('''\
139 #define C "not ignored"
143 'C': '"not ignored"',
146 # Checking for evaluation errors.
147 check_macro_eval('''\
153 2: error: macro A redefined
154 1: note: location of previous definition
157 check_macro_eval('''\
164 1: error: macro definition A refers to itself
167 check_macro_eval('''\
174 1: error: macro definition A refers to itself
175 2: note: evaluated from B
178 check_macro_eval('''\
187 1: error: macro definition A refers to itself
188 3: note: evaluated from C
189 2: note: evaluated from B
192 check_macro_eval('''\
197 1: error: uninterpretable macro token sequence: 1 +
200 check_macro_eval('''\
205 1: error: uninterpretable macro token sequence: 3 * 5
208 check_macro_eval('''\
213 1: error: missing parentheses around + expression
214 1: note: in definition of macro A