No functional change intended.
gcc/analyzer/ChangeLog:
* analyzer.cc: Convert gcall * to gcall & where we know the
pointer must be non-null.
* call-details.cc: Likewise.
* call-details.h: Likewise.
* call-info.cc: Likewise.
* call-info.h: Likewise.
* call-summary.h: Likewise.
* checker-event.cc: Likewise.
* checker-event.h: Likewise.
* common.h: Likewise.
* diagnostic-manager.cc: Likewise.
* engine.cc: Likewise.
* exploded-graph.h: Likewise.
* kf-analyzer.cc: Likewise.
* kf-lang-cp.cc: Likewise.
* kf.cc: Likewise.
* known-function-manager.cc: Likewise.
* program-state.cc: Likewise.
* program-state.h: Likewise.
* region-model.cc: Likewise.
* region-model.h: Likewise.
* sm-fd.cc: Likewise.
* sm-file.cc: Likewise.
* sm-malloc.cc: Likewise.
* sm-sensitive.cc: Likewise.
* sm-signal.cc: Likewise.
* sm-taint.cc: Likewise.
* sm.h: Likewise.
* store.cc: Likewise.
* store.h: Likewise.
* supergraph.cc: Likewise.
* supergraph.h: Likewise.
* svalue.h: Likewise.
* varargs.cc: Likewise.
gcc/testsuite/ChangeLog:
* gcc.dg/plugin/analyzer_gil_plugin.cc: Convert gcall * to gcall &
where we know the pointer must be non-null.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
If LOOK_IN_STD is true, then also look for within std:: for the name. */
bool
-is_special_named_call_p (const gcall *call, const char *funcname,
+is_special_named_call_p (const gcall &call, const char *funcname,
unsigned int num_args, bool look_in_std)
{
gcc_assert (funcname);
- tree fndecl = gimple_call_fndecl (call);
+ tree fndecl = gimple_call_fndecl (&call);
if (!fndecl)
return false;
bool
is_named_call_p (const_tree fndecl, const char *funcname,
- const gcall *call, unsigned int num_args)
+ const gcall &call, unsigned int num_args)
{
gcc_assert (fndecl);
gcc_assert (funcname);
if (!is_named_call_p (fndecl, funcname))
return false;
- if (gimple_call_num_args (call) != num_args)
+ if (gimple_call_num_args (&call) != num_args)
return false;
return true;
bool
is_std_named_call_p (const_tree fndecl, const char *funcname,
- const gcall *call, unsigned int num_args)
+ const gcall &call, unsigned int num_args)
{
gcc_assert (fndecl);
gcc_assert (funcname);
if (!is_std_named_call_p (fndecl, funcname))
return false;
- if (gimple_call_num_args (call) != num_args)
+ if (gimple_call_num_args (&call) != num_args)
return false;
return true;
/* Return true if stmt is a setjmp or sigsetjmp call. */
bool
-is_setjmp_call_p (const gcall *call)
+is_setjmp_call_p (const gcall &call)
{
if (is_special_named_call_p (call, "setjmp", 1)
|| is_special_named_call_p (call, "sigsetjmp", 2))
/* region_model::on_setjmp requires a pointer. */
- if (POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (call, 0))))
+ if (POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (&call, 0))))
return true;
return false;
/* Return true if stmt is a longjmp or siglongjmp call. */
bool
-is_longjmp_call_p (const gcall *call)
+is_longjmp_call_p (const gcall &call)
{
if (is_special_named_call_p (call, "longjmp", 2)
|| is_special_named_call_p (call, "siglongjmp", 2))
/* exploded_node::on_longjmp requires a pointer for the initial
argument. */
- if (POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (call, 0))))
+ if (POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (&call, 0))))
return true;
return false;
diagnostics (stripping the leading underscores). */
const char *
-get_user_facing_name (const gcall *call)
+get_user_facing_name (const gcall &call)
{
- tree fndecl = gimple_call_fndecl (call);
+ tree fndecl = gimple_call_fndecl (&call);
gcc_assert (fndecl);
tree identifier = DECL_NAME (fndecl);
/* call_details's ctor. */
-call_details::call_details (const gcall *call, region_model *model,
+call_details::call_details (const gcall &call, region_model *model,
region_model_context *ctxt)
: m_call (call), m_model (model), m_ctxt (ctxt),
m_lhs_type (NULL_TREE), m_lhs_region (NULL)
{
m_lhs_type = NULL_TREE;
- if (tree lhs = gimple_call_lhs (call))
+ if (tree lhs = gimple_call_lhs (&call))
{
m_lhs_region = model->get_lvalue (lhs, ctxt);
m_lhs_type = TREE_TYPE (lhs);
call_details::call_details (const call_details &cd,
region_model_context *ctxt)
+: m_call (cd.m_call), m_model (cd.m_model),
+ m_ctxt (ctxt),
+ m_lhs_type (cd.m_lhs_type),
+ m_lhs_region (cd.m_lhs_region)
{
- *this = cd;
- m_ctxt = ctxt;
}
/* Get the manager from m_model. */
unsigned
call_details::num_args () const
{
- return gimple_call_num_args (m_call);
+ return gimple_call_num_args (&m_call);
}
/* Return true if argument IDX is a size_t (or compatible with it). */
location_t
call_details::get_location () const
{
- return m_call->location;
+ return m_call.location;
}
/* Get argument IDX at the callsite as a tree. */
tree
call_details::get_arg_tree (unsigned idx) const
{
- return gimple_call_arg (m_call, idx);
+ return gimple_call_arg (&m_call, idx);
}
/* Get the type of argument IDX. */
tree
call_details::get_arg_type (unsigned idx) const
{
- return TREE_TYPE (gimple_call_arg (m_call, idx));
+ return TREE_TYPE (gimple_call_arg (&m_call, idx));
}
/* Get argument IDX at the callsite as an svalue. */
call_details::dump_to_pp (pretty_printer *pp, bool simple) const
{
pp_string (pp, "gcall: ");
- pp_gimple_stmt_1 (pp, m_call, 0 /* spc */, TDF_NONE /* flags */);
+ pp_gimple_stmt_1 (pp, &m_call, 0 /* spc */, TDF_NONE /* flags */);
pp_newline (pp);
pp_string (pp, "return region: ");
if (m_lhs_region)
else
pp_string (pp, "NULL");
pp_newline (pp);
- for (unsigned i = 0; i < gimple_call_num_args (m_call); i++)
+ for (unsigned i = 0; i < gimple_call_num_args (&m_call); i++)
{
const svalue *arg_sval = get_arg_svalue (i);
pp_printf (pp, "arg %i: ", i);
pretty_printer * const pp = &the_pp;
pp_format_decoder (pp) = default_tree_printer;
pp_string (pp, "gcall: ");
- pp_gimple_stmt_1 (pp, m_call, 0 /* spc */, TDF_NONE /* flags */);
+ pp_gimple_stmt_1 (pp, &m_call, 0 /* spc */, TDF_NONE /* flags */);
cd_widget->add_child (tree_widget::make (dwi, pp));
}
{
w->add_child (m_lhs_region->make_dump_widget (dwi));
cd_widget->add_child (std::move (w));
}
- if (gimple_call_num_args (m_call) > 0)
+ if (gimple_call_num_args (&m_call) > 0)
{
std::unique_ptr<tree_widget> args_widget
(tree_widget::from_fmt (dwi, nullptr, "Arguments"));
- for (unsigned i = 0; i < gimple_call_num_args (m_call); i++)
+ for (unsigned i = 0; i < gimple_call_num_args (&m_call); i++)
{
pretty_printer the_pp;
pretty_printer * const pp = &the_pp;
call_details::get_or_create_conjured_svalue (const region *reg) const
{
region_model_manager *mgr = m_model->get_manager ();
- return mgr->get_or_create_conjured_svalue (reg->get_type (), m_call, reg,
+ return mgr->get_or_create_conjured_svalue (reg->get_type (), &m_call, reg,
conjured_purge (m_model, m_ctxt));
}
if (tree fndecl = get_fndecl_for_call ())
allocfntype = TREE_TYPE (fndecl);
else
- allocfntype = gimple_call_fntype (m_call);
+ allocfntype = gimple_call_fntype (&m_call);
if (!allocfntype)
return NULL_TREE;
class call_details
{
public:
- call_details (const gcall *call, region_model *model,
+ call_details (const gcall &call, region_model *model,
region_model_context *ctxt);
call_details (const call_details &cd, region_model_context *ctxt);
return INTEGRAL_TYPE_P (get_arg_type (idx));
}
- const gcall *get_call_stmt () const { return m_call; }
+ const gcall &get_call_stmt () const { return m_call; }
location_t get_location () const;
tree get_arg_tree (unsigned idx) const;
const svalue *num_bytes_read_sval) const;
private:
- const gcall *m_call;
+ const gcall &m_call;
region_model *m_model;
region_model_context *m_ctxt;
tree m_lhs_type;
bool operator== (const call_arg_details &other) const
{
- return (m_call == other.m_call
+ return (&m_call == &other.m_call
&& m_called_fndecl == other.m_called_fndecl
&& m_arg_idx == other.m_arg_idx
&& pending_diagnostic::same_tree_p (m_arg_expr, other.m_arg_expr));
}
- const gcall *m_call;
+ const gcall &m_call;
tree m_called_fndecl;
unsigned m_arg_idx; // 0-based
tree m_arg_expr;
const int stack_depth = src_point.get_stack_depth ();
emission_path->add_event
- (make_unique<call_event> (event_loc_info (get_call_stmt ()->location,
+ (make_unique<call_event> (event_loc_info (get_call_stmt ().location,
caller_fndecl,
stack_depth),
this));
void add_events_to_path (checker_path *emission_path,
const exploded_edge &eedge) const final override;
- const gcall *get_call_stmt () const { return m_call_stmt; }
+ const gcall &get_call_stmt () const { return m_call_stmt; }
tree get_fndecl () const { return m_fndecl; }
virtual void print_desc (pretty_printer &pp) const = 0;
call_info (const call_details &cd, const function &called_fn);
private:
- const gcall *m_call_stmt;
+ const gcall &m_call_stmt;
tree m_fndecl;
};
const extrinsic_state &ext_state);
const call_details &get_call_details () const { return m_cd; }
- const gcall *get_call_stmt () const { return m_cd.get_call_stmt (); }
+ const gcall &get_call_stmt () const { return m_cd.get_call_stmt (); }
region_model_manager *get_manager () const { return m_cd.get_manager (); }
store_manager *get_store_manager () const
{
&& zerop (rhs))
{
if (gcall *call = dyn_cast <gcall *> (SSA_NAME_DEF_STMT (lhs)))
- if (is_special_named_call_p (call, "strcmp", 2))
+ if (is_special_named_call_p (*call, "strcmp", 2))
{
if (op == EQ_EXPR)
return label_text::borrow ("when the strings are equal");
public:
setjmp_event (const event_loc_info &loc_info,
const exploded_node *enode,
- const gcall *setjmp_call)
+ const gcall &setjmp_call)
: checker_event (event_kind::setjmp_, loc_info),
m_enode (enode), m_setjmp_call (setjmp_call)
{
private:
const exploded_node *m_enode;
- const gcall *m_setjmp_call;
+ const gcall &m_setjmp_call;
};
/* An abstract event subclass for rewinding from a longjmp to a setjmp
} // namespace ana
-extern bool is_special_named_call_p (const gcall *call, const char *funcname,
+extern bool is_special_named_call_p (const gcall &call, const char *funcname,
unsigned int num_args,
bool look_in_std = false);
extern bool is_named_call_p (const_tree fndecl, const char *funcname);
extern bool is_named_call_p (const_tree fndecl, const char *funcname,
- const gcall *call, unsigned int num_args);
+ const gcall &call, unsigned int num_args);
extern bool is_std_function_p (const_tree fndecl);
extern bool is_std_named_call_p (const_tree fndecl, const char *funcname);
extern bool is_std_named_call_p (const_tree fndecl, const char *funcname,
- const gcall *call, unsigned int num_args);
-extern bool is_setjmp_call_p (const gcall *call);
-extern bool is_longjmp_call_p (const gcall *call);
-extern bool is_placement_new_p (const gcall *call);
+ const gcall &call, unsigned int num_args);
+extern bool is_setjmp_call_p (const gcall &call);
+extern bool is_longjmp_call_p (const gcall &call);
+extern bool is_placement_new_p (const gcall &call);
-extern const char *get_user_facing_name (const gcall *call);
+extern const char *get_user_facing_name (const gcall &call);
extern void register_analyzer_pass ();
{
}
- tree get_fndecl_for_call (const gcall */*call*/) final override
+ tree get_fndecl_for_call (const gcall &/*call*/) final override
{
return NULL_TREE;
}
{
const gimple *stmt = dst_point.get_stmt ();
const gcall *call = dyn_cast <const gcall *> (stmt);
- if (call && is_setjmp_call_p (call))
+ if (call && is_setjmp_call_p (*call))
emission_path->add_event
(make_unique<setjmp_event> (event_loc_info (stmt->location,
dst_point.get_fndecl (),
dst_stack_depth),
dst_node,
- call));
+ *call));
else
emission_path->add_event
(make_unique<statement_event> (stmt,
const return_superedge *return_edge
= as_a <const return_superedge *> (eedge.m_sedge);
- const gcall *call_stmt = return_edge->get_call_stmt ();
+ const gcall &call_stmt = return_edge->get_call_stmt ();
emission_path->add_event
(make_unique<return_event> (eedge,
- event_loc_info (call_stmt
- ? call_stmt->location
- : UNKNOWN_LOCATION,
+ event_loc_info (call_stmt.location,
dst_point.get_fndecl (),
dst_stack_depth)));
}
logger *get_logger () const { return m_logger.get_logger (); }
- tree get_fndecl_for_call (const gcall *call) final override
+ tree get_fndecl_for_call (const gcall &call) final override
{
impl_region_model_context old_ctxt
(m_eg, m_enode_for_diag, NULL, NULL, NULL/*m_enode->get_state ()*/,
- NULL, call);
+ NULL, &call);
region_model *model = m_new_state->m_region_model;
return model->get_fndecl_for_call (call, &old_ctxt);
}
gcc_assert (called_fn);
return replay_call_summaries (eg,
snode,
- as_a <const gcall *> (stmt),
+ *as_a <const gcall *> (stmt),
state,
path_ctxt,
*called_fn,
region_model_context *ctxt)
{
/* Handle special-case calls that require the full program_state. */
- if (const gcall *call = dyn_cast <const gcall *> (stmt))
+ if (const gcall *call_stmt = dyn_cast <const gcall *> (stmt))
{
+ const gcall &call = *call_stmt;
if (is_special_named_call_p (call, "__analyzer_dump", 0))
{
/* Handle the builtin "__analyzer_dump" by dumping state
region_model_context *ctxt)
{
if (const gcall *call = dyn_cast <const gcall *> (stmt))
- state->m_region_model->on_call_post (call, unknown_side_effects, ctxt);
+ state->m_region_model->on_call_post (*call, unknown_side_effects, ctxt);
}
/* A concrete call_info subclass representing a replay of a call summary. */
exploded_node::on_stmt_flags
exploded_node::replay_call_summaries (exploded_graph &eg,
const supernode *snode,
- const gcall *call_stmt,
+ const gcall &call_stmt,
program_state *state,
path_context *path_ctxt,
const function &called_fn,
void
exploded_node::replay_call_summary (exploded_graph &eg,
const supernode *snode,
- const gcall *call_stmt,
+ const gcall &call_stmt,
program_state *old_state,
path_context *path_ctxt,
const function &called_fn,
logger *logger = eg.get_logger ();
LOG_SCOPE (logger);
gcc_assert (snode);
- gcc_assert (call_stmt);
gcc_assert (old_state);
gcc_assert (summary);
class stale_jmp_buf : public pending_diagnostic_subclass<stale_jmp_buf>
{
public:
- stale_jmp_buf (const gcall *setjmp_call, const gcall *longjmp_call,
+ stale_jmp_buf (const gcall &setjmp_call, const gcall &longjmp_call,
const program_point &setjmp_point)
: m_setjmp_call (setjmp_call), m_longjmp_call (longjmp_call),
m_setjmp_point (setjmp_point), m_stack_pop_event (NULL)
bool operator== (const stale_jmp_buf &other) const
{
- return (m_setjmp_call == other.m_setjmp_call
- && m_longjmp_call == other.m_longjmp_call);
+ return (&m_setjmp_call == &other.m_setjmp_call
+ && &m_longjmp_call == &other.m_longjmp_call);
}
bool
private:
- const gcall *m_setjmp_call;
- const gcall *m_longjmp_call;
+ const gcall &m_setjmp_call;
+ const gcall &m_longjmp_call;
program_point m_setjmp_point;
custom_event *m_stack_pop_event;
};
void
exploded_node::on_longjmp (exploded_graph &eg,
- const gcall *longjmp_call,
+ const gcall &longjmp_call,
program_state *new_state,
region_model_context *ctxt)
{
- tree buf_ptr = gimple_call_arg (longjmp_call, 0);
+ tree buf_ptr = gimple_call_arg (&longjmp_call, 0);
gcc_assert (POINTER_TYPE_P (TREE_TYPE (buf_ptr)));
region_model *new_region_model = new_state->m_region_model;
call back to the setjmp/sigsetjmp. */
rewind_info_t rewind_info (tmp_setjmp_record, longjmp_call);
- const gcall *setjmp_call = rewind_info.get_setjmp_call ();
+ const gcall &setjmp_call = rewind_info.get_setjmp_call ();
const program_point &setjmp_point = rewind_info.get_setjmp_point ();
const program_point &longjmp_point = get_point ();
if (m_is_returning_call)
emission_path->add_event
(make_unique<return_event> (eedge,
- event_loc_info (m_dynamic_call
- ? m_dynamic_call->location
- : UNKNOWN_LOCATION,
+ event_loc_info (m_dynamic_call.location,
dest_point.get_fndecl (),
dest_stack_depth)));
else
emission_path->add_event
(make_unique<call_event> (eedge,
- event_loc_info (m_dynamic_call
- ? m_dynamic_call->location
- : UNKNOWN_LOCATION,
+ event_loc_info (m_dynamic_call.location,
src_point.get_fndecl (),
src_stack_depth)));
}
emission_path->add_event
(make_unique<rewind_from_longjmp_event>
(&eedge,
- event_loc_info (get_longjmp_call ()->location,
+ event_loc_info (get_longjmp_call ().location,
src_point.get_fndecl (),
src_stack_depth),
this));
emission_path->add_event
(make_unique<rewind_to_setjmp_event>
(&eedge,
- event_loc_info (get_setjmp_call ()->location,
+ event_loc_info (get_setjmp_call ().location,
dst_point.get_fndecl (),
dst_stack_depth),
this));
stmt_requires_new_enode_p (const gimple *stmt,
const gimple *prev_stmt)
{
- if (const gcall *call = dyn_cast <const gcall *> (stmt))
+ if (const gcall *call_stmt = dyn_cast <const gcall *> (stmt))
{
+ const gcall &call = *call_stmt;
/* Stop consolidating at calls to
"__analyzer_dump_exploded_nodes", so they always appear at the
start of an exploded_node. */
functions or calls that happen via function pointer. */
bool
-exploded_graph::maybe_create_dynamic_call (const gcall *call,
+exploded_graph::maybe_create_dynamic_call (const gcall &call,
tree fn_decl,
exploded_node *node,
program_state next_state,
class jump_through_null : public pending_diagnostic_subclass<jump_through_null>
{
public:
- jump_through_null (const gcall *call)
+ jump_through_null (const gcall &call)
: m_call (call)
{}
bool operator== (const jump_through_null &other) const
{
- return m_call == other.m_call;
+ return &m_call == &other.m_call;
}
int get_controlling_option () const final override
}
private:
- const gcall *m_call;
+ const gcall &m_call;
};
/* The core of exploded_graph::process_worklist (the main analysis loop),
if (succ->m_kind == SUPEREDGE_INTRAPROCEDURAL_CALL
&& !(succ->get_any_callgraph_edge ()))
{
- const gcall *call
- = point.get_supernode ()->get_final_call ();
+ const gcall &call
+ = *point.get_supernode ()->get_final_call ();
impl_region_model_context ctxt (*this,
node,
if (!call_discovered)
{
/* Check for jump through NULL. */
- if (tree fn_ptr = gimple_call_fn (call))
+ if (tree fn_ptr = gimple_call_fn (&call))
{
const svalue *fn_ptr_sval
= model->get_rvalue (fn_ptr, &ctxt);
= next_point.get_supernode ()->get_returning_call ();
if (call)
- next_state.returning_call (*this, node, call, &uncertainty);
+ next_state.returning_call (*this, node, *call, &uncertainty);
if (next_state.m_valid)
{
node);
if (enode)
add_edge (node, enode, NULL, false,
- make_unique<dynamic_call_info_t> (call, true));
+ make_unique<dynamic_call_info_t> (*call, true));
}
}
}
m_model.on_asm_stmt (asm_stmt, NULL);
else if (const gcall *call = dyn_cast <const gcall *> (stmt))
{
- bool unknown_side_effects = m_model.on_call_pre (call, NULL);
- m_model.on_call_post (call, unknown_side_effects, NULL);
+ bool unknown_side_effects = m_model.on_call_pre (*call, NULL);
+ m_model.on_call_post (*call, unknown_side_effects, NULL);
}
else if (const greturn *return_ = dyn_cast <const greturn *> (stmt))
m_model.on_return (return_, NULL);
if (const gimple *stmt = enode->get_stmt ())
if (const gcall *call = dyn_cast <const gcall *> (stmt))
- if (is_special_named_call_p (call, "__analyzer_dump_exploded_nodes",
+ if (is_special_named_call_p (*call, "__analyzer_dump_exploded_nodes",
1))
{
if (seen.contains (stmt))
on_stmt_flags replay_call_summaries (exploded_graph &eg,
const supernode *snode,
- const gcall *call_stmt,
+ const gcall &call_stmt,
program_state *state,
path_context *path_ctxt,
const function &called_fn,
region_model_context *ctxt);
void replay_call_summary (exploded_graph &eg,
const supernode *snode,
- const gcall *call_stmt,
+ const gcall &call_stmt,
program_state *state,
path_context *path_ctxt,
const function &called_fn,
program_state *next_state,
uncertainty_t *uncertainty);
void on_longjmp (exploded_graph &eg,
- const gcall *call,
+ const gcall &call,
program_state *new_state,
region_model_context *ctxt);
class dynamic_call_info_t : public custom_edge_info
{
public:
- dynamic_call_info_t (const gcall *dynamic_call,
+ dynamic_call_info_t (const gcall &dynamic_call,
const bool is_returning_call = false)
: m_dynamic_call (dynamic_call),
m_is_returning_call (is_returning_call)
void add_events_to_path (checker_path *emission_path,
const exploded_edge &eedge) const final override;
private:
- const gcall *m_dynamic_call;
+ const gcall &m_dynamic_call;
const bool m_is_returning_call;
};
{
public:
rewind_info_t (const setjmp_record &setjmp_record,
- const gcall *longjmp_call)
+ const gcall &longjmp_call)
: m_setjmp_record (setjmp_record),
m_longjmp_call (longjmp_call)
{}
return origin_point;
}
- const gcall *get_setjmp_call () const
+ const gcall &get_setjmp_call () const
{
- return m_setjmp_record.m_setjmp_call;
+ return *m_setjmp_record.m_setjmp_call;
}
- const gcall *get_longjmp_call () const
+ const gcall &get_longjmp_call () const
{
return m_longjmp_call;
}
private:
setjmp_record m_setjmp_record;
- const gcall *m_longjmp_call;
+ const gcall &m_longjmp_call;
};
/* Statistics about aspects of an exploded_graph. */
bool maybe_process_run_of_before_supernode_enodes (exploded_node *node);
void process_node (exploded_node *node);
- bool maybe_create_dynamic_call (const gcall *call,
+ bool maybe_create_dynamic_call (const gcall &call,
tree fn_decl,
exploded_node *node,
program_state next_state,
const region *base_reg = reg->get_base_region ();
const svalue *capacity = model->get_capacity (base_reg);
label_text desc = capacity->get_desc (true);
- warning_at (cd.get_call_stmt ()->location, 0,
+ warning_at (cd.get_call_stmt ().location, 0,
"capacity: %qs", desc.get ());
}
};
See https://en.cppreference.com/w/cpp/memory/new/operator_new. */
-bool is_placement_new_p (const gcall *call)
+bool is_placement_new_p (const gcall &call)
{
- gcc_assert (call);
- tree fndecl = gimple_call_fndecl (call);
+ tree fndecl = gimple_call_fndecl (&call);
if (!fndecl || TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE)
/* Give up on overloaded operator new. */
region_model_manager *mgr = cd.get_manager ();
const svalue *size_sval = cd.get_arg_svalue (0);
region_model_context *ctxt = cd.get_ctxt ();
- const gcall *call = cd.get_call_stmt ();
+ const gcall &call = cd.get_call_stmt ();
/* If the call was actually a placement new, check that accessing
the buffer lhs is placed into does not result in out-of-bounds. */
: m_call_stmt (cd.get_call_stmt ()),
m_callee_fndecl (cd.get_fndecl_for_call ())
{
- gcc_assert (m_call_stmt);
gcc_assert (m_callee_fndecl);
}
bool operator== (const undefined_function_behavior &other) const
{
- return (m_call_stmt == other.m_call_stmt
+ return (&m_call_stmt == &other.m_call_stmt
&& m_callee_fndecl == other.m_callee_fndecl);
}
tree get_callee_fndecl () const { return m_callee_fndecl; }
private:
- const gimple *m_call_stmt;
+ const gimple &m_call_stmt;
tree m_callee_fndecl;
};
using the str_reg as the id of the conjured_svalue. */
const svalue *offset
= mgr->get_or_create_conjured_svalue (size_type_node,
- cd.get_call_stmt (),
+ &cd.get_call_stmt (),
str_reg,
conjured_purge (model,
ctxt));
using the str_reg as the id of the conjured_svalue. */
const svalue *offset
= mgr->get_or_create_conjured_svalue (size_type_node,
- cd.get_call_stmt (),
+ &cd.get_call_stmt (),
str_reg,
conjured_purge (model,
ctxt));
using the str_reg as the id of the conjured_svalue. */
const svalue *start_offset
= mgr->get_or_create_conjured_svalue (size_type_node,
- cd.get_call_stmt (),
+ &cd.get_call_stmt (),
str_reg,
conjured_purge (model,
ctxt),
0);
const svalue *nul_offset
= mgr->get_or_create_conjured_svalue (size_type_node,
- cd.get_call_stmt (),
+ &cd.get_call_stmt (),
str_reg,
conjured_purge (model,
ctxt),
{
if (const known_function *candidate
= get_normal_builtin (DECL_FUNCTION_CODE (fndecl)))
- if (gimple_builtin_call_types_compatible_p (cd.get_call_stmt (),
+ if (gimple_builtin_call_types_compatible_p (&cd.get_call_stmt (),
fndecl))
return candidate;
}
void
program_state::push_call (exploded_graph &eg,
exploded_node *enode,
- const gcall *call_stmt,
+ const gcall &call_stmt,
uncertainty_t *uncertainty)
{
/* Update state. */
void
program_state::returning_call (exploded_graph &eg,
exploded_node *enode,
- const gcall *call_stmt,
+ const gcall &call_stmt,
uncertainty_t *uncertainty)
{
/* Update state. */
/* Handle calls to "__analyzer_dump_state". */
void
-program_state::impl_call_analyzer_dump_state (const gcall *call,
+program_state::impl_call_analyzer_dump_state (const gcall &call,
const extrinsic_state &ext_state,
region_model_context *ctxt)
{
const char *sm_name = cd.get_arg_string_literal (0);
if (!sm_name)
{
- error_at (call->location, "cannot determine state machine");
+ error_at (call.location, "cannot determine state machine");
return;
}
unsigned sm_idx;
if (!ext_state.get_sm_idx_by_name (sm_name, &sm_idx))
{
- error_at (call->location, "unrecognized state machine %qs", sm_name);
+ error_at (call.location, "unrecognized state machine %qs", sm_name);
return;
}
const sm_state_map *smap = m_checker_states[sm_idx];
sval = cast;
state_machine::state_t state = smap->get_state (sval, ext_state);
- warning_at (call->location, 0, "state: %qs", state->get_name ());
+ warning_at (call.location, 0, "state: %qs", state->get_name ());
}
#if CHECKING_P
void push_call (exploded_graph &eg,
exploded_node *enode,
- const gcall *call_stmt,
+ const gcall &call_stmt,
uncertainty_t *uncertainty);
void returning_call (exploded_graph &eg,
exploded_node *enode,
- const gcall *call_stmt,
+ const gcall &call_stmt,
uncertainty_t *uncertainty);
bool replay_call_summary (call_summary_replay &r,
const program_state &summary);
- void impl_call_analyzer_dump_state (const gcall *call,
+ void impl_call_analyzer_dump_state (const gcall &call,
const extrinsic_state &ext_state,
region_model_context *ctxt);
anything, for which we don't have a function body, or for which we
don't know the fndecl. */
const gcall *call = as_a <const gcall *> (stmt);
- *out_unknown_side_effects = on_call_pre (call, ctxt);
+ *out_unknown_side_effects = on_call_pre (*call, ctxt);
}
break;
attributes. */
const builtin_known_function *
-region_model::get_builtin_kf (const gcall *call,
+region_model::get_builtin_kf (const gcall &call,
region_model_context *ctxt /* = NULL */) const
{
region_model *mut_this = const_cast <region_model *> (this);
fndecl it is). */
bool
-region_model::on_call_pre (const gcall *call, region_model_context *ctxt)
+region_model::on_call_pre (const gcall &call, region_model_context *ctxt)
{
call_details cd (call, this, ctxt);
Handle IFN_DEFERRED_INIT by treating it as no-op: don't touch the
lhs of the call, so that it is still uninitialized from the point of
view of the analyzer. */
- if (gimple_call_internal_p (call)
- && gimple_call_internal_fn (call) == IFN_DEFERRED_INIT)
+ if (gimple_call_internal_p (&call)
+ && gimple_call_internal_fn (&call) == IFN_DEFERRED_INIT)
return false; /* No side effects. */
/* Get svalues for all of the arguments at the callsite, to ensure that we
tree callee_fndecl = get_fndecl_for_call (call, ctxt);
- if (gimple_call_internal_p (call))
+ if (gimple_call_internal_p (&call))
if (const known_function *kf
- = get_known_function (gimple_call_internal_fn (call)))
+ = get_known_function (gimple_call_internal_fn (&call)))
{
kf->impl_call_pre (cd);
return false; /* No further side effects. */
to purge state. */
void
-region_model::on_call_post (const gcall *call,
+region_model::on_call_post (const gcall &call,
bool unknown_side_effects,
region_model_context *ctxt)
{
attribute. */
void
-region_model::check_function_attr_access (const gcall *call,
+region_model::check_function_attr_access (const gcall &call,
tree callee_fndecl,
region_model_context *ctxt,
rdwr_map &rdwr_idx) const
{
- gcc_assert (call);
gcc_assert (callee_fndecl);
gcc_assert (ctxt);
note added to them. */
annotating_ctxt my_ctxt (callee_fndecl, *access, ctxt);
- tree ptr_tree = gimple_call_arg (call, access->ptrarg);
+ tree ptr_tree = gimple_call_arg (&call, access->ptrarg);
const svalue *ptr_sval = get_rvalue (ptr_tree, &my_ctxt);
const region *reg = deref_rvalue (ptr_sval, ptr_tree, &my_ctxt);
check_region_for_write (reg, nullptr, &my_ctxt);
void
region_model::
-check_one_function_attr_null_terminated_string_arg (const gcall *call,
+check_one_function_attr_null_terminated_string_arg (const gcall &call,
tree callee_fndecl,
region_model_context *ctxt,
rdwr_map &rdwr_idx,
tree attr)
{
- gcc_assert (call);
gcc_assert (callee_fndecl);
gcc_assert (ctxt);
gcc_assert (attr);
void
region_model::
-check_function_attr_null_terminated_string_arg (const gcall *call,
+check_function_attr_null_terminated_string_arg (const gcall &call,
tree callee_fndecl,
region_model_context *ctxt,
rdwr_map &rdwr_idx)
{
- gcc_assert (call);
gcc_assert (callee_fndecl);
gcc_assert (ctxt);
function attributes, complaining to CTXT about any issues. */
void
-region_model::check_function_attrs (const gcall *call,
+region_model::check_function_attrs (const gcall &call,
tree callee_fndecl,
region_model_context *ctxt)
{
- gcc_assert (call);
gcc_assert (callee_fndecl);
gcc_assert (ctxt);
from their values, and from values that point to them. */
void
-region_model::handle_unrecognized_call (const gcall *call,
+region_model::handle_unrecognized_call (const gcall &call,
region_model_context *ctxt)
{
tree fndecl = get_fndecl_for_call (call, ctxt);
tree iter_param_types = NULL_TREE;
if (fndecl)
iter_param_types = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
- for (unsigned arg_idx = 0; arg_idx < gimple_call_num_args (call); arg_idx++)
+ for (unsigned arg_idx = 0; arg_idx < gimple_call_num_args (&call);
+ arg_idx++)
{
/* Track expected param type, where available. */
tree param_type = NULL_TREE;
iter_param_types = TREE_CHAIN (iter_param_types);
}
- tree parm = gimple_call_arg (call, arg_idx);
+ tree parm = gimple_call_arg (&call, arg_idx);
const svalue *parm_sval = get_rvalue (parm, ctxt);
reachable_regs.handle_parm (parm_sval, param_type);
}
0), as opposed to any second return due to longjmp/sigsetjmp. */
void
-region_model::on_setjmp (const gcall *call, const exploded_node *enode,
+region_model::on_setjmp (const gcall &call, const exploded_node *enode,
region_model_context *ctxt)
{
- const svalue *buf_ptr = get_rvalue (gimple_call_arg (call, 0), ctxt);
- const region *buf_reg = deref_rvalue (buf_ptr, gimple_call_arg (call, 0),
+ const svalue *buf_ptr = get_rvalue (gimple_call_arg (&call, 0), ctxt);
+ const region *buf_reg = deref_rvalue (buf_ptr, gimple_call_arg (&call, 0),
ctxt);
/* Create a setjmp_svalue for this call and store it in BUF_REG's
}
/* Direct calls to setjmp return 0. */
- if (tree lhs = gimple_call_lhs (call))
+ if (tree lhs = gimple_call_lhs (&call))
{
const svalue *new_sval
= m_mgr->get_or_create_int_cst (TREE_TYPE (lhs), 0);
done, and should be done by the caller. */
void
-region_model::on_longjmp (const gcall *longjmp_call, const gcall *setjmp_call,
+region_model::on_longjmp (const gcall &longjmp_call, const gcall &setjmp_call,
int setjmp_stack_depth, region_model_context *ctxt)
{
/* Evaluate the val, using the frame of the "longjmp". */
- tree fake_retval = gimple_call_arg (longjmp_call, 1);
+ tree fake_retval = gimple_call_arg (&longjmp_call, 1);
const svalue *fake_retval_sval = get_rvalue (fake_retval, ctxt);
/* Pop any frames until we reach the stack depth of the function where
gcc_assert (get_stack_depth () == setjmp_stack_depth);
/* Assign to LHS of "setjmp" in new_state. */
- if (tree lhs = gimple_call_lhs (setjmp_call))
+ if (tree lhs = gimple_call_lhs (&setjmp_call))
{
/* Passing 0 as the val to longjmp leads to setjmp returning 1. */
const svalue *zero_sval
caller's frame. */
void
-region_model::update_for_gcall (const gcall *call_stmt,
+region_model::update_for_gcall (const gcall &call_stmt,
region_model_context *ctxt,
function *callee)
{
/* Build a vec of argument svalues, using the current top
frame for resolving tree expressions. */
- auto_vec<const svalue *> arg_svals (gimple_call_num_args (call_stmt));
+ auto_vec<const svalue *> arg_svals (gimple_call_num_args (&call_stmt));
- for (unsigned i = 0; i < gimple_call_num_args (call_stmt); i++)
+ for (unsigned i = 0; i < gimple_call_num_args (&call_stmt); i++)
{
- tree arg = gimple_call_arg (call_stmt, i);
+ tree arg = gimple_call_arg (&call_stmt, i);
arg_svals.quick_push (get_rvalue (arg, ctxt));
}
if(!callee)
{
/* Get the function * from the gcall. */
- tree fn_decl = get_fndecl_for_call (call_stmt,ctxt);
+ tree fn_decl = get_fndecl_for_call (call_stmt, ctxt);
callee = DECL_STRUCT_FUNCTION (fn_decl);
}
the call (if any). */
void
-region_model::update_for_return_gcall (const gcall *call_stmt,
+region_model::update_for_return_gcall (const gcall &call_stmt,
region_model_context *ctxt)
{
/* Get the lvalue for the result of the call, passing it to pop_frame,
so that pop_frame can determine the region with respect to the
*caller* frame. */
- tree lhs = gimple_call_lhs (call_stmt);
- pop_frame (lhs, NULL, ctxt, call_stmt);
+ tree lhs = gimple_call_lhs (&call_stmt);
+ pop_frame (lhs, NULL, ctxt, &call_stmt);
}
/* Extract calling information from the superedge and update the model for the
region_model::update_for_call_superedge (const call_superedge &call_edge,
region_model_context *ctxt)
{
- const gcall *call_stmt = call_edge.get_call_stmt ();
+ const gcall &call_stmt = call_edge.get_call_stmt ();
update_for_gcall (call_stmt, ctxt, call_edge.get_callee_function ());
}
region_model::update_for_return_superedge (const return_superedge &return_edge,
region_model_context *ctxt)
{
- const gcall *call_stmt = return_edge.get_call_stmt ();
+ const gcall &call_stmt = return_edge.get_call_stmt ();
update_for_return_gcall (call_stmt, ctxt);
}
{
gcc_assert (last_stmt);
if (const gcall *call = dyn_cast <const gcall *> (last_stmt))
- if (tree callee_fndecl = get_fndecl_for_call (call, ctxt))
- if (is_named_call_p (callee_fndecl, "operator new", call, 1)
- || is_named_call_p (callee_fndecl, "operator new []", call, 1))
+ if (tree callee_fndecl = get_fndecl_for_call (*call, ctxt))
+ if (is_named_call_p (callee_fndecl, "operator new", *call, 1)
+ || is_named_call_p (callee_fndecl, "operator new []", *call, 1))
{
/* We have an exception thrown from operator new.
Add a constraint that the result was NULL, to avoid a false
otherwise. */
tree
-region_model::get_fndecl_for_call (const gcall *call,
+region_model::get_fndecl_for_call (const gcall &call,
region_model_context *ctxt)
{
- tree fn_ptr = gimple_call_fn (call);
+ tree fn_ptr = gimple_call_fn (&call);
if (fn_ptr == NULL_TREE)
return NULL_TREE;
const svalue *fn_ptr_sval = get_rvalue (fn_ptr, ctxt);
conjured_purge p (this, cd.get_ctxt ());
const svalue *new_errno_sval
= m_mgr->get_or_create_conjured_svalue (integer_type_node,
- cd.get_call_stmt (),
+ &cd.get_call_stmt (),
errno_reg, p);
const svalue *zero
= m_mgr->get_or_create_int_cst (integer_type_node, 0);
const svalue *get_gassign_result (const gassign *assign,
region_model_context *ctxt);
void on_asm_stmt (const gasm *asm_stmt, region_model_context *ctxt);
- bool on_call_pre (const gcall *stmt, region_model_context *ctxt);
- void on_call_post (const gcall *stmt,
+ bool on_call_pre (const gcall &stmt, region_model_context *ctxt);
+ void on_call_post (const gcall &stmt,
bool unknown_side_effects,
region_model_context *ctxt);
bool unmergeable);
void update_for_nonzero_return (const call_details &cd);
- void handle_unrecognized_call (const gcall *call,
+ void handle_unrecognized_call (const gcall &call,
region_model_context *ctxt);
void get_reachable_svalues (svalue_set *out,
const svalue *extra_sval,
const uncertainty_t *uncertainty);
void on_return (const greturn *stmt, region_model_context *ctxt);
- void on_setjmp (const gcall *stmt, const exploded_node *enode,
+ void on_setjmp (const gcall &stmt, const exploded_node *enode,
region_model_context *ctxt);
- void on_longjmp (const gcall *longjmp_call, const gcall *setjmp_call,
+ void on_longjmp (const gcall &longjmp_call, const gcall &setjmp_call,
int setjmp_stack_depth, region_model_context *ctxt);
void update_for_phis (const supernode *snode,
region_model_context *ctxt,
std::unique_ptr<rejected_constraint> *out);
- void update_for_gcall (const gcall *call_stmt,
+ void update_for_gcall (const gcall &call_stmt,
region_model_context *ctxt,
function *callee = NULL);
- void update_for_return_gcall (const gcall *call_stmt,
+ void update_for_return_gcall (const gcall &call_stmt,
region_model_context *ctxt);
const region *push_frame (const function &fun, const vec<const svalue *> *arg_sids,
const program_state *state_a = NULL,
const program_state *state_b = NULL) const;
- tree get_fndecl_for_call (const gcall *call,
+ tree get_fndecl_for_call (const gcall &call,
region_model_context *ctxt);
void get_regions_for_current_frame (auto_vec<const decl_region *> *out) const;
const svalue **out_sval) const;
const builtin_known_function *
- get_builtin_kf (const gcall *call,
+ get_builtin_kf (const gcall &call,
region_model_context *ctxt = NULL) const;
static void
void check_call_args (const call_details &cd) const;
void check_call_format_attr (const call_details &cd,
tree format_attr) const;
- void check_function_attr_access (const gcall *call,
+ void check_function_attr_access (const gcall &call,
tree callee_fndecl,
region_model_context *ctxt,
rdwr_map &rdwr_idx) const;
- void check_function_attr_null_terminated_string_arg (const gcall *call,
+ void check_function_attr_null_terminated_string_arg (const gcall &call,
tree callee_fndecl,
region_model_context *ctxt,
rdwr_map &rdwr_idx);
- void check_one_function_attr_null_terminated_string_arg (const gcall *call,
+ void check_one_function_attr_null_terminated_string_arg (const gcall &call,
tree callee_fndecl,
region_model_context *ctxt,
rdwr_map &rdwr_idx,
tree attr);
- void check_function_attrs (const gcall *call,
+ void check_function_attrs (const gcall &call,
tree callee_fndecl,
region_model_context *ctxt);
private:
void on_open (sm_context &sm_ctxt, const supernode *node, const gimple *stmt,
- const gcall *call) const;
+ const gcall &call) const;
void on_creat (sm_context &sm_ctxt, const supernode *node, const gimple *stmt,
- const gcall *call) const;
+ const gcall &call) const;
void on_close (sm_context &sm_ctxt, const supernode *node, const gimple *stmt,
- const gcall *call) const;
+ const gcall &call) const;
void on_read (sm_context &sm_ctxt, const supernode *node, const gimple *stmt,
- const gcall *call, const tree callee_fndecl) const;
+ const gcall &call, const tree callee_fndecl) const;
void on_write (sm_context &sm_ctxt, const supernode *node, const gimple *stmt,
- const gcall *call, const tree callee_fndecl) const;
+ const gcall &call, const tree callee_fndecl) const;
void check_for_open_fd (sm_context &sm_ctxt, const supernode *node,
- const gimple *stmt, const gcall *call,
+ const gimple *stmt, const gcall &call,
const tree callee_fndecl,
enum access_directions access_fn) const;
const gimple *stmt,
const svalue *lhs) const;
void check_for_fd_attrs (sm_context &sm_ctxt, const supernode *node,
- const gimple *stmt, const gcall *call,
+ const gimple *stmt, const gcall &call,
const tree callee_fndecl, const char *attr_name,
access_directions fd_attr_access_dir) const;
void check_for_dup (sm_context &sm_ctxt, const supernode *node,
- const gimple *stmt, const gcall *call, const tree callee_fndecl,
+ const gimple *stmt, const gcall &call, const tree callee_fndecl,
enum dup kind) const;
state_t get_state_for_socket_type (const svalue *socket_type_sval) const;
const gimple *stmt) const
{
if (const gcall *call = dyn_cast<const gcall *> (stmt))
- if (tree callee_fndecl = sm_ctxt.get_fndecl_for_call (call))
+ if (tree callee_fndecl = sm_ctxt.get_fndecl_for_call (*call))
{
- if (is_named_call_p (callee_fndecl, "open", call, 2))
+ if (is_named_call_p (callee_fndecl, "open", *call, 2))
{
- on_open (sm_ctxt, node, stmt, call);
+ on_open (sm_ctxt, node, stmt, *call);
return true;
} // "open"
- if (is_named_call_p (callee_fndecl, "creat", call, 2))
+ if (is_named_call_p (callee_fndecl, "creat", *call, 2))
{
- on_creat (sm_ctxt, node, stmt, call);
+ on_creat (sm_ctxt, node, stmt, *call);
return true;
} // "creat"
- if (is_named_call_p (callee_fndecl, "close", call, 1))
+ if (is_named_call_p (callee_fndecl, "close", *call, 1))
{
- on_close (sm_ctxt, node, stmt, call);
+ on_close (sm_ctxt, node, stmt, *call);
return true;
} // "close"
- if (is_named_call_p (callee_fndecl, "write", call, 3))
+ if (is_named_call_p (callee_fndecl, "write", *call, 3))
{
- on_write (sm_ctxt, node, stmt, call, callee_fndecl);
+ on_write (sm_ctxt, node, stmt, *call, callee_fndecl);
return true;
} // "write"
- if (is_named_call_p (callee_fndecl, "read", call, 3))
+ if (is_named_call_p (callee_fndecl, "read", *call, 3))
{
- on_read (sm_ctxt, node, stmt, call, callee_fndecl);
+ on_read (sm_ctxt, node, stmt, *call, callee_fndecl);
return true;
} // "read"
- if (is_named_call_p (callee_fndecl, "dup", call, 1))
+ if (is_named_call_p (callee_fndecl, "dup", *call, 1))
{
- check_for_dup (sm_ctxt, node, stmt, call, callee_fndecl, DUP_1);
+ check_for_dup (sm_ctxt, node, stmt, *call, callee_fndecl, DUP_1);
return true;
}
- if (is_named_call_p (callee_fndecl, "dup2", call, 2))
+ if (is_named_call_p (callee_fndecl, "dup2", *call, 2))
{
- check_for_dup (sm_ctxt, node, stmt, call, callee_fndecl, DUP_2);
+ check_for_dup (sm_ctxt, node, stmt, *call, callee_fndecl, DUP_2);
return true;
}
- if (is_named_call_p (callee_fndecl, "dup3", call, 3))
+ if (is_named_call_p (callee_fndecl, "dup3", *call, 3))
{
- check_for_dup (sm_ctxt, node, stmt, call, callee_fndecl, DUP_3);
+ check_for_dup (sm_ctxt, node, stmt, *call, callee_fndecl, DUP_3);
return true;
}
{
// Handle __attribute__((fd_arg))
- check_for_fd_attrs (sm_ctxt, node, stmt, call, callee_fndecl,
+ check_for_fd_attrs (sm_ctxt, node, stmt, *call, callee_fndecl,
"fd_arg", DIRS_READ_WRITE);
// Handle __attribute__((fd_arg_read))
- check_for_fd_attrs (sm_ctxt, node, stmt, call, callee_fndecl,
+ check_for_fd_attrs (sm_ctxt, node, stmt, *call, callee_fndecl,
"fd_arg_read", DIRS_READ);
// Handle __attribute__((fd_arg_write))
- check_for_fd_attrs (sm_ctxt, node, stmt, call, callee_fndecl,
+ check_for_fd_attrs (sm_ctxt, node, stmt, *call, callee_fndecl,
"fd_arg_write", DIRS_WRITE);
}
}
void
fd_state_machine::check_for_fd_attrs (
sm_context &sm_ctxt, const supernode *node, const gimple *stmt,
- const gcall *call, const tree callee_fndecl, const char *attr_name,
+ const gcall &call, const tree callee_fndecl, const char *attr_name,
access_directions fd_attr_access_dir) const
{
/* Handle interesting fd attributes of the callee_fndecl,
if (bitmap_empty_p (argmap))
return;
- for (unsigned arg_idx = 0; arg_idx < gimple_call_num_args (call); arg_idx++)
+ for (unsigned arg_idx = 0; arg_idx < gimple_call_num_args (&call); arg_idx++)
{
- tree arg = gimple_call_arg (call, arg_idx);
+ tree arg = gimple_call_arg (&call, arg_idx);
tree diag_arg = sm_ctxt.get_diagnostic_tree (arg);
state_t state = sm_ctxt.get_state (stmt, arg);
bool bit_set = bitmap_bit_p (argmap, arg_idx);
void
fd_state_machine::on_open (sm_context &sm_ctxt, const supernode *node,
- const gimple *stmt, const gcall *call) const
+ const gimple *stmt, const gcall &call) const
{
- tree lhs = gimple_call_lhs (call);
+ tree lhs = gimple_call_lhs (&call);
if (lhs)
{
- tree arg = gimple_call_arg (call, 1);
+ tree arg = gimple_call_arg (&call, 1);
enum access_mode mode = READ_WRITE;
if (TREE_CODE (arg) == INTEGER_CST)
{
void
fd_state_machine::on_creat (sm_context &sm_ctxt, const supernode *node,
- const gimple *stmt, const gcall *call) const
+ const gimple *stmt, const gcall &call) const
{
- tree lhs = gimple_call_lhs (call);
+ tree lhs = gimple_call_lhs (&call);
if (lhs)
sm_ctxt.on_transition (node, stmt, lhs, m_start, m_unchecked_write_only);
else
void
fd_state_machine::check_for_dup (sm_context &sm_ctxt, const supernode *node,
- const gimple *stmt, const gcall *call,
+ const gimple *stmt, const gcall &call,
const tree callee_fndecl, enum dup kind) const
{
- tree lhs = gimple_call_lhs (call);
- tree arg_1 = gimple_call_arg (call, 0);
+ tree lhs = gimple_call_lhs (&call);
+ tree arg_1 = gimple_call_arg (&call, 0);
state_t state_arg_1 = sm_ctxt.get_state (stmt, arg_1);
if (state_arg_1 == m_stop)
return;
case DUP_2:
case DUP_3:
- tree arg_2 = gimple_call_arg (call, 1);
+ tree arg_2 = gimple_call_arg (&call, 1);
state_t state_arg_2 = sm_ctxt.get_state (stmt, arg_2);
tree diag_arg_2 = sm_ctxt.get_diagnostic_tree (arg_2);
if (state_arg_2 == m_stop)
void
fd_state_machine::on_close (sm_context &sm_ctxt, const supernode *node,
- const gimple *stmt, const gcall *call) const
+ const gimple *stmt, const gcall &call) const
{
- tree arg = gimple_call_arg (call, 0);
+ tree arg = gimple_call_arg (&call, 0);
state_t state = sm_ctxt.get_state (stmt, arg);
tree diag_arg = sm_ctxt.get_diagnostic_tree (arg);
}
void
fd_state_machine::on_read (sm_context &sm_ctxt, const supernode *node,
- const gimple *stmt, const gcall *call,
+ const gimple *stmt, const gcall &call,
const tree callee_fndecl) const
{
check_for_open_fd (sm_ctxt, node, stmt, call, callee_fndecl, DIRS_READ);
}
void
fd_state_machine::on_write (sm_context &sm_ctxt, const supernode *node,
- const gimple *stmt, const gcall *call,
+ const gimple *stmt, const gcall &call,
const tree callee_fndecl) const
{
check_for_open_fd (sm_ctxt, node, stmt, call, callee_fndecl, DIRS_WRITE);
void
fd_state_machine::check_for_open_fd (
sm_context &sm_ctxt, const supernode *node, const gimple *stmt,
- const gcall *call, const tree callee_fndecl,
+ const gcall &call, const tree callee_fndecl,
enum access_directions callee_fndecl_dir) const
{
- tree arg = gimple_call_arg (call, 0);
+ tree arg = gimple_call_arg (&call, 0);
tree diag_arg = sm_ctxt.get_diagnostic_tree (arg);
state_t state = sm_ctxt.get_state (stmt, arg);
sm_context &sm_ctxt,
const extrinsic_state &ext_state) const
{
- const gcall *stmt = cd.get_call_stmt ();
+ const gcall &call = cd.get_call_stmt ();
engine *eng = ext_state.get_engine ();
const supergraph *sg = eng->get_supergraph ();
- const supernode *node = sg->get_supernode_for_stmt (stmt);
+ const supernode *node = sg->get_supernode_for_stmt (&call);
region_model *model = cd.get_model ();
if (successful)
{
- if (gimple_call_lhs (stmt))
+ if (gimple_call_lhs (&call))
{
conjured_purge p (model, cd.get_ctxt ());
region_model_manager *mgr = model->get_manager ();
const svalue *new_fd
= mgr->get_or_create_conjured_svalue (integer_type_node,
- stmt,
+ &call,
cd.get_lhs_region (),
p);
if (!add_constraint_ge_zero (model, new_fd, cd.get_ctxt ()))
const svalue *socket_type_sval = cd.get_arg_svalue (1);
state_machine::state_t new_state
= get_state_for_socket_type (socket_type_sval);
- sm_ctxt.on_transition (node, stmt, new_fd, m_start, new_state);
+ sm_ctxt.on_transition (node, &call, new_fd, m_start, new_state);
model->set_value (cd.get_lhs_region (), new_fd, cd.get_ctxt ());
}
else
- sm_ctxt.warn (node, stmt, NULL_TREE,
+ sm_ctxt.warn (node, &call, NULL_TREE,
make_unique<fd_leak> (*this, NULL_TREE));
}
else
state_t old_state,
bool *complained) const
{
- const gcall *stmt = cd.get_call_stmt ();
+ const gcall &call = cd.get_call_stmt ();
if (is_closed_fd_p (old_state))
{
tree diag_arg = sm_ctxt.get_diagnostic_tree (fd_sval);
sm_ctxt.warn
- (node, stmt, fd_sval,
+ (node, &call, fd_sval,
make_unique<fd_use_after_close> (*this, diag_arg,
cd.get_fndecl_for_call ()));
if (complained)
/* Complain about non-socket. */
tree diag_arg = sm_ctxt.get_diagnostic_tree (fd_sval);
sm_ctxt.warn
- (node, stmt, fd_sval,
+ (node, &call, fd_sval,
make_unique<fd_type_mismatch> (*this, diag_arg,
cd.get_fndecl_for_call (),
old_state,
{
tree diag_arg = sm_ctxt.get_diagnostic_tree (fd_sval);
sm_ctxt.warn
- (node, stmt, fd_sval,
+ (node, &call, fd_sval,
make_unique<fd_use_without_check> (*this, diag_arg,
cd.get_fndecl_for_call ()));
if (complained)
/* Complain about "bind" or "connect" in wrong phase. */
tree diag_arg = sm_ctxt.get_diagnostic_tree (fd_sval);
sm_ctxt.warn
- (node, cd.get_call_stmt (), fd_sval,
+ (node, &cd.get_call_stmt (), fd_sval,
make_unique<fd_phase_mismatch> (*this, diag_arg,
cd.get_fndecl_for_call (),
old_state,
{
/* If we were in the start state, assume we had a new socket. */
if (old_state == m_start)
- sm_ctxt.set_next_state (cd.get_call_stmt (), fd_sval,
+ sm_ctxt.set_next_state (&cd.get_call_stmt (), fd_sval,
m_new_unknown_socket);
}
sm_context &sm_ctxt,
const extrinsic_state &ext_state) const
{
- const gcall *stmt = cd.get_call_stmt ();
+ const gcall &call = cd.get_call_stmt ();
engine *eng = ext_state.get_engine ();
const supergraph *sg = eng->get_supergraph ();
- const supernode *node = sg->get_supernode_for_stmt (stmt);
+ const supernode *node = sg->get_supernode_for_stmt (&call);
const svalue *fd_sval = cd.get_arg_svalue (0);
region_model *model = cd.get_model ();
- state_t old_state = sm_ctxt.get_state (stmt, fd_sval);
+ state_t old_state = sm_ctxt.get_state (&call, fd_sval);
if (!check_for_new_socket_fd (cd, successful, sm_ctxt,
fd_sval, node, old_state,
next_state = m_stop;
else
gcc_unreachable ();
- sm_ctxt.set_next_state (cd.get_call_stmt (), fd_sval, next_state);
+ sm_ctxt.set_next_state (&cd.get_call_stmt (), fd_sval, next_state);
model->update_for_zero_return (cd, true);
}
else
sm_context &sm_ctxt,
const extrinsic_state &ext_state) const
{
- const gcall *stmt = cd.get_call_stmt ();
+ const gcall &call = cd.get_call_stmt ();
engine *eng = ext_state.get_engine ();
const supergraph *sg = eng->get_supergraph ();
- const supernode *node = sg->get_supernode_for_stmt (cd.get_call_stmt ());
+ const supernode *node = sg->get_supernode_for_stmt (&cd.get_call_stmt ());
const svalue *fd_sval = cd.get_arg_svalue (0);
region_model *model = cd.get_model ();
- state_t old_state = sm_ctxt.get_state (stmt, fd_sval);
+ state_t old_state = sm_ctxt.get_state (&call, fd_sval);
/* We expect a stream socket that's had "bind" called on it. */
if (!check_for_socket_fd (cd, successful, sm_ctxt, fd_sval, node, old_state))
tree diag_arg = sm_ctxt.get_diagnostic_tree (fd_sval);
if (is_stream_socket_fd_p (old_state))
sm_ctxt.warn
- (node, stmt, fd_sval,
+ (node, &call, fd_sval,
make_unique<fd_phase_mismatch> (*this, diag_arg,
cd.get_fndecl_for_call (),
old_state,
EXPECTED_PHASE_CAN_LISTEN));
else
sm_ctxt.warn
- (node, stmt, fd_sval,
+ (node, &call, fd_sval,
make_unique<fd_type_mismatch> (*this, diag_arg,
cd.get_fndecl_for_call (),
old_state,
if (successful)
{
model->update_for_zero_return (cd, true);
- sm_ctxt.set_next_state (cd.get_call_stmt (), fd_sval,
+ sm_ctxt.set_next_state (&cd.get_call_stmt (), fd_sval,
m_listening_stream_socket);
}
else
model->update_for_int_cst_return (cd, -1, true);
model->set_errno (cd);
if (old_state == m_start)
- sm_ctxt.set_next_state (cd.get_call_stmt (), fd_sval,
+ sm_ctxt.set_next_state (&cd.get_call_stmt (), fd_sval,
m_bound_stream_socket);
}
sm_context &sm_ctxt,
const extrinsic_state &ext_state) const
{
- const gcall *stmt = cd.get_call_stmt ();
+ const gcall &call = cd.get_call_stmt ();
engine *eng = ext_state.get_engine ();
const supergraph *sg = eng->get_supergraph ();
- const supernode *node = sg->get_supernode_for_stmt (stmt);
+ const supernode *node = sg->get_supernode_for_stmt (&call);
const svalue *fd_sval = cd.get_arg_svalue (0);
const svalue *address_sval = cd.get_arg_svalue (1);
const svalue *len_ptr_sval = cd.get_arg_svalue (2);
region_model *model = cd.get_model ();
- state_t old_state = sm_ctxt.get_state (stmt, fd_sval);
+ state_t old_state = sm_ctxt.get_state (&call, fd_sval);
if (!address_sval->all_zeroes_p ())
{
old_len_sval);
const svalue *new_addr_sval
= mgr->get_or_create_conjured_svalue (NULL_TREE,
- stmt,
+ &call,
old_sized_address_reg,
p);
model->set_value (old_sized_address_reg, new_addr_sval,
cd.get_ctxt ());
const svalue *new_addr_len
= mgr->get_or_create_conjured_svalue (NULL_TREE,
- stmt,
+ &call,
len_reg,
p);
model->set_value (len_reg, new_addr_len, cd.get_ctxt ());
if (old_state == m_start || old_state == m_constant_fd)
/* If we were in the start state (or a constant), assume we had the
expected state. */
- sm_ctxt.set_next_state (cd.get_call_stmt (), fd_sval,
+ sm_ctxt.set_next_state (&cd.get_call_stmt (), fd_sval,
m_listening_stream_socket);
else if (old_state == m_stop)
{
tree diag_arg = sm_ctxt.get_diagnostic_tree (fd_sval);
if (is_stream_socket_fd_p (old_state))
sm_ctxt.warn
- (node, stmt, fd_sval,
+ (node, &call, fd_sval,
make_unique<fd_phase_mismatch> (*this, diag_arg,
cd.get_fndecl_for_call (),
old_state,
EXPECTED_PHASE_CAN_ACCEPT));
else
sm_ctxt.warn
- (node, stmt, fd_sval,
+ (node, &call, fd_sval,
make_unique<fd_type_mismatch> (*this, diag_arg,
cd.get_fndecl_for_call (),
old_state,
if (successful)
{
/* Return new conjured FD in "connected" state. */
- if (gimple_call_lhs (stmt))
+ if (gimple_call_lhs (&call))
{
conjured_purge p (model, cd.get_ctxt ());
region_model_manager *mgr = model->get_manager ();
const svalue *new_fd
= mgr->get_or_create_conjured_svalue (integer_type_node,
- stmt,
+ &call,
cd.get_lhs_region (),
p);
if (!add_constraint_ge_zero (model, new_fd, cd.get_ctxt ()))
return false;
- sm_ctxt.on_transition (node, stmt, new_fd,
+ sm_ctxt.on_transition (node, &call, new_fd,
m_start, m_connected_stream_socket);
model->set_value (cd.get_lhs_region (), new_fd, cd.get_ctxt ());
}
else
- sm_ctxt.warn (node, stmt, NULL_TREE,
+ sm_ctxt.warn (node, &call, NULL_TREE,
make_unique<fd_leak> (*this, NULL_TREE));
}
else
sm_context &sm_ctxt,
const extrinsic_state &ext_state) const
{
- const gcall *stmt = cd.get_call_stmt ();
+ const gcall &call = cd.get_call_stmt ();
engine *eng = ext_state.get_engine ();
const supergraph *sg = eng->get_supergraph ();
- const supernode *node = sg->get_supernode_for_stmt (stmt);
+ const supernode *node = sg->get_supernode_for_stmt (&call);
const svalue *fd_sval = cd.get_arg_svalue (0);
region_model *model = cd.get_model ();
- state_t old_state = sm_ctxt.get_state (stmt, fd_sval);
+ state_t old_state = sm_ctxt.get_state (&call, fd_sval);
if (!check_for_new_socket_fd (cd, successful, sm_ctxt,
fd_sval, node, old_state,
next_state = m_stop;
else
gcc_unreachable ();
- sm_ctxt.set_next_state (cd.get_call_stmt (), fd_sval, next_state);
+ sm_ctxt.set_next_state (&cd.get_call_stmt (), fd_sval, next_state);
}
else
{
const svalue *fd_sval = cd.get_arg_svalue (0);
state_machine::state_t old_state
- = sm_ctxt->get_state (cd.get_call_stmt (), fd_sval);
+ = sm_ctxt->get_state (&cd.get_call_stmt (), fd_sval);
if (fd_sm->is_closed_fd_p (old_state)
|| old_state == fd_sm->m_invalid)
conjured_purge p (model, cd.get_ctxt ());
const svalue *fd_sval
= mgr->get_or_create_conjured_svalue (integer_type_node,
- cd.get_call_stmt (),
+ &cd.get_call_stmt (),
element_reg,
p);
model->set_value (element_reg, fd_sval, cd.get_ctxt ());
const gimple *stmt) const
{
if (const gcall *call = dyn_cast <const gcall *> (stmt))
- if (tree callee_fndecl = sm_ctxt.get_fndecl_for_call (call))
+ if (tree callee_fndecl = sm_ctxt.get_fndecl_for_call (*call))
{
- if (is_named_call_p (callee_fndecl, "fopen", call, 2))
+ if (is_named_call_p (callee_fndecl, "fopen", *call, 2))
{
tree lhs = gimple_call_lhs (call);
if (lhs)
return true;
}
- if (is_named_call_p (callee_fndecl, "fclose", call, 1))
+ if (is_named_call_p (callee_fndecl, "fclose", *call, 1))
{
tree arg = gimple_call_arg (call, 0);
tree ptr) const;
void on_allocator_call (sm_context &sm_ctxt,
- const gcall *call,
+ const gcall &call,
const deallocator_set *deallocators,
bool returns_nonnull = false) const;
void handle_free_of_non_heap (sm_context &sm_ctxt,
const supernode *node,
- const gcall *call,
+ const gcall &call,
tree arg,
const deallocator *d) const;
void on_deallocator_call (sm_context &sm_ctxt,
const supernode *node,
- const gcall *call,
+ const gcall &call,
const deallocator *d,
unsigned argno) const;
void on_realloc_call (sm_context &sm_ctxt,
const supernode *node,
- const gcall *call) const;
+ const gcall &call) const;
void on_zero_assignment (sm_context &sm_ctxt,
const gimple *stmt,
tree lhs) const;
builtin. */
static bool
-known_allocator_p (const_tree fndecl, const gcall *call)
+known_allocator_p (const_tree fndecl, const gcall &call)
{
/* Either it is a function we know by name and number of arguments... */
if (is_named_call_p (fndecl, "malloc", call, 1)
const supernode *node,
const gimple *stmt) const
{
- if (const gcall *call = dyn_cast <const gcall *> (stmt))
- if (tree callee_fndecl = sm_ctxt.get_fndecl_for_call (call))
+ if (const gcall *call_stmt = dyn_cast <const gcall *> (stmt))
+ if (tree callee_fndecl = sm_ctxt.get_fndecl_for_call (*call_stmt))
{
+ const gcall &call = *call_stmt;
+
if (known_allocator_p (callee_fndecl, call))
{
on_allocator_call (sm_ctxt, call, &m_free);
if (is_named_call_p (callee_fndecl, "alloca", call, 1)
|| is_named_call_p (callee_fndecl, "__builtin_alloca", call, 1))
{
- tree lhs = gimple_call_lhs (call);
+ tree lhs = gimple_call_lhs (&call);
if (lhs)
sm_ctxt.on_transition (node, stmt, lhs, m_start, m_non_heap);
return true;
void
malloc_state_machine::on_allocator_call (sm_context &sm_ctxt,
- const gcall *call,
+ const gcall &call,
const deallocator_set *deallocators,
bool returns_nonnull) const
{
- tree lhs = gimple_call_lhs (call);
+ tree lhs = gimple_call_lhs (&call);
if (lhs)
{
- if (sm_ctxt.get_state (call, lhs) == m_start)
- sm_ctxt.set_next_state (call, lhs,
+ if (sm_ctxt.get_state (&call, lhs) == m_start)
+ sm_ctxt.set_next_state (&call, lhs,
(returns_nonnull
? deallocators->m_nonnull
: deallocators->m_unchecked));
void
malloc_state_machine::handle_free_of_non_heap (sm_context &sm_ctxt,
const supernode *node,
- const gcall *call,
+ const gcall &call,
tree arg,
const deallocator *d) const
{
const svalue *ptr_sval = old_model->get_rvalue (arg, NULL);
freed_reg = old_model->deref_rvalue (ptr_sval, arg, NULL);
}
- sm_ctxt.warn (node, call, arg,
+ sm_ctxt.warn (node, &call, arg,
make_unique<free_of_non_heap>
(*this, diag_arg, freed_reg, d->m_name));
- sm_ctxt.set_next_state (call, arg, m_stop);
+ sm_ctxt.set_next_state (&call, arg, m_stop);
}
void
malloc_state_machine::on_deallocator_call (sm_context &sm_ctxt,
const supernode *node,
- const gcall *call,
+ const gcall &call,
const deallocator *d,
unsigned argno) const
{
- if (argno >= gimple_call_num_args (call))
+ if (argno >= gimple_call_num_args (&call))
return;
- tree arg = gimple_call_arg (call, argno);
+ tree arg = gimple_call_arg (&call, argno);
- state_t state = sm_ctxt.get_state (call, arg);
+ state_t state = sm_ctxt.get_state (&call, arg);
/* start/assumed_non_null/unchecked/nonnull -> freed. */
if (state == m_start || assumed_non_null_p (state))
- sm_ctxt.set_next_state (call, arg, d->m_freed);
+ sm_ctxt.set_next_state (&call, arg, d->m_freed);
else if (unchecked_p (state) || nonnull_p (state))
{
const allocation_state *astate = as_a_allocation_state (state);
{
/* Wrong allocator. */
tree diag_arg = sm_ctxt.get_diagnostic_tree (arg);
- sm_ctxt.warn (node, call, arg,
+ sm_ctxt.warn (node, &call, arg,
make_unique<mismatching_deallocation>
(*this, diag_arg,
astate->m_deallocators,
d));
}
- sm_ctxt.set_next_state (call, arg, d->m_freed);
+ sm_ctxt.set_next_state (&call, arg, d->m_freed);
}
/* Keep state "null" as-is, rather than transitioning to "freed";
{
/* freed -> stop, with warning. */
tree diag_arg = sm_ctxt.get_diagnostic_tree (arg);
- sm_ctxt.warn (node, call, arg,
+ sm_ctxt.warn (node, &call, arg,
make_unique<double_free> (*this, diag_arg, d->m_name));
- sm_ctxt.set_next_state (call, arg, m_stop);
+ sm_ctxt.set_next_state (&call, arg, m_stop);
}
else if (state == m_non_heap)
{
void
malloc_state_machine::on_realloc_call (sm_context &sm_ctxt,
const supernode *node,
- const gcall *call) const
+ const gcall &call) const
{
const unsigned argno = 0;
const deallocator *d = &m_realloc;
- tree arg = gimple_call_arg (call, argno);
+ tree arg = gimple_call_arg (&call, argno);
- state_t state = sm_ctxt.get_state (call, arg);
+ state_t state = sm_ctxt.get_state (&call, arg);
if (unchecked_p (state) || nonnull_p (state))
{
{
/* Wrong allocator. */
tree diag_arg = sm_ctxt.get_diagnostic_tree (arg);
- sm_ctxt.warn (node, call, arg,
+ sm_ctxt.warn (node, &call, arg,
make_unique<mismatching_deallocation>
(*this, diag_arg,
astate->m_deallocators, d));
- sm_ctxt.set_next_state (call, arg, m_stop);
+ sm_ctxt.set_next_state (&call, arg, m_stop);
if (path_context *path_ctxt = sm_ctxt.get_path_context ())
path_ctxt->terminate_path ();
}
{
/* freed -> stop, with warning. */
tree diag_arg = sm_ctxt.get_diagnostic_tree (arg);
- sm_ctxt.warn (node, call, arg,
+ sm_ctxt.warn (node, &call, arg,
make_unique<double_free> (*this, diag_arg, "free"));
- sm_ctxt.set_next_state (call, arg, m_stop);
+ sm_ctxt.set_next_state (&call, arg, m_stop);
if (path_context *path_ctxt = sm_ctxt.get_path_context ())
path_ctxt->terminate_path ();
}
const gimple *stmt) const
{
if (const gcall *call = dyn_cast <const gcall *> (stmt))
- if (tree callee_fndecl = sm_ctxt.get_fndecl_for_call (call))
+ if (tree callee_fndecl = sm_ctxt.get_fndecl_for_call (*call))
{
- if (is_named_call_p (callee_fndecl, "getpass", call, 1))
+ if (is_named_call_p (callee_fndecl, "getpass", *call, 1))
{
tree lhs = gimple_call_lhs (call);
if (lhs)
}
return true;
}
- else if (is_named_call_p (callee_fndecl, "fwrite", call, 4))
+ else if (is_named_call_p (callee_fndecl, "fwrite", *call, 4))
{
tree arg = gimple_call_arg (call, 0);
warn_for_any_exposure (sm_ctxt, node, stmt, arg);
: public pending_diagnostic_subclass<signal_unsafe_call>
{
public:
- signal_unsafe_call (const signal_state_machine &sm, const gcall *unsafe_call,
+ signal_unsafe_call (const signal_state_machine &sm, const gcall &unsafe_call,
tree unsafe_fndecl)
: m_sm (sm), m_unsafe_call (unsafe_call), m_unsafe_fndecl (unsafe_fndecl)
{
bool operator== (const signal_unsafe_call &other) const
{
- return m_unsafe_call == other.m_unsafe_call;
+ return &m_unsafe_call == &other.m_unsafe_call;
}
int get_controlling_option () const final override
suggesting the replacement. */
if (const char *replacement = get_replacement_fn ())
{
- location_t note_loc = gimple_location (m_unsafe_call);
+ location_t note_loc = gimple_location (&m_unsafe_call);
/* It would be nice to add a fixit, but the gimple call
location covers the whole call expression. It isn't
currently possible to cut this down to just the call
private:
const signal_state_machine &m_sm;
- const gcall *m_unsafe_call;
+ const gcall &m_unsafe_call;
tree m_unsafe_fndecl;
/* Returns a replacement function as text if it exists. Currently
if (global_state == m_start)
{
if (const gcall *call = dyn_cast <const gcall *> (stmt))
- if (tree callee_fndecl = sm_ctxt.get_fndecl_for_call (call))
- if (is_named_call_p (callee_fndecl, "signal", call, 2)
- || is_std_named_call_p (callee_fndecl, "signal", call, 2))
+ if (tree callee_fndecl = sm_ctxt.get_fndecl_for_call (*call))
+ if (is_named_call_p (callee_fndecl, "signal", *call, 2)
+ || is_std_named_call_p (callee_fndecl, "signal", *call, 2))
{
tree handler = gimple_call_arg (call, 1);
if (TREE_CODE (handler) == ADDR_EXPR
else if (global_state == m_in_signal_handler)
{
if (const gcall *call = dyn_cast <const gcall *> (stmt))
- if (tree callee_fndecl = sm_ctxt.get_fndecl_for_call (call))
+ if (tree callee_fndecl = sm_ctxt.get_fndecl_for_call (*call))
if (signal_unsafe_p (callee_fndecl))
if (sm_ctxt.get_global_state () == m_in_signal_handler)
sm_ctxt.warn (node, stmt, NULL_TREE,
make_unique<signal_unsafe_call>
- (*this, call, callee_fndecl));
+ (*this, *call, callee_fndecl));
}
return false;
void check_for_tainted_size_arg (sm_context &sm_ctxt,
const supernode *node,
- const gcall *call,
+ const gcall &call,
tree callee_fndecl) const;
void check_for_tainted_divisor (sm_context &sm_ctxt,
const supernode *node,
const gimple *stmt) const
{
if (const gcall *call = dyn_cast <const gcall *> (stmt))
- if (tree callee_fndecl = sm_ctxt.get_fndecl_for_call (call))
+ if (tree callee_fndecl = sm_ctxt.get_fndecl_for_call (*call))
{
- if (is_named_call_p (callee_fndecl, "fread", call, 4))
+ if (is_named_call_p (callee_fndecl, "fread", *call, 4))
{
tree arg = gimple_call_arg (call, 0);
/* External function with "access" attribute. */
if (sm_ctxt.unknown_side_effects_p ())
- check_for_tainted_size_arg (sm_ctxt, node, call, callee_fndecl);
+ check_for_tainted_size_arg (sm_ctxt, node, *call, callee_fndecl);
if (is_assertion_failure_handler_p (callee_fndecl)
&& sm_ctxt.get_global_state () == m_tainted_control_flow)
void
taint_state_machine::check_for_tainted_size_arg (sm_context &sm_ctxt,
const supernode *node,
- const gcall *call,
+ const gcall &call,
tree callee_fndecl) const
{
tree fntype = TREE_TYPE (callee_fndecl);
if (access->sizarg == UINT_MAX)
continue;
- tree size_arg = gimple_call_arg (call, access->sizarg);
+ tree size_arg = gimple_call_arg (&call, access->sizarg);
- state_t state = sm_ctxt.get_state (call, size_arg);
+ state_t state = sm_ctxt.get_state (&call, size_arg);
enum bounds b;
if (get_taint (state, TREE_TYPE (size_arg), &b))
{
const char* const access_str =
TREE_STRING_POINTER (access->to_external_string ());
tree diag_size = sm_ctxt.get_diagnostic_tree (size_arg);
- sm_ctxt.warn (node, call, size_arg,
+ sm_ctxt.warn (node, &call, size_arg,
make_unique<tainted_access_attrib_size>
(*this, diag_size, b,
callee_fndecl,
Use in preference to gimple_call_fndecl (and gimple_call_addr_fndecl),
since it can look through function pointer assignments and
other callback handling. */
- virtual tree get_fndecl_for_call (const gcall *call) = 0;
+ virtual tree get_fndecl_for_call (const gcall &call) = 0;
/* Get the old state of VAR at STMT. */
virtual state_machine::state_t get_state (const gimple *stmt,
Use P to purge state involving conjured_svalues. */
void
-binding_cluster::on_unknown_fncall (const gcall *call,
+binding_cluster::on_unknown_fncall (const gcall &call,
store_manager *mgr,
const conjured_purge &p)
{
/* Bind it to a new "conjured" value using CALL. */
const svalue *sval
= mgr->get_svalue_manager ()->get_or_create_conjured_svalue
- (m_base_region->get_type (), call, m_base_region, p);
+ (m_base_region->get_type (), &call, m_base_region, p);
bind (mgr, m_base_region, sval);
}
(either in this fncall, or in a prior one). */
void
-store::on_unknown_fncall (const gcall *call, store_manager *mgr,
+store::on_unknown_fncall (const gcall &call, store_manager *mgr,
const conjured_purge &p)
{
m_called_unknown_fn = true;
store_manager *mgr);
void mark_as_escaped ();
- void on_unknown_fncall (const gcall *call, store_manager *mgr,
+ void on_unknown_fncall (const gcall &call, store_manager *mgr,
const conjured_purge &p);
void on_asm (const gasm *stmt, store_manager *mgr,
const conjured_purge &p);
model_merger *merger);
void mark_as_escaped (const region *base_reg);
- void on_unknown_fncall (const gcall *call, store_manager *mgr,
+ void on_unknown_fncall (const gcall &call, store_manager *mgr,
const conjured_purge &p);
bool escaped_p (const region *reg) const;
/* Get the gcall * of this interprocedural call/return edge. */
-gcall *
+const gcall &
callgraph_superedge::get_call_stmt () const
{
if (m_cedge)
- return m_cedge->call_stmt;
+ return *m_cedge->call_stmt;
- return m_src->get_final_call ();
+ return *m_src->get_final_call ();
}
/* Get the calling fndecl at this interprocedural call/return edge. */
gcc_assert (TREE_CODE (parm_to_find) == PARM_DECL);
tree callee = get_callee_decl ();
- const gcall *call_stmt = get_call_stmt ();
+ const gcall &call_stmt = get_call_stmt ();
unsigned i = 0;
for (tree iter_parm = DECL_ARGUMENTS (callee); iter_parm;
iter_parm = DECL_CHAIN (iter_parm), ++i)
{
- if (i >= gimple_call_num_args (call_stmt))
+ if (i >= gimple_call_num_args (&call_stmt))
return NULL_TREE;
if (iter_parm == parm_to_find)
{
if (out)
*out = callsite_expr::from_zero_based_param (i);
- return gimple_call_arg (call_stmt, i);
+ return gimple_call_arg (&call_stmt, i);
}
}
callsite_expr *out) const
{
tree callee = get_callee_decl ();
- const gcall *call_stmt = get_call_stmt ();
+ const gcall &call_stmt = get_call_stmt ();
unsigned i = 0;
for (tree iter_parm = DECL_ARGUMENTS (callee); iter_parm;
iter_parm = DECL_CHAIN (iter_parm), ++i)
{
- if (i >= gimple_call_num_args (call_stmt))
+ if (i >= gimple_call_num_args (&call_stmt))
return NULL_TREE;
- tree param = gimple_call_arg (call_stmt, i);
+ tree param = gimple_call_arg (&call_stmt, i);
if (arg_to_find == param)
{
if (out)
if (parm)
return parm;
/* Otherwise try return value. */
- if (caller_expr == gimple_call_lhs (get_call_stmt ()))
+ if (caller_expr == gimple_call_lhs (&get_call_stmt ()))
{
if (out)
*out = callsite_expr::from_return_value ();
{
if (out)
*out = callsite_expr::from_return_value ();
- return gimple_call_lhs (get_call_stmt ());
+ return gimple_call_lhs (&get_call_stmt ());
}
return NULL_TREE;
return *const_cast <bb_to_node_t &> (m_bb_to_initial_node).get (bb);
}
- /* Get the supernode containing the second half of the gcall *
+ /* Get the supernode containing the second half of the gcall &
at an interprocedural call, within the caller. */
supernode *get_caller_next_node (cgraph_edge *edge) const
{
function *get_caller_function () const;
tree get_callee_decl () const;
tree get_caller_decl () const;
- gcall *get_call_stmt () const;
+ const gcall &get_call_stmt () const;
tree get_arg_for_parm (tree parm, callsite_expr *out) const;
tree get_parm_for_arg (tree arg, callsite_expr *out) const;
tree map_expr_from_caller_to_callee (tree caller_expr,
struct setjmp_record
{
setjmp_record (const exploded_node *enode,
- const gcall *setjmp_call)
- : m_enode (enode), m_setjmp_call (setjmp_call)
+ const gcall &setjmp_call)
+ : m_enode (enode), m_setjmp_call (&setjmp_call)
{
}
const exploded_node *m_enode;
const gcall *m_setjmp_call;
+ // non-null, but we can't use a reference since we're putting these in a hash_map
};
/* Concrete subclass of svalue representing buffers for setjmp/sigsetjmp,
static const svalue *
get_va_copy_arg (const region_model *model,
region_model_context *ctxt,
- const gcall *call,
+ const gcall &call,
unsigned arg_idx)
{
- tree arg = gimple_call_arg (call, arg_idx);
+ tree arg = gimple_call_arg (&call, arg_idx);
const svalue *arg_sval = model->get_rvalue (arg, ctxt);
if (const svalue *cast = arg_sval->maybe_undo_cast ())
arg_sval = cast;
private:
void on_va_start (sm_context &sm_ctxt, const supernode *node,
- const gcall *call) const;
+ const gcall &call) const;
void on_va_copy (sm_context &sm_ctxt, const supernode *node,
- const gcall *call) const;
+ const gcall &call) const;
void on_va_arg (sm_context &sm_ctxt, const supernode *node,
- const gcall *call) const;
+ const gcall &call) const;
void on_va_end (sm_context &sm_ctxt, const supernode *node,
- const gcall *call) const;
+ const gcall &call) const;
void check_for_ended_va_list (sm_context &sm_ctxt,
const supernode *node,
- const gcall *call,
+ const gcall &call,
const svalue *arg,
const char *usage_fnname) const;
};
const supernode *node,
const gimple *stmt) const
{
- if (const gcall *call = dyn_cast <const gcall *> (stmt))
+ if (const gcall *call_stmt = dyn_cast <const gcall *> (stmt))
{
- if (gimple_call_internal_p (call)
- && gimple_call_internal_fn (call) == IFN_VA_ARG)
+ const gcall &call = *call_stmt;
+
+ if (gimple_call_internal_p (call_stmt)
+ && gimple_call_internal_fn (call_stmt) == IFN_VA_ARG)
{
on_va_arg (sm_ctxt, node, call);
return false;
if (tree callee_fndecl = sm_ctxt.get_fndecl_for_call (call))
if (fndecl_built_in_p (callee_fndecl, BUILT_IN_NORMAL)
- && gimple_builtin_call_types_compatible_p (call, callee_fndecl))
+ && gimple_builtin_call_types_compatible_p (&call, callee_fndecl))
switch (DECL_UNCHECKED_FUNCTION_CODE (callee_fndecl))
{
default:
IDX to CALL. */
static const svalue *
-get_stateful_arg (sm_context &sm_ctxt, const gcall *call, unsigned arg_idx)
+get_stateful_arg (sm_context &sm_ctxt, const gcall &call, unsigned arg_idx)
{
- tree ap = gimple_call_arg (call, arg_idx);
+ tree ap = gimple_call_arg (&call, arg_idx);
if (ap
&& POINTER_TYPE_P (TREE_TYPE (ap)))
{
void
va_list_state_machine::on_va_start (sm_context &sm_ctxt,
const supernode *,
- const gcall *call) const
+ const gcall &call) const
{
const svalue *arg = get_stateful_arg (sm_ctxt, call, 0);
if (arg)
{
/* Transition from start state to "started". */
- if (sm_ctxt.get_state (call, arg) == m_start)
- sm_ctxt.set_next_state (call, arg, m_started);
+ if (sm_ctxt.get_state (&call, arg) == m_start)
+ sm_ctxt.set_next_state (&call, arg, m_started);
}
}
void
va_list_state_machine::check_for_ended_va_list (sm_context &sm_ctxt,
const supernode *node,
- const gcall *call,
+ const gcall &call,
const svalue *arg,
const char *usage_fnname) const
{
- if (sm_ctxt.get_state (call, arg) == m_ended)
- sm_ctxt.warn (node, call, arg,
+ if (sm_ctxt.get_state (&call, arg) == m_ended)
+ sm_ctxt.warn (node, &call, arg,
make_unique<va_list_use_after_va_end>
(*this, arg, NULL_TREE, usage_fnname));
}
static const svalue *
get_stateful_va_copy_arg (sm_context &sm_ctxt,
- const gcall *call,
+ const gcall &call,
unsigned arg_idx)
{
if (const program_state *new_state = sm_ctxt.get_new_program_state ())
void
va_list_state_machine::on_va_copy (sm_context &sm_ctxt,
const supernode *node,
- const gcall *call) const
+ const gcall &call) const
{
const svalue *src_arg = get_stateful_va_copy_arg (sm_ctxt, call, 1);
if (src_arg)
if (dst_arg)
{
/* Transition from start state to "started". */
- if (sm_ctxt.get_state (call, dst_arg) == m_start)
- sm_ctxt.set_next_state (call, dst_arg, m_started);
+ if (sm_ctxt.get_state (&call, dst_arg) == m_start)
+ sm_ctxt.set_next_state (&call, dst_arg, m_started);
}
}
void
va_list_state_machine::on_va_arg (sm_context &sm_ctxt,
const supernode *node,
- const gcall *call) const
+ const gcall &call) const
{
const svalue *arg = get_stateful_arg (sm_ctxt, call, 0);
if (arg)
void
va_list_state_machine::on_va_end (sm_context &sm_ctxt,
const supernode *node,
- const gcall *call) const
+ const gcall &call) const
{
const svalue *arg = get_stateful_arg (sm_ctxt, call, 0);
if (arg)
{
- state_t s = sm_ctxt.get_state (call, arg);
+ state_t s = sm_ctxt.get_state (&call, arg);
/* Transition from "started" to "ended". */
if (s == m_started)
- sm_ctxt.set_next_state (call, arg, m_ended);
+ sm_ctxt.set_next_state (&call, arg, m_ended);
else if (s == m_ended)
check_for_ended_va_list (sm_ctxt, node, call, arg, "va_end");
}
static int
get_num_variadic_arguments (tree callee_fndecl,
- const gcall *call_stmt)
+ const gcall &call_stmt)
{
int num_positional = 0;
for (tree iter_parm = DECL_ARGUMENTS (callee_fndecl); iter_parm;
iter_parm = DECL_CHAIN (iter_parm))
num_positional++;
- return gimple_call_num_args (call_stmt) - num_positional;
+ return gimple_call_num_args (&call_stmt) - num_positional;
}
/* An abstract subclass of pending_diagnostic for diagnostics relating
const program_point &src_point = src_node->get_point ();
const int src_stack_depth = src_point.get_stack_depth ();
const gimple *last_stmt = src_point.get_supernode ()->get_last_stmt ();
- const gcall *call_stmt = as_a <const gcall *> (last_stmt);
+ const gcall &call_stmt = *as_a <const gcall *> (last_stmt);
int num_variadic_arguments
= get_num_variadic_arguments (dst_node->get_function ()->decl,
call_stmt);
private:
void check_for_pyobject_in_call (sm_context &sm_ctxt,
const supernode *node,
- const gcall *call,
+ const gcall &call,
tree callee_fndecl) const;
public:
class double_save_thread : public gil_diagnostic
{
public:
- double_save_thread (const gil_state_machine &sm, const gcall *call)
+ double_save_thread (const gil_state_machine &sm, const gcall &call)
: gil_diagnostic (sm), m_call (call)
{}
{
const double_save_thread &sub_other
= (const double_save_thread &)base_other;
- return m_call == sub_other.m_call;
+ return &m_call == &sub_other.m_call;
}
bool emit (diagnostic_emission_context &ctxt) final override
}
private:
- const gcall *m_call;
+ const gcall &m_call;
};
class fncall_without_gil : public gil_diagnostic
{
public:
- fncall_without_gil (const gil_state_machine &sm, const gcall *call,
+ fncall_without_gil (const gil_state_machine &sm, const gcall &call,
tree callee_fndecl, unsigned arg_idx)
: gil_diagnostic (sm), m_call (call), m_callee_fndecl (callee_fndecl),
m_arg_idx (arg_idx)
{
const fncall_without_gil &sub_other
= (const fncall_without_gil &)base_other;
- return (m_call == sub_other.m_call
+ return (&m_call == &sub_other.m_call
&& m_callee_fndecl == sub_other.m_callee_fndecl
&& m_arg_idx == sub_other.m_arg_idx);
}
}
private:
- const gcall *m_call;
+ const gcall &m_call;
tree m_callee_fndecl;
unsigned m_arg_idx;
};
void
gil_state_machine::check_for_pyobject_in_call (sm_context &sm_ctxt,
const supernode *node,
- const gcall *call,
+ const gcall &call,
tree callee_fndecl) const
{
- for (unsigned i = 0; i < gimple_call_num_args (call); i++)
+ for (unsigned i = 0; i < gimple_call_num_args (&call); i++)
{
- tree arg = gimple_call_arg (call, i);
+ tree arg = gimple_call_arg (&call, i);
if (TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE)
continue;
tree type = TREE_TYPE (TREE_TYPE (arg));
if (type_based_on_pyobject_p (type))
{
- sm_ctxt.warn (node, call, NULL_TREE,
+ sm_ctxt.warn (node, &call, NULL_TREE,
make_unique<fncall_without_gil> (*this, call,
callee_fndecl,
i));
const gimple *stmt) const
{
const state_t global_state = sm_ctxt.get_global_state ();
- if (const gcall *call = dyn_cast <const gcall *> (stmt))
+ if (const gcall *call_stmt = dyn_cast <const gcall *> (stmt))
{
+ const gcall &call = *call_stmt;
if (tree callee_fndecl = sm_ctxt.get_fndecl_for_call (call))
{
if (is_named_call_p (callee_fndecl, "PyEval_SaveThread", call, 0))