fixits: report duplicate %yacc directives

We should use -ffixit and --update to clean files with duplicate
directives.  And we should complain only once about duplicate obsolete
directives: keep only the "duplicate" warning.  Let's start with %yacc.

For instance on:

    %fixed-output_files
    %fixed-output-files
    %yacc
    %%
    exp:

This run of bison:

    $ bison /tmp/foo.y -u
    foo.y:1.1-19: warning: deprecated directive, use '%fixed-output-files' [-Wdeprecated]
     %fixed-output_files
     ^~~~~~~~~~~~~~~~~~~
    foo.y:2.1-19: warning: duplicate directive [-Wother]
     %fixed-output-files
     ^~~~~~~~~~~~~~~~~~~
    foo.y:1.1-19: previous declaration
     %fixed-output_files
     ^~~~~~~~~~~~~~~~~~~
    foo.y:3.1-5: warning: duplicate directive [-Wother]
     %yacc
     ^~~~~
    foo.y:1.1-19: previous declaration
     %fixed-output_files
     ^~~~~~~~~~~~~~~~~~~
    bison: file 'foo.y' was updated (backup: 'foo.y~')

gives:

    %fixed-output-files
    %%
    exp:

* src/location.h, src/location.c (location_empty): New.
* src/complain.h, src/complain.c (duplicate_directive): New.

* src/getargs.h, src/getargs.c (yacc_flag): Instead of a Boolean, be
the location of the definition.
Update dependencies.

* src/scan-gram.l (%yacc, %fixed-output-files): Move the handling of
its warnings to...
* src/parse-gram.y (do_yacc): This new function.

* tests/input.at (Deprecated Directives): Adjust expectations.
This commit is contained in:
Akim Demaille
2019-01-16 07:45:54 +01:00
parent 2c8fb4d126
commit b6b397b7f0
11 changed files with 73 additions and 21 deletions

View File

@@ -399,6 +399,19 @@ deprecated_directive (location const *loc, char const *old, char const *upd)
fixits_register (loc, upd);
}
void
duplicate_directive (char const *directive,
location first, location second)
{
if (feature_flag & feature_caret)
complain (&second, Wother, _("duplicate directive"));
else
complain (&second, Wother, _("duplicate directive: %s"), directive);
unsigned i = SUB_INDENT;
complain_indent (&first, complaint, &i, _("previous declaration"));
fixits_register (&second, "");
}
void
duplicate_rule_directive (char const *directive,
location first, location second)

View File

@@ -126,6 +126,10 @@ void bison_directive (location const *loc, char const *directive);
void deprecated_directive (location const *loc,
char const *obsolete, char const *updated);
/** Report a repeated directive. */
void duplicate_directive (char const *directive,
location first, location second);
/** Report a repeated directive for a rule. */
void duplicate_rule_directive (char const *directive,
location first, location second);

View File

@@ -285,7 +285,7 @@ compute_file_name_parts (void)
last_component (spec_file_prefix) - spec_file_prefix);
all_but_tab_ext = xstrdup (spec_file_prefix);
}
else if (yacc_flag)
else if (! location_empty (yacc_loc))
{
/* If --yacc, then the output is 'y.tab.c'. */
dir_prefix = xstrdup ("");
@@ -306,7 +306,7 @@ compute_file_name_parts (void)
all_but_ext = xstrdup (all_but_tab_ext);
/* Compute the extensions from the grammar file name. */
if (ext && !yacc_flag)
if (ext && location_empty (yacc_loc))
compute_exts_from_gf (ext);
}
}

View File

@@ -41,7 +41,7 @@ bool graph_flag = false;
bool xml_flag = false;
bool no_lines_flag = false;
bool token_table_flag = false;
bool yacc_flag = false; /* for -y */
location yacc_loc = EMPTY_LOCATION_INIT;
bool update_flag = false; /* for -u */
bool nondeterministic_parser = false;
@@ -709,7 +709,7 @@ getargs (int argc, char *argv[])
case 'y':
warning_argmatch ("error=yacc", 0, 6);
yacc_flag = true;
yacc_loc = command_line_location ();
break;
case LOCATIONS_OPTION:

View File

@@ -39,7 +39,7 @@ extern bool graph_flag; /* for -g */
extern bool xml_flag; /* for -x */
extern bool no_lines_flag; /* for -l */
extern bool token_table_flag; /* for -k */
extern bool yacc_flag; /* for -y */
extern location yacc_loc; /* for -y */
extern bool update_flag; /* for -u */
/* GLR_PARSER is true if the input file says to use the GLR

View File

@@ -216,6 +216,13 @@ location_caret (location loc, FILE *out)
}
}
bool
location_empty (location loc)
{
return !loc.start.file && !loc.start.line && !loc.start.column
&& !loc.end.file && !loc.end.line && !loc.end.column;
}
void
boundary_set_from_string (boundary *bound, char *loc_str)
{

View File

@@ -126,6 +126,9 @@ location_cmp (location a, location b)
return res;
}
/* Whether this is the empty location. */
bool location_empty (location loc);
/* LOC_STR must be formatted as 'file:line.column', it will be modified. */
void boundary_set_from_string (boundary *bound, char *loc_str);

View File

@@ -665,7 +665,7 @@ prepare (void)
MUSCLE_INSERT_BOOL ("tag_seen_flag", tag_seen);
MUSCLE_INSERT_BOOL ("token_table_flag", token_table_flag);
MUSCLE_INSERT_BOOL ("use_push_for_pull_flag", use_push_for_pull_flag);
MUSCLE_INSERT_BOOL ("yacc_flag", yacc_flag);
MUSCLE_INSERT_BOOL ("yacc_flag", !location_empty (yacc_loc));
/* File names. */
if (spec_name_prefix)

View File

@@ -95,6 +95,9 @@
/* Handle a %skeleton directive. */
static void do_skeleton (location const *loc, char const *skel);
/* Handle a %yacc directive. */
static void do_yacc (location const *loc, char const *directive);
static void gram_error (location const *, char const *);
/* A string that describes a char (e.g., 'a' -> "'a'"). */
@@ -201,8 +204,9 @@
%type <uniqstr>
BRACKETED_ID ID ID_COLON
PERCENT_ERROR_VERBOSE PERCENT_FLAG PERCENT_NAME_PREFIX TAG
tag tag.opt variable
PERCENT_ERROR_VERBOSE PERCENT_FLAG PERCENT_NAME_PREFIX
PERCENT_YACC
TAG tag tag.opt variable
%printer { fputs ($$, yyo); } <uniqstr>
%printer { fprintf (yyo, "[%s]", $$); } BRACKETED_ID
%printer { fprintf (yyo, "%s:", $$); } ID_COLON
@@ -329,7 +333,7 @@ prologue_declaration:
| "%skeleton" STRING { do_skeleton (&@2, $2); }
| "%token-table" { token_table_flag = true; }
| "%verbose" { report_flag |= report_states; }
| "%yacc" { yacc_flag = true; }
| "%yacc" { do_yacc (&@$, $1); }
| error ";" { current_class = unknown_sym; yyerrok; }
| /*FIXME: Err? What is this horror doing here? */ ";"
;
@@ -956,6 +960,25 @@ do_skeleton (location const *loc, char const *skel)
skeleton_arg (skeleton_user, grammar_prio, *loc);
}
static void
do_yacc (location const *loc, char const *directive)
{
bison_directive (loc, directive);
bool warned = false;
if (location_empty (yacc_loc))
yacc_loc = *loc;
else
{
duplicate_directive (directive, yacc_loc, *loc);
warned = true;
}
if (!warned
&& STRNEQ (directive, "%fixed-output-files")
&& STRNEQ (directive, "%yacc"))
deprecated_directive (loc, directive, "%fixed-output-files");
}
static void
gram_error (location const *loc, char const *msg)

View File

@@ -229,7 +229,7 @@ eqopt ({sp}=)?
"%expect" return BISON_DIRECTIVE (EXPECT);
"%expect-rr" return BISON_DIRECTIVE (EXPECT_RR);
"%file-prefix" return BISON_DIRECTIVE (FILE_PREFIX);
"%fixed-output-files" return BISON_DIRECTIVE (YACC);
"%fixed-output-files" RETURN_VALUE (PERCENT_YACC, uniqstr_new (yytext));
"%initial-action" return BISON_DIRECTIVE (INITIAL_ACTION);
"%glr-parser" return BISON_DIRECTIVE (GLR_PARSER);
"%language" return BISON_DIRECTIVE (LANGUAGE);
@@ -259,7 +259,7 @@ eqopt ({sp}=)?
"%type" return PERCENT_TYPE;
"%union" return PERCENT_UNION;
"%verbose" return BISON_DIRECTIVE (VERBOSE);
"%yacc" return BISON_DIRECTIVE (YACC);
"%yacc" RETURN_VALUE (PERCENT_YACC, uniqstr_new (yytext));
/* Deprecated since Bison 3.0 (2013-07-25), but the warning is
issued only since Bison 3.3. */
@@ -274,7 +274,7 @@ eqopt ({sp}=)?
"%error"[-_]"verbose" RETURN_VALUE (PERCENT_ERROR_VERBOSE, uniqstr_new (yytext));
"%expect"[-_]"rr" DEPRECATED ("%expect-rr");
"%file-prefix"{eqopt} DEPRECATED ("%file-prefix");
"%fixed"[-_]"output"[-_]"files" DEPRECATED ("%fixed-output-files");
"%fixed"[-_]"output"[-_]"files" RETURN_VALUE (PERCENT_YACC, uniqstr_new (yytext));
"%no"[-_]"default"[-_]"prec" DEPRECATED ("%no-default-prec");
"%no"[-_]"lines" DEPRECATED ("%no-lines");
"%output"{eqopt} DEPRECATED ("%output");