On Tue, 2018-12-11 at 10:35 -0500, David Malcolm wrote:
> On Mon, 2018-12-10 at 22:47 +0000, Segher Boessenkool wrote:
> 
> [...]
> 
> > diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
> > index 121a91c..652e53c 100644
> > --- a/gcc/c/c-parser.c
> > +++ b/gcc/c/c-parser.c
> > @@ -6360,41 +6360,54 @@ c_parser_for_statement (c_parser *parser,
> > bool ivdep, unsigned short unroll,
> >  static tree
> >  c_parser_asm_statement (c_parser *parser)
> >  {
> > -  tree quals, str, outputs, inputs, clobbers, labels, ret;
> > -  bool simple, is_volatile, is_inline, is_goto;
> > +  tree str, outputs, inputs, clobbers, labels, ret;
> > +  bool simple;
> >    location_t asm_loc = c_parser_peek_token (parser)->location;
> >    int section, nsections;
> >  
> >    gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
> >    c_parser_consume_token (parser);
> >  
> > -  quals = NULL_TREE;
> > -  is_volatile = false;
> > -  is_inline = false;
> > -  is_goto = false;
> > +  /* Handle the asm-qualifier-list.  */
> > +  location_t volatile_loc = UNKNOWN_LOCATION;
> > +  location_t inline_loc = UNKNOWN_LOCATION;
> > +  location_t goto_loc = UNKNOWN_LOCATION;
> >    for (;;)
> >      {
> > -      switch (c_parser_peek_token (parser)->keyword)
> > +      c_token *token = c_parser_peek_token (parser);
> > +      location_t loc = token->location;
> > +      switch (token->keyword)
> >     {
> >     case RID_VOLATILE:
> > -     if (is_volatile)
> > -       break;
> > -     is_volatile = true;
> > -     quals = c_parser_peek_token (parser)->value;
> > +     if (volatile_loc)
> > +       {
> > +         error_at (loc, "duplicate asm qualifier %qE", token-
> > > value);
> > 
> > +         inform (volatile_loc, "first seen here");
> > +       }
> 
> Thanks for the improvements.
> 
> Is there test coverage for these errors and notes?
> 
> A diagnostic nit (new with gcc 9): please add an:
>     auto_diagnostic_group d;
> to the start of the guarded block, so that the "error" and "note" are
> known to be related.
> 
> See:  
> https://gcc.gnu.org/onlinedocs/gccint/Guidelines-for-Diagnostics.html
> #Group-logically-related-diagnostics

For bonus points, these could offer fix-it hints, so that an IDE can
offer to delete the duplicate qualifier token.  The above code could
be:

  if (volatile_loc)
    complain_about_duplicate_asm_qualifier (token->value, loc,
                                            volatile_loc);
  else
    volatile_loc = loc;


void
complain_about_duplicate_asm_qualifier (tree value,
                                        location_t duplicate_loc,
                                        location_t first_loc)
{
   auto_diagnostic_group d;
   gcc_rich_location richloc (duplicate_loc);
   richloc.add_fixit_remove ();
   error_at (&richloc, "duplicate asm qualifier %qE", value);
   inform (first_loc, "first seen here");
}

or somesuch, where rich_location::add_fixit_remove adds a fix-it hint
suggesting the removal of all of "loc", the duplicate token; given that
it's 5 lines at this point, a subroutine seems justified, to eliminate
duplication at the 6 sites it's done.

Caveat: haven't tried to compile the above.

Dave


> > +     else
> > +       volatile_loc = loc;
> >       c_parser_consume_token (parser);
> >       continue;
> >  
> >     case RID_INLINE:
> > -     if (is_inline)
> > -       break;
> > -     is_inline = true;
> > +     if (inline_loc)
> > +       {
> > +         error_at (loc, "duplicate asm qualifier %qE", token-
> > > value);
> > 
> > +         inform (inline_loc, "first seen here");
> 
> Likewise.
> 
> > +       }
> > +     else
> > +       inline_loc = loc;
> >       c_parser_consume_token (parser);
> >       continue;
> >  
> >     case RID_GOTO:
> > -     if (is_goto)
> > -       break;
> > -     is_goto = true;
> > +     if (goto_loc)
> > +       {
> > +         error_at (loc, "duplicate asm qualifier %qE", token-
> > > value);
> > 
> > +         inform (goto_loc, "first seen here");
> > +       }
> 
> Likewise.
> 
> > +     else
> > +       goto_loc = loc;
> >       c_parser_consume_token (parser);
> >       continue;
> 
> [...]
>  
> > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> > index 1cc34ba..06a6bb0 100644
> > --- a/gcc/cp/parser.c
> > +++ b/gcc/cp/parser.c
> > @@ -19649,29 +19646,50 @@ cp_parser_asm_definition (cp_parser*
> > parser)
> >      }
> >  
> >    /* Handle the asm-qualifier-list.  */
> > +  location_t volatile_loc = UNKNOWN_LOCATION;
> > +  location_t inline_loc = UNKNOWN_LOCATION;
> > +  location_t goto_loc = UNKNOWN_LOCATION;
> >    if (cp_parser_allow_gnu_extensions_p (parser))
> >      for (;;)
> >        {
> > +   cp_token *token = cp_lexer_peek_token (parser->lexer);
> > +   location_t loc = token->location;
> >     switch (cp_lexer_peek_token (parser->lexer)->keyword)
> >       {
> >       case RID_VOLATILE:
> > -       if (volatile_p)
> > -         break;
> > -       volatile_p = true;
> > +       if (volatile_loc)
> > +         {
> > +           error_at (loc, "duplicate asm qualifier %qT",
> > token-
> > > u.value);
> > 
> > +           inform (volatile_loc, "first seen here");
> 
> Likewise.
> 
> > +         }
> > +       else
> > +         volatile_loc = loc;
> >         cp_lexer_consume_token (parser->lexer);
> >         continue;
> >  
> >       case RID_INLINE:
> > -       if (inline_p || !parser->in_function_body)
> > +       if (!parser->in_function_body)
> >           break;
> > -       inline_p = true;
> > +       if (inline_loc)
> > +         {
> > +           error_at (loc, "duplicate asm qualifier %qT",
> > token-
> > > u.value);
> > 
> > +           inform (inline_loc, "first seen here");
> 
> Likewise.
> 
> > +         }
> > +       else
> > +         inline_loc = loc;
> >         cp_lexer_consume_token (parser->lexer);
> >         continue;
> >  
> >       case RID_GOTO:
> > -       if (goto_p || !parser->in_function_body)
> > +       if (!parser->in_function_body)
> >           break;
> > -       goto_p = true;
> > +       if (goto_loc)
> > +         {
> > +           error_at (loc, "duplicate asm qualifier %qT",
> > token-
> > > u.value);
> > 
> > +           inform (goto_loc, "first seen here");
> 
> Likewise.
> 
> > +         }
> > +       else
> > +         goto_loc = loc;
> >         cp_lexer_consume_token (parser->lexer);
> >         continue;
> >  
> 
> [...]
> 
> 
> Dave

Reply via email to