From 8ee5b53874f631bf6099e19fc6e13cbc47bc5fd8 Mon Sep 17 00:00:00 2001 From: "Joel E. Denny" Date: Mon, 26 Jun 2006 04:45:24 +0000 Subject: [PATCH] Don't miss %merge result type warnings just because the LHS types are declared after the %merge. * src/reader.c (get_merge_function): Don't set the merger type yet. (record_merge_function_type): New function for setting the merger type and checking for clashes. (grammar_current_rule_merge_set): Set the location of the %merge for the current rule. (packgram): Invoke record_merge_function_type for each rule now that all symbol type declarations have been parsed. * src/reader.h (merger_list.type_declaration_location): New member storing the location of the first %merge from which the type for this merging function was derived. * src/symlist.h (symbol_list.merger_declaration_location): New member storing the location of a rule's %merge, if any. * tests/glr-regression.at (Missed %merge type warnings when LHS type is declared later): New test to catch the error fixed by the above patch. --- ChangeLog | 19 ++++++++++++ src/reader.c | 66 +++++++++++++++++++++++++++++++---------- src/reader.h | 1 + src/symlist.h | 1 + tests/glr-regression.at | 55 ++++++++++++++++++++++++++++++++++ 5 files changed, 127 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3abf8f82..3b1fc915 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2006-06-26 Joel E. Denny + + Don't miss %merge result type warnings just because the LHS types are + declared after the %merge. + * src/reader.c (get_merge_function): Don't set the merger type yet. + (record_merge_function_type): New function for setting the merger type + and checking for clashes. + (grammar_current_rule_merge_set): Set the location of the %merge for + the current rule. + (packgram): Invoke record_merge_function_type for each rule now that + all symbol type declarations have been parsed. + * src/reader.h (merger_list.type_declaration_location): New member + storing the location of the first %merge from which the type for this + merging function was derived. + * src/symlist.h (symbol_list.merger_declaration_location): New member + storing the location of a rule's %merge, if any. + * tests/glr-regression.at (Missed %merge type warnings when LHS type is + declared later): New test to catch the error fixed by the above patch. + 2006-06-26 Joel E. Denny Get action warnings (grammar_rule_check) right even when symbol diff --git a/src/reader.c b/src/reader.c index 54d21c4e..31bd536d 100644 --- a/src/reader.c +++ b/src/reader.c @@ -90,14 +90,13 @@ prologue_augment (const char *prologue, location loc, bool post) -/*-------------------------------------------------------------------. -| Return the merger index for a merging function named NAME, whose | -| arguments have type TYPE. Records the function, if new, in | -| MERGER_LIST. | -`-------------------------------------------------------------------*/ +/*------------------------------------------------------------------------. +| Return the merger index for a merging function named NAME. Records the | +| function, if new, in MERGER_LIST. | +`------------------------------------------------------------------------*/ static int -get_merge_function (uniqstr name, uniqstr type, location loc) +get_merge_function (uniqstr name) { merger_list *syms; merger_list head; @@ -106,9 +105,6 @@ get_merge_function (uniqstr name, uniqstr type, location loc) if (! glr_parser) return 0; - if (type == NULL) - type = uniqstr_new (""); - head.next = merge_functions; for (syms = &head, n = 1; syms->next; syms = syms->next, n += 1) if (UNIQSTR_EQ (name, syms->next->name)) @@ -117,16 +113,54 @@ get_merge_function (uniqstr name, uniqstr type, location loc) { syms->next = xmalloc (sizeof syms->next[0]); syms->next->name = uniqstr_new (name); - syms->next->type = uniqstr_new (type); + /* After all symbol type declarations have been parsed, packgram invokes + record_merge_function_type to set the type. */ + syms->next->type = NULL; syms->next->next = NULL; merge_functions = head.next; } - else if (!UNIQSTR_EQ (type, syms->next->type)) - warn_at (loc, _("result type clash on merge function %s: <%s> != <%s>"), - name, type, syms->next->type); return n; } +/*-------------------------------------------------------------------------. +| For the existing merging function with index MERGER, record the result | +| type as TYPE as required by the lhs of the rule whose %merge declaration | +| is at DECLARATION_LOC. | +`-------------------------------------------------------------------------*/ + +static void +record_merge_function_type (int merger, uniqstr type, location declaration_loc) +{ + int merger_find; + merger_list *merge_function; + + if (merger <= 0) + return; + + if (type == NULL) + type = uniqstr_new (""); + + merger_find = 1; + for (merge_function = merge_functions; + merge_function != NULL && merger_find != merger; + merge_function = merge_function->next) + merger_find += 1; + assert (merge_function != NULL && merger_find == merger); + if (merge_function->type == NULL) + { + merge_function->type = uniqstr_new (type); + merge_function->type_declaration_location = declaration_loc; + } + else if (!UNIQSTR_EQ (merge_function->type, type)) + { + warn_at (declaration_loc, + _("result type clash on merge function `%s': <%s> != <%s>"), + merge_function->name, type, merge_function->type); + warn_at (merge_function->type_declaration_location, + _("first declaration")); + } +} + /*--------------------------------------. | Free all merge-function definitions. | `--------------------------------------*/ @@ -382,8 +416,8 @@ grammar_current_rule_merge_set (uniqstr name, location loc) warn_at (loc, _("%s affects only GLR parsers"), "%merge"); if (current_rule->merger != 0) complain_at (loc, _("only one %s allowed per rule"), "%merge"); - current_rule->merger = - get_merge_function (name, current_rule->sym->type_name, loc); + current_rule->merger = get_merge_function (name); + current_rule->merger_declaration_location = loc; } /* Attach SYM to the current rule. If needed, move the previous @@ -434,6 +468,8 @@ packgram (void) { int rule_length = 0; symbol *ruleprec = p->ruleprec; + record_merge_function_type (p->merger, p->sym->type_name, + p->merger_declaration_location); rules[ruleno].user_number = ruleno; rules[ruleno].number = ruleno; rules[ruleno].lhs = p->sym; diff --git a/src/reader.h b/src/reader.h index 7b2cbac6..52c059c4 100644 --- a/src/reader.h +++ b/src/reader.h @@ -33,6 +33,7 @@ typedef struct merger_list struct merger_list* next; uniqstr name; uniqstr type; + location type_declaration_location; } merger_list; /* From the parser. */ diff --git a/src/symlist.h b/src/symlist.h index 2b901999..a2272608 100644 --- a/src/symlist.h +++ b/src/symlist.h @@ -54,6 +54,7 @@ typedef struct symbol_list symbol *ruleprec; int dprec; int merger; + location merger_declaration_location; /* The list. */ struct symbol_list *next; diff --git a/tests/glr-regression.at b/tests/glr-regression.at index 598ab8e8..b4f65004 100644 --- a/tests/glr-regression.at +++ b/tests/glr-regression.at @@ -1661,3 +1661,58 @@ AT_CHECK([[./glr-regr17]], 0, [], ]) AT_CLEANUP + + +## -------------------------------------------------------------## +## Missed %merge type warnings when LHS type is declared later. ## +## -------------------------------------------------------------## + +AT_SETUP([Missed %merge type warnings when LHS type is declared later]) +AT_DATA_GRAMMAR([glr-regr18.y], +[[%glr-parser + +%{ + static void yyerror (char const *); + static int yylex (); +%} + +%union { + int type1; + int type2; +} + +%% + +sym1: sym2 %merge { $$ = $1; } ; +sym2: %merge { $$ = 0; } ; + +%type sym1; +%type sym2; + +%% + +static void +yyerror (char const *msg) +{ + fprintf (stderr, "%s\n", msg); +} + +static int +yylex () +{ + return 0; +} + +int +main (void) +{ + return yyparse (); +} +]]) + +AT_CHECK([[bison -o glr-regr18.c glr-regr18.y]], 0, [], +[glr-regr18.y:26.13-19: warning: result type clash on merge function `merge': != +glr-regr18.y:25.18-24: warning: first declaration +]) + +AT_CLEANUP -- 2.47.2