1 /* This plugin exercises diagnostic_metadata.  */
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-fold.h"
19 #include "tree-eh.h"
20 #include "gimple-expr.h"
21 #include "is-a.h"
22 #include "gimple.h"
23 #include "gimple-iterator.h"
24 #include "tree.h"
25 #include "tree-pass.h"
26 #include "intl.h"
27 #include "plugin-version.h"
28 #include "diagnostic.h"
29 #include "context.h"
30 #include "gcc-rich-location.h"
31 #include "diagnostic-metadata.h"
32 
33 int plugin_is_GPL_compatible;
34 
35 const pass_data pass_data_test_metadata =
36 {
37   GIMPLE_PASS, /* type */
38   "test_metadata", /* name */
39   OPTGROUP_NONE, /* optinfo_flags */
40   TV_NONE, /* tv_id */
41   PROP_ssa, /* properties_required */
42   0, /* properties_provided */
43   0, /* properties_destroyed */
44   0, /* todo_flags_start */
45   0, /* todo_flags_finish */
46 };
47 
48 class pass_test_metadata : public gimple_opt_pass
49 {
50 public:
pass_test_metadata(gcc::context * ctxt)51   pass_test_metadata(gcc::context *ctxt)
52     : gimple_opt_pass(pass_data_test_metadata, ctxt)
53   {}
54 
55   /* opt_pass methods: */
gate(function *)56   bool gate (function *) { return true; }
57   virtual unsigned int execute (function *);
58 
59 }; // class pass_test_metadata
60 
61 /* Determine if STMT is a call with NUM_ARGS arguments to a function
62    named FUNCNAME.
63    If so, return STMT as a gcall *.  Otherwise return NULL.  */
64 
65 static gcall *
check_for_named_call(gimple * stmt,const char * funcname,unsigned int num_args)66 check_for_named_call (gimple *stmt,
67 		      const char *funcname, unsigned int num_args)
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   if (gimple_call_num_args (call) != num_args)
83     {
84       error_at (stmt->location, "expected number of args: %i (got %i)",
85 		num_args, gimple_call_num_args (call));
86       return NULL;
87     }
88 
89   return call;
90 }
91 
92 /* Exercise diagnostic_metadata.  */
93 
94 unsigned int
execute(function * fun)95 pass_test_metadata::execute (function *fun)
96 {
97   gimple_stmt_iterator gsi;
98   basic_block bb;
99 
100   FOR_EACH_BB_FN (bb, fun)
101     for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
102       {
103 	gimple *stmt = gsi_stmt (gsi);
104 
105 	/* Example of CWE: complain about uses of gets.  */
106 	if (gcall *call = check_for_named_call (stmt, "gets", 1))
107 	  {
108 	    gcc_rich_location richloc (gimple_location (call));
109 	    /* CWE-242: Use of Inherently Dangerous Function.  */
110 	    diagnostic_metadata m;
111 	    m.add_cwe (242);
112 	    warning_meta (&richloc, m, 0,
113 			  "never use %qs", "gets");
114 	  }
115       }
116 
117   return 0;
118 }
119 
120 int
plugin_init(struct plugin_name_args * plugin_info,struct plugin_gcc_version * version)121 plugin_init (struct plugin_name_args *plugin_info,
122 	     struct plugin_gcc_version *version)
123 {
124   struct register_pass_info pass_info;
125   const char *plugin_name = plugin_info->base_name;
126   int argc = plugin_info->argc;
127   struct plugin_argument *argv = plugin_info->argv;
128 
129   if (!plugin_default_version_check (version, &gcc_version))
130     return 1;
131 
132   pass_info.pass = new pass_test_metadata (g);
133   pass_info.reference_pass_name = "ssa";
134   pass_info.ref_pass_instance_number = 1;
135   pass_info.pos_op = PASS_POS_INSERT_AFTER;
136   register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
137 		     &pass_info);
138 
139   return 0;
140 }
141