+
+/* debug_dump_context's ctor. Temporarily override the dump_context
+ (to forcibly enable output to stderr). */
+
+debug_dump_context::debug_dump_context ()
+: m_context (),
+ m_saved (&dump_context::get ()),
+ m_saved_flags (dump_flags),
+ m_saved_pflags (pflags),
+ m_saved_file (dump_file)
+{
+ set_dump_file (stderr);
+ dump_context::s_current = &m_context;
+ pflags = dump_flags = MSG_ALL_KINDS | MSG_ALL_PRIORITIES;
+ dump_context::get ().refresh_dumps_are_enabled ();
+}
+
+/* debug_dump_context's dtor. Restore the saved dump_context. */
+
+debug_dump_context::~debug_dump_context ()
+{
+ set_dump_file (m_saved_file);
+ dump_context::s_current = m_saved;
+ dump_flags = m_saved_flags;
+ pflags = m_saved_pflags;
+ dump_context::get ().refresh_dumps_are_enabled ();
+}
+
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* temp_dump_context's ctor. Temporarily override the dump_context
+ (to forcibly enable optinfo-generation). */
+
+temp_dump_context::temp_dump_context (bool forcibly_enable_optinfo,
+ bool forcibly_enable_dumping,
+ dump_flags_t test_pp_flags)
+: m_context (),
+ m_saved (&dump_context::get ())
+{
+ dump_context::s_current = &m_context;
+ if (forcibly_enable_optinfo)
+ m_context.set_json_writer (new optrecord_json_writer ());
+ /* Conditionally enable the test dump, so that we can verify both the
+ dump_enabled_p and the !dump_enabled_p cases in selftests. */
+ if (forcibly_enable_dumping)
+ {
+ m_context.m_test_pp = &m_pp;
+ m_context.m_test_pp_flags = test_pp_flags;
+ }
+
+ dump_context::get ().refresh_dumps_are_enabled ();
+}
+
+/* temp_dump_context's dtor. Restore the saved dump_context. */
+
+temp_dump_context::~temp_dump_context ()
+{
+ m_context.set_json_writer (NULL);
+
+ dump_context::s_current = m_saved;
+
+ dump_context::get ().refresh_dumps_are_enabled ();
+}
+
+/* 0-terminate the text dumped so far, and return it. */
+
+const char *
+temp_dump_context::get_dumped_text ()
+{
+ return pp_formatted_text (&m_pp);
+}
+
+/* Verify that IMPL_LOC is within EXPECTED_FILE at EXPECTED_LINE,
+ from EXPECTED_FUNCTION, using LOC for the location of any failure,
+ provided that the build compiler is sufficiently recent. */
+
+static void
+assert_impl_location_eq (const location &loc ATTRIBUTE_UNUSED,
+ const dump_impl_location_t &impl_loc ATTRIBUTE_UNUSED,
+ const char *expected_file ATTRIBUTE_UNUSED,
+ int expected_line ATTRIBUTE_UNUSED,
+ const char *expected_function ATTRIBUTE_UNUSED)
+{
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+ ASSERT_STR_CONTAINS_AT (loc, impl_loc.m_file, expected_file);
+ ASSERT_EQ_AT (loc, impl_loc.m_line, expected_line);
+ ASSERT_STR_CONTAINS_AT (loc, impl_loc.m_function, expected_function);
+#endif
+}
+
+/* Verify that IMPL_LOC is within EXPECTED_FILE at EXPECTED_LINE,
+ from EXPECTED_FUNCTION, provided that the build compiler is
+ sufficiently recent. */
+
+#define ASSERT_IMPL_LOCATION_EQ(IMPL_LOC, EXPECTED_FILE, EXPECTED_LINE, \
+ EXPECTED_FUNCTION) \
+ SELFTEST_BEGIN_STMT \
+ assert_impl_location_eq (SELFTEST_LOCATION, IMPL_LOC, \
+ EXPECTED_FILE, EXPECTED_LINE, \
+ EXPECTED_FUNCTION); \
+ SELFTEST_END_STMT
+
+/* Verify that the dump_location_t constructors capture the source location
+ at which they were called (provided that the build compiler is sufficiently
+ recent). */
+
+static void
+test_impl_location ()
+{
+ /* Default ctor. */
+ {
+ dump_location_t loc;
+ const int expected_line = __LINE__ - 1;
+ ASSERT_IMPL_LOCATION_EQ (loc.get_impl_location (),
+ "dumpfile.c", expected_line, "test_impl_location");
+ }
+
+ /* Constructing from a gimple. */
+ {
+ dump_location_t loc ((gimple *)NULL);
+ const int expected_line = __LINE__ - 1;
+ ASSERT_IMPL_LOCATION_EQ (loc.get_impl_location (),
+ "dumpfile.c", expected_line, "test_impl_location");
+ }
+
+ /* Constructing from an rtx_insn. */
+ {
+ dump_location_t loc ((rtx_insn *)NULL);
+ const int expected_line = __LINE__ - 1;
+ ASSERT_IMPL_LOCATION_EQ (loc.get_impl_location (),
+ "dumpfile.c", expected_line, "test_impl_location");
+ }
+}
+
+/* Verify that the text dumped so far in CONTEXT equals
+ EXPECTED_TEXT, using LOC for the location of any failure.
+ As a side-effect, the internal buffer is 0-terminated. */
+
+void
+verify_dumped_text (const location &loc,
+ temp_dump_context *context,
+ const char *expected_text)
+{
+ gcc_assert (context);
+ ASSERT_STREQ_AT (loc, context->get_dumped_text (),
+ expected_text);
+}
+
+/* Verify that ITEM has the expected values. */
+
+void
+verify_item (const location &loc,
+ const optinfo_item *item,
+ enum optinfo_item_kind expected_kind,
+ location_t expected_location,
+ const char *expected_text)
+{
+ ASSERT_EQ_AT (loc, item->get_kind (), expected_kind);
+ ASSERT_EQ_AT (loc, item->get_location (), expected_location);
+ ASSERT_STREQ_AT (loc, item->get_text (), expected_text);
+}
+
+/* Verify that calls to the dump_* API are captured and consolidated into
+ optimization records. */
+
+static void
+test_capture_of_dump_calls (const line_table_case &case_)
+{
+ /* Generate a location_t for testing. */
+ line_table_test ltt (case_);
+ linemap_add (line_table, LC_ENTER, false, "test.txt", 0);
+ linemap_line_start (line_table, 5, 100);
+ linemap_add (line_table, LC_LEAVE, false, NULL, 0);
+ location_t decl_loc = linemap_position_for_column (line_table, 8);
+ location_t stmt_loc = linemap_position_for_column (line_table, 10);
+ if (stmt_loc > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ dump_user_location_t loc = dump_user_location_t::from_location_t (stmt_loc);
+
+ gimple *stmt = gimple_build_return (NULL);
+ gimple_set_location (stmt, stmt_loc);
+
+ tree test_decl = build_decl (decl_loc, FUNCTION_DECL,
+ get_identifier ("test_decl"),
+ build_function_type_list (void_type_node,
+ NULL_TREE));
+
+ symbol_table_test tmp_symtab;
+
+ cgraph_node *node = cgraph_node::get_create (test_decl);
+ gcc_assert (node);
+
+ /* Run all tests twice, with and then without optinfo enabled, to ensure
+ that immediate destinations vs optinfo-based destinations both
+ work, independently of each other, with no leaks. */
+ for (int i = 0 ; i < 2; i++)
+ {
+ bool with_optinfo = (i == 0);
+
+ /* Test of dump_printf. */
+ {
+ temp_dump_context tmp (with_optinfo, true,
+ MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
+ dump_printf (MSG_NOTE, "int: %i str: %s", 42, "foo");
+ const int expected_impl_line = __LINE__ - 1;
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "int: 42 str: foo");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->num_items (), 1);
+ ASSERT_IS_TEXT (info->get_item (0), "int: 42 str: foo");
+ ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
+ "dumpfile.c", expected_impl_line,
+ "test_capture_of_dump_calls");
+ }
+ }
+
+ /* Test of dump_printf with %T. */
+ {
+ temp_dump_context tmp (with_optinfo, true,
+ MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
+ dump_printf (MSG_NOTE, "tree: %T", integer_zero_node);
+ const int expected_impl_line = __LINE__ - 1;
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "tree: 0");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->num_items (), 2);
+ ASSERT_IS_TEXT (info->get_item (0), "tree: ");
+ ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
+ ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
+ "dumpfile.c", expected_impl_line,
+ "test_capture_of_dump_calls");
+ }
+ }
+
+ /* Test of dump_printf with %E. */
+ {
+ temp_dump_context tmp (with_optinfo, true,
+ MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
+ dump_printf (MSG_NOTE, "gimple: %E", stmt);
+ const int expected_impl_line = __LINE__ - 1;
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "gimple: return;");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->num_items (), 2);
+ ASSERT_IS_TEXT (info->get_item (0), "gimple: ");
+ ASSERT_IS_GIMPLE (info->get_item (1), stmt_loc, "return;");
+ ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
+ "dumpfile.c", expected_impl_line,
+ "test_capture_of_dump_calls");
+ }
+ }
+
+ /* Test of dump_printf with %G. */
+ {
+ temp_dump_context tmp (with_optinfo, true,
+ MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
+ dump_printf (MSG_NOTE, "gimple: %G", stmt);
+ const int expected_impl_line = __LINE__ - 1;
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "gimple: return;\n");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->num_items (), 2);
+ ASSERT_IS_TEXT (info->get_item (0), "gimple: ");
+ ASSERT_IS_GIMPLE (info->get_item (1), stmt_loc, "return;\n");
+ ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
+ "dumpfile.c", expected_impl_line,
+ "test_capture_of_dump_calls");
+ }
+ }
+
+ /* Test of dump_printf with %C. */
+ {
+ temp_dump_context tmp (with_optinfo, true,
+ MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
+ dump_printf (MSG_NOTE, "node: %C", node);
+ const int expected_impl_line = __LINE__ - 1;
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "node: test_decl/0");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->num_items (), 2);
+ ASSERT_IS_TEXT (info->get_item (0), "node: ");
+ ASSERT_IS_SYMTAB_NODE (info->get_item (1), decl_loc, "test_decl/0");
+ ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
+ "dumpfile.c", expected_impl_line,
+ "test_capture_of_dump_calls");
+ }
+ }
+
+ /* dump_print_loc with multiple format codes. This tests various
+ things:
+ - intermingling of text, format codes handled by the base
+ pretty_printer, and dump-specific format codes
+ - multiple dump-specific format codes: some consecutive, others
+ separated by text, trailing text after the final one. */
+ {
+ temp_dump_context tmp (with_optinfo, true,
+ MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
+ dump_printf_loc (MSG_NOTE, loc, "before %T and %T"
+ " %i consecutive %E%E after\n",
+ integer_zero_node, test_decl, 42, stmt, stmt);
+
+ ASSERT_DUMPED_TEXT_EQ (tmp,
+ "test.txt:5:10: note: before 0 and test_decl"
+ " 42 consecutive return;return; after\n");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->num_items (), 8);
+ ASSERT_IS_TEXT (info->get_item (0), "before ");
+ ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
+ ASSERT_IS_TEXT (info->get_item (2), " and ");
+ ASSERT_IS_TREE (info->get_item (3), UNKNOWN_LOCATION, "test_decl");
+ ASSERT_IS_TEXT (info->get_item (4), " 42 consecutive ");
+ ASSERT_IS_GIMPLE (info->get_item (5), stmt_loc, "return;");
+ ASSERT_IS_GIMPLE (info->get_item (6), stmt_loc, "return;");
+ ASSERT_IS_TEXT (info->get_item (7), " after\n");
+ /* We don't ASSERT_IMPL_LOCATION_EQ here, to avoid having to
+ enforce at which exact line the multiline dump_printf_loc
+ occurred. */
+ }
+ }
+
+ /* Tree, via dump_generic_expr. */
+ {
+ temp_dump_context tmp (with_optinfo, true,
+ MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
+ dump_printf_loc (MSG_NOTE, loc, "test of tree: ");
+ const int expected_impl_line = __LINE__ - 1;
+ dump_generic_expr (MSG_NOTE, TDF_SLIM, integer_zero_node);
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: test of tree: 0");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->get_location_t (), stmt_loc);
+ ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->num_items (), 2);
+ ASSERT_IS_TEXT (info->get_item (0), "test of tree: ");
+ ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
+ ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
+ "dumpfile.c", expected_impl_line,
+ "test_capture_of_dump_calls");
+ }
+ }
+
+ /* Tree, via dump_generic_expr_loc. */
+ {
+ temp_dump_context tmp (with_optinfo, true,
+ MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
+ dump_generic_expr_loc (MSG_NOTE, loc, TDF_SLIM, integer_one_node);
+ const int expected_impl_line = __LINE__ - 1;
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: 1");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->get_location_t (), stmt_loc);
+ ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->num_items (), 1);
+ ASSERT_IS_TREE (info->get_item (0), UNKNOWN_LOCATION, "1");
+ ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
+ "dumpfile.c", expected_impl_line,
+ "test_capture_of_dump_calls");
+ }
+ }
+
+ /* Gimple. */
+ {
+ /* dump_gimple_stmt_loc. */
+ {
+ temp_dump_context tmp (with_optinfo, true,
+ MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
+ dump_gimple_stmt_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
+ const int expected_impl_line = __LINE__ - 1;
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: return;\n");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->num_items (), 1);
+ ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;\n");
+ ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
+ "dumpfile.c", expected_impl_line,
+ "test_capture_of_dump_calls");
+ }
+ }
+
+ /* dump_gimple_stmt. */
+ {
+ temp_dump_context tmp (with_optinfo, true,
+ MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
+ dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 2);
+ const int expected_impl_line = __LINE__ - 1;
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "return;\n");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->num_items (), 1);
+ ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;\n");
+ ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
+ "dumpfile.c", expected_impl_line,
+ "test_capture_of_dump_calls");
+ }
+ }
+
+ /* dump_gimple_expr_loc. */
+ {
+ temp_dump_context tmp (with_optinfo, true,
+ MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
+ dump_gimple_expr_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
+ const int expected_impl_line = __LINE__ - 1;
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: return;");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->num_items (), 1);
+ ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;");
+ ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
+ "dumpfile.c", expected_impl_line,
+ "test_capture_of_dump_calls");
+ }
+ }
+
+ /* dump_gimple_expr. */
+ {
+ temp_dump_context tmp (with_optinfo, true,
+ MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
+ dump_gimple_expr (MSG_NOTE, TDF_SLIM, stmt, 2);
+ const int expected_impl_line = __LINE__ - 1;
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "return;");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->num_items (), 1);
+ ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;");
+ ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
+ "dumpfile.c", expected_impl_line,
+ "test_capture_of_dump_calls");
+ }
+ }
+ }
+
+ /* symtab_node. */
+ {
+ temp_dump_context tmp (with_optinfo, true,
+ MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
+ dump_symtab_node (MSG_NOTE, node);
+ const int expected_impl_line = __LINE__ - 1;
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "test_decl/0");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->num_items (), 1);
+ ASSERT_IS_SYMTAB_NODE (info->get_item (0), decl_loc, "test_decl/0");
+ ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
+ "dumpfile.c", expected_impl_line,
+ "test_capture_of_dump_calls");
+ }
+ }
+
+ /* poly_int. */
+ {
+ temp_dump_context tmp (with_optinfo, true,
+ MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
+ dump_dec (MSG_NOTE, poly_int64 (42));
+ const int expected_impl_line = __LINE__ - 1;
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "42");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->num_items (), 1);
+ ASSERT_IS_TEXT (info->get_item (0), "42");
+ ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
+ "dumpfile.c", expected_impl_line,
+ "test_capture_of_dump_calls");
+ }
+ }
+
+ /* Scopes. Test with all 4 combinations of
+ filtering by MSG_PRIORITY_USER_FACING
+ and/or filtering by MSG_PRIORITY_INTERNALS. */
+ for (int j = 0; j < 3; j++)
+ {
+ dump_flags_t dump_filter = MSG_ALL_KINDS;
+ if (j % 2)
+ dump_filter |= MSG_PRIORITY_USER_FACING;
+ if (j / 2)
+ dump_filter |= MSG_PRIORITY_INTERNALS;
+
+ temp_dump_context tmp (with_optinfo, true, dump_filter);
+ /* Emit various messages, mostly with implicit priority. */
+ dump_printf_loc (MSG_NOTE, stmt, "msg 1\n");
+ dump_printf_loc (MSG_NOTE | MSG_PRIORITY_INTERNALS, stmt,
+ "explicitly internal msg\n");
+ {
+ AUTO_DUMP_SCOPE ("outer scope", stmt);
+ dump_printf_loc (MSG_NOTE, stmt, "msg 2\n");
+ {
+ AUTO_DUMP_SCOPE ("middle scope", stmt);
+ dump_printf_loc (MSG_NOTE, stmt, "msg 3\n");
+ {
+ AUTO_DUMP_SCOPE ("inner scope", stmt);
+ dump_printf_loc (MSG_NOTE, stmt, "msg 4\n");
+ dump_printf_loc (MSG_NOTE | MSG_PRIORITY_USER_FACING, stmt,
+ "explicitly user-facing msg\n");
+ }
+ dump_printf_loc (MSG_NOTE, stmt, "msg 5\n");
+ }
+ dump_printf_loc (MSG_NOTE, stmt, "msg 6\n");
+ }
+ dump_printf_loc (MSG_NOTE, stmt, "msg 7\n");
+ const int expected_impl_line = __LINE__ - 1;
+
+ switch (dump_filter & MSG_ALL_PRIORITIES)
+ {
+ default:
+ gcc_unreachable ();
+ case 0:
+ ASSERT_DUMPED_TEXT_EQ (tmp, "");
+ break;
+ case MSG_PRIORITY_USER_FACING:
+ ASSERT_DUMPED_TEXT_EQ
+ (tmp,
+ "test.txt:5:10: note: msg 1\n"
+ "test.txt:5:10: note: explicitly user-facing msg\n"
+ "test.txt:5:10: note: msg 7\n");
+ break;
+ case MSG_PRIORITY_INTERNALS:
+ ASSERT_DUMPED_TEXT_EQ
+ (tmp,
+ "test.txt:5:10: note: explicitly internal msg\n"
+ "test.txt:5:10: note: === outer scope ===\n"
+ "test.txt:5:10: note: msg 2\n"
+ "test.txt:5:10: note: === middle scope ===\n"
+ "test.txt:5:10: note: msg 3\n"
+ "test.txt:5:10: note: === inner scope ===\n"
+ "test.txt:5:10: note: msg 4\n"
+ "test.txt:5:10: note: msg 5\n"
+ "test.txt:5:10: note: msg 6\n");
+ break;
+ case MSG_ALL_PRIORITIES:
+ ASSERT_DUMPED_TEXT_EQ
+ (tmp,
+ "test.txt:5:10: note: msg 1\n"
+ "test.txt:5:10: note: explicitly internal msg\n"
+ "test.txt:5:10: note: === outer scope ===\n"
+ "test.txt:5:10: note: msg 2\n"
+ "test.txt:5:10: note: === middle scope ===\n"
+ "test.txt:5:10: note: msg 3\n"
+ "test.txt:5:10: note: === inner scope ===\n"
+ "test.txt:5:10: note: msg 4\n"
+ "test.txt:5:10: note: explicitly user-facing msg\n"
+ "test.txt:5:10: note: msg 5\n"
+ "test.txt:5:10: note: msg 6\n"
+ "test.txt:5:10: note: msg 7\n");
+ break;
+ }
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->num_items (), 1);
+ ASSERT_IS_TEXT (info->get_item (0), "msg 7\n");
+ ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
+ "dumpfile.c", expected_impl_line,
+ "test_capture_of_dump_calls");
+ }
+ }
+ }
+
+ /* Verify that MSG_* affects optinfo->get_kind (); we tested MSG_NOTE
+ above. */
+ {
+ /* MSG_OPTIMIZED_LOCATIONS. */
+ {
+ temp_dump_context tmp (true, true, MSG_ALL_KINDS);
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, "test");
+ ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
+ OPTINFO_KIND_SUCCESS);
+ }
+
+ /* MSG_MISSED_OPTIMIZATION. */
+ {
+ temp_dump_context tmp (true, true, MSG_ALL_KINDS);
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, "test");
+ ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
+ OPTINFO_KIND_FAILURE);
+ }
+ }
+
+ /* Verify that MSG_* affect AUTO_DUMP_SCOPE and the dump calls. */
+ {
+ temp_dump_context tmp (false, true,
+ MSG_OPTIMIZED_LOCATIONS | MSG_ALL_PRIORITIES);
+ dump_printf_loc (MSG_NOTE, stmt, "msg 1\n");
+ {
+ AUTO_DUMP_SCOPE ("outer scope", stmt);
+ dump_printf_loc (MSG_NOTE, stmt, "msg 2\n");
+ {
+ AUTO_DUMP_SCOPE ("middle scope", stmt);
+ dump_printf_loc (MSG_NOTE, stmt, "msg 3\n");
+ {
+ AUTO_DUMP_SCOPE ("inner scope", stmt);
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, stmt, "msg 4\n");
+ }
+ dump_printf_loc (MSG_NOTE, stmt, "msg 5\n");
+ }
+ dump_printf_loc (MSG_NOTE, stmt, "msg 6\n");
+ }
+ dump_printf_loc (MSG_NOTE, stmt, "msg 7\n");
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: optimized: msg 4\n");
+ }
+}
+
+static void
+test_pr87025 ()
+{
+ dump_user_location_t loc
+ = dump_user_location_t::from_location_t (UNKNOWN_LOCATION);
+
+ temp_dump_context tmp (true, true,
+ MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
+ {
+ AUTO_DUMP_SCOPE ("outer scope", loc);
+ dump_printf (MSG_NOTE, "msg1\n");
+ }
+}
+
+/* Run all of the selftests within this file. */
+
+void
+dumpfile_c_tests ()
+{
+ test_impl_location ();
+ for_each_line_table_case (test_capture_of_dump_calls);
+ test_pr87025 ();
+}
+
+} // namespace selftest
+
+#endif /* CHECKING_P */