From 29cbaca3c6c9bcc36d88a5da5a55f30d8faf8bc2 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Tue, 1 Sep 2015 14:21:41 -0400
Subject: [PATCH 36/58] C frontend: store and use token ranges in c_declspecs

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 +++++++-------
 3 files changed, 28 insertions(+), 25 deletions(-)

diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 39c961e..6eecde6 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -9468,7 +9468,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;
@@ -9491,7 +9491,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;
@@ -9534,7 +9534,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;
@@ -9772,7 +9772,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)
@@ -9998,7 +9998,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)
@@ -10282,7 +10282,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)
 {
@@ -10401,7 +10401,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;
@@ -10413,7 +10413,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 397131d..768909e 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1779,19 +1779,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))
@@ -1841,14 +1842,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);
 		}
 	    }
@@ -2262,7 +2264,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,
@@ -2283,7 +2285,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;
@@ -2329,7 +2331,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))
@@ -3718,7 +3720,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 c1a61c6..3e6be78 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -256,7 +256,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
@@ -547,19 +547,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 *);
 
-- 
1.8.5.3

