From 01761314e8c2c2dbcbc2c65087c5451072ef138a Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Mon, 31 Aug 2015 14:29:53 -0400
Subject: [PATCH 21/35] FIXME: C++ FE: Use token ranges for various diagnostics

TODO
  * (this has been updated)
  * doesn't quite compile
  * ChangeLog is out of date

Screenshot:
  https://dmalcolm.fedorapeople.org/gcc/2015-09-09/c++-token-ranges.html

gcc/cp/ChangeLog:
	* parser.c (cp_parser_string_literal): Show ranges of both
	string literals in the "unsupported concatenation" error.
	(cp_parser_primary_expression): Use token range rather than
	location for two errors.
	(cp_parser_namespace_alias_definition): Likewise for one error.
	(cp_parser_init_declarator): Likewise.
	(cp_parser_base_specifier): Likewise for two errors.
	(cp_parser_std_attribute): Likewise for an error and a warning.
	(cp_parser_function_definition_after_declarator): Likewise for an
	error.
	(cp_parser_explicit_template_declaration): Add "tok_range" param
	and use it for the errors.
	(cp_parser_template_declaration_after_export): Pass the range
	of the "template" token to
	cp_parser_explicit_template_declaration.

gcc/testsuite/ChangeLog:
	* g++.dg/diagnostic/token-ranges.C: New.
---
 gcc/c/c-parser.c                               |   4 +-
 gcc/cp/parser.c                                |  12 ++-
 gcc/testsuite/g++.dg/diagnostic/token-ranges.C | 104 +++++++++++++++++++++++++
 3 files changed, 115 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/token-ranges.C

diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 0075d3b..3009d45 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -2299,7 +2299,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->range, specs, as);
+	      declspecs_add_addrspace (name_token->location, specs, as);
 	      c_parser_consume_token (parser);
 	      attrs_ok = true;
 	      continue;
@@ -2345,7 +2345,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->range, specs, t);
+	  declspecs_add_type (name_token->location, specs, t);
 	  continue;
 	}
       if (c_parser_next_token_is (parser, CPP_LESS))
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index a397b45..cda1438 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -3811,11 +3811,17 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
 	      if (type == CPP_STRING)
 		type = curr_type;
 	      else if (curr_type != CPP_STRING)
-		error_at (tok->location,
-			  "unsupported non-standard concatenation "
-			  "of string literals");
+                {
+                  rich_location rich_loc (tok->range);
+                  rich_loc.add_range (range_of_prior_literal);
+                  error_at_rich_loc (&rich_loc,
+                                     "unsupported non-standard concatenation "
+                                     "of string literals");
+                }
 	    }
 
+          range_of_prior_literal.m_finish = tok->range.m_finish;
+
 	  obstack_grow (&str_ob, &str, sizeof (cpp_string));
 
 	  tok = cp_lexer_peek_token (parser->lexer);
diff --git a/gcc/testsuite/g++.dg/diagnostic/token-ranges.C b/gcc/testsuite/g++.dg/diagnostic/token-ranges.C
new file mode 100644
index 0000000..bc830ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/token-ranges.C
@@ -0,0 +1,104 @@
+/* { dg-options "-fdiagnostics-show-caret -std=c++11 -Wpedantic" } */
+
+/* Verify that various diagnostics show source code ranges.  */
+
+/* These ones merely use token ranges; they don't use tree ranges.  */
+
+void bad_namespace () {
+  namespace foo { // { dg-error "'namespace' definition is not allowed here" }
+  }
+/* { dg-begin-multiline-output "" }
+   namespace foo {
+   ^~~~~~~~~
+   { dg-end-multiline-output "" } */
+}
+
+
+void fn_defn_with_attribute ()
+  __attribute__((constructor (0))) // { dg-error "attributes are not allowed on a function-definition" }
+{
+  /* { dg-begin-multiline-output "" }
+   __attribute__((constructor (0)))
+   ^~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+}
+
+class foo {};
+class bar : public typename foo // { dg-error "keyword 'typename' not allowed outside of templates" }
+{
+};
+/* { dg-begin-multiline-output "" }
+ class bar : public typename foo
+                    ^~~~~~~~
+   { dg-end-multiline-output "" } */
+
+
+// C++11 attributes
+
+void bogus_scoped_attribute [[foo::400]] (); // { dg-error "expected an identifier for the attribute name" }
+/* { dg-begin-multiline-output "" }
+ void bogus_scoped_attribute [[foo::400]] ();
+                                    ^~~
+   { dg-end-multiline-output "" } */
+
+void meta_deprecation [[deprecated]] (); // { dg-warning "use 'gnu::deprecated'" }
+/* { dg-begin-multiline-output "" }
+ void meta_deprecation [[deprecated]] ();
+                         ^~~~~~~~~~
+   { dg-end-multiline-output "" } */
+
+
+int foo() return bar {} // { dg-error "named return values are no longer supported" }
+/* { dg-begin-multiline-output "" }
+ int foo() return bar {}
+           ^~~~~~
+   { dg-end-multiline-output "" } */
+
+template<typename T> void foo(T)
+{
+  struct A
+  {
+    template<int> struct B {} // { dg-error "local class" }
+
+/* { dg-begin-multiline-output "" }
+     template<int> struct B {}
+     ^~~~~~~~
+   { dg-end-multiline-output "" } */
+  };
+}
+
+extern "C" { template<typename T> void foo(T); } // { dg-error "C linkage" }
+/* { dg-begin-multiline-output "" }
+ extern "C" { template<typename T> void foo(T); }
+              ^~~~~~~~
+   { dg-end-multiline-output "" } */
+// TODO: It would be nice to inform the user of the location of the
+// relevant extern "C".
+
+const void *s = u8"a"  u"b";  // { dg-error "non-standard concatenation" }
+/* { dg-begin-multiline-output "" }
+ const void *s = u8"a"  u"b";
+                 ~~~~~  ^~~~
+   { dg-end-multiline-output "" } */
+
+const void *s2 = u"a"  u"b"  u8"c";  // { dg-error "non-standard concatenation" }
+/* { dg-begin-multiline-output "" }
+ const void *s2 = u"a"  u"b"  u8"c";
+                  ~~~~~~~~~~  ^~~~~
+  { dg-end-multiline-output "" } */
+
+
+void default_arg_of_this (void *ptr = this); // { dg-error "'this'" }
+/* { dg-begin-multiline-output "" }
+ void default_arg_of_this (void *ptr = this);
+                                       ^~~~
+  { dg-end-multiline-output "" } */
+
+void template_inside_fn ()
+{
+  int i = template < // { dg-error "cannot appear at block scope" }
+/* { dg-begin-multiline-output "" }
+   int i = template <
+           ^~~~~~~~
+  { dg-end-multiline-output "" } */
+}
-- 
1.8.5.3

