Files
bison/tests/diagnostics.at
Akim Demaille fec13ce2db diagnostics: sort symbols per location
Because the checking of the grammar is made by phases after the whole
grammar was read, we sometimes have diagnostics that look weird.  In
some case, within one type of checking, the entities are not checked
in the order in which they appear in the file.  For instance, checking
symbols is done on the list of symbols sorted by tag:

    foo.y:1.20-22: warning: symbol BAR is used, but is not defined as a token and has no rules [-Wother]
        1 | %destructor {} QUX BAR
          |                    ^~~
    foo.y:1.16-18: warning: symbol QUX is used, but is not defined as a token and has no rules [-Wother]
        1 | %destructor {} QUX BAR
          |                ^~~

Let's sort them by location instead:

    foo.y:1.16-18: warning: symbol 'QUX' is used, but is not defined as a token and has no rules [-Wother]
        1 | %destructor {} QUX BAR
          |                ^~~
    foo.y:1.20-22: warning: symbol 'BAR' is used, but is not defined as a token and has no rules [-Wother]
        1 | %destructor {} QUX BAR
          |                    ^~~

* src/location.h (location_cmp): Be robust to empty file names.
* src/symtab.c (symbol_cmp): Sort by location.
* tests/input.at: Adjust expectations.
2019-10-06 09:54:25 +02:00

479 lines
19 KiB
Plaintext

# Checking diagnotics. -*- Autotest -*-
# Copyright (C) 2019 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AT_BANNER([[Diagnostics.]])
# AT_TEST($1: TITLE, $2: GRAMMAR, $3: EXIT-STATUS, $4: OUTPUT-WITH-STYLE,
# $5: EXTRA_ENV
# -----------------------------------------------------------------------
# Run Bison on GRAMMAR with debugging style enabled, and expect
# OUTPUT-WITH-STYLE as diagnostics.
m4_pushdef([AT_TEST],
[
AT_SETUP([$1])
AT_KEYWORDS([diagnostics])
# We need UTF-8 support for correct screen-width computation of UTF-8
# characters. Skip the test if not available.
AT_SKIP_IF([! locale -a | grep '^en_US.UTF-8$'])
AT_BISON_OPTION_PUSHDEFS
AT_DATA_GRAMMAR([[input.y]], [$2])
# For some reason, literal ^M in the input are removed and don't end
# in `input.y`. So use the two-character ^M represent it, and let
# Perl insert real CR characters.
AT_CHECK([perl -pi -e 's{\^M}{\r}gx' input.y])
AT_DATA([experr], [$4])
AT_CHECK([LC_ALL=en_US.UTF-8 $5 bison -fcaret --color=debug -Wall input.y], [$3], [], [experr])
# When no style, same messages, but without style.
AT_CHECK([perl -pi -e 's{(</?(-|\w)+>)}{ $[]1 eq "<tag>" ? $[]1 : "" }ge' experr])
# Cannot use AT_BISON_CHECK easily as we need to change the
# environment.
# FIXME: Enhance AT_BISON_CHECK.
AT_CHECK([LC_ALL=en_US.UTF-8 $5 bison -fcaret -Wall input.y], [$3], [], [experr])
AT_BISON_OPTION_POPDEFS
AT_CLEANUP
])
## ---------- ##
## Warnings. ##
## ---------- ##
AT_TEST([[Warnings]],
[[%token FOO FOO FOO
%token FOO FOO FOO
%%
exp: %empty;
]],
[0],
[[input.y:9.12-14: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>]
9 | %token FOO <warning>FOO</warning> FOO
| <warning>^~~</warning>
input.y:9.8-10: previous declaration
9 | %token <note>FOO</note> FOO FOO
| <note>^~~</note>
input.y:9.16-18: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>]
9 | %token FOO FOO <warning>FOO</warning>
| <warning>^~~</warning>
input.y:9.8-10: previous declaration
9 | %token <note>FOO</note> FOO FOO
| <note>^~~</note>
input.y:10.8-10: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>]
10 | %token <warning>FOO</warning> FOO FOO
| <warning>^~~</warning>
input.y:9.8-10: previous declaration
9 | %token <note>FOO</note> FOO FOO
| <note>^~~</note>
input.y:10.13-15: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>]
10 | %token FOO <warning>FOO</warning> FOO
| <warning>^~~</warning>
input.y:9.8-10: previous declaration
9 | %token <note>FOO</note> FOO FOO
| <note>^~~</note>
input.y:10.18-20: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>]
10 | %token FOO FOO <warning>FOO</warning>
| <warning>^~~</warning>
input.y:9.8-10: previous declaration
9 | %token <note>FOO</note> FOO FOO
| <note>^~~</note>
]])
## ------------------------ ##
## Single point locations. ##
## ------------------------ ##
# Single point locations (equal boundaries) are troublesome: it's easy
# to mess up the opening/closing of style. They come from the parser,
# rules with empty rhs. Their position is therefore debatable
# (between the previous token and the next one).
AT_TEST([[Single point locations]],
[[%%
exp: a b c d e
a: {}
b:{
};
c:
d
:
e:
]],
[0],
[[input.y:11.4-5: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
11 | a: <warning>{}</warning>
| <warning>^~</warning>
input.y:12.3-13.1: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
12 | b:<warning>{</warning>
| <warning>^</warning>
input.y:14.3: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
14 | c:
| <warning>^</warning>
input.y:16.2: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
16 | :
| <warning>^</warning>
input.y:17.3: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
17 | e:
| <warning>^</warning>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]])
## -------------------------------------- ##
## Tabulations and multibyte characters. ##
## -------------------------------------- ##
# Make sure we treat tabulations as eight spaces, and that multibyte
# characters have correct width.
AT_TEST([[Tabulations and multibyte characters]],
[[%%
exp: a b c d e f g h
a: { }
b: { }
c: {------------}
d: {éééééééééééé}
e: {∇⃗×𝐸⃗ = -∂𝐵⃗/∂t}
f: { 42 }
g: { "฿¥$€₦" }
h: { 🐃 }
]],
[0],
[[input.y:11.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
11 | a: <warning>{ }</warning>
| <warning>^~~~~~~~~~~~~~</warning>
input.y:12.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
12 | b: <warning>{ }</warning>
| <warning>^~~~~~~~~~~~~~</warning>
input.y:13.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
13 | c: <warning>{------------}</warning>
| <warning>^~~~~~~~~~~~~~</warning>
input.y:14.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
14 | d: <warning>{éééééééééééé}</warning>
| <warning>^~~~~~~~~~~~~~</warning>
input.y:15.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
15 | e: <warning>{∇⃗×𝐸⃗ = -∂𝐵⃗/∂t}</warning>
| <warning>^~~~~~~~~~~~~~</warning>
input.y:16.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
16 | f: <warning>{ 42 }</warning>
| <warning>^~~~~~~~~~~~~~</warning>
input.y:17.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
17 | g: <warning>{ "฿¥$€₦" }</warning>
| <warning>^~~~~~~~~~~~~~</warning>
input.y:18.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
18 | h: <warning>{ 🐃 }</warning>
| <warning>^~~~~~~~~~~~~~</warning>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]])
## --------------- ##
## Special files. ##
## --------------- ##
# Don't try to quote special files.
# http://lists.gnu.org/archive/html/bug-bison/2019-04/msg00000.html
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90034
AT_TEST([[Special files]],
[[%%
exp: a b
a: {}
#line 1 "/dev/stdout"
b: {}
]],
[0],
[[input.y:11.4-5: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
11 | a: <warning>{}</warning>
| <warning>^~</warning>
/dev/stdout:1.4-5: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
/dev/stdout: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]])
## ------------------- ##
## Locations from M4. ##
## ------------------- ##
# Locations coming from m4 need the byte-column for diagnostics.
AT_TEST([[Locations from M4]],
[[%define api.prefix {foo}
%define api.prefix {bar}
%%
exp:;
]],
[1],
[[input.y:10.1-24: <error>error:</error> %define variable 'api.prefix' redefined
10 | <error>%define api.prefix {bar}</error>
| <error>^~~~~~~~~~~~~~~~~~~~~~~~</error>
input.y:9.1-24: previous definition
9 | <note>%define api.prefix {foo}</note>
| <note>^~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]])
## ---------------------------------------------- ##
## Tabulations and multibyte characters from M4. ##
## ---------------------------------------------- ##
# Locations coming from m4 need the byte-column for diagnostics.
AT_TEST([[Tabulations and multibyte characters from M4]],
[[%define api.prefix {sun}
%define api.prefix {🌞}
%%
exp:;
]],
[1],
[[input.y:10.1-35: <error>error:</error> %define variable 'api.prefix' redefined
10 | <error>%define api.prefix {🌞}</error>
| <error>^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</error>
input.y:9.1-37: previous definition
9 | <note>%define api.prefix {sun}</note>
| <note>^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]])
## ----------------- ##
## Carriage return. ##
## ----------------- ##
# Carriage-return used to count as a newline in the scanner, and not
# in diagnostics. Resulting in all sort of nice bugs.
AT_TEST([[Carriage return]],
[[^M^M^M^M^M^M^M^M^M^M^M^M^M^M^M^M^M^M^M^M^M^M^M^M^M^M^M^M
%token "
%%
]],
[1],
[[input.y:10.8-11.0: <error>error:</error> missing '"' at end of line
10 | %token <error>"</error>
| <error>^</error>
input.y:10.8-11.0: <error>error:</error> syntax error, unexpected string, expecting character literal or identifier or <tag>
10 | %token <error>"</error>
| <error>^</error>
]])
## ------- ##
## CR NL. ##
## ------- ##
# Check Windows EOLs.
AT_TEST([[CR NL]],
[[^M
%token ^M FOO^M
%token ^M FOO^M
%%^M
exp:^M
]],
[0],
[[input.y:11.9-11: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>]
11 | %token
<warning>FOO</warning>
| <warning>^~~</warning>
input.y:10.9-11: previous declaration
10 | %token
<note>FOO</note>
| <note>^~~</note>
input.y:13.5: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
13 | exp:
| <warning>^</warning>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]])
## -------------- ##
## Screen width. ##
## -------------- ##
AT_TEST([[Screen width: 200 columns]],
[[%token ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ
%error-verbose
%%
exp: ABCDEFGHIJKLMNOPQRSTUVWXYZ
]],
[0],
[[input.y:9.36-61: <warning>warning:</warning> symbol ABCDEFGHIJKLMNOPQRSTUVWXYZ redeclared [<warning>-Wother</warning>]
9 | %token ABCDEFGHIJKLMNOPQRSTUVWXYZ <warning>ABCDEFGHIJKLMNOPQRSTUVWXYZ</warning> ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ
| <warning>^~~~~~~~~~~~~~~~~~~~~~~~~~</warning>
input.y:9.8-33: previous declaration
9 | %token <note>ABCDEFGHIJKLMNOPQRSTUVWXYZ</note> ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ
| <note>^~~~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y:9.64-89: <warning>warning:</warning> symbol ABCDEFGHIJKLMNOPQRSTUVWXYZ redeclared [<warning>-Wother</warning>]
9 | %token ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ <warning>ABCDEFGHIJKLMNOPQRSTUVWXYZ</warning> ABCDEFGHIJKLMNOPQRSTUVWXYZ
| <warning>^~~~~~~~~~~~~~~~~~~~~~~~~~</warning>
input.y:9.8-33: previous declaration
9 | %token <note>ABCDEFGHIJKLMNOPQRSTUVWXYZ</note> ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ
| <note>^~~~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y:9.92-117: <warning>warning:</warning> symbol ABCDEFGHIJKLMNOPQRSTUVWXYZ redeclared [<warning>-Wother</warning>]
9 | %token ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ <warning>ABCDEFGHIJKLMNOPQRSTUVWXYZ</warning>
| <warning>^~~~~~~~~~~~~~~~~~~~~~~~~~</warning>
input.y:9.8-33: previous declaration
9 | %token <note>ABCDEFGHIJKLMNOPQRSTUVWXYZ</note> ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ
| <note>^~~~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y:10.56-69: <warning>warning:</warning> deprecated directive: '%error-verbose', use '%define parse.error verbose' [<warning>-Wdeprecated</warning>]
10 | <warning>%error-verbose</warning>
| <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%define parse.error verbose</fixit-insert>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]],
[[COLUMNS=200]])
AT_TEST([[Screen width: 80 columns]],
[[%token ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ
%error-verbose
%%
exp: ABCDEFGHIJKLMNOPQRSTUVWXYZ
]],
[0],
[[input.y:9.36-61: <warning>warning:</warning> symbol ABCDEFGHIJKLMNOPQRSTUVWXYZ redeclared [<warning>-Wother</warning>]
9 | %token ABCDEFGHIJKLMNOPQRSTUVWXYZ <warning>ABCDEFGHIJKLMNOPQRSTUVWXYZ</warning> ABCDEF...
| <warning>^~~~~~~~~~~~~~~~~~~~~~~~~~</warning>
input.y:9.8-33: previous declaration
9 | %token <note>ABCDEFGHIJKLMNOPQRSTUVWXYZ</note> ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEF...
| <note>^~~~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y:9.64-89: <warning>warning:</warning> symbol ABCDEFGHIJKLMNOPQRSTUVWXYZ redeclared [<warning>-Wother</warning>]
9 | %token ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ <warning>ABCDEF</warning>...
| <warning>^~~~~~</warning>
input.y:9.8-33: previous declaration
9 | %token <note>ABCDEFGHIJKLMNOPQRSTUVWXYZ</note> ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEF...
| <note>^~~~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y:9.92-117: <warning>warning:</warning> symbol ABCDEFGHIJKLMNOPQRSTUVWXYZ redeclared [<warning>-Wother</warning>]
9 | ...TUVWXYZ <warning>ABCDEFGHIJKLMNOPQRSTUVWXYZ</warning>
| <warning>^~~~~~~~~~~~~~~~~~~~~~~~~~</warning>
input.y:9.8-33: previous declaration
9 | %token <note>ABCDEFGHIJKLMNOPQRSTUVWXYZ</note> ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEF...
| <note>^~~~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y:10.56-69: <warning>warning:</warning> deprecated directive: '%error-verbose', use '%define parse.error verbose' [<warning>-Wdeprecated</warning>]
10 | <warning>%error-verbose</warning>
| <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%define parse.error verbose</fixit-insert>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]],
[[COLUMNS=80]])
AT_TEST([[Screen width: 60 columns]],
[[%token ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ
%error-verbose
%%
exp: ABCDEFGHIJKLMNOPQRSTUVWXYZ
]],
[0],
[[input.y:9.36-61: <warning>warning:</warning> symbol ABCDEFGHIJKLMNOPQRSTUVWXYZ redeclared [<warning>-Wother</warning>]
9 | %token ABCDEFGHIJKLMNOPQRSTUVWXYZ <warning>ABCDEFGHIJKLMN</warning>...
| <warning>^~~~~~~~~~~~~~</warning>
input.y:9.8-33: previous declaration
9 | %token <note>ABCDEFGHIJKLMNOPQRSTUVWXYZ</note> ABCDEFGHIJKLMN...
| <note>^~~~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y:9.64-89: <warning>warning:</warning> symbol ABCDEFGHIJKLMNOPQRSTUVWXYZ redeclared [<warning>-Wother</warning>]
9 | ...TUVWXYZ <warning>ABCDEFGHIJKLMNOPQRSTUVWXYZ</warning> ABCDEFGHI...
| <warning>^~~~~~~~~~~~~~~~~~~~~~~~~~</warning>
input.y:9.8-33: previous declaration
9 | %token <note>ABCDEFGHIJKLMNOPQRSTUVWXYZ</note> ABCDEFGHIJKLMN...
| <note>^~~~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y:9.92-117: <warning>warning:</warning> symbol ABCDEFGHIJKLMNOPQRSTUVWXYZ redeclared [<warning>-Wother</warning>]
9 | ...TUVWXYZ <warning>ABCDEFGHIJKLMNOPQRSTUVWXYZ</warning>
| <warning>^~~~~~~~~~~~~~~~~~~~~~~~~~</warning>
input.y:9.8-33: previous declaration
9 | %token <note>ABCDEFGHIJKLMNOPQRSTUVWXYZ</note> ABCDEFGHIJKLMN...
| <note>^~~~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y:10.56-69: <warning>warning:</warning> deprecated directive: '%error-verbose', use '%define parse.error verbose' [<warning>-Wdeprecated</warning>]
10 | ... <warning>%error-verbose</warning>
| <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%define parse.error verbose</fixit-insert>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]],
[[COLUMNS=60]])
## ------------- ##
## Suggestions. ##
## ------------- ##
# Don't suggest to fix QUX with QUUX and QUUX with QUX...
AT_TEST([[Suggestions]],
[[%%
res: QUX baz
bar: QUUX
]],
[1],
[[input.y:10.6-8: <error>error:</error> symbol 'QUX' is used, but is not defined as a token and has no rules
10 | res: <error>QUX</error> baz
| <error>^~~</error>
input.y:10.10-12: <error>error:</error> symbol 'baz' is used, but is not defined as a token and has no rules; did you mean 'bar'?
10 | res: QUX <error>baz</error>
| <error>^~~</error>
| <fixit-insert>bar</fixit-insert>
input.y:11.6-9: <error>error:</error> symbol 'QUUX' is used, but is not defined as a token and has no rules
11 | bar: <error>QUUX</error>
| <error>^~~~</error>
]])
m4_popdef([AT_TEST])
## -------------------------------------- ##
## Indentation with message suppression. ##
## -------------------------------------- ##
AT_SETUP([[Indentation with message suppression]])
# https://lists.gnu.org/archive/html/bug-bison/2019-08/msg00002.html
AT_DATA([[input.y]],
[[%define api.pure
%pure-parser
%error-verbose
%%
exp : '0'
]])
AT_BISON_CHECK([[-fcaret -Wno-other input.y]], [0], [],
[[input.y:2.1-12: warning: deprecated directive: '%pure-parser', use '%define api.pure' [-Wdeprecated]
2 | %pure-parser
| ^~~~~~~~~~~~
| %define api.pure
input.y:3.1-14: warning: deprecated directive: '%error-verbose', use '%define parse.error verbose' [-Wdeprecated]
3 | %error-verbose
| ^~~~~~~~~~~~~~
| %define parse.error verbose
]])
AT_CLEANUP