libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / testsuite / gcc.dg / plugin / diagnostic_group_plugin.c
blob2f780338b6e74ee1116a96ebe9fb96abff830392
1 /* { dg-options "-O" } */
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 "diagnostic-format-text.h"
31 #include "context.h"
33 int plugin_is_GPL_compatible;
35 /* A custom pass for emitting dummy warnings from the middle-end. */
37 const pass_data pass_data_test_groups =
39 GIMPLE_PASS, /* type */
40 "test_groups", /* 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 */
50 class pass_test_groups : public gimple_opt_pass
52 public:
53 pass_test_groups(gcc::context *ctxt)
54 : gimple_opt_pass(pass_data_test_groups, ctxt)
57 /* opt_pass methods: */
58 bool gate (function *) { return true; }
59 virtual unsigned int execute (function *);
61 }; // class pass_test_groups
63 /* Determine if STMT is a call with NUM_ARGS arguments to a function
64 named FUNCNAME.
65 If so, return STMT as a gcall *. Otherwise return NULL. */
67 static gcall *
68 check_for_named_call (gimple *stmt,
69 const char *funcname, unsigned int num_args)
71 gcc_assert (funcname);
73 gcall *call = dyn_cast <gcall *> (stmt);
74 if (!call)
75 return NULL;
77 tree fndecl = gimple_call_fndecl (call);
78 if (!fndecl)
79 return NULL;
81 if (strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), funcname))
82 return NULL;
84 if (gimple_call_num_args (call) != num_args)
86 error_at (stmt->location, "expected number of args: %i (got %i)",
87 num_args, gimple_call_num_args (call));
88 return NULL;
91 return call;
94 /* Emit a warning at LOC. */
96 static void
97 emit_warning (location_t loc)
99 source_range src_range = get_range_from_loc (line_table, loc);
100 warning_at (loc, 0, "range %i:%i-%i:%i",
101 LOCATION_LINE (src_range.m_start),
102 LOCATION_COLUMN (src_range.m_start),
103 LOCATION_LINE (src_range.m_finish),
104 LOCATION_COLUMN (src_range.m_finish));
107 /* Code for simulating the emission of a warning from the middle-end.
108 Emit a warning for each call to a function named "__emit_warning". */
110 static void
111 test_groups (gimple *stmt)
113 gcall *call = check_for_named_call (stmt, "__emit_warning", 1);
114 if (!call)
115 return;
117 /* We expect an ADDR_EXPR with a STRING_CST inside it for the
118 initial arg. */
119 tree t_addr_string = gimple_call_arg (call, 0);
120 if (TREE_CODE (t_addr_string) != ADDR_EXPR)
122 error_at (call->location, "string literal required for arg 1");
123 return;
126 tree t_string = TREE_OPERAND (t_addr_string, 0);
127 if (TREE_CODE (t_string) != STRING_CST)
129 error_at (call->location, "string literal required for arg 1");
130 return;
134 auto_diagnostic_group d;
135 if (warning_at (call->location, 0, "%s", call,
136 TREE_STRING_POINTER (t_string)))
138 inform (call->location, "message for note");
139 inform (call->location, " some more detail");
140 inform (call->location, " yet more detail");
143 inform (call->location, "an unrelated message");
146 /* Call test_groups on every statement within FUN. */
148 unsigned int
149 pass_test_groups::execute (function *fun)
151 gimple_stmt_iterator gsi;
152 basic_block bb;
154 FOR_EACH_BB_FN (bb, fun)
155 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
157 gimple *stmt = gsi_stmt (gsi);
158 test_groups (stmt);
161 return 0;
164 /* Custom diagnostic callback, to avoid having the path in the
165 expected output. */
167 void
168 test_diagnostic_text_starter (diagnostic_text_output_format &text_output,
169 const diagnostic_info *diagnostic)
171 pp_set_prefix (text_output.get_printer (), xstrdup ("PREFIX: "));
174 /* Custom diagnostic callback, to avoid having the path in the
175 expected output. */
177 void
178 test_diagnostic_start_span_fn (const diagnostic_location_print_policy &,
179 pretty_printer *pp,
180 expanded_location)
182 pp_string (pp, "START_SPAN_FN: ");
183 pp_newline (pp);
186 /* Custom output format subclass. */
188 class test_output_format : public diagnostic_text_output_format
190 public:
191 test_output_format (diagnostic_context &context)
192 : diagnostic_text_output_format (context)
195 void on_begin_group () final override
197 /* Loudly announce a new diagnostic group. */
198 pretty_printer *const pp = get_printer ();
199 pp_string (pp,
200 "================================= BEGIN GROUP ==============================");
201 pp_newline (pp);
203 void on_end_group () final override
205 /* Loudly announce the end of a diagnostic group. */
206 pretty_printer *const pp = get_printer ();
207 pp_set_prefix (pp, NULL);
208 pp_string (pp,
209 "---------------------------------- END GROUP -------------------------------");
210 pp_newline_and_flush (pp);
214 /* Entrypoint for the plugin.
215 Install custom callbacks into the global_dc.
216 Create and register the custom pass. */
219 plugin_init (struct plugin_name_args *plugin_info,
220 struct plugin_gcc_version *version)
222 struct register_pass_info pass_info;
223 const char *plugin_name = plugin_info->base_name;
224 int argc = plugin_info->argc;
225 struct plugin_argument *argv = plugin_info->argv;
227 if (!plugin_default_version_check (version, &gcc_version))
228 return 1;
230 diagnostic_text_starter (global_dc) = test_diagnostic_text_starter;
231 diagnostic_start_span (global_dc) = test_diagnostic_start_span_fn;
232 global_dc->set_output_format (new test_output_format (*global_dc));
234 pass_info.pass = new pass_test_groups (g);
235 pass_info.reference_pass_name = "*warn_function_noreturn";
236 pass_info.ref_pass_instance_number = 1;
237 pass_info.pos_op = PASS_POS_INSERT_AFTER;
238 register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
239 &pass_info);
241 return 0;