Mercurial > hg > CbC > CbC_gcc
comparison gcc/testsuite/gcc.dg/plugin/diagnostic_group_plugin.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
111:04ced10e8804 | 131:84e7813d76e9 |
---|---|
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-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 "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 emitting dummy warnings from the middle-end. */ | |
35 | |
36 const pass_data pass_data_test_groups = | |
37 { | |
38 GIMPLE_PASS, /* type */ | |
39 "test_groups", /* name */ | |
40 OPTGROUP_NONE, /* optinfo_flags */ | |
41 TV_NONE, /* tv_id */ | |
42 PROP_ssa, /* properties_required */ | |
43 0, /* properties_provided */ | |
44 0, /* properties_destroyed */ | |
45 0, /* todo_flags_start */ | |
46 0, /* todo_flags_finish */ | |
47 }; | |
48 | |
49 class pass_test_groups : public gimple_opt_pass | |
50 { | |
51 public: | |
52 pass_test_groups(gcc::context *ctxt) | |
53 : gimple_opt_pass(pass_data_test_groups, ctxt) | |
54 {} | |
55 | |
56 /* opt_pass methods: */ | |
57 bool gate (function *) { return true; } | |
58 virtual unsigned int execute (function *); | |
59 | |
60 }; // class pass_test_groups | |
61 | |
62 /* Determine if STMT is a call with NUM_ARGS arguments to a function | |
63 named FUNCNAME. | |
64 If so, return STMT as a gcall *. Otherwise return NULL. */ | |
65 | |
66 static gcall * | |
67 check_for_named_call (gimple *stmt, | |
68 const char *funcname, unsigned int num_args) | |
69 { | |
70 gcc_assert (funcname); | |
71 | |
72 gcall *call = dyn_cast <gcall *> (stmt); | |
73 if (!call) | |
74 return NULL; | |
75 | |
76 tree fndecl = gimple_call_fndecl (call); | |
77 if (!fndecl) | |
78 return NULL; | |
79 | |
80 if (strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), funcname)) | |
81 return NULL; | |
82 | |
83 if (gimple_call_num_args (call) != num_args) | |
84 { | |
85 error_at (stmt->location, "expected number of args: %i (got %i)", | |
86 num_args, gimple_call_num_args (call)); | |
87 return NULL; | |
88 } | |
89 | |
90 return call; | |
91 } | |
92 | |
93 /* Emit a warning at LOC. */ | |
94 | |
95 static void | |
96 emit_warning (location_t loc) | |
97 { | |
98 source_range src_range = get_range_from_loc (line_table, loc); | |
99 warning_at (loc, 0, "range %i:%i-%i:%i", | |
100 LOCATION_LINE (src_range.m_start), | |
101 LOCATION_COLUMN (src_range.m_start), | |
102 LOCATION_LINE (src_range.m_finish), | |
103 LOCATION_COLUMN (src_range.m_finish)); | |
104 } | |
105 | |
106 /* Code for simulating the emission of a warning from the middle-end. | |
107 Emit a warning for each call to a function named "__emit_warning". */ | |
108 | |
109 static void | |
110 test_groups (gimple *stmt) | |
111 { | |
112 gcall *call = check_for_named_call (stmt, "__emit_warning", 1); | |
113 if (!call) | |
114 return; | |
115 | |
116 /* We expect an ADDR_EXPR with a STRING_CST inside it for the | |
117 initial arg. */ | |
118 tree t_addr_string = gimple_call_arg (call, 0); | |
119 if (TREE_CODE (t_addr_string) != ADDR_EXPR) | |
120 { | |
121 error_at (call->location, "string literal required for arg 1"); | |
122 return; | |
123 } | |
124 | |
125 tree t_string = TREE_OPERAND (t_addr_string, 0); | |
126 if (TREE_CODE (t_string) != STRING_CST) | |
127 { | |
128 error_at (call->location, "string literal required for arg 1"); | |
129 return; | |
130 } | |
131 | |
132 { | |
133 auto_diagnostic_group d; | |
134 if (warning_at (call->location, 0, "%s", call, | |
135 TREE_STRING_POINTER (t_string))) | |
136 { | |
137 inform (call->location, "message for note"); | |
138 inform (call->location, " some more detail"); | |
139 inform (call->location, " yet more detail"); | |
140 } | |
141 } | |
142 inform (call->location, "an unrelated message"); | |
143 } | |
144 | |
145 /* Call test_groups on every statement within FUN. */ | |
146 | |
147 unsigned int | |
148 pass_test_groups::execute (function *fun) | |
149 { | |
150 gimple_stmt_iterator gsi; | |
151 basic_block bb; | |
152 | |
153 FOR_EACH_BB_FN (bb, fun) | |
154 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | |
155 { | |
156 gimple *stmt = gsi_stmt (gsi); | |
157 test_groups (stmt); | |
158 } | |
159 | |
160 return 0; | |
161 } | |
162 | |
163 /* Custom diagnostic callback, to avoid having the path in the | |
164 expected output. */ | |
165 | |
166 void | |
167 test_diagnostic_starter (diagnostic_context *context, | |
168 diagnostic_info *diagnostic) | |
169 { | |
170 pp_set_prefix (context->printer, xstrdup ("PREFIX: ")); | |
171 } | |
172 | |
173 /* Custom diagnostic callback, to avoid having the path in the | |
174 expected output. */ | |
175 | |
176 void | |
177 test_diagnostic_start_span_fn (diagnostic_context *context, | |
178 expanded_location exploc) | |
179 { | |
180 pp_string (context->printer, "START_SPAN_FN: "); | |
181 pp_newline (context->printer); | |
182 } | |
183 | |
184 /* Custom diagnostic callback: loudly announce a new diagnostic group. */ | |
185 | |
186 static void | |
187 test_begin_group_cb (diagnostic_context * context) | |
188 { | |
189 pp_string (context->printer, | |
190 "================================= BEGIN GROUP =============================="); | |
191 pp_newline (context->printer); | |
192 } | |
193 | |
194 /* Custom diagnostic callback: loudly announce the end of a | |
195 diagnostic group. */ | |
196 | |
197 static void | |
198 test_end_group_cb (diagnostic_context * context) | |
199 { | |
200 pp_string (context->printer, | |
201 "---------------------------------- END GROUP -------------------------------"); | |
202 pp_newline_and_flush (context->printer); | |
203 } | |
204 | |
205 /* Entrypoint for the plugin. | |
206 Install custom callbacks into the global_dc. | |
207 Create and register the custom pass. */ | |
208 | |
209 int | |
210 plugin_init (struct plugin_name_args *plugin_info, | |
211 struct plugin_gcc_version *version) | |
212 { | |
213 struct register_pass_info pass_info; | |
214 const char *plugin_name = plugin_info->base_name; | |
215 int argc = plugin_info->argc; | |
216 struct plugin_argument *argv = plugin_info->argv; | |
217 | |
218 if (!plugin_default_version_check (version, &gcc_version)) | |
219 return 1; | |
220 | |
221 diagnostic_starter (global_dc) = test_diagnostic_starter; | |
222 global_dc->start_span = test_diagnostic_start_span_fn; | |
223 global_dc->begin_group_cb = test_begin_group_cb; | |
224 global_dc->end_group_cb = test_end_group_cb; | |
225 | |
226 pass_info.pass = new pass_test_groups (g); | |
227 pass_info.reference_pass_name = "*warn_function_noreturn"; | |
228 pass_info.ref_pass_instance_number = 1; | |
229 pass_info.pos_op = PASS_POS_INSERT_AFTER; | |
230 register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, | |
231 &pass_info); | |
232 | |
233 return 0; | |
234 } |