From patchwork Thu Feb 29 23:18:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Malcolm X-Patchwork-Id: 208544 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2097:b0:108:e6aa:91d0 with SMTP id gs23csp738980dyb; Thu, 29 Feb 2024 15:19:11 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCVMJt9wz3jl/+SHySUkMGxhTL+ZvBQqiYc+dB+Zo+pwiyNvabGfxENAM4u9Oidvdp+BcimaRmOihRljc75Lk/f6ULPR2w== X-Google-Smtp-Source: AGHT+IGf3huk9k7ZvG/vnxI/DomEYOmrRxs8FdI+RaYLYud1FoscV5xXgVKjrprhkBor06Gu5cL8 X-Received: by 2002:a05:6214:1786:b0:690:521b:df12 with SMTP id ct6-20020a056214178600b00690521bdf12mr64599qvb.8.1709248751242; Thu, 29 Feb 2024 15:19:11 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1709248751; cv=pass; d=google.com; s=arc-20160816; b=wW7p4nu3vinLildthaomr6HNEKr24pf68+QBrCO8/TbtAeNSbyXeW07x1BXNKITIN1 tWQ4LyfyBgdkfoa/VdM8XwKN76adLDkTgYj8k6ojOCJujAYfhtOcbjQDGU7nA+924zMh kblINXKx3+VDq+TL4YpGtAuMSLUrK1AatwxKwYDLcOwb4qJ40YCuP+7/3C9maQplzVQs ZOrX1OtpazSHIgqdTO/z8V/qTUK69KNUNvNYpeWc/qqckmdU2jRhhqAiBgr6aJFNfkyw jPE92Kwrlz9CuApLI08QOymk9hWK0OZnVvoTfvc34WJfKqQWZ6F+6dPue8QoBjVrp61e Z7pA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:message-id:date:subject:cc:to:from:dkim-signature :arc-filter:dmarc-filter:delivered-to; bh=0Xz9H1oJjz5aaK9PpIgtan5gekt8jI6JBg6pRY7J3s0=; fh=NXemEfxTRbZtBxUkxR2ehQUaYlcDfMdzPkO8MChVQE4=; b=0wVABJDKwZW9m80JeUPRztJ8icPi5b1XhycRD4WIisx4SgLYxzB0c9ADf/UP9PcSOE 7aL/6ndmGy/nXB3hOuyxGmZU57mXm5DkS0Pzs4hd5Th39JWHNH1IhabmqPFerGrAkFzO ivPxMwGUKFVXv4DIjl6zorCYjuQyKyS6z5Nq6OQRuJgNd/1HVC2Q9FFH19+9Qym2AGAT WXYWGqKYoTHz0gwBiCi69JHiJNn2DdCAModT1Rotg/3PeaunzUpoaMmSHGfL3cAvxHA9 prUWiL/e3geoWG3ot419ltNDhGwrOvsz/5b3sUAf0iVrnSpyC2OSaZew0fCmMAeDdGuN M9aA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=bSTsg9Nu; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id iv9-20020ad45ce9000000b0068f74097af6si2441192qvb.82.2024.02.29.15.19.11 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 29 Feb 2024 15:19:11 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=bSTsg9Nu; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5CB5B3858C31 for ; Thu, 29 Feb 2024 23:19:10 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 541193858C5F for ; Thu, 29 Feb 2024 23:18:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 541193858C5F Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 541193858C5F Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1709248692; cv=none; b=hf+QUyylDXhjw8q+JS8vI0xUkzId3jlEBn4+YGqMTu0TuYZtqcqwfXGkUSoxDibXDYccwAMiqWh5Ko3nT2W5j9zyAK29FA9j+OivU9flEONu5M3yDT3XUGyZ8XScqdAUiJ2XTgQf+dHek6SF1NYOG7ra78ikjOo6uga9egimfgU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1709248692; c=relaxed/simple; bh=xeXPt+mEdUMSUqhRrcdDqOtFlXC2DvIZ7DemO3A9j6c=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=ZP26+24JXiBwEMOzUgcn+fh2W0e8dwMZoXXoGvHpoIRM7K8qIqp8T5Jm+qDsM63mNT2pdrDHRMyNOOIK4tPsQHf094b9kmRKXAV2cQygOT6mwEsW04hBOxA4exV9LsAXJcpJhFqUvnLwrGhRVje4ZcVJHZJl5pygDYkReT5jPPs= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1709248684; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=0Xz9H1oJjz5aaK9PpIgtan5gekt8jI6JBg6pRY7J3s0=; b=bSTsg9NuQ7fwgLnT3kp0aK/NB75fKoUiU2trUoh2Su6YtpOvpmDuvXTlTyvBCou7BpmKOp 5nL7X+F4vMIZVgrC7jWXt1/P/lFoKTCNUUyXJ88dM6ArVmJU79fGY9PIFQPegXTgRAPyOM nhf4venwN/YtQjlcWKipmfyad2VbsqA= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-589-aLQl6dEDOjONLdnCBv79fA-1; Thu, 29 Feb 2024 18:18:02 -0500 X-MC-Unique: aLQl6dEDOjONLdnCBv79fA-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id C8D51862DC1 for ; Thu, 29 Feb 2024 23:18:01 +0000 (UTC) Received: from t14s.localdomain.com (unknown [10.22.9.138]) by smtp.corp.redhat.com (Postfix) with ESMTP id 85C324D906; Thu, 29 Feb 2024 23:18:01 +0000 (UTC) From: David Malcolm To: gcc-patches@gcc.gnu.org Cc: David Malcolm Subject: [pushed] analyzer: fix ICE in call summarization [PR114159] Date: Thu, 29 Feb 2024 18:18:00 -0500 Message-Id: <20240229231800.3643660-1-dmalcolm@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.5 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP, T_FILL_THIS_FORM_SHORT, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1792277218637208885 X-GMAIL-MSGID: 1792277218637208885 PR analyzer/114159 reports an ICE inside playback of call summaries for very low values of --param=analyzer-max-svalue-depth=VAL. Root cause is that call_summary_edge_info's ctor tries to evaluate the function ptr of a gimple call stmt and assumes it gets a function *, but with low values of --param=analyzer-max-svalue-depth=VAL we get back an UNKNOWN svalue, rather than a pointer to a specific function. Fix by adding a new call_info ctor that passes a specific const function & from the call_summary_edge_info, rather than trying to compute the function. In doing so, I noticed that the analyzer was using "function *" despite not modifying functions, and was sloppy about can-be-null versus must-be-non-null function pointers, so I "constified" the function, and converted the many places where the function must be non-null to be "const function &". Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. Successful run of analyzer integration tests on x86_64-pc-linux-gnu. Pushed to trunk as r14-9245-gc0d8a64e72324d. gcc/analyzer/ChangeLog: PR analyzer/114159 * analyzer.cc: Include "tree-dfa.h". (get_ssa_default_def): New decl. * analyzer.h (get_ssa_default_def): New. * call-info.cc (call_info::call_info): New ctor taking an explicit called_fn. * call-info.h (call_info::call_info): Likewise. * call-summary.cc (call_summary_replay::call_summary_replay): Convert param from function * to const function &. * call-summary.h (call_summary_replay::call_summary_replay): Likewise. * checker-event.h (state_change_event::get_dest_function): Constify return value. * engine.cc (point_and_state::validate): Update for conversion to const function &. (exploded_node::on_stmt): Likewise. (call_summary_edge_info::call_summary_edge_info): Likewise. Pass in called_fn to call_info ctor. (exploded_node::replay_call_summaries): Update for conversion to const function &. Convert per_function_data from * to &. (exploded_node::replay_call_summary): Update for conversion to const function &. (exploded_graph::add_function_entry): Likewise. (toplevel_function_p): Likewise. (add_tainted_args_callback): Likewise. (exploded_graph::build_initial_worklist): Likewise. (exploded_graph::maybe_create_dynamic_call): Likewise. (maybe_update_for_edge): Likewise. (exploded_graph::on_escaped_function): Likewise. * exploded-graph.h (exploded_node::replay_call_summaries): Likewise. (exploded_node::replay_call_summary): Likewise. (exploded_graph::add_function_entry): Likewise. * program-point.cc (function_point::from_function_entry): Likewise. (program_point::from_function_entry): Likewise. * program-point.h (function_point::from_function_entry): Likewise. (program_point::from_function_entry): Likewise. * program-state.cc (program_state::push_frame): Likewise. (program_state::get_current_function): Constify return type. * program-state.h (program_state::push_frame): Update for conversion to const function &. (program_state::get_current_function): Likewise. * region-model-manager.cc (region_model_manager::get_frame_region): Likewise. * region-model-manager.h (region_model_manager::get_frame_region): Likewise. * region-model.cc (region_model::called_from_main_p): Likewise. (region_model::update_for_gcall): Likewise. (region_model::push_frame): Likewise. (region_model::get_current_function): Constify return type. (region_model::pop_frame): Update for conversion to const function &. (selftest::test_stack_frames): Likewise. (selftest::test_get_representative_path_var): Likewise. (selftest::test_state_merging): Likewise. (selftest::test_alloca): Likewise. * region-model.h (region_model::push_frame): Likewise. (region_model::get_current_function): Likewise. * region.cc (frame_region::dump_to_pp): Likewise. (frame_region::get_region_for_local): Likewise. * region.h (class frame_region): Likewise. * sm-signal.cc (signal_unsafe_call::describe_state_change): Likewise. (update_model_for_signal_handler): Likewise. (signal_delivery_edge_info_t::update_model): Likewise. (register_signal_handler::impl_transition): Likewise. * state-purge.cc (class gimple_op_visitor): Likewise. (state_purge_map::state_purge_map): Likewise. (state_purge_map::get_or_create_data_for_decl): Likewise. (state_purge_per_ssa_name::state_purge_per_ssa_name): Likewise. (state_purge_per_ssa_name::add_to_worklist): Likewise. (state_purge_per_ssa_name::process_point): Likewise. (state_purge_per_decl::add_to_worklist): Likewise. (state_purge_annotator::print_needed): Likewise. * state-purge.h (state_purge_map::get_or_create_data_for_decl): Likewise. (class state_purge_per_tree): Likewise. (class state_purge_per_ssa_name): Likewise. (class state_purge_per_decl): Likewise. * supergraph.cc (supergraph::dump_dot_to_pp): Likewise. * supergraph.h (supergraph::get_node_for_function_entry): Likewise. (supergraph::get_node_for_function_exit): Likewise. gcc/ChangeLog: PR analyzer/114159 * function.cc (function_name): Make param const. * function.h (function_name): Likewise. gcc/testsuite/ChangeLog: PR analyzer/114159 * c-c++-common/analyzer/call-summaries-pr114159.c: New test. Signed-off-by: David Malcolm --- gcc/analyzer/analyzer.cc | 9 ++ gcc/analyzer/analyzer.h | 3 + gcc/analyzer/call-info.cc | 8 ++ gcc/analyzer/call-info.h | 1 + gcc/analyzer/call-summary.cc | 6 +- gcc/analyzer/call-summary.h | 2 +- gcc/analyzer/checker-event.h | 2 +- gcc/analyzer/engine.cc | 83 ++++++++++--------- gcc/analyzer/exploded-graph.h | 8 +- gcc/analyzer/program-point.cc | 4 +- gcc/analyzer/program-point.h | 4 +- gcc/analyzer/program-state.cc | 4 +- gcc/analyzer/program-state.h | 4 +- gcc/analyzer/region-model-manager.cc | 2 +- gcc/analyzer/region-model-manager.h | 2 +- gcc/analyzer/region-model.cc | 42 +++++----- gcc/analyzer/region-model.h | 4 +- gcc/analyzer/region.cc | 10 +-- gcc/analyzer/region.h | 18 ++-- gcc/analyzer/sm-signal.cc | 13 +-- gcc/analyzer/state-purge.cc | 29 ++++--- gcc/analyzer/state-purge.h | 15 ++-- gcc/analyzer/supergraph.cc | 5 +- gcc/analyzer/supergraph.h | 8 +- gcc/function.cc | 2 +- gcc/function.h | 2 +- .../analyzer/call-summaries-pr114159.c | 20 +++++ 27 files changed, 181 insertions(+), 129 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/analyzer/call-summaries-pr114159.c diff --git a/gcc/analyzer/analyzer.cc b/gcc/analyzer/analyzer.cc index 389496cd57ab..7f5d3d56d338 100644 --- a/gcc/analyzer/analyzer.cc +++ b/gcc/analyzer/analyzer.cc @@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/analyzer.h" #include "tree-pretty-print.h" #include "diagnostic-event-id.h" +#include "tree-dfa.h" #if ENABLE_ANALYZER @@ -275,6 +276,14 @@ byte_offset_to_json (const byte_offset_t &offset) return new json::string (pp_formatted_text (&pp)); } +/* Workaround for lack of const-correctness of ssa_default_def. */ + +tree +get_ssa_default_def (const function &fun, tree var) +{ + return ssa_default_def (const_cast (&fun), var); +} + } // namespace ana /* Helper function for checkers. Is the CALL to the given function name, diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h index 20a8e3f9a1d0..1d792ed23ec7 100644 --- a/gcc/analyzer/analyzer.h +++ b/gcc/analyzer/analyzer.h @@ -433,6 +433,9 @@ compare_constants (tree lhs_const, enum tree_code op, tree rhs_const); extern tree get_string_cst_size (const_tree string_cst); +extern tree +get_ssa_default_def (const function &fun, tree var); + } // namespace ana extern bool is_special_named_call_p (const gcall *call, const char *funcname, diff --git a/gcc/analyzer/call-info.cc b/gcc/analyzer/call-info.cc index 7ec82124d523..4c965b2136c0 100644 --- a/gcc/analyzer/call-info.cc +++ b/gcc/analyzer/call-info.cc @@ -143,6 +143,14 @@ call_info::call_info (const call_details &cd) gcc_assert (m_fndecl); } +call_info::call_info (const call_details &cd, + const function &called_fn) +: m_call_stmt (cd.get_call_stmt ()), + m_fndecl (called_fn.decl) +{ + gcc_assert (m_fndecl); +} + /* class succeed_or_fail_call_info : public call_info. */ label_text diff --git a/gcc/analyzer/call-info.h b/gcc/analyzer/call-info.h index 9815b4141c34..17d5fdfec735 100644 --- a/gcc/analyzer/call-info.h +++ b/gcc/analyzer/call-info.h @@ -44,6 +44,7 @@ public: protected: call_info (const call_details &cd); + call_info (const call_details &cd, const function &called_fn); private: const gcall *m_call_stmt; diff --git a/gcc/analyzer/call-summary.cc b/gcc/analyzer/call-summary.cc index ecb6fb13c9ec..8b8567a15280 100644 --- a/gcc/analyzer/call-summary.cc +++ b/gcc/analyzer/call-summary.cc @@ -167,7 +167,7 @@ call_summary::dump (const extrinsic_state &ext_state, bool simple) const arguments at the caller. */ call_summary_replay::call_summary_replay (const call_details &cd, - function *called_fn, + const function &called_fn, call_summary *summary, const extrinsic_state &ext_state) : m_cd (cd), @@ -177,7 +177,7 @@ call_summary_replay::call_summary_replay (const call_details &cd, region_model_manager *mgr = cd.get_manager (); // populate params based on args - tree fndecl = called_fn->decl; + tree fndecl = called_fn.decl; /* Get a frame_region for use with respect to the summary. This will be a top-level frame, since that's what's in @@ -196,7 +196,7 @@ call_summary_replay::call_summary_replay (const call_details &cd, break; const svalue *caller_arg_sval = cd.get_arg_svalue (idx); tree parm_lval = iter_parm; - if (tree parm_default_ssa = ssa_default_def (called_fn, iter_parm)) + if (tree parm_default_ssa = get_ssa_default_def (called_fn, iter_parm)) parm_lval = parm_default_ssa; const region *summary_parm_reg = summary_frame->get_region_for_local (mgr, parm_lval, cd.get_ctxt ()); diff --git a/gcc/analyzer/call-summary.h b/gcc/analyzer/call-summary.h index 73f21ac72826..220dd0831846 100644 --- a/gcc/analyzer/call-summary.h +++ b/gcc/analyzer/call-summary.h @@ -68,7 +68,7 @@ class call_summary_replay { public: call_summary_replay (const call_details &cd, - function *called_fn, + const function &called_fn, call_summary *m_summary, const extrinsic_state &ext_state); diff --git a/gcc/analyzer/checker-event.h b/gcc/analyzer/checker-event.h index 7d8915c8e530..d2fb87fb523f 100644 --- a/gcc/analyzer/checker-event.h +++ b/gcc/analyzer/checker-event.h @@ -370,7 +370,7 @@ public: label_text get_desc (bool can_colorize) const final override; meaning get_meaning () const override; - function *get_dest_function () const + const function *get_dest_function () const { return m_dst_state.get_current_function (); } diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index 44ff20cf9af7..ad310b4d8731 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -1072,7 +1072,7 @@ point_and_state::validate (const extrinsic_state &ext_state) const { int index = iter_frame->get_index (); gcc_assert (m_point.get_function_at_depth (index) - == iter_frame->get_function ()); + == &iter_frame->get_function ()); } } @@ -1496,14 +1496,17 @@ exploded_node::on_stmt (exploded_graph &eg, per_function_data *called_fn_data = eg.get_per_function_data (called_fn); if (called_fn_data) - return replay_call_summaries (eg, - snode, - as_a (stmt), - state, - path_ctxt, - called_fn, - called_fn_data, - &ctxt); + { + gcc_assert (called_fn); + return replay_call_summaries (eg, + snode, + as_a (stmt), + state, + path_ctxt, + *called_fn, + *called_fn_data, + &ctxt); + } } bool unknown_side_effects = false; @@ -1610,10 +1613,10 @@ class call_summary_edge_info : public call_info { public: call_summary_edge_info (const call_details &cd, - function *called_fn, + const function &called_fn, call_summary *summary, const extrinsic_state &ext_state) - : call_info (cd), + : call_info (cd, called_fn), m_called_fn (called_fn), m_summary (summary), m_ext_state (ext_state) @@ -1648,7 +1651,7 @@ public: } private: - function *m_called_fn; + const function &m_called_fn; call_summary *m_summary; const extrinsic_state &m_ext_state; }; @@ -1662,18 +1665,15 @@ exploded_node::replay_call_summaries (exploded_graph &eg, const gcall *call_stmt, program_state *state, path_context *path_ctxt, - function *called_fn, - per_function_data *called_fn_data, + const function &called_fn, + per_function_data &called_fn_data, region_model_context *ctxt) { logger *logger = eg.get_logger (); LOG_SCOPE (logger); - gcc_assert (called_fn); - gcc_assert (called_fn_data); - /* Each summary will call bifurcate on the PATH_CTXT. */ - for (auto summary : called_fn_data->m_summaries) + for (auto summary : called_fn_data.m_summaries) replay_call_summary (eg, snode, call_stmt, state, path_ctxt, called_fn, summary, ctxt); path_ctxt->terminate_path (); @@ -1691,7 +1691,7 @@ exploded_node::replay_call_summary (exploded_graph &eg, const gcall *call_stmt, program_state *old_state, path_context *path_ctxt, - function *called_fn, + const function &called_fn, call_summary *summary, region_model_context *ctxt) { @@ -1700,13 +1700,12 @@ exploded_node::replay_call_summary (exploded_graph &eg, gcc_assert (snode); gcc_assert (call_stmt); gcc_assert (old_state); - gcc_assert (called_fn); gcc_assert (summary); if (logger) logger->log ("using %s as summary for call to %qE from %qE", summary->get_desc ().get (), - called_fn->decl, + called_fn.decl, snode->get_function ()->decl); const extrinsic_state &ext_state = eg.get_ext_state (); const program_state &summary_end_state = summary->get_state (); @@ -2784,16 +2783,17 @@ private: Return the exploded_node for the entrypoint to the function. */ exploded_node * -exploded_graph::add_function_entry (function *fun) +exploded_graph::add_function_entry (const function &fun) { - gcc_assert (gimple_has_body_p (fun->decl)); + gcc_assert (gimple_has_body_p (fun.decl)); /* Be idempotent. */ - if (m_functions_with_enodes.contains (fun)) + function *key = const_cast (&fun); + if (m_functions_with_enodes.contains (key)) { logger * const logger = get_logger (); if (logger) - logger->log ("entrypoint for %qE already exists", fun->decl); + logger->log ("entrypoint for %qE already exists", fun.decl); return NULL; } @@ -2805,10 +2805,10 @@ exploded_graph::add_function_entry (function *fun) std::unique_ptr edge_info = NULL; - if (lookup_attribute ("tainted_args", DECL_ATTRIBUTES (fun->decl))) + if (lookup_attribute ("tainted_args", DECL_ATTRIBUTES (fun.decl))) { - if (mark_params_as_tainted (&state, fun->decl, m_ext_state)) - edge_info = make_unique (fun->decl); + if (mark_params_as_tainted (&state, fun.decl, m_ext_state)) + edge_info = make_unique (fun.decl); } if (!state.m_valid) @@ -2820,7 +2820,7 @@ exploded_graph::add_function_entry (function *fun) add_edge (m_origin, enode, NULL, false, std::move (edge_info)); - m_functions_with_enodes.add (fun); + m_functions_with_enodes.add (key); return enode; } @@ -3108,7 +3108,7 @@ exploded_graph::get_per_function_data (function *fun) const called via other functions. */ static bool -toplevel_function_p (function *fun, logger *logger) +toplevel_function_p (const function &fun, logger *logger) { /* Don't directly traverse into functions that have an "__analyzer_" prefix. Doing so is useful for the analyzer test suite, allowing @@ -3119,17 +3119,17 @@ toplevel_function_p (function *fun, logger *logger) excess messages from the case of the first function being traversed directly. */ #define ANALYZER_PREFIX "__analyzer_" - if (!strncmp (IDENTIFIER_POINTER (DECL_NAME (fun->decl)), ANALYZER_PREFIX, + if (!strncmp (IDENTIFIER_POINTER (DECL_NAME (fun.decl)), ANALYZER_PREFIX, strlen (ANALYZER_PREFIX))) { if (logger) logger->log ("not traversing %qE (starts with %qs)", - fun->decl, ANALYZER_PREFIX); + fun.decl, ANALYZER_PREFIX); return false; } if (logger) - logger->log ("traversing %qE (all checks passed)", fun->decl); + logger->log ("traversing %qE (all checks passed)", fun.decl); return true; } @@ -3254,9 +3254,9 @@ add_tainted_args_callback (exploded_graph *eg, tree field, tree fndecl, program_point point = program_point::from_function_entry (*ext_state.get_model_manager (), - eg->get_supergraph (), fun); + eg->get_supergraph (), *fun); program_state state (ext_state); - state.push_frame (ext_state, fun); + state.push_frame (ext_state, *fun); if (!mark_params_as_tainted (&state, fndecl, ext_state)) return; @@ -3330,9 +3330,10 @@ exploded_graph::build_initial_worklist () FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) { function *fun = node->get_fun (); - if (!toplevel_function_p (fun, logger)) + gcc_assert (fun); + if (!toplevel_function_p (*fun, logger)) continue; - exploded_node *enode = add_function_entry (fun); + exploded_node *enode = add_function_entry (*fun); if (logger) { if (enode) @@ -3838,8 +3839,8 @@ exploded_graph::maybe_create_dynamic_call (const gcall *call, if (fun) { const supergraph &sg = this->get_supergraph (); - supernode *sn_entry = sg.get_node_for_function_entry (fun); - supernode *sn_exit = sg.get_node_for_function_exit (fun); + supernode *sn_entry = sg.get_node_for_function_entry (*fun); + supernode *sn_exit = sg.get_node_for_function_exit (*fun); program_point new_point = program_point::before_supernode (sn_entry, @@ -4962,7 +4963,7 @@ maybe_update_for_edge (logger *logger, == PK_BEFORE_SUPERNODE); function *fun = eedge->m_dest->get_function (); gcc_assert (fun); - m_model.push_frame (fun, NULL, ctxt); + m_model.push_frame (*fun, NULL, ctxt); if (logger) logger->log (" pushing frame for %qD", fun->decl); } @@ -5582,7 +5583,7 @@ exploded_graph::on_escaped_function (tree fndecl) if (!gimple_has_body_p (fndecl)) return; - exploded_node *enode = add_function_entry (fun); + exploded_node *enode = add_function_entry (*fun); if (logger) { if (enode) diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h index 387ae3a3aea0..642d69bbcc0a 100644 --- a/gcc/analyzer/exploded-graph.h +++ b/gcc/analyzer/exploded-graph.h @@ -285,15 +285,15 @@ class exploded_node : public dnode const gcall *call_stmt, program_state *state, path_context *path_ctxt, - function *called_fn, - per_function_data *called_fn_data, + const function &called_fn, + per_function_data &called_fn_data, region_model_context *ctxt); void replay_call_summary (exploded_graph &eg, const supernode *snode, const gcall *call_stmt, program_state *state, path_context *path_ctxt, - function *called_fn, + const function &called_fn, call_summary *summary, region_model_context *ctxt); @@ -810,7 +810,7 @@ public: exploded_node *get_origin () const { return m_origin; } - exploded_node *add_function_entry (function *fun); + exploded_node *add_function_entry (const function &fun); void build_initial_worklist (); void process_worklist (); diff --git a/gcc/analyzer/program-point.cc b/gcc/analyzer/program-point.cc index 5e98b5234dcc..6e225cfe7254 100644 --- a/gcc/analyzer/program-point.cc +++ b/gcc/analyzer/program-point.cc @@ -230,7 +230,7 @@ function_point::final_stmt_p () const /* Create a function_point representing the entrypoint of function FUN. */ function_point -function_point::from_function_entry (const supergraph &sg, function *fun) +function_point::from_function_entry (const supergraph &sg, const function &fun) { return before_supernode (sg.get_node_for_function_entry (fun), NULL); } @@ -698,7 +698,7 @@ program_point::origin (const region_model_manager &mgr) program_point program_point::from_function_entry (const region_model_manager &mgr, const supergraph &sg, - function *fun) + const function &fun) { return program_point (function_point::from_function_entry (sg, fun), mgr.get_empty_call_string ()); diff --git a/gcc/analyzer/program-point.h b/gcc/analyzer/program-point.h index 62c2c946412d..61b895f4499b 100644 --- a/gcc/analyzer/program-point.h +++ b/gcc/analyzer/program-point.h @@ -112,7 +112,7 @@ public: /* Factory functions for making various kinds of program_point. */ static function_point from_function_entry (const supergraph &sg, - function *fun); + const function &fun); static function_point before_supernode (const supernode *supernode, const superedge *from_edge); @@ -252,7 +252,7 @@ public: static program_point origin (const region_model_manager &mgr); static program_point from_function_entry (const region_model_manager &mgr, const supergraph &sg, - function *fun); + const function &fun); static program_point before_supernode (const supernode *supernode, const superedge *from_edge, diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc index 55dd6ca71667..c88652baf5ca 100644 --- a/gcc/analyzer/program-state.cc +++ b/gcc/analyzer/program-state.cc @@ -1143,14 +1143,14 @@ program_state::to_json (const extrinsic_state &ext_state) const void program_state::push_frame (const extrinsic_state &ext_state ATTRIBUTE_UNUSED, - function *fun) + const function &fun) { m_region_model->push_frame (fun, NULL, NULL); } /* Get the current function of this state. */ -function * +const function * program_state::get_current_function () const { return m_region_model->get_current_function (); diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h index 69bf931f070c..3ba6a931cd6f 100644 --- a/gcc/analyzer/program-state.h +++ b/gcc/analyzer/program-state.h @@ -226,8 +226,8 @@ public: json::object *to_json (const extrinsic_state &ext_state) const; - void push_frame (const extrinsic_state &ext_state, function *fun); - function * get_current_function () const; + void push_frame (const extrinsic_state &ext_state, const function &fun); + const function * get_current_function () const; void push_call (exploded_graph &eg, exploded_node *enode, diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc index 93e72ec45a85..8530f49e74ab 100644 --- a/gcc/analyzer/region-model-manager.cc +++ b/gcc/analyzer/region-model-manager.cc @@ -1676,7 +1676,7 @@ region_model_manager::get_cast_region (const region *original_region, const frame_region * region_model_manager::get_frame_region (const frame_region *calling_frame, - function *fun) + const function &fun) { int index = calling_frame ? calling_frame->get_index () + 1 : 0; diff --git a/gcc/analyzer/region-model-manager.h b/gcc/analyzer/region-model-manager.h index 5c89de1f7c13..7d1208c70a70 100644 --- a/gcc/analyzer/region-model-manager.h +++ b/gcc/analyzer/region-model-manager.h @@ -131,7 +131,7 @@ public: const region *get_cast_region (const region *original_region, tree type); const frame_region *get_frame_region (const frame_region *calling_frame, - function *fun); + const function &fun); const region *get_symbolic_region (const svalue *sval); const string_region *get_region_for_string (tree string_cst); const region *get_bit_range (const region *parent, tree type, diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index 6ab917465d6f..33a4584841e4 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -2619,7 +2619,7 @@ region_model::called_from_main_p () const /* Determine if the oldest stack frame in this model is for "main". */ const frame_region *frame0 = get_frame_at_index (0); gcc_assert (frame0); - return id_equal (DECL_NAME (frame0->get_function ()->decl), "main"); + return id_equal (DECL_NAME (frame0->get_function ().decl), "main"); } /* Subroutine of region_model::get_store_value for when REG is (or is within) @@ -5552,7 +5552,8 @@ region_model::update_for_gcall (const gcall *call_stmt, callee = DECL_STRUCT_FUNCTION (fn_decl); } - push_frame (callee, &arg_svals, ctxt); + gcc_assert (callee); + push_frame (*callee, &arg_svals, ctxt); } /* Pop the top-most frame_region from the stack, and copy the return @@ -5896,14 +5897,15 @@ region_model::on_top_level_param (tree param, Return the frame_region for the new frame. */ const region * -region_model::push_frame (function *fun, const vec *arg_svals, +region_model::push_frame (const function &fun, + const vec *arg_svals, region_model_context *ctxt) { m_current_frame = m_mgr->get_frame_region (m_current_frame, fun); if (arg_svals) { /* Arguments supplied from a caller frame. */ - tree fndecl = fun->decl; + tree fndecl = fun.decl; unsigned idx = 0; for (tree iter_parm = DECL_ARGUMENTS (fndecl); iter_parm; iter_parm = DECL_CHAIN (iter_parm), ++idx) @@ -5914,7 +5916,7 @@ region_model::push_frame (function *fun, const vec *arg_svals, if (idx >= arg_svals->length ()) break; tree parm_lval = iter_parm; - if (tree parm_default_ssa = ssa_default_def (fun, iter_parm)) + if (tree parm_default_ssa = get_ssa_default_def (fun, iter_parm)) parm_lval = parm_default_ssa; const region *parm_reg = get_lvalue (parm_lval, ctxt); const svalue *arg_sval = (*arg_svals)[idx]; @@ -5937,7 +5939,7 @@ region_model::push_frame (function *fun, const vec *arg_svals, /* Otherwise we have a top-level call within the analysis. The params have defined but unknown initial values. Anything they point to has escaped. */ - tree fndecl = fun->decl; + tree fndecl = fun.decl; /* Handle "__attribute__((nonnull))". */ tree fntype = TREE_TYPE (fndecl); @@ -5951,7 +5953,7 @@ region_model::push_frame (function *fun, const vec *arg_svals, ? (bitmap_empty_p (nonnull_args) || bitmap_bit_p (nonnull_args, parm_idx)) : false); - if (tree parm_default_ssa = ssa_default_def (fun, iter_parm)) + if (tree parm_default_ssa = get_ssa_default_def (fun, iter_parm)) on_top_level_param (parm_default_ssa, non_null, ctxt); else on_top_level_param (iter_parm, non_null, ctxt); @@ -5967,12 +5969,12 @@ region_model::push_frame (function *fun, const vec *arg_svals, /* Get the function of the top-most frame in this region_model's stack. There must be such a frame. */ -function * +const function * region_model::get_current_function () const { const frame_region *frame = get_current_frame (); gcc_assert (frame); - return frame->get_function (); + return &frame->get_function (); } /* Pop the topmost frame_region from this region_model's stack; @@ -6007,7 +6009,7 @@ region_model::pop_frame (tree result_lvalue, ctxt->on_pop_frame (frame_reg); /* Evaluate the result, within the callee frame. */ - tree fndecl = m_current_frame->get_function ()->decl; + tree fndecl = m_current_frame->get_function ().decl; tree result = DECL_RESULT (fndecl); const svalue *retval = NULL; if (result @@ -7966,7 +7968,7 @@ test_stack_frames () /* Push stack frame for "parent_fn". */ const region *parent_frame_reg - = model.push_frame (DECL_STRUCT_FUNCTION (parent_fndecl), + = model.push_frame (*DECL_STRUCT_FUNCTION (parent_fndecl), NULL, &ctxt); ASSERT_EQ (model.get_current_frame (), parent_frame_reg); ASSERT_TRUE (model.region_exists_p (parent_frame_reg)); @@ -7982,7 +7984,7 @@ test_stack_frames () /* Push stack frame for "child_fn". */ const region *child_frame_reg - = model.push_frame (DECL_STRUCT_FUNCTION (child_fndecl), NULL, &ctxt); + = model.push_frame (*DECL_STRUCT_FUNCTION (child_fndecl), NULL, &ctxt); ASSERT_EQ (model.get_current_frame (), child_frame_reg); ASSERT_TRUE (model.region_exists_p (child_frame_reg)); const region *x_in_child_reg = model.get_lvalue (x, &ctxt); @@ -8075,7 +8077,7 @@ test_get_representative_path_var () for (int depth = 0; depth < 5; depth++) { const region *frame_n_reg - = model.push_frame (DECL_STRUCT_FUNCTION (fndecl), NULL, &ctxt); + = model.push_frame (*DECL_STRUCT_FUNCTION (fndecl), NULL, &ctxt); const region *parm_n_reg = model.get_lvalue (path_var (n, depth), &ctxt); parm_regs.safe_push (parm_n_reg); @@ -8319,9 +8321,9 @@ test_state_merging () region_model model0 (&mgr); region_model model1 (&mgr); ASSERT_EQ (model0.get_stack_depth (), 0); - model0.push_frame (DECL_STRUCT_FUNCTION (test_fndecl), NULL, &ctxt); + model0.push_frame (*DECL_STRUCT_FUNCTION (test_fndecl), NULL, &ctxt); ASSERT_EQ (model0.get_stack_depth (), 1); - model1.push_frame (DECL_STRUCT_FUNCTION (test_fndecl), NULL, &ctxt); + model1.push_frame (*DECL_STRUCT_FUNCTION (test_fndecl), NULL, &ctxt); placeholder_svalue test_sval (mgr.alloc_symbol_id (), integer_type_node, "test sval"); @@ -8413,7 +8415,7 @@ test_state_merging () /* Pointers: non-NULL and non-NULL: ptr to a local. */ { region_model model0 (&mgr); - model0.push_frame (DECL_STRUCT_FUNCTION (test_fndecl), NULL, NULL); + model0.push_frame (*DECL_STRUCT_FUNCTION (test_fndecl), NULL, NULL); model0.set_value (model0.get_lvalue (p, NULL), model0.get_rvalue (addr_of_a, NULL), NULL); @@ -8552,12 +8554,12 @@ test_state_merging () frame points to a local in a more recent stack frame. */ { region_model model0 (&mgr); - model0.push_frame (DECL_STRUCT_FUNCTION (test_fndecl), NULL, NULL); + model0.push_frame (*DECL_STRUCT_FUNCTION (test_fndecl), NULL, NULL); const region *q_in_first_frame = model0.get_lvalue (q, NULL); /* Push a second frame. */ const region *reg_2nd_frame - = model0.push_frame (DECL_STRUCT_FUNCTION (test_fndecl), NULL, NULL); + = model0.push_frame (*DECL_STRUCT_FUNCTION (test_fndecl), NULL, NULL); /* Have a pointer in the older frame point to a local in the more recent frame. */ @@ -8584,7 +8586,7 @@ test_state_merging () /* Verify that we can merge a model in which a local points to a global. */ { region_model model0 (&mgr); - model0.push_frame (DECL_STRUCT_FUNCTION (test_fndecl), NULL, NULL); + model0.push_frame (*DECL_STRUCT_FUNCTION (test_fndecl), NULL, NULL); model0.set_value (model0.get_lvalue (q, NULL), model0.get_rvalue (addr_of_y, NULL), NULL); @@ -9110,7 +9112,7 @@ test_alloca () /* Push stack frame. */ const region *frame_reg - = model.push_frame (DECL_STRUCT_FUNCTION (fndecl), + = model.push_frame (*DECL_STRUCT_FUNCTION (fndecl), NULL, &ctxt); /* "p = alloca (n * 4);". */ const svalue *size_sval = model.get_rvalue (n_times_4, &ctxt); diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h index d4ef10120dd5..118e0f254273 100644 --- a/gcc/analyzer/region-model.h +++ b/gcc/analyzer/region-model.h @@ -347,10 +347,10 @@ class region_model void update_for_return_gcall (const gcall *call_stmt, region_model_context *ctxt); - const region *push_frame (function *fun, const vec *arg_sids, + const region *push_frame (const function &fun, const vec *arg_sids, region_model_context *ctxt); const frame_region *get_current_frame () const { return m_current_frame; } - function * get_current_function () const; + const function *get_current_function () const; void pop_frame (tree result_lvalue, const svalue **out_result, region_model_context *ctxt, diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc index 50821a592302..d45706141fb0 100644 --- a/gcc/analyzer/region.cc +++ b/gcc/analyzer/region.cc @@ -1306,10 +1306,10 @@ void frame_region::dump_to_pp (pretty_printer *pp, bool simple) const { if (simple) - pp_printf (pp, "frame: %qs@%i", function_name (m_fun), get_stack_depth ()); + pp_printf (pp, "frame: %qs@%i", function_name (&m_fun), get_stack_depth ()); else pp_printf (pp, "frame_region(%qs, index: %i, depth: %i)", - function_name (m_fun), m_index, get_stack_depth ()); + function_name (&m_fun), m_index, get_stack_depth ()); } const decl_region * @@ -1334,14 +1334,14 @@ frame_region::get_region_for_local (region_model_manager *mgr, /* Fall through. */ case PARM_DECL: case RESULT_DECL: - gcc_assert (DECL_CONTEXT (expr) == m_fun->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); + gcc_assert (DECL_CONTEXT (var) == m_fun.decl); } else if (ctxt) if (const extrinsic_state *ext_state = ctxt->get_ext_state ()) @@ -1351,7 +1351,7 @@ frame_region::get_region_for_local (region_model_manager *mgr, 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); + gcc_assert (snode->get_function () == &m_fun); } } break; diff --git a/gcc/analyzer/region.h b/gcc/analyzer/region.h index 70557babbc04..73f35f55ba71 100644 --- a/gcc/analyzer/region.h +++ b/gcc/analyzer/region.h @@ -305,11 +305,10 @@ public: /* A support class for uniquifying instances of frame_region. */ struct key_t { - key_t (const frame_region *calling_frame, function *fun) - : m_calling_frame (calling_frame), m_fun (fun) + key_t (const frame_region *calling_frame, const function &fun) + : m_calling_frame (calling_frame), m_fun (&fun) { /* calling_frame can be NULL. */ - gcc_assert (fun); } hashval_t hash () const @@ -322,7 +321,8 @@ public: bool operator== (const key_t &other) const { - return (m_calling_frame == other.m_calling_frame && m_fun == other.m_fun); + return (m_calling_frame == other.m_calling_frame + && m_fun == other.m_fun); } void mark_deleted () { m_fun = reinterpret_cast (1); } @@ -334,12 +334,12 @@ public: bool is_empty () const { return m_fun == NULL; } const frame_region *m_calling_frame; - function *m_fun; + const function *m_fun; }; frame_region (symbol::id_t id, const region *parent, const frame_region *calling_frame, - function *fun, int index) + const function &fun, int index) : space_region (id, parent), m_calling_frame (calling_frame), m_fun (fun), m_index (index) {} @@ -356,8 +356,8 @@ public: /* Accessors. */ const frame_region *get_calling_frame () const { return m_calling_frame; } - function *get_function () const { return m_fun; } - tree get_fndecl () const { return get_function ()->decl; } + const function &get_function () const { return m_fun; } + tree get_fndecl () const { return get_function ().decl; } int get_index () const { return m_index; } int get_stack_depth () const { return m_index + 1; } @@ -373,7 +373,7 @@ public: private: const frame_region *m_calling_frame; - function *m_fun; + const function &m_fun; int m_index; /* The regions for the decls within this frame are managed by this diff --git a/gcc/analyzer/sm-signal.cc b/gcc/analyzer/sm-signal.cc index 5be857a99ff8..93269caa0dc5 100644 --- a/gcc/analyzer/sm-signal.cc +++ b/gcc/analyzer/sm-signal.cc @@ -146,7 +146,8 @@ public: if (change.is_global_p () && change.m_new_state == m_sm.m_in_signal_handler) { - function *handler = change.m_event.get_dest_function (); + const function *handler = change.m_event.get_dest_function (); + gcc_assert (handler); return change.formatted_print ("registering %qD as signal handler", handler->decl); } @@ -193,7 +194,7 @@ signal_state_machine::signal_state_machine (logger *logger) static void update_model_for_signal_handler (region_model *model, - function *handler_fun) + const function &handler_fun) { gcc_assert (model); /* Purge all state within MODEL. */ @@ -222,7 +223,9 @@ public: region_model_context *) const final override { gcc_assert (eedge); - update_model_for_signal_handler (model, eedge->m_dest->get_function ()); + gcc_assert (eedge->m_dest->get_function ()); + update_model_for_signal_handler (model, + *eedge->m_dest->get_function ()); return true; } @@ -263,11 +266,11 @@ public: program_point entering_handler = program_point::from_function_entry (*ext_state.get_model_manager (), eg->get_supergraph (), - handler_fun); + *handler_fun); program_state state_entering_handler (ext_state); update_model_for_signal_handler (state_entering_handler.m_region_model, - handler_fun); + *handler_fun); state_entering_handler.m_checker_states[sm_idx]->set_global_state (m_sm.m_in_signal_handler); diff --git a/gcc/analyzer/state-purge.cc b/gcc/analyzer/state-purge.cc index 93959fb08ea3..324b548f75b1 100644 --- a/gcc/analyzer/state-purge.cc +++ b/gcc/analyzer/state-purge.cc @@ -89,7 +89,7 @@ class gimple_op_visitor : public log_user public: gimple_op_visitor (state_purge_map *map, const function_point &point, - function *fun) + const function &fun) : log_user (map->get_logger ()), m_map (map), m_point (point), @@ -172,7 +172,7 @@ private: state_purge_map *m_map; const function_point &m_point; - function *m_fun; + const function &m_fun; }; static bool @@ -214,6 +214,7 @@ state_purge_map::state_purge_map (const supergraph &sg, FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) { function *fun = node->get_fun (); + gcc_assert (fun); if (logger) log ("function: %s", function_name (fun)); tree name; @@ -225,7 +226,7 @@ state_purge_map::state_purge_map (const supergraph &sg, if (TREE_CODE (var) == VAR_DECL) if (VAR_DECL_IS_VIRTUAL_OPERAND (var)) continue; - m_ssa_map.put (name, new state_purge_per_ssa_name (*this, name, fun)); + m_ssa_map.put (name, new state_purge_per_ssa_name (*this, name, *fun)); } } @@ -241,8 +242,10 @@ state_purge_map::state_purge_map (const supergraph &sg, unsigned i; FOR_EACH_VEC_ELT (snode->m_stmts, i, stmt) { + function *fun = snode->get_function (); + gcc_assert (fun); function_point point (function_point::before_stmt (snode, i)); - gimple_op_visitor v (this, point, snode->get_function ()); + gimple_op_visitor v (this, point, *fun); walk_stmt_load_store_addr_ops (stmt, &v, my_load_cb, my_store_cb, my_addr_cb); } @@ -272,7 +275,7 @@ state_purge_map::~state_purge_map () if necessary. */ state_purge_per_decl & -state_purge_map::get_or_create_data_for_decl (function *fun, tree decl) +state_purge_map::get_or_create_data_for_decl (const function &fun, tree decl) { if (state_purge_per_decl **slot = const_cast (m_decl_map).get (decl)) @@ -295,14 +298,14 @@ state_purge_map::get_or_create_data_for_decl (function *fun, tree decl) state_purge_per_ssa_name::state_purge_per_ssa_name (const state_purge_map &map, tree name, - function *fun) + const function &fun) : state_purge_per_tree (fun), m_points_needing_name (), m_name (name) { LOG_FUNC (map.get_logger ()); if (map.get_logger ()) { - map.log ("SSA name: %qE within %qD", name, fun->decl); + map.log ("SSA name: %qE within %qD", name, fun.decl); /* Show def stmt. */ const gimple *def_stmt = SSA_NAME_DEF_STMT (name); @@ -410,7 +413,7 @@ state_purge_per_ssa_name::state_purge_per_ssa_name (const state_purge_map &map, if (map.get_logger ()) { - map.log ("%qE in %qD is needed to process:", name, fun->decl); + map.log ("%qE in %qD is needed to process:", name, fun.decl); /* Log m_points_needing_name, sorting it to avoid churn when comparing dumps. */ auto_vec points; @@ -472,7 +475,7 @@ state_purge_per_ssa_name::add_to_worklist (const function_point &point, logger->end_log_line (); } - gcc_assert (point.get_function () == get_function ()); + gcc_assert (point.get_function () == &get_function ()); if (point.get_from_edge ()) gcc_assert (point.get_from_edge ()->get_kind () == SUPEREDGE_CFG_EDGE); @@ -678,7 +681,7 @@ state_purge_per_ssa_name::process_point (const function_point &point, state_purge_per_decl::state_purge_per_decl (const state_purge_map &map, tree decl, - function *fun) + const function &fun) : state_purge_per_tree (fun), m_decl (decl) { @@ -794,7 +797,7 @@ state_purge_per_decl::add_to_worklist (const function_point &point, logger->end_log_line (); } - gcc_assert (point.get_function () == get_function ()); + gcc_assert (point.get_function () == &get_function ()); if (point.get_from_edge ()) gcc_assert (point.get_from_edge ()->get_kind () == SUPEREDGE_CFG_EDGE); @@ -1192,7 +1195,7 @@ state_purge_annotator::print_needed (graphviz_out *gv, { tree name = (*iter).first; state_purge_per_ssa_name *per_name_data = (*iter).second; - if (per_name_data->get_function () == point.get_function ()) + if (&per_name_data->get_function () == point.get_function ()) { if (per_name_data->needed_at_point_p (point)) needed.safe_push (name); @@ -1206,7 +1209,7 @@ state_purge_annotator::print_needed (graphviz_out *gv, { tree decl = (*iter).first; state_purge_per_decl *per_decl_data = (*iter).second; - if (per_decl_data->get_function () == point.get_function ()) + if (&per_decl_data->get_function () == point.get_function ()) { if (per_decl_data->needed_at_point_p (point)) needed.safe_push (decl); diff --git a/gcc/analyzer/state-purge.h b/gcc/analyzer/state-purge.h index c6d64b41fd46..4eb2ba0a908a 100644 --- a/gcc/analyzer/state-purge.h +++ b/gcc/analyzer/state-purge.h @@ -112,7 +112,8 @@ public: return NULL; } - state_purge_per_decl &get_or_create_data_for_decl (function *fun, tree decl); + state_purge_per_decl & + get_or_create_data_for_decl (const function &fun, tree decl); const supergraph &get_sg () const { return m_sg; } @@ -135,19 +136,19 @@ private: class state_purge_per_tree { public: - function *get_function () const { return m_fun; } - tree get_fndecl () const { return m_fun->decl; } + const function &get_function () const { return m_fun; } + tree get_fndecl () const { return m_fun.decl; } protected: typedef hash_set point_set_t; - state_purge_per_tree (function *fun) + state_purge_per_tree (const function &fun) : m_fun (fun) { } private: - function *m_fun; + const function &m_fun; }; /* The part of a state_purge_map relating to a specific SSA name. @@ -162,7 +163,7 @@ class state_purge_per_ssa_name : public state_purge_per_tree public: state_purge_per_ssa_name (const state_purge_map &map, tree name, - function *fun); + const function &fun); bool needed_at_point_p (const function_point &point) const; @@ -194,7 +195,7 @@ class state_purge_per_decl : public state_purge_per_tree public: state_purge_per_decl (const state_purge_map &map, tree decl, - function *fun); + const function &fun); bool needed_at_point_p (const function_point &point) const; diff --git a/gcc/analyzer/supergraph.cc b/gcc/analyzer/supergraph.cc index b82275256b72..adbf90f17ede 100644 --- a/gcc/analyzer/supergraph.cc +++ b/gcc/analyzer/supergraph.cc @@ -364,6 +364,7 @@ supergraph::dump_dot_to_pp (pretty_printer *pp, FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) { function *fun = node->get_fun (); + gcc_assert (fun); const char *funcname = function_name (fun); gv.println ("subgraph \"cluster_%s\" {", funcname); @@ -409,9 +410,9 @@ supergraph::dump_dot_to_pp (pretty_printer *pp, /* Add an invisible edge from ENTRY to EXIT, to improve the graph layout. */ pp_string (pp, "\t"); - get_node_for_function_entry (fun)->dump_dot_id (pp); + get_node_for_function_entry (*fun)->dump_dot_id (pp); pp_string (pp, ":s -> "); - get_node_for_function_exit (fun)->dump_dot_id (pp); + get_node_for_function_exit (*fun)->dump_dot_id (pp); pp_string (pp, ":n [style=\"invis\",constraint=true];\n"); /* Terminate per-function "subgraph" */ diff --git a/gcc/analyzer/supergraph.h b/gcc/analyzer/supergraph.h index 2677acad8d6a..86f918bc8b5d 100644 --- a/gcc/analyzer/supergraph.h +++ b/gcc/analyzer/supergraph.h @@ -111,14 +111,14 @@ public: supergraph (logger *logger); ~supergraph (); - supernode *get_node_for_function_entry (function *fun) const + supernode *get_node_for_function_entry (const function &fun) const { - return get_node_for_block (ENTRY_BLOCK_PTR_FOR_FN (fun)); + return get_node_for_block (ENTRY_BLOCK_PTR_FOR_FN (&fun)); } - supernode *get_node_for_function_exit (function *fun) const + supernode *get_node_for_function_exit (const function &fun) const { - return get_node_for_block (EXIT_BLOCK_PTR_FOR_FN (fun)); + return get_node_for_block (EXIT_BLOCK_PTR_FOR_FN (&fun)); } supernode *get_node_for_block (basic_block bb) const diff --git a/gcc/function.cc b/gcc/function.cc index 5ffd438475e9..9488181cbd95 100644 --- a/gcc/function.cc +++ b/gcc/function.cc @@ -6391,7 +6391,7 @@ fndecl_name (tree fndecl) /* Returns the name of function FN. */ const char * -function_name (struct function *fn) +function_name (const function *fn) { tree fndecl = (fn == NULL) ? NULL : fn->decl; return fndecl_name (fndecl); diff --git a/gcc/function.h b/gcc/function.h index 2d775b877fc2..19e15bd63b0a 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -730,7 +730,7 @@ extern poly_int64 get_stack_dynamic_offset (); /* Returns the name of the current function. */ extern const char *fndecl_name (tree); -extern const char *function_name (struct function *); +extern const char *function_name (const function *); extern const char *current_function_name (void); extern void used_types_insert (tree); diff --git a/gcc/testsuite/c-c++-common/analyzer/call-summaries-pr114159.c b/gcc/testsuite/c-c++-common/analyzer/call-summaries-pr114159.c new file mode 100644 index 000000000000..19b545a1154d --- /dev/null +++ b/gcc/testsuite/c-c++-common/analyzer/call-summaries-pr114159.c @@ -0,0 +1,20 @@ +/* Verify we don't ICE on this case with these options. */ + +/* { dg-additional-options "-fanalyzer-call-summaries --param=analyzer-max-svalue-depth=0 -Wno-analyzer-symbol-too-complex" } */ + +int foo_i; +void bar() {} +void foo() { + if (foo_i) + bar(); + else + goto f1; + bar(); +f1: + bar(); +} +int main() { + foo(); + foo(); + return 0; +}