On Wed, Nov 7, 2018 at 5:22 PM David Malcolm <dmalc...@redhat.com> wrote:
>
> This patch implements support for %C in dump_printf for dumping
> cgraph_node *.
> (I would have preferred to have a code for printing symtab_node *
> and both subclasses, but there doesn't seem to be a good way for
> -Wformat to handle inheritance, so, failing that, I went with
> this approach).
>
> Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu, in
> conjunction with the rest of the patch kit.
>
> OK for trunk?

OK

> gcc/c-family/ChangeLog:
>         * c-format.c (local_cgraph_node_ptr_node): New variable.
>         (gcc_dump_printf_char_table): Add entry for %C.
>         (get_pointer_to_named_type): New function, taken from the handling
>         code for "gimple *" from...
>         (init_dynamic_diag_info): ...here.  Add handling for
>         "cgraph_node *".
>         * c-format.h (T_CGRAPH_NODE): New.
>
> gcc/ChangeLog:
>         * dump-context.h (ASSERT_IS_CGRAPH_NODE): New macro.
>         * dumpfile.c (make_item_for_dump_cgraph_node): Move to before...
>         (dump_pretty_printer::decode_format): Implement "%C" for
>         cgraph_node *.
>         (selftest::test_capture_of_dump_calls): Rename "where" to
>         "stmt_loc".  Convert test_decl to a function decl and set its
>         location.  Add a symbol_table_test RAII instance and a
>         cgraph_node, using it to test "%C" and dump_symtab_node.
>
> gcc/testsuite/ChangeLog:
>         * gcc.dg/format/gcc_diag-10.c (cgraph_node): New typedef.
>         (test_dump): Add testing of %C.
> ---
>  gcc/c-family/c-format.c                   |  56 ++++++++++-----
>  gcc/c-family/c-format.h                   |   1 +
>  gcc/dump-context.h                        |   8 +++
>  gcc/dumpfile.c                            | 115 
> ++++++++++++++++++++++--------
>  gcc/testsuite/gcc.dg/format/gcc_diag-10.c |   5 +-
>  5 files changed, 135 insertions(+), 50 deletions(-)
>
> diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
> index a1133c7..385ee1a 100644
> --- a/gcc/c-family/c-format.c
> +++ b/gcc/c-family/c-format.c
> @@ -60,6 +60,7 @@ struct function_format_info
>  /* Initialized in init_dynamic_diag_info.  */
>  static GTY(()) tree local_tree_type_node;
>  static GTY(()) tree local_gimple_ptr_node;
> +static GTY(()) tree local_cgraph_node_ptr_node;
>  static GTY(()) tree locus;
>
>  static bool decode_format_attr (tree, function_format_info *, int);
> @@ -803,6 +804,9 @@ static const format_char_info 
> gcc_dump_printf_char_table[] =
>    /* E and G require a "gimple *" argument at runtime.  */
>    { "EG",   1, STD_C89, { T89_G,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  
> BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "", "\"",   
> NULL },
>
> +  /* C requires a "cgraph_node *" argument at runtime.  */
> +  { "C",   1, STD_C89, { T_CGRAPH_NODE,   BADLEN,  BADLEN,  BADLEN,  BADLEN, 
>  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "", "\"",   
> NULL },
> +
>    /* T requires a "tree" at runtime.  */
>    { "T",   1, STD_C89, { T89_T,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  
> BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "", "\"",   
> NULL },
>
> @@ -3879,6 +3883,33 @@ init_dynamic_gfc_info (void)
>      }
>  }
>
> +/* Lookup the type named NAME and return a pointer-to-NAME type if found.
> +   Otherwise, return void_type_node if NAME has not been used yet, or 
> NULL_TREE if
> +   NAME is not a type (issuing an error).  */
> +
> +static tree
> +get_pointer_to_named_type (const char *name)
> +{
> +  tree result;
> +  if ((result = maybe_get_identifier (name)))
> +    {
> +      result = identifier_global_value (result);
> +      if (result)
> +       {
> +         if (TREE_CODE (result) != TYPE_DECL)
> +           {
> +             error ("%qs is not defined as a type", name);
> +             result = NULL_TREE;
> +           }
> +         else
> +           result = TREE_TYPE (result);
> +       }
> +    }
> +  else
> +    result = void_type_node;
> +  return result;
> +}
> +
>  /* Determine the types of "tree" and "location_t" in the code being
>     compiled for use in GCC's diagnostic custom format attributes.  You
>     must have set dynamic_format_types before calling this function.  */
> @@ -3932,25 +3963,12 @@ init_dynamic_diag_info (void)
>    /* Similar to the above but for gimple*.  */
>    if (!local_gimple_ptr_node
>        || local_gimple_ptr_node == void_type_node)
> -    {
> -      if ((local_gimple_ptr_node = maybe_get_identifier ("gimple")))
> -       {
> -         local_gimple_ptr_node
> -           = identifier_global_value (local_gimple_ptr_node);
> -         if (local_gimple_ptr_node)
> -           {
> -             if (TREE_CODE (local_gimple_ptr_node) != TYPE_DECL)
> -               {
> -                 error ("%<gimple%> is not defined as a type");
> -                 local_gimple_ptr_node = 0;
> -               }
> -             else
> -               local_gimple_ptr_node = TREE_TYPE (local_gimple_ptr_node);
> -           }
> -       }
> -      else
> -       local_gimple_ptr_node = void_type_node;
> -    }
> +    local_gimple_ptr_node = get_pointer_to_named_type ("gimple");
> +
> +  /* Similar to the above but for cgraph_node*.  */
> +  if (!local_cgraph_node_ptr_node
> +      || local_cgraph_node_ptr_node == void_type_node)
> +    local_cgraph_node_ptr_node = get_pointer_to_named_type ("cgraph_node");
>
>    static tree hwi;
>
> diff --git a/gcc/c-family/c-format.h b/gcc/c-family/c-format.h
> index d984d10..eabb4f0 100644
> --- a/gcc/c-family/c-format.h
> +++ b/gcc/c-family/c-format.h
> @@ -299,6 +299,7 @@ struct format_kind_info
>  #define T99_UC { STD_C99, NULL, T_UC }
>  #define T_V    &void_type_node
>  #define T89_G   { STD_C89, NULL, &local_gimple_ptr_node }
> +#define T_CGRAPH_NODE   { STD_C89, NULL, &local_cgraph_node_ptr_node }
>  #define T89_T   { STD_C89, NULL, &local_tree_type_node }
>  #define T89_V  { STD_C89, NULL, T_V }
>  #define T_W    &wchar_type_node
> diff --git a/gcc/dump-context.h b/gcc/dump-context.h
> index 3a45f23..ace139c 100644
> --- a/gcc/dump-context.h
> +++ b/gcc/dump-context.h
> @@ -251,6 +251,14 @@ verify_item (const location &loc,
>                  (EXPECTED_LOCATION), (EXPECTED_TEXT));     \
>    SELFTEST_END_STMT
>
> +/* Verify that ITEM is a symtab node, with the expected values.  */
> +
> +#define ASSERT_IS_SYMTAB_NODE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \
> +  SELFTEST_BEGIN_STMT                                              \
> +    verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_SYMTAB_NODE, \
> +                (EXPECTED_LOCATION), (EXPECTED_TEXT));     \
> +  SELFTEST_END_STMT
> +
>  } // namespace selftest
>
>  #endif /* CHECKING_P */
> diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c
> index 0b140ff..09c2490 100644
> --- a/gcc/dumpfile.c
> +++ b/gcc/dumpfile.c
> @@ -748,6 +748,18 @@ dump_context::dump_generic_expr_loc (dump_flags_t 
> dump_kind,
>    dump_generic_expr (dump_kind, extra_dump_flags, t);
>  }
>
> +/* Make an item for the given dump call.  */
> +
> +static optinfo_item *
> +make_item_for_dump_symtab_node (symtab_node *node)
> +{
> +  location_t loc = DECL_SOURCE_LOCATION (node->decl);
> +  optinfo_item *item
> +    = new optinfo_item (OPTINFO_ITEM_KIND_SYMTAB_NODE, loc,
> +                       xstrdup (node->dump_name ()));
> +  return item;
> +}
> +
>  /* dump_pretty_printer's ctor.  */
>
>  dump_pretty_printer::dump_pretty_printer (dump_context *context,
> @@ -881,6 +893,8 @@ dump_pretty_printer::format_decoder_cb (pretty_printer 
> *pp, text_info *text,
>     Supported format codes (in addition to the standard pretty_printer ones)
>     are:
>
> +   %C: cgraph_node *:
> +       Equivalent to: dump_symtab_node (MSG_*, node)
>     %E: gimple *:
>         Equivalent to: dump_gimple_expr (MSG_*, TDF_SLIM, stmt, 0)
>     %G: gimple *:
> @@ -888,7 +902,9 @@ dump_pretty_printer::format_decoder_cb (pretty_printer 
> *pp, text_info *text,
>     %T: tree:
>         Equivalent to: dump_generic_expr (MSG_*, arg, TDF_SLIM).
>
> -   FIXME: add symtab_node?
> +   TODO: add a format code that can handle (symtab_node*) *and* both
> +   subclasses (presumably means teaching -Wformat about non-virtual
> +   subclasses).
>
>     These format codes build optinfo_item instances, thus capturing metadata
>     about the arguments being dumped, as well as the textual output.  */
> @@ -901,6 +917,16 @@ dump_pretty_printer::decode_format (text_info *text, 
> const char *spec,
>       for later use (to capture metadata, rather than plain text).  */
>    switch (*spec)
>      {
> +    case 'C':
> +      {
> +       cgraph_node *node = va_arg (*text->args_ptr, cgraph_node *);
> +
> +       /* Make an item for the node, and stash it.  */
> +       optinfo_item *item = make_item_for_dump_symtab_node (node);
> +       stash_item (buffer_ptr, item);
> +       return true;
> +      }
> +
>      case 'E':
>        {
>         gimple *stmt = va_arg (*text->args_ptr, gimple *);
> @@ -1023,18 +1049,6 @@ dump_context::dump_dec (dump_flags_t dump_kind, const 
> poly_int<N, C> &value)
>      delete item;
>  }
>
> -/* Make an item for the given dump call.  */
> -
> -static optinfo_item *
> -make_item_for_dump_symtab_node (symtab_node *node)
> -{
> -  location_t loc = DECL_SOURCE_LOCATION (node->decl);
> -  optinfo_item *item
> -    = new optinfo_item (OPTINFO_ITEM_KIND_SYMTAB_NODE, loc,
> -                       xstrdup (node->dump_name ()));
> -  return item;
> -}
> -
>  /* Output the name of NODE on appropriate dump streams.  */
>
>  void
> @@ -2067,18 +2081,26 @@ test_capture_of_dump_calls (const line_table_case 
> &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 where = linemap_position_for_column (line_table, 10);
> -  if (where > LINE_MAP_MAX_LOCATION_WITH_COLS)
> +  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_location_t loc = dump_location_t::from_location_t (where);
> +  dump_location_t loc = dump_location_t::from_location_t (stmt_loc);
>
>    gimple *stmt = gimple_build_return (NULL);
> -  gimple_set_location (stmt, where);
> +  gimple_set_location (stmt, stmt_loc);
>
> -  tree test_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
> +  tree test_decl = build_decl (decl_loc, FUNCTION_DECL,
>                                get_identifier ("test_decl"),
> -                              integer_type_node);
> +                              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.  */
> @@ -2135,7 +2157,7 @@ test_capture_of_dump_calls (const line_table_case 
> &case_)
>             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), where, "return;");
> +           ASSERT_IS_GIMPLE (info->get_item (1), stmt_loc, "return;");
>           }
>        }
>
> @@ -2153,7 +2175,25 @@ test_capture_of_dump_calls (const line_table_case 
> &case_)
>             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), where, "return;\n");
> +           ASSERT_IS_GIMPLE (info->get_item (1), stmt_loc, "return;\n");
> +         }
> +      }
> +
> +      /* 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);
> +
> +       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");
>           }
>        }
>
> @@ -2184,8 +2224,8 @@ test_capture_of_dump_calls (const line_table_case 
> &case_)
>             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), where, "return;");
> -           ASSERT_IS_GIMPLE (info->get_item (6), where, "return;");
> +           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");
>           }
>        }
> @@ -2202,7 +2242,7 @@ test_capture_of_dump_calls (const line_table_case 
> &case_)
>           {
>             optinfo *info = tmp.get_pending_optinfo ();
>             ASSERT_TRUE (info != NULL);
> -           ASSERT_EQ (info->get_location_t (), where);
> +           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: ");
> @@ -2221,7 +2261,7 @@ test_capture_of_dump_calls (const line_table_case 
> &case_)
>           {
>             optinfo *info = tmp.get_pending_optinfo ();
>             ASSERT_TRUE (info != NULL);
> -           ASSERT_EQ (info->get_location_t (), where);
> +           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");
> @@ -2242,7 +2282,7 @@ test_capture_of_dump_calls (const line_table_case 
> &case_)
>               optinfo *info = tmp.get_pending_optinfo ();
>               ASSERT_TRUE (info != NULL);
>               ASSERT_EQ (info->num_items (), 1);
> -             ASSERT_IS_GIMPLE (info->get_item (0), where, "return;\n");
> +             ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;\n");
>             }
>         }
>
> @@ -2258,7 +2298,7 @@ test_capture_of_dump_calls (const line_table_case 
> &case_)
>               optinfo *info = tmp.get_pending_optinfo ();
>               ASSERT_TRUE (info != NULL);
>               ASSERT_EQ (info->num_items (), 1);
> -             ASSERT_IS_GIMPLE (info->get_item (0), where, "return;\n");
> +             ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;\n");
>             }
>         }
>
> @@ -2274,7 +2314,7 @@ test_capture_of_dump_calls (const line_table_case 
> &case_)
>               optinfo *info = tmp.get_pending_optinfo ();
>               ASSERT_TRUE (info != NULL);
>               ASSERT_EQ (info->num_items (), 1);
> -             ASSERT_IS_GIMPLE (info->get_item (0), where, "return;");
> +             ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;");
>             }
>         }
>
> @@ -2290,11 +2330,28 @@ test_capture_of_dump_calls (const line_table_case 
> &case_)
>               optinfo *info = tmp.get_pending_optinfo ();
>               ASSERT_TRUE (info != NULL);
>               ASSERT_EQ (info->num_items (), 1);
> -             ASSERT_IS_GIMPLE (info->get_item (0), where, "return;");
> +             ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;");
>             }
>         }
>        }
>
> +      /* symtab_node.  */
> +      {
> +       temp_dump_context tmp (with_optinfo, true,
> +                              MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
> +       dump_symtab_node (MSG_NOTE, node);
> +
> +       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");
> +         }
> +      }
> +
>        /* poly_int.  */
>        {
>         temp_dump_context tmp (with_optinfo, true,
> diff --git a/gcc/testsuite/gcc.dg/format/gcc_diag-10.c 
> b/gcc/testsuite/gcc.dg/format/gcc_diag-10.c
> index 2f6a002..97a1993 100644
> --- a/gcc/testsuite/gcc.dg/format/gcc_diag-10.c
> +++ b/gcc/testsuite/gcc.dg/format/gcc_diag-10.c
> @@ -20,7 +20,7 @@ typedef union tree_node *tree;
>  typedef struct gimple gimple;
>
>  /* Likewise for gimple.  */
> -typedef struct gimple gimple;
> +typedef struct cgraph_node cgraph_node;
>
>  #define FORMAT(kind) __attribute__ ((format (__gcc_## kind ##__, 1, 2)))
>
> @@ -162,7 +162,7 @@ void test_cxxdiag (tree t, gimple *gc)
>    cxxdiag ("%<%X%>", t);
>  }
>
> -void test_dump (tree t, gimple *stmt)
> +void test_dump (tree t, gimple *stmt, cgraph_node *node)
>  {
>    dump ("%<");   /* { dg-warning "unterminated quoting directive" } */
>    dump ("%>");   /* { dg-warning "unmatched quoting directive " } */
> @@ -182,4 +182,5 @@ void test_dump (tree t, gimple *stmt)
>    dump ("%E", stmt);
>    dump ("%T", t);
>    dump ("%G", stmt);
> +  dump ("%C", node);
>  }
> --
> 1.8.5.3
>

Reply via email to