@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see
#include "analyzer/pending-diagnostic.h"
#include "analyzer/call-details.h"
#include "make-unique.h"
+#include "pretty-print-markup.h"
#if ENABLE_ANALYZER
@@ -176,23 +177,40 @@ public:
probably most user-friendly. */
escaped_decls.qsort (cmp_decls_ptr_ptr);
- pretty_printer pp;
- pp_format_decoder (&pp) = default_tree_printer;
- pp_show_color (&pp) = pp_show_color (global_dc->m_printer);
- bool first = true;
- for (auto iter : escaped_decls)
+ class escaped_list_element : public pp_element
+ {
+ public:
+ escaped_list_element (auto_vec<tree> &escaped_decls)
+ : m_escaped_decls (escaped_decls)
{
- if (first)
- first = false;
- else
- pp_string (&pp, ", ");
- pp_printf (&pp, "%qD", iter);
}
+
+ void add_to_phase_2 (pp_markup::context &ctxt) final override
+ {
+ /* We can't call pp_printf directly on ctxt.m_pp from within
+ formatting. As a workaround, work with a clone of the pp. */
+ std::unique_ptr<pretty_printer> pp (ctxt.m_pp.clone ());
+ bool first = true;
+ for (auto iter : m_escaped_decls)
+ {
+ if (first)
+ first = false;
+ else
+ pp_string (pp.get (), ", ");
+ pp_printf (pp.get (), "%qD", iter);
+ }
+ pp_string (&ctxt.m_pp, pp_formatted_text (pp.get ()));
+ }
+
+ private:
+ auto_vec<tree> &m_escaped_decls;
+ } e_escaped (escaped_decls);
+
/* Print the number to make it easier to write DejaGnu tests for
the "nothing has escaped" case. */
- warning_at (cd.get_location (), 0, "escaped: %i: %s",
+ warning_at (cd.get_location (), 0, "escaped: %i: %e",
escaped_decls.length (),
- pp_formatted_text (&pp));
+ &e_escaped);
}
};
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "hash-set.h"
#include "diagnostic.h"
#include "pretty-print.h"
+#include "pretty-print-markup.h"
#include "tree-pretty-print.h"
#include "intl.h"
@@ -2196,15 +2197,14 @@ has_attribute (tree node, tree attrs, const char *aname)
the "template" function declaration TMPL and DECL. The word "template"
doesn't necessarily refer to a C++ template but rather a declaration
whose attributes should be matched by those on DECL. For a non-zero
- return value set *ATTRSTR to a string representation of the list of
- mismatched attributes with quoted names.
+ return value append the names of the mismatcheed attributes to OUTATTRS.
ATTRLIST is a list of additional attributes that SPEC should be
taken to ultimately be declared with. */
unsigned
decls_mismatched_attributes (tree tmpl, tree decl, tree attrlist,
const char* const blacklist[],
- pretty_printer *attrstr)
+ auto_vec<const char *> &outattrs)
{
if (TREE_CODE (tmpl) != FUNCTION_DECL)
return 0;
@@ -2278,11 +2278,7 @@ decls_mismatched_attributes (tree tmpl, tree decl, tree attrlist,
if (!found)
{
- if (nattrs)
- pp_string (attrstr, ", ");
- pp_begin_quote (attrstr, pp_show_color (global_dc->m_printer));
- pp_string (attrstr, blacklist[i]);
- pp_end_quote (attrstr, pp_show_color (global_dc->m_printer));
+ outattrs.safe_push (blacklist[i]);
++nattrs;
}
@@ -2312,23 +2308,24 @@ maybe_diag_alias_attributes (tree alias, tree target)
"returns_twice", NULL
};
- pretty_printer attrnames;
if (warn_attribute_alias > 1)
{
/* With -Wattribute-alias=2 detect alias declarations that are more
restrictive than their targets first. Those indicate potential
codegen bugs. */
+ auto_vec<const char *> mismatches;
if (unsigned n = decls_mismatched_attributes (alias, target, NULL_TREE,
- blacklist, &attrnames))
+ blacklist, mismatches))
{
auto_diagnostic_group d;
+ pp_markup::comma_separated_quoted_strings e (mismatches);
if (warning_n (DECL_SOURCE_LOCATION (alias),
OPT_Wattribute_alias_, n,
"%qD specifies more restrictive attribute than "
- "its target %qD: %s",
+ "its target %qD: %e",
"%qD specifies more restrictive attributes than "
- "its target %qD: %s",
- alias, target, pp_formatted_text (&attrnames)))
+ "its target %qD: %e",
+ alias, target, &e))
inform (DECL_SOURCE_LOCATION (target),
"%qD target declared here", alias);
return;
@@ -2338,17 +2335,19 @@ maybe_diag_alias_attributes (tree alias, tree target)
/* Detect alias declarations that are less restrictive than their
targets. Those suggest potential optimization opportunities
(solved by adding the missing attribute(s) to the alias). */
+ auto_vec<const char *> mismatches;
if (unsigned n = decls_mismatched_attributes (target, alias, NULL_TREE,
- blacklist, &attrnames))
+ blacklist, mismatches))
{
auto_diagnostic_group d;
+ pp_markup::comma_separated_quoted_strings e (mismatches);
if (warning_n (DECL_SOURCE_LOCATION (alias),
OPT_Wmissing_attributes, n,
"%qD specifies less restrictive attribute than "
- "its target %qD: %s",
+ "its target %qD: %e",
"%qD specifies less restrictive attributes than "
- "its target %qD: %s",
- alias, target, pp_formatted_text (&attrnames)))
+ "its target %qD: %e",
+ alias, target, &e))
inform (DECL_SOURCE_LOCATION (target),
"%qD target declared here", alias);
}
@@ -131,7 +131,7 @@ extern tree private_lookup_attribute (const char *attr_ns,
extern unsigned decls_mismatched_attributes (tree, tree, tree,
const char* const[],
- pretty_printer*);
+ auto_vec<const char *> &);
extern void maybe_diag_alias_attributes (tree, tree);
@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "builtins.h"
#include "omp-general.h"
+#include "pretty-print-markup.h"
/* The type of functions taking a tree, and some additional data, and
returning an int. */
@@ -2764,9 +2765,9 @@ warn_spec_missing_attributes (tree tmpl, tree spec, tree attrlist)
/* Put together a list of the black listed attributes that the primary
template is declared with that the specialization is not, in case
it's not apparent from the most recent declaration of the primary. */
- pretty_printer str;
+ auto_vec<const char *> mismatches;
unsigned nattrs = decls_mismatched_attributes (tmpl, spec, attrlist,
- blacklist, &str);
+ blacklist, mismatches);
if (!nattrs)
return;
@@ -2775,11 +2776,14 @@ warn_spec_missing_attributes (tree tmpl, tree spec, tree attrlist)
if (warning_at (DECL_SOURCE_LOCATION (spec), OPT_Wmissing_attributes,
"explicit specialization %q#D may be missing attributes",
spec))
- inform (DECL_SOURCE_LOCATION (tmpl),
- nattrs > 1
- ? G_("missing primary template attributes %s")
- : G_("missing primary template attribute %s"),
- pp_formatted_text (&str));
+ {
+ pp_markup::comma_separated_quoted_strings e (mismatches);
+ inform (DECL_SOURCE_LOCATION (tmpl),
+ nattrs > 1
+ ? G_("missing primary template attributes %e")
+ : G_("missing primary template attribute %e"),
+ &e);
+ }
}
/* Check to see if the function just declared, as indicated in
@@ -55,6 +55,7 @@
#include "demangle.h"
#include "attr-fnspec.h"
#include "pointer-query.h"
+#include "pretty-print-markup.h"
/* Return true if tree node X has an associated location. */
@@ -2942,15 +2943,14 @@ pass_waccess::maybe_warn_memmodel (gimple *stmt, tree ord_sucs,
return false;
/* Print a note with the valid memory models. */
- pretty_printer pp;
- pp_show_color (&pp) = pp_show_color (global_dc->m_printer);
+ auto_vec<const char *> strings;
for (unsigned i = 0; valid[i] != UCHAR_MAX; ++i)
{
const char *modname = memory_models[valid[i]].modname;
- pp_printf (&pp, "%s%qs", i ? ", " : "", modname);
+ strings.safe_push (modname);
}
-
- inform (loc, "valid models are %s", pp_formatted_text (&pp));
+ pp_markup::comma_separated_quoted_strings e (strings);
+ inform (loc, "valid models are %e", &e);
return true;
}
@@ -2992,19 +2992,16 @@ pass_waccess::maybe_warn_memmodel (gimple *stmt, tree ord_sucs,
/* Print a note with the valid failure memory models which are
those with a value less than or equal to the success mode. */
- char buf[120];
- *buf = '\0';
+ auto_vec<const char *> strings;
for (unsigned i = 0;
memory_models[i].modval <= memmodel_base (sucs); ++i)
{
- if (*buf)
- strcat (buf, ", ");
-
const char *modname = memory_models[valid[i]].modname;
- sprintf (buf + strlen (buf), "'%s'", modname);
+ strings.safe_push (modname);
}
+ pp_markup::comma_separated_quoted_strings e (strings);
- inform (loc, "valid models are %s", buf);
+ inform (loc, "valid models are %e", &e);
return true;
}
@@ -70,6 +70,23 @@ private:
DISABLE_COPY_AND_ASSIGN (element);
};
+/* Concrete subclass: handle "%e" by printing a comma-separated list
+ of quoted strings. */
+
+class comma_separated_quoted_strings : public element
+{
+public:
+ comma_separated_quoted_strings (const auto_vec<const char *> &strings)
+ : m_strings (strings)
+ {
+ }
+
+ void add_to_phase_2 (context &ctxt) final override;
+
+private:
+ const auto_vec<const char *> &m_strings;
+};
+
} // namespace pp_markup
#endif /* GCC_PRETTY_PRINT_MARKUP_H */
@@ -3092,6 +3092,19 @@ pp_markup::context::push_back_any_text ()
const char *)));
}
+void
+pp_markup::comma_separated_quoted_strings::add_to_phase_2 (context &ctxt)
+{
+ for (unsigned i = 0; i < m_strings.length (); i++)
+ {
+ if (i > 0)
+ pp_string (&ctxt.m_pp, ", ");
+ ctxt.begin_quote ();
+ pp_string (&ctxt.m_pp, m_strings[i]);
+ ctxt.end_quote ();
+ }
+}
+
/* Color names for expressing "expected" vs "actual" values. */
const char *const highlight_colors::expected = "highlight-a";
const char *const highlight_colors::actual = "highlight-b";
@@ -3669,6 +3682,54 @@ test_pp_format_stack ()
"In function: `test_fn'\nunexpected foo: 42 bar: `test'");
}
+/* Verify usage of pp_printf from within a pp_element's
+ add_to_phase_2 vfunc. */
+static void
+test_pp_printf_within_pp_element ()
+{
+ class kv_element : public pp_element
+ {
+ public:
+ kv_element (const char *key, int value)
+ : m_key (key), m_value (value)
+ {
+ }
+
+ void add_to_phase_2 (pp_markup::context &ctxt) final override
+ {
+ /* We can't call pp_printf directly on ctxt.m_pp from within
+ formatting. As a workaround, work with a clone of the pp. */
+ std::unique_ptr<pretty_printer> pp (ctxt.m_pp.clone ());
+ pp_printf (pp.get (), "(%qs: %qi)", m_key, m_value);
+ pp_string (&ctxt.m_pp, pp_formatted_text (pp.get ()));
+ }
+
+ private:
+ const char *m_key;
+ int m_value;
+ };
+
+ auto_fix_quotes fix_quotes;
+
+ kv_element e1 ("foo", 42);
+ kv_element e2 ("bar", 1066);
+ ASSERT_PP_FORMAT_2 ("before (`foo': `42') (`bar': `1066') after",
+ "before %e %e after",
+ &e1, &e2);
+ assert_pp_format_colored (SELFTEST_LOCATION,
+ ("before "
+ "(`\33[01m\33[Kfoo\33[m\33[K'"
+ ": "
+ "`\33[01m\33[K42\33[m\33[K')"
+ " "
+ "(`\33[01m\33[Kbar\33[m\33[K'"
+ ": "
+ "`\33[01m\33[K1066\33[m\33[K')"
+ " after"),
+ "before %e %e after",
+ &e1, &e2);
+}
+
/* A subclass of pretty_printer for use by test_prefixes_and_wrapping. */
class test_pretty_printer : public pretty_printer
@@ -4088,6 +4149,35 @@ static void test_utf8 ()
}
+/* Verify that class comma_separated_quoted_strings works as expected. */
+
+static void
+test_comma_separated_quoted_strings ()
+{
+ auto_fix_quotes fix_quotes;
+
+ auto_vec<const char *> none;
+ pp_markup::comma_separated_quoted_strings e_none (none);
+
+ auto_vec<const char *> one;
+ one.safe_push ("one");
+ pp_markup::comma_separated_quoted_strings e_one (one);
+
+ auto_vec<const char *> many;
+ many.safe_push ("0");
+ many.safe_push ("1");
+ many.safe_push ("2");
+ pp_markup::comma_separated_quoted_strings e_many (many);
+
+ ASSERT_PP_FORMAT_3 ("none: () one: (`one') many: (`0', `1', `2')",
+ "none: (%e) one: (%e) many: (%e)",
+ &e_none, &e_one, &e_many);
+ assert_pp_format_colored (SELFTEST_LOCATION,
+ "one: (`[01m[Kone[m[K')",
+ "one: (%e)",
+ &e_one);
+}
+
/* Run all of the selftests within this file. */
void
@@ -4099,12 +4189,14 @@ pretty_print_cc_tests ()
test_custom_tokens_1 ();
test_custom_tokens_2 ();
test_pp_format_stack ();
+ test_pp_printf_within_pp_element ();
test_prefixes_and_wrapping ();
test_urls ();
test_urls_from_braces ();
test_null_urls ();
test_urlification ();
test_utf8 ();
+ test_comma_separated_quoted_strings ();
}
} // namespace selftest
@@ -13,16 +13,13 @@ static void test_1 (void)
__analyzer_dump_escaped (); /* { dg-warning "escaped: 0: " } */
unknown_fn (&local_1);
- __analyzer_dump_escaped (); /* { dg-warning "escaped: 1: 'local_1'" "" { target c } } */
- /* { dg-warning "escaped: 1: 'int local_1'" "" { target c++ } .-1 } */
+ __analyzer_dump_escaped (); /* { dg-warning "escaped: 1: 'local_1'" } */
/* Should be idempotent. */
unknown_fn (&local_1);
- __analyzer_dump_escaped (); /* { dg-warning "escaped: 1: 'local_1'" "" { target c } } */
- /* { dg-warning "escaped: 1: 'int local_1'" "" { target c++ } .-1 } */
+ __analyzer_dump_escaped (); /* { dg-warning "escaped: 1: 'local_1'" } */
/* Escape a static global. */
unknown_fn (&only_used_by_test_1);
- __analyzer_dump_escaped (); /* { dg-warning "escaped: 2: 'local_1', 'only_used_by_test_1'" "" { target c } } */
- /* { dg-warning "escaped: 2: 'int local_1', 'int only_used_by_test_1'" "" { target c++ } .-1 } */
+ __analyzer_dump_escaped (); /* { dg-warning "escaped: 2: 'local_1', 'only_used_by_test_1'" } */
}