X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/f91b1629440cb52b851004570b7f280e79167383..abd189e8dc6ca848f038da12e4110d6192374b82:/tests/regression.at diff --git a/tests/regression.at b/tests/regression.at index 80a0ba5c..c07b7442 100644 --- a/tests/regression.at +++ b/tests/regression.at @@ -1,22 +1,19 @@ # Bison Regressions. -*- Autotest -*- -# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Free Software -# Foundation, Inc. +# Copyright (C) 2001-2011 Free Software Foundation, Inc. -# This program is free software; you can redistribute it and/or modify +# 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 2, or (at your option) -# any later version. - +# 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, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. +# along with this program. If not, see . AT_BANNER([[Regression tests.]]) @@ -41,7 +38,7 @@ int yylex (void); program: 'x'; ]]) -AT_CHECK([bison -o input.c input.y]) +AT_BISON_CHECK([-o input.c input.y]) AT_COMPILE([input.o], [-c input.c]) AT_COMPILE([input.o], [-DYYDEBUG -c input.c]) @@ -69,7 +66,7 @@ typedef union { char const *val; } YYSTYPE; program: { $$ = ""; }; ]]) -AT_CHECK([bison -o input.c input.y]) +AT_BISON_CHECK([-o input.c input.y]) AT_COMPILE([input.o], [-c input.c]) AT_CLEANUP @@ -107,7 +104,7 @@ exp: MY_TOKEN; %% ]]) -AT_CHECK([bison -y -o input.c input.y]) +AT_BISON_CHECK([-y -o input.c input.y]) AT_COMPILE([input.o], [-c input.c]) AT_CLEANUP @@ -150,7 +147,7 @@ exp: MY_TOKEN; %% ]]) -AT_CHECK([bison -o input.c input.y]) +AT_BISON_CHECK([-o input.c input.y]) AT_COMPILE([input.o], [-c input.c]) AT_CLEANUP @@ -172,7 +169,7 @@ exp: { tests = {{{{{{{{{{}}}}}}}}}}; }; %% ]]) -AT_CHECK([bison -v -o input.c input.y]) +AT_BISON_CHECK([-v -o input.c input.y]) AT_CHECK([grep 'tests = {{{{{{{{{{}}}}}}}}}};' input.c], 0, [ignore]) @@ -199,7 +196,7 @@ exp: '(' exp ')' | NUM ; %% ]]) -AT_CHECK([bison -v -o input.c input.y], 0, [], +AT_BISON_CHECK([-v -o input.c input.y], 0, [], [[input.y:6.8-14: warning: symbol `"<="' used more than once as a literal string ]]) @@ -244,7 +241,7 @@ expr: }; ]]) -AT_CHECK([bison -o input.c -v input.y]) +AT_BISON_CHECK([-o input.c -v input.y]) # Check the contents of the report. AT_CHECK([cat input.output], [], @@ -366,7 +363,7 @@ exp: ; %% ]]) -AT_CHECK([bison -v -o input.c input.y]) +AT_BISON_CHECK([-v -o input.c input.y]) AT_CLEANUP @@ -389,7 +386,7 @@ default: 'a' } %{ ]]) -AT_CHECK([bison input.y], [1], [], +AT_BISON_CHECK([input.y], [1], [], [[input.y:2.1: invalid character: `?' input.y:3.14: invalid character: `}' input.y:4.1: invalid character: `%' @@ -416,7 +413,7 @@ AT_DATA([input.y], %union ]]) -AT_CHECK([bison input.y], [1], [], +AT_BISON_CHECK([input.y], [1], [], [[input.y:3.1-15: syntax error, unexpected %initial-action, expecting {...} ]]) @@ -446,6 +443,7 @@ int yylex (void); %token C_TOKEN 'c' %token 'd' D_TOKEN %token SPECIAL "\\\'\?\"\a\b\f\n\r\t\v\001\201\x001\x000081??!" +%token SPECIAL "\\\'\?\"\a\b\f\n\r\t\v\001\201\x001\x000081??!" %% exp: "a" "\\\'\?\"\a\b\f\n\r\t\v\001\201\x001\x000081??!"; %% @@ -471,10 +469,22 @@ main (void) } ]]) -AT_CHECK([bison -o input.c input.y]) +# Checking the warning message guarantees that the trigraph "??!" isn't +# unnecessarily escaped here even though it would need to be if encoded in a +# C-string literal. Also notice that unnecessary escaping, such as "\?", from +# the user specification is eliminated. +AT_BISON_CHECK([-o input.c input.y], [[0]], [[]], +[[input.y:22.8-14: warning: symbol SPECIAL redeclared +input.y:22.8-63: warning: symbol `"\\'?\"\a\b\f\n\r\t\v\001\201\001\201??!"' used more than once as a literal string +]]) AT_COMPILE([input]) + +# Checking the error message here guarantees that yytname, which does contain +# C-string literals, does have the trigraph escaped correctly. Thus, the +# symbol name reported by the parser is exactly the same as that reported by +# Bison itself. AT_DATA([experr], -[[syntax error, unexpected "\\'?\"\a\b\f\n\r\t\v\001\201\001\201?\?!", expecting a +[[syntax error, unexpected "\\'?\"\a\b\f\n\r\t\v\001\201\001\201??!", expecting a ]]) AT_PARSER_CHECK([./input], 1, [], [experr]) AT_CLEANUP @@ -502,7 +512,7 @@ exp: ]]) # Pacify font-lock-mode: " -AT_CHECK([bison -o input.c input.y]) +AT_BISON_CHECK([-o input.c input.y]) AT_COMPILE([input.o], [-c input.c]) AT_CLEANUP @@ -542,7 +552,7 @@ CONST_DEC: %% ]]) -AT_CHECK([bison -v input.y]) +AT_BISON_CHECK([-v input.y]) AT_CHECK([cat input.output], 0, [[Grammar @@ -707,10 +717,9 @@ else: "else" statement; %% ]]) -AT_CHECK([bison -v -o input.c input.y]) +AT_BISON_CHECK([-v -o input.c input.y]) -# Check only the tables. We don't use --no-parser, because it is -# still to be implemented in the experimental branch of Bison. +# Check only the tables. [sed -n 's/ *$//;/^static const.*\[\] =/,/^}/p' input.c >tables.c] AT_CHECK([[cat tables.c]], 0, @@ -928,12 +937,8 @@ m4_define([AT_CHECK_DANCER], [AT_SETUP([Dancer $1]) AT_BISON_OPTION_PUSHDEFS([$1]) _AT_DATA_DANCER_Y([$1]) -AT_CHECK([bison -o dancer.c dancer.y]) -AT_LALR1_CC_IF( - [AT_CHECK([bison -o dancer.cc dancer.y]) - AT_COMPILE_CXX([dancer])], - [AT_CHECK([bison -o dancer.c dancer.y]) - AT_COMPILE([dancer])]) +AT_BISON_CHECK([-o dancer.c dancer.y]) +AT_FULL_COMPILE([dancer]) AT_PARSER_CHECK([./dancer], 1, [], [syntax error, unexpected ':' ]) @@ -1028,12 +1033,8 @@ m4_define([AT_CHECK_EXPECT2], [AT_SETUP([Expecting two tokens $1]) AT_BISON_OPTION_PUSHDEFS([$1]) _AT_DATA_EXPECT2_Y([$1]) -AT_CHECK([bison -o expect2.c expect2.y]) -AT_LALR1_CC_IF( - [AT_CHECK([bison -o expect2.cc expect2.y]) - AT_COMPILE_CXX([expect2])], - [AT_CHECK([bison -o expect2.c expect2.y]) - AT_COMPILE([expect2])]) +AT_BISON_CHECK([-o expect2.c expect2.y]) +AT_FULL_COMPILE([expect2]) AT_PARSER_CHECK([./expect2], 1, [], [syntax error, unexpected '+', expecting A or B ]) @@ -1099,7 +1100,7 @@ main (void) } ]]) -AT_CHECK([bison -t -o input.c input.y]) +AT_BISON_CHECK([-t -o input.c input.y]) AT_COMPILE([input]) AT_PARSER_CHECK([./input], 0, [[Bison would once convert this action to a midrule because of the subsequent braced code. @@ -1140,6 +1141,533 @@ start: 'a' "A" 'b'; %token 'a' "A"; ]]) -AT_CHECK([bison -t -o input.c input.y]) +AT_BISON_CHECK([-t -o input.c input.y]) + +AT_CLEANUP + + + +## -------------------------------- ## +## Extra lookahead sets in report. ## +## -------------------------------- ## + +AT_SETUP([[Extra lookahead sets in report]]) + +# Bison prints each reduction's lookahead set only next to the associated +# state's one item that (1) is associated with the same rule as the reduction +# and (2) has its dot at the end of its RHS. Previously, Bison also +# erroneously printed the lookahead set next to all of the state's other items +# associated with the same rule. This bug affected only the `.output' file and +# not the generated parser source code. + +AT_DATA([[input.y]], +[[%% +start: a | 'a' a 'a' ; +a: 'a' ; +]]) + +AT_BISON_CHECK([[--report=all input.y]]) +AT_CHECK([[sed -n '/^state 1$/,/^state 2$/p' input.output]], [[0]], +[[state 1 + + 2 start: 'a' . a 'a' + 3 a: . 'a' + 3 | 'a' . [$end] + + 'a' shift, and go to state 4 + + $default reduce using rule 3 (a) + + a go to state 5 + + +state 2 +]]) + +AT_CLEANUP + + + +## ---------------------------------------- ## +## Token number in precedence declaration. ## +## ---------------------------------------- ## + +AT_SETUP([[Token number in precedence declaration]]) + +# POSIX says token numbers can be declared in %left, %right, and %nonassoc, but +# we lost this in Bison 1.50. + +AT_DATA_GRAMMAR([input.y], +[[%{ + #include + void yyerror (char const *); + int yylex (void); +%} + +%error-verbose +%right END 0 +%left TK1 1 TK2 2 "tok alias" 3 + +%% + +start: + TK1 sr_conflict "tok alias" + | start %prec END + ; +sr_conflict: + TK2 + | TK2 "tok alias" + ; + +%% + +void +yyerror (char const *msg) +{ + fprintf (stderr, "%s\n", msg); +} + +int +yylex (void) +{ + static int const input[] = { 1, 2, 3, 0 }; + static int const *inputp = input; + return *inputp++; +} + +int +main (void) +{ + return yyparse (); +} +]]) + +AT_BISON_CHECK([[-o input.c input.y]], [[0]],, +[[input.y:23.5-19: warning: rule useless in parser due to conflicts: start: start +input.y:27.5-19: warning: rule useless in parser due to conflicts: sr_conflict: TK2 "tok alias" +]]) +AT_COMPILE([[input]]) +AT_PARSER_CHECK([[./input]]) + +AT_CLEANUP + + + +## --------------------------- ## +## parse-gram.y: LALR = IELR. ## +## --------------------------- ## + +# If parse-gram.y's LALR and IELR parser tables ever begin to differ, we +# need to fix parse-gram.y or start using IELR. + +AT_SETUP([[parse-gram.y: LALR = IELR]]) + +# Avoid differences in synclines by telling bison that the output files +# have the same name. +[cp $abs_top_srcdir/src/parse-gram.y input.y] +AT_BISON_CHECK([[-o input.c -Dlr.type=lalr input.y]]) +[mv input.c lalr.c] +AT_BISON_CHECK([[-o input.c -Dlr.type=ielr input.y]]) +[mv input.c ielr.c] +AT_CHECK([[diff -u lalr.c ielr.c]]) + +AT_CLEANUP + + + +## --------------------------------------- ## +## %error-verbose and YYSTACK_USE_ALLOCA. ## +## --------------------------------------- ## + +AT_SETUP([[%error-verbose and YYSTACK_USE_ALLOCA]]) + +AT_DATA_GRAMMAR([input.y], +[[%code { + #include + void yyerror (char const *); + int yylex (void); + #define YYSTACK_USE_ALLOCA 1 +} + +%error-verbose + +%% + +start: check syntax_error syntax_error ; + +check: +{ + if (128 < sizeof yymsgbuf) + { + fprintf (stderr, + "The initial size of yymsgbuf in yyparse has increased\n" + "since this test group was last updated. As a result,\n" + "this test group may no longer manage to induce a\n" + "reallocation of the syntax error message buffer.\n" + "This test group must be adjusted to produce a longer\n" + "error message.\n"); + YYABORT; + } +} +; + +// Induce a syntax error message whose total length is more than +// sizeof yymsgbuf in yyparse. Each token here is 64 bytes. +syntax_error: + "123456789112345678921234567893123456789412345678951234567896123A" +| "123456789112345678921234567893123456789412345678951234567896123B" +| error 'a' 'b' 'c' +; + +%% + +void +yyerror (char const *msg) +{ + fprintf (stderr, "%s\n", msg); +} + +int +yylex (void) +{ + /* Induce two syntax error messages (which requires full error + recovery by shifting 3 tokens) in order to detect any loss of the + reallocated buffer. */ + static char const *input = "abc"; + return *input++; +} + +int +main (void) +{ + return yyparse (); +} +]]) + +AT_BISON_CHECK([[-o input.c input.y]]) +AT_COMPILE([[input]]) +AT_PARSER_CHECK([[./input]], [[1]], [], +[[syntax error, unexpected 'a', expecting 123456789112345678921234567893123456789412345678951234567896123A or 123456789112345678921234567893123456789412345678951234567896123B +syntax error, unexpected $end, expecting 123456789112345678921234567893123456789412345678951234567896123A or 123456789112345678921234567893123456789412345678951234567896123B +]]) + +AT_CLEANUP + + + +## ------------------------- ## +## %error-verbose overflow. ## +## ------------------------- ## + +# Imagine the case where YYSTACK_ALLOC_MAXIMUM = YYSIZE_MAXIMUM and an +# invocation of yysyntax_error has caused yymsg_alloc to grow to exactly +# YYSTACK_ALLOC_MAXIMUM (perhaps because the normal doubling of size had +# to be clipped to YYSTACK_ALLOC_MAXIMUM). In an old version of yacc.c, +# a subsequent invocation of yysyntax_error that overflows during its +# size calculation would return YYSIZE_MAXIMUM to yyparse. Then, +# yyparse would invoke yyerror using the old contents of yymsg. + +AT_SETUP([[%error-verbose overflow]]) + +AT_DATA_GRAMMAR([input.y], +[[%code { + #include + void yyerror (char const *); + int yylex (void); + + /* This prevents this test case from having to induce error messages + large enough to overflow size_t. */ + #define YYSIZE_T unsigned char + + /* Bring in malloc and set EXIT_SUCCESS so yacc.c doesn't try to + provide a malloc prototype using our YYSIZE_T. */ + #include + #ifndef EXIT_SUCCESS + # define EXIT_SUCCESS 0 + #endif + + /* Max depth is usually much smaller than YYSTACK_ALLOC_MAXIMUM, and + we don't want gcc to warn everywhere this constant would be too big + to make sense for our YYSIZE_T. */ + #define YYMAXDEPTH 100 +} + +%error-verbose + +%% + +start: syntax_error1 check syntax_error2 ; + +// Induce a syntax error message whose total length causes yymsg in +// yyparse to be reallocated to size YYSTACK_ALLOC_MAXIMUM, which +// should be 255. Each token here is 64 bytes. +syntax_error1: + "123456789112345678921234567893123456789412345678951234567896123A" +| "123456789112345678921234567893123456789412345678951234567896123B" +| "123456789112345678921234567893123456789412345678951234567896123C" +| error 'a' 'b' 'c' +; + +check: +{ + if (yymsg_alloc != YYSTACK_ALLOC_MAXIMUM + || YYSTACK_ALLOC_MAXIMUM != YYSIZE_MAXIMUM + || YYSIZE_MAXIMUM != 255) + { + fprintf (stderr, + "The assumptions of this test group are no longer\n" + "valid, so it may no longer catch the error it was\n" + "designed to catch. Specifically, the following\n" + "values should all be 255:\n\n"); + fprintf (stderr, " yymsg_alloc = %d\n", yymsg_alloc); + fprintf (stderr, " YYSTACK_ALLOC_MAXIMUM = %d\n", + YYSTACK_ALLOC_MAXIMUM); + fprintf (stderr, " YYSIZE_MAXIMUM = %d\n", YYSIZE_MAXIMUM); + YYABORT; + } +} +; + +// Now overflow. +syntax_error2: + "123456789112345678921234567893123456789412345678951234567896123A" +| "123456789112345678921234567893123456789412345678951234567896123B" +| "123456789112345678921234567893123456789412345678951234567896123C" +| "123456789112345678921234567893123456789412345678951234567896123D" +| "123456789112345678921234567893123456789412345678951234567896123E" +; + +%% + +void +yyerror (char const *msg) +{ + fprintf (stderr, "%s\n", msg); +} + +int +yylex (void) +{ + /* Induce two syntax error messages (which requires full error + recovery by shifting 3 tokens). */ + static char const *input = "abc"; + return *input++; +} + +int +main (void) +{ + /* Push parsers throw away the message buffer between tokens, so skip + this test under maintainer-push-check. */ + if (YYPUSH) + return 77; + return yyparse (); +} +]]) + +AT_BISON_CHECK([[-o input.c input.y]]) + +# gcc warns about tautologies and fallacies involving comparisons for +# unsigned char. However, it doesn't produce these same warnings for +# size_t and many other types when the warnings would seem to make just +# as much sense. We ignore the warnings. +[CFLAGS="$NO_WERROR_CFLAGS"] +AT_COMPILE([[input]]) + +AT_PARSER_CHECK([[./input]], [[2]], [], +[[syntax error, unexpected 'a', expecting 123456789112345678921234567893123456789412345678951234567896123A or 123456789112345678921234567893123456789412345678951234567896123B or 123456789112345678921234567893123456789412345678951234567896123C +syntax error +memory exhausted +]]) + +AT_CLEANUP + + + +## ------------------------ ## +## LAC: Exploratory stack. ## +## ------------------------ ## + +AT_SETUP([[LAC: Exploratory stack]]) + +m4_pushdef([AT_LAC_CHECK], [ + +AT_BISON_OPTION_PUSHDEFS([$1]) + +AT_DATA_GRAMMAR([input.y], +[[%code { + #include + void yyerror (char const *); + int yylex (]AT_PURE_IF([[YYSTYPE *]], [[void]])[); +} + +]$1[ +%error-verbose +%token 'c' + +%% + +// default reductions in inconsistent states +// v v v v v v v v v v v v v v +S: A B A A B A A A A B A A A A A A A B C C A A A A A A A A A A A A B ; +// ^ ^ ^ +// LAC reallocs + +A: 'a' | /*empty*/ { printf ("inconsistent default reduction\n"); } ; +B: 'b' ; +C: /*empty*/ { printf ("consistent default reduction\n"); } ; + +%% + +void +yyerror (char const *msg) +{ + fprintf (stderr, "%s\n", msg); +} + +int +yylex (]AT_PURE_IF([[YYSTYPE *v]], [[void]])[) +{ + static char const *input = "bbbbc";]AT_PURE_IF([[ + *v = 0;]])[ + return *input++; +} + +int +main (void) +{ + yydebug = 1; + return yyparse (); +} +]]) + +AT_BISON_CHECK([[-Dparse.lac=full -Dparse.lac.es-capacity-initial=1 \ + -Dparse.lac.memory-trace=full \ + -t -o input.c input.y]], [[0]], [], +[[input.y: conflicts: 21 shift/reduce +]]) +AT_COMPILE([[input]]) +AT_PARSER_CHECK([[./input > stdout.txt 2> stderr.txt]], [[1]]) + +# Make sure syntax error doesn't forget that 'a' is expected. It would +# be forgotten without lookahead correction. +AT_CHECK([[grep 'syntax error,' stderr.txt]], [[0]], +[[syntax error, unexpected 'c', expecting 'a' or 'b' +]]) + +# Check number of default reductions in inconsistent states to be sure +# syntax error is detected before unnecessary reductions are performed. +AT_CHECK([[perl -0777 -ne 'print s/inconsistent default reduction//g;' \ + < stdout.txt || exit 77]], [[0]], [[14]]) + +# Check number of default reductions in consistent states to be sure +# it is performed before the syntax error is detected. +AT_CHECK([[perl -0777 -ne 'print s/\bconsistent default reduction//g;' \ + < stdout.txt || exit 77]], [[0]], [[2]]) + +# Check number of reallocs to be sure reallocated memory isn't somehow +# lost between LAC invocations. +AT_CHECK([[perl -0777 -ne 'print s/\(realloc//g;' < stderr.txt \ + || exit 77]], [[0]], [[3]]) + +AT_BISON_OPTION_POPDEFS +]) + +AT_LAC_CHECK([[%define api.push-pull pull]]) +AT_LAC_CHECK([[%define api.push-pull pull %define api.pure]]) +AT_LAC_CHECK([[%define api.push-pull both]]) +AT_LAC_CHECK([[%define api.push-pull both %define api.pure]]) + +m4_popdef([AT_LAC_CHECK]) + +AT_CLEANUP + + + +## ------------------------ ## +## LAC: Memory exhaustion. ## +## ------------------------ ## + +AT_SETUP([[LAC: Memory exhaustion]]) + +m4_pushdef([AT_LAC_CHECK], [ + +AT_DATA_GRAMMAR([input.y], +[[%code { + #include + void yyerror (char const *); + int yylex (void); + #define YYMAXDEPTH 8 +} + +%error-verbose + +%% + +S: A A A A A A A A A ; +A: /*empty*/ | 'a' ; + +%% + +void +yyerror (char const *msg) +{ + fprintf (stderr, "%s\n", msg); +} + +int +yylex (void) +{ + static char const *input = "]$1["; + return *input++; +} + +int +main (void) +{ + yydebug = 1; + return yyparse (); +} +]]) + +AT_BISON_CHECK([[-Dparse.lac=full -Dparse.lac.es-capacity-initial=1 \ + -t -o input.c input.y]], [[0]], [], +[[input.y: conflicts: 8 shift/reduce +]]) +AT_COMPILE([[input]]) + +]) + +# Check for memory exhaustion during parsing. +AT_LAC_CHECK([[]]) +AT_PARSER_CHECK([[./input]], [[2]], [[]], +[[Starting parse +Entering state 0 +Reading a token: Now at end of input. +LAC: initial context established for $end +LAC: checking lookahead $end: R2 G3 R2 G5 R2 G6 R2 G7 R2 G8 R2 G9 R2 G10 R2 G11 R2 (max size exceeded) +memory exhausted +Cleanup: discarding lookahead token $end () +Stack now 0 +]]) + +# Induce an immediate syntax error with an undefined token, and check +# for memory exhaustion while building syntax error message. +AT_LAC_CHECK([[z]], [[0]]) +AT_PARSER_CHECK([[./input]], [[2]], [[]], +[[Starting parse +Entering state 0 +Reading a token: Next token is token $undefined () +LAC: initial context established for $undefined +LAC: checking lookahead $undefined: Always Err +Constructing syntax error message +LAC: checking lookahead $end: R2 G3 R2 G5 R2 G6 R2 G7 R2 G8 R2 G9 R2 G10 R2 G11 R2 (max size exceeded) +syntax error +memory exhausted +Cleanup: discarding lookahead token $undefined () +Stack now 0 +]]) + +m4_popdef([AT_LAC_CHECK]) AT_CLEANUP