| /* Iterator for walking a chain of inlining locations. |
| Copyright (C) 2022 Free Software Foundation, Inc. |
| Contributed by David Malcolm <dmalcolm@redhat.com>. |
| |
| This file is part of GCC. |
| |
| GCC is free software; you can redistribute it and/or modify it |
| under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3, or (at your option) |
| any later version. |
| |
| GCC is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GCC; see the file COPYING3. If not see |
| <http://www.gnu.org/licenses/>. */ |
| |
| #ifndef GCC_ANALYZER_INLINING_ITERATOR_H |
| #define GCC_ANALYZER_INLINING_ITERATOR_H |
| |
| /* Iterator for walking a chain of inlining locations. |
| |
| The fndecls and locations will be traversed from innermost to outermost. |
| For example, given: |
| |
| inline void inner (void) |
| { |
| ...LOCATION HERE... |
| } |
| void outer (void) |
| { |
| inner (); <-- CALLSITE |
| } |
| |
| then the fndecl will be "inner" on the initial iteration, and "outer" on |
| the second (final) iteration. |
| |
| Compare with lhd_print_error_function, cp_print_error_function, |
| and optrecord_json_writer::inlining_chain_to_json. */ |
| |
| class inlining_iterator |
| { |
| public: |
| inlining_iterator (location_t loc) |
| : m_abstract_origin (LOCATION_BLOCK (loc)), |
| m_callsite (UNKNOWN_LOCATION), m_fndecl (NULL), |
| m_next_abstract_origin (NULL) |
| { |
| prepare_iteration (); |
| } |
| |
| bool done_p () const { return m_abstract_origin == NULL; } |
| |
| void next () |
| { |
| m_abstract_origin = m_next_abstract_origin; |
| prepare_iteration (); |
| } |
| |
| tree get_fndecl () const { return m_fndecl; } |
| location_t get_callsite () const { return m_callsite; } |
| tree get_block () const { return m_abstract_origin; } |
| |
| private: |
| void prepare_iteration () |
| { |
| if (done_p ()) |
| return; |
| tree block = m_abstract_origin; |
| m_callsite = BLOCK_SOURCE_LOCATION (block); |
| m_fndecl = NULL; |
| block = BLOCK_SUPERCONTEXT (block); |
| while (block && TREE_CODE (block) == BLOCK |
| && BLOCK_ABSTRACT_ORIGIN (block)) |
| { |
| tree ao = BLOCK_ABSTRACT_ORIGIN (block); |
| if (TREE_CODE (ao) == FUNCTION_DECL) |
| { |
| m_fndecl = ao; |
| break; |
| } |
| else if (TREE_CODE (ao) != BLOCK) |
| break; |
| |
| block = BLOCK_SUPERCONTEXT (block); |
| } |
| if (m_fndecl) |
| m_next_abstract_origin = block; |
| else |
| { |
| while (block && TREE_CODE (block) == BLOCK) |
| block = BLOCK_SUPERCONTEXT (block); |
| |
| if (block && TREE_CODE (block) == FUNCTION_DECL) |
| m_fndecl = block; |
| m_next_abstract_origin = NULL; |
| } |
| } |
| |
| tree m_abstract_origin; |
| location_t m_callsite; |
| tree m_fndecl; |
| tree m_next_abstract_origin; |
| }; |
| |
| #endif /* GCC_ANALYZER_INLINING_ITERATOR_H */ |