Modernization; no functional change intended.
gcc/analyzer/ChangeLog:
* access-diagram.cc: Convert enum access_direction to
"enum class".
* bounds-checking.cc: Likewise.
* checker-event.cc: Convert enum event_kind to "enum class".
* checker-event.h: Likewise.
* checker-path.cc: Likewise.
* common.h: Convert enum access_direction to "enum class".
* constraint-manager.cc: Convert enum bound_kind to "enum class".
* constraint-manager.h: Likewise.
* diagnostic-manager.cc: Convert enum event_kind to "enum class".
* engine.cc: Convert enum status to "enum class".
* exploded-graph.h: Likewise.
* infinite-loop.cc: Likewise.
* kf-lang-cp.cc: Convert enum poison_kind to "enum class".
* kf.cc: Likewise.
* region-model-manager.cc: Likewise.
* region-model.cc: Likewise; also for enum access_direction.
* svalue.cc: Likewise.
* svalue.h: Likewise.
gcc/testsuite/ChangeLog:
* gcc.dg/plugin/analyzer_cpython_plugin.cc: Convert
enum poison_kind to "enum class".
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
pp_format_decoder (&pp) = default_tree_printer;
if (num_bits.maybe_print_for_user (&pp, op.m_model))
{
- if (op.m_dir == DIR_READ)
+ if (op.m_dir == access_direction::read)
return fmt_styled_string (sm,
_("read of %qT (%s)"),
type,
pp_formatted_text (&pp));
}
}
- if (op.m_dir == DIR_READ)
+ if (op.m_dir == access_direction::read)
{
if (auto p
= num_bits.maybe_get_formatted_str (sm, op.m_model,
if (type)
{
- if (op.m_dir == DIR_READ)
+ if (op.m_dir == access_direction::read)
return fmt_styled_string (sm, _("read of %qT"), type);
else
return fmt_styled_string (sm, _("write of %qT"), type);
}
- if (op.m_dir == DIR_READ)
+ if (op.m_dir == access_direction::read)
return styled_string (sm, _("read"));
else
return styled_string (sm, _("write"));
bit_size_expr num_before_bits
(invalid_before_bits.get_size (m_op.get_manager ()));
std::unique_ptr<styled_string> label;
- if (m_op.m_dir == DIR_READ)
+ if (m_op.m_dir == access_direction::read)
label = num_before_bits.maybe_get_formatted_str
(m_sm, m_op.m_model,
_("under-read of %wi bit"),
maybe_add_gap (w, invalid_before_bits, valid_bits);
std::unique_ptr<styled_string> label;
- if (m_op.m_dir == DIR_READ)
+ if (m_op.m_dir == access_direction::read)
label = num_valid_bits.maybe_get_formatted_str (m_sm,
m_op.m_model,
_("size: %wi bit"),
bit_size_expr num_after_bits
(invalid_after_bits.get_size (m_op.get_manager ()));
std::unique_ptr<styled_string> label;
- if (m_op.m_dir == DIR_READ)
+ if (m_op.m_dir == access_direction::read)
label = num_after_bits.maybe_get_formatted_str
(m_sm, m_op.m_model,
_("over-read of %wi bit"),
(canvas,
canvas_x,
canvas::range_t (get_y_range ()),
- (m_dia_impl.get_op ().m_dir == DIR_READ
+ (m_dia_impl.get_op ().m_dir == access_direction::read
? theme::y_arrow_dir::UP
: theme::y_arrow_dir::DOWN),
style_id);
sarif_property_bag &props = result_obj.get_or_create_properties ();
#define PROPERTY_PREFIX "gcc/analyzer/out_of_bounds/"
props.set_string (PROPERTY_PREFIX "dir",
- get_dir () == DIR_READ ? "read" : "write");
+ get_dir () == access_direction::read ? "read" : "write");
props.set (PROPERTY_PREFIX "model", m_model.to_json ());
props.set (PROPERTY_PREFIX "region", m_reg->to_json ());
props.set (PROPERTY_PREFIX "diag_arg", tree_to_json (m_diag_arg));
}
}
- enum access_direction get_dir () const final override { return DIR_WRITE; }
+ enum access_direction get_dir () const final override { return access_direction::write; }
};
/* Concrete subclass to complain about buffer over-reads. */
}
}
- enum access_direction get_dir () const final override { return DIR_READ; }
+ enum access_direction get_dir () const final override { return access_direction::read; }
};
/* Concrete subclass to complain about buffer underwrites. */
}
}
- enum access_direction get_dir () const final override { return DIR_WRITE; }
+ enum access_direction get_dir () const final override { return access_direction::write; }
};
/* Concrete subclass to complain about buffer under-reads. */
}
}
- enum access_direction get_dir () const final override { return DIR_READ; }
+ enum access_direction get_dir () const final override { return access_direction::read; }
};
/* Abstract class to complain about out-of-bounds read/writes where
return true;
}
- enum access_direction get_dir () const final override { return DIR_WRITE; }
+ enum access_direction get_dir () const final override { return access_direction::write; }
};
/* Concrete subclass to complain about over-reads with symbolic values. */
return true;
}
- enum access_direction get_dir () const final override { return DIR_READ; }
+ enum access_direction get_dir () const final override { return access_direction::read; }
};
const svalue *
default:
gcc_unreachable ();
break;
- case DIR_READ:
+ case access_direction::read:
gcc_assert (sval_hint == nullptr);
ctxt->warn (make_unique<symbolic_buffer_over_read> (*this,
sized_offset_reg,
capacity_tree));
return false;
break;
- case DIR_WRITE:
+ case access_direction::write:
ctxt->warn (make_unique<symbolic_buffer_overflow> (*this,
sized_offset_reg,
diag_arg,
default:
gcc_unreachable ();
break;
- case DIR_READ:
+ case access_direction::read:
gcc_assert (sval_hint == nullptr);
ctxt->warn (make_unique<concrete_buffer_under_read> (*this, reg,
diag_arg,
bits_outside));
oob_safe = false;
break;
- case DIR_WRITE:
+ case access_direction::write:
ctxt->warn (make_unique<concrete_buffer_underwrite> (*this,
reg, diag_arg,
bits_outside,
default:
gcc_unreachable ();
break;
- case DIR_READ:
+ case access_direction::read:
gcc_assert (sval_hint == nullptr);
ctxt->warn (make_unique<concrete_buffer_over_read> (*this,
reg, diag_arg,
bit_bound));
oob_safe = false;
break;
- case DIR_WRITE:
+ case access_direction::write:
ctxt->warn (make_unique<concrete_buffer_overflow> (*this,
reg, diag_arg,
bits_outside,
{
default:
gcc_unreachable ();
- case EK_DEBUG:
- return "EK_DEBUG";
- case EK_CUSTOM:
- return "EK_CUSTOM";
- case EK_STMT:
- return "EK_STMT";
- case EK_REGION_CREATION:
- return "EK_REGION_CREATION";
- case EK_FUNCTION_ENTRY:
- return "EK_FUNCTION_ENTRY";
- case EK_STATE_CHANGE:
- return "EK_STATE_CHANGE";
- case EK_START_CFG_EDGE:
- return "EK_START_CFG_EDGE";
- case EK_END_CFG_EDGE:
- return "EK_END_CFG_EDGE";
- case EK_CALL_EDGE:
- return "EK_CALL_EDGE";
- case EK_RETURN_EDGE:
- return "EK_RETURN_EDGE";
- case EK_START_CONSOLIDATED_CFG_EDGES:
- return "EK_START_CONSOLIDATED_CFG_EDGES";
- case EK_END_CONSOLIDATED_CFG_EDGES:
- return "EK_END_CONSOLIDATED_CFG_EDGES";
- case EK_INLINED_CALL:
- return "EK_INLINED_CALL";
- case EK_SETJMP:
- return "EK_SETJMP";
- case EK_REWIND_FROM_LONGJMP:
- return "EK_REWIND_FROM_LONGJMP";
- case EK_REWIND_TO_SETJMP:
- return "EK_REWIND_TO_SETJMP";
- case EK_WARNING:
- return "EK_WARNING";
+ case event_kind::debug:
+ return "debug";
+ case event_kind::custom:
+ return "custom";
+ case event_kind::stmt:
+ return "stmt";
+ case event_kind::region_creation:
+ return "region_creation";
+ case event_kind::function_entry:
+ return "function_entry";
+ case event_kind::state_change:
+ return "state_change";
+ case event_kind::start_cfg_edge:
+ return "start_cfg_edge";
+ case event_kind::end_cfg_edge:
+ return "end_cfg_edge";
+ case event_kind::call_edge:
+ return "call_edge";
+ case event_kind::return_edge:
+ return "return_edge";
+ case event_kind::start_consolidated_cfg_edges:
+ return "start_consolidated_cfg_edges";
+ case event_kind::end_consolidated_cfg_edges:
+ return "end_consolidated_cfg_edges";
+ case event_kind::inlined_call:
+ return "inlined_call";
+ case event_kind::setjmp_:
+ return "setjmp";
+ case event_kind::rewind_from_longjmp:
+ return "rewind_from_longjmp";
+ case event_kind::rewind_to_setjmp:
+ return "rewind_to_setjmp";
+ case event_kind::warning:
+ return "warning";
}
}
statement_event::statement_event (const gimple *stmt, tree fndecl, int depth,
const program_state &dst_state)
-: checker_event (EK_STMT,
+: checker_event (event_kind::stmt,
event_loc_info (gimple_location (stmt), fndecl, depth)),
m_stmt (stmt),
m_dst_state (dst_state)
/* class region_creation_event : public checker_event. */
region_creation_event::region_creation_event (const event_loc_info &loc_info)
-: checker_event (EK_REGION_CREATION, loc_info)
+: checker_event (event_kind::region_creation, loc_info)
{
}
/* class function_entry_event : public checker_event. */
function_entry_event::function_entry_event (const program_point &dst_point)
-: checker_event (EK_FUNCTION_ENTRY,
+: checker_event (event_kind::function_entry,
event_loc_info (dst_point.get_supernode
()->get_start_location (),
dst_point.get_fndecl (),
const svalue *origin,
const program_state &dst_state,
const exploded_node *enode)
-: checker_event (EK_STATE_CHANGE,
+: checker_event (event_kind::state_change,
event_loc_info (stmt->location,
node->m_fun->decl,
stack_depth)),
call_event::call_event (const exploded_edge &eedge,
const event_loc_info &loc_info)
-: superedge_event (EK_CALL_EDGE, eedge, loc_info)
+: superedge_event (event_kind::call_edge, eedge, loc_info)
{
if (eedge.m_sedge)
gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_CALL);
return_event::return_event (const exploded_edge &eedge,
const event_loc_info &loc_info)
-: superedge_event (EK_RETURN_EDGE, eedge, loc_info)
+: superedge_event (event_kind::return_edge, eedge, loc_info)
{
if (eedge.m_sedge)
gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_RETURN);
/* An enum for discriminating between the concrete subclasses of
checker_event. */
-enum event_kind
+enum class event_kind
{
- EK_DEBUG,
- EK_CUSTOM,
- EK_STMT,
- EK_REGION_CREATION,
- EK_FUNCTION_ENTRY,
- EK_STATE_CHANGE,
- EK_START_CFG_EDGE,
- EK_END_CFG_EDGE,
- EK_CALL_EDGE,
- EK_RETURN_EDGE,
- EK_START_CONSOLIDATED_CFG_EDGES,
- EK_END_CONSOLIDATED_CFG_EDGES,
- EK_INLINED_CALL,
- EK_SETJMP,
- EK_REWIND_FROM_LONGJMP,
- EK_REWIND_TO_SETJMP,
- EK_WARNING
+ debug,
+ custom,
+ stmt,
+ region_creation,
+ function_entry,
+ state_change,
+ start_cfg_edge,
+ end_cfg_edge,
+ call_edge,
+ return_edge,
+ start_consolidated_cfg_edges,
+ end_consolidated_cfg_edges,
+ inlined_call,
+ setjmp_,
+ rewind_from_longjmp,
+ rewind_to_setjmp,
+ warning
};
extern const char *event_kind_to_string (enum event_kind ek);
diagnostic_event
checker_event
- debug_event (EK_DEBUG)
- custom_event (EK_CUSTOM)
+ debug_event (event_kind::debug)
+ custom_event (event_kind::custom)
precanned_custom_event
- statement_event (EK_STMT)
- region_creation_event (EK_REGION_CREATION)
- function_entry_event (EK_FUNCTION_ENTRY)
- state_change_event (EK_STATE_CHANGE)
+ statement_event (event_kind::stmt)
+ region_creation_event (event_kind::region_creation)
+ function_entry_event (event_kind::function_entry)
+ state_change_event (event_kind::state_change)
superedge_event
cfg_edge_event
- start_cfg_edge_event (EK_START_CFG_EDGE)
- end_cfg_edge_event (EK_END_CFG_EDGE)
- call_event (EK_CALL_EDGE)
- return_edge (EK_RETURN_EDGE)
- start_consolidated_cfg_edges_event (EK_START_CONSOLIDATED_CFG_EDGES)
- end_consolidated_cfg_edges_event (EK_END_CONSOLIDATED_CFG_EDGES)
- inlined_call_event (EK_INLINED_CALL)
- setjmp_event (EK_SETJMP)
+ start_cfg_edge_event (event_kind::start_cfg_edge)
+ end_cfg_edge_event (event_kind::end_cfg_edge)
+ call_event (event_kind::call_edge)
+ return_edge (event_kind::return_edge)
+ start_consolidated_cfg_edges_event (event_kind::start_consolidated_cfg_edges)
+ end_consolidated_cfg_edges_event (event_kind::end_consolidated_cfg_edges)
+ inlined_call_event (event_kind::inlined_call)
+ setjmp_event (event_kind::setjmp_)
rewind_event
- rewind_from_longjmp_event (EK_REWIND_FROM_LONGJMP)
- rewind_to_setjmp_event (EK_REWIND_TO_SETJMP)
- warning_event (EK_WARNING). */
+ rewind_from_longjmp_event (event_kind::rewind_from_longjmp)
+ rewind_to_setjmp_event (event_kind::rewind_to_setjmp)
+ warning_event (event_kind::warning). */
/* Abstract subclass of diagnostic_event; the base class for use in
checker_path (the analyzer's diagnostic_path subclass). */
debug_event (const event_loc_info &loc_info,
const char *desc)
- : checker_event (EK_DEBUG, loc_info),
+ : checker_event (event_kind::debug, loc_info),
m_desc (xstrdup (desc))
{
}
{
protected:
custom_event (const event_loc_info &loc_info)
- : checker_event (EK_CUSTOM, loc_info)
+ : checker_event (event_kind::custom, loc_info)
{
}
};
{
public:
function_entry_event (const event_loc_info &loc_info)
- : checker_event (EK_FUNCTION_ENTRY, loc_info)
+ : checker_event (event_kind::function_entry, loc_info)
{
}
public:
start_cfg_edge_event (const exploded_edge &eedge,
const event_loc_info &loc_info)
- : cfg_edge_event (EK_START_CFG_EDGE, eedge, loc_info)
+ : cfg_edge_event (event_kind::start_cfg_edge, eedge, loc_info)
{
}
public:
end_cfg_edge_event (const exploded_edge &eedge,
const event_loc_info &loc_info)
- : cfg_edge_event (EK_END_CFG_EDGE, eedge, loc_info)
+ : cfg_edge_event (event_kind::end_cfg_edge, eedge, loc_info)
{
}
public:
start_consolidated_cfg_edges_event (const event_loc_info &loc_info,
bool edge_sense)
- : checker_event (EK_START_CONSOLIDATED_CFG_EDGES, loc_info),
+ : checker_event (event_kind::start_consolidated_cfg_edges, loc_info),
m_edge_sense (edge_sense)
{
}
{
public:
end_consolidated_cfg_edges_event (const event_loc_info &loc_info)
- : checker_event (EK_END_CONSOLIDATED_CFG_EDGES, loc_info)
+ : checker_event (event_kind::end_consolidated_cfg_edges, loc_info)
{
}
tree apparent_caller_fndecl,
int actual_depth,
int stack_depth_adjustment)
- : checker_event (EK_INLINED_CALL,
+ : checker_event (event_kind::inlined_call,
event_loc_info (loc,
apparent_caller_fndecl,
actual_depth + stack_depth_adjustment)),
setjmp_event (const event_loc_info &loc_info,
const exploded_node *enode,
const gcall *setjmp_call)
- : checker_event (EK_SETJMP, loc_info),
+ : checker_event (event_kind::setjmp_, loc_info),
m_enode (enode), m_setjmp_call (setjmp_call)
{
}
rewind_from_longjmp_event (const exploded_edge *eedge,
const event_loc_info &loc_info,
const rewind_info_t *rewind_info)
- : rewind_event (eedge, EK_REWIND_FROM_LONGJMP, loc_info,
+ : rewind_event (eedge, event_kind::rewind_from_longjmp, loc_info,
rewind_info)
{
}
rewind_to_setjmp_event (const exploded_edge *eedge,
const event_loc_info &loc_info,
const rewind_info_t *rewind_info)
- : rewind_event (eedge, EK_REWIND_TO_SETJMP, loc_info,
+ : rewind_event (eedge, event_kind::rewind_to_setjmp, loc_info,
rewind_info)
{
}
const exploded_node *enode,
const state_machine *sm,
tree var, state_machine::state_t state)
- : checker_event (EK_WARNING, loc_info),
+ : checker_event (event_kind::warning, loc_info),
m_enode (enode),
m_sm (sm), m_var (var), m_state (state)
{
{
if (m_events.length () < idx + 1)
return false;
- return (m_events[idx]->m_kind == EK_START_CFG_EDGE
- && m_events[idx + 1]->m_kind == EK_END_CFG_EDGE);
+ return (m_events[idx]->m_kind == event_kind::start_cfg_edge
+ && m_events[idx + 1]->m_kind == event_kind::end_cfg_edge);
}
/* Consider a call from "outer" to "middle" which calls "inner",
(for gcc.dg/analyzer/inlining-4.c):
before[0]:
- EK_FUNCTION_ENTRY "entry to ‘outer’"
+ event_kind::function_entry "entry to ‘outer’"
(depth 1, fndecl ‘outer’, m_loc=511c4)
before[1]:
- EK_START_CFG_EDGE "following ‘true’ branch (when ‘flag != 0’)..."
+ event_kind::start_cfg_edge "following ‘true’ branch (when ‘flag != 0’)..."
(depth 3 corrected from 1,
fndecl ‘inner’ corrected from ‘outer’, m_loc=8000000f)
before[2]:
- EK_END_CFG_EDGE "...to here"
+ event_kind::end_cfg_edge "...to here"
(depth 1, fndecl ‘outer’, m_loc=0)
before[3]:
- EK_WARNING "here (‘<unknown>’ is in state ‘null’)"
+ event_kind::warning "here (‘<unknown>’ is in state ‘null’)"
(depth 1, fndecl ‘outer’, m_loc=80000004)
We want to add inlined_call_events showing the calls, so that
the above becomes:
after[0]:
- EK_FUNCTION_ENTRY "entry to ‘outer’"
+ event_kind::function_entry "entry to ‘outer’"
(depth 1, fndecl ‘outer’, m_loc=511c4)
after[1]:
- EK_INLINED_CALL "inlined call to ‘middle’ from ‘outer’"
+ event_kind::inlined_call "inlined call to ‘middle’ from ‘outer’"
(depth 1, fndecl ‘outer’, m_loc=53300)
after[2]:
- EK_INLINED_CALL "inlined call to ‘inner’ from ‘middle’"
+ event_kind::inlined_call "inlined call to ‘inner’ from ‘middle’"
(depth 2, fndecl ‘middle’, m_loc=4d2e0)
after[3]:
- EK_START_CFG_EDGE "following ‘true’ branch (when ‘flag != 0’)..."
+ event_kind::start_cfg_edge "following ‘true’ branch (when ‘flag != 0’)..."
(depth 3 corrected from 1,
fndecl ‘inner’ corrected from ‘outer’, m_loc=8000000f)
- after[4]: EK_END_CFG_EDGE "...to here"
+ after[4]: event_kind::end_cfg_edge "...to here"
(depth 1, fndecl ‘outer’, m_loc=0)
- after[5]: EK_WARNING "here (‘<unknown>’ is in state ‘null’)"
+ after[5]: event_kind::warning "here (‘<unknown>’ is in state ‘null’)"
(depth 1, fndecl ‘outer’, m_loc=80000004)
where we've added events between before[0] and before[1] to show
/* An enum for describing the direction of an access to memory. */
-enum access_direction
+enum class access_direction
{
- DIR_READ,
- DIR_WRITE
+ read,
+ write
};
/* Abstract base class for associating custom data with an
and convert x < 5 into x <= 4. */
gcc_assert (CONSTANT_CLASS_P (m_constant));
gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (m_constant)));
- m_constant = fold_build2 (bound_kind == BK_UPPER ? MINUS_EXPR : PLUS_EXPR,
+ m_constant = fold_build2 (bound_kind == bound_kind::upper ? MINUS_EXPR : PLUS_EXPR,
TREE_TYPE (m_constant),
m_constant, integer_one_node);
gcc_assert (CONSTANT_CLASS_P (m_constant));
return NULL_TREE;
/* Convert any open bounds to closed bounds. */
- m_lower_bound.ensure_closed (BK_LOWER);
- m_upper_bound.ensure_closed (BK_UPPER);
+ m_lower_bound.ensure_closed (bound_kind::lower);
+ m_upper_bound.ensure_closed (bound_kind::upper);
// Are they equal?
tree comparison = fold_binary (EQ_EXPR, boolean_type_node,
{
default:
gcc_unreachable ();
- case BK_LOWER:
+ case bound_kind::lower:
/* Discard redundant bounds. */
if (m_lower_bound.m_constant)
{
- m_lower_bound.ensure_closed (BK_LOWER);
+ m_lower_bound.ensure_closed (bound_kind::lower);
if (tree_int_cst_le (b.m_constant,
m_lower_bound.m_constant))
return true;
}
if (m_upper_bound.m_constant)
{
- m_upper_bound.ensure_closed (BK_UPPER);
+ m_upper_bound.ensure_closed (bound_kind::upper);
/* Reject B <= V <= UPPER when B > UPPER. */
if (!tree_int_cst_le (b.m_constant,
m_upper_bound.m_constant))
m_lower_bound = b;
break;
- case BK_UPPER:
+ case bound_kind::upper:
/* Discard redundant bounds. */
if (m_upper_bound.m_constant)
{
- m_upper_bound.ensure_closed (BK_UPPER);
+ m_upper_bound.ensure_closed (bound_kind::upper);
if (!tree_int_cst_lt (b.m_constant,
m_upper_bound.m_constant))
return true;
}
if (m_lower_bound.m_constant)
{
- m_lower_bound.ensure_closed (BK_LOWER);
+ m_lower_bound.ensure_closed (bound_kind::lower);
/* Reject LOWER <= V <= B when LOWER > B. */
if (!tree_int_cst_le (m_lower_bound.m_constant,
b.m_constant))
return true;
case LT_EXPR:
/* "V < RHS_CONST" */
- return add_bound (bound (rhs_const, false), BK_UPPER);
+ return add_bound (bound (rhs_const, false), bound_kind::upper);
case LE_EXPR:
/* "V <= RHS_CONST" */
- return add_bound (bound (rhs_const, true), BK_UPPER);
+ return add_bound (bound (rhs_const, true), bound_kind::upper);
case GE_EXPR:
/* "V >= RHS_CONST" */
- return add_bound (bound (rhs_const, true), BK_LOWER);
+ return add_bound (bound (rhs_const, true), bound_kind::lower);
case GT_EXPR:
/* "V > RHS_CONST" */
- return add_bound (bound (rhs_const, false), BK_LOWER);
+ return add_bound (bound (rhs_const, false), bound_kind::lower);
}
}
case CONSTRAINT_LT:
/* We have "EC_ID < OTHER_CST". */
- result.add_bound (bound (other_cst, false), BK_UPPER);
+ result.add_bound (bound (other_cst, false), bound_kind::upper);
break;
case CONSTRAINT_LE:
/* We have "EC_ID <= OTHER_CST". */
- result.add_bound (bound (other_cst, true), BK_UPPER);
+ result.add_bound (bound (other_cst, true), bound_kind::upper);
break;
}
}
case CONSTRAINT_LT:
/* We have "OTHER_CST < EC_ID"
i.e. "EC_ID > OTHER_CST". */
- result.add_bound (bound (other_cst, false), BK_LOWER);
+ result.add_bound (bound (other_cst, false), bound_kind::lower);
break;
case CONSTRAINT_LE:
/* We have "OTHER_CST <= EC_ID"
i.e. "EC_ID >= OTHER_CST". */
- result.add_bound (bound (other_cst, true), BK_LOWER);
+ result.add_bound (bound (other_cst, true), bound_kind::lower);
break;
}
}
class constraint_manager;
-enum bound_kind
+enum class bound_kind
{
- BK_LOWER,
- BK_UPPER
+ lower,
+ upper
};
/* One of the end-points of a range. */
default:
gcc_unreachable ();
- case EK_DEBUG:
+ case event_kind::debug:
if (m_verbosity < 4)
{
log ("filtering event %i: debug event", idx);
}
break;
- case EK_CUSTOM:
+ case event_kind::custom:
/* Don't filter custom events. */
break;
- case EK_STMT:
+ case event_kind::stmt:
{
if (m_verbosity < 4)
{
}
break;
- case EK_REGION_CREATION:
+ case event_kind::region_creation:
/* Don't filter these. */
break;
- case EK_FUNCTION_ENTRY:
+ case event_kind::function_entry:
if (m_verbosity < 1)
{
log ("filtering event %i: function entry", idx);
}
break;
- case EK_STATE_CHANGE:
+ case event_kind::state_change:
{
state_change_event *state_change = (state_change_event *)base_event;
gcc_assert (state_change->m_dst_state.m_region_model);
}
break;
- case EK_START_CFG_EDGE:
+ case event_kind::start_cfg_edge:
{
cfg_edge_event *event = (cfg_edge_event *)base_event;
{
log ("filtering events %i and %i: CFG edge", idx, idx + 1);
path->delete_event (idx);
- /* Also delete the corresponding EK_END_CFG_EDGE. */
+ /* Also delete the corresponding event_kind::end_cfg_edge. */
gcc_assert (path->get_checker_event (idx)->m_kind
- == EK_END_CFG_EDGE);
+ == event_kind::end_cfg_edge);
path->delete_event (idx);
}
}
break;
- case EK_END_CFG_EDGE:
- /* These come in pairs with EK_START_CFG_EDGE events and are
+ case event_kind::end_cfg_edge:
+ /* These come in pairs with event_kind::start_cfg_edge events and are
filtered when their start event is filtered. */
break;
- case EK_CALL_EDGE:
+ case event_kind::call_edge:
{
call_event *event = (call_event *)base_event;
const region_model *callee_model
}
break;
- case EK_RETURN_EDGE:
+ case event_kind::return_edge:
{
if (sval)
{
}
break;
- case EK_INLINED_CALL:
+ case event_kind::inlined_call:
/* We don't expect to see these yet, as they're added later.
We'd want to keep them around. */
break;
- case EK_SETJMP:
+ case event_kind::setjmp_:
/* TODO: only show setjmp_events that matter i.e. those for which
there is a later rewind event using them. */
- case EK_REWIND_FROM_LONGJMP:
- case EK_REWIND_TO_SETJMP:
+ case event_kind::rewind_from_longjmp:
+ case event_kind::rewind_to_setjmp:
break;
- case EK_WARNING:
+ case event_kind::warning:
/* Always show the final "warning" event in the path. */
break;
}
continue;
/* Are we looking for a run of all TRUE edges, or all FALSE edges? */
- gcc_assert (old_start_ev->m_kind == EK_START_CFG_EDGE);
+ gcc_assert (old_start_ev->m_kind == event_kind::start_cfg_edge);
const start_cfg_edge_event *old_start_cfg_ev
= (const start_cfg_edge_event *)old_start_ev;
const cfg_superedge& first_cfg_sedge
{
const checker_event *iter_ev
= path->get_checker_event (next_idx);
- gcc_assert (iter_ev->m_kind == EK_START_CFG_EDGE);
+ gcc_assert (iter_ev->m_kind == event_kind::start_cfg_edge);
const start_cfg_edge_event *iter_cfg_ev
= (const start_cfg_edge_event *)iter_ev;
const cfg_superedge& iter_cfg_sedge
while (idx >= 0 && idx < (signed)path->num_events ())
{
checker_event *base_event = path->get_checker_event (idx);
- if (base_event->m_kind == EK_FUNCTION_ENTRY)
+ if (base_event->m_kind == event_kind::function_entry)
{
log ("filtering event %i:"
" function entry for purely intraprocedural path", idx);
switch (s)
{
default: gcc_unreachable ();
- case STATUS_WORKLIST: return "WORKLIST";
- case STATUS_PROCESSED: return "PROCESSED";
- case STATUS_MERGER: return "MERGER";
- case STATUS_BULK_MERGED: return "BULK_MERGED";
+ case status::worklist: return "worklist";
+ case status::processed: return "processed";
+ case status::merger: return "merger";
+ case status::bulk_merged: return "bulk_merged";
}
}
exploded_node::exploded_node (const point_and_state &ps,
int index)
-: m_ps (ps), m_status (STATUS_WORKLIST), m_index (index),
+: m_ps (ps), m_status (status::worklist), m_index (index),
m_num_processed_stmts (0)
{
gcc_checking_assert (ps.get_state ().m_region_model->canonicalized_p ());
pp_write_text_to_stream (pp);
pp_printf (pp, "EN: %i", m_index);
- if (m_status == STATUS_MERGER)
+ if (m_status == status::merger)
pp_string (pp, " (merger)");
- else if (m_status == STATUS_BULK_MERGED)
+ else if (m_status == status::bulk_merged)
pp_string (pp, " (bulk merged)");
pp_newline (pp);
void
worklist::add_node (exploded_node *enode)
{
- gcc_assert (enode->get_status () == exploded_node::STATUS_WORKLIST);
+ gcc_assert (enode->get_status () == exploded_node::status::worklist);
m_queue.insert (key_t (*this, enode), enode);
}
while (m_worklist.length () > 0)
{
exploded_node *node = m_worklist.take_next ();
- gcc_assert (node->get_status () == exploded_node::STATUS_WORKLIST);
+ gcc_assert (node->get_status () == exploded_node::status::worklist);
gcc_assert (node->m_succs.length () == 0
|| node == m_origin);
if (exploded_node *node_2 = m_worklist.peek_next ())
{
gcc_assert (node_2->get_status ()
- == exploded_node::STATUS_WORKLIST);
+ == exploded_node::status::worklist);
gcc_assert (node->m_succs.length () == 0);
gcc_assert (node_2->m_succs.length () == 0);
/* Remove node_2 from the worklist. */
m_worklist.take_next ();
- node_2->set_status (exploded_node::STATUS_MERGER);
+ node_2->set_status (exploded_node::status::merger);
/* Continue processing "node" below. */
}
in the worklist, to be processed on the next
iteration. */
add_edge (node, node_2, NULL, false);
- node->set_status (exploded_node::STATUS_MERGER);
+ node->set_status (exploded_node::status::merger);
continue;
}
else
else
{
add_edge (node, merged_enode, NULL, false);
- node->set_status (exploded_node::STATUS_MERGER);
+ node->set_status (exploded_node::status::merger);
}
if (merged_enode == node_2)
else
{
add_edge (node_2, merged_enode, NULL, false);
- node_2->set_status (exploded_node::STATUS_MERGER);
+ node_2->set_status (exploded_node::status::merger);
}
continue;
If ENODE's point is of the form (before-supernode, SNODE) and the next
nodes in the worklist are a consecutive run of enodes of the same form,
for the same supernode as ENODE (but potentially from different in-edges),
- process them all together, setting their status to STATUS_BULK_MERGED,
+ process them all together, setting their status to status::bulk_merged,
and return true.
Otherwise, return false, in which case ENODE must be processed in the
normal way.
int m_merger_idx;
};
- gcc_assert (enode->get_status () == exploded_node::STATUS_WORKLIST);
+ gcc_assert (enode->get_status () == exploded_node::status::worklist);
gcc_assert (enode->m_succs.length () == 0);
const program_point &point = enode->get_point ();
while (exploded_node *enode_2 = m_worklist.peek_next ())
{
gcc_assert (enode_2->get_status ()
- == exploded_node::STATUS_WORKLIST);
+ == exploded_node::status::worklist);
gcc_assert (enode_2->m_succs.length () == 0);
const program_point &point_2 = enode_2->get_point ();
if (next)
add_edge (it->m_input_enode, next, NULL,
false); /* no "work" is done during merger. */
- it->m_input_enode->set_status (exploded_node::STATUS_BULK_MERGED);
+ it->m_input_enode->set_status (exploded_node::status::bulk_merged);
}
if (logger)
logger * const logger = get_logger ();
LOG_FUNC_1 (logger, "EN: %i", node->m_index);
- node->set_status (exploded_node::STATUS_PROCESSED);
+ node->set_status (exploded_node::status::processed);
const program_point &point = node->get_point ();
{
default:
gcc_unreachable ();
- case exploded_node::STATUS_WORKLIST:
+ case exploded_node::status::worklist:
worklist_enodes.safe_push (other_enode);
break;
- case exploded_node::STATUS_PROCESSED:
+ case exploded_node::status::processed:
processed_enodes.safe_push (other_enode);
break;
- case exploded_node::STATUS_MERGER:
+ case exploded_node::status::merger:
merger_enodes.safe_push (other_enode);
break;
}
{
default:
gcc_unreachable ();
- case exploded_node::STATUS_WORKLIST:
+ case exploded_node::status::worklist:
pp_string (pp, "(W)");
break;
- case exploded_node::STATUS_PROCESSED:
+ case exploded_node::status::processed:
break;
- case exploded_node::STATUS_MERGER:
+ case exploded_node::status::merger:
pp_string (pp, "(M)");
break;
- case exploded_node::STATUS_BULK_MERGED:
+ case exploded_node::status::bulk_merged:
pp_string (pp, "(BM)");
break;
}
This allows us to distinguish enodes that were merged during
worklist-handling, and thus never had process_node called on them
(in favor of processing the merged node). */
- enum status
+ enum class status
{
/* Node is in the worklist. */
- STATUS_WORKLIST,
+ worklist,
/* Node has had exploded_graph::process_node called on it. */
- STATUS_PROCESSED,
+ processed,
/* Node was left unprocessed due to merger; it won't have had
exploded_graph::process_node called on it. */
- STATUS_MERGER,
+ merger,
/* Node was processed by maybe_process_run_of_before_supernode_enodes. */
- STATUS_BULK_MERGED
+ bulk_merged
};
static const char * status_to_str (enum status s);
enum status get_status () const { return m_status; }
void set_status (enum status status)
{
- gcc_assert (m_status == STATUS_WORKLIST);
+ gcc_assert (m_status == status::worklist);
m_status = status;
}
if (logger)
logger->log ("iter: EN: %i", iter->m_index);
/* Analysis bailed out before processing this node. */
- if (iter->get_status () == exploded_node::STATUS_WORKLIST)
+ if (iter->get_status () == exploded_node::status::worklist)
{
if (logger)
logger->log ("rejecting: EN: %i is still in worklist",
/* If the ptr points to an underlying heap region, delete it,
poisoning pointers. */
model->unbind_region_and_descendents (freed_reg,
- POISON_KIND_DELETED);
+ poison_kind::deleted);
}
}
/* If the ptr points to an underlying heap region, delete it,
poisoning pointers. */
region_model *model = cd.get_model ();
- model->unbind_region_and_descendents (freed_reg, POISON_KIND_FREED);
+ model->unbind_region_and_descendents (freed_reg, poison_kind::freed);
model->unset_dynamic_extents (freed_reg);
}
}
/* If the ptr points to an underlying heap region, delete it,
poisoning pointers. */
- model->unbind_region_and_descendents (freed_reg, POISON_KIND_FREED);
+ model->unbind_region_and_descendents (freed_reg, poison_kind::freed);
model->unset_dynamic_extents (freed_reg);
}
bool check_poisoned)
{
if (!reg->can_have_initial_svalue_p () && check_poisoned)
- return get_or_create_poisoned_svalue (POISON_KIND_UNINIT,
+ return get_or_create_poisoned_svalue (poison_kind::uninit,
reg->get_type ());
/* The initial value of a cast is a cast of the initial value. */
bool use_of_uninit_p () const final override
{
- return m_pkind == POISON_KIND_UNINIT;
+ return m_pkind == poison_kind::uninit;
}
bool operator== (const poisoned_value_diagnostic &other) const
{
default:
gcc_unreachable ();
- case POISON_KIND_UNINIT:
+ case poison_kind::uninit:
return OPT_Wanalyzer_use_of_uninitialized_value;
- case POISON_KIND_FREED:
- case POISON_KIND_DELETED:
+ case poison_kind::freed:
+ case poison_kind::deleted:
return OPT_Wanalyzer_use_after_free;
- case POISON_KIND_POPPED_STACK:
+ case poison_kind::popped_stack:
return OPT_Wanalyzer_use_of_pointer_in_stale_stack_frame;
}
}
{
default:
gcc_unreachable ();
- case POISON_KIND_UNINIT:
+ case poison_kind::uninit:
{
ctxt.add_cwe (457); /* "CWE-457: Use of Uninitialized Variable". */
return ctxt.warn ("use of uninitialized value %qE",
m_expr);
}
break;
- case POISON_KIND_FREED:
+ case poison_kind::freed:
{
ctxt.add_cwe (416); /* "CWE-416: Use After Free". */
return ctxt.warn ("use after %<free%> of %qE",
m_expr);
}
break;
- case POISON_KIND_DELETED:
+ case poison_kind::deleted:
{
ctxt.add_cwe (416); /* "CWE-416: Use After Free". */
return ctxt.warn ("use after %<delete%> of %qE",
m_expr);
}
break;
- case POISON_KIND_POPPED_STACK:
+ case poison_kind::popped_stack:
{
/* TODO: which CWE? */
return ctxt.warn
{
default:
gcc_unreachable ();
- case POISON_KIND_UNINIT:
+ case poison_kind::uninit:
{
pp_printf (&pp,
"use of uninitialized value %qE here",
m_expr);
return true;
}
- case POISON_KIND_FREED:
+ case poison_kind::freed:
{
pp_printf (&pp,
"use after %<free%> of %qE here",
m_expr);
return true;
}
- case POISON_KIND_DELETED:
+ case poison_kind::deleted:
{
pp_printf (&pp,
"use after %<delete%> of %qE here",
m_expr);
return true;
}
- case POISON_KIND_POPPED_STACK:
+ case poison_kind::popped_stack:
{
pp_printf (&pp,
"dereferencing pointer %qE to within stale stack frame",
/* Ignore uninitialized uses of empty types; there's nothing
to initialize. */
- if (pkind == POISON_KIND_UNINIT
+ if (pkind == poison_kind::uninit
&& sval->get_type ()
&& is_empty_type (sval->get_type ()))
return sval;
- if (pkind == POISON_KIND_UNINIT)
+ if (pkind == poison_kind::uninit)
if (const gimple *curr_stmt = ctxt->get_stmt ())
if (const gassign *assign_stmt
= dyn_cast <const gassign *> (curr_stmt))
the tree other than via the def stmts, using
fixup_tree_for_diagnostic. */
tree diag_arg = fixup_tree_for_diagnostic (expr);
- if (src_region == NULL && pkind == POISON_KIND_UNINIT)
+ if (src_region == NULL && pkind == poison_kind::uninit)
src_region = get_region_for_poisoned_expr (expr);
/* Can we reliably get the poisoned value from "expr"?
{
default:
gcc_unreachable ();
- case DIR_READ:
+ case access_direction::read:
/* Currently a no-op. */
break;
- case DIR_WRITE:
+ case access_direction::write:
check_for_writable_region (reg, ctxt);
break;
}
const svalue *sval_hint,
region_model_context *ctxt) const
{
- check_region_access (dest_reg, DIR_WRITE, sval_hint, ctxt);
+ check_region_access (dest_reg, access_direction::write, sval_hint, ctxt);
}
/* If CTXT is non-NULL, use it to warn about any problems reading from REG.
region_model::check_region_for_read (const region *src_reg,
region_model_context *ctxt) const
{
- return check_region_access (src_reg, DIR_READ, NULL, ctxt);
+ return check_region_access (src_reg, access_direction::read, NULL, ctxt);
}
/* Concrete subclass for casts of pointers that lead to trailing bytes. */
Purge the frame region and all its descendent regions.
Convert any pointers that point into such regions into
- POISON_KIND_POPPED_STACK svalues. */
+ poison_kind::popped_stack svalues. */
void
region_model::pop_frame (tree result_lvalue,
set_value (result_dst_reg, retval, call_stmt ? &caller_ctxt : ctxt);
}
- unbind_region_and_descendents (frame_reg,POISON_KIND_POPPED_STACK);
+ unbind_region_and_descendents (frame_reg,poison_kind::popped_stack);
notify_on_pop_frame (this, &pre_popped_model, retval, ctxt);
}
{
const poisoned_svalue *poisoned_sval
= as_a <const poisoned_svalue *> (m_copied_sval);
- gcc_assert (poisoned_sval->get_poison_kind () == POISON_KIND_UNINIT);
+ gcc_assert (poisoned_sval->get_poison_kind () == poison_kind::uninit);
/* Give up if don't have type information. */
if (m_copied_sval->get_type () == NULL_TREE)
const svalue *sval = iter.second;
if (const poisoned_svalue *psval
= sval->dyn_cast_poisoned_svalue ())
- if (psval->get_poison_kind () == POISON_KIND_UNINIT)
+ if (psval->get_poison_kind () == poison_kind::uninit)
{
const binding_key *key = iter.first;
const concrete_binding *ckey
const svalue *sval = iter.second;
if (const poisoned_svalue *psval
= sval->dyn_cast_poisoned_svalue ())
- if (psval->get_poison_kind () == POISON_KIND_UNINIT)
+ if (psval->get_poison_kind () == poison_kind::uninit)
{
const binding_key *key = iter.first;
const concrete_binding *ckey
{
const poisoned_svalue *psval
= as_a <const poisoned_svalue *> (sval);
- return psval->get_poison_kind () == POISON_KIND_UNINIT;
+ return psval->get_poison_kind () == poison_kind::uninit;
}
case SK_COMPOUND:
{
const svalue *sval = iter.second;
if (const poisoned_svalue *psval
= sval->dyn_cast_poisoned_svalue ())
- if (psval->get_poison_kind () == POISON_KIND_UNINIT)
+ if (psval->get_poison_kind () == poison_kind::uninit)
return true;
}
const svalue *new_p_sval = model.get_rvalue (p, NULL);
ASSERT_EQ (new_p_sval->get_kind (), SK_POISONED);
ASSERT_EQ (new_p_sval->dyn_cast_poisoned_svalue ()->get_poison_kind (),
- POISON_KIND_POPPED_STACK);
+ poison_kind::popped_stack);
/* Verify that q still points to p, in spite of the region
renumbering. */
{
const poisoned_svalue *poisoned_sval1 = (const poisoned_svalue *)sval1;
const poisoned_svalue *poisoned_sval2 = (const poisoned_svalue *)sval2;
- return (poisoned_sval1->get_poison_kind ()
- - poisoned_sval2->get_poison_kind ());
+ return (static_cast<int> (poisoned_sval1->get_poison_kind ())
+ - static_cast<int> (poisoned_sval2->get_poison_kind ()));
}
break;
case SK_SETJMP:
{
default:
gcc_unreachable ();
- case POISON_KIND_UNINIT:
+ case poison_kind::uninit:
return "uninit";
- case POISON_KIND_FREED:
+ case poison_kind::freed:
return "freed";
- case POISON_KIND_DELETED:
+ case poison_kind::deleted:
return "deleted";
- case POISON_KIND_POPPED_STACK:
+ case poison_kind::popped_stack:
return "popped stack";
}
}
/* An enum describing a particular kind of "poisoned" value. */
-enum poison_kind
+enum class poison_kind
{
/* For use to describe uninitialized memory. */
- POISON_KIND_UNINIT,
+ uninit,
/* For use to describe freed memory. */
- POISON_KIND_FREED,
+ freed,
/* For use to describe deleted memory. */
- POISON_KIND_DELETED,
+ deleted,
/* For use on pointers to regions within popped stack frames. */
- POISON_KIND_POPPED_STACK
+ popped_stack
};
extern const char *poison_kind_to_str (enum poison_kind);
hashval_t hash () const
{
inchash::hash hstate;
- hstate.add_int (m_kind);
+ hstate.add_int (static_cast<int> (m_kind));
hstate.add_ptr (m_type);
return hstate.end ();
}
= old_ptr_sval->dyn_cast_region_svalue ())
{
const region *freed_reg = old_reg->get_pointee ();
- model->unbind_region_and_descendents (freed_reg, POISON_KIND_FREED);
+ model->unbind_region_and_descendents (freed_reg, poison_kind::freed);
model->unset_dynamic_extents (freed_reg);
}
model->mark_region_as_unknown (freed_reg, cd.get_uncertainty ());
}
- model->unbind_region_and_descendents (freed_reg, POISON_KIND_FREED);
+ model->unbind_region_and_descendents (freed_reg, poison_kind::freed);
model->unset_dynamic_extents (freed_reg);
}