glcpp: Add support for "redefined macro" error.
Carefully avoiding printing any error when the new definition matches the existing definition. This fixes the recently-added 088-redefine-macro-legitimate.c and 089-redefine-macro-error.c tests as well as glsparsertest/preprocess1 in piglit.
This commit is contained in:
parent
105e2137d6
commit
3882cf2169
|
@ -63,6 +63,9 @@ _string_list_contains (string_list_t *list, const char *member, int *index);
|
|||
static int
|
||||
_string_list_length (string_list_t *list);
|
||||
|
||||
static int
|
||||
_string_list_equal (string_list_t *a, string_list_t *b);
|
||||
|
||||
static argument_list_t *
|
||||
_argument_list_create (void *ctx);
|
||||
|
||||
|
@ -95,6 +98,9 @@ _token_list_append (token_list_t *list, token_t *token);
|
|||
static void
|
||||
_token_list_append_list (token_list_t *list, token_list_t *tail);
|
||||
|
||||
static int
|
||||
_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b);
|
||||
|
||||
static active_list_t *
|
||||
_active_list_push (active_list_t *list,
|
||||
const char *identifier,
|
||||
|
@ -604,6 +610,31 @@ _string_list_length (string_list_t *list)
|
|||
return length;
|
||||
}
|
||||
|
||||
int
|
||||
_string_list_equal (string_list_t *a, string_list_t *b)
|
||||
{
|
||||
string_node_t *node_a, *node_b;
|
||||
|
||||
if (a == NULL && b == NULL)
|
||||
return 1;
|
||||
|
||||
if (a == NULL || b == NULL)
|
||||
return 0;
|
||||
|
||||
for (node_a = a->head, node_b = b->head;
|
||||
node_a && node_b;
|
||||
node_a = node_a->next, node_b = node_b->next)
|
||||
{
|
||||
if (strcmp (node_a->str, node_b->str))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Catch the case of lists being different lengths, (which
|
||||
* would cause the loop above to terminate after the shorter
|
||||
* list). */
|
||||
return node_a == node_b;
|
||||
}
|
||||
|
||||
argument_list_t *
|
||||
_argument_list_create (void *ctx)
|
||||
{
|
||||
|
@ -781,6 +812,61 @@ _token_list_trim_trailing_space (token_list_t *list)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b)
|
||||
{
|
||||
token_node_t *node_a, *node_b;
|
||||
|
||||
node_a = a->head;
|
||||
node_b = b->head;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (node_a == NULL && node_b == NULL)
|
||||
break;
|
||||
|
||||
if (node_a == NULL || node_b == NULL)
|
||||
return 0;
|
||||
|
||||
if (node_a->token->type == SPACE) {
|
||||
node_a = node_a->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node_b->token->type == SPACE) {
|
||||
node_b = node_b->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node_a->token->type != node_b->token->type)
|
||||
return 0;
|
||||
|
||||
switch (node_a->token->type) {
|
||||
case INTEGER:
|
||||
if (node_a->token->value.ival !=
|
||||
node_b->token->value.ival)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case IDENTIFIER:
|
||||
case INTEGER_STRING:
|
||||
case OTHER:
|
||||
if (strcmp (node_a->token->value.str,
|
||||
node_b->token->value.str))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
node_a = node_a->next;
|
||||
node_b = node_b->next;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
_token_print (char **out, token_t *token)
|
||||
{
|
||||
|
@ -1522,13 +1608,28 @@ _check_for_reserved_macro_name (glcpp_parser_t *parser, YYLTYPE *loc,
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
_macro_equal (macro_t *a, macro_t *b)
|
||||
{
|
||||
if (a->is_function != b->is_function)
|
||||
return 0;
|
||||
|
||||
if (a->is_function) {
|
||||
if (! _string_list_equal (a->parameters, b->parameters))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _token_list_equal_ignoring_space (a->replacements,
|
||||
b->replacements);
|
||||
}
|
||||
|
||||
void
|
||||
_define_object_macro (glcpp_parser_t *parser,
|
||||
YYLTYPE *loc,
|
||||
const char *identifier,
|
||||
token_list_t *replacements)
|
||||
{
|
||||
macro_t *macro;
|
||||
macro_t *macro, *previous;
|
||||
|
||||
if (loc != NULL)
|
||||
_check_for_reserved_macro_name(parser, loc, identifier);
|
||||
|
@ -1540,6 +1641,16 @@ _define_object_macro (glcpp_parser_t *parser,
|
|||
macro->identifier = talloc_strdup (macro, identifier);
|
||||
macro->replacements = talloc_steal (macro, replacements);
|
||||
|
||||
previous = hash_table_find (parser->defines, identifier);
|
||||
if (previous) {
|
||||
if (_macro_equal (macro, previous)) {
|
||||
talloc_free (macro);
|
||||
return;
|
||||
}
|
||||
glcpp_error (loc, parser, "Redefinition of macro %s\n",
|
||||
identifier);
|
||||
}
|
||||
|
||||
hash_table_insert (parser->defines, macro, identifier);
|
||||
}
|
||||
|
||||
|
@ -1550,7 +1661,7 @@ _define_function_macro (glcpp_parser_t *parser,
|
|||
string_list_t *parameters,
|
||||
token_list_t *replacements)
|
||||
{
|
||||
macro_t *macro;
|
||||
macro_t *macro, *previous;
|
||||
|
||||
_check_for_reserved_macro_name(parser, loc, identifier);
|
||||
|
||||
|
@ -1561,6 +1672,16 @@ _define_function_macro (glcpp_parser_t *parser,
|
|||
macro->identifier = talloc_strdup (macro, identifier);
|
||||
macro->replacements = talloc_steal (macro, replacements);
|
||||
|
||||
previous = hash_table_find (parser->defines, identifier);
|
||||
if (previous) {
|
||||
if (_macro_equal (macro, previous)) {
|
||||
talloc_free (macro);
|
||||
return;
|
||||
}
|
||||
glcpp_error (loc, parser, "Redefinition of macro %s\n",
|
||||
identifier);
|
||||
}
|
||||
|
||||
hash_table_insert (parser->defines, macro, identifier);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue