(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
plugin/
crash_test_plugin.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  
      32  int plugin_is_GPL_compatible;
      33  
      34  /* A custom pass for injecting a crash in the middle-end when compiling
      35     certain functions.  */
      36  
      37  const pass_data pass_data_crash_test =
      38  {
      39    GIMPLE_PASS, /* type */
      40    "crash_test", /* name */
      41    OPTGROUP_NONE, /* optinfo_flags */
      42    TV_NONE, /* tv_id */
      43    PROP_ssa, /* properties_required */
      44    0, /* properties_provided */
      45    0, /* properties_destroyed */
      46    0, /* todo_flags_start */
      47    0, /* todo_flags_finish */
      48  };
      49  
      50  class pass_crash_test : public gimple_opt_pass
      51  {
      52  public:
      53    pass_crash_test(gcc::context *ctxt)
      54      : gimple_opt_pass(pass_data_crash_test, ctxt)
      55    {}
      56  
      57    /* opt_pass methods: */
      58    bool gate (function *) final override { return true; }
      59    unsigned int execute (function *) final override;
      60  
      61  }; // class pass_test_groups
      62  
      63  /* Determine if STMT is a call to a function named FUNCNAME.
      64     If so, return STMT as a gcall *.  Otherwise return NULL.  */
      65  
      66  static gcall *
      67  check_for_named_call (gimple *stmt, const char *funcname)
      68  {
      69    gcc_assert (funcname);
      70  
      71    gcall *call = dyn_cast <gcall *> (stmt);
      72    if (!call)
      73      return NULL;
      74  
      75    tree fndecl = gimple_call_fndecl (call);
      76    if (!fndecl)
      77      return NULL;
      78  
      79    if (strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), funcname))
      80      return NULL;
      81  
      82    return call;
      83  }
      84  
      85  unsigned int
      86  pass_crash_test::execute (function *fun)
      87  {
      88    gimple_stmt_iterator gsi;
      89    basic_block bb;
      90  
      91    FOR_EACH_BB_FN (bb, fun)
      92      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
      93        {
      94  	gimple *stmt = gsi_stmt (gsi);
      95  	if (gcall *call = check_for_named_call (stmt, "inject_ice"))
      96  	  {
      97  	    input_location = stmt->location;
      98  	    internal_error ("I'm sorry Dave, I'm afraid I can't do that");
      99  	  }
     100  	if (gcall *call = check_for_named_call (stmt,
     101  						"inject_write_through_null"))
     102  	  {
     103  	    input_location = stmt->location;
     104  	    int *p = NULL;
     105  	    *p = 42;
     106  	  }
     107        }
     108  
     109    return 0;
     110  }
     111  
     112  /* Entrypoint for the plugin.
     113     Create and register the custom pass.  */
     114  
     115  int
     116  plugin_init (struct plugin_name_args *plugin_info,
     117  	     struct plugin_gcc_version *version)
     118  {
     119    struct register_pass_info pass_info;
     120    const char *plugin_name = plugin_info->base_name;
     121    int argc = plugin_info->argc;
     122    struct plugin_argument *argv = plugin_info->argv;
     123  
     124    if (!plugin_default_version_check (version, &gcc_version))
     125      return 1;
     126  
     127    pass_info.pass = new pass_crash_test (g);
     128    pass_info.reference_pass_name = "*warn_function_noreturn";
     129    pass_info.ref_pass_instance_number = 1;
     130    pass_info.pos_op = PASS_POS_INSERT_AFTER;
     131    register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
     132  		     &pass_info);
     133  
     134    return 0;
     135  }