1 /* { dg-options "-O" } */
3 #include "gcc-plugin.h"
9 #include "stringpool.h"
11 #include "basic-block.h"
12 #include "hash-table.h"
15 #include "basic-block.h"
16 #include "tree-ssa-alias.h"
17 #include "internal-fn.h"
18 #include "gimple-fold.h"
20 #include "gimple-expr.h"
23 #include "gimple-iterator.h"
25 #include "tree-pass.h"
27 #include "plugin-version.h"
28 #include "c-family/c-common.h"
29 #include "diagnostic.h"
32 int plugin_is_GPL_compatible
;
34 /* A custom pass for emitting dummy warnings from the middle-end. */
36 const pass_data pass_data_test_groups
=
38 GIMPLE_PASS
, /* type */
39 "test_groups", /* name */
40 OPTGROUP_NONE
, /* optinfo_flags */
42 PROP_ssa
, /* properties_required */
43 0, /* properties_provided */
44 0, /* properties_destroyed */
45 0, /* todo_flags_start */
46 0, /* todo_flags_finish */
49 class pass_test_groups
: public gimple_opt_pass
52 pass_test_groups(gcc::context
*ctxt
)
53 : gimple_opt_pass(pass_data_test_groups
, ctxt
)
56 /* opt_pass methods: */
57 bool gate (function
*) { return true; }
58 virtual unsigned int execute (function
*);
60 }; // class pass_test_groups
62 /* Determine if STMT is a call with NUM_ARGS arguments to a function
64 If so, return STMT as a gcall *. Otherwise return NULL. */
67 check_for_named_call (gimple
*stmt
,
68 const char *funcname
, unsigned int num_args
)
70 gcc_assert (funcname
);
72 gcall
*call
= dyn_cast
<gcall
*> (stmt
);
76 tree fndecl
= gimple_call_fndecl (call
);
80 if (strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl
)), funcname
))
83 if (gimple_call_num_args (call
) != num_args
)
85 error_at (stmt
->location
, "expected number of args: %i (got %i)",
86 num_args
, gimple_call_num_args (call
));
93 /* Emit a warning at LOC. */
96 emit_warning (location_t loc
)
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
));
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". */
110 test_groups (gimple
*stmt
)
112 gcall
*call
= check_for_named_call (stmt
, "__emit_warning", 1);
116 /* We expect an ADDR_EXPR with a STRING_CST inside it for the
118 tree t_addr_string
= gimple_call_arg (call
, 0);
119 if (TREE_CODE (t_addr_string
) != ADDR_EXPR
)
121 error_at (call
->location
, "string literal required for arg 1");
125 tree t_string
= TREE_OPERAND (t_addr_string
, 0);
126 if (TREE_CODE (t_string
) != STRING_CST
)
128 error_at (call
->location
, "string literal required for arg 1");
133 auto_diagnostic_group d
;
134 if (warning_at (call
->location
, 0, "%s", call
,
135 TREE_STRING_POINTER (t_string
)))
137 inform (call
->location
, "message for note");
138 inform (call
->location
, " some more detail");
139 inform (call
->location
, " yet more detail");
142 inform (call
->location
, "an unrelated message");
145 /* Call test_groups on every statement within FUN. */
148 pass_test_groups::execute (function
*fun
)
150 gimple_stmt_iterator gsi
;
153 FOR_EACH_BB_FN (bb
, fun
)
154 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
156 gimple
*stmt
= gsi_stmt (gsi
);
163 /* Custom diagnostic callback, to avoid having the path in the
167 test_diagnostic_starter (diagnostic_context
*context
,
168 diagnostic_info
*diagnostic
)
170 pp_set_prefix (context
->printer
, xstrdup ("PREFIX: "));
173 /* Custom diagnostic callback, to avoid having the path in the
177 test_diagnostic_start_span_fn (diagnostic_context
*context
,
178 expanded_location exploc
)
180 pp_string (context
->printer
, "START_SPAN_FN: ");
181 pp_newline (context
->printer
);
184 /* Custom diagnostic callback: loudly announce a new diagnostic group. */
187 test_begin_group_cb (diagnostic_context
* context
)
189 pp_string (context
->printer
,
190 "================================= BEGIN GROUP ==============================");
191 pp_newline (context
->printer
);
194 /* Custom diagnostic callback: loudly announce the end of a
198 test_end_group_cb (diagnostic_context
* context
)
200 pp_string (context
->printer
,
201 "---------------------------------- END GROUP -------------------------------");
202 pp_newline_and_flush (context
->printer
);
205 /* Entrypoint for the plugin.
206 Install custom callbacks into the global_dc.
207 Create and register the custom pass. */
210 plugin_init (struct plugin_name_args
*plugin_info
,
211 struct plugin_gcc_version
*version
)
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
;
218 if (!plugin_default_version_check (version
, &gcc_version
))
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
;
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
,