From 5aebfb71763c7c8d0bb96adcd0a5f94de96a2a13 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Tue, 28 Jan 2020 10:06:24 -0800 Subject: [PATCH] analyzer: fix ICE when longjmp isn't marked 'noreturn' (PR 93316) Comments 11-16 within PR analyzer/93316 discuss an ICE in some setjmp tests seen on AIX and powerpc-darwin9. The issue turned out to be an implicit assumption that longjmp is marked "noreturn". There are two places in engine.cc where the code attempted to locate the longjmp GIMPLE_CALL by finding the final stmt within its supernode, in one place casting it via "as_a ", in the other using it as the location_t of the "rewinding from longjmp..." event. When longjmp isn't marked noreturn, its basic block and hence supernode can have additional stmts after the longjmp; in the setjmp-3.c case this was a GIMPLE_RETURN, leading to a ICE when casting this to a GIMPLE_CALL. This patch fixes the two places in question to use the rewind_info_t::get_longjmp_call member function introduced by 342e14ffa30e9163a1a75e0a4fb21b6883d58dbe, fixing the ICE (and ensuring the correct location_t is used for events). gcc/analyzer/ChangeLog: PR analyzer/93316 * engine.cc (rewind_info_t::update_model): Get the longjmp call stmt via get_longjmp_call () rather than assuming it is the last stmt in the longjmp's supernode. (rewind_info_t::add_events_to_path): Get the location_t for the rewind_from_longjmp_event via get_longjmp_call () rather than from the supernode's get_end_location (). --- gcc/analyzer/ChangeLog | 10 ++++++++++ gcc/analyzer/engine.cc | 12 ++---------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog index cea973d9a47..c665ac10e63 100644 --- a/gcc/analyzer/ChangeLog +++ b/gcc/analyzer/ChangeLog @@ -1,3 +1,13 @@ +2020-01-28 David Malcolm + + PR analyzer/93316 + * engine.cc (rewind_info_t::update_model): Get the longjmp call + stmt via get_longjmp_call () rather than assuming it is the last + stmt in the longjmp's supernode. + (rewind_info_t::add_events_to_path): Get the location_t for the + rewind_from_longjmp_event via get_longjmp_call () rather than from + the supernode's get_end_location (). + 2020-01-28 David Malcolm * region-model.cc (poisoned_value_diagnostic::emit): Update for diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index 2bc0aff6a6e..9acec704224 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -1333,21 +1333,13 @@ void rewind_info_t::update_model (region_model *model, const exploded_edge &eedge) { - const exploded_node &src_enode = *eedge.m_src; - const program_point &src_point = src_enode.get_point (); - - const gimple *last_stmt - = src_point.get_supernode ()->get_last_stmt (); - gcc_assert (last_stmt); - const gcall *longjmp_call = as_a (last_stmt); - const program_point &longjmp_point = eedge.m_src->get_point (); const program_point &setjmp_point = eedge.m_dest->get_point (); gcc_assert (longjmp_point.get_stack_depth () >= setjmp_point.get_stack_depth ()); - model->on_longjmp (longjmp_call, + model->on_longjmp (get_longjmp_call (), get_setjmp_call (), setjmp_point.get_stack_depth (), NULL); } @@ -1368,7 +1360,7 @@ rewind_info_t::add_events_to_path (checker_path *emission_path, emission_path->add_event (new rewind_from_longjmp_event - (&eedge, src_point.get_supernode ()->get_end_location (), + (&eedge, get_longjmp_call ()->location, src_point.get_fndecl (), src_stack_depth, this)); emission_path->add_event -- 2.30.2