]> git.saurik.com Git - bison.git/commitdiff
* tests/glr-regression.at (Leaked semantic values when reporting
authorJoel E. Denny <jdenny@ces.clemson.edu>
Sat, 4 Mar 2006 03:29:03 +0000 (03:29 +0000)
committerJoel E. Denny <jdenny@ces.clemson.edu>
Sat, 4 Mar 2006 03:29:03 +0000 (03:29 +0000)
ambiguity): Remove unnecessary union and type declarations.
(Leaked lookahead after nondeterministic parse syntax error): New test
case.
* data/glr.c (yyparse): Check for zero stacks remaining before
attempting to shift the lookahead so that you don't lose it.

ChangeLog
data/glr.c
tests/glr-regression.at

index b3413819a6eb5ed6bceece9a26a143c4767c1cf3..1dce255377e1f3c3b3036f67f759084b6733638f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2006-03-04  Joel E. Denny  <jdenny@ces.clemson.edu>
+
+       * tests/glr-regression.at (Leaked semantic values when reporting
+       ambiguity): Remove unnecessary union and type declarations.
+       (Leaked lookahead after nondeterministic parse syntax error): New test
+       case.
+       * data/glr.c (yyparse): Check for zero stacks remaining before
+       attempting to shift the lookahead so that you don't lose it.
+
 2006-03-02  Joel E. Denny  <jdenny@ces.clemson.edu>
 
        Avoid memory leaks by not invoking longjmp in yyreportAmbiguity.
 2006-03-02  Joel E. Denny  <jdenny@ces.clemson.edu>
 
        Avoid memory leaks by not invoking longjmp in yyreportAmbiguity.
@@ -23,7 +32,7 @@
        * data/glr.c (yydestroyGLRState): In debugging output, distinguish
        between an unresolved state (non-empty chain of semantic options) and
        an incomplete one (signaled by an empty chain).
        * data/glr.c (yydestroyGLRState): In debugging output, distinguish
        between an unresolved state (non-empty chain of semantic options) and
        an incomplete one (signaled by an empty chain).
-       (yyresolveStates): Document the interface.  Move all manipulation of an
+       (yyresolveStates): Document the interface.  Move all manipulation of a
        successfully or unsuccessfully resolved yyGLRState to...
        (yyresolveValue): ... here so that yyresolveValue always leaves a
        yyGLRState with consistent data and thus is easier to understand.
        successfully or unsuccessfully resolved yyGLRState to...
        (yyresolveValue): ... here so that yyresolveValue always leaves a
        yyGLRState with consistent data and thus is easier to understand.
index aab6779ce6293769a635a2aee6a897992f062202..13fd2ff2872c4914aaa9aecd97ad67841fdf47e8 100644 (file)
@@ -2338,9 +2338,8 @@ b4_syncline([@oline@], [@ofile@])])dnl
        {
          yySymbol yytoken_to_shift;
          size_t yys;
        {
          yySymbol yytoken_to_shift;
          size_t yys;
-         size_t yyn = yystack.yytops.yysize;
 
 
-         for (yys = 0; yys < yyn; yys += 1)
+         for (yys = 0; yys < yystack.yytops.yysize; yys += 1)
            yystackp->yytops.yylookaheadNeeds[yys] = yychar != YYEMPTY;
 
          /* yyprocessOneStack returns one of three things:
            yystackp->yytops.yylookaheadNeeds[yys] = yychar != YYEMPTY;
 
          /* yyprocessOneStack returns one of three things:
@@ -2359,13 +2358,23 @@ b4_syncline([@oline@], [@ofile@])])dnl
             Except in the first case, yyparse will invoke yyremoveDeletes and
             then shift the next token onto all remaining stacks.  This
             synchronization of the shift (that is, after all preceding
             Except in the first case, yyparse will invoke yyremoveDeletes and
             then shift the next token onto all remaining stacks.  This
             synchronization of the shift (that is, after all preceding
-            reductions on all stacks) helps prevents double destructor calls
+            reductions on all stacks) helps prevent double destructor calls
             on yylval in the event of memory exhaustion.  */
 
             on yylval in the event of memory exhaustion.  */
 
-         for (yys = 0; yys < yyn; yys += 1)
+         for (yys = 0; yys < yystack.yytops.yysize; yys += 1)
            YYCHK1 (yyprocessOneStack (&yystack, yys, yyposn]b4_lpure_args[));
          yyremoveDeletes (&yystack);
            YYCHK1 (yyprocessOneStack (&yystack, yys, yyposn]b4_lpure_args[));
          yyremoveDeletes (&yystack);
-         yyn = yystack.yytops.yysize;
+         if (yystack.yytops.yysize == 0)
+           {
+             yyundeleteLastStack (&yystack);
+             if (yystack.yytops.yysize == 0)
+               yyFail (&yystack][]b4_lpure_args[, YY_("syntax error"));
+             YYCHK1 (yyresolveStack (&yystack]b4_user_args[));
+             YYDPRINTF ((stderr, "Returning to deterministic operation.\n"));
+]b4_location_if([[           yystack.yyerror_range[1].yystate.yyloc = yylloc;]])[
+             yyreportSyntaxError (&yystack]b4_user_args[);
+             goto yyuser_error;
+           }
 
          /* If any yyglrShift call fails, it will fail after shifting.  Thus,
             a copy of yylval will already be on stack 0 in the event of a
 
          /* If any yyglrShift call fails, it will fail after shifting.  Thus,
             a copy of yylval will already be on stack 0 in the event of a
@@ -2375,7 +2384,7 @@ b4_syncline([@oline@], [@ofile@])])dnl
          yytoken_to_shift = YYTRANSLATE (yychar);
          yychar = YYEMPTY;
          yyposn += 1;
          yytoken_to_shift = YYTRANSLATE (yychar);
          yychar = YYEMPTY;
          yyposn += 1;
-         for (yys = 0; yys < yyn; yys += 1)
+         for (yys = 0; yys < yystack.yytops.yysize; yys += 1)
            {
              int yyaction;
              const short int* yyconflicts;
            {
              int yyaction;
              const short int* yyconflicts;
@@ -2391,18 +2400,8 @@ b4_syncline([@oline@], [@ofile@])])dnl
                          (unsigned long int) yys,
                          yystack.yytops.yystates[yys]->yylrState));
            }
                          (unsigned long int) yys,
                          yystack.yytops.yystates[yys]->yylrState));
            }
-         if (yystack.yytops.yysize == 0)
-           {
-             yyundeleteLastStack (&yystack);
-             if (yystack.yytops.yysize == 0)
-               yyFail (&yystack][]b4_lpure_args[, YY_("syntax error"));
-             YYCHK1 (yyresolveStack (&yystack]b4_user_args[));
-             YYDPRINTF ((stderr, "Returning to deterministic operation.\n"));
-]b4_location_if([[           yystack.yyerror_range[1].yystate.yyloc = yylloc;]])[
-             yyreportSyntaxError (&yystack]b4_user_args[);
-             goto yyuser_error;
-           }
-         else if (yystack.yytops.yysize == 1)
+
+         if (yystack.yytops.yysize == 1)
            {
              YYCHK1 (yyresolveStack (&yystack]b4_user_args[));
              YYDPRINTF ((stderr, "Returning to deterministic operation.\n"));
            {
              YYCHK1 (yyresolveStack (&yystack]b4_user_args[));
              YYDPRINTF ((stderr, "Returning to deterministic operation.\n"));
index 54c02f5614797f3f5b86558d86424640b17f7d7a..c9b745bc36706207a2692c80231e917c30247886 100644 (file)
@@ -1431,8 +1431,6 @@ AT_SETUP([Leaked semantic values when reporting ambiguity])
 AT_DATA_GRAMMAR([glr-regr15.y],
 [[
 %glr-parser
 AT_DATA_GRAMMAR([glr-regr15.y],
 [[
 %glr-parser
-%union { int dummy; }
-%type <dummy> parent_rhs_before
 %destructor { parent_rhs_before_value = 0; } parent_rhs_before
 
 %{
 %destructor { parent_rhs_before_value = 0; } parent_rhs_before
 
 %{
@@ -1512,3 +1510,69 @@ AT_CHECK([[./glr-regr15]], 0, [],
 ])
 
 AT_CLEANUP
 ])
 
 AT_CLEANUP
+
+
+## ------------------------------------------------------------------------- ##
+## Leaked lookahead after nondeterministic parse syntax error.              ##
+## ------------------------------------------------------------------------- ##
+
+AT_SETUP([Leaked lookahead after nondeterministic parse syntax error])
+AT_DATA_GRAMMAR([glr-regr16.y],
+[[
+%glr-parser
+%destructor { lookahead_value = 0; } 'b'
+
+%{
+# include <stdlib.h>
+  static void yyerror (char const *);
+  static int yylex (void);
+  static int lookahead_value = 0;
+# define USE(val)
+%}
+
+%%
+
+start: alt1 'a' | alt2 'a' ;
+alt1: ;
+alt2: ;
+
+%%
+
+static void
+yyerror (char const *msg)
+{
+  fprintf (stderr, "%s\n", msg);
+}
+
+static int
+yylex (void)
+{
+  static const char *input = "ab";
+  if (*input == 'b')
+    lookahead_value = 1;
+  return *input++;
+}
+
+int
+main (void)
+{
+  int exit_status = yyparse () != 1;
+  if (lookahead_value)
+    {
+      fprintf (stderr, "Lookahead destructor not called.\n");
+      exit_status = 1;
+    }
+  return exit_status;
+}
+]])
+
+AT_CHECK([[bison -o glr-regr16.c glr-regr16.y]], 0, [],
+[glr-regr16.y: conflicts: 1 reduce/reduce
+])
+AT_COMPILE([glr-regr16])
+
+AT_CHECK([[./glr-regr16]], 0, [],
+[syntax error
+])
+
+AT_CLEANUP