diff mbox

[09/22] C frontend: store and use token ranges in c_declspecs

Message ID 1441916913-11547-10-git-send-email-dmalcolm@redhat.com
State New
Headers show

Commit Message

David Malcolm Sept. 10, 2015, 8:28 p.m. UTC
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 mbox

Patch

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 "" } */