Introduce a helper function for complaining about "signed unsigned"
and "short long".  Add colorization there so that e.g. the 'signed'
and 'unsigned' are given consisten contrasting colors in both the
message and the quoted source.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.

gcc/cp/ChangeLog:
        * decl.cc: Add #include "diagnostic-highlight-colors.h"
        and #include "pretty-print-markup.h".
        (complain_about_incompatible_declspecs): New.
        (grokdeclarator): Use it when complaining about both 'signed' and
        'unsigned', and both 'long' and 'short'.

gcc/ChangeLog:
        * diagnostic-highlight-colors.h; Tweak comment.
        * pretty-print-markup.h (class pp_element_quoted_string): New,
        based on pretty-print.cc's selftest::test_element, adding an
        optional highlight color.
        * pretty-print.cc (class test_element): Drop.
        (selftest::test_pp_format): Use pp_element_quoted_string.
        (selftest::test_urlification): Likewise.

gcc/testsuite/ChangeLog:
        * g++.dg/diagnostic/long-short-colorization.C: New test.

Signed-off-by: David Malcolm <dmalc...@redhat.com>
---
 gcc/cp/decl.cc                                | 36 +++++++++++++------
 gcc/diagnostic-highlight-colors.h             |  3 +-
 gcc/pretty-print-markup.h                     | 25 +++++++++++++
 gcc/pretty-print.cc                           | 22 ++----------
 .../diagnostic/long-short-colorization.C      | 20 +++++++++++
 5 files changed, 75 insertions(+), 31 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/long-short-colorization.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index b4e7ceefedb0..10c2b2e3ad10 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -61,6 +61,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "opts.h"
 #include "langhooks-def.h"  /* For lhd_simulate_record_decl  */
 #include "coroutines.h"
+#include "diagnostic-highlight-colors.h"
+#include "pretty-print-markup.h"
 
 /* Possible cases of bad specifiers type used by bad_specifiers. */
 enum bad_spec_place {
@@ -12302,6 +12304,23 @@ check_decltype_auto (location_t loc, tree type)
   return false;
 }
 
+/* Issue an error about two mutually incompatible declspecs
+   with the given names and locations
+   e.g. "error: `signed' and `unsigned' specified together" */
+
+static void
+complain_about_incompatible_declspecs (const char *name_a, location_t loc_a,
+                                      const char *name_b, location_t loc_b)
+{
+  gcc_rich_location richloc (loc_a, nullptr, highlight_colors::lhs);
+  richloc.add_range (loc_b, SHOW_RANGE_WITHOUT_CARET,
+                    nullptr, highlight_colors::rhs);
+  pp_element_quoted_string e_name_a (name_a, highlight_colors::lhs);
+  pp_element_quoted_string e_name_b (name_b, highlight_colors::rhs);
+  error_at (&richloc, "%e and %e specified together",
+           &e_name_a, &e_name_b);
+}
+
 /* Given declspecs and a declarator (abstract or otherwise), determine
    the name and type of the object declared and construct a DECL node
    for it.
@@ -12935,18 +12954,13 @@ grokdeclarator (const cp_declarator *declarator,
       int ok = 0;
 
       if (signed_p && unsigned_p)
-       {
-         gcc_rich_location richloc (declspecs->locations[ds_signed]);
-         richloc.add_range (declspecs->locations[ds_unsigned]);
-         error_at (&richloc,
-                   "%<signed%> and %<unsigned%> specified together");
-       }
+       complain_about_incompatible_declspecs
+         ("signed", declspecs->locations[ds_signed],
+          "unsigned", declspecs->locations[ds_unsigned]);
       else if (long_p && short_p)
-       {
-         gcc_rich_location richloc (declspecs->locations[ds_long]);
-         richloc.add_range (declspecs->locations[ds_short]);
-         error_at (&richloc, "%<long%> and %<short%> specified together");
-       }
+       complain_about_incompatible_declspecs
+         ("long", declspecs->locations[ds_long],
+          "short", declspecs->locations[ds_short]);
       else if (TREE_CODE (type) != INTEGER_TYPE
               || type == char8_type_node
               || type == char16_type_node
diff --git a/gcc/diagnostic-highlight-colors.h 
b/gcc/diagnostic-highlight-colors.h
index 66acfc8e8145..72e3ade358dc 100644
--- a/gcc/diagnostic-highlight-colors.h
+++ b/gcc/diagnostic-highlight-colors.h
@@ -47,7 +47,8 @@ namespace highlight_colors {
 extern const char *const expected;
 extern const char *const actual;
 
-/* Color names for expressing "LHS" vs "RHS" values in a binary operation.  */
+/* Color names for expressing "LHS" vs "RHS" values in a binary operation
+   or when we are listing two different things.  */
 extern const char *const lhs;
 extern const char *const rhs;
 
diff --git a/gcc/pretty-print-markup.h b/gcc/pretty-print-markup.h
index 8e6897ce25ff..0de04c7fee55 100644
--- a/gcc/pretty-print-markup.h
+++ b/gcc/pretty-print-markup.h
@@ -89,4 +89,29 @@ private:
 
 } // namespace pp_markup
 
+class pp_element_quoted_string : public pp_element
+{
+public:
+  pp_element_quoted_string (const char *text,
+                           const char *highlight_color = nullptr)
+  : m_text (text),
+    m_highlight_color (highlight_color)
+  {}
+
+  void add_to_phase_2 (pp_markup::context &ctxt) final override
+  {
+    ctxt.begin_quote ();
+    if (m_highlight_color)
+      ctxt.begin_highlight_color (m_highlight_color);
+    pp_string (&ctxt.m_pp, m_text);
+    if (m_highlight_color)
+      ctxt.end_highlight_color ();
+    ctxt.end_quote ();
+  }
+
+private:
+  const char *m_text;
+  const char *m_highlight_color;
+};
+
 #endif /* GCC_PRETTY_PRINT_MARKUP_H */
diff --git a/gcc/pretty-print.cc b/gcc/pretty-print.cc
index a3f369132dd0..643fbb589c74 100644
--- a/gcc/pretty-print.cc
+++ b/gcc/pretty-print.cc
@@ -3315,22 +3315,6 @@ assert_pp_format_colored (const location &loc, const 
char *expected,
                       (ARG1), (ARG2), (ARG3));               \
   SELFTEST_END_STMT
 
-class test_element : public pp_element
-{
-public:
-  test_element (const char *text) : m_text (text) {}
-
-  void add_to_phase_2 (pp_markup::context &ctxt) final override
-  {
-    ctxt.begin_quote ();
-    pp_string (&ctxt.m_pp, m_text);
-    ctxt.end_quote ();
-  }
-
-private:
-  const char *m_text;
-};
-
 /* Verify that pp_format works, for various format codes.  */
 
 static void
@@ -3445,8 +3429,8 @@ test_pp_format ()
 
   /* Verify %e.  */
   {
-    test_element foo ("foo");
-    test_element bar ("bar");
+    pp_element_quoted_string foo ("foo");
+    pp_element_quoted_string bar ("bar");
     ASSERT_PP_FORMAT_2 ("before `foo' `bar' after",
                        "before %e %e after",
                        &foo, &bar);
@@ -4205,7 +4189,7 @@ test_urlification ()
   {
     pretty_printer pp;
     pp.set_url_format (URL_FORMAT_ST);
-    test_element elem ("-foption");
+    pp_element_quoted_string elem ("-foption");
     pp_printf_with_urlifier (&pp, &urlifier,
                             "foo %e bar",
                             &elem);
diff --git a/gcc/testsuite/g++.dg/diagnostic/long-short-colorization.C 
b/gcc/testsuite/g++.dg/diagnostic/long-short-colorization.C
new file mode 100644
index 000000000000..d2111fee1d21
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/long-short-colorization.C
@@ -0,0 +1,20 @@
+// Verify colorization of printing of declspec mismatches
+// Use dg-*-multiline-output to avoid regexp interpretation.
+
+// { dg-options "-fdiagnostics-color=always -fdiagnostics-show-caret" }
+
+long short int a;
+/* { dg-begin-multiline-output "" }
+'long' and 
'short' specified together
+ long 
short
 int a;
+ ^~~~ 
~~~~~
+   { dg-end-multiline-output "" } */
+short long int b;
+/* { dg-begin-multiline-output "" }
+'long' and 
'short' specified together
+ 
short
 long int b;
+ 
~~~~~
 ^~~~
+   { dg-end-multiline-output "" } */
+
+// Discard the remaining colorized output that confuses dejagnu.
+// { dg-prune-output diagnostic/long-short-colorization.C }
-- 
2.26.3

Reply via email to