aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/error.c
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2017-11-22 20:37:58 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2017-11-22 20:37:58 +0000
commitce95abc41e998c8d1e1b2112a634d5a6cdd9ede0 (patch)
tree1dfdcc2ae24d09d53824e4b7b34934a19d570519 /gcc/cp/error.c
parentd8d9aa38aed6489fa28308d3955e3467c5eb935b (diff)
downloadgcc-ce95abc41e998c8d1e1b2112a634d5a6cdd9ede0.zip
gcc-ce95abc41e998c8d1e1b2112a634d5a6cdd9ede0.tar.gz
gcc-ce95abc41e998c8d1e1b2112a634d5a6cdd9ede0.tar.bz2
C/C++: fix quoting of "aka" typedef information (PR 62170)
PR 62170 describes a problem with how the quoting in pp_format interacts with the "aka" information for typedefs in %qT for the C family of frontends, and also now for %qH and %qI in the C++ frontend: we print: 'Py_ssize_t* {aka int*}' ^^^^^^^^^^^^^^^^^^^^^^ colorized as "quote" i.e. '[START_COLOR]Py_ssize_t* {aka int*}[END_COLOR]' when we should print: 'Py_ssize_t*' {aka 'int*'} ^^^^^^^^^^^ ^^^^ colorized as "quote" i.e. '[START_COLOR]Py_ssize_t*[END_COLOR]' {aka '[START_COLOR]int*[END_COLOR]'} where the opening and closing quote characters and colorization are added by the 'q' handling within pp_format. This patch fixes the quoting by updating the %T handling in C and C++ and the %H/%I handling in C++ to insert the quoting appropriately. It converts the "quote" param of the pp_format_decoder callback from bool to bool *, allowing for the %T and %H/%I handlers to write false back to it, to avoid printing the closing quote for the cases like the above where the trailing closing quote isn't needed. It introduces pp_begin_quote/pp_end_quote to simplify this. These take a "bool show_color", rather than using "pp_show_color (pp)" since cxx_pp's pp_show_color isn't currently initialized (since cxx_initialize_diagnostics happens before diagnostic_color_init). gcc/c/ChangeLog: PR c++/62170 * c-objc-common.c (c_tree_printer): Convert penultimate param from bool to bool *. Within '%T' handling, if showing an "aka", use "quoted" param to add appropriate quoting. gcc/cp/ChangeLog: PR c++/62170 * error.c (type_to_string): Add leading comment. Add params "postprocessed", "quote", and "show_color", using them to fix quoting of the "aka" for types involving typedefs. (arg_to_string): Update for new params to type_to_string. (cxx_format_postprocessor::handle): Likewise. (cp_printer): Convert penultimate param from bool to bool *. Update call to type_to_string and calls to defer_phase_2_of_type_diff. gcc/fortran/ChangeLog: PR c++/62170 * error.c (gfc_notify_std): Convert "quoted" param from bool to bool *. gcc/ChangeLog: PR c++/62170 * pretty-print.c (pp_format): Move quoting implementation to pp_begin_quote and pp_end_quote. Update pp_format_decoder call to pass address of "quote" local. (pp_begin_quote): New function. (pp_end_quote): New function. * pretty-print.h (printer_fn): Convert penultimate param from bool to bool *. (pp_begin_quote): New decl. (pp_end_quote): New decl. * tree-diagnostic.c (default_tree_printer): Convert penultimate param from bool to bool *. * tree-diagnostic.h (default_tree_printer): Likewise. gcc/testsuite/ChangeLog: PR c++/62170 * g++.dg/diagnostic/aka1.C: Update expected error messages to reflect fixes to quoting. * g++.dg/diagnostic/aka2.C: New test case. * g++.dg/parse/error55.C: Update expected error messages to reflect fixes to quoting. * gcc.dg/diag-aka-1.c: Likewise. * gcc.dg/diag-aka-2.c: New test case. * gcc.dg/pr13804-1.c: Update expected error messages to reflect fixes to quoting. * gcc.dg/pr56980.c: Likewise. * gcc.dg/pr65050.c: Likewise. * gcc.dg/redecl-14.c: Likewise. * gcc.dg/utf16-4.c Likewise. * gcc.target/i386/sse-vect-types.c (__m128d): Likewise. * obj-c++.dg/invalid-type-1.mm: Likewise. * objc.dg/proto-lossage-4.m: Likewise. From-SVN: r255076
Diffstat (limited to 'gcc/cp/error.c')
-rw-r--r--gcc/cp/error.c99
1 files changed, 81 insertions, 18 deletions
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 6d1f3da..a47822a 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -57,7 +57,7 @@ static const char *expr_to_string (tree);
static const char *fndecl_to_string (tree, int);
static const char *op_to_string (bool, enum tree_code);
static const char *parm_to_string (int);
-static const char *type_to_string (tree, int);
+static const char *type_to_string (tree, int, bool, bool *, bool);
static void dump_alias_template_specialization (cxx_pretty_printer *, tree, int);
static void dump_type (cxx_pretty_printer *, tree, int);
@@ -99,7 +99,7 @@ static void cp_diagnostic_starter (diagnostic_context *, diagnostic_info *);
static void cp_print_error_function (diagnostic_context *, diagnostic_info *);
static bool cp_printer (pretty_printer *, text_info *, const char *,
- int, bool, bool, bool, bool, const char **);
+ int, bool, bool, bool, bool *, const char **);
/* Struct for handling %H or %I, which require delaying printing the
type until a postprocessing stage. */
@@ -3144,8 +3144,28 @@ op_to_string (bool assop, enum tree_code p)
return id ? IDENTIFIER_POINTER (id) : M_("<unknown>");
}
+/* Return a GC-allocated representation of type TYP, with verbosity VERBOSE.
+
+ If QUOTE is non-NULL and if *QUOTE is true, then quotes are added to the
+ string in appropriate places, and *QUOTE is written to with false
+ to suppress pp_format's trailing close quote so that e.g.
+ foo_typedef {aka underlying_foo} {enum}
+ can be printed by "%qT" as:
+ `foo_typedef' {aka `underlying_foo'} {enum}
+ rather than:
+ `foo_typedef {aka underlying_foo} {enum}'
+ When adding such quotes, if POSTPROCESSED is true (for handling %H and %I)
+ then a leading open quote will be added, whereas if POSTPROCESSED is false
+ (for handling %T) then any leading quote has already been added by
+ pp_format, or is not needed due to QUOTE being NULL (for template arguments
+ within %H and %I).
+
+ SHOW_COLOR is used to determine the colorization of any quotes that
+ are added. */
+
static const char *
-type_to_string (tree typ, int verbose)
+type_to_string (tree typ, int verbose, bool postprocessed, bool *quote,
+ bool show_color)
{
int flags = 0;
if (verbose)
@@ -3153,7 +3173,19 @@ type_to_string (tree typ, int verbose)
flags |= TFF_TEMPLATE_HEADER;
reinit_cxx_pp ();
+
+ if (postprocessed && quote && *quote)
+ pp_begin_quote (cxx_pp, show_color);
+
+ struct obstack *ob = pp_buffer (cxx_pp)->obstack;
+ int type_start, type_len;
+ type_start = obstack_object_size (ob);
+
dump_type (cxx_pp, typ, flags);
+
+ /* Remember the end of the initial dump. */
+ type_len = obstack_object_size (ob) - type_start;
+
/* If we're printing a type that involves typedefs, also print the
stripped version. But sometimes the stripped version looks
exactly the same, so we don't want it after all. To avoid printing
@@ -3162,21 +3194,44 @@ type_to_string (tree typ, int verbose)
&& !uses_template_parms (typ))
{
int aka_start, aka_len; char *p;
- struct obstack *ob = pp_buffer (cxx_pp)->obstack;
- /* Remember the end of the initial dump. */
- int len = obstack_object_size (ob);
tree aka = strip_typedefs (typ);
+ if (quote && *quote)
+ pp_end_quote (cxx_pp, show_color);
pp_string (cxx_pp, " {aka");
pp_cxx_whitespace (cxx_pp);
+ if (quote && *quote)
+ pp_begin_quote (cxx_pp, show_color);
/* And remember the start of the aka dump. */
aka_start = obstack_object_size (ob);
dump_type (cxx_pp, aka, flags);
aka_len = obstack_object_size (ob) - aka_start;
+ if (quote && *quote)
+ pp_end_quote (cxx_pp, show_color);
pp_right_brace (cxx_pp);
p = (char*)obstack_base (ob);
- /* If they are identical, cut off the aka with a NUL. */
- if (len == aka_len && memcmp (p, p+aka_start, len) == 0)
- p[len] = '\0';
+ /* If they are identical, cut off the aka by unwinding the obstack. */
+ if (type_len == aka_len
+ && memcmp (p + type_start, p+aka_start, type_len) == 0)
+ {
+ /* We can't add a '\0' here, since we may be adding a closing quote
+ below, and it would be hidden by the '\0'.
+ Instead, manually unwind the current object within the obstack
+ so that the insertion point is at the end of the type, before
+ the "' {aka". */
+ int delta = type_start + type_len - obstack_object_size (ob);
+ gcc_assert (delta <= 0);
+ obstack_blank_fast (ob, delta);
+ }
+ else
+ if (quote)
+ /* No further closing quotes are needed. */
+ *quote = false;
+ }
+
+ if (quote && *quote)
+ {
+ pp_end_quote (cxx_pp, show_color);
+ *quote = false;
}
return pp_ggc_formatted_text (cxx_pp);
}
@@ -3634,7 +3689,7 @@ static const char *
arg_to_string (tree arg, bool verbose)
{
if (TYPE_P (arg))
- return type_to_string (arg, verbose);
+ return type_to_string (arg, verbose, true, NULL, false);
else
return expr_to_string (arg);
}
@@ -3924,10 +3979,13 @@ cxx_format_postprocessor::handle (pretty_printer *pp)
}
else
{
- /* If the types were not comparable, they are printed normally,
- and no difference tree is printed. */
- type_a_text = type_to_string (type_a.m_tree, type_a.m_verbose);
- type_b_text = type_to_string (type_b.m_tree, type_b.m_verbose);
+ /* If the types were not comparable (or if only one of %H/%I was
+ provided), they are printed normally, and no difference tree
+ is printed. */
+ type_a_text = type_to_string (type_a.m_tree, type_a.m_verbose,
+ true, &type_a.m_quote, show_color);
+ type_b_text = type_to_string (type_b.m_tree, type_b.m_verbose,
+ true, &type_b.m_quote, show_color);
}
if (type_a.m_quote)
@@ -4000,7 +4058,7 @@ defer_phase_2_of_type_diff (deferred_printed_type *deferred,
static bool
cp_printer (pretty_printer *pp, text_info *text, const char *spec,
int precision, bool wide, bool set_locus, bool verbose,
- bool quoted, const char **buffer_ptr)
+ bool *quoted, const char **buffer_ptr)
{
gcc_assert (pp->m_format_postprocessor);
cxx_format_postprocessor *postprocessor
@@ -4043,7 +4101,12 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec,
case 'P': result = parm_to_string (next_int); break;
case 'Q': result = op_to_string (true, next_tcode); break;
case 'S': result = subst_to_string (next_tree); break;
- case 'T': result = type_to_string (next_tree, verbose); break;
+ case 'T':
+ {
+ result = type_to_string (next_tree, verbose, false, quoted,
+ pp_show_color (pp));
+ }
+ break;
case 'V': result = cv_to_string (next_tree, verbose); break;
case 'X': result = eh_spec_to_string (next_tree, verbose); break;
@@ -4059,14 +4122,14 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec,
case 'H':
{
defer_phase_2_of_type_diff (&postprocessor->m_type_a, next_tree,
- buffer_ptr, verbose, quoted);
+ buffer_ptr, verbose, *quoted);
return true;
}
case 'I':
{
defer_phase_2_of_type_diff (&postprocessor->m_type_b, next_tree,
- buffer_ptr, verbose, quoted);
+ buffer_ptr, verbose, *quoted);
return true;
}