diff --git a/NEWS b/NEWS index 20127a74..9309de64 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,20 @@ GNU Bison NEWS The use of the %error-verbose directive is deprecated in favor of "%define parse.error verbose" since Bison 3.0, but no warning was issued. +** Bug fixes + +*** Incorrect number of reduce-reduce conflicts + + On a grammar such as + + exp: "num" | "num" | "num" + + bison used report a single RR conflict, instead of two. This is now + fixed. This was the oldest (known) bug in Bison: it was there when Bison + was entered in the RCS version control system, in December 1987. + + Some grammar files might have to adjust their %expect-rr. + * Noteworthy changes in release 3.2.2 (2018-11-21) [stable] ** Bug fixes diff --git a/src/conflicts.c b/src/conflicts.c index 2838243e..af67aaea 100644 --- a/src/conflicts.c +++ b/src/conflicts.c @@ -467,15 +467,13 @@ count_sr_conflicts (void) -/*----------------------------------------------------------------. -| Count the number of reduce/reduce conflicts. If ONE_PER_TOKEN, | -| count one conflict for each token that has any reduce/reduce | -| conflicts. Otherwise, count one conflict for each reduction | -| after the first for a given token. | -`----------------------------------------------------------------*/ +/*-----------------------------------------------------------------. +| Count the number of reduce/reduce conflicts. Count one conflict | +| for each reduction after the first for a given token. | +`-----------------------------------------------------------------*/ static size_t -count_state_rr_conflicts (state *s, bool one_per_token) +count_state_rr_conflicts (state *s) { reductions *reds = s->reductions; size_t res = 0; @@ -486,20 +484,20 @@ count_state_rr_conflicts (state *s, bool one_per_token) for (int j = 0; j < reds->num; ++j) count += bitset_test (reds->lookahead_tokens[j], i); if (count >= 2) - res += one_per_token ? 1 : count-1; + res += count-1; } return res; } static size_t -count_rr_conflicts (bool one_per_token) +count_rr_conflicts (void) { size_t res = 0; /* Conflicts by state. */ for (state_number i = 0; i < nstates; ++i) if (conflicts[i]) - res += count_state_rr_conflicts (states[i], one_per_token); + res += count_state_rr_conflicts (states[i]); return res; } @@ -591,7 +589,7 @@ conflicts_output (FILE *out) if (conflicts[i]) { int src = count_state_sr_conflicts (s); - int rrc = count_state_rr_conflicts (s, true); + int rrc = count_state_rr_conflicts (s); fprintf (out, _("State %d "), i); if (src && rrc) fprintf (out, @@ -608,17 +606,14 @@ conflicts_output (FILE *out) fputs ("\n\n", out); } -/*--------------------------------------------------------. -| Total the number of S/R and R/R conflicts. Unlike the | -| code in conflicts_output, however, count EACH pair of | -| reductions for the same state and lookahead as one | -| conflict. | -`--------------------------------------------------------*/ +/*--------------------------------------------. +| Total the number of S/R and R/R conflicts. | +`--------------------------------------------*/ int conflicts_total_count (void) { - return count_sr_conflicts () + count_rr_conflicts (false); + return count_sr_conflicts () + count_rr_conflicts (); } /*------------------------------. @@ -692,7 +687,7 @@ conflicts_print (void) } { - int total = count_rr_conflicts (true); + int total = count_rr_conflicts (); /* If %expect-rr is not used, but %expect is, then expect 0 rr. */ int expected = (expected_rr_conflicts == -1 && expected_sr_conflicts != -1) diff --git a/src/conflicts.h b/src/conflicts.h index 22a177cb..7524ef4e 100644 --- a/src/conflicts.h +++ b/src/conflicts.h @@ -44,4 +44,5 @@ void conflicts_free (void); /* Were there conflicts? */ extern int expected_sr_conflicts; extern int expected_rr_conflicts; + #endif /* !CONFLICTS_H_ */ diff --git a/tests/glr-regression.at b/tests/glr-regression.at index 9f2fb3fb..884f74f4 100644 --- a/tests/glr-regression.at +++ b/tests/glr-regression.at @@ -342,7 +342,7 @@ AT_BISON_OPTION_POPDEFS AT_BISON_CHECK([[-o glr-regr3.c -rall glr-regr3.y]], 0, [], [[glr-regr3.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] -glr-regr3.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] +glr-regr3.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr] ]]) AT_COMPILE([glr-regr3]) @@ -437,7 +437,7 @@ merge (YYSTYPE s1, YYSTYPE s2) AT_BISON_OPTION_POPDEFS AT_BISON_CHECK([[-o glr-regr4.c -rall glr-regr4.y]], 0, [], -[[glr-regr4.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] +[[glr-regr4.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr] ]]) AT_COMPILE([glr-regr4]) @@ -799,7 +799,7 @@ main (void) AT_BISON_OPTION_POPDEFS AT_BISON_CHECK([[-o glr-regr9.c -rall glr-regr9.y]], 0, [], -[[glr-regr9.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] +[[glr-regr9.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr] ]]) AT_COMPILE([glr-regr9]) @@ -1363,7 +1363,7 @@ main (void) AT_BISON_OPTION_POPDEFS AT_BISON_CHECK([[-o glr-regr14.c -rall glr-regr14.y]], 0, [], -[[glr-regr14.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr] +[[glr-regr14.y: warning: 5 reduce/reduce conflicts [-Wconflicts-rr] ]]) AT_COMPILE([glr-regr14])