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.
This commit is contained in:
Akim Demaille
2009-06-03 23:15:38 +02:00
parent 796a2b0ab0
commit 12cf133f34
5 changed files with 67 additions and 9 deletions

View File

@@ -1,3 +1,15 @@
2009-06-10 Akim Demaille <demaille@gostai.com>
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.
2009-05-25 Akim Demaille <demaille@gostai.com> 2009-05-25 Akim Demaille <demaille@gostai.com>
build: avoid ignored errors. build: avoid ignored errors.

View File

@@ -55,6 +55,19 @@ boundary_set (boundary *b, const char *f, int l, int c)
b->column = 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. */ /* Return nonzero if A and B are equal boundaries. */
static inline bool static inline bool
equal_boundaries (boundary a, boundary b) equal_boundaries (boundary a, boundary b)
@@ -87,6 +100,17 @@ void location_compute (location *loc,
void location_print (FILE *out, 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. */ /* LOC_STR must be formatted as `file:line.column', it will be modified. */
void boundary_set_from_string (boundary *bound, char *loc_str); void boundary_set_from_string (boundary *bound, char *loc_str);

View File

@@ -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 | | Set the TYPE_NAME associated with SYM. Does nothing if passed 0 |
| as TYPE_NAME. | | 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. | | 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? */ /* A token which translation has already been set? */
if (token_translations[this->user_token_number] != undeftoken->number) if (token_translations[this->user_token_number] != undeftoken->number)
complain_at (this->location, user_token_number_redeclaration
_("tokens %s and %s both assigned number %d"), (this->user_token_number,
symbols[token_translations[this->user_token_number]]->tag, symbols[token_translations[this->user_token_number]],
this->tag, this->user_token_number); this);
token_translations[this->user_token_number] = this->number; token_translations[this->user_token_number] = this->number;
} }

View File

@@ -1,6 +1,6 @@
/* Keeping a unique copy of strings. /* 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. 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. */ /* Two uniqstr values have the same value iff they are the same. */
#define UNIQSTR_EQ(USTR1, USTR2) ((USTR1) == (USTR2)) #define UNIQSTR_EQ(USTR1, USTR2) ((USTR1) == (USTR2))
/* Compare two uniqstr a la strlen: negative for <, nul for =, and /* Compare two uniqstr a la strcmp: negative for <, nul for =, and
positive for >. */ positive for >. Undefined order, relies on addresses. */
#define UNIQSTR_CMP(USTR1, USTR2) ((USTR1) - (USTR2)) #define UNIQSTR_CMP(USTR1, USTR2) ((USTR1) - (USTR2))
/*--------------------------------------. /*--------------------------------------.

View File

@@ -686,8 +686,10 @@ start: HEXADECIMAL_1 HEXADECIMAL_2
]]) ]])
AT_BISON_CHECK([input.y], [1], [], AT_BISON_CHECK([input.y], [1], [],
[[input.y:12.12-20: tokens HEXADECIMAL_2 and DECIMAL_2 both assigned number 16702650 [[input.y:10.12-20: user token number 11259375 redeclaration for DECIMAL_1
input.y:9.8-20: tokens DECIMAL_1 and HEXADECIMAL_1 both assigned number 11259375 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], AT_DATA_GRAMMAR([input.y],