I'd like to push this patch to master, branch-2.5, and branch-2.4.2 so that push parser users are informed that they can't set YYSTACK_USE_ALLOCA=1. The only way I can see to do this is with #error in yacc.c. However, I don't see any other use of #error in the skeletons. Is there any reason not to use it?
>From bb6c1be1dca11f798e5fe9a0348a44dfff963908 Mon Sep 17 00:00:00 2001 From: Joel E. Denny <[email protected]> Date: Sun, 13 Sep 2009 14:03:30 -0400 Subject: [PATCH] api.push-pull: complain about YYSTACK_USE_ALLOCA=1. Previously it was just ignored for push parsers. * NEWS (2.4.2): Document. * data/yacc.c: Implement complaint with #error. * doc/bison.texinfo (Push Decl): Cross-reference ... (Table of Symbols): ... the YYSTACK_USE_ALLOCA entry here, and document the incompatibility. * tests/push.at (Error for YYSTACK_USE_ALLOCA=1): New test group. * tests/torture.at (Exploding the Stack Size with Alloca): For push parsing, instead of checking that alloca is ignored, just skip the test. --- ChangeLog | 15 +++++++++++++++ NEWS | 9 +++++++++ data/yacc.c | 12 ++++++------ doc/bison.texinfo | 11 +++++++++++ src/parse-gram.c | 4 ++-- src/parse-gram.h | 2 +- tests/push.at | 23 +++++++++++++++++++++++ tests/torture.at | 15 ++------------- 8 files changed, 69 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index f99cc59..d44b065 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,20 @@ 2009-09-13 Joel E. Denny <[email protected]> + api.push-pull: complain about YYSTACK_USE_ALLOCA=1. + Previously it was just ignored for push parsers. + * NEWS (2.4.2): Document. + * data/yacc.c: Implement complaint with #error. + * doc/bison.texinfo (Push Decl): Cross-reference ... + (Table of Symbols): ... the YYSTACK_USE_ALLOCA entry here, and + document the incompatibility. + * tests/push.at (Error for YYSTACK_USE_ALLOCA=1): New test + group. + * tests/torture.at (Exploding the Stack Size with Alloca): For + push parsing, instead of checking that alloca is ignored, just + skip the test. + +2009-09-13 Joel E. Denny <[email protected]> + tests: clean up push.at test group titles. * tests/push.at: Remove "Push Parsing: " from test group titles because these are already under the banner "Push Parsing Tests". diff --git a/NEWS b/NEWS index 41ab73d..979596d 100644 --- a/NEWS +++ b/NEWS @@ -214,6 +214,15 @@ Bison News Bison's Java feature as a whole including its current usage of %code is still considered experimental. +** Compilation error for push parsers and YYSTACK_USE_ALLOCA=1. + + Push parsers cannot use alloca to reallocate the parsing stacks as + they grow because, in order to preserve the stacks between calls to + yypush_parse, the stacks are stored in a yypstate instance rather than + locally in yypush_parse. Previously, YYSTACK_USE_ALLOCA=1 was simply + ignored in the generated push parser code. Now, #error is used + instead to complain to the user. + ** Internationalization. Fix a regression introduced in Bison 2.4: Under some circumstances, diff --git a/data/yacc.c b/data/yacc.c index 26c5996..0605af3 100644 --- a/data/yacc.c +++ b/data/yacc.c @@ -404,11 +404,12 @@ typedef short int yytype_int16; #if ! defined yyoverflow || YYERROR_VERBOSE -]b4_push_if([], -[[/* The parser invokes alloca or malloc; define the necessary symbols. */ +/* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA -# if YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA]b4_push_if([[ + /* Push parser stacks are not locals, so reject alloca requests. */ +# error push parsers are not compatible with YYSTACK_USE_ALLOCA=1]], [[ # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR @@ -426,12 +427,11 @@ typedef short int yytype_int16; # define _STDLIB_H 1 # endif # endif -# endif +# endif]])[ # endif # endif -]])dnl -[# ifdef YYSTACK_ALLOC +# ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) # ifndef YYSTACK_ALLOC_MAXIMUM diff --git a/doc/bison.texinfo b/doc/bison.texinfo index e3da40a..e8565e8 100644 --- a/doc/bison.texinfo +++ b/doc/bison.texinfo @@ -4675,6 +4675,9 @@ Adding the @samp{%define api.pure} declaration does exactly the same thing to the generated parser with @samp{%define api.push-pull both} as it did for @samp{%define api.push-pull push}. +Push parsers are not compatible with @samp{YYSTACK_USE_ALLOCA=1}. +See @ref{Table of Symbols, , YYSTACK_USE_ALLOCA}. + @node Decl Summary @subsection Bison Declaration Summary @cindex Bison declaration summary @@ -10613,6 +10616,14 @@ unchecked stack overflow on any of your target hosts when @code{alloca} is called. You can inspect the code that Bison generates in order to determine the proper numeric values. This will require some expertise in low-level implementation details. + +Push parsers cannot use @code{alloca} to reallocate the parsing stacks +because, in order to preserve the stacks between calls to +...@code{yypush_parse}, the stacks are stored in a @code{yypstate} instance +rather than locally in @code{yypush_parse}. +Thus, if you set @samp{YYSTACK_USE_ALLOCA=1}, @code{#error} is used to +generate a complaint. + @end deffn @deffn {Type} YYSTYPE diff --git a/tests/push.at b/tests/push.at index 741b362..cde07ab 100644 --- a/tests/push.at +++ b/tests/push.at @@ -166,3 +166,26 @@ AT_BISON_CHECK([[input.y]], [[1]], [], ]]) AT_CLEANUP + +## -------------------------------- ## +## Error for YYSTACK_USE_ALLOCA=1. ## +## -------------------------------- ## + +AT_SETUP([[Error for YYSTACK_USE_ALLOCA=1]]) + +AT_DATA_GRAMMAR([[input.y]], +[[%define api.push-pull push +%code { + void yyerror (char const *msg); + int yylex (void); +} +%% +start: ; +]]) +AT_BISON_CHECK([[-o input.c input.y]]) +AT_CHECK([[$CC $CFLAGS $CPPFLAGS -c input.c]]) +AT_CHECK([[$CC -DYYSTACK_USE_ALLOCA=0 $CFLAGS $CPPFLAGS -c input.c]]) +AT_CHECK([[$CC -DYYSTACK_USE_ALLOCA=1 $CFLAGS $CPPFLAGS -c input.c \ + || exit 1]], [[1]], [ignore], [ignore]) + +AT_CLEANUP diff --git a/tests/torture.at b/tests/torture.at index 47435cb..41d9b71 100644 --- a/tests/torture.at +++ b/tests/torture.at @@ -479,6 +479,8 @@ m4_pushdef([AT_USE_ALLOCA], [[ #endif ]]) +AT_CHECK([[if test x"$BISON_USE_PUSH_FOR_PULL" = x1; then exit 77; fi]]) + AT_DATA_STACK_TORTURE([AT_USE_ALLOCA]) # Below the limit of 200. @@ -492,19 +494,6 @@ AT_PARSER_CHECK([./input 900], 0, [], [ignore], AT_PARSER_CHECK([./input 10000], 2, [], [ignore], [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]]) -# The push parser can't use alloca since the stacks can't be locals. This test -# just helps guarantee we don't let the YYSTACK_USE_ALLOCA feature affect -# push parsers. -AT_DATA_STACK_TORTURE([AT_USE_ALLOCA], -[[%define api.push-pull both -]]) -AT_PARSER_CHECK([./input 20], 0, [], [ignore], - [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]]) -AT_PARSER_CHECK([./input 900], 0, [], [ignore], - [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]]) -AT_PARSER_CHECK([./input 10000], 2, [], [ignore], - [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]]) - m4_popdef([AT_USE_ALLOCA]) AT_CLEANUP -- 1.5.4.3
