]> git.saurik.com Git - bison.git/blobdiff - src/parse-gram.y
named references: fix double free.
[bison.git] / src / parse-gram.y
index 8871f67203fd763a19ca9efb1f22320f161ca97b..8c2e18d1102f2be9a71a70d69a4a9433110d627e 100644 (file)
@@ -61,11 +61,30 @@ static void add_param (char const *type, char *decl, location loc);
 
 static symbol_class current_class = unknown_sym;
 static uniqstr current_type = NULL;
-static symbol *current_lhs;
+static symbol *current_lhs_symbol;
 static location current_lhs_location;
 static named_ref *current_lhs_named_ref;
 static int current_prec = 0;
 
+/** Set the new current left-hand side symbol, possibly common
+ * to several right-hand side parts of rule.
+ */
+static
+void
+current_lhs(symbol *sym, location loc, named_ref *ref)
+{
+  current_lhs_symbol = sym;
+  current_lhs_location = loc;
+  /* In order to simplify memory management, named references for lhs
+     are always assigned by deep copy into the current symbol_list
+     node.  This is because a single named-ref in the grammar may
+     result in several uses when the user factors lhs between several
+     rules using "|".  Therefore free the parser's original copy.  */
+  free (current_lhs_named_ref);
+  current_lhs_named_ref = ref;
+}
+
+
 #define YYTYPE_INT16 int_fast16_t
 #define YYTYPE_INT8 int_fast8_t
 #define YYTYPE_UINT16 uint_fast16_t
@@ -526,8 +545,11 @@ rules_or_grammar_declaration:
 ;
 
 rules:
-  id_colon named_ref.opt { current_lhs = $1; current_lhs_location = @1;
-    current_lhs_named_ref = $2; } rhses.1
+  id_colon named_ref.opt { current_lhs ($1, @1, $2); } rhses.1
+  {
+    /* Free the current lhs. */
+    current_lhs (0, @1, 0);
+  }
 ;
 
 rhses.1:
@@ -538,7 +560,7 @@ rhses.1:
 
 rhs:
   /* Nothing.  */
-    { grammar_current_rule_begin (current_lhs, current_lhs_location,
+    { grammar_current_rule_begin (current_lhs_symbol, current_lhs_location,
                                  current_lhs_named_ref); }
 | rhs symbol named_ref.opt
     { grammar_current_rule_symbol_append ($2, @2, $3); }