diff options
author | David Malcolm <dmalcolm@redhat.com> | 2017-11-22 20:37:58 +0000 |
---|---|---|
committer | David Malcolm <dmalcolm@gcc.gnu.org> | 2017-11-22 20:37:58 +0000 |
commit | ce95abc41e998c8d1e1b2112a634d5a6cdd9ede0 (patch) | |
tree | 1dfdcc2ae24d09d53824e4b7b34934a19d570519 /gcc/cp/error.c | |
parent | d8d9aa38aed6489fa28308d3955e3467c5eb935b (diff) | |
download | gcc-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.c | 99 |
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; } |