int stack_index = pv.m_stack_depth;
const frame_region *frame = get_frame_at_index (stack_index);
gcc_assert (frame);
- return frame->get_region_for_local (m_mgr, expr);
+ return frame->get_region_for_local (m_mgr, expr, ctxt);
}
case COMPONENT_REF:
region_model::update_for_return_gcall (const gcall *call_stmt,
region_model_context *ctxt)
{
- /* Get the region for the result of the call, within the caller frame. */
- const region *result_dst_reg = NULL;
+ /* 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);
- if (lhs)
- {
- /* Normally we access the top-level frame, which is:
- path_var (expr, get_stack_depth () - 1)
- whereas here we need the caller frame, hence "- 2" here. */
- gcc_assert (get_stack_depth () >= 2);
- result_dst_reg = get_lvalue (path_var (lhs, get_stack_depth () - 2),
- ctxt);
- }
-
- pop_frame (result_dst_reg, NULL, ctxt);
+ pop_frame (lhs, NULL, ctxt);
}
/* Extract calling information from the superedge and update the model for the
/* Pop the topmost frame_region from this region_model's stack;
- If RESULT_DST_REG is non-null, copy any return value from the frame
- into RESULT_DST_REG's region.
+ If RESULT_LVALUE is non-null, copy any return value from the frame
+ into the corresponding region (evaluated with respect to the *caller*
+ frame, rather than the called frame).
If OUT_RESULT is non-null, copy any return value from the frame
into *OUT_RESULT.
POISON_KIND_POPPED_STACK svalues. */
void
-region_model::pop_frame (const region *result_dst_reg,
+region_model::pop_frame (tree result_lvalue,
const svalue **out_result,
region_model_context *ctxt)
{
const frame_region *frame_reg = m_current_frame;
tree fndecl = m_current_frame->get_function ()->decl;
tree result = DECL_RESULT (fndecl);
+ const svalue *retval = NULL;
if (result && TREE_TYPE (result) != void_type_node)
{
- const svalue *retval = get_rvalue (result, ctxt);
- if (result_dst_reg)
- set_value (result_dst_reg, retval, ctxt);
+ retval = get_rvalue (result, ctxt);
if (out_result)
*out_result = retval;
}
/* Pop the frame. */
m_current_frame = m_current_frame->get_calling_frame ();
+ if (result_lvalue && retval)
+ {
+ /* Compute result_dst_reg using RESULT_LVALUE *after* popping
+ the frame, but before poisoning pointers into the old frame. */
+ const region *result_dst_reg = get_lvalue (result_lvalue, ctxt);
+ set_value (result_dst_reg, retval, ctxt);
+ }
+
unbind_region_and_descendents (frame_reg,POISON_KIND_POPPED_STACK);
}
/* engine's ctor. */
-engine::engine (logger *logger)
-: m_mgr (logger)
+engine::engine (const supergraph *sg, logger *logger)
+: m_sg (sg), m_mgr (logger)
{
}
tree a = build_decl (UNKNOWN_LOCATION, PARM_DECL,
get_identifier ("a"),
integer_type_node);
+ DECL_CONTEXT (a) = parent_fndecl;
tree b = build_decl (UNKNOWN_LOCATION, PARM_DECL,
get_identifier ("b"),
integer_type_node);
+ DECL_CONTEXT (b) = parent_fndecl;
/* "x" and "y" in a child frame. */
tree x = build_decl (UNKNOWN_LOCATION, PARM_DECL,
get_identifier ("x"),
integer_type_node);
+ DECL_CONTEXT (x) = child_fndecl;
tree y = build_decl (UNKNOWN_LOCATION, PARM_DECL,
get_identifier ("y"),
integer_type_node);
+ DECL_CONTEXT (y) = child_fndecl;
/* "p" global. */
tree p = build_global_decl ("p", ptr_type_node);
tree n = build_decl (UNKNOWN_LOCATION, PARM_DECL,
get_identifier ("n"),
integer_type_node);
+ DECL_CONTEXT (n) = fndecl;
region_model_manager mgr;
test_region_model_context ctxt;
tree a = build_decl (UNKNOWN_LOCATION, PARM_DECL,
get_identifier ("a"),
integer_type_node);
+ DECL_CONTEXT (a) = test_fndecl;
tree addr_of_a = build1 (ADDR_EXPR, ptr_type_node, a);
/* Param "q", a pointer. */
tree q = build_decl (UNKNOWN_LOCATION, PARM_DECL,
get_identifier ("q"),
ptr_type_node);
+ DECL_CONTEXT (q) = test_fndecl;
program_point point (program_point::origin ());
region_model_manager mgr;
#include "analyzer/store.h"
#include "analyzer/region.h"
#include "analyzer/region-model.h"
+#include "analyzer/sm.h"
+#include "analyzer/program-state.h"
#if ENABLE_ANALYZER
const decl_region *
frame_region::get_region_for_local (region_model_manager *mgr,
- tree expr) const
+ tree expr,
+ const region_model_context *ctxt) const
{
- // TODO: could also check that VAR_DECLs are locals
- gcc_assert (TREE_CODE (expr) == PARM_DECL
- || TREE_CODE (expr) == VAR_DECL
- || TREE_CODE (expr) == SSA_NAME
- || TREE_CODE (expr) == RESULT_DECL);
+ if (CHECKING_P)
+ {
+ /* Verify that EXPR is a local or SSA name, and that it's for the
+ correct function for this stack frame. */
+ gcc_assert (TREE_CODE (expr) == PARM_DECL
+ || TREE_CODE (expr) == VAR_DECL
+ || TREE_CODE (expr) == SSA_NAME
+ || TREE_CODE (expr) == RESULT_DECL);
+ switch (TREE_CODE (expr))
+ {
+ default:
+ gcc_unreachable ();
+ case VAR_DECL:
+ gcc_assert (!is_global_var (expr));
+ /* Fall through. */
+ case PARM_DECL:
+ case RESULT_DECL:
+ gcc_assert (DECL_CONTEXT (expr) == m_fun->decl);
+ break;
+ case SSA_NAME:
+ {
+ if (tree var = SSA_NAME_VAR (expr))
+ {
+ if (DECL_P (var))
+ gcc_assert (DECL_CONTEXT (var) == m_fun->decl);
+ }
+ else if (ctxt)
+ if (const extrinsic_state *ext_state = ctxt->get_ext_state ())
+ if (const supergraph *sg
+ = ext_state->get_engine ()->get_supergraph ())
+ {
+ const gimple *def_stmt = SSA_NAME_DEF_STMT (expr);
+ const supernode *snode
+ = sg->get_supernode_for_stmt (def_stmt);
+ gcc_assert (snode->get_function () == m_fun);
+ }
+ }
+ break;
+ }
+ }
/* Ideally we'd use mutable here. */
map_t &mutable_locals = const_cast <map_t &> (m_locals);