(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
plugin/
diagnostic_plugin_test_inlining.c
       1  /* { dg-options "-O" } */
       2  
       3  #include "gcc-plugin.h"
       4  #include "config.h"
       5  #include "system.h"
       6  #include "coretypes.h"
       7  #include "tm.h"
       8  #include "tree.h"
       9  #include "stringpool.h"
      10  #include "toplev.h"
      11  #include "basic-block.h"
      12  #include "hash-table.h"
      13  #include "vec.h"
      14  #include "ggc.h"
      15  #include "basic-block.h"
      16  #include "tree-ssa-alias.h"
      17  #include "internal-fn.h"
      18  #include "gimple.h"
      19  #include "gimple-iterator.h"
      20  #include "gimple-fold.h"
      21  #include "tree-eh.h"
      22  #include "gimple-expr.h"
      23  #include "is-a.h"
      24  #include "tree.h"
      25  #include "tree-pass.h"
      26  #include "intl.h"
      27  #include "plugin-version.h"
      28  #include "c-family/c-common.h"
      29  #include "diagnostic.h"
      30  #include "context.h"
      31  #include "print-tree.h"
      32  #include "cpplib.h"
      33  #include "c-family/c-pragma.h"
      34  #include "substring-locations.h"
      35  
      36  int plugin_is_GPL_compatible;
      37  
      38  /* A custom pass for emitting dummy warnings from the middle-end.  */
      39  
      40  const pass_data pass_data_test_inlining =
      41  {
      42    GIMPLE_PASS, /* type */
      43    "test_inlining", /* name */
      44    OPTGROUP_NONE, /* optinfo_flags */
      45    TV_NONE, /* tv_id */
      46    PROP_ssa, /* properties_required */
      47    0, /* properties_provided */
      48    0, /* properties_destroyed */
      49    0, /* todo_flags_start */
      50    0, /* todo_flags_finish */
      51  };
      52  
      53  class pass_test_inlining : public gimple_opt_pass
      54  {
      55  public:
      56    pass_test_inlining(gcc::context *ctxt)
      57      : gimple_opt_pass(pass_data_test_inlining, ctxt)
      58    {}
      59  
      60    /* opt_pass methods: */
      61    bool gate (function *) { return true; }
      62    virtual unsigned int execute (function *);
      63  
      64  }; // class pass_test_inlining
      65  
      66  /* Determine if STMT is a call with NUM_ARGS arguments to a function
      67     named FUNCNAME.
      68     If so, return STMT as a gcall *.  Otherwise return NULL.  */
      69  
      70  static gcall *
      71  check_for_named_call (gimple *stmt,
      72  		      const char *funcname, unsigned int num_args)
      73  {
      74    gcc_assert (funcname);
      75  
      76    gcall *call = dyn_cast <gcall *> (stmt);
      77    if (!call)
      78      return NULL;
      79  
      80    tree fndecl = gimple_call_fndecl (call);
      81    if (!fndecl)
      82      return NULL;
      83  
      84    if (strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), funcname))
      85      return NULL;
      86  
      87    if (gimple_call_num_args (call) != num_args)
      88      {
      89        error_at (stmt->location, "expected number of args: %i (got %i)",
      90  		num_args, gimple_call_num_args (call));
      91        return NULL;
      92      }
      93  
      94    return call;
      95  }
      96  
      97  /* Emit a warning at LOC.  */
      98  
      99  static void
     100  emit_warning (location_t loc)
     101  {
     102    source_range src_range = get_range_from_loc (line_table, loc);
     103    warning_at (loc, 0, "range %i:%i-%i:%i",
     104  	      LOCATION_LINE (src_range.m_start),
     105  	      LOCATION_COLUMN (src_range.m_start),
     106  	      LOCATION_LINE (src_range.m_finish),
     107  	      LOCATION_COLUMN (src_range.m_finish));
     108  }
     109  
     110  /* Code for simulating the emission of a warning from the middle-end.
     111     Emit a warning for each call to a function named "__emit_warning".  */
     112  
     113  static void
     114  test_inlining (gimple *stmt)
     115  {
     116    gcall *call = check_for_named_call (stmt, "__emit_warning", 1);
     117    if (!call)
     118      return;
     119  
     120    /* We expect an ADDR_EXPR with a STRING_CST inside it for the
     121       initial arg.  */
     122    tree t_addr_string = gimple_call_arg (call, 0);
     123    if (TREE_CODE (t_addr_string) != ADDR_EXPR)
     124      {
     125        error_at (call->location, "string literal required for arg 1");
     126        return;
     127      }
     128  
     129    tree t_string = TREE_OPERAND (t_addr_string, 0);
     130    if (TREE_CODE (t_string) != STRING_CST)
     131      {
     132        error_at (call->location, "string literal required for arg 1");
     133        return;
     134      }
     135  
     136    warning_at (call->location, 0, "%s",
     137  	      TREE_STRING_POINTER (t_string));
     138  }
     139  
     140  /* Call test_inlining on every statement within FUN.  */
     141  
     142  unsigned int
     143  pass_test_inlining::execute (function *fun)
     144  {
     145    gimple_stmt_iterator gsi;
     146    basic_block bb;
     147  
     148    FOR_EACH_BB_FN (bb, fun)
     149      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
     150        {
     151  	gimple *stmt = gsi_stmt (gsi);
     152  	test_inlining (stmt);
     153        }
     154  
     155    return 0;
     156  }
     157  
     158  /* Entrypoint for the plugin.  Create and register the custom pass.  */
     159  
     160  int
     161  plugin_init (struct plugin_name_args *plugin_info,
     162  	     struct plugin_gcc_version *version)
     163  {
     164    struct register_pass_info pass_info;
     165    const char *plugin_name = plugin_info->base_name;
     166    int argc = plugin_info->argc;
     167    struct plugin_argument *argv = plugin_info->argv;
     168  
     169    if (!plugin_default_version_check (version, &gcc_version))
     170      return 1;
     171  
     172    global_dc->caret_max_width = 80;
     173  
     174    pass_info.pass = new pass_test_inlining (g);
     175    pass_info.reference_pass_name = "*warn_function_noreturn";
     176    pass_info.ref_pass_instance_number = 1;
     177    pass_info.pos_op = PASS_POS_INSERT_AFTER;
     178    register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
     179  		     &pass_info);
     180  
     181    return 0;
     182  }