Index: ChangeLog
from  Akim Demaille  <akim@epita.fr>

	* src/reader.c (grammar_current_rule_check): Also check that $$
	is used.
	Take the rule to check as argument, hence rename as...
	(grammar_rule_check): this.
	* src/reader.h, src/reader.c (grammar_rule_begin, grammar_rule_end):
	Rename as...
	(grammar_rule_begin, grammar_rule_end): these, for consistency.
	(grammar_midrule_action, grammar_symbol_append): Now static.
	* tests/torture.at (input): Don't rely on the default action
	being always performed.
	* tests/calc.at: "Set" $$ even when the action is "cut" with
	YYERROR or other.
	* tests/actions.at (Exotic Dollars): Instead of using unused
	values, check that the warning is issued.

Index: NEWS
===================================================================
RCS file: /cvsroot/bison/bison/NEWS,v
retrieving revision 1.138
diff -u -r1.138 NEWS
--- NEWS 23 Dec 2005 00:13:11 -0000 1.138
+++ NEWS 27 Dec 2005 17:37:20 -0000
@@ -7,13 +7,13 @@
   Typed right-hand side symbols whose value are not used are reported.
   For instance:
 
-     exp: exp "?" exp ":" exp { $$ = $1 ? $1 : $3; }
+     exp: exp "?" exp ":" exp { $1 ? $1 : $3; }
 	| exp "+" exp
 	;
 
-  will trigger a warning about $5 of the first rule, and $3 in the
-  second ($1 is copied to $$ by the default rule).  This example
-  most likely contains two errors, and should be rewritten as:
+  will trigger a warning about $$ and $5 in the first rule, and $3 in
+  the second ($1 is copied to $$ by the default rule).  This example
+  most likely contains three errors, and should be rewritten as:
 
      exp: exp "?" exp ":" exp { $$ = $1 ? $3 : $5; }
 	| exp "+" exp         { $$ = $1 + $3; }
@@ -22,7 +22,7 @@
   However, if the original actions were really intended, the warnings
   can be suppressed by letting Bison believe the values are used, e.g.:
 
-     exp: exp "?" exp ":" exp { $$ = $1 ? $1 : $3; (void) $5; }
+     exp: exp "?" exp ":" exp { $1 ? $1 : $3; (void) ($$, $5); }
 	| exp "+" exp         { $$ = $1; (void) $3; }
 	;
 
Index: src/parse-gram.y
===================================================================
RCS file: /cvsroot/bison/bison/src/parse-gram.y,v
retrieving revision 1.64
diff -u -r1.64 parse-gram.y
--- src/parse-gram.y 9 Dec 2005 23:51:26 -0000 1.64
+++ src/parse-gram.y 27 Dec 2005 17:37:27 -0000
@@ -396,14 +396,14 @@
 ;
 
 rhses.1:
-  rhs                { grammar_rule_end (@1); }
-| rhses.1 "|" rhs    { grammar_rule_end (@3); }
+  rhs                { grammar_current_rule_end (@1); }
+| rhses.1 "|" rhs    { grammar_current_rule_end (@3); }
 | rhses.1 ";"
 ;
 
 rhs:
   /* Nothing.  */
-    { grammar_rule_begin (current_lhs, current_lhs_location); }
+    { grammar_current_rule_begin (current_lhs, current_lhs_location); }
 | rhs symbol
     { grammar_current_rule_symbol_append ($2, @2); }
 | rhs action
Index: src/reader.c
===================================================================
RCS file: /cvsroot/bison/bison/src/reader.c,v
retrieving revision 1.241
diff -u -r1.241 reader.c
--- src/reader.c 22 Dec 2005 11:40:05 -0000 1.241
+++ src/reader.c 27 Dec 2005 17:37:28 -0000
@@ -36,6 +36,9 @@
 #include "symlist.h"
 #include "symtab.h"
 
+static void grammar_midrule_action (void);
+static void grammar_symbol_append (symbol *sym, location loc);
+
 static symbol_list *grammar = NULL;
 static bool start_flag = false;
 merger_list *merge_functions;
@@ -153,7 +156,7 @@
 static symbol_list *grammar_end = NULL;
 
 /* Append SYM to the grammar.  */
-void
+static void
 grammar_symbol_append (symbol *sym, location loc)
 {
   symbol_list *p = symbol_list_new (sym, loc);
@@ -164,6 +167,11 @@
     grammar = p;
 
   grammar_end = p;
+
+  /* SYM = 0 stands for an end of rule, it is not an actual
+     part of it.  */
+  if (sym)
+    ++nritems;
 }
 
 /* The rule currently being defined, and the previous rule.
@@ -178,7 +186,7 @@
 `----------------------------------------------*/
 
 void
-grammar_rule_begin (symbol *lhs, location loc)
+grammar_current_rule_begin (symbol *lhs, location loc)
 {
   if (!start_flag)
     {
@@ -189,8 +197,6 @@
 
   /* Start a new rule and record its lhs.  */
   ++nrules;
-  ++nritems;
-
   previous_rule_end = grammar_end;
   grammar_symbol_append (lhs, loc);
   current_rule = grammar_end;
@@ -207,17 +213,14 @@
 }
 
 
-/*------------------------------------------------------------------.
-| Check that the last rule (CURRENT_RULE) is properly defined.  For |
-| instance, there should be no type clash on the default action.    |
-`------------------------------------------------------------------*/
+/*----------------------------------------------------------------.
+| Check that the rule R is properly defined.  For instance, there |
+| should be no type clash on the default action.                  |
+`----------------------------------------------------------------*/
 
 static void
-grammar_current_rule_check (void)
+grammar_rule_check (const symbol_list *r)
 {
-  symbol *lhs = current_rule->sym;
-  char const *lhs_type = lhs->type_name;
-
   /* Type check.
 
      If there is an action, then there is nothing we can do: the user
@@ -225,36 +228,40 @@
 
      Don't worry about the default action if $$ is untyped, since $$'s
      value can't be used.  */
-  if (!current_rule->action && lhs_type)
+  if (!r->action && r->sym->type_name)
     {
-      symbol *first_rhs = current_rule->next->sym;
+      symbol *first_rhs = r->next->sym;
       /* If $$ is being set in default way, report if any type mismatch.  */
       if (first_rhs)
 	{
+	  char const *lhs_type = r->sym->type_name;
 	  const char *rhs_type =
 	    first_rhs->type_name ? first_rhs->type_name : "";
 	  if (!UNIQSTR_EQ (lhs_type, rhs_type))
-	    warn_at (current_rule->location,
+	    warn_at (r->location,
 		     _("type clash on default action: <%s> != <%s>"),
 		     lhs_type, rhs_type);
 	}
       /* Warn if there is no default for $$ but we need one.  */
       else
-	warn_at (current_rule->location,
+	warn_at (r->location,
 		 _("empty rule for typed nonterminal, and no action"));
     }
-
-  /* Check that all the symbol values are used. */
-  if (typed)
-    {
-      symbol_list *l = current_rule;
-      int n = 1;
-      for (l = current_rule->next; l && l->sym; l = l->next, ++n)
-	/* The default action `uses' $1. */
-	if (! (!current_rule->action && n == 1)
-	    && l->sym->type_name && !l->used)
-	  warn_at (current_rule->location, _("unused value: $%d"), n);
-    }
+  
+  /* Check that typed symbol values are used.  */
+  {
+    symbol_list *l = r;
+    int n = 0;
+    for (; l && l->sym; l = l->next, ++n)
+      if (! (l->used
+	     || !l->sym->type_name
+	     /* The default action, $$ = $1, `uses' both.  */
+	     || !r->action && (n == 0 || n == 1)))
+	if (n)
+	  warn_at (r->location, _("unused value: $%d"), n);
+	else
+	  warn_at (r->location, _("unset value: $$"));
+  }
 }
 
 
@@ -263,12 +270,12 @@
 `-------------------------------------*/
 
 void
-grammar_rule_end (location loc)
+grammar_current_rule_end (location loc)
 {
   /* Put an empty link in the list to mark the end of this rule  */
   grammar_symbol_append (NULL, grammar_end->location);
   current_rule->location = loc;
-  grammar_current_rule_check ();
+  grammar_rule_check (current_rule);
 }
 
 
@@ -279,7 +286,7 @@
 | rule.                                                              |
 `-------------------------------------------------------------------*/
 
-void
+static void
 grammar_midrule_action (void)
 {
   /* Since the action was written out with this rule's number, we must
@@ -364,7 +371,6 @@
 {
   if (current_rule->action)
     grammar_midrule_action ();
-  ++nritems;
   grammar_symbol_append (sym, loc);
 }
 
Index: src/reader.h
===================================================================
RCS file: /cvsroot/bison/bison/src/reader.h,v
retrieving revision 1.46
diff -u -r1.46 reader.h
--- src/reader.h 22 Dec 2005 11:40:05 -0000 1.46
+++ src/reader.h 27 Dec 2005 17:37:28 -0000
@@ -61,14 +61,11 @@
 /* From reader.c. */
 void grammar_start_symbol_set (symbol *sym, location loc);
 void prologue_augment (const char *prologue, location loc);
-void grammar_symbol_append (symbol *sym, location loc);
-void grammar_rule_begin (symbol *lhs, location loc);
-void grammar_rule_end (location loc);
-void grammar_midrule_action (void);
+void grammar_current_rule_begin (symbol *lhs, location loc);
+void grammar_current_rule_end (location loc);
 void grammar_current_rule_prec_set (symbol *precsym, location loc);
 void grammar_current_rule_dprec_set (int dprec, location loc);
 void grammar_current_rule_merge_set (uniqstr name, location loc);
-
 void grammar_current_rule_symbol_append (symbol *sym, location loc);
 void grammar_current_rule_action_append (const char *action, location loc);
 extern symbol_list *current_rule;
Index: src/scan-gram.l
===================================================================
RCS file: /cvsroot/bison/bison/src/scan-gram.l,v
retrieving revision 1.79
diff -u -r1.79 scan-gram.l
--- src/scan-gram.l 22 Dec 2005 11:40:05 -0000 1.79
+++ src/scan-gram.l 27 Dec 2005 17:37:30 -0000
@@ -815,6 +815,7 @@
 	type_name = "";
       obstack_fgrow1 (&obstack_for_string,
 		      "]b4_lhs_value([%s])[", type_name);
+      current_rule->used = true;
     }
   else
     {
@@ -837,8 +838,7 @@
 	  obstack_fgrow3 (&obstack_for_string,
 			  "]b4_rhs_value(%d, %d, [%s])[",
 			  rule_length, n, type_name);
-	  if (typed)
-	    symbol_list_n_used_set (current_rule, n, true);
+	  symbol_list_n_used_set (current_rule, n, true);
 	}
       else
 	complain_at (loc, _("integer out of range: %s"), quote (text));
Index: tests/actions.at
===================================================================
RCS file: /cvsroot/bison/bison/tests/actions.at,v
retrieving revision 1.55
diff -u -r1.55 actions.at
--- tests/actions.at 22 Dec 2005 11:40:05 -0000 1.55
+++ tests/actions.at 27 Dec 2005 17:37:33 -0000
@@ -30,13 +30,13 @@
 # action.
 
 AT_DATA_GRAMMAR([[input.y]],
-[[%{
+[[%error-verbose
+%debug
+%{
 # include <stdio.h>
 # include <stdlib.h>
   static void yyerror (const char *msg);
   static int yylex (void);
-# define YYDEBUG         1
-# define YYERROR_VERBOSE 1
 %}
 %%
 exp:     { putchar ('0'); }
@@ -91,13 +91,13 @@
 AT_SETUP([Exotic Dollars])
 
 AT_DATA_GRAMMAR([[input.y]],
-[[%{
+[[%error-verbose
+%debug
+%{
 # include <stdio.h>
 # include <stdlib.h>
   static void yyerror (const char *msg);
   static int yylex (void);
-# define YYDEBUG         1
-# define YYERROR_VERBOSE 1
 # define USE(Var)
 %}
 
@@ -107,13 +107,12 @@
 };
 
 %type <val> a_1 a_2 a_5
-            sum_of_the_five_previous_values
+            exp sum_of_the_five_previous_values
 
 %%
 exp: a_1 a_2 { $<val>$ = 3; } { $<val>$ = $<val>3 + 1; } a_5
      sum_of_the_five_previous_values
     {
-       USE (($1, $2, $5));
        printf ("%d\n", $6);
     }
 ;
@@ -147,7 +146,11 @@
 }
 ]])
 
-AT_CHECK([bison -d -v -o input.c input.y])
+AT_CHECK([bison -d -v -o input.c input.y], 0, [], 
+[input.y:30.6-34.5: warning: unused value: $1
+input.y:30.6-34.5: warning: unused value: $2
+input.y:30.6-34.5: warning: unused value: $5
+])
 AT_COMPILE([input])
 AT_PARSER_CHECK([./input], 0,
 [[15
Index: tests/calc.at
===================================================================
RCS file: /cvsroot/bison/bison/tests/calc.at,v
retrieving revision 1.84
diff -u -r1.84 calc.at
--- tests/calc.at 22 Dec 2005 11:40:05 -0000 1.84
+++ tests/calc.at 27 Dec 2005 17:37:34 -0000
@@ -129,15 +129,15 @@
 | exp '^' exp        { $$ = power ($1, $3); }
 | '(' exp ')'        { $$ = $2;             }
 | '(' error ')'      { $$ = 1111;           }
-| '!'                { YYERROR;             }
-| '-' error          { YYERROR;             }
+| '!'                { $$ = 0; YYERROR;     }
+| '-' error          { $$ = 0; YYERROR;     }
 ;
 %%
-/* The input. */
+/* The input.  */
 static FILE *input;
 
 ]AT_LALR1_CC_IF(
-[/* A C++ error reporting function. */
+[/* A C++ error reporting function.  */
 void
 yy::parser::error (const location& l, const std::string& m)
 {
Index: tests/torture.at
===================================================================
RCS file: /cvsroot/bison/bison/tests/torture.at,v
retrieving revision 1.30
diff -u -r1.30 torture.at
--- tests/torture.at 21 Sep 2005 20:08:38 -0000 1.30
+++ tests/torture.at 27 Dec 2005 17:37:35 -0000
@@ -50,13 +50,12 @@
 
 print <<EOF;
 ]AT_DATA_GRAMMAR_PROLOGUE[
+%error-verbose
+%debug
 %{
 #include <stdio.h>
 #include <stdlib.h>
 
-#define YYERROR_VERBOSE 1
-#define YYDEBUG 1
-
 static int yylex (void);
 static void yyerror (const char *msg);
 %}
@@ -166,24 +165,25 @@
 
 print <<EOF;
 ]AT_DATA_GRAMMAR_PROLOGUE[
+%error-verbose
+%debug
 %{
 #include <stdio.h>
 #include <stdlib.h>
 
-#define YYERROR_VERBOSE 1
-#define YYDEBUG 1
-
 static int yylex (void);
 static void yyerror (const char *msg);
 %}
-EOF
 
+%token
+EOF
 for my $size (1 .. $max)
   {
-    print "%token t$size $size \"$size\"\n";
+    print "    t$size $size \"$size\"\n";
   };
 
 print <<EOF;
+
 %%
 EOF
 
@@ -258,7 +258,7 @@
 
 
 # AT_DATA_LOOK_AHEAD_TOKENS_GRAMMAR(FILE-NAME, SIZE)
-# -------------------------------------------
+# --------------------------------------------------
 # Create FILE-NAME, containing a self checking parser for a grammar
 # requiring SIZE look-ahead tokens.
 m4_define([AT_DATA_LOOK_AHEAD_TOKENS_GRAMMAR],
@@ -270,12 +270,12 @@
 my $max = $ARGV[0] || 10;
 
 print <<EOF;
+%error-verbose
+%debug
 %{
-#include <stdio.h>
-#include <stdlib.h>
-
-#define YYERROR_VERBOSE 1
-#define YYDEBUG 1
+# include <stdio.h>
+# include <stdlib.h>
+# include <assert.h>
 
 static int yylex (void);
 static void yyerror (const char *msg);
@@ -295,25 +295,26 @@
 	map { "n$_" } (1 .. $max)),
   "\n";
 
+print "%token\n";
 for my $count (1 .. $max)
   {
-    print "%token t$count $count \"$count\"\n";
+    print "    t$count $count \"$count\"\n";
   };
 
 print <<EOF;
 %%
 input:
-  exp        { if (\@S|@1 != 1) abort (); \$\$ = \@S|@1; }
-| input exp  { if (\@S|@2 != \@S|@1 + 1) abort (); \$\$ = \@S|@2; }
+  exp        { assert (\@S|@1 == 1); \$\$ = \@S|@1; }
+| input exp  { assert (\@S|@2 == \@S|@1 + 1); \$\$ = \@S|@2; }
 ;
 
 exp:
-  n1 "1" { if (\@S|@1 != 1) abort (); }
+  n1 "1" { assert (\@S|@1 == 1); \@S|@\@S|@ = \@S|@1; }
 EOF
 
 for my $count (2 .. $max)
   {
-    print "| n$count \"$count\" { if (\@S|@1 != $count) abort (); }\n";
+    print "| n$count \"$count\" { assert (\@S|@1 == $count); \@S|@\@S|@ = \@S|@1; }\n";
   };
 print ";\n";
 
