This patch replaces the source_location in c_declspecs with
a source_range, and uses it for various diagnostics to gain
underlines.

Screenshot:
 https://dmalcolm.fedorapeople.org/gcc/2015-09-09/bad-c-decls.html

gcc/c/ChangeLog:
        * c-decl.c (declspecs_add_addrspace): Convert param 1 from
        source_location to source_range.
        (declspecs_add_qual): Likewise.
        (declspecs_add_type): Likewise.
        (declspecs_add_scspec): Likewise.
        (declspecs_add_attrs): Likewise.
        (declspecs_add_alignas): Likewise.
        * c-parser.c (c_parser_declaration_or_fndef): Likewise for local
        "init_loc".
        (c_parser_declspecs): Likewise for local "loc", and for calls
        to declspecs_add_addrspace and declspecs_add_type.
        * c-tree.h (struct c_declspecs): Convert elements of "locations"
        array from source_location to source_range.
        (declspecs_add_qual): Convert param 1 from source_location to
        source_range.
        (declspecs_add_type): Likewise.
        (declspecs_add_scspec): Likewise.
        (declspecs_add_attrs): Likewise.
        (declspecs_add_addrspace): Likewise.
        (declspecs_add_alignas): Likewise.

gcc/testsuite/ChangeLog:
        * gcc.dg/diagnostic-token-ranges.c: Add tests of various
        kinds of bad declaration.
---
 gcc/c/c-decl.c                                 | 16 ++++++++--------
 gcc/c/c-parser.c                               | 23 +++++++++++++----------
 gcc/c/c-tree.h                                 | 14 +++++++-------
 gcc/testsuite/gcc.dg/diagnostic-token-ranges.c | 26 ++++++++++++++++++++++++++
 4 files changed, 54 insertions(+), 25 deletions(-)

diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 9fe8aa4..b7f0241 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -9443,7 +9443,7 @@ build_null_declspecs (void)
    SPECS, returning SPECS.  */
 
 struct c_declspecs *
-declspecs_add_addrspace (source_location location,
+declspecs_add_addrspace (source_range location,
                         struct c_declspecs *specs, addr_space_t as)
 {
   specs->non_sc_seen_p = true;
@@ -9466,7 +9466,7 @@ declspecs_add_addrspace (source_location location,
    returning SPECS.  */
 
 struct c_declspecs *
-declspecs_add_qual (source_location loc,
+declspecs_add_qual (source_range loc,
                    struct c_declspecs *specs, tree qual)
 {
   enum rid i;
@@ -9509,7 +9509,7 @@ declspecs_add_qual (source_location loc,
    returning SPECS.  */
 
 struct c_declspecs *
-declspecs_add_type (location_t loc, struct c_declspecs *specs,
+declspecs_add_type (source_range loc, struct c_declspecs *specs,
                    struct c_typespec spec)
 {
   tree type = spec.spec;
@@ -9747,7 +9747,7 @@ declspecs_add_type (location_t loc, struct c_declspecs 
*specs,
              break;
            case RID_COMPLEX:
              dupe = specs->complex_p;
-             if (!in_system_header_at (loc))
+             if (!in_system_header_at (loc.m_start))
                pedwarn_c90 (loc, OPT_Wpedantic,
                             "ISO C90 does not support complex types");
              if (specs->typespec_word == cts_auto_type)
@@ -9973,7 +9973,7 @@ declspecs_add_type (location_t loc, struct c_declspecs 
*specs,
                }
              return specs;
            case RID_BOOL:
-             if (!in_system_header_at (loc))
+             if (!in_system_header_at (loc.m_start))
                pedwarn_c90 (loc, OPT_Wpedantic,
                             "ISO C90 does not support boolean types");
              if (specs->long_p)
@@ -10257,7 +10257,7 @@ declspecs_add_type (location_t loc, struct c_declspecs 
*specs,
    declaration specifiers SPECS, returning SPECS.  */
 
 struct c_declspecs *
-declspecs_add_scspec (source_location loc,
+declspecs_add_scspec (source_range loc,
                      struct c_declspecs *specs,
                      tree scspec)
 {
@@ -10376,7 +10376,7 @@ declspecs_add_scspec (source_location loc,
    returning SPECS.  */
 
 struct c_declspecs *
-declspecs_add_attrs (source_location loc, struct c_declspecs *specs, tree 
attrs)
+declspecs_add_attrs (source_range loc, struct c_declspecs *specs, tree attrs)
 {
   specs->attrs = chainon (attrs, specs->attrs);
   specs->locations[cdw_attributes] = loc;
@@ -10388,7 +10388,7 @@ declspecs_add_attrs (source_location loc, struct 
c_declspecs *specs, tree attrs)
    alignment is ALIGN) to the declaration specifiers SPECS, returning
    SPECS.  */
 struct c_declspecs *
-declspecs_add_alignas (source_location loc,
+declspecs_add_alignas (source_range loc,
                       struct c_declspecs *specs, tree align)
 {
   int align_log;
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 1c93d39..6e6464b 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1746,19 +1746,20 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
fndef_ok,
            {
              tree d;
              struct c_expr init;
-             location_t init_loc;
+             source_range init_loc;
              c_parser_consume_token (parser);
              if (auto_type_p)
                {
                  start_init (NULL_TREE, asm_name, global_bindings_p ());
-                 init_loc = c_parser_peek_token (parser)->location;
+                 init_loc = c_parser_peek_token (parser)->range;
                  init = c_parser_expr_no_commas (parser, NULL);
                  if (TREE_CODE (init.value) == COMPONENT_REF
                      && DECL_C_BIT_FIELD (TREE_OPERAND (init.value, 1)))
                    error_at (here,
                              "%<__auto_type%> used with a bit-field"
                              " initializer");
-                 init = convert_lvalue_to_rvalue (init_loc, init, true, true);
+                 init = convert_lvalue_to_rvalue (init_loc.m_start, init,
+                                                  true, true);
                  tree init_type = TREE_TYPE (init.value);
                  /* As with typeof, remove all qualifiers from atomic types.  
*/
                  if (init_type != error_mark_node && TYPE_ATOMIC (init_type))
@@ -1808,14 +1809,15 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
fndef_ok,
                    c_finish_omp_declare_simd (parser, d, NULL_TREE,
                                               omp_declare_simd_clauses);
                  start_init (d, asm_name, global_bindings_p ());
-                 init_loc = c_parser_peek_token (parser)->location;
+                 init_loc = c_parser_peek_token (parser)->range;
                  init = c_parser_initializer (parser);
                  finish_init ();
                }
              if (d != error_mark_node)
                {
-                 maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
-                 finish_decl (d, init_loc, init.value,
+                 maybe_warn_string_init (init_loc.m_start, TREE_TYPE (d),
+                                         init);
+                 finish_decl (d, init_loc.m_start, init.value,
                               init.original_type, asm_name);
                }
            }
@@ -2228,7 +2230,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs 
*specs,
       struct c_typespec t;
       tree attrs;
       tree align;
-      location_t loc = c_parser_peek_token (parser)->location;
+      source_range loc = c_parser_peek_token (parser)->range;
 
       /* If we cannot accept a type, exit if the next token must start
         one.  Also, if we already have seen a tagged definition,
@@ -2249,7 +2251,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs 
*specs,
            {
              addr_space_t as
                = name_token->keyword - RID_FIRST_ADDR_SPACE;
-             declspecs_add_addrspace (name_token->location, specs, as);
+             declspecs_add_addrspace (name_token->range, specs, as);
              c_parser_consume_token (parser);
              attrs_ok = true;
              continue;
@@ -2295,7 +2297,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs 
*specs,
            }
          t.expr = NULL_TREE;
          t.expr_const_operands = true;
-         declspecs_add_type (name_token->location, specs, t);
+         declspecs_add_type (name_token->range, specs, t);
          continue;
        }
       if (c_parser_next_token_is (parser, CPP_LESS))
@@ -3684,7 +3686,8 @@ c_parser_parameter_declaration (c_parser *parser, tree 
attrs)
   specs = build_null_declspecs ();
   if (attrs)
     {
-      declspecs_add_attrs (input_location, specs, attrs);
+      declspecs_add_attrs (source_range::from_location (input_location),
+                          specs, attrs);
       attrs = NULL_TREE;
     }
   c_parser_declspecs (parser, specs, true, true, true, true, false,
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 4b0ec22..0810a74 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -253,7 +253,7 @@ enum c_declspec_word {
    specifier is added, please update the enum c_declspec_word above
    accordingly.  */
 struct c_declspecs {
-  source_location locations[cdw_number_of_elements];
+  source_range locations[cdw_number_of_elements];
   /* The type specified, if a single type specifier such as a struct,
      union or enum specifier, typedef name or typeof specifies the
      whole type, or NULL_TREE if none or a keyword such as "void" or
@@ -544,19 +544,19 @@ extern struct c_declarator *build_id_declarator (tree);
 extern struct c_declarator *make_pointer_declarator (struct c_declspecs *,
                                                     struct c_declarator *);
 extern struct c_declspecs *build_null_declspecs (void);
-extern struct c_declspecs *declspecs_add_qual (source_location,
+extern struct c_declspecs *declspecs_add_qual (source_range,
                                               struct c_declspecs *, tree);
-extern struct c_declspecs *declspecs_add_type (location_t,
+extern struct c_declspecs *declspecs_add_type (source_range,
                                               struct c_declspecs *,
                                               struct c_typespec);
-extern struct c_declspecs *declspecs_add_scspec (source_location,
+extern struct c_declspecs *declspecs_add_scspec (source_range,
                                                 struct c_declspecs *, tree);
-extern struct c_declspecs *declspecs_add_attrs (source_location,
+extern struct c_declspecs *declspecs_add_attrs (source_range,
                                                struct c_declspecs *, tree);
-extern struct c_declspecs *declspecs_add_addrspace (source_location,
+extern struct c_declspecs *declspecs_add_addrspace (source_range,
                                                    struct c_declspecs *,
                                                    addr_space_t);
-extern struct c_declspecs *declspecs_add_alignas (source_location,
+extern struct c_declspecs *declspecs_add_alignas (source_range,
                                                  struct c_declspecs *, tree);
 extern struct c_declspecs *finish_declspecs (struct c_declspecs *);
 
diff --git a/gcc/testsuite/gcc.dg/diagnostic-token-ranges.c 
b/gcc/testsuite/gcc.dg/diagnostic-token-ranges.c
index 6bd9e0b..5f00563 100644
--- a/gcc/testsuite/gcc.dg/diagnostic-token-ranges.c
+++ b/gcc/testsuite/gcc.dg/diagnostic-token-ranges.c
@@ -107,3 +107,29 @@ void break_and_continue_in_wrong_places (void)
      ^~~~~~~~
     { dg-end-multiline-output "" } */
 }
+
+/* Various examples of bad type decls.  */
+
+int float bogus; /* { dg-error "two or more data types in declaration 
specifiers" } */
+/* { dg-begin-multiline-output "" }
+ int float bogus;
+     ^~~~~
+    { dg-end-multiline-output "" } */
+
+long long long bogus2; /* { dg-error "'long long long' is too long for GCC" } 
*/
+/* { dg-begin-multiline-output "" }
+ long long long bogus2;
+           ^~~~
+    { dg-end-multiline-output "" } */
+
+long short bogus3; /* { dg-error "both 'long' and 'short' in declaration 
specifiers" } */
+/* { dg-begin-multiline-output "" }
+ long short bogus3;
+      ^~~~~
+    { dg-end-multiline-output "" } */
+
+signed unsigned bogus4; /* { dg-error "both 'signed' and 'unsigned' in 
declaration specifiers" } */
+/* { dg-begin-multiline-output "" }
+ signed unsigned bogus4;
+        ^~~~~~~~
+    { dg-end-multiline-output "" } */
-- 
1.8.5.3

Reply via email to