]> git.saurik.com Git - bison.git/commitdiff
* data/glr.c (yyresolveValue): When merging semantic options, if at
authorJoel E. Denny <jdenny@ces.clemson.edu>
Thu, 5 Jan 2006 21:07:54 +0000 (21:07 +0000)
committerJoel E. Denny <jdenny@ces.clemson.edu>
Thu, 5 Jan 2006 21:07:54 +0000 (21:07 +0000)
least one user action succeeds but a later one cuts the parse, then
destroy the semantic value before returning rather than leaking it.
(yyresolveStates): If a user action cuts the parse and thus
yyresolveValue fails, ignore the (unset) semantic value rather than
corrupting the yyGLRState, and empty the semantic options list since
the user actions should have called all necessary destructors.
Simplify code with YYCHK.
* tests/glr-regression.at (Corrupted semantic options if user action
cuts parse): New test case.
(Undesirable destructors if user action cuts parse): New test case.
Before applying any of this patch, this test case never actually failed
for me... but only because the corrupted semantic options usually
masked this bug.
(Leaked merged semantic value if user action cuts parse): New test
case.

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

index 5da2b92bd72d0646463460051957a535bb0d0a91..c5e77034458b00b50f2e72b60a30955d177a367a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2006-01-05  Joel E. Denny  <jdenny@ces.clemson.edu>
+
+       * data/glr.c (yyresolveValue): When merging semantic options, if at
+       least one user action succeeds but a later one cuts the parse, then
+       destroy the semantic value before returning rather than leaking it.
+       (yyresolveStates): If a user action cuts the parse and thus
+       yyresolveValue fails, ignore the (unset) semantic value rather than
+       corrupting the yyGLRState, and empty the semantic options list since
+       the user actions should have called all necessary destructors.
+       Simplify code with YYCHK.
+       * tests/glr-regression.at (Corrupted semantic options if user action
+       cuts parse): New test case.
+       (Undesirable destructors if user action cuts parse): New test case.
+       Before applying any of this patch, this test case never actually failed
+       for me... but only because the corrupted semantic options usually
+       masked this bug.
+       (Leaked merged semantic value if user action cuts parse): New test
+       case.
+
 2006-01-05  Akim Demaille  <akim@epita.fr>
 
        * src/reader.c, src/symlist.h, src/symlist.c: s/mid_rule/midrule/.
index 20f5043fa433fc7cc610e1feaa7626657afb4c07..975ec578cbe53a3094693cefdb2c3f4e22bc1f29 100644 (file)
@@ -1612,7 +1612,7 @@ yypreference (yySemanticOption* y0, yySemanticOption* y1)
   return 0;
 }
 
-static YYRESULTTAG yyresolveValue (yySemanticOption* yyoptionList,
+static YYRESULTTAG yyresolveValue (yyGLRState* yys,
                                   yyGLRStack* yystackp, YYSTYPE* yyvalp,
                                   YYLTYPE* yylocp]b4_user_formals[);
 
@@ -1620,20 +1620,21 @@ static YYRESULTTAG
 yyresolveStates (yyGLRState* yys, int yyn,
                 yyGLRStack* yystackp]b4_user_formals[)
 {
-  YYRESULTTAG yyflag;
   if (0 < yyn)
     {
       YYASSERT (yys->yypred);
-      yyflag = yyresolveStates (yys->yypred, yyn-1, yystackp]b4_user_args[);
-      if (yyflag != yyok)
-       return yyflag;
+      YYCHK (yyresolveStates (yys->yypred, yyn-1, yystackp]b4_user_args[));
       if (! yys->yyresolved)
        {
-         yyflag = yyresolveValue (yys->yysemantics.yyfirstVal, yystackp,
-                                  &yys->yysemantics.yysval, &yys->yyloc
-                                 ]b4_user_args[);
+         YYSTYPE yysval;
+         YYRESULTTAG yyflag = yyresolveValue (yys, yystackp, &yysval,
+                                              &yys->yyloc]b4_user_args[);
          if (yyflag != yyok)
-           return yyflag;
+           {
+             yys->yysemantics.yyfirstVal = NULL;
+             return yyflag;
+           }
+         yys->yysemantics.yysval = yysval;
          yys->yyresolved = yytrue;
        }
     }
@@ -1728,12 +1729,13 @@ yyreportAmbiguity (yySemanticOption* yyx0, yySemanticOption* yyx1,
 }
 
 
-/** Resolve the ambiguity represented by OPTIONLIST, perform the indicated
+/** Resolve the ambiguity represented in state S, perform the indicated
  *  actions, and return the result.  */
 static YYRESULTTAG
-yyresolveValue (yySemanticOption* yyoptionList, yyGLRStack* yystackp,
-               YYSTYPE* yyvalp, YYLTYPE* yylocp]b4_user_formals[)
+yyresolveValue (yyGLRState* yys, yyGLRStack* yystackp, YYSTYPE* yyvalp,
+               YYLTYPE* yylocp]b4_user_formals[)
 {
+  yySemanticOption* yyoptionList = yys->yysemantics.yyfirstVal;
   yySemanticOption* yybest;
   yySemanticOption** yypp;
   yybool yymerge;
@@ -1786,8 +1788,15 @@ yyresolveValue (yySemanticOption* yyoptionList, yyGLRStack* yystackp,
            {
              YYSTYPE yyval1;
              YYLTYPE yydummy;
-             YYCHK (yyresolveAction (yyp, yystackp, &yyval1,
-                                     &yydummy]b4_user_args[));
+             YYRESULTTAG yyflag = yyresolveAction (yyp, yystackp, &yyval1,
+                                                   &yydummy]b4_user_args[);
+             if (yyflag != yyok)
+               {
+                 yydestruct ("Cleanup: discarding merged value",
+                             yystos[yys->yylrState],
+                             yyvalp]b4_location_if([, yylocp])[]b4_user_args[);
+                 return yyflag;
+               }
              yyuserMerge (yymerger[yyp->yyrule], yyvalp, &yyval1);
            }
        }
index ad8f6d864fbb3b6733b0668a61d51973f1466f24..b1e91180c8a62eaceef915baa2aa69f45a831e91 100644 (file)
@@ -815,3 +815,203 @@ AT_CHECK([[./glr-regr9]], 0, [],
 ])
 
 AT_CLEANUP
+
+
+## ------------------------------------------------------------------------- ##
+## Corrupted semantic options if user action cuts parse.                    ##
+## ------------------------------------------------------------------------- ##
+
+AT_SETUP([Corrupted semantic options if user action cuts parse.])
+
+AT_DATA_GRAMMAR([glr-regr10.y],
+[[
+%{
+# include <stdio.h>
+  static void yyerror (char const *);
+  static int yylex (void);
+  #define GARBAGE_SIZE 50
+  static char garbage[GARBAGE_SIZE];
+%}
+
+%glr-parser
+%union { char *ptr; }
+%type <ptr> start
+
+%%
+
+start:
+    %dprec 2 { $$ = garbage; YYACCEPT; }
+  | %dprec 1 { $$ = garbage; YYACCEPT; }
+  ;
+
+%%
+
+static void
+yyerror (char const *msg)
+{
+  fprintf (stderr, "%s\n", msg);
+}
+
+static int
+yylex (void)
+{
+  return 0;
+}
+
+int
+main (void)
+{
+  int index;
+  for (index = 0; index < GARBAGE_SIZE; index+=1)
+    garbage[index] = 132;
+  return yyparse ();
+}
+]])
+
+AT_CHECK([[bison -t -o glr-regr10.c glr-regr10.y]], 0, [],
+[glr-regr10.y: conflicts: 1 reduce/reduce
+])
+AT_COMPILE([glr-regr10])
+
+AT_CHECK([[./glr-regr10]], 0, [], [])
+
+AT_CLEANUP
+
+
+## ------------------------------------------------------------------------- ##
+## Undesirable destructors if user action cuts parse.                       ##
+## ------------------------------------------------------------------------- ##
+
+AT_SETUP([Undesirable destructors if user action cuts parse.])
+
+AT_DATA_GRAMMAR([glr-regr11.y],
+[[
+%{
+# include <stdlib.h>
+  static void yyerror (char const *);
+  static int yylex (void);
+  static int destructors = 0;
+# define USE(val)
+%}
+
+%glr-parser
+%union { int dummy; }
+%type <int> 'a'
+%destructor { destructors += 1; } 'a'
+
+%%
+
+start:
+    'a' %dprec 2 { USE ($1); destructors += 1; YYACCEPT; }
+  | 'a' %dprec 1 { USE ($1); destructors += 1; YYACCEPT; }
+  ;
+
+%%
+
+static void
+yyerror (char const *msg)
+{
+  fprintf (stderr, "%s\n", msg);
+}
+
+static int
+yylex (void)
+{
+  static char const *input = "a";
+  return *input++;
+}
+
+int
+main (void)
+{
+  int exit_status = yyparse ();
+  if (destructors != 1)
+    {
+      fprintf (stderr, "Destructor calls: %d\n", destructors);
+      return 1;
+    }
+  return exit_status;
+}
+]])
+
+AT_CHECK([[bison -t -o glr-regr11.c glr-regr11.y]], 0, [],
+[glr-regr11.y: conflicts: 1 reduce/reduce
+])
+AT_COMPILE([glr-regr11])
+
+AT_CHECK([[./glr-regr11]], 0, [], [])
+
+AT_CLEANUP
+
+
+## ------------------------------------------------------------------------- ##
+## Leaked merged semantic value if user action cuts parse.                  ##
+## ------------------------------------------------------------------------- ##
+
+AT_SETUP([Leaked merged semantic value if user action cuts parse.])
+
+AT_DATA_GRAMMAR([glr-regr12.y],
+[[
+%glr-parser
+%union { int dummy; }
+%type <dummy> start
+%destructor { has_value = 0; } start
+
+%{
+# include <stdlib.h>
+  static int merge (YYSTYPE, YYSTYPE);
+  static void yyerror (char const *);
+  static int yylex (void);
+  static int has_value = 0;
+# define USE(val)
+%}
+
+%%
+
+start:
+    %merge<merge> { has_value = 1; USE ($$); }
+  | %merge<merge> { USE ($$); YYACCEPT; }
+  ;
+
+%%
+
+static int
+merge (YYSTYPE s1, YYSTYPE s2)
+{
+  /* Not invoked. */
+  return 0;
+}
+
+static void
+yyerror (char const *msg)
+{
+  fprintf (stderr, "%s\n", msg);
+}
+
+static int
+yylex (void)
+{
+  return 0;
+}
+
+int
+main (void)
+{
+  int exit_status = yyparse ();
+  if (has_value)
+    {
+      fprintf (stderr, "Destructor not called.\n");
+      return 1;
+    }
+  return exit_status;
+}
+]])
+
+AT_CHECK([[bison -t -o glr-regr12.c glr-regr12.y]], 0, [],
+[glr-regr12.y: conflicts: 1 reduce/reduce
+])
+AT_COMPILE([glr-regr12])
+
+AT_CHECK([[./glr-regr12]], 0, [], [])
+
+AT_CLEANUP