We can use rich_location and the new diagnostic_show_locus to print
both locations when complaining about a bogus string concatenation
in the C++ FE, giving e.g.:

test.C:3:24: error: unsupported non-standard concatenation of string literals
 const void *s = u8"a"  u"b";
                 ~~~~~  ^~~~

Earlier versions of this were posted as part of
  https://gcc.gnu.org/ml/gcc-patches/2015-09/msg00730.html
    "[PATCH 10/22] C++ FE: Use token ranges for various diagnostics"
and:
  https://gcc.gnu.org/ml/gcc-patches/2015-12/msg01497.html
though the implementation has changed slightly.

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu;
adds 7 PASS results to g++.sum.

OK for trunk?

gcc/cp/ChangeLog:
        * parser.c (cp_parser_string_literal): Convert non-standard
        concatenation error to directly use a rich_location, and
        use that to add the location of the first literal to the
        diagnostic.

gcc/testsuite/ChangeLog:
        * g++.dg/diagnostic/string-literal-concat.C: New test case.
---
 gcc/cp/parser.c                                    | 15 +++++++++-----
 .../g++.dg/diagnostic/string-literal-concat.C      | 23 ++++++++++++++++++++++
 2 files changed, 33 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/string-literal-concat.C

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 632b25f..e1e9271 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -3893,13 +3893,12 @@ cp_parser_string_literal (cp_parser *parser, bool 
translate, bool wide_ok,
     }
   else
     {
-      location_t last_tok_loc;
+      location_t last_tok_loc = tok->location;
       gcc_obstack_init (&str_ob);
       count = 0;
 
       do
        {
-         last_tok_loc = tok->location;
          cp_lexer_consume_token (parser->lexer);
          count++;
          str.text = (const unsigned char *)TREE_STRING_POINTER (string_tree);
@@ -3931,13 +3930,19 @@ 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 (line_table, tok->location);
+                 rich_loc.add_range (last_tok_loc, false);
+                 error_at_rich_loc (&rich_loc,
+                                    "unsupported non-standard concatenation "
+                                    "of string literals");
+               }
            }
 
          obstack_grow (&str_ob, &str, sizeof (cpp_string));
 
+         last_tok_loc = tok->location;
+
          tok = cp_lexer_peek_token (parser->lexer);
          if (cpp_userdef_string_p (tok->type))
            {
diff --git a/gcc/testsuite/g++.dg/diagnostic/string-literal-concat.C 
b/gcc/testsuite/g++.dg/diagnostic/string-literal-concat.C
new file mode 100644
index 0000000..4ede799
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/string-literal-concat.C
@@ -0,0 +1,23 @@
+/* { dg-options "-fdiagnostics-show-caret -std=c++11" } */
+
+const void *s = u8"a"  u"b";  // { dg-error "24: 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 "30: non-standard 
concatenation" }
+/* { dg-begin-multiline-output "" }
+ const void *s2 = u"a"  u"b"  u8"c";
+                        ~~~~  ^~~~~
+  { dg-end-multiline-output "" } */
+
+#define TEST_U8_LITERAL u8"a"
+
+const void *s3 = TEST_U8_LITERAL u8"b";
+
+const void *s4 = TEST_U8_LITERAL u"b"; // { dg-error "34: non-standard 
concatenation" }
+/* { dg-begin-multiline-output "" }
+ const void *s4 = TEST_U8_LITERAL u"b";
+                                  ^~~~
+  { dg-end-multiline-output "" } */
-- 
1.8.5.3

Reply via email to