From 2f8d401672befbb085e16f714e24acbf43d9da88 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Wed, 3 Jun 2009 23:15:38 +0200 Subject: [PATCH] deterministic user-token-number redeclaration errors. Address nondeterminism reported by Joel E. Denny. http://lists.gnu.org/archive/html/bison-patches/2009-05/msg00023.html * src/uniqstr.h: Comment changes. * src/location.h (boundary_cmp, location_cmp): New. * src/symtab.c (user_token_number_redeclaration): New. (symbol_translation): Use it. * tests/input.at (Numbered tokens): Adjust the expected output. --- src/location.h | 24 ++++++++++++++++++++++++ src/symtab.c | 28 ++++++++++++++++++++++++---- src/uniqstr.h | 6 +++--- tests/input.at | 6 ++++-- 4 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/location.h b/src/location.h index a99232b..ec48164 100644 --- a/src/location.h +++ b/src/location.h @@ -55,6 +55,19 @@ boundary_set (boundary *b, const char *f, int l, int c) b->column = c; } +/* Return -1, 0, 1, depending whether a is before, equal, or + after b. */ +static inline int +boundary_cmp (boundary a, boundary b) +{ + int res = strcmp (a.file, b.file); + if (!res) + res = a.line - b.line; + if (!res) + res = a.column - b.column; + return res; +} + /* Return nonzero if A and B are equal boundaries. */ static inline bool equal_boundaries (boundary a, boundary b) @@ -87,6 +100,17 @@ void location_compute (location *loc, void location_print (FILE *out, location loc); +/* Return -1, 0, 1, depending whether a is before, equal, or + after b. */ +static inline int +location_cmp (location a, location b) +{ + int res = boundary_cmp (a.start, b.start); + if (!res) + res = boundary_cmp (a.end, b.end); + return res; +} + /* LOC_STR must be formatted as `file:line.column', it will be modified. */ void boundary_set_from_string (boundary *bound, char *loc_str); diff --git a/src/symtab.c b/src/symtab.c index c956e72..e68e473 100644 --- a/src/symtab.c +++ b/src/symtab.c @@ -193,6 +193,7 @@ semantic_type_redeclaration (semantic_type *s, const char *what, location first, } + /*-----------------------------------------------------------------. | Set the TYPE_NAME associated with SYM. Does nothing if passed 0 | | as TYPE_NAME. | @@ -582,7 +583,26 @@ symbol_pack_processor (void *this, void *null ATTRIBUTE_UNUSED) } +static void +user_token_number_redeclaration (int num, symbol *first, symbol *second) +{ + /* User token numbers are not assigned during the parsing, but in a + second step, via a (nondeterministic) traversal of the symbol + hash table. + Make errors deterministic: keep the first declaration first. */ + if (location_cmp (first->location, second->location) > 0) + { + symbol* tmp = first; + first = second; + second = tmp; + } + complain_at (second->location, + _("user token number %d redeclaration for %s"), + num, second->tag); + complain_at (first->location, _("previous declaration for %s"), + first->tag); +} /*--------------------------------------------------. | Put THIS in TOKEN_TRANSLATIONS if it is a token. | @@ -597,10 +617,10 @@ symbol_translation (symbol *this) { /* A token which translation has already been set? */ if (token_translations[this->user_token_number] != undeftoken->number) - complain_at (this->location, - _("tokens %s and %s both assigned number %d"), - symbols[token_translations[this->user_token_number]]->tag, - this->tag, this->user_token_number); + user_token_number_redeclaration + (this->user_token_number, + symbols[token_translations[this->user_token_number]], + this); token_translations[this->user_token_number] = this->number; } diff --git a/src/uniqstr.h b/src/uniqstr.h index c986df0..04600e9 100644 --- a/src/uniqstr.h +++ b/src/uniqstr.h @@ -1,6 +1,6 @@ /* Keeping a unique copy of strings. - Copyright (C) 2002, 2003, 2008 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2008, 2009 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -32,8 +32,8 @@ uniqstr uniqstr_new (char const *str); /* Two uniqstr values have the same value iff they are the same. */ #define UNIQSTR_EQ(USTR1, USTR2) ((USTR1) == (USTR2)) -/* Compare two uniqstr a la strlen: negative for <, nul for =, and - positive for >. */ +/* Compare two uniqstr a la strcmp: negative for <, nul for =, and + positive for >. Undefined order, relies on addresses. */ #define UNIQSTR_CMP(USTR1, USTR2) ((USTR1) - (USTR2)) /*--------------------------------------. diff --git a/tests/input.at b/tests/input.at index c43aeb1..6de0e1a 100644 --- a/tests/input.at +++ b/tests/input.at @@ -686,8 +686,10 @@ start: HEXADECIMAL_1 HEXADECIMAL_2 ]]) AT_BISON_CHECK([input.y], [1], [], -[[input.y:12.12-20: tokens HEXADECIMAL_2 and DECIMAL_2 both assigned number 16702650 -input.y:9.8-20: tokens DECIMAL_1 and HEXADECIMAL_1 both assigned number 11259375 +[[input.y:10.12-20: user token number 11259375 redeclaration for DECIMAL_1 +input.y:9.8-20: previous declaration for HEXADECIMAL_1 +input.y:12.12-20: user token number 16702650 redeclaration for DECIMAL_2 +input.y:11.8-20: previous declaration for HEXADECIMAL_2 ]]) AT_DATA_GRAMMAR([input.y], -- 1.6.3