c/c++, asm: Use nicer error for duplicate asm qualifiers
authorSegher Boessenkool <segher@kernel.crashing.org>
Wed, 19 Dec 2018 16:12:17 +0000 (17:12 +0100)
committerSegher Boessenkool <segher@gcc.gnu.org>
Wed, 19 Dec 2018 16:12:17 +0000 (17:12 +0100)
Also as suggested by Jason.

c/
* c-parser.c (c_parser_asm_statement): Keep track of the location each
asm qualifier is first seen; use that to give nicer "duplicate asm
qualifier" messages.  Delete 'quals" variable, instead pass the
"is_volatile_ flag to build_asm_stmt directly.
* c-tree.h (build_asm_stmt): Make the first arg bool instead of tree.
* c-typeck.c (build_asm_stmt): Ditto; adjust.

cp/
* parser.c (cp_parser_asm_definition): Rewrite the loop to work without
"done" boolean variable.
* parser.c (cp_parser_asm_definition): Keep track of the location each
asm qualifier is first seen; use that to give nicer "duplicate asm
qualifier" messages.

From-SVN: r267278

gcc/c/ChangeLog
gcc/c/c-parser.c
gcc/c/c-tree.h
gcc/c/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/parser.c

index d1beffaac6241be870e299c6ba5c6a25f942e1d0..52b2c65ce8157716b98c78ab53ca75c2a8b9743f 100644 (file)
@@ -1,3 +1,12 @@
+2018-12-19  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * c-parser.c (c_parser_asm_statement): Keep track of the location each
+       asm qualifier is first seen; use that to give nicer "duplicate asm
+       qualifier" messages.  Delete 'quals" variable, instead pass the
+       "is_volatile_ flag to build_asm_stmt directly.
+       * c-tree.h (build_asm_stmt): Make the first arg bool instead of tree.
+       * c-typeck.c (build_asm_stmt): Ditto; adjust.
+
 2018-12-19  Segher Boessenkool  <segher@kernel.crashing.org>
 
        * c-parser.c (c_parser_asm_statement): Rewrite the loop to work without
index 835c0d8b879b5ea9534e946d0a5858eb7dac98ad..652e53ca0258beb56b78b996be25ea036f863136 100644 (file)
@@ -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");
+           }
+         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");
+           }
+         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");
+           }
+         else
+           goto_loc = loc;
          c_parser_consume_token (parser);
          continue;
 
@@ -6404,6 +6417,10 @@ c_parser_asm_statement (c_parser *parser)
       break;
     }
 
+  bool is_volatile = (volatile_loc != UNKNOWN_LOCATION);
+  bool is_inline = (inline_loc != UNKNOWN_LOCATION);
+  bool is_goto = (goto_loc != UNKNOWN_LOCATION);
+
   /* ??? Follow the C++ parser rather than using the
      lex_untranslated_string kludge.  */
   parser->lex_untranslated_string = true;
@@ -6478,9 +6495,9 @@ c_parser_asm_statement (c_parser *parser)
   if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
     c_parser_skip_to_end_of_block_or_statement (parser);
 
-  ret = build_asm_stmt (quals, build_asm_expr (asm_loc, str, outputs, inputs,
-                                              clobbers, labels, simple,
-                                              is_inline));
+  ret = build_asm_stmt (is_volatile,
+                       build_asm_expr (asm_loc, str, outputs, inputs,
+                                       clobbers, labels, simple, is_inline));
 
  error:
   parser->lex_untranslated_string = false;
index f08a8fc8bcc4c8f62fe525151b7768f514aa7a83..dc9e3cd587dd28b125c38ee5df63ec36efeac08a 100644 (file)
@@ -679,7 +679,7 @@ extern tree c_start_case (location_t, location_t, tree, bool);
 extern void c_finish_case (tree, tree);
 extern tree build_asm_expr (location_t, tree, tree, tree, tree, tree, bool,
                            bool);
-extern tree build_asm_stmt (tree, tree);
+extern tree build_asm_stmt (bool, tree);
 extern int c_types_compatible_p (tree, tree);
 extern tree c_begin_compound_stmt (bool);
 extern tree c_end_compound_stmt (location_t, tree, bool);
index 72ecd46cea63b00661628848284eee91c7661ea2..1ae5ede81e603f61c0fbf0fad6893df1a0f0cbc4 100644 (file)
@@ -10316,9 +10316,9 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
    (guaranteed to be 'volatile' or null) and ARGS (represented using
    an ASM_EXPR node).  */
 tree
-build_asm_stmt (tree cv_qualifier, tree args)
+build_asm_stmt (bool is_volatile, tree args)
 {
-  if (!ASM_VOLATILE_P (args) && cv_qualifier)
+  if (is_volatile)
     ASM_VOLATILE_P (args) = 1;
   return add_stmt (args);
 }
index 44ac2a96ff0291f4bd5469e9a84250a5568826d6..eb54a5250dc3575af59fd934558d57c11652eee8 100644 (file)
@@ -1,3 +1,11 @@
+2018-12-19  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * parser.c (cp_parser_asm_definition): Rewrite the loop to work without
+       "done" boolean variable.
+       * parser.c (cp_parser_asm_definition): Keep track of the location each
+       asm qualifier is first seen; use that to give nicer "duplicate asm
+       qualifier" messages.
+
 2018-12-19  Segher Boessenkool  <segher@kernel.crashing.org>
 
        * parser.c (cp_parser_asm_definition): Rewrite the loop to work without
index 0e4716ff0d5e86b7ae0bdfea9eb2da42d63b1651..b860fc4d2dc88066df8a26058fe56ee3b026c8e8 100644 (file)
@@ -19680,12 +19680,9 @@ cp_parser_asm_definition (cp_parser* parser)
   tree clobbers = NULL_TREE;
   tree labels = NULL_TREE;
   tree asm_stmt;
-  bool volatile_p = false;
   bool extended_p = false;
   bool invalid_inputs_p = false;
   bool invalid_outputs_p = false;
-  bool inline_p = false;
-  bool goto_p = false;
   required_token missing = RT_NONE;
 
   /* Look for the `asm' keyword.  */
@@ -19699,29 +19696,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");
+             }
+           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");
+             }
+           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");
+             }
+           else
+             goto_loc = loc;
            cp_lexer_consume_token (parser->lexer);
            continue;
 
@@ -19731,6 +19749,10 @@ cp_parser_asm_definition (cp_parser* parser)
        break;
       }
 
+  bool volatile_p = (volatile_loc != UNKNOWN_LOCATION);
+  bool inline_p = (inline_loc != UNKNOWN_LOCATION);
+  bool goto_p = (goto_loc != UNKNOWN_LOCATION);
+
   /* Look for the opening `('.  */
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return;
@@ -19822,8 +19844,7 @@ cp_parser_asm_definition (cp_parser* parser)
                                             CPP_CLOSE_PAREN))
            clobbers = cp_parser_asm_clobber_list (parser);
        }
-      else if (goto_p
-              && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
+      else if (goto_p && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
        /* The labels are coming next.  */
        labels_p = true;