aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/analyzer')
-rw-r--r--gcc/analyzer/ChangeLog237
-rw-r--r--gcc/analyzer/access-diagram.cc6
-rw-r--r--gcc/analyzer/ana-state-to-diagnostic-state.cc786
-rw-r--r--gcc/analyzer/ana-state-to-diagnostic-state.h89
-rw-r--r--gcc/analyzer/analyzer-language.cc2
-rw-r--r--gcc/analyzer/analyzer-language.h2
-rw-r--r--gcc/analyzer/analyzer-logging.h19
-rw-r--r--gcc/analyzer/analyzer-pass.cc16
-rw-r--r--gcc/analyzer/analyzer.cc4
-rw-r--r--gcc/analyzer/bounds-checking.cc6
-rw-r--r--gcc/analyzer/call-details.cc24
-rw-r--r--gcc/analyzer/call-string.cc10
-rw-r--r--gcc/analyzer/call-string.h8
-rw-r--r--gcc/analyzer/call-summary.cc80
-rw-r--r--gcc/analyzer/checker-event.cc87
-rw-r--r--gcc/analyzer/checker-event.h57
-rw-r--r--gcc/analyzer/checker-path.cc12
-rw-r--r--gcc/analyzer/checker-path.h6
-rw-r--r--gcc/analyzer/common.h16
-rw-r--r--gcc/analyzer/constraint-manager.cc40
-rw-r--r--gcc/analyzer/constraint-manager.h4
-rw-r--r--gcc/analyzer/diagnostic-manager.cc76
-rw-r--r--gcc/analyzer/engine.cc236
-rw-r--r--gcc/analyzer/exploded-graph.h38
-rw-r--r--gcc/analyzer/function-set.cc2
-rw-r--r--gcc/analyzer/infinite-recursion.cc29
-rw-r--r--gcc/analyzer/inlining-iterator.h4
-rw-r--r--gcc/analyzer/kf-analyzer.cc18
-rw-r--r--gcc/analyzer/kf.cc10
-rw-r--r--gcc/analyzer/known-function-manager.cc14
-rw-r--r--gcc/analyzer/pending-diagnostic.cc10
-rw-r--r--gcc/analyzer/pending-diagnostic.h6
-rw-r--r--gcc/analyzer/program-point.cc28
-rw-r--r--gcc/analyzer/program-point.h10
-rw-r--r--gcc/analyzer/program-state.cc121
-rw-r--r--gcc/analyzer/program-state.h17
-rw-r--r--gcc/analyzer/record-layout.cc4
-rw-r--r--gcc/analyzer/record-layout.h9
-rw-r--r--gcc/analyzer/region-model-asm.cc4
-rw-r--r--gcc/analyzer/region-model-manager.cc48
-rw-r--r--gcc/analyzer/region-model-manager.h2
-rw-r--r--gcc/analyzer/region-model-reachability.cc6
-rw-r--r--gcc/analyzer/region-model.cc320
-rw-r--r--gcc/analyzer/region-model.h50
-rw-r--r--gcc/analyzer/region.cc56
-rw-r--r--gcc/analyzer/region.h56
-rw-r--r--gcc/analyzer/sm-fd.cc72
-rw-r--r--gcc/analyzer/sm-file.cc39
-rw-r--r--gcc/analyzer/sm-malloc.cc141
-rw-r--r--gcc/analyzer/sm-pattern-test.cc2
-rw-r--r--gcc/analyzer/sm-sensitive.cc4
-rw-r--r--gcc/analyzer/sm-signal.cc4
-rw-r--r--gcc/analyzer/sm-taint.cc18
-rw-r--r--gcc/analyzer/sm.cc23
-rw-r--r--gcc/analyzer/sm.h22
-rw-r--r--gcc/analyzer/state-purge.cc12
-rw-r--r--gcc/analyzer/state-purge.h2
-rw-r--r--gcc/analyzer/store.cc86
-rw-r--r--gcc/analyzer/store.h20
-rw-r--r--gcc/analyzer/supergraph.cc37
-rw-r--r--gcc/analyzer/supergraph.h34
-rw-r--r--gcc/analyzer/svalue.cc48
-rw-r--r--gcc/analyzer/svalue.h54
-rw-r--r--gcc/analyzer/varargs.cc57
64 files changed, 2416 insertions, 944 deletions
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog
index 1fbba5d..d31cbbc 100644
--- a/gcc/analyzer/ChangeLog
+++ b/gcc/analyzer/ChangeLog
@@ -1,3 +1,240 @@
+2025-06-30 David Malcolm <dmalcolm@redhat.com>
+
+ * access-diagram.cc: Use nullptr rather than NULL where
+ appropriate.
+ * analyzer-language.cc: Likewise.
+ * analyzer-language.h: Likewise.
+ * analyzer-logging.h: Likewise.
+ * analyzer-pass.cc: Likewise.
+ * analyzer.cc: Likewise.
+ * bounds-checking.cc: Likewise.
+ * call-details.cc: Likewise.
+ * call-string.cc: Likewise.
+ * call-string.h: Likewise.
+ * call-summary.cc: Likewise.
+ * checker-event.cc: Likewise.
+ * common.h: Likewise.
+ * constraint-manager.cc: Likewise.
+ * constraint-manager.h: Likewise.
+ * diagnostic-manager.cc: Likewise.
+ * engine.cc: Likewise.
+ * exploded-graph.h: Likewise.
+ * function-set.cc: Likewise
+ * infinite-recursion.cc: Likewise
+ * inlining-iterator.h: Likewise
+ * kf.cc: Likewise
+ * known-function-manager.cc: Likewise
+ * pending-diagnostic.cc: Likewise
+ * program-point.cc: Likewise
+ * program-point.h: Likewise
+ * program-state.cc: Likewise
+ * program-state.h: Likewise
+ * record-layout.cc: Likewise
+ * region-model-asm.cc: Likewise
+ * region-model-manager.cc: Likewise
+ * region-model-manager.h: Likewise
+ * region-model-reachability.cc: Likewise
+ * region-model.cc: Likewise
+ * region-model.h: Likewise
+ * region.cc: Likewise
+ * region.h: Likewise
+ * sm-fd.cc: Likewise
+ * sm-malloc.cc: Likewise
+ * sm-pattern-test.cc: Likewise
+ * sm-signal.cc: Likewise
+ * sm-taint.cc: Likewise
+ * sm.cc: Likewise
+ * sm.h: Likewise
+ * state-purge.cc: Likewise
+ * state-purge.h: Likewise
+ * store.cc: Likewise
+ * store.h: Likewise
+ * supergraph.cc: Likewise
+ * supergraph.h: Likewise
+ * svalue.cc: Likewise
+ * svalue.h: Likewise
+ * varargs.cc: Likewise
+
+2025-06-30 David Malcolm <dmalcolm@redhat.com>
+
+ * checker-event.cc (function_entry_event::get_meaning): Convert
+ diagnostic_event::meaning enums to enum class.
+ (cfg_edge_event::get_meaning): Likewise.
+ (call_event::get_meaning): Likewise.
+ (return_event::get_meaning): Likewise.
+ (start_consolidated_cfg_edges_event::get_meaning): Likewise.
+ (inlined_call_event::get_meaning): Likewise.
+ (warning_event::get_meaning): Likewise.
+ * sm-fd.cc (fd_diagnostic::get_meaning_for_state_change):
+ Likewise.
+ * sm-file.cc (file_diagnostic::get_meaning_for_state_change):
+ Likewise.
+ * sm-malloc.cc (malloc_diagnostic::get_meaning_for_state_change):
+ Likewise.
+ * sm-sensitive.cc
+ (exposure_through_output_file::get_meaning_for_state_change):
+ Likewise.
+ * sm-taint.cc (taint_diagnostic::get_meaning_for_state_change):
+ Likewise.
+ * varargs.cc
+ (va_list_sm_diagnostic::get_meaning_for_state_change): Likewise.
+
+2025-06-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/120520
+ PR c/117023
+ * sm-malloc.cc (malloc_state_machine::on_stmt): Handle 3 argument
+ nonnull_if_nonzero attribute.
+
+2025-06-23 David Malcolm <dmalcolm@redhat.com>
+
+ * region-model.cc
+ (exception_thrown_from_unrecognized_call::print): Add
+ "final override" to vfunc.
+
+2025-06-23 David Malcolm <dmalcolm@redhat.com>
+
+ PR other/116792
+ * ana-state-to-diagnostic-state.cc: New file.
+ * ana-state-to-diagnostic-state.h: New file.
+ * checker-event.cc: Include "xml.h".
+ (checker_event::checker_event): Initialize m_path.
+ (checker_event::prepare_for_emission): Store the path pointer into
+ m_path.
+ (checker_event::maybe_make_xml_state): New.
+ (function_entry_event::function_entry_event): Add "state" param
+ and use it to initialize m_state.
+ (superedge_event::get_program_state): New.
+ (call_event::get_program_state): New.
+ (warning_event::get_program_state): New.
+ * checker-event.h (checker_event::get_program_state): New vfunc.
+ (checker_event::maybe_make_xml_state): New decl.
+ (checker_event::m_path): New field.
+ (statement_event::get_program_state): New vfunc impl.
+ (function_entry_event::function_entry_event): Add "state" param.
+ (function_entry_event::get_program_state): New vfunc impl.
+ (function_entry_event::m_state): New field.
+ (state_change_event::get_program_state): New vfunc impl.
+ (superedge_event::get_program_state): New vfunc decl.
+ (warning_event::warning_event): Add "program_state_" param and
+ copy it.
+ (warning_event::get_program_state): New vfunc decl.
+ (warning_event::m_program_state): New field.
+ * checker-path.h (checker_path::checker_path): Add ext_state param.
+ (checker_path::get_ext_state): New accessor.
+ (checker_path::m_ext_state): New field.
+ * common.h: Define INCLUDE_MAP and INCLUDE_STRING.
+ * diagnostic-manager.cc (saved_diagnostic::operator==): Don't
+ deduplicate dump_path_diagnostic instances.
+ (diagnostic_manager::emit_saved_diagnostic): Pass ext_state to
+ checker_path ctor.
+ * engine.cc:
+ (impl_region_model_context::on_state_leak): Pass old and new state
+ to state_machine::on_leak.
+ (exploded_node::on_stmt_pre): Implement __analyzer_dump_xml and
+ __analyzer_dump_dot.
+ * exploded-graph.h (impl_region_model_context::get_state): New.
+ * infinite-recursion.cc
+ (recursive_function_entry_event::recursive_function_entry_event):
+ Add "dst_state" param and pass to function_entry_event ctor.
+ (infinite_recursion_diagnostic::add_function_entry_event): Pass state
+ to event ctor.
+ * kf-analyzer.cc: Include "analyzer/program-state.h"
+ (dump_path_diagnostic::dump_path_diagnostic): Add "state" param.
+ (dump_path_diagnostic::get_final_state): New.
+ (dump_path_diagnostic::m_state): New field.
+ (kf_analyzer_dump_path::impl_call_pre): Pass state to warning.
+ * pending-diagnostic.cc
+ (pending_diagnostic::add_function_entry_event): Pass state to
+ function_entry_event.
+ (pending_diagnostic::add_final_event): Likewise to warning_event.
+ * pending-diagnostic.h (pending_diagnostic::get_final_state): New
+ vfunc decl.
+ * program-state.cc: Include "diagnostic-state.h", "graphviz.h" and
+ "analyzer/ana-state-to-diagnostic-state.h".
+ (program_state::dump_dot): New.
+ * program-state.h: Include "text-art/tree-widget.h" and
+ "analyzer/store.h".
+ (class xml::document): New forward decl.
+ (make_xml): New.
+ (dump_xml_to_pp): New.
+ (dump_xml_to_file): New.
+ (dump_xml): New.
+ (dump_dot): New.
+ * record-layout.cc (record_layout::record_layout): Make param
+ const_tree.
+ * record-layout.h (item::item): Likewise.
+ (item::m_field): Likewise.
+ (record_layout::record_layout): Likewise.
+ (record_layout::begin): New.
+ (record_layout::end): New.
+ * region-model.cc
+ (exposure_through_uninit_copy::complain_about_fully_uninit_item):
+ Use const_tree.
+ (exposure_through_uninit_copy::complain_about_partially_uninit_item):
+ Likewise.
+ * region-model.h (region_model_context::get_state): New vfunc.
+ (noop_region_model_context::get_state): New.
+ (region_model_context_decorator::get_state): New.
+ * sm-fd.cc (fd_leak::fd_leak): Add "final_state" param and capture
+ it if present.
+ (fd_leak::get_final_state): New.
+ (fd_leak::m_final_state): New.
+ (fd_state_machine::on_open): Pass nullptr for new "final_state"
+ param.
+ (fd_state_machine::on_creat): Likewise.
+ (fd_state_machine::on_socket): Likewise.
+ (fd_state_machine::on_accept): Likewise.
+ (fd_state_machine::on_leak): Add state params and pass new state
+ as final state to fd_leak ctor.
+ * sm-file.cc: Include "analyzer/program-state.h".
+ (file_leak::file_leak): Add "final_state" param and capture it if
+ present.
+ (file_leak::get_final_state): New.
+ (file_leak::m_final_state): New.
+ (fileptr_state_machine::on_leak): Add state params and pass new
+ state as final state to fd_leak ctor.
+ * sm-malloc.cc: Include
+ "analyzer/ana-state-to-diagnostic-state.h".
+ (malloc_leak::malloc_leak): Add "final_state" param and use it.
+ (malloc_leak::get_final_state): New vfunc impl.
+ (malloc_leak::m_final_state): New field.
+ (malloc_state_machine::on_leak): Add state params; capture final
+ state.
+ (malloc_state_machine::add_state_to_xml): New.
+ * sm.cc (state_machine::on_leak): Add "old_state" and "new_state"
+ params. Use nullptr.
+ (state_machine::add_state_to_xml): New.
+ (state_machine::add_global_state_to_xml): New.
+ * sm.h (class xml_state): New forward decl.
+ (state_machine::on_leak): Add state params.
+ (state_machine::add_state_to_xml): New vfunc decl.
+ (state_machine::add_global_state_to_xml): New vfunc decl.
+ * store.h (bit_range::operator<): New.
+ * varargs.cc (va_list_leak::va_list_leak): Add final_state param
+ and capture it if non-null.
+ (va_list_leak::get_final_state): New.
+ (va_list_leak::m_final_state): New.
+ (va_list_state_machine::on_leak): Add state params and pass final
+ state to va_list_leak ctor.
+
+2025-06-18 David Malcolm <dmalcolm@redhat.com>
+
+ * checker-event.h (checker_event::get_kind): New accessor.
+ (checker_event::m_kind): Make private.
+ * checker-path.cc (checker_path::maybe_log): Use accessor for
+ checker_event::m_kind.
+ (checker_path::add_event): Likewise.
+ (checker_path::debug): Likewise.
+ (checker_path::cfg_edge_pair_at_p): Likewise.
+ (checker_path::inject_any_inlined_call_events): Likewise.
+ * diagnostic-manager.cc
+ (diagnostic_manager::prune_for_sm_diagnostic): Likewise.
+ (diagnostic_manager::prune_for_sm_diagnostic): Likewise.
+ (diagnostic_manager::consolidate_conditions): Likewise.
+ (diagnostic_manager::consolidate_unwind_events): Likewise.
+ (diagnostic_manager::finish_pruning): Likewise.
+
2025-05-06 David Malcolm <dmalcolm@redhat.com>
* checker-event.cc (checker_event::checker_event): Update
diff --git a/gcc/analyzer/access-diagram.cc b/gcc/analyzer/access-diagram.cc
index 4283360..90b396c 100644
--- a/gcc/analyzer/access-diagram.cc
+++ b/gcc/analyzer/access-diagram.cc
@@ -1116,7 +1116,7 @@ public:
{
logger.start_log_line ();
logger.log_partial ("table_x: %i", table_x);
- access_range range_for_column (NULL, bit_range (0, 0));
+ access_range range_for_column (nullptr, bit_range (0, 0));
if (maybe_get_access_range_for_table_x (table_x, &range_for_column))
{
logger.log_partial (": range: ");
@@ -2244,7 +2244,7 @@ private:
for (int table_x = 0; table_x < t.get_size ().w; table_x++)
{
const int table_y = 1;
- access_range range_for_column (NULL, bit_range (0, 0));
+ access_range range_for_column (nullptr, bit_range (0, 0));
if (m_btm.maybe_get_access_range_for_table_x (table_x,
&range_for_column))
{
@@ -2495,7 +2495,7 @@ private:
std::vector<bit_offset_t> bit_sizes (num_columns);
for (unsigned table_x = 0; table_x < num_columns; table_x++)
{
- access_range range_for_column (NULL, bit_range (0, 0));
+ access_range range_for_column (nullptr, bit_range (0, 0));
if (m_btm.maybe_get_access_range_for_table_x (table_x,
&range_for_column))
{
diff --git a/gcc/analyzer/ana-state-to-diagnostic-state.cc b/gcc/analyzer/ana-state-to-diagnostic-state.cc
new file mode 100644
index 0000000..b85a2f1
--- /dev/null
+++ b/gcc/analyzer/ana-state-to-diagnostic-state.cc
@@ -0,0 +1,786 @@
+/* Converting ana::program_state to XML state documents.
+ Copyright (C) 2025 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/>. */
+
+#define INCLUDE_ALGORITHM
+#define INCLUDE_MAP
+#define INCLUDE_SET
+#include "analyzer/common.h"
+
+#include "xml.h"
+#include "xml-printer.h"
+
+#include "analyzer/region-model.h"
+#include "analyzer/program-state.h"
+#include "analyzer/record-layout.h"
+#include "analyzer/ana-state-to-diagnostic-state.h"
+
+#if ENABLE_ANALYZER
+
+#if __GNUC__ >= 10
+#pragma GCC diagnostic ignored "-Wformat"
+#endif
+
+namespace ana {
+
+static void
+set_wi_attr (xml::element &e,
+ const char *attr_name,
+ const wide_int_ref &w,
+ signop sgn)
+{
+ pretty_printer pp;
+ pp_wide_int (&pp, w, sgn);
+ e.set_attr (attr_name, pp_formatted_text (&pp));
+}
+
+static void
+set_type_attr (xml::element &e, const_tree type)
+{
+ gcc_assert (type);
+ pretty_printer pp;
+ pp_format_decoder (&pp) = default_tree_printer;
+ pp_printf (&pp, "%T", type);
+ e.set_attr ("type", pp_formatted_text (&pp));
+}
+
+static void
+set_bits_attr (xml::element &e,
+ bit_range bits)
+{
+ pretty_printer pp;
+ bits.dump_to_pp (&pp);
+ e.set_attr ("bits", pp_formatted_text (&pp));
+}
+
+static void
+set_region_id_attr (xml::element &e,
+ const region &reg)
+{
+ e.set_attr ("region_id", std::to_string (reg.get_id ()));
+}
+
+// class xml_state : public xml::document
+
+xml_state::xml_state (const program_state &state,
+ const extrinsic_state &ext_state)
+: xml::document (),
+ m_state (state),
+ m_ext_state (ext_state),
+ m_mgr (*ext_state.get_engine ()->get_model_manager ()),
+ m_root (nullptr)
+{
+ auto root = std::make_unique<xml::element> ("state-diagram", false);
+ m_root = root.get ();
+ add_child (std::move (root));
+
+ /* Find pointers to heap-allocated regions, and record their types,
+ so that we have a user-friendly way of showing the memory
+ (by field, rather than by byte offset). */
+ for (auto cluster_iter : *state.m_region_model->get_store ())
+ for (auto binding_iter : *cluster_iter.second)
+ {
+ const svalue *svalue = binding_iter.second;
+ if (const region *reg = svalue->maybe_get_region ())
+ if (svalue->get_type () && !reg->get_type ())
+ {
+ tree pointed_to_type = TREE_TYPE (svalue->get_type ());
+ if (!VOID_TYPE_P (pointed_to_type))
+ m_types_for_untyped_regions[reg] = pointed_to_type;
+ }
+ }
+
+ /* TODO: look for vtable pointers at the top of dynamically-allocated
+ regions and use that type as a fallback. */
+
+ /* Find regions of interest.
+ Create elements per region, and build into hierarchy.
+ Add edges for pointers. */
+
+ /* Create stack, from top to bottom. */
+ for (int i = state.m_region_model->get_stack_depth () - 1; i >= 0; --i)
+ {
+ const frame_region *reg = state.m_region_model->get_frame_at_index (i);
+ get_or_create_element (*reg);
+ }
+
+ /* Create bound memory. */
+ for (auto iter : *state.m_region_model->get_store ())
+ {
+ const bool create_all = false; // "true" for verbose, for debugging
+ create_elements_for_binding_cluster (*iter.second, create_all);
+ }
+
+ /* TODO: Constraints. */
+
+ /* Annotate with information from state machines. */
+ {
+ int i;
+ sm_state_map *smap;
+ FOR_EACH_VEC_ELT (state.m_checker_states, i, smap)
+ {
+ auto &sm = ext_state.get_sm (i);
+ for (const auto &iter : *smap)
+ sm.add_state_to_xml (*this, *iter.first, iter.second.m_state);
+ if (auto s = smap->get_global_state ())
+ sm.add_global_state_to_xml (*this, s);
+ }
+ }
+}
+
+xml::element &
+xml_state::get_or_create_element (const region &reg)
+{
+ auto existing = m_region_to_element_map.find (&reg);
+ if (existing != m_region_to_element_map.end ())
+ return *existing->second;
+
+ auto &e = create_and_add_element (reg);
+ m_region_to_element_map[&reg] = &e;
+ return e;
+}
+
+xml::element&
+xml_state::create_and_add_element (const region &reg)
+{
+ auto e = create_element (reg);
+ xml::element &result = *e;
+ if (auto parent_reg = reg.get_parent_region ())
+ {
+ auto parent_element = &get_or_create_element (*parent_reg);
+ parent_element->add_child (std::move (e));
+ }
+ else
+ m_root->add_child (std::move (e));
+ return result;
+}
+
+std::unique_ptr<xml::element>
+xml_state::make_memory_space_element (const char *label)
+{
+ auto e = std::make_unique<xml::element> ("memory-space", false);
+ e->set_attr ("label", label);
+ return e;
+}
+
+std::unique_ptr<xml::element>
+xml_state::create_element (const region &reg)
+{
+ std::unique_ptr<xml::element> e;
+ switch (reg.get_kind ())
+ {
+ default:
+ gcc_unreachable ();
+
+ case RK_FRAME:
+ {
+ e = std::make_unique<xml::element> ("stack-frame", false);
+ const frame_region &frame_reg
+ = static_cast<const frame_region &> (reg);
+ {
+ pretty_printer pp;
+ pp_format_decoder (&pp) = default_tree_printer;
+ pp_printf (&pp, "%E", frame_reg.get_fndecl ());
+ e->set_attr ("function", pp_formatted_text (&pp));
+ }
+ }
+ break;
+ case RK_GLOBALS:
+ e = make_memory_space_element ("Globals");
+ break;
+ case RK_CODE:
+ e = make_memory_space_element ("Code");
+ break;
+ case RK_FUNCTION:
+ e = std::make_unique<xml::element> ("function", false);
+ // TODO
+ break;
+ case RK_LABEL:
+ e = std::make_unique<xml::element> ("label", false);
+ // TODO
+ break;
+ case RK_STACK:
+ e = std::make_unique<xml::element> ("stack", false);
+ break;
+ case RK_HEAP:
+ e = make_memory_space_element ("Heap");
+ break;
+ case RK_THREAD_LOCAL:
+ e = make_memory_space_element ("Thread-local");
+ break;
+ case RK_ROOT:
+ e = std::make_unique<xml::element> ("memory-regions", false);
+ break;
+ case RK_SYMBOLIC:
+ e = std::make_unique<xml::element> ("symbolic-region", false);
+ // TODO
+ break;
+ case RK_DECL:
+ {
+ e = std::make_unique<xml::element> ("variable", false);
+ const decl_region &decl_reg
+ = static_cast<const decl_region &> (reg);
+ {
+ pretty_printer pp;
+ pp_format_decoder (&pp) = default_tree_printer;
+ pp_printf (&pp, "%E", decl_reg.get_decl ());
+ e->set_attr ("name", pp_formatted_text (&pp));
+ }
+ set_type_attr (*e, TREE_TYPE (decl_reg.get_decl ()));
+ }
+ break;
+ case RK_FIELD:
+ e = std::make_unique<xml::element> ("field", false);
+ break;
+ case RK_ELEMENT:
+ e = std::make_unique<xml::element> ("element", false);
+ break;
+ case RK_OFFSET:
+ e = std::make_unique<xml::element> ("offset-region", false);
+ // TODO
+ break;
+ case RK_SIZED:
+ e = std::make_unique<xml::element> ("sized-region", false);
+ // TODO
+ break;
+ case RK_CAST:
+ e = std::make_unique<xml::element> ("cast-region", false);
+ // TODO
+ break;
+ case RK_HEAP_ALLOCATED:
+ e = std::make_unique<xml::element> ("heap-buffer", false);
+ set_attr_for_dynamic_extents (reg, *e);
+ break;
+ case RK_ALLOCA:
+ e = std::make_unique<xml::element> ("alloca-buffer", false);
+ set_attr_for_dynamic_extents (reg, *e);
+ break;
+ case RK_STRING:
+ e = std::make_unique<xml::element> ("string-region", false);
+ // TODO
+ break;
+ case RK_BIT_RANGE:
+ e = std::make_unique<xml::element> ("RK_BIT_RANGE", false); // TODO
+ break;
+ case RK_VAR_ARG:
+ e = std::make_unique<xml::element> ("RK_VAR_ARG", false); // TODO
+ break;
+ case RK_ERRNO:
+ e = std::make_unique<xml::element> ("errno", false);
+ break;
+ case RK_PRIVATE:
+ e = std::make_unique<xml::element> ("RK_PRIVATE", false); // TODO
+ break;
+ case RK_UNKNOWN:
+ e = std::make_unique<xml::element> ("RK_UNKNOWN", false); // TODO
+ break;
+ }
+ gcc_assert (e);
+
+ set_region_id_attr (*e, reg);
+
+ if (reg.get_base_region () == &reg)
+ if (!reg.get_type ())
+ {
+ auto search
+ = m_types_for_untyped_regions.find (&reg);
+ if (search != m_types_for_untyped_regions.end ())
+ {
+ tree type_to_use = search->second;
+ set_type_attr (*e, type_to_use);
+ }
+ }
+
+ return e;
+}
+
+void
+xml_state::create_elements_for_binding_cluster (const binding_cluster &cluster,
+ bool create_all)
+{
+ /* TODO:
+ - symbolic bindings
+ - get current svalue, so as to get "zeros" and "uninitialized". */
+
+ concrete_bindings_t conc_bindings;
+ for (auto iter : cluster)
+ {
+ const binding_key *key = iter.first;
+ const svalue *svalue = iter.second;
+ if (auto conc_key = key->dyn_cast_concrete_binding ())
+ conc_bindings[conc_key->get_bit_range ()] = svalue;
+ if (const region *reg = svalue->maybe_get_region ())
+ get_or_create_element (*reg);
+ }
+
+ auto &e = get_or_create_element (*cluster.get_base_region ());
+
+ e.add_child (create_element_for_conc_bindings (conc_bindings));
+
+ const region *typed_reg = cluster.get_base_region ();
+ if (!typed_reg->get_type ())
+ {
+ auto search
+ = m_types_for_untyped_regions.find (cluster.get_base_region ());
+ if (search != m_types_for_untyped_regions.end ())
+ {
+ tree type_to_use = search->second;
+ typed_reg = m_mgr.get_cast_region (typed_reg, type_to_use);
+ }
+ }
+
+ if (typed_reg->get_type ())
+ populate_element_for_typed_region (e,
+ *typed_reg,
+ conc_bindings,
+ create_all);
+ else
+ {
+ // TODO
+ }
+}
+
+std::unique_ptr<xml::element>
+xml_state::create_element_for_conc_bindings (const concrete_bindings_t &conc_bindings)
+{
+ auto e = std::make_unique<xml::element> ("concrete-bindings", false);
+ for (auto iter : conc_bindings)
+ {
+ const bit_range bits = iter.first;
+ const svalue *sval = iter.second;
+ auto binding_element
+ = std::make_unique<xml::element> ("binding", false);
+ set_bits_attr (*binding_element, bits);
+ {
+ pretty_printer pp;
+ pp_format_decoder (&pp) = default_tree_printer;
+ sval->dump_to_pp (&pp, true);
+ binding_element->set_attr ("value", pp_formatted_text (&pp));
+ if (auto svalue_element = create_element_for_svalue (sval))
+ binding_element->add_child (std::move (svalue_element));
+ }
+ e->add_child (std::move (binding_element));
+ }
+ return e;
+}
+
+// Try to get the bit_range of REG within its base region
+bool
+xml_state::get_bit_range_within_base_region (const region &reg,
+ bit_range &out)
+{
+ region_offset start_offset = reg.get_offset (&m_mgr);
+ if (!start_offset.concrete_p ())
+ return false;
+ region_offset next_offset = reg.get_next_offset (&m_mgr);
+ if (!next_offset.concrete_p ())
+ return false;
+ out = bit_range (start_offset.get_bit_offset (),
+ next_offset.get_bit_offset ()
+ - start_offset.get_bit_offset ());
+ return true;
+}
+
+void
+xml_state::populate_element_for_typed_region (xml::element &e,
+ const region &reg,
+ const concrete_bindings_t &conc_bindings,
+ bool create_all)
+{
+ const_tree reg_type = reg.get_type ();
+ gcc_assert (reg_type);
+ set_type_attr (e, reg_type);
+
+ bit_range bits (0, 0);
+ if (get_bit_range_within_base_region (reg, bits))
+ {
+ set_bits_attr (e, bits);
+
+ auto search = conc_bindings.find (bits);
+ if (search != conc_bindings.end ())
+ {
+ const svalue *bound_sval = search->second;
+ if (auto svalue_element = create_element_for_svalue (bound_sval))
+ {
+ xml::printer xp (e);
+ xp.push_tag ("value-of-region");
+ xp.append (std::move (svalue_element));
+ }
+ }
+ }
+
+ switch (TREE_CODE (reg_type))
+ {
+ default:
+ break;
+
+ case ARRAY_TYPE:
+ {
+ tree domain = TYPE_DOMAIN (reg_type);
+ if (!domain)
+ return;
+ const_tree max_idx = TYPE_MAX_VALUE (domain);
+ if (!max_idx)
+ return;
+ if (TREE_CODE (max_idx) != INTEGER_CST)
+ return;
+ const_tree min_idx = TYPE_MIN_VALUE (domain);
+ if (TREE_CODE (min_idx) != INTEGER_CST)
+ return;
+ for (offset_int idx = wi::to_offset (min_idx);
+ idx <= wi::to_offset (max_idx);
+ ++idx)
+ {
+ const_tree element_type = TREE_TYPE (reg_type);
+ const svalue *sval_index
+ = m_mgr.get_or_create_int_cst (domain, idx);
+ const region *child_reg
+ = m_mgr.get_element_region (&reg,
+ const_cast<tree> (element_type),
+ sval_index);
+ if (show_child_element_for_child_region_p (*child_reg,
+ conc_bindings,
+ create_all))
+ {
+ // Here "element" is in the xml sense
+ auto child_element
+ = std::make_unique<xml::element> ("element", false);
+ set_wi_attr (*child_element, "index", idx, UNSIGNED);
+ set_region_id_attr (*child_element, *child_reg);
+ // Recurse:
+ gcc_assert (element_type);
+ populate_element_for_typed_region (*child_element,
+ *child_reg,
+ conc_bindings,
+ create_all);
+ e.add_child (std::move (child_element));
+ }
+ }
+ }
+ break;
+
+ case RECORD_TYPE:
+ {
+ const record_layout layout (reg_type);
+ for (auto item : layout)
+ {
+ if (item.m_is_padding)
+ {
+ const bit_range bits (0, item.m_bit_range.m_size_in_bits);
+ const region *child_reg
+ = m_mgr.get_bit_range (&reg, NULL_TREE, bits);
+ if (show_child_element_for_child_region_p (*child_reg,
+ conc_bindings,
+ create_all))
+ {
+ auto child_element
+ = std::make_unique<xml::element> ("padding", false);
+ set_wi_attr (*child_element, "num_bits",
+ item.m_bit_range.m_size_in_bits, SIGNED);
+ e.add_child (std::move (child_element));
+ }
+ }
+ else
+ {
+ const region *child_reg
+ = m_mgr.get_field_region (&reg,
+ const_cast<tree> (item.m_field));
+ if (show_child_element_for_child_region_p (*child_reg,
+ conc_bindings,
+ create_all))
+ {
+ auto child_element
+ = std::make_unique<xml::element> ("field", false);
+ {
+ pretty_printer pp;
+ pp_format_decoder (&pp) = default_tree_printer;
+ pp_printf (&pp, "%D", item.m_field);
+ child_element->set_attr ("name",
+ pp_formatted_text (&pp));
+ }
+ set_region_id_attr (*child_element, *child_reg);
+ // Recurse:
+ populate_element_for_typed_region (*child_element,
+ *child_reg,
+ conc_bindings,
+ create_all);
+ e.add_child (std::move (child_element));
+ }
+ }
+ }
+ }
+ break;
+ }
+}
+
+void
+xml_state::set_attr_for_dynamic_extents (const region &reg, xml::element &e)
+{
+ const svalue *sval = m_state.m_region_model->get_dynamic_extents (&reg);
+ if (sval)
+ {
+ pretty_printer pp;
+ pp_format_decoder (&pp) = default_tree_printer;
+ if (auto cst = sval->maybe_get_constant ())
+ pp_wide_int (&pp, wi::to_wide (cst), UNSIGNED);
+ else
+ sval->dump_to_pp (&pp, true);
+ e.set_attr ("dynamic-extents", pp_formatted_text (&pp));
+ }
+}
+
+bool
+xml_state::
+show_child_element_for_child_region_p (const region &reg,
+ const concrete_bindings_t &conc_bindings,
+ bool create_all)
+{
+ if (create_all)
+ return true;
+ bit_range reg_bits (0, 0);
+ if (!get_bit_range_within_base_region (reg, reg_bits))
+ return true;
+
+ /* Is any of "bits" bound?
+ TODO: ideally there would be a more efficient way to do this, using
+ spatial relationships. */
+ for (auto iter : conc_bindings)
+ {
+ const bit_range bound_bits = iter.first;
+ if (bound_bits.intersects_p (reg_bits))
+ return true;
+ }
+ return false;
+}
+
+std::unique_ptr<xml::element>
+xml_state::create_element_for_svalue (const svalue *sval)
+{
+ if (!sval)
+ return nullptr;
+
+ std::unique_ptr<xml::element> result;
+ switch (sval->get_kind ())
+ {
+ default:
+ gcc_unreachable ();
+ case SK_REGION:
+ {
+ const region_svalue *region_sval = (const region_svalue *)sval;
+ result
+ = std::make_unique<xml::element> ("pointer-to-region", false);
+ set_region_id_attr (*result, *region_sval->get_pointee ());
+ }
+ break;
+ case SK_CONSTANT:
+ {
+ const constant_svalue *constant_sval = (const constant_svalue *)sval;
+ result = std::make_unique<xml::element> ("constant", false);
+ pretty_printer pp;
+ pp_format_decoder (&pp) = default_tree_printer;
+ pp_printf (&pp, "%E", constant_sval->get_constant ());
+ result->set_attr ("value", pp_formatted_text (&pp));
+ }
+ break;
+ case SK_UNKNOWN:
+ result = std::make_unique<xml::element> ("unknown", false);
+ break;
+ case SK_POISONED:
+ {
+ const poisoned_svalue *poisoned_sval = (const poisoned_svalue *)sval;
+ switch (poisoned_sval->get_poison_kind ())
+ {
+ default:
+ gcc_unreachable ();
+ case poison_kind::uninit:
+ result = std::make_unique<xml::element> ("uninitialized", false);
+ break;
+ case poison_kind::freed:
+ result = std::make_unique<xml::element> ("freed", false);
+ break;
+ case poison_kind::deleted:
+ result = std::make_unique<xml::element> ("deleted", false);
+ break;
+ case poison_kind::popped_stack:
+ result = std::make_unique<xml::element> ("popped-stack", false);
+ break;
+ }
+ }
+ break;
+ case SK_SETJMP:
+ {
+ //const setjmp_svalue *setjmp_sval = (const setjmp_svalue *)sval;
+ result = std::make_unique<xml::element> ("setjmp-buffer", false);
+ // TODO
+ }
+ break;
+ case SK_INITIAL:
+ {
+ const initial_svalue *initial_sval = (const initial_svalue *)sval;
+ result = std::make_unique<xml::element> ("initial-value-of", false);
+ set_region_id_attr (*result, *initial_sval->get_region ());
+ }
+ break;
+ case SK_UNARYOP:
+ {
+ const unaryop_svalue *unaryop_sval = (const unaryop_svalue *)sval;
+ result = std::make_unique<xml::element> ("unary-op", false);
+ result->set_attr ("op", get_tree_code_name (unaryop_sval->get_op ()));
+ result->add_child
+ (create_element_for_svalue (unaryop_sval->get_arg ()));
+ }
+ break;
+ case SK_BINOP:
+ {
+ const binop_svalue *binop_sval = (const binop_svalue *)sval;
+ result = std::make_unique<xml::element> ("binary-op", false);
+ result->set_attr ("op", get_tree_code_name (binop_sval->get_op ()));
+ result->add_child (create_element_for_svalue (binop_sval->get_arg0 ()));
+ result->add_child (create_element_for_svalue (binop_sval->get_arg1 ()));
+ }
+ break;
+ case SK_SUB:
+ {
+ //const sub_svalue *sub_sval = (const sub_svalue *)sval;
+ result = std::make_unique<xml::element> ("subregion-value", false);
+ // TODO
+ }
+ break;
+ case SK_REPEATED:
+ {
+ const repeated_svalue *repeated_sval = (const repeated_svalue *)sval;
+ result = std::make_unique<xml::element> ("repeated-value", false);
+ result->add_child
+ (create_element_for_svalue (repeated_sval->get_outer_size ()));
+ result->add_child
+ (create_element_for_svalue (repeated_sval->get_inner_svalue ()));
+ }
+ break;
+ case SK_BITS_WITHIN:
+ {
+ const bits_within_svalue *bits_within_sval
+ = (const bits_within_svalue *)sval;
+ result = std::make_unique<xml::element> ("bits-within", false);
+ set_bits_attr (*result, bits_within_sval->get_bits ());
+ result->add_child
+ (create_element_for_svalue (bits_within_sval->get_inner_svalue ()));
+ }
+ break;
+ case SK_UNMERGEABLE:
+ {
+ const unmergeable_svalue *unmergeable_sval
+ = (const unmergeable_svalue *)sval;
+ result = std::make_unique<xml::element> ("unmergeable", false);
+ result->add_child
+ (create_element_for_svalue (unmergeable_sval->get_arg ()));
+ }
+ break;
+ case SK_PLACEHOLDER:
+ {
+ const placeholder_svalue *placeholder_sval
+ = (const placeholder_svalue *)sval;
+ result = std::make_unique<xml::element> ("placeholder", false);
+ result->set_attr ("name", placeholder_sval->get_name ());
+ }
+ break;
+ case SK_WIDENING:
+ {
+ //const widening_svalue *widening_sval = (const widening_svalue *)sval;
+ result = std::make_unique<xml::element> ("iterating-value", false);
+ // TODO
+ }
+ break;
+ case SK_COMPOUND:
+ {
+ //const compound_svalue *compound_sval = (const compound_svalue *)sval;
+ result = std::make_unique<xml::element> ("compound-value", false);
+ // TODO
+ }
+ break;
+ case SK_CONJURED:
+ {
+ //const conjured_svalue *conjured_sval = (const conjured_svalue *)sval;
+ result = std::make_unique<xml::element> ("conjured-value", false);
+ // TODO
+ }
+ break;
+ case SK_ASM_OUTPUT:
+ {
+ /* const asm_output_svalue *asm_output_sval
+ = (const asm_output_svalue *)sval; */
+ result = std::make_unique<xml::element> ("asm-output", false);
+ // TODO
+ }
+ break;
+ case SK_CONST_FN_RESULT:
+ {
+ /* const const_fn_result_svalue *const_fn_result_sval
+ = (const const_fn_result_svalue *)sval; */
+ result = std::make_unique<xml::element> ("const-fn-result", false);
+ // TODO
+ }
+ }
+
+ if (result)
+ {
+ if (sval->get_type ())
+ set_type_attr (*result, sval->get_type ());
+
+ pretty_printer pp;
+ pp_format_decoder (&pp) = default_tree_printer;
+ sval->dump_to_pp (&pp, true);
+ result->set_attr ("dump-text", pp_formatted_text (&pp));
+ }
+
+ return result;
+}
+
+std::unique_ptr<xml::document>
+program_state::make_xml (const extrinsic_state &ext_state) const
+{
+ return std::make_unique<xml_state> (*this, ext_state);
+}
+
+void
+program_state::dump_xml_to_pp (const extrinsic_state &ext_state,
+ pretty_printer *pp) const
+{
+ auto doc = make_xml (ext_state);
+ doc->write_as_xml (pp, 0, true);
+}
+
+void
+program_state::dump_xml_to_file (const extrinsic_state &ext_state,
+ FILE *outf) const
+{
+ pretty_printer pp;
+ pp.set_output_stream (outf);
+ dump_xml_to_pp (ext_state, &pp);
+ pp_flush (&pp);
+}
+
+void
+program_state::dump_xml (const extrinsic_state &ext_state) const
+{
+ dump_xml_to_file (ext_state, stderr);
+}
+
+} // namespace ana
+
+#endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/ana-state-to-diagnostic-state.h b/gcc/analyzer/ana-state-to-diagnostic-state.h
new file mode 100644
index 0000000..bd6aa46
--- /dev/null
+++ b/gcc/analyzer/ana-state-to-diagnostic-state.h
@@ -0,0 +1,89 @@
+/* XML documents for dumping state in an easier-to-read form.
+ Copyright (C) 2025 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_ANA_STATE_TO_XML_STATE_H
+#define GCC_ANALYZER_ANA_STATE_TO_XML_STATE_H
+
+#include "xml.h"
+
+namespace ana {
+
+class xml_state : public xml::document
+{
+public:
+ xml_state (const program_state &state,
+ const extrinsic_state &ext_state);
+
+ xml::element &
+ get_or_create_element (const region &reg);
+
+private:
+ xml::element&
+ create_and_add_element (const region &reg);
+
+ static std::unique_ptr<xml::element>
+ make_memory_space_element (const char *label);
+
+ std::unique_ptr<xml::element>
+ create_element (const region &reg);
+
+ /* Spatially sorted concrete bindings. */
+ typedef std::map<bit_range, const svalue *> concrete_bindings_t;
+
+ void
+ create_elements_for_binding_cluster (const binding_cluster &cluster,
+ bool create_all);
+
+ std::unique_ptr<xml::element>
+ create_element_for_conc_bindings (const concrete_bindings_t &conc_bindings);
+
+ // Try to get the bit_range of REG within its base region
+ bool
+ get_bit_range_within_base_region (const region &reg,
+ bit_range &out);
+
+ void
+ populate_element_for_typed_region (xml::element &e,
+ const region &reg,
+ const concrete_bindings_t &conc_bindings,
+ bool create_all);
+
+ void
+ set_attr_for_dynamic_extents (const region &reg, xml::element &e);
+
+ bool
+ show_child_element_for_child_region_p (const region &reg,
+ const concrete_bindings_t &conc_bindings,
+ bool create_all);
+
+ std::unique_ptr<xml::element>
+ create_element_for_svalue (const svalue *sval);
+
+ const program_state &m_state;
+ const extrinsic_state &m_ext_state;
+ region_model_manager &m_mgr;
+ xml::element *m_root;
+ std::map<const region *, xml::element *> m_region_to_element_map;
+ std::map<const region *, tree> m_types_for_untyped_regions;
+};
+
+} // namespace ana
+
+#endif /* GCC_ANALYZER_ANA_STATE_TO_XML_STATE_H */
diff --git a/gcc/analyzer/analyzer-language.cc b/gcc/analyzer/analyzer-language.cc
index 9a25baf..d4169f7 100644
--- a/gcc/analyzer/analyzer-language.cc
+++ b/gcc/analyzer/analyzer-language.cc
@@ -114,7 +114,7 @@ on_finish_translation_unit (const translation_unit &tu)
return;
FILE *logfile = get_or_create_any_logfile ();
- log_user the_logger (NULL);
+ log_user the_logger (nullptr);
if (logfile)
the_logger.set_logger (new logger (logfile, 0, 0,
*global_dc->get_reference_printer ()));
diff --git a/gcc/analyzer/analyzer-language.h b/gcc/analyzer/analyzer-language.h
index 1987ee0..a0c85a8 100644
--- a/gcc/analyzer/analyzer-language.h
+++ b/gcc/analyzer/analyzer-language.h
@@ -35,7 +35,7 @@ class translation_unit
public:
/* Attempt to look up an value for identifier ID (e.g. in the headers that
have been seen). If it is defined and an integer (e.g. either as a
- macro or enum), return the INTEGER_CST value, otherwise return NULL. */
+ macro or enum), return the INTEGER_CST value, otherwise return NULL_TREE. */
virtual tree lookup_constant_by_id (tree id) const = 0;
virtual tree lookup_type_by_id (tree id) const = 0;
virtual tree lookup_global_var_by_id (tree id) const = 0;
diff --git a/gcc/analyzer/analyzer-logging.h b/gcc/analyzer/analyzer-logging.h
index 3208989..e85d293 100644
--- a/gcc/analyzer/analyzer-logging.h
+++ b/gcc/analyzer/analyzer-logging.h
@@ -91,7 +91,7 @@ public:
/* The constructor for log_scope.
- The normal case is that the logger is NULL, in which case this should
+ The normal case is that the logger is nullptr, in which case this should
be largely a no-op.
If we do have a logger, notify it that we're entering the given scope.
@@ -139,7 +139,8 @@ log_scope::~log_scope ()
}
}
-/* A log_user is something that potentially uses a logger (which could be NULL).
+/* A log_user is something that potentially uses a logger (which could be
+ nullptr).
The log_user class keeps the reference-count of a logger up-to-date. */
@@ -169,8 +170,8 @@ class log_user
FILE *get_logger_file () const
{
- if (m_logger == NULL)
- return NULL;
+ if (m_logger == nullptr)
+ return nullptr;
return m_logger->get_file ();
}
@@ -181,7 +182,7 @@ class log_user
};
/* A shortcut for calling log from a log_user, handling the common
- case where the underlying logger is NULL via a no-op. */
+ case where the underlying logger is nullptr via a no-op. */
inline void
log_user::log (const char *fmt, ...) const
@@ -196,7 +197,7 @@ log_user::log (const char *fmt, ...) const
}
/* A shortcut for starting a log line from a log_user,
- handling the common case where the underlying logger is NULL via
+ handling the common case where the underlying logger is nullptr via
a no-op. */
inline void
@@ -207,7 +208,7 @@ log_user::start_log_line () const
}
/* A shortcut for ending a log line from a log_user,
- handling the common case where the underlying logger is NULL via
+ handling the common case where the underlying logger is nullptr via
a no-op. */
inline void
@@ -218,7 +219,7 @@ log_user::end_log_line () const
}
/* A shortcut for recording entry into a scope from a log_user,
- handling the common case where the underlying logger is NULL via
+ handling the common case where the underlying logger is nullptr via
a no-op. */
inline void
@@ -229,7 +230,7 @@ log_user::enter_scope (const char *scope_name)
}
/* A shortcut for recording exit from a scope from a log_user,
- handling the common case where the underlying logger is NULL via
+ handling the common case where the underlying logger is nullptr via
a no-op. */
inline void
diff --git a/gcc/analyzer/analyzer-pass.cc b/gcc/analyzer/analyzer-pass.cc
index b3a0dfd..559fb94 100644
--- a/gcc/analyzer/analyzer-pass.cc
+++ b/gcc/analyzer/analyzer-pass.cc
@@ -48,15 +48,15 @@ class pass_analyzer : public ipa_opt_pass_d
public:
pass_analyzer(gcc::context *ctxt)
: ipa_opt_pass_d (pass_data_analyzer, ctxt,
- NULL, /* generate_summary */
- NULL, /* write_summary */
- NULL, /* read_summary */
- NULL, /* write_optimization_summary */
- NULL, /* read_optimization_summary */
- NULL, /* stmt_fixup */
+ nullptr, /* generate_summary */
+ nullptr, /* write_summary */
+ nullptr, /* read_summary */
+ nullptr, /* write_optimization_summary */
+ nullptr, /* read_optimization_summary */
+ nullptr, /* stmt_fixup */
0, /* function_transform_todo_flags_start */
- NULL, /* function_transform */
- NULL) /* variable_transform */
+ nullptr, /* function_transform */
+ nullptr) /* variable_transform */
{}
/* opt_pass methods: */
diff --git a/gcc/analyzer/analyzer.cc b/gcc/analyzer/analyzer.cc
index 56cb370..938ad6d 100644
--- a/gcc/analyzer/analyzer.cc
+++ b/gcc/analyzer/analyzer.cc
@@ -518,7 +518,7 @@ make_label_text (bool can_colorize, const char *fmt, ...)
va_start (ap, fmt);
- text_info ti (_(fmt), &ap, 0, NULL, &rich_loc);
+ text_info ti (_(fmt), &ap, 0, nullptr, &rich_loc);
pp_format (pp.get (), &ti);
pp_output_formatted_text (pp.get ());
@@ -549,7 +549,7 @@ make_label_text_n (bool can_colorize, unsigned HOST_WIDE_INT n,
const char *fmt = ngettext (singular_fmt, plural_fmt, n);
- text_info ti (fmt, &ap, 0, NULL, &rich_loc);
+ text_info ti (fmt, &ap, 0, nullptr, &rich_loc);
pp_format (pp.get (), &ti);
pp_output_formatted_text (pp.get ());
diff --git a/gcc/analyzer/bounds-checking.cc b/gcc/analyzer/bounds-checking.cc
index a3b1345..d2e2b34 100644
--- a/gcc/analyzer/bounds-checking.cc
+++ b/gcc/analyzer/bounds-checking.cc
@@ -507,7 +507,7 @@ public:
concrete_buffer_over_read (const region_model &model,
const region *reg, tree diag_arg,
bit_range range, tree bit_bound)
- : concrete_past_the_end (model, reg, diag_arg, range, bit_bound, NULL)
+ : concrete_past_the_end (model, reg, diag_arg, range, bit_bound, nullptr)
{}
const char *get_kind () const final override
@@ -819,7 +819,7 @@ public:
concrete_buffer_under_read (const region_model &model,
const region *reg, tree diag_arg,
bit_range range)
- : concrete_out_of_bounds (model, reg, diag_arg, range, NULL)
+ : concrete_out_of_bounds (model, reg, diag_arg, range, nullptr)
{}
const char *get_kind () const final override
@@ -1119,7 +1119,7 @@ public:
const region *reg, tree diag_arg, tree offset,
tree num_bytes, tree capacity)
: symbolic_past_the_end (model, reg, diag_arg, offset, num_bytes, capacity,
- NULL)
+ nullptr)
{
}
diff --git a/gcc/analyzer/call-details.cc b/gcc/analyzer/call-details.cc
index bca8658..cb95843 100644
--- a/gcc/analyzer/call-details.cc
+++ b/gcc/analyzer/call-details.cc
@@ -43,7 +43,7 @@ namespace ana {
call_details::call_details (const gcall &call, region_model *model,
region_model_context *ctxt)
: m_call (call), m_model (model), m_ctxt (ctxt),
- m_lhs_type (NULL_TREE), m_lhs_region (NULL)
+ m_lhs_type (NULL_TREE), m_lhs_region (nullptr)
{
m_lhs_type = NULL_TREE;
if (tree lhs = gimple_call_lhs (&call))
@@ -81,7 +81,7 @@ call_details::get_logger () const
if (m_ctxt)
return m_ctxt->get_logger ();
else
- return NULL;
+ return nullptr;
}
/* Get any uncertainty_t associated with the region_model_context. */
@@ -92,7 +92,7 @@ call_details::get_uncertainty () const
if (m_ctxt)
return m_ctxt->get_uncertainty ();
else
- return NULL;
+ return nullptr;
}
/* If the callsite has a left-hand-side region, set it to RESULT
@@ -127,25 +127,25 @@ const_fn_p (const call_details &cd)
/* If this CD is known to be a call to a function with
__attribute__((const)), attempt to get a const_fn_result_svalue
- based on the arguments, or return NULL otherwise. */
+ based on the arguments, or return nullptr otherwise. */
static const svalue *
maybe_get_const_fn_result (const call_details &cd)
{
if (!const_fn_p (cd))
- return NULL;
+ return nullptr;
unsigned num_args = cd.num_args ();
if (num_args > const_fn_result_svalue::MAX_INPUTS)
/* Too many arguments. */
- return NULL;
+ return nullptr;
auto_vec<const svalue *> inputs (num_args);
for (unsigned arg_idx = 0; arg_idx < num_args; arg_idx++)
{
const svalue *arg_sval = cd.get_arg_svalue (arg_idx);
if (!arg_sval->can_have_associated_state_p ())
- return NULL;
+ return nullptr;
inputs.quick_push (arg_sval);
}
@@ -222,8 +222,8 @@ call_details::set_any_lhs_with_defaults () const
if (lookup_function_attribute ("malloc"))
{
const region *new_reg
- = m_model->get_or_create_region_for_heap_alloc (NULL, m_ctxt);
- m_model->mark_region_as_unknown (new_reg, NULL);
+ = m_model->get_or_create_region_for_heap_alloc (nullptr, m_ctxt);
+ m_model->mark_region_as_unknown (new_reg, nullptr);
sval = mgr->get_ptr_svalue (get_lhs_type (), new_reg);
}
else
@@ -292,7 +292,7 @@ call_details::get_arg_svalue (unsigned idx) const
/* If argument IDX's svalue at the callsite is of pointer type,
return the region it points to.
- Otherwise return NULL. */
+ Otherwise return nullptr. */
const region *
call_details::deref_ptr_arg (unsigned idx) const
@@ -301,7 +301,7 @@ call_details::deref_ptr_arg (unsigned idx) const
return m_model->deref_rvalue (ptr_sval, get_arg_tree (idx), m_ctxt);
}
-/* Attempt to get the string literal for argument IDX, or return NULL
+/* Attempt to get the string literal for argument IDX, or return nullptr
otherwise.
For use when implementing "__analyzer_*" functions that take
string literals. */
@@ -316,7 +316,7 @@ call_details::get_arg_string_literal (unsigned idx) const
tree string_cst = string_reg->get_string_cst ();
return TREE_STRING_POINTER (string_cst);
}
- return NULL;
+ return nullptr;
}
/* Attempt to get the fndecl used at this call, if known, or NULL_TREE
diff --git a/gcc/analyzer/call-string.cc b/gcc/analyzer/call-string.cc
index afa8004..0bac8b4 100644
--- a/gcc/analyzer/call-string.cc
+++ b/gcc/analyzer/call-string.cc
@@ -223,22 +223,22 @@ call_string::cmp_ptr_ptr (const void *pa, const void *pb)
}
/* Return the pointer to callee of the topmost call in the stack,
- or NULL if stack is empty. */
+ or nullptr if stack is empty. */
const supernode *
call_string::get_callee_node () const
{
if(m_elements.is_empty ())
- return NULL;
+ return nullptr;
return m_elements[m_elements.length () - 1].m_callee;
}
/* Return the pointer to caller of the topmost call in the stack,
- or NULL if stack is empty. */
+ or nullptr if stack is empty. */
const supernode *
call_string::get_caller_node () const
{
if(m_elements.is_empty ())
- return NULL;
+ return nullptr;
return m_elements[m_elements.length () - 1].m_caller;
}
@@ -266,7 +266,7 @@ call_string::validate () const
/* ctor for the root/empty call_string. */
call_string::call_string ()
-: m_parent (NULL), m_elements ()
+: m_parent (nullptr), m_elements ()
{
}
diff --git a/gcc/analyzer/call-string.h b/gcc/analyzer/call-string.h
index 642cf76..f8c6a25 100644
--- a/gcc/analyzer/call-string.h
+++ b/gcc/analyzer/call-string.h
@@ -129,12 +129,12 @@ private:
}
template <typename T> static inline void remove (T &entry)
{
- entry.m_key = element_t (NULL, NULL);
+ entry.m_key = element_t (nullptr, nullptr);
}
static const bool empty_zero_p = true;
template <typename T> static inline bool is_empty (const T &entry)
{
- return entry.m_key.m_caller == NULL;
+ return entry.m_key.m_caller == nullptr;
}
template <typename T> static inline bool is_deleted (const T &entry)
{
@@ -142,8 +142,8 @@ private:
}
template <typename T> static inline void mark_empty (T &entry)
{
- entry.m_key = element_t (NULL, NULL);
- entry.m_value = NULL;
+ entry.m_key = element_t (nullptr, nullptr);
+ entry.m_value = nullptr;
}
template <typename T> static inline void mark_deleted (T &entry)
{
diff --git a/gcc/analyzer/call-summary.cc b/gcc/analyzer/call-summary.cc
index 33de3d6..a094cba 100644
--- a/gcc/analyzer/call-summary.cc
+++ b/gcc/analyzer/call-summary.cc
@@ -71,9 +71,9 @@ call_summary::get_user_facing_desc (pretty_printer *pp) const
if (tree result = DECL_RESULT (fndecl))
{
const region *result_reg
- = get_state ().m_region_model->get_lvalue (result, NULL);
+ = get_state ().m_region_model->get_lvalue (result, nullptr);
const svalue *result_sval
- = get_state ().m_region_model->get_store_value (result_reg, NULL);
+ = get_state ().m_region_model->get_store_value (result_reg, nullptr);
switch (result_sval->get_kind ())
{
default:
@@ -172,7 +172,7 @@ call_summary_replay::call_summary_replay (const call_details &cd,
This will be a top-level frame, since that's what's in
the summary. */
const frame_region *summary_frame
- = mgr->get_frame_region (NULL, called_fn);
+ = mgr->get_frame_region (nullptr, called_fn);
unsigned idx = 0;
for (tree iter_parm = DECL_ARGUMENTS (fndecl); iter_parm;
@@ -210,7 +210,7 @@ call_summary_replay::call_summary_replay (const call_details &cd,
/* Try to convert SUMMARY_SVAL in the summary to a corresponding svalue
in the caller, caching the result.
- Return NULL if the conversion is not possible. */
+ Return nullptr if the conversion is not possible. */
const svalue *
call_summary_replay::convert_svalue_from_summary (const svalue *summary_sval)
@@ -252,7 +252,7 @@ call_summary_replay::convert_svalue_from_summary_1 (const svalue *summary_sval)
const region *summary_reg = region_summary_sval->get_pointee ();
const region *caller_reg = convert_region_from_summary (summary_reg);
if (!caller_reg)
- return NULL;
+ return nullptr;
region_model_manager *mgr = get_manager ();
const svalue *caller_ptr
= mgr->get_ptr_svalue (summary_sval->get_type (),
@@ -268,7 +268,7 @@ call_summary_replay::convert_svalue_from_summary_1 (const svalue *summary_sval)
return summary_sval;
case SK_SETJMP:
- return NULL; // TODO
+ return nullptr; // TODO
case SK_INITIAL:
{
@@ -282,7 +282,7 @@ call_summary_replay::convert_svalue_from_summary_1 (const svalue *summary_sval)
const region *summary_reg = initial_summary_sval->get_region ();
const region *caller_reg = convert_region_from_summary (summary_reg);
if (!caller_reg)
- return NULL;
+ return nullptr;
const svalue *caller_sval
= m_cd.get_model ()->get_store_value (caller_reg, m_cd.get_ctxt ());
return caller_sval;
@@ -295,7 +295,7 @@ call_summary_replay::convert_svalue_from_summary_1 (const svalue *summary_sval)
const svalue *summary_arg = unaryop_summary_sval->get_arg ();
const svalue *caller_arg = convert_svalue_from_summary (summary_arg);
if (!caller_arg)
- return NULL;
+ return nullptr;
region_model_manager *mgr = get_manager ();
return mgr->get_or_create_unaryop (summary_sval->get_type (),
unaryop_summary_sval->get_op (),
@@ -309,11 +309,11 @@ call_summary_replay::convert_svalue_from_summary_1 (const svalue *summary_sval)
const svalue *summary_arg0 = binop_summary_sval->get_arg0 ();
const svalue *caller_arg0 = convert_svalue_from_summary (summary_arg0);
if (!caller_arg0)
- return NULL;
+ return nullptr;
const svalue *summary_arg1 = binop_summary_sval->get_arg1 ();
const svalue *caller_arg1 = convert_svalue_from_summary (summary_arg1);
if (!caller_arg1)
- return NULL;
+ return nullptr;
region_model_manager *mgr = get_manager ();
return mgr->get_or_create_binop (summary_sval->get_type (),
binop_summary_sval->get_op (),
@@ -328,10 +328,10 @@ call_summary_replay::convert_svalue_from_summary_1 (const svalue *summary_sval)
region_model_manager *mgr = get_manager ();
const svalue *summary_parent_sval = sub_summary_sval->get_parent ();
if (!summary_parent_sval)
- return NULL;
+ return nullptr;
const region *summary_subregion = sub_summary_sval->get_subregion ();
if (!summary_subregion)
- return NULL;
+ return nullptr;
return mgr->get_or_create_sub_svalue (summary_sval->get_type (),
summary_parent_sval,
summary_subregion);
@@ -346,13 +346,13 @@ call_summary_replay::convert_svalue_from_summary_1 (const svalue *summary_sval)
const svalue *caller_outer_size
= convert_svalue_from_summary (summary_outer_size);
if (!caller_outer_size)
- return NULL;
+ return nullptr;
const svalue *summary_inner_sval
= repeated_summary_sval->get_inner_svalue ();
const svalue *caller_inner_sval
= convert_svalue_from_summary (summary_inner_sval);
if (!caller_inner_sval)
- return NULL;
+ return nullptr;
region_model_manager *mgr = get_manager ();
return mgr->get_or_create_repeated_svalue (summary_sval->get_type (),
caller_outer_size,
@@ -369,7 +369,7 @@ call_summary_replay::convert_svalue_from_summary_1 (const svalue *summary_sval)
const svalue *caller_inner_sval
= convert_svalue_from_summary (summary_inner_sval);
if (!caller_inner_sval)
- return NULL;
+ return nullptr;
region_model_manager *mgr = get_manager ();
return mgr->get_or_create_bits_within (summary_sval->get_type (),
bits,
@@ -384,7 +384,7 @@ call_summary_replay::convert_svalue_from_summary_1 (const svalue *summary_sval)
const svalue *caller_arg_sval
= convert_svalue_from_summary (summary_arg_sval);
if (!caller_arg_sval)
- return NULL;
+ return nullptr;
region_model_manager *mgr = get_manager ();
return mgr->get_or_create_unmergeable (caller_arg_sval);
}
@@ -400,14 +400,14 @@ call_summary_replay::convert_svalue_from_summary_1 (const svalue *summary_sval)
= convert_svalue_from_summary (summary_base_sval);
if (!(caller_base_sval
&& caller_base_sval->can_have_associated_state_p ()))
- return NULL;
+ return nullptr;
const svalue *summary_iter_sval
= widening_summary_sval->get_iter_svalue ();
const svalue *caller_iter_sval
= convert_svalue_from_summary (summary_iter_sval);
if (!(caller_iter_sval
&& caller_iter_sval->can_have_associated_state_p ()))
- return NULL;
+ return nullptr;
region_model_manager *mgr = get_manager ();
return mgr->get_or_create_widening_svalue
(summary_iter_sval->get_type (),
@@ -491,7 +491,7 @@ call_summary_replay::convert_svalue_from_summary_1 (const svalue *summary_sval)
const svalue *caller_input
= convert_svalue_from_summary (summary_input);
if (!caller_input)
- return NULL;
+ return nullptr;
inputs.safe_push (caller_input);
}
region_model_manager *mgr = get_manager ();
@@ -516,7 +516,7 @@ call_summary_replay::convert_svalue_from_summary_1 (const svalue *summary_sval)
const svalue *caller_input
= convert_svalue_from_summary (summary_input);
if (!caller_input)
- return NULL;
+ return nullptr;
inputs.safe_push (caller_input);
}
region_model_manager *mgr = get_manager ();
@@ -532,7 +532,7 @@ call_summary_replay::convert_svalue_from_summary_1 (const svalue *summary_sval)
/* Try to convert SUMMARY_REG in the summary to a corresponding region
in the caller, caching the result.
- Return NULL if the conversion is not possible. */
+ Return nullptr if the conversion is not possible. */
const region *
call_summary_replay::convert_region_from_summary (const region *summary_reg)
@@ -596,7 +596,7 @@ call_summary_replay::convert_region_from_summary_1 (const region *summary_reg)
const svalue *caller_ptr_sval
= convert_svalue_from_summary (summary_ptr_sval);
if (!caller_ptr_sval)
- return NULL;
+ return nullptr;
const region *caller_reg
= get_caller_model ()->deref_rvalue (caller_ptr_sval,
NULL_TREE,
@@ -619,7 +619,7 @@ call_summary_replay::convert_region_from_summary_1 (const region *summary_reg)
case SSA_NAME:
/* We don't care about writes to locals within
the summary. */
- return NULL;
+ return nullptr;
case VAR_DECL:
/* We don't care about writes to locals within
the summary. */
@@ -628,12 +628,12 @@ call_summary_replay::convert_region_from_summary_1 (const region *summary_reg)
return summary_reg;
else
/* Otherwise, we don't care about locals. */
- return NULL;
+ return nullptr;
case RESULT_DECL:
return m_cd.get_lhs_region ();
case PARM_DECL:
/* Writes (by value) to parms should be visible to the caller. */
- return NULL;
+ return nullptr;
}
}
break;
@@ -645,7 +645,7 @@ call_summary_replay::convert_region_from_summary_1 (const region *summary_reg)
const region *caller_parent_reg
= convert_region_from_summary (summary_parent_reg);
if (!caller_parent_reg)
- return NULL;
+ return nullptr;
tree field = summary_field_reg->get_field ();
return mgr->get_field_region (caller_parent_reg, field);
}
@@ -658,12 +658,12 @@ call_summary_replay::convert_region_from_summary_1 (const region *summary_reg)
const region *caller_parent_reg
= convert_region_from_summary (summary_parent_reg);
if (!caller_parent_reg)
- return NULL;
+ return nullptr;
const svalue *summary_index = summary_element_reg->get_index ();
const svalue *caller_index
= convert_svalue_from_summary (summary_index);
if (!caller_index)
- return NULL;
+ return nullptr;
return mgr->get_element_region (caller_parent_reg,
summary_reg->get_type (),
caller_index);
@@ -677,13 +677,13 @@ call_summary_replay::convert_region_from_summary_1 (const region *summary_reg)
const region *caller_parent_reg
= convert_region_from_summary (summary_parent_reg);
if (!caller_parent_reg)
- return NULL;
+ return nullptr;
const svalue *summary_byte_offset
= summary_offset_reg->get_byte_offset ();
const svalue *caller_byte_offset
= convert_svalue_from_summary (summary_byte_offset);
if (!caller_byte_offset)
- return NULL;
+ return nullptr;
return mgr->get_offset_region (caller_parent_reg,
summary_reg->get_type (),
caller_byte_offset);
@@ -697,13 +697,13 @@ call_summary_replay::convert_region_from_summary_1 (const region *summary_reg)
const region *caller_parent_reg
= convert_region_from_summary (summary_parent_reg);
if (!caller_parent_reg)
- return NULL;
+ return nullptr;
const svalue *summary_byte_size
= summary_sized_reg->get_byte_size_sval (mgr);
const svalue *caller_byte_size
= convert_svalue_from_summary (summary_byte_size);
if (!caller_byte_size)
- return NULL;
+ return nullptr;
return mgr->get_sized_region (caller_parent_reg,
summary_reg->get_type (),
caller_byte_size);
@@ -715,7 +715,7 @@ call_summary_replay::convert_region_from_summary_1 (const region *summary_reg)
const region *caller_parent_reg
= convert_region_from_summary (summary_parent_reg);
if (!caller_parent_reg)
- return NULL;
+ return nullptr;
return mgr->get_cast_region (caller_parent_reg,
summary_reg->get_type ());
}
@@ -731,7 +731,7 @@ call_summary_replay::convert_region_from_summary_1 (const region *summary_reg)
}
break;
case RK_ALLOCA:
- return NULL;
+ return nullptr;
case RK_BIT_RANGE:
{
const bit_range_region *summary_bit_range_reg
@@ -740,7 +740,7 @@ call_summary_replay::convert_region_from_summary_1 (const region *summary_reg)
const region *caller_parent_reg
= convert_region_from_summary (summary_parent_reg);
if (!caller_parent_reg)
- return NULL;
+ return nullptr;
const bit_range &bits = summary_bit_range_reg->get_bits ();
return mgr->get_bit_range (caller_parent_reg,
summary_reg->get_type (),
@@ -748,14 +748,14 @@ call_summary_replay::convert_region_from_summary_1 (const region *summary_reg)
}
break;
case RK_VAR_ARG:
- return NULL;
+ return nullptr;
}
}
/* Try to convert SUMMARY_KEY in the summary to a corresponding binding key
in the caller.
- Return NULL if the conversion is not possible. */
+ Return nullptr if the conversion is not possible. */
const binding_key *
call_summary_replay::convert_key_from_summary (const binding_key *summary_key)
@@ -767,7 +767,7 @@ call_summary_replay::convert_key_from_summary (const binding_key *summary_key)
const region *summary_reg = symbolic_key->get_region ();
const region *caller_reg = convert_region_from_summary (summary_reg);
if (!caller_reg)
- return NULL;
+ return nullptr;
region_model_manager *mgr = get_manager ();
store_manager *store_mgr = mgr->get_store_manager ();
return store_mgr->get_symbolic_binding (caller_reg);
@@ -780,7 +780,7 @@ call_summary_replay::add_svalue_mapping (const svalue *summary_sval,
const svalue *caller_sval)
{
gcc_assert (summary_sval);
- // CALLER_SVAL can be NULL
+ // CALLER_SVAL can be nullptr
m_map_svalue_from_summary_to_caller.put (summary_sval, caller_sval);
}
@@ -791,7 +791,7 @@ call_summary_replay::add_region_mapping (const region *summary_reg,
const region *caller_reg)
{
gcc_assert (summary_reg);
- // CALLER_REG can be NULL
+ // CALLER_REG can be nullptr
m_map_region_from_summary_to_caller.put (summary_reg, caller_reg);
}
diff --git a/gcc/analyzer/checker-event.cc b/gcc/analyzer/checker-event.cc
index e041778..af336df 100644
--- a/gcc/analyzer/checker-event.cc
+++ b/gcc/analyzer/checker-event.cc
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see
#include "inlining-iterator.h"
#include "tree-logical-location.h"
#include "diagnostic-format-sarif.h"
+#include "xml.h"
#include "analyzer/analyzer-logging.h"
#include "analyzer/sm.h"
@@ -106,12 +107,13 @@ event_kind_to_string (enum event_kind ek)
checker_event::checker_event (enum event_kind kind,
const event_loc_info &loc_info)
-: m_kind (kind), m_loc (loc_info.m_loc),
+: m_path (nullptr),
+ m_kind (kind), m_loc (loc_info.m_loc),
m_original_fndecl (loc_info.m_fndecl),
m_effective_fndecl (loc_info.m_fndecl),
m_original_depth (loc_info.m_depth),
m_effective_depth (loc_info.m_depth),
- m_pending_diagnostic (NULL), m_emission_id (),
+ m_pending_diagnostic (nullptr), m_emission_id (),
m_logical_loc
(tree_logical_location_manager::key_from_tree (loc_info.m_fndecl))
{
@@ -211,10 +213,11 @@ checker_event::debug () const
pertinent data within the sm-state). */
void
-checker_event::prepare_for_emission (checker_path *,
+checker_event::prepare_for_emission (checker_path *path,
pending_diagnostic *pd,
diagnostic_event_id_t emission_id)
{
+ m_path = path;
m_pending_diagnostic = pd;
m_emission_id = emission_id;
@@ -222,6 +225,29 @@ checker_event::prepare_for_emission (checker_path *,
print_desc (*pp.get ());
}
+std::unique_ptr<xml::document>
+checker_event::maybe_make_xml_state (bool debug) const
+{
+ const program_state *state = get_program_state ();
+ if (!state)
+ return nullptr;
+
+ gcc_assert (m_path);
+ const extrinsic_state &ext_state = m_path->get_ext_state ();
+
+ auto result = state->make_xml (ext_state);
+
+ if (debug)
+ {
+ pretty_printer pp;
+ text_art::theme *theme = global_dc->get_diagram_theme ();
+ text_art::dump_to_pp (*state, theme, &pp);
+ result->add_comment (pp_formatted_text (&pp));
+ }
+
+ return result;
+}
+
/* class debug_event : public checker_event. */
/* Implementation of diagnostic_event::print_desc vfunc for
@@ -344,12 +370,14 @@ region_creation_event_debug::print_desc (pretty_printer &pp) const
/* class function_entry_event : public checker_event. */
-function_entry_event::function_entry_event (const program_point &dst_point)
+function_entry_event::function_entry_event (const program_point &dst_point,
+ const program_state &state)
: checker_event (event_kind::function_entry,
event_loc_info (dst_point.get_supernode
()->get_start_location (),
dst_point.get_fndecl (),
- dst_point.get_stack_depth ()))
+ dst_point.get_stack_depth ())),
+ m_state (state)
{
}
@@ -370,7 +398,7 @@ function_entry_event::print_desc (pretty_printer &pp) const
diagnostic_event::meaning
function_entry_event::get_meaning () const
{
- return meaning (VERB_enter, NOUN_function);
+ return meaning (verb::enter, noun::function);
}
/* class state_change_event : public checker_event. */
@@ -470,7 +498,7 @@ state_change_event::print_desc (pretty_printer &pp) const
}
else
{
- gcc_assert (m_origin == NULL);
+ gcc_assert (m_origin == nullptr);
pp_printf (&pp,
"global state: %qs -> %qs",
m_from->get_name (),
@@ -557,6 +585,12 @@ superedge_event::should_filter_p (int verbosity) const
return false;
}
+const program_state *
+superedge_event::get_program_state () const
+{
+ return &m_eedge.m_dest->get_state ();
+}
+
/* superedge_event's ctor. */
superedge_event::superedge_event (enum event_kind kind,
@@ -598,9 +632,9 @@ cfg_edge_event::get_meaning () const
{
const cfg_superedge& cfg_sedge = get_cfg_superedge ();
if (cfg_sedge.true_value_p ())
- return meaning (VERB_branch, PROPERTY_true);
+ return meaning (verb::branch, property::true_);
else if (cfg_sedge.false_value_p ())
- return meaning (VERB_branch, PROPERTY_false);
+ return meaning (verb::branch, property::false_);
else
return meaning ();
}
@@ -710,7 +744,7 @@ start_cfg_edge_event::maybe_describe_condition (bool can_colorize) const
lhs, op, rhs);
}
}
- return label_text::borrow (NULL);
+ return label_text::borrow (nullptr);
}
/* Subroutine of maybe_describe_condition above.
@@ -747,9 +781,9 @@ start_cfg_edge_event::maybe_describe_condition (bool can_colorize,
/* Only attempt to generate text for sufficiently simple expressions. */
if (!should_print_expr_p (lhs))
- return label_text::borrow (NULL);
+ return label_text::borrow (nullptr);
if (!should_print_expr_p (rhs))
- return label_text::borrow (NULL);
+ return label_text::borrow (nullptr);
/* Special cases for pointer comparisons against NULL. */
if (POINTER_TYPE_P (TREE_TYPE (lhs))
@@ -846,7 +880,7 @@ call_event::print_desc (pretty_printer &pp) const
diagnostic_event::meaning
call_event::get_meaning () const
{
- return meaning (VERB_call, NOUN_function);
+ return meaning (verb::call, noun::function);
}
/* Override of checker_event::is_call_p for calls. */
@@ -869,6 +903,14 @@ call_event::get_callee_fndecl () const
return m_dest_snode->m_fun->decl;
}
+const program_state *
+call_event::get_program_state () const
+{
+ /* Use the state at the source (at the caller),
+ rather than the one at the dest, which has a frame for the callee. */
+ return &m_eedge.m_src->get_state ();
+}
+
/* class return_event : public superedge_event. */
/* return_event's ctor. */
@@ -922,7 +964,7 @@ return_event::print_desc (pretty_printer &pp) const
diagnostic_event::meaning
return_event::get_meaning () const
{
- return meaning (VERB_return, NOUN_function);
+ return meaning (verb::return_, noun::function);
}
/* Override of checker_event::is_return_p for returns. */
@@ -949,8 +991,8 @@ start_consolidated_cfg_edges_event::print_desc (pretty_printer &pp) const
diagnostic_event::meaning
start_consolidated_cfg_edges_event::get_meaning () const
{
- return meaning (VERB_branch,
- (m_edge_sense ? PROPERTY_true : PROPERTY_false));
+ return meaning (verb::branch,
+ (m_edge_sense ? property::true_ : property::false_));
}
/* class inlined_call_event : public checker_event. */
@@ -970,7 +1012,7 @@ inlined_call_event::print_desc (pretty_printer &pp) const
diagnostic_event::meaning
inlined_call_event::get_meaning () const
{
- return meaning (VERB_call, NOUN_function);
+ return meaning (verb::call, noun::function);
}
/* class setjmp_event : public checker_event. */
@@ -1210,7 +1252,16 @@ warning_event::print_desc (pretty_printer &pp) const
diagnostic_event::meaning
warning_event::get_meaning () const
{
- return meaning (VERB_danger, NOUN_unknown);
+ return meaning (verb::danger, noun::unknown);
+}
+
+const program_state *
+warning_event::get_program_state () const
+{
+ if (m_program_state)
+ return m_program_state.get ();
+ else
+ return &m_enode->get_state ();
}
} // namespace ana
diff --git a/gcc/analyzer/checker-event.h b/gcc/analyzer/checker-event.h
index 2f26b8d..7c44f1e 100644
--- a/gcc/analyzer/checker-event.h
+++ b/gcc/analyzer/checker-event.h
@@ -116,6 +116,7 @@ public:
sarif_object &thread_flow_loc_obj) const override;
/* Additional functionality. */
+ enum event_kind get_kind () const { return m_kind; }
tree get_fndecl () const { return m_effective_fndecl; }
int get_original_stack_depth () const { return m_original_depth; }
@@ -127,6 +128,12 @@ public:
virtual bool is_function_entry_p () const { return false; }
virtual bool is_return_p () const { return false; }
+ virtual const program_state *
+ get_program_state () const { return nullptr; }
+
+ std::unique_ptr<xml::document>
+ maybe_make_xml_state (bool debug) const final override;
+
/* For use with %@. */
const diagnostic_event_id_t *get_id_ptr () const
{
@@ -142,7 +149,8 @@ protected:
checker_event (enum event_kind kind,
const event_loc_info &loc_info);
- public:
+ private:
+ const checker_path *m_path;
const enum event_kind m_kind;
protected:
location_t m_loc;
@@ -224,6 +232,12 @@ public:
void print_desc (pretty_printer &) const final override;
+ const program_state *
+ get_program_state () const final override
+ {
+ return &m_dst_state;
+ }
+
const gimple * const m_stmt;
const program_state m_dst_state;
};
@@ -334,17 +348,29 @@ private:
class function_entry_event : public checker_event
{
public:
- function_entry_event (const event_loc_info &loc_info)
- : checker_event (event_kind::function_entry, loc_info)
+ function_entry_event (const event_loc_info &loc_info,
+ const program_state &state)
+ : checker_event (event_kind::function_entry, loc_info),
+ m_state (state)
{
}
- function_entry_event (const program_point &dst_point);
+ function_entry_event (const program_point &dst_point,
+ const program_state &state);
void print_desc (pretty_printer &pp) const override;
meaning get_meaning () const override;
bool is_function_entry_p () const final override { return true; }
+
+ const program_state *
+ get_program_state () const final override
+ {
+ return &m_state;
+ }
+
+private:
+ const program_state &m_state;
};
/* Subclass of checker_event describing a state change. */
@@ -365,6 +391,12 @@ public:
void print_desc (pretty_printer &pp) const final override;
meaning get_meaning () const override;
+ const program_state *
+ get_program_state () const final override
+ {
+ return &m_dst_state;
+ }
+
const function *get_dest_function () const
{
return m_dst_state.get_current_function ();
@@ -407,6 +439,9 @@ public:
bool should_filter_p (int verbosity) const;
+ const program_state *
+ get_program_state () const override;
+
protected:
superedge_event (enum event_kind kind, const exploded_edge &eedge,
const event_loc_info &loc_info);
@@ -517,6 +552,9 @@ public:
bool is_call_p () const final override;
+ const program_state *
+ get_program_state () const final override;
+
protected:
tree get_caller_fndecl () const;
tree get_callee_fndecl () const;
@@ -791,16 +829,22 @@ public:
warning_event (const event_loc_info &loc_info,
const exploded_node *enode,
const state_machine *sm,
- tree var, state_machine::state_t state)
+ tree var, state_machine::state_t state,
+ const program_state *program_state_ = nullptr)
: checker_event (event_kind::warning, loc_info),
m_enode (enode),
m_sm (sm), m_var (var), m_state (state)
{
+ if (program_state_)
+ m_program_state = std::make_unique<program_state> (*program_state_);
}
void print_desc (pretty_printer &pp) const final override;
meaning get_meaning () const override;
+ const program_state *
+ get_program_state () const final override;
+
const exploded_node *get_exploded_node () const { return m_enode; }
private:
@@ -808,6 +852,9 @@ private:
const state_machine *m_sm;
tree m_var;
state_machine::state_t m_state;
+ /* Optional copy of program state, for when this is different from
+ m_enode's state: */
+ std::unique_ptr<program_state> m_program_state;
};
} // namespace ana
diff --git a/gcc/analyzer/checker-path.cc b/gcc/analyzer/checker-path.cc
index 9bde6f2..45593e0 100644
--- a/gcc/analyzer/checker-path.cc
+++ b/gcc/analyzer/checker-path.cc
@@ -89,7 +89,7 @@ checker_path::maybe_log (logger *logger, const char *desc) const
{
logger->start_log_line ();
logger->log_partial ("%s[%i]: %s ", desc, i,
- event_kind_to_string (m_events[i]->m_kind));
+ event_kind_to_string (m_events[i]->get_kind ()));
m_events[i]->dump (logger->get_printer ());
logger->end_log_line ();
}
@@ -103,7 +103,7 @@ checker_path::add_event (std::unique_ptr<checker_event> event)
m_logger->start_log_line ();
m_logger->log_partial ("added event[%i]: %s ",
m_events.length (),
- event_kind_to_string (event.get ()->m_kind));
+ event_kind_to_string (event.get ()->get_kind ()));
event.get ()->dump (m_logger->get_printer ());
m_logger->end_log_line ();
}
@@ -123,7 +123,7 @@ checker_path::debug () const
fprintf (stderr,
"[%i]: %s \"%s\"\n",
i,
- event_kind_to_string (m_events[i]->m_kind),
+ event_kind_to_string (m_events[i]->get_kind ()),
event_desc.get ());
}
}
@@ -167,8 +167,8 @@ checker_path::cfg_edge_pair_at_p (unsigned idx) const
{
if (m_events.length () < idx + 1)
return false;
- return (m_events[idx]->m_kind == event_kind::start_cfg_edge
- && m_events[idx + 1]->m_kind == event_kind::end_cfg_edge);
+ return (m_events[idx]->get_kind () == event_kind::start_cfg_edge
+ && m_events[idx + 1]->get_kind () == event_kind::end_cfg_edge);
}
/* Consider a call from "outer" to "middle" which calls "inner",
@@ -254,7 +254,7 @@ checker_path::inject_any_inlined_call_events (logger *logger)
{
logger->start_log_line ();
logger->log_partial ("event[%i]: %s ", ev_idx,
- event_kind_to_string (curr_event->m_kind));
+ event_kind_to_string (curr_event->get_kind ()));
curr_event->dump (logger->get_printer ());
logger->end_log_line ();
for (inlining_iterator iter (curr_event->get_location ());
diff --git a/gcc/analyzer/checker-path.h b/gcc/analyzer/checker-path.h
index 80c975c..3c174bf 100644
--- a/gcc/analyzer/checker-path.h
+++ b/gcc/analyzer/checker-path.h
@@ -32,8 +32,10 @@ class checker_path : public diagnostic_path
{
public:
checker_path (const logical_location_manager &logical_loc_mgr,
+ const extrinsic_state &ext_state,
logger *logger)
: diagnostic_path (logical_loc_mgr),
+ m_ext_state (ext_state),
m_thread ("main"),
m_logger (logger)
{}
@@ -59,6 +61,8 @@ public:
return m_thread;
}
+ const extrinsic_state &get_ext_state () const { return m_ext_state; }
+
checker_event *get_checker_event (int idx)
{
return m_events[idx];
@@ -140,6 +144,8 @@ public:
private:
DISABLE_COPY_AND_ASSIGN(checker_path);
+ const extrinsic_state &m_ext_state;
+
simple_diagnostic_thread m_thread;
/* The events that have occurred along this path. */
diff --git a/gcc/analyzer/common.h b/gcc/analyzer/common.h
index cb03004..148bfdd 100644
--- a/gcc/analyzer/common.h
+++ b/gcc/analyzer/common.h
@@ -22,6 +22,8 @@ along with GCC; see the file COPYING3. If not see
#define GCC_ANALYZER_COMMON_H
#include "config.h"
+#define INCLUDE_MAP
+#define INCLUDE_STRING
#define INCLUDE_VECTOR
#include "system.h"
#include "coretypes.h"
@@ -207,14 +209,14 @@ class region_offset
{
public:
region_offset ()
- : m_base_region (NULL), m_offset (0), m_sym_offset (NULL)
+ : m_base_region (nullptr), m_offset (0), m_sym_offset (nullptr)
{
}
static region_offset make_concrete (const region *base_region,
bit_offset_t offset)
{
- return region_offset (base_region, offset, NULL);
+ return region_offset (base_region, offset, nullptr);
}
static region_offset make_symbolic (const region *base_region,
const svalue *sym_offset)
@@ -226,8 +228,8 @@ public:
const region *get_base_region () const { return m_base_region; }
- bool concrete_p () const { return m_sym_offset == NULL; }
- bool symbolic_p () const { return m_sym_offset != NULL; }
+ bool concrete_p () const { return m_sym_offset == nullptr; }
+ bool symbolic_p () const { return m_sym_offset != nullptr; }
bit_offset_t get_bit_offset () const
{
@@ -304,7 +306,7 @@ public:
}
virtual const builtin_known_function *
- dyn_cast_builtin_kf () const { return NULL; }
+ dyn_cast_builtin_kf () const { return nullptr; }
};
/* Subclass of known_function for builtin functions. */
@@ -565,13 +567,13 @@ public:
delete (*iter).second;
}
- /* Get the instance of T for K if one exists, or NULL. */
+ /* Get the instance of T for K if one exists, or nullptr. */
T *get (const key_t &k) const
{
if (instance_t **slot = const_cast<inner_map_t &> (m_inner_map).get (k))
return *slot;
- return NULL;
+ return nullptr;
}
/* Take ownership of INSTANCE. */
diff --git a/gcc/analyzer/constraint-manager.cc b/gcc/analyzer/constraint-manager.cc
index 869e437..58c60fe 100644
--- a/gcc/analyzer/constraint-manager.cc
+++ b/gcc/analyzer/constraint-manager.cc
@@ -609,7 +609,7 @@ bounded_ranges::canonicalize ()
{
bounded_range *prev = &m_ranges[i - 1];
const bounded_range *next = &m_ranges[i];
- if (prev->intersects_p (*next, NULL)
+ if (prev->intersects_p (*next, nullptr)
|| (can_plus_one_p (prev->m_upper)
&& tree_int_cst_equal (plus_one (prev->m_upper),
next->m_lower)))
@@ -1058,7 +1058,7 @@ bounded_ranges_manager::log_stats (logger *logger, bool show_objs) const
/* equiv_class's default ctor. */
equiv_class::equiv_class ()
-: m_constant (NULL_TREE), m_cst_sval (NULL), m_vars ()
+: m_constant (NULL_TREE), m_cst_sval (nullptr), m_vars ()
{
}
@@ -3024,7 +3024,7 @@ on_liveness_change (const svalue_set &live_svalues,
const region_model *model)
{
dead_svalue_purger p (live_svalues, model);
- purge (p, NULL);
+ purge (p, nullptr);
}
class svalue_purger
@@ -3047,7 +3047,7 @@ void
constraint_manager::purge_state_involving (const svalue *sval)
{
svalue_purger p (sval);
- purge (p, NULL);
+ purge (p, nullptr);
}
/* Comparator for use by constraint_manager::canonicalize.
@@ -3191,7 +3191,7 @@ public:
{
/* Special-case for widening. */
if (lhs->get_kind () == SK_WIDENING)
- if (!m_cm_b->get_equiv_class_by_svalue (lhs, NULL))
+ if (!m_cm_b->get_equiv_class_by_svalue (lhs, nullptr))
{
/* LHS isn't constrained within m_cm_b. */
bool sat = m_out->add_constraint (lhs, code, rhs);
@@ -3515,7 +3515,7 @@ test_constraint_conditions ()
ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, x);
ADD_SAT_CONSTRAINT (model, int_42, EQ_EXPR, int_42);
/* ...even when done directly via svalues: */
- const svalue *sval_int_42 = model.get_rvalue (int_42, NULL);
+ const svalue *sval_int_42 = model.get_rvalue (int_42, nullptr);
bool sat = model.get_constraints ()->add_constraint (sval_int_42,
EQ_EXPR,
sval_int_42);
@@ -4304,8 +4304,8 @@ test_purging (void)
ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
/* Purge state for "a". */
- const svalue *sval_a = model.get_rvalue (a, NULL);
- model.purge_state_involving (sval_a, NULL);
+ const svalue *sval_a = model.get_rvalue (a, nullptr);
+ model.purge_state_involving (sval_a, nullptr);
model.canonicalize ();
/* We should have an empty constraint_manager. */
ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 0);
@@ -4322,8 +4322,8 @@ test_purging (void)
ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 2);
/* Purge state for "a". */
- const svalue *sval_a = model.get_rvalue (a, NULL);
- model.purge_state_involving (sval_a, NULL);
+ const svalue *sval_a = model.get_rvalue (a, nullptr);
+ model.purge_state_involving (sval_a, nullptr);
model.canonicalize ();
/* We should just have the constraint/ECs involving b != 0. */
ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
@@ -4341,8 +4341,8 @@ test_purging (void)
ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
/* Purge state for "a". */
- const svalue *sval_a = model.get_rvalue (a, NULL);
- model.purge_state_involving (sval_a, NULL);
+ const svalue *sval_a = model.get_rvalue (a, nullptr);
+ model.purge_state_involving (sval_a, nullptr);
model.canonicalize ();
/* We should just have the EC involving b == 0. */
ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
@@ -4359,8 +4359,8 @@ test_purging (void)
ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
/* Purge state for "a". */
- const svalue *sval_a = model.get_rvalue (a, NULL);
- model.purge_state_involving (sval_a, NULL);
+ const svalue *sval_a = model.get_rvalue (a, nullptr);
+ model.purge_state_involving (sval_a, nullptr);
model.canonicalize ();
/* We should have an empty constraint_manager. */
ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 0);
@@ -4377,8 +4377,8 @@ test_purging (void)
ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
/* Purge state for "a". */
- const svalue *sval_a = model.get_rvalue (a, NULL);
- model.purge_state_involving (sval_a, NULL);
+ const svalue *sval_a = model.get_rvalue (a, nullptr);
+ model.purge_state_involving (sval_a, nullptr);
model.canonicalize ();
/* We should just have the constraint/ECs involving b != 0. */
ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
@@ -4396,8 +4396,8 @@ test_purging (void)
ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
/* Purge state for "a". */
- const svalue *sval_a = model.get_rvalue (a, NULL);
- model.purge_state_involving (sval_a, NULL);
+ const svalue *sval_a = model.get_rvalue (a, nullptr);
+ model.purge_state_involving (sval_a, nullptr);
model.canonicalize ();
/* We should just have the EC involving b == 0. */
ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
@@ -4459,8 +4459,8 @@ test_bounded_range ()
bounded_range br_u8_64_128 (u8_64, u8_128);
ASSERT_DUMP_BOUNDED_RANGE_EQ (br_u8_64_128, "[64, 128]");
- ASSERT_FALSE (br_u8_0.intersects_p (br_u8_64_128, NULL));
- ASSERT_FALSE (br_u8_64_128.intersects_p (br_u8_0, NULL));
+ ASSERT_FALSE (br_u8_0.intersects_p (br_u8_64_128, nullptr));
+ ASSERT_FALSE (br_u8_64_128.intersects_p (br_u8_0, nullptr));
bounded_range br_u8_128_255 (u8_128, u8_255);
ASSERT_DUMP_BOUNDED_RANGE_EQ (br_u8_128_255, "[128, 255]");
diff --git a/gcc/analyzer/constraint-manager.h b/gcc/analyzer/constraint-manager.h
index a26b48d..4339ea6 100644
--- a/gcc/analyzer/constraint-manager.h
+++ b/gcc/analyzer/constraint-manager.h
@@ -226,8 +226,8 @@ private:
{
return k->get_hash ();
}
- static inline bool is_empty (key_type k) { return k == NULL; }
- static inline void mark_empty (key_type &k) { k = NULL; }
+ static inline bool is_empty (key_type k) { return k == nullptr; }
+ static inline void mark_empty (key_type &k) { k = nullptr; }
static inline bool is_deleted (key_type k)
{
return k == reinterpret_cast<key_type> (1);
diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc
index e5d1a25..c083b8c 100644
--- a/gcc/analyzer/diagnostic-manager.cc
+++ b/gcc/analyzer/diagnostic-manager.cc
@@ -63,7 +63,7 @@ class epath_finder
public:
epath_finder (const exploded_graph &eg)
: m_eg (eg),
- m_sep (NULL)
+ m_sep (nullptr)
{
/* This is shared by all diagnostics, but only needed if
!flag_analyzer_feasibility. */
@@ -125,7 +125,7 @@ private:
within ENODE.
Ideally we want to report the shortest feasible path.
- Return NULL if we could not find a feasible path
+ Return nullptr if we could not find a feasible path
(when flag_analyzer_feasibility is true).
If flag_analyzer_feasibility is false, then simply return the
@@ -177,7 +177,7 @@ epath_finder::get_best_epath (const exploded_node *enode,
logger->log ("rejecting %qs at EN: %i, SN: %i (sd: %i)"
" due to not finding feasible path",
desc, enode->m_index, snode_idx, diag_idx);
- return NULL;
+ return nullptr;
}
}
else
@@ -221,7 +221,7 @@ class feasible_worklist
{
public:
feasible_worklist (const shortest_paths<eg_traits, exploded_path> &sep)
- : m_queue (key_t (*this, NULL)),
+ : m_queue (key_t (*this, nullptr)),
m_sep (sep)
{
}
@@ -416,7 +416,7 @@ epath_finder::explore_feasible_paths (const exploded_node *target_enode,
a limit. */
/* Set this if we find a feasible path to TARGET_ENODE. */
- std::unique_ptr<exploded_path> best_path = NULL;
+ std::unique_ptr<exploded_path> best_path = nullptr;
{
auto_checking_feasibility sentinel (mgr);
@@ -508,7 +508,7 @@ process_worklist_item (feasible_worklist *worklist,
std::unique_ptr<rejected_constraint> rc;
if (succ_state.maybe_update_for_edge (logger, succ_eedge, nullptr, &rc))
{
- gcc_assert (rc == NULL);
+ gcc_assert (rc == nullptr);
feasible_node *succ_fnode
= fg->add_node (succ_eedge->m_dest,
succ_state,
@@ -612,7 +612,7 @@ dump_trimmed_graph (const exploded_node *target_enode,
pp_printf (&pp, "%s.%s.%i.to-en%i.tg.dot",
dump_base_name, desc, diag_idx, target_enode->m_index);
char *filename = xstrdup (pp_formatted_text (&pp));
- tg.dump_dot (filename, NULL, args);
+ tg.dump_dot (filename, nullptr, args);
free (filename);
}
@@ -630,7 +630,7 @@ epath_finder::dump_feasible_graph (const exploded_node *target_enode,
pp_printf (&pp, "%s.%s.%i.to-en%i.fg.dot",
dump_base_name, desc, diag_idx, target_enode->m_index);
char *filename = xstrdup (pp_formatted_text (&pp));
- fg.dump_dot (filename, NULL, args);
+ fg.dump_dot (filename, nullptr, args);
free (filename);
}
@@ -687,6 +687,11 @@ saved_diagnostic::operator== (const saved_diagnostic &other) const
for (unsigned i = 0; i < m_notes.length (); i++)
if (!m_notes[i]->equal_p (*other.m_notes[i]))
return false;
+
+ // Don't deduplicate dump_path_diagnostic instances
+ if (!strcmp (m_d->get_kind (), "dump_path_diagnostic"))
+ return this == &other;
+
return (m_sm == other.m_sm
/* We don't compare m_enode. */
&& m_snode == other.m_snode
@@ -822,7 +827,7 @@ saved_diagnostic::dump_as_dot_node (pretty_printer *pp) const
/* Use PF to find the best exploded_path for this saved_diagnostic,
and store it in m_best_epath.
- If we don't have a specific location in m_loc and m_stmt is still NULL,
+ If we don't have a specific location in m_loc and m_stmt is still nullptr,
use m_stmt_finder on the epath to populate m_stmt.
Return true if a best path was found. */
@@ -831,20 +836,20 @@ saved_diagnostic::calc_best_epath (epath_finder *pf)
{
logger *logger = pf->get_logger ();
LOG_SCOPE (logger);
- m_problem = NULL;
+ m_problem = nullptr;
m_best_epath = pf->get_best_epath (m_enode, m_stmt,
*m_d, m_d->get_kind (), m_idx,
&m_problem);
/* Handle failure to find a feasible path. */
- if (m_best_epath == NULL)
+ if (m_best_epath == nullptr)
return false;
gcc_assert (m_best_epath);
if (m_loc == UNKNOWN_LOCATION)
{
- if (m_stmt == NULL)
+ if (m_stmt == nullptr)
{
gcc_assert (m_stmt_finder);
m_stmt = m_stmt_finder->find_stmt (*m_best_epath);
@@ -1193,7 +1198,7 @@ diagnostic_manager::add_diagnostic (const pending_location &ploc,
std::unique_ptr<pending_diagnostic> d)
{
gcc_assert (ploc.m_enode);
- return add_diagnostic (NULL, ploc, NULL_TREE, NULL, 0, std::move (d));
+ return add_diagnostic (nullptr, ploc, NULL_TREE, nullptr, 0, std::move (d));
}
/* Add PN to the most recent saved_diagnostic. */
@@ -1338,7 +1343,7 @@ public:
template <typename T>
static inline void mark_empty (T &entry)
{
- entry.m_key = NULL;
+ entry.m_key = nullptr;
}
template <typename T>
static inline bool is_deleted (const T &entry)
@@ -1348,7 +1353,7 @@ public:
template <typename T>
static inline bool is_empty (const T &entry)
{
- return entry.m_key == NULL;
+ return entry.m_key == nullptr;
}
static const bool empty_zero_p = true;
};
@@ -1581,6 +1586,7 @@ diagnostic_manager::emit_saved_diagnostic (const exploded_graph &eg,
/* This is the diagnostic_path subclass that will be built for
the diagnostic. */
checker_path emission_path (get_logical_location_manager (),
+ eg.get_ext_state (),
get_logger ());
/* Populate emission_path with a full description of EPATH. */
@@ -1614,7 +1620,7 @@ diagnostic_manager::emit_saved_diagnostic (const exploded_graph &eg,
trailing eedge stashed, add any events for it. This is for use
in handling longjmp, to show where a longjmp is rewinding to. */
if (sd.m_trailing_eedge)
- add_events_for_eedge (pb, *sd.m_trailing_eedge, &emission_path, NULL);
+ add_events_for_eedge (pb, *sd.m_trailing_eedge, &emission_path, nullptr);
emission_path.inject_any_inlined_call_events (get_logger ());
@@ -1698,7 +1704,7 @@ diagnostic_manager::build_emission_path (const path_builder &pb,
{
emission_path->add_region_creation_events
(pb.get_pending_diagnostic (),
- reg, NULL,
+ reg, nullptr,
event_loc_info (DECL_SOURCE_LOCATION (decl),
NULL_TREE,
0),
@@ -1757,7 +1763,7 @@ diagnostic_manager::add_event_on_final_node (const path_builder &pb,
= src_model->get_dynamic_extents (base_reg);
const svalue *new_extents
= dst_model->get_dynamic_extents (base_reg);
- if (old_extents == NULL && new_extents != NULL)
+ if (old_extents == nullptr && new_extents != nullptr)
switch (base_reg->get_kind ())
{
default:
@@ -1970,7 +1976,7 @@ struct null_assignment_sm_context : public sm_context
tree var) final override
{
const svalue *var_old_sval
- = m_old_state->m_region_model->get_rvalue (var, NULL);
+ = m_old_state->m_region_model->get_rvalue (var, nullptr);
const sm_state_map *old_smap = m_old_state->m_checker_states[m_sm_idx];
state_machine::state_t current
@@ -1999,7 +2005,7 @@ struct null_assignment_sm_context : public sm_context
return;
const svalue *var_new_sval
- = m_new_state->m_region_model->get_rvalue (var, NULL);
+ = m_new_state->m_region_model->get_rvalue (var, nullptr);
const supernode *supernode = m_point->get_supernode ();
int stack_depth = m_point->get_stack_depth ();
@@ -2086,7 +2092,7 @@ struct null_assignment_sm_context : public sm_context
if (!assign_stmt)
return NULL_TREE;
if (const svalue *sval
- = m_new_state->m_region_model->get_gassign_result (assign_stmt, NULL))
+ = m_new_state->m_region_model->get_gassign_result (assign_stmt, nullptr))
if (tree cst = sval->maybe_get_constant ())
if (::zerop(cst))
return gimple_assign_lhs (assign_stmt);
@@ -2247,7 +2253,7 @@ diagnostic_manager::add_events_for_eedge (const path_builder &pb,
{
const extrinsic_state &ext_state = pb.get_ext_state ();
program_state old_state (iter_state);
- iter_state.m_region_model->on_assignment (assign, NULL);
+ iter_state.m_region_model->on_assignment (assign, nullptr);
for (unsigned i = 0; i < ext_state.get_num_checkers (); i++)
{
const state_machine &sm = ext_state.get_sm (i);
@@ -2293,7 +2299,7 @@ diagnostic_manager::add_events_for_eedge (const path_builder &pb,
= src_model->get_dynamic_extents (base_reg);
const svalue *new_extents
= dst_model->get_dynamic_extents (base_reg);
- if (old_extents == NULL && new_extents != NULL)
+ if (old_extents == nullptr && new_extents != nullptr)
switch (base_reg->get_kind ())
{
default:
@@ -2599,19 +2605,19 @@ diagnostic_manager::prune_for_sm_diagnostic (checker_path *path,
{
label_text sval_desc = sval->get_desc ();
log ("considering event %i (%s), with sval: %qs, state: %qs",
- idx, event_kind_to_string (base_event->m_kind),
+ idx, event_kind_to_string (base_event->get_kind ()),
sval_desc.get (), state->get_name ());
}
else
log ("considering event %i (%s), with global state: %qs",
- idx, event_kind_to_string (base_event->m_kind),
+ idx, event_kind_to_string (base_event->get_kind ()),
state->get_name ());
}
else
log ("considering event %i", idx);
}
- switch (base_event->m_kind)
+ switch (base_event->get_kind ())
{
default:
gcc_unreachable ();
@@ -2718,7 +2724,7 @@ diagnostic_manager::prune_for_sm_diagnostic (checker_path *path,
log ("filtering events %i and %i: CFG edge", idx, idx + 1);
path->delete_event (idx);
/* Also delete the corresponding event_kind::end_cfg_edge. */
- gcc_assert (path->get_checker_event (idx)->m_kind
+ gcc_assert (path->get_checker_event (idx)->get_kind ()
== event_kind::end_cfg_edge);
path->delete_event (idx);
}
@@ -3038,7 +3044,7 @@ same_line_as_p (const expanded_location &ref_exp_loc,
const checker_event *ev = path->get_checker_event (idx);
expanded_location idx_exp_loc = expand_location (ev->get_location ());
gcc_assert (ref_exp_loc.file);
- if (idx_exp_loc.file == NULL)
+ if (idx_exp_loc.file == nullptr)
return false;
if (strcmp (ref_exp_loc.file, idx_exp_loc.file))
return false;
@@ -3103,13 +3109,13 @@ diagnostic_manager::consolidate_conditions (checker_path *path) const
= path->get_checker_event (start_idx);
expanded_location start_exp_loc
= expand_location (old_start_ev->get_location ());
- if (start_exp_loc.file == NULL)
+ if (start_exp_loc.file == nullptr)
continue;
if (!same_line_as_p (start_exp_loc, path, start_idx + 1))
continue;
/* Are we looking for a run of all TRUE edges, or all FALSE edges? */
- gcc_assert (old_start_ev->m_kind == event_kind::start_cfg_edge);
+ gcc_assert (old_start_ev->get_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
@@ -3132,7 +3138,7 @@ diagnostic_manager::consolidate_conditions (checker_path *path) const
{
const checker_event *iter_ev
= path->get_checker_event (next_idx);
- gcc_assert (iter_ev->m_kind == event_kind::start_cfg_edge);
+ gcc_assert (iter_ev->get_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
@@ -3190,11 +3196,13 @@ diagnostic_manager::consolidate_unwind_events (checker_path *path) const
start_idx++)
{
/* Find a run of consecutive unwind_event instances. */
- if (path->get_checker_event (start_idx)->m_kind != event_kind::unwind)
+ if (path->get_checker_event (start_idx)->get_kind ()
+ != event_kind::unwind)
continue;
int iter_idx = start_idx + 1;
while (iter_idx < (int)path->num_events ())
- if (path->get_checker_event (iter_idx)->m_kind == event_kind::unwind)
+ if (path->get_checker_event (iter_idx)->get_kind ()
+ == event_kind::unwind)
++iter_idx;
else
break;
@@ -3232,7 +3240,7 @@ diagnostic_manager::finish_pruning (checker_path *path) const
while (idx >= 0 && idx < (signed)path->num_events ())
{
checker_event *base_event = path->get_checker_event (idx);
- if (base_event->m_kind == event_kind::function_entry)
+ if (base_event->get_kind () == event_kind::function_entry)
{
log ("filtering event %i:"
" function entry for purely intraprocedural path", idx);
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index c3e4800..67024e9 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -95,14 +95,14 @@ impl_region_model_context (program_state *state,
const extrinsic_state &ext_state,
uncertainty_t *uncertainty,
logger *logger)
-: m_eg (NULL), m_logger (logger), m_enode_for_diag (NULL),
- m_old_state (NULL),
+: m_eg (nullptr), m_logger (logger), m_enode_for_diag (nullptr),
+ m_old_state (nullptr),
m_new_state (state),
- m_stmt (NULL),
- m_stmt_finder (NULL),
+ m_stmt (nullptr),
+ m_stmt_finder (nullptr),
m_ext_state (ext_state),
m_uncertainty (uncertainty),
- m_path_ctxt (NULL),
+ m_path_ctxt (nullptr),
m_out_could_have_done_work (nullptr)
{
}
@@ -113,7 +113,7 @@ impl_region_model_context::warn (std::unique_ptr<pending_diagnostic> d,
{
LOG_FUNC (get_logger ());
auto curr_stmt_finder = custom_finder ? custom_finder : m_stmt_finder;
- if (m_stmt == NULL && curr_stmt_finder == NULL)
+ if (m_stmt == nullptr && curr_stmt_finder == nullptr)
{
if (get_logger ())
get_logger ()->log ("rejecting diagnostic: no stmt");
@@ -296,7 +296,7 @@ public:
const sm_state_map *old_smap,
sm_state_map *new_smap,
path_context *path_ctxt,
- const stmt_finder *stmt_finder = NULL,
+ const stmt_finder *stmt_finder = nullptr,
bool unknown_side_effects = false)
: sm_context (sm_idx, sm),
m_logger (eg.get_logger ()),
@@ -314,8 +314,8 @@ public:
tree get_fndecl_for_call (const gcall &call) final override
{
impl_region_model_context old_ctxt
- (m_eg, m_enode_for_diag, NULL, NULL, NULL/*m_enode->get_state ()*/,
- NULL, &call);
+ (m_eg, m_enode_for_diag, nullptr, nullptr, nullptr/*m_enode->get_state ()*/,
+ nullptr, &call);
region_model *model = m_new_state->m_region_model;
return model->get_fndecl_for_call (call, &old_ctxt);
}
@@ -325,10 +325,10 @@ public:
{
logger * const logger = get_logger ();
LOG_FUNC (logger);
- /* Use NULL ctxt on this get_rvalue call to avoid triggering
+ /* Use nullptr ctxt on this get_rvalue call to avoid triggering
uninitialized value warnings. */
const svalue *var_old_sval
- = m_old_state->m_region_model->get_rvalue (var, NULL);
+ = m_old_state->m_region_model->get_rvalue (var, nullptr);
state_machine::state_t current
= m_old_smap->get_state (var_old_sval, m_eg.get_ext_state ());
@@ -353,9 +353,9 @@ public:
logger * const logger = get_logger ();
LOG_FUNC (logger);
const svalue *var_new_sval
- = m_new_state->m_region_model->get_rvalue (var, NULL);
+ = m_new_state->m_region_model->get_rvalue (var, nullptr);
const svalue *origin_new_sval
- = m_new_state->m_region_model->get_rvalue (origin, NULL);
+ = m_new_state->m_region_model->get_rvalue (origin, nullptr);
/* We use the new sval here to avoid issues with uninitialized values. */
state_machine::state_t current
@@ -378,11 +378,11 @@ public:
logger * const logger = get_logger ();
LOG_FUNC (logger);
impl_region_model_context old_ctxt
- (m_eg, m_enode_for_diag, NULL, NULL, NULL/*m_enode->get_state ()*/,
- NULL, stmt);
+ (m_eg, m_enode_for_diag, nullptr, nullptr, nullptr/*m_enode->get_state ()*/,
+ nullptr, stmt);
const svalue *origin_new_sval
- = m_new_state->m_region_model->get_rvalue (origin, NULL);
+ = m_new_state->m_region_model->get_rvalue (origin, nullptr);
state_machine::state_t current
= m_old_smap->get_state (sval, m_eg.get_ext_state ());
@@ -408,7 +408,7 @@ public:
LOG_FUNC (get_logger ());
gcc_assert (d);
const svalue *var_old_sval
- = m_old_state->m_region_model->get_rvalue (var, NULL);
+ = m_old_state->m_region_model->get_rvalue (var, nullptr);
state_machine::state_t current
= (var
? m_old_smap->get_state (var_old_sval, m_eg.get_ext_state ())
@@ -461,7 +461,7 @@ public:
return expr;
gcc_assert (m_new_state);
- const svalue *sval = m_new_state->m_region_model->get_rvalue (expr, NULL);
+ const svalue *sval = m_new_state->m_region_model->get_rvalue (expr, nullptr);
/* Find trees for all regions storing the value. */
if (tree t = m_new_state->m_region_model->get_representative_tree (sval))
return t;
@@ -502,7 +502,7 @@ public:
if (!assign_stmt)
return NULL_TREE;
impl_region_model_context old_ctxt
- (m_eg, m_enode_for_diag, m_old_state, m_new_state, NULL, NULL, stmt);
+ (m_eg, m_enode_for_diag, m_old_state, m_new_state, nullptr, nullptr, stmt);
if (const svalue *sval
= m_new_state->m_region_model->get_gassign_result (assign_stmt,
&old_ctxt))
@@ -666,7 +666,7 @@ public:
}
gcc_unreachable ();
- return NULL;
+ return nullptr;
}
void update_event_loc_info (event_loc_info &) final override
@@ -925,7 +925,9 @@ impl_region_model_context::on_state_leak (const state_machine &sm,
}
tree leaked_tree_for_diag = fixup_tree_for_diagnostic (leaked_tree);
- std::unique_ptr<pending_diagnostic> pd = sm.on_leak (leaked_tree_for_diag);
+ std::unique_ptr<pending_diagnostic> pd = sm.on_leak (leaked_tree_for_diag,
+ m_old_state,
+ m_new_state);
if (pd)
{
pending_location ploc (m_enode_for_diag,
@@ -960,7 +962,7 @@ impl_region_model_context::on_condition (const svalue *lhs,
sm.on_condition (sm_ctxt,
(m_enode_for_diag
? m_enode_for_diag->get_supernode ()
- : NULL),
+ : nullptr),
m_stmt,
lhs, op, rhs);
}
@@ -987,7 +989,7 @@ impl_region_model_context::on_bounded_ranges (const svalue &sval,
sm.on_bounded_ranges (sm_ctxt,
(m_enode_for_diag
? m_enode_for_diag->get_supernode ()
- : NULL),
+ : nullptr),
m_stmt, sval, ranges);
}
}
@@ -1538,7 +1540,7 @@ exploded_node::on_stmt (exploded_graph &eg,
= old_state.m_checker_states[sm_idx];
sm_state_map *new_smap = state->m_checker_states[sm_idx];
impl_sm_context sm_ctxt (eg, sm_idx, sm, this, &old_state, state,
- old_smap, new_smap, path_ctxt, NULL,
+ old_smap, new_smap, path_ctxt, nullptr,
unknown_side_effects);
/* Allow the state_machine to handle the stmt. */
@@ -1578,6 +1580,16 @@ exploded_node::on_stmt_pre (exploded_graph &eg,
state->dump (eg.get_ext_state (), true);
return;
}
+ else if (is_special_named_call_p (call, "__analyzer_dump_xml", 0))
+ {
+ state->dump_xml (eg.get_ext_state ());
+ return;
+ }
+ else if (is_special_named_call_p (call, "__analyzer_dump_dot", 0))
+ {
+ state->dump_dot (eg.get_ext_state ());
+ return;
+ }
else if (is_special_named_call_p (call, "__analyzer_dump_state", 2))
{
state->impl_call_analyzer_dump_state (call, eg.get_ext_state (),
@@ -1839,7 +1851,7 @@ public:
stale_jmp_buf (const gcall &setjmp_call, const gcall &longjmp_call,
const program_point &setjmp_point)
: m_setjmp_call (setjmp_call), m_longjmp_call (longjmp_call),
- m_setjmp_point (setjmp_point), m_stack_pop_event (NULL)
+ m_setjmp_point (setjmp_point), m_stack_pop_event (nullptr)
{}
int get_controlling_option () const final override
@@ -1981,7 +1993,7 @@ exploded_node::on_longjmp (exploded_graph &eg,
setjmp_point.get_stack_depth (), ctxt);
/* Detect leaks in the new state relative to the old state. */
- program_state::detect_leaks (get_state (), *new_state, NULL,
+ program_state::detect_leaks (get_state (), *new_state, nullptr,
eg.get_ext_state (), ctxt);
program_point next_point
@@ -1995,7 +2007,7 @@ exploded_node::on_longjmp (exploded_graph &eg,
if (next)
{
exploded_edge *eedge
- = eg.add_edge (const_cast<exploded_node *> (this), next, NULL, true,
+ = eg.add_edge (const_cast<exploded_node *> (this), next, nullptr, true,
std::make_unique<rewind_info_t> (tmp_setjmp_record,
longjmp_call));
@@ -2226,7 +2238,7 @@ exploded_graph::unwind_from_exception (exploded_node &thrown_enode,
if (!next_enode)
return;
- add_edge (iter_enode, next_enode, NULL, false, nullptr);
+ add_edge (iter_enode, next_enode, nullptr, false, nullptr);
return;
}
else
@@ -2254,7 +2266,7 @@ exploded_graph::unwind_from_exception (exploded_node &thrown_enode,
throw_stmt);
program_state::detect_leaks (iter_enode->get_state (),
unwound_state,
- NULL,
+ nullptr,
get_ext_state (), &ctxt);
}
const call_string &cs = iter_enode->get_point ().get_call_string ();
@@ -2284,7 +2296,7 @@ exploded_graph::unwind_from_exception (exploded_node &thrown_enode,
if (!after_unwind_enode)
return;
- add_edge (iter_enode, after_unwind_enode, NULL, true,
+ add_edge (iter_enode, after_unwind_enode, nullptr, true,
std::move (unwind_edge_info));
iter_enode = after_unwind_enode;
}
@@ -2339,7 +2351,7 @@ exploded_node::on_throw (exploded_graph &eg,
return;
/* Create custom exploded_edge for a throw. */
- eg.add_edge (this, after_throw_enode, NULL, true,
+ eg.add_edge (this, after_throw_enode, nullptr, true,
std::move (throw_edge_info));
eg.unwind_from_exception (*after_throw_enode, &throw_call, ctxt);
@@ -2392,10 +2404,10 @@ exploded_node::detect_leaks (exploded_graph &eg)
uncertainty_t uncertainty;
impl_region_model_context ctxt (eg, this,
- &old_state, &new_state, &uncertainty, NULL,
+ &old_state, &new_state, &uncertainty, nullptr,
get_stmt ());
- const svalue *result = NULL;
- new_state.m_region_model->pop_frame (NULL, &result, &ctxt, nullptr);
+ const svalue *result = nullptr;
+ new_state.m_region_model->pop_frame (nullptr, &result, &ctxt, nullptr);
program_state::detect_leaks (old_state, new_state, result,
eg.get_ext_state (), &ctxt);
}
@@ -2502,7 +2514,7 @@ rewind_info_t::update_model (region_model *model,
model->on_longjmp (get_longjmp_call (),
get_setjmp_call (),
- setjmp_point.get_stack_depth (), NULL);
+ setjmp_point.get_stack_depth (), nullptr);
return true;
}
@@ -2817,7 +2829,7 @@ strongly_connected_components::strong_connect (unsigned index)
worklist::worklist (const exploded_graph &eg, const analysis_plan &plan)
: m_scc (eg.get_supergraph (), eg.get_logger ()),
m_plan (plan),
- m_queue (key_t (*this, NULL))
+ m_queue (key_t (*this, nullptr))
{
}
@@ -2879,8 +2891,8 @@ worklist::key_t::cmp (const worklist::key_t &ka, const worklist::key_t &kb)
if (flag_analyzer_call_summaries
&& call_string_a.empty_p ()
&& call_string_b.empty_p ()
- && point_a.get_function () != NULL
- && point_b.get_function () != NULL
+ && point_a.get_function () != nullptr
+ && point_b.get_function () != nullptr
&& point_a.get_function () != point_b.get_function ())
{
if (int cmp = ka.m_worklist.m_plan.cmp_function (point_a.get_function (),
@@ -2916,19 +2928,19 @@ worklist::key_t::cmp (const worklist::key_t &ka, const worklist::key_t &kb)
ordering). */
const supernode *snode_a = ka.m_enode->get_supernode ();
const supernode *snode_b = kb.m_enode->get_supernode ();
- if (snode_a == NULL)
+ if (snode_a == nullptr)
{
- if (snode_b != NULL)
- /* One is NULL. */
+ if (snode_b != nullptr)
+ /* One is nullptr. */
return -1;
else
- /* Both are NULL. */
+ /* Both are nullptr. */
return 0;
}
- if (snode_b == NULL)
- /* One is NULL. */
+ if (snode_b == nullptr)
+ /* One is nullptr. */
return 1;
- /* Neither are NULL. */
+ /* Neither are nullptr. */
gcc_assert (snode_a && snode_b);
if (snode_a->m_index != snode_b->m_index)
return snode_a->m_index - snode_b->m_index;
@@ -3002,7 +3014,7 @@ exploded_graph::exploded_graph (const supergraph &sg, logger *logger,
{
m_origin = get_or_create_node
(program_point::origin (*ext_state.get_model_manager ()),
- program_state (ext_state), NULL);
+ program_state (ext_state), nullptr);
for (int i = 0; i < m_sg.num_nodes (); i++)
m_PK_AFTER_SUPERNODE_per_snode.quick_push (i);
}
@@ -3054,10 +3066,10 @@ mark_params_as_tainted (program_state *state, tree fndecl,
tree param = iter_parm;
if (tree parm_default_ssa = ssa_default_def (fun, iter_parm))
param = parm_default_ssa;
- const region *param_reg = state->m_region_model->get_lvalue (param, NULL);
+ const region *param_reg = state->m_region_model->get_lvalue (param, nullptr);
const svalue *init_sval = mgr->get_or_create_initial_value (param_reg);
smap->set_state (state->m_region_model, init_sval,
- tainted, NULL /*origin_new_sval*/, ext_state);
+ tainted, nullptr /*origin_new_sval*/, ext_state);
if (POINTER_TYPE_P (TREE_TYPE (param)))
{
const region *pointee_reg = mgr->get_symbolic_region (init_sval);
@@ -3065,7 +3077,7 @@ mark_params_as_tainted (program_state *state, tree fndecl,
const svalue *init_pointee_sval
= mgr->get_or_create_initial_value (pointee_reg);
smap->set_state (state->m_region_model, init_pointee_sval,
- tainted, NULL /*origin_new_sval*/, ext_state);
+ tainted, nullptr /*origin_new_sval*/, ext_state);
}
}
@@ -3151,7 +3163,7 @@ exploded_graph::add_function_entry (const function &fun)
logger * const logger = get_logger ();
if (logger)
logger->log ("entrypoint for %qE already exists", fun.decl);
- return NULL;
+ return nullptr;
}
program_point point
@@ -3160,7 +3172,7 @@ exploded_graph::add_function_entry (const function &fun)
program_state state (m_ext_state);
state.push_frame (m_ext_state, fun);
- std::unique_ptr<custom_edge_info> edge_info = NULL;
+ std::unique_ptr<custom_edge_info> edge_info = nullptr;
if (lookup_attribute ("tainted_args", DECL_ATTRIBUTES (fun.decl)))
{
@@ -3169,13 +3181,13 @@ exploded_graph::add_function_entry (const function &fun)
}
if (!state.m_valid)
- return NULL;
+ return nullptr;
- exploded_node *enode = get_or_create_node (point, state, NULL);
+ exploded_node *enode = get_or_create_node (point, state, nullptr);
if (!enode)
- return NULL;
+ return nullptr;
- add_edge (m_origin, enode, NULL, false, std::move (edge_info));
+ add_edge (m_origin, enode, nullptr, false, std::move (edge_info));
m_functions_with_enodes.add (key);
@@ -3218,7 +3230,7 @@ exploded_graph::get_or_create_node (const program_point &point,
{
if (logger)
logger->log ("invalid state; not creating node");
- return NULL;
+ return nullptr;
}
auto_cfun sentinel (point.get_function ());
@@ -3332,7 +3344,7 @@ exploded_graph::get_or_create_node (const program_point &point,
"terminating analysis for this program point: %s",
pp_formatted_text (&pp));
per_point_data->m_excess_enodes++;
- return NULL;
+ return nullptr;
}
ps.validate (m_ext_state);
@@ -3412,7 +3424,7 @@ get_or_create_per_program_point_data (const program_point &point)
}
/* Get this graph's per-program-point-data for POINT if there is any,
- otherwise NULL. */
+ otherwise nullptr. */
per_program_point_data *
exploded_graph::get_per_program_point_data (const program_point &point) const
@@ -3421,7 +3433,7 @@ exploded_graph::get_per_program_point_data (const program_point &point) const
= const_cast <point_map_t &> (m_per_point_data).get (&point))
return *slot;
- return NULL;
+ return nullptr;
}
/* Ensure that this graph has per-call_string-data for CS;
@@ -3454,7 +3466,7 @@ exploded_graph::get_or_create_per_function_data (function *fun)
}
/* Get this graph's per-function-data for FUN if there is any,
- otherwise NULL. */
+ otherwise nullptr. */
per_function_data *
exploded_graph::get_per_function_data (function *fun) const
@@ -3463,7 +3475,7 @@ exploded_graph::get_per_function_data (function *fun) const
= const_cast <per_function_data_t &> (m_per_function_data).get (fun))
return *slot;
- return NULL;
+ return nullptr;
}
/* Return true if FUN should be traversed directly, rather than only as
@@ -3626,7 +3638,7 @@ add_tainted_args_callback (exploded_graph *eg, tree field, tree fndecl,
if (!state.m_valid)
return;
- exploded_node *enode = eg->get_or_create_node (point, state, NULL);
+ exploded_node *enode = eg->get_or_create_node (point, state, nullptr);
if (logger)
{
if (enode)
@@ -3640,7 +3652,7 @@ add_tainted_args_callback (exploded_graph *eg, tree field, tree fndecl,
}
}
- eg->add_edge (eg->get_origin (), enode, NULL, false,
+ eg->add_edge (eg->get_origin (), enode, nullptr, false,
std::make_unique<tainted_args_call_info> (field, fndecl, loc));
}
@@ -3714,7 +3726,7 @@ exploded_graph::build_initial_worklist ()
tree init = DECL_INITIAL (decl);
if (!init)
continue;
- walk_tree (&init, add_any_callbacks, this, NULL);
+ walk_tree (&init, add_any_callbacks, this, nullptr);
}
}
@@ -3795,7 +3807,7 @@ exploded_graph::process_worklist ()
if (merged_state == state)
{
/* Then merge node_2 into node by adding an edge. */
- add_edge (node_2, node, NULL, false);
+ add_edge (node_2, node, nullptr, false);
/* Remove node_2 from the worklist. */
m_worklist.take_next ();
@@ -3808,7 +3820,7 @@ exploded_graph::process_worklist ()
/* Then merge node into node_2, and leave node_2
in the worklist, to be processed on the next
iteration. */
- add_edge (node, node_2, NULL, false);
+ add_edge (node, node_2, nullptr, false);
node->set_status (exploded_node::status::merger);
continue;
}
@@ -3825,7 +3837,7 @@ exploded_graph::process_worklist ()
exploded_node *merged_enode
= get_or_create_node (node->get_point (),
merged_state, node);
- if (merged_enode == NULL)
+ if (merged_enode == nullptr)
continue;
if (logger)
@@ -3853,7 +3865,7 @@ exploded_graph::process_worklist ()
m_worklist.add_node (merged_enode);
else
{
- add_edge (node, merged_enode, NULL, false);
+ add_edge (node, merged_enode, nullptr, false);
node->set_status (exploded_node::status::merger);
}
@@ -3861,7 +3873,7 @@ exploded_graph::process_worklist ()
m_worklist.add_node (merged_enode);
else
{
- add_edge (node_2, merged_enode, NULL, false);
+ add_edge (node_2, merged_enode, nullptr, false);
node_2->set_status (exploded_node::status::merger);
}
@@ -4016,7 +4028,7 @@ maybe_process_run_of_before_supernode_enodes (exploded_node *enode)
uncertainty_t uncertainty;
impl_region_model_context ctxt (*this, iter_enode,
&state, next_state,
- &uncertainty, NULL, NULL);
+ &uncertainty, nullptr, nullptr);
const cfg_superedge *last_cfg_superedge
= iter_sedge->dyn_cast_cfg_superedge ();
if (last_cfg_superedge)
@@ -4079,7 +4091,7 @@ maybe_process_run_of_before_supernode_enodes (exploded_node *enode)
= first_item_for_each_merged_state[i]->m_input_enode;
exploded_node *next
= get_or_create_node (next_point, *merged_state, src_enode);
- /* "next" could be NULL; we handle that when adding the edges below. */
+ /* "next" could be nullptr; we handle that when adding the edges below. */
next_enodes.quick_push (next);
if (logger)
{
@@ -4096,7 +4108,7 @@ maybe_process_run_of_before_supernode_enodes (exploded_node *enode)
{
exploded_node *next = next_enodes[it->m_merger_idx];
if (next)
- add_edge (it->m_input_enode, next, NULL,
+ add_edge (it->m_input_enode, next, nullptr,
false); /* no "work" is done during merger. */
it->m_input_enode->set_status (exploded_node::status::bulk_merged);
}
@@ -4207,7 +4219,7 @@ exploded_graph::maybe_create_dynamic_call (const gcall &call,
program_point new_point
= program_point::before_supernode (sn_entry,
- NULL,
+ nullptr,
this_point->get_call_string ());
new_point.push_to_call_stack (sn_exit,
@@ -4240,7 +4252,7 @@ exploded_graph::maybe_create_dynamic_call (const gcall &call,
next_state,
node);
if (enode)
- add_edge (node,enode, NULL,
+ add_edge (node,enode, nullptr,
false, /* No work is done by the call itself. */
std::make_unique<dynamic_call_info_t> (call));
return true;
@@ -4420,7 +4432,7 @@ exploded_graph::process_node (exploded_node *node)
{
impl_region_model_context ctxt (*this, node,
&state, &next_state,
- &uncertainty, NULL, NULL);
+ &uncertainty, nullptr, nullptr);
const cfg_superedge *last_cfg_superedge
= point.get_from_edge ()->dyn_cast_cfg_superedge ();
if (last_cfg_superedge)
@@ -4428,14 +4440,14 @@ exploded_graph::process_node (exploded_node *node)
(node->get_supernode (),
last_cfg_superedge,
&ctxt);
- program_state::detect_leaks (state, next_state, NULL,
+ program_state::detect_leaks (state, next_state, nullptr,
get_ext_state (), &ctxt);
}
program_point next_point (point.get_next ());
exploded_node *next = get_or_create_node (next_point, next_state, node);
if (next)
- add_edge (node, next, NULL,
+ add_edge (node, next, nullptr,
false); /* Assume no work is done at phi nodes. */
}
break;
@@ -4468,7 +4480,7 @@ exploded_graph::process_node (exploded_node *node)
uncertainty_t uncertainty;
const supernode *snode = point.get_supernode ();
unsigned stmt_idx;
- const gimple *prev_stmt = NULL;
+ const gimple *prev_stmt = nullptr;
for (stmt_idx = point.get_stmt_idx ();
stmt_idx < snode->m_stmts.length ();
stmt_idx++)
@@ -4500,8 +4512,8 @@ exploded_graph::process_node (exploded_node *node)
{
impl_region_model_context ctxt (*this, node,
&old_state, &next_state,
- &uncertainty, NULL, stmt);
- program_state::detect_leaks (old_state, next_state, NULL,
+ &uncertainty, nullptr, stmt);
+ program_state::detect_leaks (old_state, next_state, nullptr,
get_ext_state (), &ctxt);
}
@@ -4545,7 +4557,7 @@ exploded_graph::process_node (exploded_node *node)
node->m_num_processed_stmts--;
if (logger)
logger->log ("creating edge to split_enode");
- add_edge (node, split_enode, NULL, could_have_done_work);
+ add_edge (node, split_enode, nullptr, could_have_done_work);
return;
}
else
@@ -4572,7 +4584,7 @@ exploded_graph::process_node (exploded_node *node)
exploded_node *next
= get_or_create_node (next_point, next_state, node);
if (next)
- add_edge (node, next, NULL, could_have_done_work);
+ add_edge (node, next, nullptr, could_have_done_work);
}
/* If we have custom edge infos, "bifurcate" the state
@@ -4600,11 +4612,11 @@ exploded_graph::process_node (exploded_node *node)
node, // enode_for_diag
&path_ctxt.get_state_at_bifurcation (),
&bifurcated_new_state,
- NULL, // uncertainty_t *uncertainty
- NULL, // path_context *path_ctxt
+ nullptr, // uncertainty_t *uncertainty
+ nullptr, // path_context *path_ctxt
stmt);
if (edge_info->update_state (&bifurcated_new_state,
- NULL, /* no exploded_edge yet. */
+ nullptr, /* no exploded_edge yet. */
&bifurcation_ctxt))
{
if (exploded_node *next2
@@ -4615,7 +4627,7 @@ exploded_graph::process_node (exploded_node *node)
node,
&bifurcation_ctxt))
{
- add_edge (node, next2, NULL,
+ add_edge (node, next2, nullptr,
true /* assume that work could be done */,
std::move (edge_info));
}
@@ -4696,7 +4708,7 @@ exploded_graph::process_node (exploded_node *node)
&state,
&next_state,
&uncertainty,
- NULL,
+ nullptr,
point.get_stmt());
region_model *model = state.m_region_model;
@@ -4712,7 +4724,7 @@ exploded_graph::process_node (exploded_node *node)
logger);
if (!call_discovered)
{
- /* Check for jump through NULL. */
+ /* Check for jump through nullptr. */
if (tree fn_ptr = gimple_call_fn (&call))
{
const svalue *fn_ptr_sval
@@ -4779,7 +4791,7 @@ exploded_graph::process_node (exploded_node *node)
const call_string &cs = point.get_call_string ();
program_point next_point
= program_point::before_supernode (cs.get_caller_node (),
- NULL,
+ nullptr,
cs);
program_state next_state (state);
uncertainty_t uncertainty;
@@ -4797,7 +4809,7 @@ exploded_graph::process_node (exploded_node *node)
next_state,
node);
if (enode)
- add_edge (node, enode, NULL, false,
+ add_edge (node, enode, nullptr, false,
std::make_unique<dynamic_call_info_t> (*call, true));
}
}
@@ -4807,7 +4819,7 @@ exploded_graph::process_node (exploded_node *node)
}
/* Ensure that this graph has a stats instance for FN, return it.
- FN can be NULL, in which case a stats instances is returned covering
+ FN can be nullptr, in which case a stats instances is returned covering
"functionless" parts of the graph (the origin node). */
stats *
@@ -5389,16 +5401,16 @@ void
feasibility_state::update_for_stmt (const gimple *stmt)
{
if (const gassign *assign = dyn_cast <const gassign *> (stmt))
- m_model.on_assignment (assign, NULL);
+ m_model.on_assignment (assign, nullptr);
else if (const gasm *asm_stmt = dyn_cast <const gasm *> (stmt))
- m_model.on_asm_stmt (asm_stmt, NULL);
+ m_model.on_asm_stmt (asm_stmt, nullptr);
else if (const gcall *call = dyn_cast <const gcall *> (stmt))
{
- bool unknown_side_effects = m_model.on_call_pre (*call, NULL);
- m_model.on_call_post (*call, unknown_side_effects, NULL);
+ bool unknown_side_effects = m_model.on_call_pre (*call, nullptr);
+ m_model.on_call_post (*call, unknown_side_effects, nullptr);
}
else if (const greturn *return_ = dyn_cast <const greturn *> (stmt))
- m_model.on_return (return_, NULL);
+ m_model.on_return (return_, nullptr);
}
/* Dump this object to PP. */
@@ -5613,7 +5625,7 @@ template <>
inline void
pod_hash_traits<function_call_string>::mark_empty (value_type &v)
{
- v.m_fun = NULL;
+ v.m_fun = nullptr;
}
template <>
inline bool
@@ -5625,7 +5637,7 @@ template <>
inline bool
pod_hash_traits<function_call_string>::is_empty (value_type v)
{
- return v.m_fun == NULL;
+ return v.m_fun == nullptr;
}
namespace ana {
@@ -5781,7 +5793,7 @@ exploded_graph::dump_exploded_nodes () const
{
auto_timevar tv (TV_ANALYZER_DUMP);
char *filename
- = concat (dump_base_name, ".eg.txt", NULL);
+ = concat (dump_base_name, ".eg.txt", nullptr);
FILE *outf = fopen (filename, "w");
if (!outf)
error_at (UNKNOWN_LOCATION, "unable to open %qs for writing", filename);
@@ -6208,7 +6220,7 @@ dump_callgraph (const supergraph &sg, const char *filename,
// TODO
viz_callgraph vcg (sg);
- vcg.dump_dot (filename, NULL, viz_callgraph_traits::dump_args_t (eg));
+ vcg.dump_dot (filename, nullptr, viz_callgraph_traits::dump_args_t (eg));
fclose (outf);
}
@@ -6219,7 +6231,7 @@ static void
dump_callgraph (const supergraph &sg, const exploded_graph *eg)
{
auto_timevar tv (TV_ANALYZER_DUMP);
- char *filename = concat (dump_base_name, ".callgraph.dot", NULL);
+ char *filename = concat (dump_base_name, ".callgraph.dot", nullptr);
dump_callgraph (sg, filename, eg);
free (filename);
}
@@ -6445,7 +6457,7 @@ dump_analyzer_json (const supergraph &sg,
const exploded_graph &eg)
{
auto_timevar tv (TV_ANALYZER_DUMP);
- char *filename = concat (dump_base_name, ".analyzer.json.gz", NULL);
+ char *filename = concat (dump_base_name, ".analyzer.json.gz", nullptr);
gzFile output = gzopen (filename, "w");
if (!output)
{
@@ -6532,7 +6544,7 @@ impl_run_checkers (logger *logger)
engine eng (&sg, logger);
- state_purge_map *purge_map = NULL;
+ state_purge_map *purge_map = nullptr;
if (flag_analyzer_state_purge)
purge_map = new state_purge_map (sg, eng.get_model_manager (), logger);
@@ -6541,8 +6553,8 @@ impl_run_checkers (logger *logger)
{
/* Dump supergraph pre-analysis. */
auto_timevar tv (TV_ANALYZER_DUMP);
- char *filename = concat (dump_base_name, ".supergraph.dot", NULL);
- supergraph::dump_args_t args ((enum supergraph_dot_flags)0, NULL);
+ char *filename = concat (dump_base_name, ".supergraph.dot", nullptr);
+ supergraph::dump_args_t args ((enum supergraph_dot_flags)0, nullptr);
sg.dump_dot (filename, args);
free (filename);
}
@@ -6551,7 +6563,7 @@ impl_run_checkers (logger *logger)
{
auto_timevar tv (TV_ANALYZER_DUMP);
state_purge_annotator a (purge_map);
- char *filename = concat (dump_base_name, ".state-purge.dot", NULL);
+ char *filename = concat (dump_base_name, ".state-purge.dot", nullptr);
supergraph::dump_args_t args ((enum supergraph_dot_flags)0, &a);
sg.dump_dot (filename, args);
free (filename);
@@ -6596,7 +6608,7 @@ impl_run_checkers (logger *logger)
{
auto_timevar tv (TV_ANALYZER_DUMP);
char *filename
- = concat (dump_base_name, ".eg.dot", NULL);
+ = concat (dump_base_name, ".eg.dot", nullptr);
exploded_graph::dump_args_t args (eg);
root_cluster c;
eg.dump_dot (filename, &c, args);
@@ -6617,7 +6629,7 @@ impl_run_checkers (logger *logger)
{
/* Dump post-analysis form of supergraph. */
auto_timevar tv (TV_ANALYZER_DUMP);
- char *filename = concat (dump_base_name, ".supergraph-eg.dot", NULL);
+ char *filename = concat (dump_base_name, ".supergraph-eg.dot", nullptr);
exploded_graph_annotator a (eg);
supergraph::dump_args_t args ((enum supergraph_dot_flags)0, &a);
sg.dump_dot (filename, args);
@@ -6641,7 +6653,7 @@ impl_run_checkers (logger *logger)
}
/* Handle -fdump-analyzer and -fdump-analyzer-stderr. */
-static FILE *dump_fout = NULL;
+static FILE *dump_fout = nullptr;
/* Track if we're responsible for closing dump_fout. */
static bool owns_dump_fout = false;
@@ -6658,7 +6670,7 @@ get_or_create_any_logfile ()
dump_fout = stderr;
else if (flag_dump_analyzer)
{
- char *dump_filename = concat (dump_base_name, ".analyzer.txt", NULL);
+ char *dump_filename = concat (dump_base_name, ".analyzer.txt", nullptr);
dump_fout = fopen (dump_filename, "w");
free (dump_filename);
if (dump_fout)
@@ -6678,7 +6690,7 @@ run_checkers ()
location_t saved_input_location = input_location;
{
- log_user the_logger (NULL);
+ log_user the_logger (nullptr);
get_or_create_any_logfile ();
if (dump_fout)
the_logger.set_logger (new logger (dump_fout, 0, 0,
@@ -6695,7 +6707,7 @@ run_checkers ()
{
fclose (dump_fout);
owns_dump_fout = false;
- dump_fout = NULL;
+ dump_fout = nullptr;
}
/* Restore input_location. Subsequent passes may assume that input_location
diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h
index 23e344d..1d31097 100644
--- a/gcc/analyzer/exploded-graph.h
+++ b/gcc/analyzer/exploded-graph.h
@@ -49,17 +49,17 @@ class impl_region_model_context : public region_model_context
path_context *path_ctxt,
const gimple *stmt,
- stmt_finder *stmt_finder = NULL,
+ stmt_finder *stmt_finder = nullptr,
bool *out_could_have_done_work = nullptr);
impl_region_model_context (program_state *state,
const extrinsic_state &ext_state,
uncertainty_t *uncertainty,
- logger *logger = NULL);
+ logger *logger = nullptr);
bool warn (std::unique_ptr<pending_diagnostic> d,
- const stmt_finder *custom_finder = NULL) final override;
+ const stmt_finder *custom_finder = nullptr) final override;
void add_note (std::unique_ptr<pending_note> pn) final override;
void add_event (std::unique_ptr<checker_event> event) final override;
void on_svalue_leak (const svalue *) override;
@@ -112,6 +112,8 @@ class impl_region_model_context : public region_model_context
const gimple *get_stmt () const override { return m_stmt; }
const exploded_graph *get_eg () const override { return m_eg; }
+ const program_state *get_state () const override { return m_new_state; }
+
void maybe_did_work () override;
bool checking_for_infinite_loop_p () const override { return false; }
void on_unusable_in_infinite_loop () override {}
@@ -405,7 +407,7 @@ class exploded_edge : public dedge<eg_traits>
//private:
const superedge *const m_sedge;
- /* NULL for most edges; will be non-NULL for special cases
+ /* nullptr for most edges; will be non-NULL for special cases
such as an unwind from a longjmp to a setjmp, or when
a signal is delivered to a signal-handler. */
std::unique_ptr<custom_edge_info> m_custom_info;
@@ -546,14 +548,14 @@ struct eg_hash_map_traits
static inline hashval_t hash (const key_type &k)
{
- gcc_assert (k != NULL);
+ gcc_assert (k != nullptr);
gcc_assert (k != reinterpret_cast<key_type> (1));
return k->hash ();
}
static inline bool equal_keys (const key_type &k1, const key_type &k2)
{
- gcc_assert (k1 != NULL);
- gcc_assert (k2 != NULL);
+ gcc_assert (k1 != nullptr);
+ gcc_assert (k2 != nullptr);
gcc_assert (k1 != reinterpret_cast<key_type> (1));
gcc_assert (k2 != reinterpret_cast<key_type> (1));
if (k1 && k2)
@@ -575,7 +577,7 @@ struct eg_hash_map_traits
template <typename T>
static inline void mark_empty (T &entry)
{
- entry.m_key = NULL;
+ entry.m_key = nullptr;
}
template <typename T>
static inline bool is_deleted (const T &entry)
@@ -585,7 +587,7 @@ struct eg_hash_map_traits
template <typename T>
static inline bool is_empty (const T &entry)
{
- return entry.m_key == NULL;
+ return entry.m_key == nullptr;
}
static const bool empty_zero_p = false;
};
@@ -616,14 +618,14 @@ struct eg_point_hash_map_traits
static inline hashval_t hash (const key_type &k)
{
- gcc_assert (k != NULL);
+ gcc_assert (k != nullptr);
gcc_assert (k != reinterpret_cast<key_type> (1));
return k->hash ();
}
static inline bool equal_keys (const key_type &k1, const key_type &k2)
{
- gcc_assert (k1 != NULL);
- gcc_assert (k2 != NULL);
+ gcc_assert (k1 != nullptr);
+ gcc_assert (k2 != nullptr);
gcc_assert (k1 != reinterpret_cast<key_type> (1));
gcc_assert (k2 != reinterpret_cast<key_type> (1));
if (k1 && k2)
@@ -645,7 +647,7 @@ struct eg_point_hash_map_traits
template <typename T>
static inline void mark_empty (T &entry)
{
- entry.m_key = NULL;
+ entry.m_key = nullptr;
}
template <typename T>
static inline bool is_deleted (const T &entry)
@@ -655,7 +657,7 @@ struct eg_point_hash_map_traits
template <typename T>
static inline bool is_empty (const T &entry)
{
- return entry.m_key == NULL;
+ return entry.m_key == nullptr;
}
static const bool empty_zero_p = false;
};
@@ -776,7 +778,7 @@ private:
int get_scc_id (const exploded_node *enode) const
{
const supernode *snode = enode->get_supernode ();
- if (snode == NULL)
+ if (snode == nullptr)
return 0;
return m_worklist.m_scc.get_scc_id (snode->m_index);
}
@@ -844,7 +846,7 @@ public:
bool add_to_worklist = true);
exploded_edge *add_edge (exploded_node *src, exploded_node *dest,
const superedge *sedge, bool could_do_work,
- std::unique_ptr<custom_edge_info> custom = NULL);
+ std::unique_ptr<custom_edge_info> custom = nullptr);
per_program_point_data *
get_or_create_per_program_point_data (const program_point &);
@@ -977,7 +979,7 @@ public:
void dump_to_pp (pretty_printer *pp,
const extrinsic_state *ext_state) const;
void dump (FILE *fp, const extrinsic_state *ext_state) const;
- void dump (const extrinsic_state *ext_state = NULL) const;
+ void dump (const extrinsic_state *ext_state = nullptr) const;
void dump_to_file (const char *filename,
const extrinsic_state &ext_state) const;
@@ -1042,7 +1044,7 @@ private:
typedef shortest_paths<eg_traits, exploded_path> shortest_exploded_paths;
-/* Abstract base class for use when passing NULL as the stmt for
+/* Abstract base class for use when passing nullptr as the stmt for
a possible warning, allowing the choice of stmt to be deferred
until after we have an emission path (and know we're emitting a
warning). */
diff --git a/gcc/analyzer/function-set.cc b/gcc/analyzer/function-set.cc
index 817a512..530e0ad 100644
--- a/gcc/analyzer/function-set.cc
+++ b/gcc/analyzer/function-set.cc
@@ -95,7 +95,7 @@ namespace selftest {
static void
test_empty ()
{
- function_set fs (NULL, 0);
+ function_set fs (nullptr, 0);
fs.assert_sorted ();
fs.assert_sane ();
ASSERT_FALSE (fs.contains_name_p (""));
diff --git a/gcc/analyzer/infinite-recursion.cc b/gcc/analyzer/infinite-recursion.cc
index 0641117..b80b94a 100644
--- a/gcc/analyzer/infinite-recursion.cc
+++ b/gcc/analyzer/infinite-recursion.cc
@@ -55,7 +55,7 @@ public:
: m_prev_entry_enode (prev_entry_enode),
m_new_entry_enode (new_entry_enode),
m_callee_fndecl (callee_fndecl),
- m_prev_entry_event (NULL)
+ m_prev_entry_event (nullptr)
{}
const char *get_kind () const final override
@@ -108,9 +108,10 @@ public:
{
public:
recursive_function_entry_event (const program_point &dst_point,
+ const program_state &dst_state,
const infinite_recursion_diagnostic &pd,
bool topmost)
- : function_entry_event (dst_point),
+ : function_entry_event (dst_point, dst_state),
m_pd (pd),
m_topmost (topmost)
{
@@ -146,17 +147,19 @@ public:
const program_point &dst_point = dst_node->get_point ();
if (eedge.m_dest == m_prev_entry_enode)
{
- gcc_assert (m_prev_entry_event == NULL);
+ gcc_assert (m_prev_entry_event == nullptr);
std::unique_ptr<checker_event> prev_entry_event
- = std::make_unique <recursive_function_entry_event> (dst_point,
- *this, false);
+ = std::make_unique <recursive_function_entry_event>
+ (dst_point,
+ dst_node->get_state (),
+ *this, false);
m_prev_entry_event = prev_entry_event.get ();
emission_path->add_event (std::move (prev_entry_event));
}
else if (eedge.m_dest == m_new_entry_enode)
emission_path->add_event
(std::make_unique<recursive_function_entry_event>
- (dst_point, *this, true));
+ (dst_point, dst_node->get_state (), *this, true));
else
pending_diagnostic::add_function_entry_event (eedge, emission_path);
}
@@ -288,7 +291,7 @@ private:
bool m_found_conjured_svalues;
};
- const svalue *sval = model.get_rvalue (expr, NULL);
+ const svalue *sval = model.get_rvalue (expr, nullptr);
conjured_svalue_finder v;
sval->accept (&v);
return v.m_found_conjured_svalues;
@@ -348,7 +351,7 @@ exploded_graph::find_previous_entry_to (function *top_of_stack_fun,
}
/* Not found. */
- return NULL;
+ return nullptr;
}
/* Given BASE_REG within ENCLOSING_FRAME (such as a function parameter),
@@ -382,7 +385,7 @@ remap_enclosing_frame (const region *base_reg,
const decl_region *decl_reg = (const decl_region *)base_reg;
return equiv_prev_frame->get_region_for_local (mgr,
decl_reg->get_decl (),
- NULL);
+ nullptr);
}
}
}
@@ -424,7 +427,7 @@ sufficiently_different_region_binding_p (exploded_node *new_entry_enode,
/* Get the value within the new frame. */
const svalue *new_sval
- = new_model.get_store_value (base_reg, NULL);
+ = new_model.get_store_value (base_reg, nullptr);
/* If any part of the value is UNKNOWN (e.g. due to hitting
complexity limits) assume that it differs from the previous
@@ -444,7 +447,7 @@ sufficiently_different_region_binding_p (exploded_node *new_entry_enode,
to the recursion. */
const int old_stack_depth = prev_entry_enode->get_stack_depth ();
if (enclosing_frame->get_stack_depth () < old_stack_depth)
- prev_sval = prev_model.get_store_value (base_reg, NULL);
+ prev_sval = prev_model.get_store_value (base_reg, nullptr);
else
{
/* Ignore bindings within frames below the new entry node. */
@@ -466,11 +469,11 @@ sufficiently_different_region_binding_p (exploded_node *new_entry_enode,
equiv_prev_frame,
new_model.get_manager ());
prev_sval
- = prev_model.get_store_value (equiv_prev_base_reg, NULL);
+ = prev_model.get_store_value (equiv_prev_base_reg, nullptr);
}
}
else
- prev_sval = prev_model.get_store_value (base_reg, NULL);
+ prev_sval = prev_model.get_store_value (base_reg, nullptr);
/* If the prev_sval contains UNKNOWN (e.g. due to hitting complexity limits)
assume that it will differ from any new value. */
diff --git a/gcc/analyzer/inlining-iterator.h b/gcc/analyzer/inlining-iterator.h
index ac1463d..20d1d2b 100644
--- a/gcc/analyzer/inlining-iterator.h
+++ b/gcc/analyzer/inlining-iterator.h
@@ -46,7 +46,7 @@ class inlining_iterator
public:
inlining_iterator (location_t loc)
: m_abstract_origin (LOCATION_BLOCK (loc)),
- m_callsite (UNKNOWN_LOCATION), m_fndecl (NULL),
+ m_callsite (UNKNOWN_LOCATION), m_fndecl (NULL_TREE),
m_next_abstract_origin (NULL)
{
prepare_iteration ();
@@ -71,7 +71,7 @@ private:
return;
tree block = m_abstract_origin;
m_callsite = BLOCK_SOURCE_LOCATION (block);
- m_fndecl = NULL;
+ m_fndecl = NULL_TREE;
block = BLOCK_SUPERCONTEXT (block);
while (block && TREE_CODE (block) == BLOCK
&& BLOCK_ABSTRACT_ORIGIN (block))
diff --git a/gcc/analyzer/kf-analyzer.cc b/gcc/analyzer/kf-analyzer.cc
index 3e671e5..13476de 100644
--- a/gcc/analyzer/kf-analyzer.cc
+++ b/gcc/analyzer/kf-analyzer.cc
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see
#include "analyzer/region-model.h"
#include "analyzer/pending-diagnostic.h"
#include "analyzer/call-details.h"
+#include "analyzer/program-state.h"
#if ENABLE_ANALYZER
@@ -260,6 +261,11 @@ class dump_path_diagnostic
: public pending_diagnostic_subclass<dump_path_diagnostic>
{
public:
+ dump_path_diagnostic (const program_state &state)
+ : m_state (state)
+ {
+ }
+
int get_controlling_option () const final override
{
return 0;
@@ -280,6 +286,15 @@ public:
{
return true;
}
+
+ const program_state *
+ get_final_state () const final override
+ {
+ return &m_state;
+ }
+
+private:
+ program_state m_state;
};
/* Handle calls to "__analyzer_dump_path" by queuing a diagnostic at this
@@ -297,7 +312,8 @@ public:
region_model_context *ctxt = cd.get_ctxt ();
if (!ctxt)
return;
- ctxt->warn (std::make_unique<dump_path_diagnostic> ());
+ if (const program_state *state = ctxt->get_state ())
+ ctxt->warn (std::make_unique<dump_path_diagnostic> (*state));
}
};
diff --git a/gcc/analyzer/kf.cc b/gcc/analyzer/kf.cc
index 75b6279..fe25520 100644
--- a/gcc/analyzer/kf.cc
+++ b/gcc/analyzer/kf.cc
@@ -1053,11 +1053,11 @@ kf_realloc::impl_call_post (const call_details &cd) const
const svalue *copied_size_sval
= get_copied_size (model, old_size_sval, new_size_sval);
const region *copied_old_reg
- = mgr->get_sized_region (freed_reg, NULL, copied_size_sval);
+ = mgr->get_sized_region (freed_reg, nullptr, copied_size_sval);
const svalue *buffer_content_sval
= model->get_store_value (copied_old_reg, cd.get_ctxt ());
const region *copied_new_reg
- = mgr->get_sized_region (new_reg, NULL, copied_size_sval);
+ = mgr->get_sized_region (new_reg, nullptr, copied_size_sval);
model->set_value (copied_new_reg, buffer_content_sval,
cd.get_ctxt ());
}
@@ -1636,7 +1636,7 @@ kf_strncpy::impl_call_post (const call_details &cd) const
}
private:
/* (strlen + 1) of the source string if it has a terminator,
- or NULL for the case where UB would happen before
+ or nullptr for the case where UB would happen before
finding any terminator. */
const svalue *m_num_bytes_with_terminator_sval;
@@ -1691,8 +1691,8 @@ public:
region_model_manager *mgr = cd.get_manager ();
/* Ideally we'd get the size here, and simulate copying the bytes. */
const region *new_reg
- = model->get_or_create_region_for_heap_alloc (NULL, cd.get_ctxt ());
- model->mark_region_as_unknown (new_reg, NULL);
+ = model->get_or_create_region_for_heap_alloc (nullptr, cd.get_ctxt ());
+ model->mark_region_as_unknown (new_reg, nullptr);
if (cd.get_lhs_type ())
{
const svalue *ptr_sval
diff --git a/gcc/analyzer/known-function-manager.cc b/gcc/analyzer/known-function-manager.cc
index 1a2930e..3b645a8 100644
--- a/gcc/analyzer/known-function-manager.cc
+++ b/gcc/analyzer/known-function-manager.cc
@@ -92,7 +92,7 @@ known_function_manager::add (enum internal_fn ifn,
The call must match all assumptions made by the known_function (such as
e.g. "argument 1's type must be a pointer type").
- Return NULL if no known_function is found, or it does not match the
+ Return nullptr if no known_function is found, or it does not match the
assumption(s). */
const known_function *
@@ -122,16 +122,16 @@ known_function_manager::get_match (tree fndecl, const call_details &cd) const
if (DECL_CONTEXT (fndecl)
&& TREE_CODE (DECL_CONTEXT (fndecl)) != TRANSLATION_UNIT_DECL)
- return NULL;
+ return nullptr;
if (tree identifier = DECL_NAME (fndecl))
if (const known_function *candidate = get_by_identifier (identifier))
if (candidate->matches_call_types_p (cd))
return candidate;
- return NULL;
+ return nullptr;
}
-/* Get any known_function for IFN, or NULL. */
+/* Get any known_function for IFN, or nullptr. */
const known_function *
known_function_manager::get_internal_fn (enum internal_fn ifn) const
@@ -141,7 +141,7 @@ known_function_manager::get_internal_fn (enum internal_fn ifn) const
}
/* Get any known_function for NAME, without type-checking.
- Return NULL if there isn't one. */
+ Return nullptr if there isn't one. */
const known_function *
known_function_manager::get_normal_builtin (enum built_in_function name) const
@@ -160,7 +160,7 @@ get_normal_builtin (const builtin_known_function *builtin_kf) const
}
/* Get any known_function matching IDENTIFIER, without type-checking.
- Return NULL if there isn't one. */
+ Return nullptr if there isn't one. */
const known_function *
known_function_manager::get_by_identifier (tree identifier) const
@@ -170,7 +170,7 @@ known_function_manager::get_by_identifier (tree identifier) const
if (slot)
return *slot;
else
- return NULL;
+ return nullptr;
}
/* Get any known_function in C++ std:: namespace matching IDENTIFIER, without
diff --git a/gcc/analyzer/pending-diagnostic.cc b/gcc/analyzer/pending-diagnostic.cc
index 70dc815..5e95edd 100644
--- a/gcc/analyzer/pending-diagnostic.cc
+++ b/gcc/analyzer/pending-diagnostic.cc
@@ -171,7 +171,7 @@ pending_diagnostic::fixup_location (location_t loc, bool) const
const line_map_macro *macro_map = linemap_check_macro (map);
if (fixup_location_in_macro_p (macro_map->macro))
loc = linemap_resolve_location (line_table, loc,
- LRK_MACRO_EXPANSION_POINT, NULL);
+ LRK_MACRO_EXPANSION_POINT, nullptr);
}
return loc;
}
@@ -185,7 +185,10 @@ pending_diagnostic::add_function_entry_event (const exploded_edge &eedge,
{
const exploded_node *dst_node = eedge.m_dest;
const program_point &dst_point = dst_node->get_point ();
- emission_path->add_event (std::make_unique<function_entry_event> (dst_point));
+ const program_state &dst_state = dst_node->get_state ();
+ emission_path->add_event
+ (std::make_unique<function_entry_event> (dst_point,
+ dst_state));
}
/* Base implementation of pending_diagnostic::add_call_event.
@@ -241,7 +244,8 @@ pending_diagnostic::add_final_event (const state_machine *sm,
(std::make_unique<warning_event>
(loc_info,
enode,
- sm, var, state));
+ sm, var, state,
+ get_final_state ()));
}
} // namespace ana
diff --git a/gcc/analyzer/pending-diagnostic.h b/gcc/analyzer/pending-diagnostic.h
index 6a0289e..469513c 100644
--- a/gcc/analyzer/pending-diagnostic.h
+++ b/gcc/analyzer/pending-diagnostic.h
@@ -364,6 +364,12 @@ class pending_diagnostic
tree var, state_machine::state_t state,
checker_path *emission_path);
+ virtual const program_state *
+ get_final_state () const
+ {
+ return nullptr;
+ }
+
/* Vfunc for determining that this pending_diagnostic supercedes OTHER,
and that OTHER should therefore not be emitted.
They have already been tested for being at the same stmt. */
diff --git a/gcc/analyzer/program-point.cc b/gcc/analyzer/program-point.cc
index c95f863..1f82559 100644
--- a/gcc/analyzer/program-point.cc
+++ b/gcc/analyzer/program-point.cc
@@ -171,7 +171,7 @@ function_point::get_function () const
if (m_supernode)
return m_supernode->m_fun;
else
- return NULL;
+ return nullptr;
}
/* Get the gimple stmt for this function_point, if any. */
@@ -184,7 +184,7 @@ function_point::get_stmt () const
else if (m_kind == PK_AFTER_SUPERNODE)
return m_supernode->get_last_stmt ();
else
- return NULL;
+ return nullptr;
}
/* Get a location for this function_point, if any. */
@@ -219,18 +219,18 @@ function_point::final_stmt_p () const
function_point
function_point::from_function_entry (const supergraph &sg, const function &fun)
{
- return before_supernode (sg.get_node_for_function_entry (fun), NULL);
+ return before_supernode (sg.get_node_for_function_entry (fun), nullptr);
}
/* Create a function_point representing entering supernode SUPERNODE,
- having reached it via FROM_EDGE (which could be NULL). */
+ having reached it via FROM_EDGE (which could be nullptr). */
function_point
function_point::before_supernode (const supernode *supernode,
const superedge *from_edge)
{
if (from_edge && from_edge->get_kind () != SUPEREDGE_CFG_EDGE)
- from_edge = NULL;
+ from_edge = nullptr;
return function_point (supernode, from_edge, 0, PK_BEFORE_SUPERNODE);
}
@@ -673,7 +673,7 @@ function_point::get_next () const
program_point
program_point::origin (const region_model_manager &mgr)
{
- return program_point (function_point (NULL, NULL,
+ return program_point (function_point (nullptr, nullptr,
0, PK_ORIGIN),
mgr.get_empty_call_string ());
}
@@ -766,11 +766,11 @@ namespace selftest {
static void
test_function_point_equality ()
{
- const supernode *snode = NULL;
+ const supernode *snode = nullptr;
- function_point a = function_point (snode, NULL, 0,
+ function_point a = function_point (snode, nullptr, 0,
PK_BEFORE_SUPERNODE);
- function_point b = function_point::before_supernode (snode, NULL);
+ function_point b = function_point::before_supernode (snode, nullptr);
ASSERT_EQ (a, b);
}
@@ -779,12 +779,12 @@ test_function_point_equality ()
static void
test_function_point_ordering ()
{
- const supernode *snode = NULL;
+ const supernode *snode = nullptr;
/* Populate an array with various points within the same
snode, in order. */
auto_vec<function_point> points;
- points.safe_push (function_point::before_supernode (snode, NULL));
+ points.safe_push (function_point::before_supernode (snode, nullptr));
points.safe_push (function_point::before_stmt (snode, 0));
points.safe_push (function_point::before_stmt (snode, 1));
points.safe_push (function_point::after_supernode (snode));
@@ -816,14 +816,14 @@ test_program_point_equality ()
{
region_model_manager mgr;
- const supernode *snode = NULL;
+ const supernode *snode = nullptr;
const call_string &cs = mgr.get_empty_call_string ();
- program_point a = program_point::before_supernode (snode, NULL,
+ program_point a = program_point::before_supernode (snode, nullptr,
cs);
- program_point b = program_point::before_supernode (snode, NULL,
+ program_point b = program_point::before_supernode (snode, nullptr,
cs);
ASSERT_EQ (a, b);
diff --git a/gcc/analyzer/program-point.h b/gcc/analyzer/program-point.h
index 38d83197..fc543c0 100644
--- a/gcc/analyzer/program-point.h
+++ b/gcc/analyzer/program-point.h
@@ -120,23 +120,23 @@ public:
static function_point before_stmt (const supernode *supernode,
unsigned stmt_idx)
{
- return function_point (supernode, NULL, stmt_idx, PK_BEFORE_STMT);
+ return function_point (supernode, nullptr, stmt_idx, PK_BEFORE_STMT);
}
static function_point after_supernode (const supernode *supernode)
{
- return function_point (supernode, NULL, 0, PK_AFTER_SUPERNODE);
+ return function_point (supernode, nullptr, 0, PK_AFTER_SUPERNODE);
}
/* Support for hash_map. */
static function_point empty ()
{
- return function_point (NULL, NULL, 0, PK_EMPTY);
+ return function_point (nullptr, nullptr, 0, PK_EMPTY);
}
static function_point deleted ()
{
- return function_point (NULL, NULL, 0, PK_DELETED);
+ return function_point (nullptr, nullptr, 0, PK_DELETED);
}
static int cmp_within_supernode_1 (const function_point &point_a,
@@ -305,7 +305,7 @@ public:
private:
program_point (const function_point &fn_point)
: m_function_point (fn_point),
- m_call_string (NULL)
+ m_call_string (nullptr)
{
}
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index 21f78e5..c0befac 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -28,6 +28,8 @@ along with GCC; see the file COPYING3. If not see
#include "cgraph.h"
#include "digraph.h"
#include "diagnostic-event-id.h"
+#include "diagnostic-state.h"
+#include "graphviz.h"
#include "text-art/tree-widget.h"
#include "text-art/dump.h"
@@ -48,6 +50,7 @@ along with GCC; see the file COPYING3. If not see
#include "analyzer/state-purge.h"
#include "analyzer/call-summary.h"
#include "analyzer/analyzer-selftests.h"
+#include "analyzer/ana-state-to-diagnostic-state.h"
#if ENABLE_ANALYZER
@@ -112,7 +115,7 @@ extrinsic_state::get_model_manager () const
if (m_engine)
return m_engine->get_model_manager ();
else
- return NULL; /* for selftests. */
+ return nullptr; /* for selftests. */
}
/* Try to find a state machine named NAME.
@@ -255,7 +258,7 @@ DEBUG_FUNCTION void
sm_state_map::dump (bool simple) const
{
tree_dump_pretty_printer pp (stderr);
- print (NULL, simple, true, &pp);
+ print (nullptr, simple, true, &pp);
pp_newline (&pp);
}
@@ -417,7 +420,7 @@ sm_state_map::operator== (const sm_state_map &other) const
const svalue *sval = (*iter).first;
entry_t e = (*iter).second;
entry_t *other_slot = const_cast <map_t &> (other.m_map).get (sval);
- if (other_slot == NULL)
+ if (other_slot == nullptr)
return false;
if (e != *other_slot)
return false;
@@ -498,7 +501,7 @@ sm_state_map::get_origin (const svalue *sval,
if (slot)
return slot->m_origin;
else
- return NULL;
+ return nullptr;
}
/* Set the state of SID within MODEL to STATE, recording that
@@ -511,7 +514,7 @@ sm_state_map::set_state (region_model *model,
const svalue *origin,
const extrinsic_state &ext_state)
{
- if (model == NULL)
+ if (model == nullptr)
return;
/* Reject attempts to set state on UNKNOWN/POISONED. */
@@ -768,7 +771,7 @@ sm_state_map::on_unknown_change (const svalue *sval,
for (svalue_set::iterator iter = svals_to_unset.begin ();
iter != svals_to_unset.end (); ++iter)
- impl_set_state (*iter, (state_machine::state_t)0, NULL, ext_state);
+ impl_set_state (*iter, (state_machine::state_t)0, nullptr, ext_state);
}
/* Purge state for things involving SVAL.
@@ -799,7 +802,7 @@ sm_state_map::purge_state_involving (const svalue *sval,
for (svalue_set::iterator iter = svals_to_unset.begin ();
iter != svals_to_unset.end (); ++iter)
- impl_set_state (*iter, (state_machine::state_t)0, NULL, ext_state);
+ impl_set_state (*iter, (state_machine::state_t)0, nullptr, ext_state);
}
/* Comparator for imposing an order on sm_state_map instances. */
@@ -909,7 +912,7 @@ sm_state_map::can_merge_with_p (const sm_state_map &other,
state_machine::state_t other_state = other.get_state (sval, ext_state);
if (state_machine::state_t merged_state
= sm.maybe_get_merged_state (this_state, other_state))
- (*out)->impl_set_state (sval, merged_state, NULL, ext_state);
+ (*out)->impl_set_state (sval, merged_state, nullptr, ext_state);
else
return false;
}
@@ -923,7 +926,7 @@ sm_state_map::can_merge_with_p (const sm_state_map &other,
/* program_state's ctor. */
program_state::program_state (const extrinsic_state &ext_state)
-: m_region_model (NULL),
+: m_region_model (nullptr),
m_checker_states (ext_state.get_num_checkers ()),
m_valid (true)
{
@@ -957,8 +960,8 @@ sm_state_map::replay_call_summary (call_summary_replay &r,
const svalue *caller_origin
= (summary_origin
? r.convert_svalue_from_summary (summary_origin)
- : NULL);
- // caller_origin can be NULL.
+ : nullptr);
+ // caller_origin can be nullptr.
m_map.put (caller_sval, entry_t (kv.second.m_state, caller_origin));
}
m_global_state = summary.m_global_state;
@@ -1006,7 +1009,7 @@ program_state::program_state (program_state &&other)
: m_region_model (other.m_region_model),
m_checker_states (other.m_checker_states.length ())
{
- other.m_region_model = NULL;
+ other.m_region_model = nullptr;
int i;
sm_state_map *smap;
@@ -1224,6 +1227,18 @@ program_state::make_dump_widget (const text_art::dump_widget_info &dwi) const
return state_widget;
}
+void
+program_state::dump_dot (const extrinsic_state &ext_state) const
+{
+ auto doc = make_xml (ext_state);
+ auto graph = make_dot_graph_from_xml_state (*doc);
+
+ pretty_printer pp;
+ dot::writer w (pp);
+ graph->print (w);
+ pp_flush (&pp);
+}
+
/* Update this program_state to reflect a top-level call to FUN.
The params will have initial_svalues. */
@@ -1322,7 +1337,7 @@ program_state::on_edge (exploded_graph &eg,
return false;
program_state::detect_leaks (enode->get_state (), *this,
- NULL, eg.get_ext_state (),
+ nullptr, eg.get_ext_state (),
&ctxt);
return true;
@@ -1346,7 +1361,7 @@ program_state::push_call (exploded_graph &eg,
&enode->get_state (),
this,
uncertainty,
- NULL,
+ nullptr,
last_stmt);
m_region_model->update_for_gcall (call_stmt, &ctxt);
}
@@ -1369,7 +1384,7 @@ program_state::returning_call (exploded_graph &eg,
&enode->get_state (),
this,
uncertainty,
- NULL,
+ nullptr,
last_stmt);
m_region_model->update_for_return_gcall (call_stmt, &ctxt);
}
@@ -1427,7 +1442,7 @@ program_state::prune_for_point (exploded_graph &eg,
temporaries keep the value reachable until the frame is
popped. */
const svalue *sval
- = new_state.m_region_model->get_store_value (reg, NULL);
+ = new_state.m_region_model->get_store_value (reg, nullptr);
if (!new_state.can_purge_p (eg.get_ext_state (), sval)
&& SSA_NAME_VAR (ssa_name))
{
@@ -1486,9 +1501,9 @@ program_state::prune_for_point (exploded_graph &eg,
impl_region_model_context ctxt (eg, enode_for_diag,
this,
&new_state,
- uncertainty, NULL,
+ uncertainty, nullptr,
point.get_stmt ());
- detect_leaks (*this, new_state, NULL, eg.get_ext_state (), &ctxt);
+ detect_leaks (*this, new_state, nullptr, eg.get_ext_state (), &ctxt);
}
}
@@ -1660,7 +1675,7 @@ program_state::detect_leaks (const program_state &src_state,
*might* still be reachable in dst_state. */
svalue_set known_src_svalues;
src_state.m_region_model->get_reachable_svalues (&known_src_svalues,
- NULL, NULL);
+ nullptr, nullptr);
svalue_set maybe_dest_svalues;
dest_state.m_region_model->get_reachable_svalues (&maybe_dest_svalues,
extra_sval, uncertainty);
@@ -1778,7 +1793,7 @@ test_sm_state_map ()
tree y = build_global_decl ("y", integer_type_node);
tree z = build_global_decl ("z", integer_type_node);
- std::unique_ptr<state_machine> sm = make_malloc_state_machine (NULL);
+ std::unique_ptr<state_machine> sm = make_malloc_state_machine (nullptr);
state_machine::state_t start = sm->get_start_state ();
std::vector<std::unique_ptr<state_machine>> checkers;
const state_machine &borrowed_sm = *sm.get ();
@@ -1792,9 +1807,9 @@ test_sm_state_map ()
const state_machine::state_t TEST_STATE_42 = &test_state_42;
region_model_manager mgr;
region_model model (&mgr);
- const svalue *x_sval = model.get_rvalue (x, NULL);
- const svalue *y_sval = model.get_rvalue (y, NULL);
- const svalue *z_sval = model.get_rvalue (z, NULL);
+ const svalue *x_sval = model.get_rvalue (x, nullptr);
+ const svalue *y_sval = model.get_rvalue (y, nullptr);
+ const svalue *z_sval = model.get_rvalue (z, nullptr);
sm_state_map map (borrowed_sm);
ASSERT_TRUE (map.is_empty_p ());
@@ -1821,16 +1836,16 @@ test_sm_state_map ()
{
region_model_manager mgr;
region_model model (&mgr);
- const svalue *x_sval = model.get_rvalue (x, NULL);
- const svalue *y_sval = model.get_rvalue (y, NULL);
- const svalue *z_sval = model.get_rvalue (z, NULL);
+ const svalue *x_sval = model.get_rvalue (x, nullptr);
+ const svalue *y_sval = model.get_rvalue (y, nullptr);
+ const svalue *z_sval = model.get_rvalue (z, nullptr);
sm_state_map map (borrowed_sm);
ASSERT_TRUE (map.is_empty_p ());
ASSERT_EQ (map.get_state (x_sval, ext_state), start);
ASSERT_EQ (map.get_state (y_sval, ext_state), start);
- model.add_constraint (x, EQ_EXPR, y, NULL);
+ model.add_constraint (x, EQ_EXPR, y, nullptr);
/* Setting x to a state should also update y, as they
are in the same equivalence class. */
@@ -1845,8 +1860,8 @@ test_sm_state_map ()
{
region_model_manager mgr;
region_model model (&mgr);
- const svalue *y_sval = model.get_rvalue (y, NULL);
- const svalue *z_sval = model.get_rvalue (z, NULL);
+ const svalue *y_sval = model.get_rvalue (y, nullptr);
+ const svalue *z_sval = model.get_rvalue (z, nullptr);
sm_state_map map0 (borrowed_sm);
sm_state_map map1 (borrowed_sm);
@@ -1880,17 +1895,17 @@ test_sm_state_map ()
region_model_manager mgr;
region_model model (&mgr);
- const svalue *x_sval = model.get_rvalue (x, NULL);
- const svalue *y_sval = model.get_rvalue (y, NULL);
- const svalue *z_sval = model.get_rvalue (z, NULL);
+ const svalue *x_sval = model.get_rvalue (x, nullptr);
+ const svalue *y_sval = model.get_rvalue (y, nullptr);
+ const svalue *z_sval = model.get_rvalue (z, nullptr);
- map1.impl_set_state (x_sval, TEST_STATE_2, NULL, ext_state);
- map1.impl_set_state (y_sval, TEST_STATE_3, NULL, ext_state);
- map1.impl_set_state (z_sval, TEST_STATE_2, NULL, ext_state);
+ map1.impl_set_state (x_sval, TEST_STATE_2, nullptr, ext_state);
+ map1.impl_set_state (y_sval, TEST_STATE_3, nullptr, ext_state);
+ map1.impl_set_state (z_sval, TEST_STATE_2, nullptr, ext_state);
- map2.impl_set_state (z_sval, TEST_STATE_2, NULL, ext_state);
- map2.impl_set_state (y_sval, TEST_STATE_3, NULL, ext_state);
- map2.impl_set_state (x_sval, TEST_STATE_2, NULL, ext_state);
+ map2.impl_set_state (z_sval, TEST_STATE_2, nullptr, ext_state);
+ map2.impl_set_state (y_sval, TEST_STATE_3, nullptr, ext_state);
+ map2.impl_set_state (x_sval, TEST_STATE_2, nullptr, ext_state);
ASSERT_EQ (map1.hash (), map2.hash ());
ASSERT_EQ (map1, map2);
@@ -1908,7 +1923,7 @@ test_program_state_1 ()
malloc sm-state, pointing to a region on the heap. */
tree p = build_global_decl ("p", ptr_type_node);
- std::unique_ptr<state_machine> sm = make_malloc_state_machine (NULL);
+ std::unique_ptr<state_machine> sm = make_malloc_state_machine (nullptr);
const state_machine::state_t UNCHECKED_STATE
= sm->get_state_by_name ("unchecked");
@@ -1920,13 +1935,13 @@ test_program_state_1 ()
const svalue *size_in_bytes
= mgr->get_or_create_unknown_svalue (size_type_node);
const region *new_reg
- = model->get_or_create_region_for_heap_alloc (size_in_bytes, NULL);
+ = model->get_or_create_region_for_heap_alloc (size_in_bytes, nullptr);
const svalue *ptr_sval = mgr->get_ptr_svalue (ptr_type_node, new_reg);
- model->set_value (model->get_lvalue (p, NULL),
- ptr_sval, NULL);
+ model->set_value (model->get_lvalue (p, nullptr),
+ ptr_sval, nullptr);
sm_state_map *smap = s.m_checker_states[0];
- smap->impl_set_state (ptr_sval, UNCHECKED_STATE, NULL, ext_state);
+ smap->impl_set_state (ptr_sval, UNCHECKED_STATE, nullptr, ext_state);
ASSERT_EQ (smap->get_state (ptr_sval, ext_state), UNCHECKED_STATE);
}
@@ -1947,9 +1962,9 @@ test_program_state_2 ()
program_state s (ext_state);
region_model *model = s.m_region_model;
- const region *p_reg = model->get_lvalue (p, NULL);
- const svalue *str_sval = model->get_rvalue (string_cst_ptr, NULL);
- model->set_value (p_reg, str_sval, NULL);
+ const region *p_reg = model->get_lvalue (p, nullptr);
+ const svalue *str_sval = model->get_rvalue (string_cst_ptr, nullptr);
+ model->set_value (p_reg, str_sval, nullptr);
}
/* Verify that program_states with identical sm-state can be merged,
@@ -1965,7 +1980,7 @@ test_program_state_merging ()
engine eng;
region_model_manager *mgr = eng.get_model_manager ();
program_point point (program_point::origin (*mgr));
- extrinsic_state ext_state (make_malloc_state_machine (NULL),
+ extrinsic_state ext_state (make_malloc_state_machine (nullptr),
&eng);
program_state s0 (ext_state);
@@ -1976,20 +1991,20 @@ test_program_state_merging ()
const svalue *size_in_bytes
= mgr->get_or_create_unknown_svalue (size_type_node);
const region *new_reg
- = model0->get_or_create_region_for_heap_alloc (size_in_bytes, NULL);
+ = model0->get_or_create_region_for_heap_alloc (size_in_bytes, nullptr);
const svalue *ptr_sval = mgr->get_ptr_svalue (ptr_type_node, new_reg);
model0->set_value (model0->get_lvalue (p, &ctxt),
ptr_sval, &ctxt);
sm_state_map *smap = s0.m_checker_states[0];
const state_machine::state test_state ("test state", 0);
const state_machine::state_t TEST_STATE = &test_state;
- smap->impl_set_state (ptr_sval, TEST_STATE, NULL, ext_state);
+ smap->impl_set_state (ptr_sval, TEST_STATE, nullptr, ext_state);
ASSERT_EQ (smap->get_state (ptr_sval, ext_state), TEST_STATE);
model0->canonicalize ();
/* Verify that canonicalization preserves sm-state. */
- ASSERT_EQ (smap->get_state (model0->get_rvalue (p, NULL), ext_state),
+ ASSERT_EQ (smap->get_state (model0->get_rvalue (p, nullptr), ext_state),
TEST_STATE);
/* Make a copy of the program_state. */
@@ -2006,7 +2021,7 @@ test_program_state_merging ()
/* Verify that the merged state has the sm-state for "p". */
region_model *merged_model = merged.m_region_model;
sm_state_map *merged_smap = merged.m_checker_states[0];
- ASSERT_EQ (merged_smap->get_state (merged_model->get_rvalue (p, NULL),
+ ASSERT_EQ (merged_smap->get_state (merged_model->get_rvalue (p, nullptr),
ext_state),
TEST_STATE);
@@ -2015,7 +2030,7 @@ test_program_state_merging ()
merged.validate (ext_state);
/* Verify that the merged state still has the sm-state for "p". */
- ASSERT_EQ (merged_smap->get_state (merged_model->get_rvalue (p, NULL),
+ ASSERT_EQ (merged_smap->get_state (merged_model->get_rvalue (p, nullptr),
ext_state),
TEST_STATE);
@@ -2032,7 +2047,7 @@ test_program_state_merging_2 ()
engine eng;
region_model_manager *mgr = eng.get_model_manager ();
program_point point (program_point::origin (*mgr));
- extrinsic_state ext_state (make_signal_state_machine (NULL), &eng);
+ extrinsic_state ext_state (make_signal_state_machine (nullptr), &eng);
const state_machine::state test_state_0 ("test state 0", 0);
const state_machine::state test_state_1 ("test state 1", 1);
diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h
index 269ffde..e2076c1 100644
--- a/gcc/analyzer/program-state.h
+++ b/gcc/analyzer/program-state.h
@@ -22,6 +22,11 @@ along with GCC; see the file COPYING3. If not see
#define GCC_ANALYZER_PROGRAM_STATE_H
#include "text-art/widget.h"
+#include "text-art/tree-widget.h"
+
+#include "analyzer/store.h"
+
+namespace xml { class document; }
namespace ana {
@@ -32,7 +37,7 @@ class extrinsic_state
public:
extrinsic_state (std::vector<std::unique_ptr<state_machine>> &&checkers,
engine *eng,
- logger *logger = NULL)
+ logger *logger = nullptr)
: m_checkers (std::move (checkers)),
m_logger (logger),
m_engine (eng)
@@ -42,7 +47,7 @@ public:
// For use in selftests that use just one state machine
extrinsic_state (std::unique_ptr<state_machine> sm,
engine *eng,
- logger *logger = NULL)
+ logger *logger = nullptr)
: m_logger (logger),
m_engine (eng)
{
@@ -93,7 +98,7 @@ public:
{
/* Default ctor needed by hash_map::empty. */
entry_t ()
- : m_state (0), m_origin (NULL)
+ : m_state (0), m_origin (nullptr)
{
}
@@ -243,6 +248,12 @@ public:
void dump (const extrinsic_state &ext_state, bool simple) const;
void dump () const;
+ std::unique_ptr<xml::document> make_xml (const extrinsic_state &ext_state) const;
+ void dump_xml_to_pp (const extrinsic_state &ext_state, pretty_printer *pp) const;
+ void dump_xml_to_file (const extrinsic_state &ext_state, FILE *outf) const;
+ void dump_xml (const extrinsic_state &ext_state) const;
+ void dump_dot (const extrinsic_state &ext_state) const;
+
std::unique_ptr<json::object>
to_json (const extrinsic_state &ext_state) const;
diff --git a/gcc/analyzer/record-layout.cc b/gcc/analyzer/record-layout.cc
index aaf8ccd..3446536 100644
--- a/gcc/analyzer/record-layout.cc
+++ b/gcc/analyzer/record-layout.cc
@@ -30,7 +30,7 @@ namespace ana {
/* class record_layout. */
-record_layout::record_layout (tree record_type)
+record_layout::record_layout (const_tree record_type)
{
gcc_assert (TREE_CODE (record_type) == RECORD_TYPE);
@@ -86,7 +86,7 @@ record_layout::get_item_at (bit_offset_t offset) const
FOR_EACH_VEC_ELT (m_items, i, it)
if (it->contains_p (offset))
return it;
- return NULL;
+ return nullptr;
}
/* Subroutine of ctor. Add padding item to NEXT_OFFSET if necessary. */
diff --git a/gcc/analyzer/record-layout.h b/gcc/analyzer/record-layout.h
index c1c4189..8649d1d 100644
--- a/gcc/analyzer/record-layout.h
+++ b/gcc/analyzer/record-layout.h
@@ -36,7 +36,7 @@ public:
{
public:
item (const bit_range &br,
- tree field,
+ const_tree field,
bool is_padding)
: m_bit_range (br),
m_field (field),
@@ -69,17 +69,20 @@ public:
}
bit_range m_bit_range;
- tree m_field;
+ const_tree m_field;
bool m_is_padding;
};
- record_layout (tree record_type);
+ record_layout (const_tree record_type);
void dump_to_pp (pretty_printer *pp) const;
DEBUG_FUNCTION void dump () const;
const record_layout::item *get_item_at (bit_offset_t offset) const;
+ auto begin () const { return m_items.begin (); }
+ auto end () const { return m_items.end (); }
+
private:
void maybe_pad_to (bit_offset_t next_offset);
diff --git a/gcc/analyzer/region-model-asm.cc b/gcc/analyzer/region-model-asm.cc
index 7d7e3b9..d280ae2 100644
--- a/gcc/analyzer/region-model-asm.cc
+++ b/gcc/analyzer/region-model-asm.cc
@@ -119,7 +119,7 @@ deterministic_p (const gasm *asm_stmt)
void
region_model::on_asm_stmt (const gasm *stmt, region_model_context *ctxt)
{
- logger *logger = ctxt ? ctxt->get_logger () : NULL;
+ logger *logger = ctxt ? ctxt->get_logger () : nullptr;
LOG_SCOPE (logger);
const unsigned noutputs = gimple_asm_noutputs (stmt);
@@ -216,7 +216,7 @@ region_model::on_asm_stmt (const gasm *stmt, region_model_context *ctxt)
tree src_expr = input_tvec[i];
const svalue *src_sval = get_rvalue (src_expr, ctxt);
- check_for_poison (src_sval, src_expr, NULL, ctxt);
+ check_for_poison (src_sval, src_expr, nullptr, ctxt);
input_svals.quick_push (src_sval);
reachable_regs.handle_sval (src_sval);
diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc
index df92503..872b1d6 100644
--- a/gcc/analyzer/region-model-manager.cc
+++ b/gcc/analyzer/region-model-manager.cc
@@ -49,7 +49,7 @@ region_model_manager::region_model_manager (logger *logger)
m_root_region (alloc_symbol_id ()),
m_stack_region (alloc_symbol_id (), &m_root_region),
m_heap_region (alloc_symbol_id (), &m_root_region),
- m_unknown_NULL (NULL),
+ m_unknown_NULL (nullptr),
m_checking_feasibility (false),
m_max_complexity (0, 0),
m_code_region (alloc_symbol_id (), &m_root_region),
@@ -259,7 +259,7 @@ region_model_manager::get_or_create_null_ptr (tree pointer_type)
return get_or_create_int_cst (pointer_type, 0);
}
-/* Return the svalue * for a unknown_svalue for TYPE (which can be NULL),
+/* Return the svalue * for a unknown_svalue for TYPE (which can be NULL_TREE),
creating it if necessary.
The unknown_svalue instances are reused, based on pointer equality
of the types */
@@ -407,7 +407,7 @@ region_model_manager::get_ptr_svalue (tree ptr_type, const region *pointee)
/* Subroutine of region_model_manager::get_or_create_unaryop.
Attempt to fold the inputs and return a simpler svalue *.
- Otherwise, return NULL. */
+ Otherwise, return nullptr. */
const svalue *
region_model_manager::maybe_fold_unaryop (tree type, enum tree_code op,
@@ -516,7 +516,7 @@ region_model_manager::maybe_fold_unaryop (tree type, enum tree_code op,
}
}
- return NULL;
+ return nullptr;
}
/* Return the svalue * for an unary operation OP on ARG with a result of
@@ -594,7 +594,7 @@ region_model_manager::get_or_create_cast (tree type, const svalue *arg)
If COMPOUND_SVAL has a value for the appropriate bits, return it,
shifted accordingly.
- Otherwise return NULL. */
+ Otherwise return nullptr. */
const svalue *
region_model_manager::
@@ -606,7 +606,7 @@ maybe_undo_optimize_bit_field_compare (tree type,
if (!type)
return nullptr;
if (!INTEGRAL_TYPE_P (type))
- return NULL;
+ return nullptr;
const binding_map &map = compound_sval->get_map ();
unsigned HOST_WIDE_INT mask = TREE_INT_CST_LOW (cst);
@@ -614,7 +614,7 @@ maybe_undo_optimize_bit_field_compare (tree type,
compound_sval has a value for those bits. */
bit_range bits (0, 0);
if (!bit_range::from_mask (mask, &bits))
- return NULL;
+ return nullptr;
bit_range bound_bits (bits);
if (BYTES_BIG_ENDIAN)
@@ -624,7 +624,7 @@ maybe_undo_optimize_bit_field_compare (tree type,
= get_store_manager ()->get_concrete_binding (bound_bits);
const svalue *sval = map.get (conc);
if (!sval)
- return NULL;
+ return nullptr;
/* We have a value;
shift it by the correct number of bits. */
@@ -641,7 +641,7 @@ maybe_undo_optimize_bit_field_compare (tree type,
/* Subroutine of region_model_manager::get_or_create_binop.
Attempt to fold the inputs and return a simpler svalue *.
- Otherwise, return NULL. */
+ Otherwise, return nullptr. */
const svalue *
region_model_manager::maybe_fold_binop (tree type, enum tree_code op,
@@ -669,7 +669,7 @@ region_model_manager::maybe_fold_binop (tree type, enum tree_code op,
if ((type && FLOAT_TYPE_P (type))
|| (arg0->get_type () && FLOAT_TYPE_P (arg0->get_type ()))
|| (arg1->get_type () && FLOAT_TYPE_P (arg1->get_type ())))
- return NULL;
+ return nullptr;
switch (op)
{
@@ -898,7 +898,7 @@ region_model_manager::maybe_fold_binop (tree type, enum tree_code op,
/* etc. */
- return NULL;
+ return nullptr;
}
/* Return the svalue * for an binary operation OP on ARG0 and ARG1
@@ -933,7 +933,7 @@ region_model_manager::get_or_create_binop (tree type, enum tree_code op,
}
/* Subroutine of region_model_manager::get_or_create_sub_svalue.
- Return a folded svalue, or NULL. */
+ Return a folded svalue, or nullptr. */
const svalue *
region_model_manager::maybe_fold_sub_svalue (tree type,
@@ -1020,7 +1020,7 @@ region_model_manager::maybe_fold_sub_svalue (tree type,
if (type)
return get_or_create_cast (type, repeated_sval->get_inner_svalue ());
- return NULL;
+ return nullptr;
}
/* Return the svalue * for extracting a subvalue of type TYPE from
@@ -1046,7 +1046,7 @@ region_model_manager::get_or_create_sub_svalue (tree type,
}
/* Subroutine of region_model_manager::get_or_create_repeated_svalue.
- Return a folded svalue, or NULL. */
+ Return a folded svalue, or nullptr. */
const svalue *
region_model_manager::maybe_fold_repeated_svalue (tree type,
@@ -1080,7 +1080,7 @@ region_model_manager::maybe_fold_repeated_svalue (tree type,
if (zerop (cst) && type)
return get_or_create_cast (type, inner_svalue);
- return NULL;
+ return nullptr;
}
/* Return the svalue * of type TYPE in which INNER_SVALUE is repeated
@@ -1274,7 +1274,7 @@ region_model_manager::maybe_fold_bits_within_svalue (tree type,
}
break;
}
- return NULL;
+ return nullptr;
}
/* Return the svalue * of type TYPE for extracting BITS from INNER_SVALUE,
@@ -1401,7 +1401,7 @@ region_model_manager::get_or_create_conjured_svalue (tree type,
}
/* Subroutine of region_model_manager::get_or_create_asm_output_svalue.
- Return a folded svalue, or NULL. */
+ Return a folded svalue, or nullptr. */
const svalue *
region_model_manager::
@@ -1413,7 +1413,7 @@ maybe_fold_asm_output_svalue (tree type,
if (iter->get_kind () == SK_UNKNOWN)
return get_or_create_unknown_svalue (type);
- return NULL;
+ return nullptr;
}
/* Return the svalue * of type TYPE for OUTPUT_IDX of the deterministic
@@ -1501,7 +1501,7 @@ get_or_create_const_fn_result_svalue (tree type,
/* Given DATA_CST (a STRING_CST or RAW_DATA_CST) and BYTE_OFFSET_CST a constant,
attempt to get the character at that offset, returning either
- the svalue for the character constant, or NULL if unsuccessful. */
+ the svalue for the character constant, or nullptr if unsuccessful. */
const svalue *
region_model_manager::maybe_get_char_from_cst (tree data_cst,
@@ -1533,7 +1533,7 @@ get_string_cst_size (const_tree string_cst)
/* Given STRING_CST, a STRING_CST and BYTE_OFFSET_CST a constant,
attempt to get the character at that offset, returning either
- the svalue for the character constant, or NULL if unsuccessful. */
+ the svalue for the character constant, or nullptr if unsuccessful. */
const svalue *
region_model_manager::maybe_get_char_from_string_cst (tree string_cst,
@@ -1552,7 +1552,7 @@ region_model_manager::maybe_get_char_from_string_cst (tree string_cst,
if (compare_constants (byte_offset_cst,
GE_EXPR,
get_string_cst_size (string_cst)).is_true ())
- return NULL;
+ return nullptr;
int char_val;
if (compare_tree_int (byte_offset_cst,
@@ -1567,12 +1567,12 @@ region_model_manager::maybe_get_char_from_string_cst (tree string_cst,
= build_int_cst_type (TREE_TYPE (TREE_TYPE (string_cst)), char_val);
return get_or_create_constant_svalue (char_cst);
}
- return NULL;
+ return nullptr;
}
/* Given RAW_DATA_CST, a RAW_DATA_CST and BYTE_OFFSET_CST a constant,
attempt to get the character at that offset, returning either
- the svalue for the character constant, or NULL if unsuccessful. */
+ the svalue for the character constant, or nullptr if unsuccessful. */
const svalue *
region_model_manager::maybe_get_char_from_raw_data_cst (tree raw_data_cst,
@@ -1801,7 +1801,7 @@ region_model_manager::get_cast_region (const region *original_region,
}
/* Return the frame_region for call to FUN from CALLING_FRAME, creating it
- if necessary. CALLING_FRAME may be NULL. */
+ if necessary. CALLING_FRAME may be nullptr. */
const frame_region *
region_model_manager::get_frame_region (const frame_region *calling_frame,
diff --git a/gcc/analyzer/region-model-manager.h b/gcc/analyzer/region-model-manager.h
index c3f0a64..865bedf 100644
--- a/gcc/analyzer/region-model-manager.h
+++ b/gcc/analyzer/region-model-manager.h
@@ -31,7 +31,7 @@ namespace ana {
class region_model_manager
{
public:
- region_model_manager (logger *logger = NULL);
+ region_model_manager (logger *logger = nullptr);
~region_model_manager ();
unsigned get_num_symbols () const { return m_next_symbol_id; }
diff --git a/gcc/analyzer/region-model-reachability.cc b/gcc/analyzer/region-model-reachability.cc
index d3bfeb7..0fe324d 100644
--- a/gcc/analyzer/region-model-reachability.cc
+++ b/gcc/analyzer/region-model-reachability.cc
@@ -68,7 +68,7 @@ reachable_regions::init_cluster (const region *base_reg)
if (const symbolic_region *sym_reg = base_reg->dyn_cast_symbolic_region ())
{
const svalue *ptr = sym_reg->get_pointer ();
- if (ptr->implicitly_live_p (NULL, m_model))
+ if (ptr->implicitly_live_p (nullptr, m_model))
add (base_reg, true);
switch (ptr->get_kind ())
{
@@ -84,7 +84,7 @@ reachable_regions::init_cluster (const region *base_reg)
const region *other_base_reg = init_sval_reg->get_base_region ();
const binding_cluster *other_cluster
= m_store->get_cluster (other_base_reg);
- if (other_cluster == NULL
+ if (other_cluster == nullptr
|| !other_cluster->touched_p ())
add (base_reg, true);
}
@@ -131,7 +131,7 @@ reachable_regions::add (const region *reg, bool is_mutable)
if (binding_cluster *bind_cluster = m_store->get_cluster (base_reg))
bind_cluster->for_each_value (handle_sval_cb, this);
else
- handle_sval (m_model->get_store_value (reg, NULL));
+ handle_sval (m_model->get_store_value (reg, nullptr));
}
void
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 1ee882c..6df3842 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -159,7 +159,7 @@ region_to_value_map::operator== (const region_to_value_map &other) const
const region *reg = iter.first;
const svalue *sval = iter.second;
const svalue * const *other_slot = other.get (reg);
- if (other_slot == NULL)
+ if (other_slot == nullptr)
return false;
if (sval != *other_slot)
return false;
@@ -403,7 +403,7 @@ exception_node::add_to_reachable_regions (reachable_regions &regs) const
/* Ctor for region_model: construct an "empty" model. */
region_model::region_model (region_model_manager *mgr)
-: m_mgr (mgr), m_store (), m_current_frame (NULL),
+: m_mgr (mgr), m_store (), m_current_frame (nullptr),
m_thrown_exceptions_stack (),
m_caught_exceptions_stack (),
m_dynamic_extents ()
@@ -895,7 +895,7 @@ public:
/* Couldn't get state; accept this diagnostic. */
return true;
- const svalue *fsval = emission_model.get_rvalue (m_check_expr, NULL);
+ const svalue *fsval = emission_model.get_rvalue (m_check_expr, nullptr);
/* Check to see if the expr is also poisoned in FNODE (and in the
same way). */
const poisoned_svalue * fspval = fsval->dyn_cast_poisoned_svalue ();
@@ -1173,7 +1173,7 @@ check_for_invalid_ptrdiff (const gassign *assign,
/* If ASSIGN is a stmt that can be modelled via
set_value (lhs_reg, SVALUE, CTXT)
for some SVALUE, get the SVALUE.
- Otherwise return NULL. */
+ Otherwise return nullptr. */
const svalue *
region_model::get_gassign_result (const gassign *assign,
@@ -1196,7 +1196,7 @@ region_model::get_gassign_result (const gassign *assign,
switch (op)
{
default:
- return NULL;
+ return nullptr;
case POINTER_PLUS_EXPR:
{
@@ -1461,8 +1461,8 @@ within_short_circuited_stmt_p (const region_model *model,
that implies that the value of the second arg doesn't matter, i.e.
1 for bitwise or, 0 for bitwise and. */
tree other_arg = gimple_assign_rhs1 (use_assign);
- /* Use a NULL ctxt here to avoid generating warnings. */
- const svalue *other_arg_sval = model->get_rvalue (other_arg, NULL);
+ /* Use a nullptr ctxt here to avoid generating warnings. */
+ const svalue *other_arg_sval = model->get_rvalue (other_arg, nullptr);
tree other_arg_cst = other_arg_sval->maybe_get_constant ();
if (!other_arg_cst)
return false;
@@ -1529,7 +1529,7 @@ due_to_ifn_deferred_init_p (const gassign *assign_stmt)
/* Check for SVAL being poisoned, adding a warning to CTXT.
Return SVAL, or, if a warning is added, another value, to avoid
repeatedly complaining about the same poisoned value in followup code.
- SRC_REGION is a hint about where SVAL came from, and can be NULL. */
+ SRC_REGION is a hint about where SVAL came from, and can be nullptr. */
const svalue *
region_model::check_for_poison (const svalue *sval,
@@ -1572,7 +1572,7 @@ region_model::check_for_poison (const svalue *sval,
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 == nullptr && pkind == poison_kind::uninit)
src_region = get_region_for_poisoned_expr (expr);
/* Can we reliably get the poisoned value from "expr"?
@@ -1581,11 +1581,11 @@ region_model::check_for_poison (const svalue *sval,
Hence we only query its value now, and only use it if we get the
poisoned value back again. */
tree check_expr = expr;
- const svalue *foo_sval = get_rvalue (expr, NULL);
+ const svalue *foo_sval = get_rvalue (expr, nullptr);
if (foo_sval == sval)
check_expr = expr;
else
- check_expr = NULL;
+ check_expr = nullptr;
if (ctxt->warn
(std::make_unique<poisoned_value_diagnostic> (diag_arg,
pkind,
@@ -1606,7 +1606,7 @@ region_model::check_for_poison (const svalue *sval,
/* Attempt to get a region for describing EXPR, the source of region of
a poisoned_svalue for use in a poisoned_value_diagnostic.
- Return NULL if there is no good region to use. */
+ Return nullptr if there is no good region to use. */
const region *
region_model::get_region_for_poisoned_expr (tree expr) const
@@ -1617,9 +1617,9 @@ region_model::get_region_for_poisoned_expr (tree expr) const
if (decl && DECL_P (decl))
expr = decl;
else
- return NULL;
+ return nullptr;
}
- return get_lvalue (expr, NULL);
+ return get_lvalue (expr, nullptr);
}
/* Update this model for the ASSIGN stmt, using CTXT to report any
@@ -1648,7 +1648,7 @@ region_model::on_assignment (const gassign *assign, region_model_context *ctxt)
if (const svalue *sval = get_gassign_result (assign, ctxt))
{
tree expr = get_diagnostic_tree_for_gassign (assign);
- check_for_poison (sval, expr, NULL, ctxt);
+ check_for_poison (sval, expr, nullptr, ctxt);
set_value (lhs_reg, sval, ctxt);
return;
}
@@ -1708,7 +1708,7 @@ region_model::on_assignment (const gassign *assign, region_model_context *ctxt)
/* e.g. "struct s2 x = {{'A', 'B', 'C', 'D'}};". */
const svalue *rhs_sval = get_rvalue (rhs1, ctxt);
m_store.set_value (m_mgr->get_store_manager(), lhs_reg, rhs_sval,
- ctxt ? ctxt->get_uncertainty () : NULL);
+ ctxt ? ctxt->get_uncertainty () : nullptr);
}
break;
}
@@ -1939,7 +1939,7 @@ region_model::update_for_nonzero_return (const call_details &cd)
to set an upper bound on the size of a copy_to_user.
Attempt to simplify such sizes by trying to get the upper bound as a
constant.
- Return the simplified svalue if possible, or NULL otherwise. */
+ Return the simplified svalue if possible, or nullptr otherwise. */
static const svalue *
maybe_simplify_upper_bound (const svalue *num_bytes_sval,
@@ -1957,7 +1957,7 @@ maybe_simplify_upper_bound (const svalue *num_bytes_sval,
when recording the diagnostic, or note that we're using
the upper bound. */
}
- return NULL;
+ return nullptr;
}
/* Attempt to get an upper bound for the size of a copy when simulating a
@@ -1968,7 +1968,7 @@ maybe_simplify_upper_bound (const svalue *num_bytes_sval,
that, use the size of SRC_REG if constant.
Return a symbolic value for an upper limit on the number of bytes
- copied, or NULL if no such value could be determined. */
+ copied, or nullptr if no such value could be determined. */
const svalue *
region_model::maybe_get_copy_bounds (const region *src_reg,
@@ -1994,7 +1994,7 @@ region_model::maybe_get_copy_bounds (const region *src_reg,
return num_bytes_sval;
/* Non-constant: give up. */
- return NULL;
+ return nullptr;
}
/* Get any known_function for FNDECL for call CD.
@@ -2002,7 +2002,7 @@ region_model::maybe_get_copy_bounds (const region *src_reg,
The call must match all assumptions made by the known_function (such as
e.g. "argument 1's type must be a pointer type").
- Return NULL if no known_function is found, or it does not match the
+ Return nullptr if no known_function is found, or it does not match the
assumption(s). */
const known_function *
@@ -2012,7 +2012,7 @@ region_model::get_known_function (tree fndecl, const call_details &cd) const
return known_fn_mgr->get_match (fndecl, cd);
}
-/* Get any known_function for IFN, or NULL. */
+/* Get any known_function for IFN, or nullptr. */
const known_function *
region_model::get_known_function (enum internal_fn ifn) const
@@ -2022,12 +2022,12 @@ region_model::get_known_function (enum internal_fn ifn) const
}
/* Get any builtin_known_function for CALL and emit any warning to CTXT
- if not NULL.
+ if not nullptr.
The call must match all assumptions made by the known_function (such as
e.g. "argument 1's type must be a pointer type").
- Return NULL if no builtin_known_function is found, or it does
+ Return nullptr if no builtin_known_function is found, or it does
not match the assumption(s).
Internally calls get_known_function to find a known_function and cast it
@@ -2063,18 +2063,18 @@ region_model::get_known_function (enum internal_fn ifn) const
const builtin_known_function *
region_model::get_builtin_kf (const gcall &call,
- region_model_context *ctxt /* = NULL */) const
+ region_model_context *ctxt /* = nullptr */) const
{
region_model *mut_this = const_cast <region_model *> (this);
tree callee_fndecl = mut_this->get_fndecl_for_call (call, ctxt);
if (! callee_fndecl)
- return NULL;
+ return nullptr;
call_details cd (call, mut_this, ctxt);
if (const known_function *kf = get_known_function (callee_fndecl, cd))
return kf->dyn_cast_builtin_kf ();
- return NULL;
+ return nullptr;
}
/* Subclass of custom_edge_info for use by exploded_edges that represent
@@ -2090,7 +2090,7 @@ public:
{
}
- void print (pretty_printer *pp) const
+ void print (pretty_printer *pp) const final override
{
if (m_fndecl)
pp_printf (pp, "if %qD throws an exception...", m_fndecl);
@@ -2677,7 +2677,7 @@ region_model::handle_unrecognized_call (const gcall &call,
}
}
- uncertainty_t *uncertainty = ctxt ? ctxt->get_uncertainty () : NULL;
+ uncertainty_t *uncertainty = ctxt ? ctxt->get_uncertainty () : nullptr;
/* Purge sm-state for the svalues that were reachable,
both in non-mutable and mutable form. */
@@ -2839,7 +2839,7 @@ region_model::on_longjmp (const gcall &longjmp_call, const gcall &setjmp_call,
setjmp was called. */
gcc_assert (get_stack_depth () >= setjmp_stack_depth);
while (get_stack_depth () > setjmp_stack_depth)
- pop_frame (NULL, NULL, ctxt, nullptr, false);
+ pop_frame (nullptr, nullptr, ctxt, nullptr, false);
gcc_assert (get_stack_depth () == setjmp_stack_depth);
@@ -3040,7 +3040,7 @@ const region *
region_model::get_lvalue (path_var pv, region_model_context *ctxt) const
{
if (pv.m_tree == NULL_TREE)
- return NULL;
+ return nullptr;
const region *result_reg = get_lvalue_1 (pv, ctxt);
assert_compat_types (result_reg->get_type (), TREE_TYPE (pv.m_tree));
@@ -3185,13 +3185,13 @@ const svalue *
region_model::get_rvalue (path_var pv, region_model_context *ctxt) const
{
if (pv.m_tree == NULL_TREE)
- return NULL;
+ return nullptr;
const svalue *result_sval = get_rvalue_1 (pv, ctxt);
assert_compat_types (result_sval->get_type (), TREE_TYPE (pv.m_tree));
- result_sval = check_for_poison (result_sval, pv.m_tree, NULL, ctxt);
+ result_sval = check_for_poison (result_sval, pv.m_tree, nullptr, ctxt);
return result_sval;
}
@@ -3579,7 +3579,7 @@ void
region_model::check_for_writable_region (const region* dest_reg,
region_model_context *ctxt) const
{
- /* Fail gracefully if CTXT is NULL. */
+ /* Fail gracefully if CTXT is nullptr. */
if (!ctxt)
return;
@@ -3644,13 +3644,13 @@ region_model::get_capacity (const region *reg) const
{
tree type = TREE_TYPE (decl);
tree size = TYPE_SIZE (type);
- return get_rvalue (size, NULL);
+ return get_rvalue (size, nullptr);
}
else
{
tree size = decl_init_size (decl, false);
if (size)
- return get_rvalue (size, NULL);
+ return get_rvalue (size, nullptr);
}
}
break;
@@ -3727,7 +3727,7 @@ bool
region_model::check_region_for_read (const region *src_reg,
region_model_context *ctxt) const
{
- return check_region_access (src_reg, access_direction::read, NULL, ctxt);
+ return check_region_access (src_reg, access_direction::read, nullptr, ctxt);
}
/* Concrete subclass for casts of pointers that lead to trailing bytes. */
@@ -4115,7 +4115,7 @@ void
region_model::check_region_size (const region *lhs_reg, const svalue *rhs_sval,
region_model_context *ctxt) const
{
- if (!ctxt || ctxt->get_stmt () == NULL)
+ if (!ctxt || ctxt->get_stmt () == nullptr)
return;
/* Only report warnings on assignments that actually change the type. */
if (!is_any_cast_p (ctxt->get_stmt ()))
@@ -4208,7 +4208,7 @@ region_model::set_value (const region *lhs_reg, const svalue *rhs_sval,
check_region_for_write (lhs_reg, rhs_sval, ctxt);
m_store.set_value (m_mgr->get_store_manager(), lhs_reg, rhs_sval,
- ctxt ? ctxt->get_uncertainty () : NULL);
+ ctxt ? ctxt->get_uncertainty () : nullptr);
}
/* Set the value of the region given by LHS to the value given by RHS. */
@@ -4845,7 +4845,7 @@ region_model::scan_for_null_terminator (const region *reg,
Simulate scanning through the buffer, reading until we find a 0 byte
(equivalent to calling strlen).
- Complain and return NULL if:
+ Complain and return nullptr if:
- the buffer pointed to isn't null-terminated
- the buffer pointed to has any uninitalized bytes before any 0-terminator
- any of the reads aren't within the bounds of the underlying base region
@@ -4873,7 +4873,7 @@ region_model::check_for_null_terminated_string_arg (const call_details &cd,
Simulate scanning through the buffer, reading until we find a 0 byte
(equivalent to calling strlen).
- Complain and return NULL if:
+ Complain and return nullptr if:
- the buffer pointed to isn't null-terminated
- the buffer pointed to has any uninitalized bytes before any 0-terminator
- any of the reads aren't within the bounds of the underlying base region
@@ -4882,7 +4882,7 @@ region_model::check_for_null_terminated_string_arg (const call_details &cd,
(including the null terminator) if INCLUDE_TERMINATOR is true, or strlen
of the buffer (not including the null terminator) if it is false.
- Also, when returning an svalue, if OUT_SVAL is non-NULL, write to
+ Also, when returning an svalue, if OUT_SVAL is non-nullptr, write to
*OUT_SVAL with an svalue representing the content of the buffer up to
and including the terminator.
@@ -5845,7 +5845,7 @@ region_model::get_representative_path_var (const svalue *sval,
svalue_set *visited,
logger *logger) const
{
- if (sval == NULL)
+ if (sval == nullptr)
return path_var (NULL_TREE, 0);
LOG_SCOPE (logger);
@@ -6204,7 +6204,7 @@ region_model::maybe_update_for_edge (const superedge &edge,
break;
}
- if (last_stmt == NULL)
+ if (last_stmt == nullptr)
return true;
/* Apply any constraints for conditionals/switch/computed-goto statements. */
@@ -6285,7 +6285,7 @@ region_model::update_for_return_gcall (const gcall &call_stmt,
so that pop_frame can determine the region with respect to the
*caller* frame. */
tree lhs = gimple_call_lhs (&call_stmt);
- pop_frame (lhs, NULL, ctxt, &call_stmt);
+ pop_frame (lhs, nullptr, ctxt, &call_stmt);
}
/* Extract calling information from the superedge and update the model for the
@@ -6361,7 +6361,7 @@ apply_constraints_for_gcond (const cfg_superedge &sedge,
std::unique_ptr<rejected_constraint> *out)
{
::edge cfg_edge = sedge.get_cfg_edge ();
- gcc_assert (cfg_edge != NULL);
+ gcc_assert (cfg_edge != nullptr);
gcc_assert (cfg_edge->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE));
enum tree_code op = gimple_cond_code (cond_stmt);
@@ -6379,7 +6379,7 @@ static bool
has_nondefault_case_for_value_p (const gswitch *switch_stmt, tree int_cst)
{
/* We expect the initial label to be the default; skip it. */
- gcc_assert (CASE_LOW (gimple_switch_label (switch_stmt, 0)) == NULL);
+ gcc_assert (CASE_LOW (gimple_switch_label (switch_stmt, 0)) == NULL_TREE);
unsigned min_idx = 1;
unsigned max_idx = gimple_switch_num_labels (switch_stmt) - 1;
@@ -6981,7 +6981,7 @@ region_model::pop_frame (tree result_lvalue,
/* Evaluate the result, within the callee frame. */
tree fndecl = m_current_frame->get_function ().decl;
tree result = DECL_RESULT (fndecl);
- const svalue *retval = NULL;
+ const svalue *retval = nullptr;
if (result
&& TREE_TYPE (result) != void_type_node
&& eval_return_svalue)
@@ -7312,7 +7312,7 @@ private:
class contains_floating_point_visitor : public visitor
{
public:
- contains_floating_point_visitor (const svalue *root_sval) : m_result (NULL)
+ contains_floating_point_visitor (const svalue *root_sval) : m_result (nullptr)
{
root_sval->accept (this);
}
@@ -7476,7 +7476,7 @@ region_model::set_dynamic_extents (const region *reg,
m_dynamic_extents.put (reg, size_in_bytes);
}
-/* Get the recording of REG in bytes, or NULL if no dynamic size was
+/* Get the recording of REG in bytes, or nullptr if no dynamic size was
recorded. */
const svalue *
@@ -7484,7 +7484,7 @@ region_model::get_dynamic_extents (const region *reg) const
{
if (const svalue * const *slot = m_dynamic_extents.get (reg))
return *slot;
- return NULL;
+ return nullptr;
}
/* Unset any recorded dynamic size of REG. */
@@ -7798,7 +7798,7 @@ private:
static void
complain_about_fully_uninit_item (const record_layout::item &item)
{
- tree field = item.m_field;
+ const_tree field = item.m_field;
bit_size_t num_bits = item.m_bit_range.m_size_in_bits;
if (item.m_is_padding)
{
@@ -7859,7 +7859,7 @@ private:
static void
complain_about_partially_uninit_item (const record_layout::item &item)
{
- tree field = item.m_field;
+ const_tree field = item.m_field;
if (item.m_is_padding)
inform (DECL_SOURCE_LOCATION (field),
"padding after field %qD is partially uninitialized",
@@ -7930,7 +7930,7 @@ contains_uninit_p (const svalue *sval)
Check that COPIED_SVAL is fully initialized. If not, complain about
an infoleak to CTXT.
- SRC_REG can be NULL; if non-NULL it is used as a hint in the diagnostic
+ SRC_REG can be nullptr; if non-NULL it is used as a hint in the diagnostic
as to where COPIED_SVAL came from. */
void
@@ -8083,8 +8083,8 @@ void
rejected_op_constraint::dump_to_pp (pretty_printer *pp) const
{
region_model m (m_model);
- const svalue *lhs_sval = m.get_rvalue (m_lhs, NULL);
- const svalue *rhs_sval = m.get_rvalue (m_rhs, NULL);
+ const svalue *lhs_sval = m.get_rvalue (m_lhs, nullptr);
+ const svalue *rhs_sval = m.get_rvalue (m_rhs, nullptr);
lhs_sval->dump_to_pp (pp, true);
pp_printf (pp, " %s ", op_symbol_code (m_op));
rhs_sval->dump_to_pp (pp, true);
@@ -8104,7 +8104,7 @@ void
rejected_ranges_constraint::dump_to_pp (pretty_printer *pp) const
{
region_model m (m_model);
- const svalue *sval = m.get_rvalue (m_expr, NULL);
+ const svalue *sval = m.get_rvalue (m_expr, nullptr);
sval->dump_to_pp (pp, true);
pp_string (pp, " in ");
m_ranges->dump_to_pp (pp, true);
@@ -8205,7 +8205,7 @@ assert_condition (const location &loc,
tree lhs, tree_code op, tree rhs,
tristate expected)
{
- tristate actual = model.eval_condition (lhs, op, rhs, NULL);
+ tristate actual = model.eval_condition (lhs, op, rhs, nullptr);
ASSERT_EQ_AT (loc, actual, expected);
}
@@ -8294,7 +8294,7 @@ make_test_compound_type (const char *name, bool is_struct,
TYPE_NAME (t) = get_identifier (name);
TYPE_SIZE (t) = 0;
- tree fieldlist = NULL;
+ tree fieldlist = NULL_TREE;
int i;
tree field;
FOR_EACH_VEC_ELT (*fields, i, field)
@@ -8349,22 +8349,22 @@ test_struct ()
region_model_manager mgr;
region_model model (&mgr);
- model.set_value (c_x, int_17, NULL);
- model.set_value (c_y, int_m3, NULL);
+ model.set_value (c_x, int_17, nullptr);
+ model.set_value (c_y, int_m3, nullptr);
/* Verify get_offset for "c.x". */
{
- const region *c_x_reg = model.get_lvalue (c_x, NULL);
+ const region *c_x_reg = model.get_lvalue (c_x, nullptr);
region_offset offset = c_x_reg->get_offset (&mgr);
- ASSERT_EQ (offset.get_base_region (), model.get_lvalue (c, NULL));
+ ASSERT_EQ (offset.get_base_region (), model.get_lvalue (c, nullptr));
ASSERT_EQ (offset.get_bit_offset (), 0);
}
/* Verify get_offset for "c.y". */
{
- const region *c_y_reg = model.get_lvalue (c_y, NULL);
+ const region *c_y_reg = model.get_lvalue (c_y, nullptr);
region_offset offset = c_y_reg->get_offset (&mgr);
- ASSERT_EQ (offset.get_base_region (), model.get_lvalue (c, NULL));
+ ASSERT_EQ (offset.get_base_region (), model.get_lvalue (c, nullptr));
ASSERT_EQ (offset.get_bit_offset (), INT_TYPE_SIZE);
}
}
@@ -8385,7 +8385,7 @@ test_array_1 ()
tree a_0 = build4 (ARRAY_REF, char_type_node,
a, int_0, NULL_TREE, NULL_TREE);
tree char_A = build_int_cst (char_type_node, 'A');
- model.set_value (a_0, char_A, NULL);
+ model.set_value (a_0, char_A, nullptr);
}
/* Verify that region_model::get_representative_tree works as expected. */
@@ -8399,7 +8399,7 @@ test_get_representative_tree ()
{
tree string_cst = build_string (4, "foo");
region_model m (&mgr);
- const svalue *str_sval = m.get_rvalue (string_cst, NULL);
+ const svalue *str_sval = m.get_rvalue (string_cst, nullptr);
tree rep = m.get_representative_tree (str_sval);
ASSERT_EQ (rep, string_cst);
}
@@ -8408,7 +8408,7 @@ test_get_representative_tree ()
{
tree string_cst_ptr = build_string_literal (4, "foo");
region_model m (&mgr);
- const svalue *str_sval = m.get_rvalue (string_cst_ptr, NULL);
+ const svalue *str_sval = m.get_rvalue (string_cst_ptr, nullptr);
tree rep = m.get_representative_tree (str_sval);
ASSERT_DUMP_TREE_EQ (rep, "&\"foo\"[0]");
}
@@ -8533,12 +8533,12 @@ test_unique_unknowns ()
/* Different types (or the NULL type) should have different
unknown_svalues. */
- const svalue *unknown_NULL_type = mgr.get_or_create_unknown_svalue (NULL);
+ const svalue *unknown_NULL_type = mgr.get_or_create_unknown_svalue (nullptr);
ASSERT_NE (unknown_NULL_type, unknown_int);
/* Repeated calls with NULL for the type should get the same "unknown"
svalue. */
- const svalue *unknown_NULL_type_2 = mgr.get_or_create_unknown_svalue (NULL);
+ const svalue *unknown_NULL_type_2 = mgr.get_or_create_unknown_svalue (nullptr);
ASSERT_EQ (unknown_NULL_type, unknown_NULL_type_2);
}
@@ -8882,9 +8882,9 @@ test_assignment ()
region_model model (&mgr);
ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
ASSERT_CONDITION_UNKNOWN (model, y, EQ_EXPR, int_0);
- model.set_value (model.get_lvalue (y, NULL),
- model.get_rvalue (int_0, NULL),
- NULL);
+ model.set_value (model.get_lvalue (y, nullptr),
+ model.get_rvalue (int_0, nullptr),
+ nullptr);
ASSERT_CONDITION_TRUE (model, y, EQ_EXPR, int_0);
ASSERT_CONDITION_TRUE (model, y, EQ_EXPR, x);
}
@@ -8912,16 +8912,16 @@ test_compound_assignment ()
region_model_manager mgr;
region_model model (&mgr);
- model.set_value (c_x, int_17, NULL);
- model.set_value (c_y, int_m3, NULL);
+ model.set_value (c_x, int_17, nullptr);
+ model.set_value (c_y, int_m3, nullptr);
/* Copy c to d. */
- const svalue *sval = model.get_rvalue (c, NULL);
- model.set_value (model.get_lvalue (d, NULL), sval, NULL);
+ const svalue *sval = model.get_rvalue (c, nullptr);
+ model.set_value (model.get_lvalue (d, nullptr), sval, nullptr);
/* Check that the fields have the same svalues. */
- ASSERT_EQ (model.get_rvalue (c_x, NULL), model.get_rvalue (d_x, NULL));
- ASSERT_EQ (model.get_rvalue (c_y, NULL), model.get_rvalue (d_y, NULL));
+ ASSERT_EQ (model.get_rvalue (c_x, nullptr), model.get_rvalue (d_x, nullptr));
+ ASSERT_EQ (model.get_rvalue (c_y, nullptr), model.get_rvalue (d_y, nullptr));
}
/* Verify the details of pushing and popping stack frames. */
@@ -9011,7 +9011,7 @@ test_stack_frames ()
model.set_value (p_in_globals_reg,
mgr.get_ptr_svalue (ptr_type_node, x_in_child_reg),
&ctxt);
- ASSERT_EQ (p_in_globals_reg->maybe_get_frame_region (), NULL);
+ ASSERT_EQ (p_in_globals_reg->maybe_get_frame_region (), nullptr);
/* Point another global pointer at p: q = &p. */
const region *q_in_globals_reg = model.get_lvalue (q, &ctxt);
@@ -9025,13 +9025,13 @@ test_stack_frames ()
ASSERT_FALSE (a_in_parent_reg->descendent_of_p (child_frame_reg));
/* Pop the "child_fn" frame from the stack. */
- model.pop_frame (NULL, NULL, &ctxt, nullptr);
+ model.pop_frame (nullptr, nullptr, &ctxt, nullptr);
ASSERT_FALSE (model.region_exists_p (child_frame_reg));
ASSERT_TRUE (model.region_exists_p (parent_frame_reg));
/* Verify that p (which was pointing at the local "x" in the popped
frame) has been poisoned. */
- const svalue *new_p_sval = model.get_rvalue (p, NULL);
+ const svalue *new_p_sval = model.get_rvalue (p, nullptr);
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);
@@ -9109,7 +9109,7 @@ test_get_representative_path_var ()
}
/* ...and that we can lookup lvalues for locals for all frames,
not just the top. */
- ASSERT_EQ (model.get_lvalue (path_var (n, depth), NULL),
+ ASSERT_EQ (model.get_lvalue (path_var (n, depth), nullptr),
parm_regs[depth]);
/* ...and that we can locate the svalues. */
{
@@ -9138,22 +9138,22 @@ test_equality_1 ()
/* Verify that setting state in model1 makes the models non-equal. */
tree x = build_global_decl ("x", integer_type_node);
- model0.set_value (x, int_42, NULL);
- ASSERT_EQ (model0.get_rvalue (x, NULL)->maybe_get_constant (), int_42);
+ model0.set_value (x, int_42, nullptr);
+ ASSERT_EQ (model0.get_rvalue (x, nullptr)->maybe_get_constant (), int_42);
ASSERT_NE (model0, model1);
/* Verify the copy-ctor. */
region_model model2 (model0);
ASSERT_EQ (model0, model2);
- ASSERT_EQ (model2.get_rvalue (x, NULL)->maybe_get_constant (), int_42);
+ ASSERT_EQ (model2.get_rvalue (x, nullptr)->maybe_get_constant (), int_42);
ASSERT_NE (model1, model2);
/* Verify that models obtained from copy-ctor are independently editable
w/o affecting the original model. */
- model2.set_value (x, int_17, NULL);
+ model2.set_value (x, int_17, nullptr);
ASSERT_NE (model0, model2);
- ASSERT_EQ (model2.get_rvalue (x, NULL)->maybe_get_constant (), int_17);
- ASSERT_EQ (model0.get_rvalue (x, NULL)->maybe_get_constant (), int_42);
+ ASSERT_EQ (model2.get_rvalue (x, nullptr)->maybe_get_constant (), int_17);
+ ASSERT_EQ (model0.get_rvalue (x, nullptr)->maybe_get_constant (), int_42);
}
/* Verify that region models for
@@ -9172,20 +9172,20 @@ test_canonicalization_2 ()
region_model_manager mgr;
region_model model0 (&mgr);
- model0.set_value (model0.get_lvalue (x, NULL),
- model0.get_rvalue (int_42, NULL),
- NULL);
- model0.set_value (model0.get_lvalue (y, NULL),
- model0.get_rvalue (int_113, NULL),
- NULL);
+ model0.set_value (model0.get_lvalue (x, nullptr),
+ model0.get_rvalue (int_42, nullptr),
+ nullptr);
+ model0.set_value (model0.get_lvalue (y, nullptr),
+ model0.get_rvalue (int_113, nullptr),
+ nullptr);
region_model model1 (&mgr);
- model1.set_value (model1.get_lvalue (y, NULL),
- model1.get_rvalue (int_113, NULL),
- NULL);
- model1.set_value (model1.get_lvalue (x, NULL),
- model1.get_rvalue (int_42, NULL),
- NULL);
+ model1.set_value (model1.get_lvalue (y, nullptr),
+ model1.get_rvalue (int_113, nullptr),
+ nullptr);
+ model1.set_value (model1.get_lvalue (x, nullptr),
+ model1.get_rvalue (int_42, nullptr),
+ nullptr);
ASSERT_EQ (model0, model1);
}
@@ -9206,12 +9206,12 @@ test_canonicalization_3 ()
region_model_manager mgr;
region_model model0 (&mgr);
- model0.add_constraint (x, GT_EXPR, int_3, NULL);
- model0.add_constraint (y, GT_EXPR, int_42, NULL);
+ model0.add_constraint (x, GT_EXPR, int_3, nullptr);
+ model0.add_constraint (y, GT_EXPR, int_42, nullptr);
region_model model1 (&mgr);
- model1.add_constraint (y, GT_EXPR, int_42, NULL);
- model1.add_constraint (x, GT_EXPR, int_3, NULL);
+ model1.add_constraint (y, GT_EXPR, int_42, nullptr);
+ model1.add_constraint (x, GT_EXPR, int_3, nullptr);
model0.canonicalize ();
model1.canonicalize ();
@@ -9231,7 +9231,7 @@ test_canonicalization_4 ()
region_model model (&mgr);
for (tree cst : csts)
- model.get_rvalue (cst, NULL);
+ model.get_rvalue (cst, nullptr);
model.canonicalize ();
}
@@ -9240,7 +9240,7 @@ test_canonicalization_4 ()
with values VAL_A and VAL_B for EXPR that they are
mergable. Write the merged model to *OUT_MERGED_MODEL,
and the merged svalue ptr to *OUT_MERGED_SVALUE.
- If VAL_A or VAL_B are NULL_TREE, don't populate EXPR
+ If VAL_A or VAL_B are nullptr_TREE, don't populate EXPR
for that region_model. */
static void
@@ -9431,8 +9431,8 @@ test_state_merging ()
region_model model0 (&mgr);
model0.push_frame (*DECL_STRUCT_FUNCTION (test_fndecl),
nullptr, nullptr, nullptr);
- model0.set_value (model0.get_lvalue (p, NULL),
- model0.get_rvalue (addr_of_a, NULL), NULL);
+ model0.set_value (model0.get_lvalue (p, nullptr),
+ model0.get_rvalue (addr_of_a, nullptr), nullptr);
region_model model1 (model0);
ASSERT_EQ (model0, model1);
@@ -9456,7 +9456,7 @@ test_state_merging ()
const region_svalue *merged_p_ptr
= merged_p_sval->dyn_cast_region_svalue ();
const region *merged_p_star_reg = merged_p_ptr->get_pointee ();
- ASSERT_EQ (merged_p_star_reg, merged.get_lvalue (y, NULL));
+ ASSERT_EQ (merged_p_star_reg, merged.get_lvalue (y, nullptr));
}
/* Pointers: non-NULL ptrs to different globals: should be unknown. */
@@ -9571,7 +9571,7 @@ test_state_merging ()
region_model model0 (&mgr);
model0.push_frame (*DECL_STRUCT_FUNCTION (test_fndecl),
nullptr, nullptr, nullptr);
- const region *q_in_first_frame = model0.get_lvalue (q, NULL);
+ const region *q_in_first_frame = model0.get_lvalue (q, nullptr);
/* Push a second frame. */
const region *reg_2nd_frame
@@ -9580,8 +9580,8 @@ test_state_merging ()
/* Have a pointer in the older frame point to a local in the
more recent frame. */
- const svalue *sval_ptr = model0.get_rvalue (addr_of_a, NULL);
- model0.set_value (q_in_first_frame, sval_ptr, NULL);
+ const svalue *sval_ptr = model0.get_rvalue (addr_of_a, nullptr);
+ model0.set_value (q_in_first_frame, sval_ptr, nullptr);
/* Verify that it's pointing at the newer frame. */
const region *reg_pointee = sval_ptr->maybe_get_region ();
@@ -9605,8 +9605,8 @@ test_state_merging ()
region_model model0 (&mgr);
model0.push_frame (*DECL_STRUCT_FUNCTION (test_fndecl),
nullptr, nullptr, nullptr);
- model0.set_value (model0.get_lvalue (q, NULL),
- model0.get_rvalue (addr_of_y, NULL), NULL);
+ model0.set_value (model0.get_lvalue (q, nullptr),
+ model0.get_rvalue (addr_of_y, nullptr), nullptr);
region_model model1 (model0);
ASSERT_EQ (model0, model1);
@@ -9638,14 +9638,14 @@ test_constraint_merging ()
/* model0: 0 <= (x == y) < n. */
region_model model0 (&mgr);
model0.add_constraint (x, EQ_EXPR, y, &ctxt);
- model0.add_constraint (x, GE_EXPR, int_0, NULL);
- model0.add_constraint (x, LT_EXPR, n, NULL);
+ model0.add_constraint (x, GE_EXPR, int_0, nullptr);
+ model0.add_constraint (x, LT_EXPR, n, nullptr);
/* model1: z != 5 && (0 <= x < n). */
region_model model1 (&mgr);
- model1.add_constraint (z, NE_EXPR, int_5, NULL);
- model1.add_constraint (x, GE_EXPR, int_0, NULL);
- model1.add_constraint (x, LT_EXPR, n, NULL);
+ model1.add_constraint (z, NE_EXPR, int_5, nullptr);
+ model1.add_constraint (x, GE_EXPR, int_0, nullptr);
+ model1.add_constraint (x, LT_EXPR, n, nullptr);
/* They should be mergeable; the merged constraints should
be: (0 <= x < n). */
@@ -9870,17 +9870,17 @@ test_malloc_constraints ()
const svalue *size_in_bytes
= mgr.get_or_create_unknown_svalue (size_type_node);
const region *reg
- = model.get_or_create_region_for_heap_alloc (size_in_bytes, NULL);
+ = model.get_or_create_region_for_heap_alloc (size_in_bytes, nullptr);
const svalue *sval = mgr.get_ptr_svalue (ptr_type_node, reg);
- model.set_value (model.get_lvalue (p, NULL), sval, NULL);
- model.set_value (q, p, NULL);
+ model.set_value (model.get_lvalue (p, nullptr), sval, nullptr);
+ model.set_value (q, p, nullptr);
ASSERT_CONDITION_UNKNOWN (model, p, NE_EXPR, null_ptr);
ASSERT_CONDITION_UNKNOWN (model, p, EQ_EXPR, null_ptr);
ASSERT_CONDITION_UNKNOWN (model, q, NE_EXPR, null_ptr);
ASSERT_CONDITION_UNKNOWN (model, q, EQ_EXPR, null_ptr);
- model.add_constraint (p, NE_EXPR, null_ptr, NULL);
+ model.add_constraint (p, NE_EXPR, null_ptr, nullptr);
ASSERT_CONDITION_TRUE (model, p, NE_EXPR, null_ptr);
ASSERT_CONDITION_FALSE (model, p, EQ_EXPR, null_ptr);
@@ -9902,25 +9902,25 @@ test_var ()
region_model_manager mgr;
region_model model (&mgr);
- const region *i_reg = model.get_lvalue (i, NULL);
+ const region *i_reg = model.get_lvalue (i, nullptr);
ASSERT_EQ (i_reg->get_kind (), RK_DECL);
/* Reading "i" should give a symbolic "initial value". */
- const svalue *sval_init = model.get_rvalue (i, NULL);
+ const svalue *sval_init = model.get_rvalue (i, nullptr);
ASSERT_EQ (sval_init->get_kind (), SK_INITIAL);
ASSERT_EQ (sval_init->dyn_cast_initial_svalue ()->get_region (), i_reg);
/* ..and doing it again should give the same "initial value". */
- ASSERT_EQ (model.get_rvalue (i, NULL), sval_init);
+ ASSERT_EQ (model.get_rvalue (i, nullptr), sval_init);
/* "i = 17;". */
- model.set_value (i, int_17, NULL);
- ASSERT_EQ (model.get_rvalue (i, NULL),
- model.get_rvalue (int_17, NULL));
+ model.set_value (i, int_17, nullptr);
+ ASSERT_EQ (model.get_rvalue (i, nullptr),
+ model.get_rvalue (int_17, nullptr));
/* "i = -3;". */
- model.set_value (i, int_m3, NULL);
- ASSERT_EQ (model.get_rvalue (i, NULL),
- model.get_rvalue (int_m3, NULL));
+ model.set_value (i, int_m3, nullptr);
+ ASSERT_EQ (model.get_rvalue (i, nullptr),
+ model.get_rvalue (int_m3, nullptr));
/* Verify get_offset for "i". */
{
@@ -9959,38 +9959,41 @@ test_array_2 ()
region_model_manager mgr;
region_model model (&mgr);
/* "arr[0] = 17;". */
- model.set_value (arr_0, int_17, NULL);
+ model.set_value (arr_0, int_17, nullptr);
/* "arr[1] = -3;". */
- model.set_value (arr_1, int_m3, NULL);
+ model.set_value (arr_1, int_m3, nullptr);
- ASSERT_EQ (model.get_rvalue (arr_0, NULL), model.get_rvalue (int_17, NULL));
- ASSERT_EQ (model.get_rvalue (arr_1, NULL), model.get_rvalue (int_m3, NULL));
+ ASSERT_EQ (model.get_rvalue (arr_0, nullptr),
+ model.get_rvalue (int_17, nullptr));
+ ASSERT_EQ (model.get_rvalue (arr_1, nullptr),
+ model.get_rvalue (int_m3, nullptr));
/* Overwrite a pre-existing binding: "arr[1] = 42;". */
- model.set_value (arr_1, int_42, NULL);
- ASSERT_EQ (model.get_rvalue (arr_1, NULL), model.get_rvalue (int_42, NULL));
+ model.set_value (arr_1, int_42, nullptr);
+ ASSERT_EQ (model.get_rvalue (arr_1, nullptr),
+ model.get_rvalue (int_42, nullptr));
/* Verify get_offset for "arr[0]". */
{
- const region *arr_0_reg = model.get_lvalue (arr_0, NULL);
+ const region *arr_0_reg = model.get_lvalue (arr_0, nullptr);
region_offset offset = arr_0_reg->get_offset (&mgr);
- ASSERT_EQ (offset.get_base_region (), model.get_lvalue (arr, NULL));
+ ASSERT_EQ (offset.get_base_region (), model.get_lvalue (arr, nullptr));
ASSERT_EQ (offset.get_bit_offset (), 0);
}
/* Verify get_offset for "arr[1]". */
{
- const region *arr_1_reg = model.get_lvalue (arr_1, NULL);
+ const region *arr_1_reg = model.get_lvalue (arr_1, nullptr);
region_offset offset = arr_1_reg->get_offset (&mgr);
- ASSERT_EQ (offset.get_base_region (), model.get_lvalue (arr, NULL));
+ ASSERT_EQ (offset.get_base_region (), model.get_lvalue (arr, nullptr));
ASSERT_EQ (offset.get_bit_offset (), INT_TYPE_SIZE);
}
/* Verify get_offset for "arr[i]". */
{
- const region *arr_i_reg = model.get_lvalue (arr_i, NULL);
+ const region *arr_i_reg = model.get_lvalue (arr_i, nullptr);
region_offset offset = arr_i_reg->get_offset (&mgr);
- ASSERT_EQ (offset.get_base_region (), model.get_lvalue (arr, NULL));
+ ASSERT_EQ (offset.get_base_region (), model.get_lvalue (arr, nullptr));
const svalue *offset_sval = offset.get_symbolic_byte_offset ();
if (const svalue *cast = offset_sval->maybe_undo_cast ())
offset_sval = cast;
@@ -9998,14 +10001,15 @@ test_array_2 ()
}
/* "arr[i] = i;" - this should remove the earlier bindings. */
- model.set_value (arr_i, i, NULL);
- ASSERT_EQ (model.get_rvalue (arr_i, NULL), model.get_rvalue (i, NULL));
- ASSERT_EQ (model.get_rvalue (arr_0, NULL)->get_kind (), SK_UNKNOWN);
+ model.set_value (arr_i, i, nullptr);
+ ASSERT_EQ (model.get_rvalue (arr_i, nullptr), model.get_rvalue (i, nullptr));
+ ASSERT_EQ (model.get_rvalue (arr_0, nullptr)->get_kind (), SK_UNKNOWN);
/* "arr[0] = 17;" - this should remove the arr[i] binding. */
- model.set_value (arr_0, int_17, NULL);
- ASSERT_EQ (model.get_rvalue (arr_0, NULL), model.get_rvalue (int_17, NULL));
- ASSERT_EQ (model.get_rvalue (arr_i, NULL)->get_kind (), SK_UNKNOWN);
+ model.set_value (arr_0, int_17, nullptr);
+ ASSERT_EQ (model.get_rvalue (arr_0, nullptr),
+ model.get_rvalue (int_17, nullptr));
+ ASSERT_EQ (model.get_rvalue (arr_i, nullptr)->get_kind (), SK_UNKNOWN);
}
/* Smoketest of dereferencing a pointer via MEM_REF. */
@@ -10032,12 +10036,12 @@ test_mem_ref ()
region_model model (&mgr);
/* "x = 17;". */
- model.set_value (x, int_17, NULL);
+ model.set_value (x, int_17, nullptr);
/* "p = &x;". */
- model.set_value (p, addr_of_x, NULL);
+ model.set_value (p, addr_of_x, nullptr);
- const svalue *sval = model.get_rvalue (star_p, NULL);
+ const svalue *sval = model.get_rvalue (star_p, nullptr);
ASSERT_EQ (sval->maybe_get_constant (), int_17);
}
@@ -10083,8 +10087,8 @@ test_POINTER_PLUS_EXPR_then_MEM_REF ()
region_model m (&mgr);
tree int_42 = build_int_cst (integer_type_node, 42);
- m.set_value (mem_ref, int_42, NULL);
- ASSERT_EQ (m.get_rvalue (mem_ref, NULL)->maybe_get_constant (), int_42);
+ m.set_value (mem_ref, int_42, nullptr);
+ ASSERT_EQ (m.get_rvalue (mem_ref, nullptr)->maybe_get_constant (), int_42);
}
/* Verify that malloc works. */
@@ -10147,8 +10151,8 @@ test_alloca ()
/* Verify that the pointers to the alloca region are replaced by
poisoned values when the frame is popped. */
- model.pop_frame (NULL, NULL, &ctxt, nullptr);
- ASSERT_EQ (model.get_rvalue (p, NULL)->get_kind (), SK_POISONED);
+ model.pop_frame (nullptr, nullptr, &ctxt, nullptr);
+ ASSERT_EQ (model.get_rvalue (p, nullptr)->get_kind (), SK_POISONED);
}
/* Verify that svalue::involves_p works. */
diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h
index 2c7f737..6271ea2 100644
--- a/gcc/analyzer/region-model.h
+++ b/gcc/analyzer/region-model.h
@@ -385,11 +385,11 @@ class region_model
std::unique_ptr<rejected_constraint> *out);
void update_for_gcall (const gcall &call_stmt,
- region_model_context *ctxt,
- function *callee = NULL);
+ region_model_context *ctxt,
+ function *callee = nullptr);
void update_for_return_gcall (const gcall &call_stmt,
- region_model_context *ctxt);
+ region_model_context *ctxt);
const region *push_frame (const function &fun,
const gcall *call_stmt,
@@ -517,9 +517,9 @@ class region_model
bool can_merge_with_p (const region_model &other_model,
const program_point &point,
region_model *out_model,
- const extrinsic_state *ext_state = NULL,
- const program_state *state_a = NULL,
- const program_state *state_b = NULL) const;
+ const extrinsic_state *ext_state = nullptr,
+ const program_state *state_a = nullptr,
+ const program_state *state_b = nullptr) const;
tree get_fndecl_for_call (const gcall &call,
region_model_context *ctxt);
@@ -600,7 +600,7 @@ class region_model
const builtin_known_function *
get_builtin_kf (const gcall &call,
- region_model_context *ctxt = NULL) const;
+ region_model_context *ctxt = nullptr) const;
static void
register_pop_frame_callback (const pop_frame_callback &callback)
@@ -818,7 +818,7 @@ class region_model_context
Return true if the diagnostic was stored, or false if it was deleted.
Optionally provide a custom stmt_finder. */
virtual bool warn (std::unique_ptr<pending_diagnostic> d,
- const stmt_finder *custom_finder = NULL) = 0;
+ const stmt_finder *custom_finder = nullptr) = 0;
/* Hook for clients to add a note to the last previously stored
pending diagnostic. */
@@ -912,13 +912,15 @@ class region_model_context
const state_machine **out_sm,
unsigned *out_sm_idx)
{
- return get_state_map_by_name ("malloc", out_smap, out_sm, out_sm_idx, NULL);
+ return get_state_map_by_name ("malloc", out_smap, out_sm, out_sm_idx,
+ nullptr);
}
bool get_taint_map (sm_state_map **out_smap,
const state_machine **out_sm,
unsigned *out_sm_idx)
{
- return get_state_map_by_name ("taint", out_smap, out_sm, out_sm_idx, NULL);
+ return get_state_map_by_name ("taint", out_smap, out_sm, out_sm_idx,
+ nullptr);
}
bool possibly_tainted_p (const svalue *sval);
@@ -928,6 +930,8 @@ class region_model_context
virtual const exploded_graph *get_eg () const = 0;
+ virtual const program_state *get_state () const = 0;
+
/* Hooks for detecting infinite loops. */
virtual void maybe_did_work () = 0;
virtual bool checking_for_infinite_loop_p () const = 0;
@@ -946,7 +950,7 @@ public:
void on_svalue_leak (const svalue *) override {}
void on_liveness_change (const svalue_set &,
const region_model *) override {}
- logger *get_logger () override { return NULL; }
+ logger *get_logger () override { return nullptr; }
void on_condition (const svalue *lhs ATTRIBUTE_UNUSED,
enum tree_code op ATTRIBUTE_UNUSED,
const svalue *rhs ATTRIBUTE_UNUSED) override
@@ -969,14 +973,14 @@ public:
void on_escaped_function (tree) override {}
- uncertainty_t *get_uncertainty () override { return NULL; }
+ uncertainty_t *get_uncertainty () override { return nullptr; }
void purge_state_involving (const svalue *sval ATTRIBUTE_UNUSED) override {}
void bifurcate (std::unique_ptr<custom_edge_info> info) override;
void terminate_path () override;
- const extrinsic_state *get_ext_state () const override { return NULL; }
+ const extrinsic_state *get_ext_state () const override { return nullptr; }
bool get_state_map_by_name (const char *,
sm_state_map **,
@@ -987,8 +991,10 @@ public:
return false;
}
- const gimple *get_stmt () const override { return NULL; }
- const exploded_graph *get_eg () const override { return NULL; }
+ const gimple *get_stmt () const override { return nullptr; }
+ const exploded_graph *get_eg () const override { return nullptr; }
+ const program_state *get_state () const override { return nullptr; }
+
void maybe_did_work () override {}
bool checking_for_infinite_loop_p () const override { return false; }
void on_unusable_in_infinite_loop () override {}
@@ -1167,6 +1173,14 @@ class region_model_context_decorator : public region_model_context
return nullptr;
}
+ const program_state *get_state () const override
+ {
+ if (m_inner)
+ return m_inner->get_state ();
+ else
+ return nullptr;
+ }
+
void maybe_did_work () override
{
if (m_inner)
@@ -1337,7 +1351,7 @@ private:
class engine
{
public:
- engine (const supergraph *sg = NULL, logger *logger = NULL);
+ engine (const supergraph *sg = nullptr, logger *logger = nullptr);
const supergraph *get_supergraph () { return m_sg; }
region_model_manager *get_model_manager () { return &m_mgr; }
known_function_manager *get_known_function_manager ()
@@ -1396,7 +1410,7 @@ private:
#define ADD_SAT_CONSTRAINT(MODEL, LHS, OP, RHS) \
SELFTEST_BEGIN_STMT \
- bool sat = (MODEL).add_constraint (LHS, OP, RHS, NULL); \
+ bool sat = (MODEL).add_constraint (LHS, OP, RHS, nullptr); \
ASSERT_TRUE (sat); \
SELFTEST_END_STMT
@@ -1405,7 +1419,7 @@ private:
#define ADD_UNSAT_CONSTRAINT(MODEL, LHS, OP, RHS) \
SELFTEST_BEGIN_STMT \
- bool sat = (MODEL).add_constraint (LHS, OP, RHS, NULL); \
+ bool sat = (MODEL).add_constraint (LHS, OP, RHS, nullptr); \
ASSERT_FALSE (sat); \
SELFTEST_END_STMT
diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc
index efbbca0..e27fc6e 100644
--- a/gcc/analyzer/region.cc
+++ b/gcc/analyzer/region.cc
@@ -124,7 +124,7 @@ region_offset::dump (bool simple) const
}
/* An svalue that matches the pattern (BASE * FACTOR) + OFFSET
- where FACTOR or OFFSET could be the identity (represented as NULL). */
+ where FACTOR or OFFSET could be the identity (represented as nullptr). */
struct linear_op
{
@@ -231,7 +231,7 @@ struct linear_op
{
*out = linear_op (binop_sval.get_arg0 (),
binop_sval.get_arg1 (),
- NULL);
+ nullptr);
return true;
}
else if (binop_sval.get_op () == PLUS_EXPR)
@@ -250,7 +250,7 @@ struct linear_op
}
*out = linear_op (binop_sval.get_arg0 (),
- NULL,
+ nullptr,
binop_sval.get_arg1 ());
return true;
}
@@ -276,8 +276,8 @@ operator< (const region_offset &a, const region_offset &b)
const svalue &a_sval = *a.get_symbolic_byte_offset ();
const svalue &b_sval = *b.get_symbolic_byte_offset ();
- linear_op op_a (NULL, NULL, NULL);
- linear_op op_b (NULL, NULL, NULL);
+ linear_op op_a (nullptr, nullptr, nullptr);
+ linear_op op_b (nullptr, nullptr, nullptr);
if (linear_op::from_svalue (a_sval, &op_a)
&& linear_op::from_svalue (b_sval, &op_b))
{
@@ -318,8 +318,8 @@ operator<= (const region_offset &a, const region_offset &b)
const svalue &a_sval = *a.get_symbolic_byte_offset ();
const svalue &b_sval = *b.get_symbolic_byte_offset ();
- linear_op op_a (NULL, NULL, NULL);
- linear_op op_b (NULL, NULL, NULL);
+ linear_op op_a (nullptr, nullptr, nullptr);
+ linear_op op_b (nullptr, nullptr, nullptr);
if (linear_op::from_svalue (a_sval, &op_a)
&& linear_op::from_svalue (b_sval, &op_b))
{
@@ -448,7 +448,7 @@ region::descendent_of_p (const region *elder) const
}
/* If this region is a frame_region, or a descendent of one, return it.
- Otherwise return NULL. */
+ Otherwise return nullptr. */
const frame_region *
region::maybe_get_frame_region () const
@@ -460,7 +460,7 @@ region::maybe_get_frame_region () const
return frame_reg;
iter = iter->get_parent_region ();
}
- return NULL;
+ return nullptr;
}
/* Get the memory space of this region. */
@@ -609,7 +609,7 @@ region::calc_initial_value_at_main (region_model_manager *mgr) const
}
/* If this region is a decl_region, return the decl.
- Otherwise return NULL. */
+ Otherwise return NULL_TREE. */
tree
region::maybe_get_decl () const
@@ -769,7 +769,7 @@ get_field_at_bit_offset (tree record_type, bit_offset_t bit_offset)
{
gcc_assert (TREE_CODE (record_type) == RECORD_TYPE);
if (bit_offset < 0)
- return NULL;
+ return nullptr;
/* Find the first field that has an offset > BIT_OFFSET,
then return the one preceding it.
@@ -879,7 +879,7 @@ region::calc_offset (region_model_manager *mgr) const
{
const region *iter_region = this;
bit_offset_t accum_bit_offset = 0;
- const svalue *accum_byte_sval = NULL;
+ const svalue *accum_byte_sval = nullptr;
while (iter_region)
{
@@ -1155,7 +1155,7 @@ region::is_named_decl_p (const char *decl_name) const
region::region (complexity c, symbol::id_t id, const region *parent, tree type)
: symbol (c, id),
m_parent (parent), m_type (type),
- m_cached_offset (NULL), m_cached_init_sval_at_main (NULL)
+ m_cached_offset (nullptr), m_cached_init_sval_at_main (nullptr)
{
gcc_assert (type == NULL_TREE || TYPE_P (type));
}
@@ -1548,7 +1548,7 @@ heap_region::print_dump_widget_label (pretty_printer *pp) const
/* root_region's ctor. */
root_region::root_region (symbol::id_t id)
-: region (complexity (1, 1), id, NULL, NULL_TREE)
+: region (complexity (1, 1), id, nullptr, NULL_TREE)
{
}
@@ -1680,7 +1680,7 @@ decl_region::print_dump_widget_label (pretty_printer *pp) const
int
decl_region::get_stack_depth () const
{
- if (get_parent_region () == NULL)
+ if (get_parent_region () == nullptr)
return 0;
if (const frame_region *frame_reg
= get_parent_region ()->dyn_cast_frame_region ())
@@ -1690,7 +1690,7 @@ decl_region::get_stack_depth () const
/* If the underlying decl is in the global constant pool,
return an svalue representing the constant value.
- Otherwise return NULL. */
+ Otherwise return nullptr. */
const svalue *
decl_region::maybe_get_constant_value (region_model_manager *mgr) const
@@ -1700,7 +1700,7 @@ decl_region::maybe_get_constant_value (region_model_manager *mgr) const
&& DECL_INITIAL (m_decl)
&& TREE_CODE (DECL_INITIAL (m_decl)) == CONSTRUCTOR)
return get_svalue_for_constructor (DECL_INITIAL (m_decl), mgr);
- return NULL;
+ return nullptr;
}
/* Implementation of decl_region::get_svalue_for_constructor
@@ -1742,7 +1742,7 @@ decl_region::get_svalue_for_constructor (tree ctor,
"main" (either based on DECL_INITIAL, or implicit initialization to
zero.
- Return NULL if there is a problem. */
+ Return nullptr if there is a problem. */
const svalue *
decl_region::get_svalue_for_initializer (region_model_manager *mgr) const
@@ -1753,10 +1753,10 @@ decl_region::get_svalue_for_initializer (region_model_manager *mgr) const
/* If we have an "extern" decl then there may be an initializer in
another TU. */
if (DECL_EXTERNAL (m_decl))
- return NULL;
+ return nullptr;
if (empty_p ())
- return NULL;
+ return nullptr;
/* Implicit initialization to zero; use a compound_svalue for it.
Doing so requires that we have a concrete binding for this region,
@@ -1765,12 +1765,12 @@ decl_region::get_svalue_for_initializer (region_model_manager *mgr) const
const binding_key *binding
= binding_key::make (mgr->get_store_manager (), this);
if (binding->symbolic_p ())
- return NULL;
+ return nullptr;
/* If we don't care about tracking the content of this region, then
it's unused, and the value doesn't matter. */
if (!tracked_p ())
- return NULL;
+ return nullptr;
binding_cluster c (this);
c.zero_fill_region (mgr->get_store_manager (), this);
@@ -1781,14 +1781,14 @@ decl_region::get_svalue_for_initializer (region_model_manager *mgr) const
/* LTO can write out error_mark_node as the DECL_INITIAL for simple scalar
values (to avoid writing out an extra section). */
if (init == error_mark_node)
- return NULL;
+ return nullptr;
if (TREE_CODE (init) == CONSTRUCTOR)
return get_svalue_for_constructor (init, mgr);
/* Reuse the get_rvalue logic from region_model. */
region_model m (mgr);
- return m.get_rvalue (path_var (init, 0), NULL);
+ return m.get_rvalue (path_var (init, 0), nullptr);
}
/* Subroutine of symnode_requires_tracking_p; return true if REF
@@ -1802,7 +1802,7 @@ ipa_ref_requires_tracking (ipa_ref *ref)
if (ref->use != IPA_REF_ADDR)
return true;
- if (ref->stmt == NULL)
+ if (ref->stmt == nullptr)
return true;
switch (ref->stmt->code)
@@ -1812,12 +1812,12 @@ ipa_ref_requires_tracking (ipa_ref *ref)
case GIMPLE_CALL:
{
cgraph_node *caller_cnode = dyn_cast <cgraph_node *> (ref->referring);
- if (caller_cnode == NULL)
+ if (caller_cnode == nullptr)
return true;
cgraph_edge *edge = caller_cnode->get_edge (ref->stmt);
if (!edge)
return true;
- if (edge->callee == NULL)
+ if (edge->callee == nullptr)
return true; /* e.g. call through function ptr. */
if (edge->callee->definition)
return true;
@@ -1852,7 +1852,7 @@ symnode_requires_tracking_p (symtab_node *symnode)
if (symnode->externally_visible)
return true;
tree context_fndecl = DECL_CONTEXT (symnode->decl);
- if (context_fndecl == NULL)
+ if (context_fndecl == nullptr)
return true;
if (TREE_CODE (context_fndecl) != FUNCTION_DECL)
return true;
diff --git a/gcc/analyzer/region.h b/gcc/analyzer/region.h
index 801a8d3..e01a2e2 100644
--- a/gcc/analyzer/region.h
+++ b/gcc/analyzer/region.h
@@ -129,29 +129,29 @@ public:
virtual enum region_kind get_kind () const = 0;
virtual const frame_region *
- dyn_cast_frame_region () const { return NULL; }
+ dyn_cast_frame_region () const { return nullptr; }
virtual const function_region *
- dyn_cast_function_region () const { return NULL; }
+ dyn_cast_function_region () const { return nullptr; }
virtual const symbolic_region *
- dyn_cast_symbolic_region () const { return NULL; }
+ dyn_cast_symbolic_region () const { return nullptr; }
virtual const decl_region *
- dyn_cast_decl_region () const { return NULL; }
+ dyn_cast_decl_region () const { return nullptr; }
virtual const field_region *
- dyn_cast_field_region () const { return NULL; }
+ dyn_cast_field_region () const { return nullptr; }
virtual const element_region *
- dyn_cast_element_region () const { return NULL; }
+ dyn_cast_element_region () const { return nullptr; }
virtual const offset_region *
- dyn_cast_offset_region () const { return NULL; }
+ dyn_cast_offset_region () const { return nullptr; }
virtual const sized_region *
- dyn_cast_sized_region () const { return NULL; }
+ dyn_cast_sized_region () const { return nullptr; }
virtual const cast_region *
- dyn_cast_cast_region () const { return NULL; }
+ dyn_cast_cast_region () const { return nullptr; }
virtual const string_region *
- dyn_cast_string_region () const { return NULL; }
+ dyn_cast_string_region () const { return nullptr; }
virtual const bit_range_region *
- dyn_cast_bit_range_region () const { return NULL; }
+ dyn_cast_bit_range_region () const { return nullptr; }
virtual const var_arg_region *
- dyn_cast_var_arg_region () const { return NULL; }
+ dyn_cast_var_arg_region () const { return nullptr; }
virtual void accept (visitor *v) const;
@@ -324,7 +324,7 @@ public:
key_t (const frame_region *calling_frame, const function &fun)
: m_calling_frame (calling_frame), m_fun (&fun)
{
- /* calling_frame can be NULL. */
+ /* calling_frame can be nullptr. */
}
hashval_t hash () const
@@ -342,12 +342,12 @@ public:
}
void mark_deleted () { m_fun = reinterpret_cast<function *> (1); }
- void mark_empty () { m_fun = NULL; }
+ void mark_empty () { m_fun = nullptr; }
bool is_deleted () const
{
return m_fun == reinterpret_cast<function *> (1);
}
- bool is_empty () const { return m_fun == NULL; }
+ bool is_empty () const { return m_fun == nullptr; }
const frame_region *m_calling_frame;
const function *m_fun;
@@ -685,12 +685,12 @@ public:
}
void mark_deleted () { m_sval_ptr = reinterpret_cast<const svalue *> (1); }
- void mark_empty () { m_sval_ptr = NULL; }
+ void mark_empty () { m_sval_ptr = nullptr; }
bool is_deleted () const
{
return m_sval_ptr == reinterpret_cast<const svalue *> (1);
}
- bool is_empty () const { return m_sval_ptr == NULL; }
+ bool is_empty () const { return m_sval_ptr == nullptr; }
const region *m_parent;
const svalue *m_sval_ptr;
@@ -744,7 +744,7 @@ public:
decl_region (symbol::id_t id, const region *parent, tree decl)
: region (complexity (parent), id, parent, TREE_TYPE (decl)), m_decl (decl),
m_tracked (calc_tracked_p (decl)),
- m_ctor_svalue (NULL)
+ m_ctor_svalue (nullptr)
{}
enum region_kind get_kind () const final override { return RK_DECL; }
@@ -904,12 +904,12 @@ public:
}
void mark_deleted () { m_index = reinterpret_cast<const svalue *> (1); }
- void mark_empty () { m_index = NULL; }
+ void mark_empty () { m_index = nullptr; }
bool is_deleted () const
{
return m_index == reinterpret_cast<const svalue *> (1);
}
- bool is_empty () const { return m_index == NULL; }
+ bool is_empty () const { return m_index == nullptr; }
const region *m_parent;
tree m_element_type;
@@ -998,12 +998,12 @@ public:
}
void mark_deleted () { m_byte_offset = reinterpret_cast<const svalue *> (1); }
- void mark_empty () { m_byte_offset = NULL; }
+ void mark_empty () { m_byte_offset = nullptr; }
bool is_deleted () const
{
return m_byte_offset == reinterpret_cast<const svalue *> (1);
}
- bool is_empty () const { return m_byte_offset == NULL; }
+ bool is_empty () const { return m_byte_offset == nullptr; }
const region *m_parent;
tree m_element_type;
@@ -1094,12 +1094,12 @@ public:
}
void mark_deleted () { m_byte_size_sval = reinterpret_cast<const svalue *> (1); }
- void mark_empty () { m_byte_size_sval = NULL; }
+ void mark_empty () { m_byte_size_sval = nullptr; }
bool is_deleted () const
{
return m_byte_size_sval == reinterpret_cast<const svalue *> (1);
}
- bool is_empty () const { return m_byte_size_sval == NULL; }
+ bool is_empty () const { return m_byte_size_sval == nullptr; }
const region *m_parent;
tree m_element_type;
@@ -1342,12 +1342,12 @@ public:
}
void mark_deleted () { m_parent = reinterpret_cast<const region *> (1); }
- void mark_empty () { m_parent = NULL; }
+ void mark_empty () { m_parent = nullptr; }
bool is_deleted () const
{
return m_parent == reinterpret_cast<const region *> (1);
}
- bool is_empty () const { return m_parent == NULL; }
+ bool is_empty () const { return m_parent == nullptr; }
const region *m_parent;
tree m_type;
@@ -1432,12 +1432,12 @@ public:
{
m_parent = reinterpret_cast<const frame_region *> (1);
}
- void mark_empty () { m_parent = NULL; }
+ void mark_empty () { m_parent = nullptr; }
bool is_deleted () const
{
return m_parent == reinterpret_cast<const frame_region *> (1);
}
- bool is_empty () const { return m_parent == NULL; }
+ bool is_empty () const { return m_parent == nullptr; }
const frame_region *m_parent;
unsigned m_idx;
diff --git a/gcc/analyzer/sm-fd.cc b/gcc/analyzer/sm-fd.cc
index cee8d2d..370d7a0 100644
--- a/gcc/analyzer/sm-fd.cc
+++ b/gcc/analyzer/sm-fd.cc
@@ -116,7 +116,11 @@ public:
const svalue *rhs) const final override;
bool can_purge_p (state_t s) const final override;
- std::unique_ptr<pending_diagnostic> on_leak (tree var) const final override;
+
+ std::unique_ptr<pending_diagnostic>
+ on_leak (tree var,
+ const program_state *old_state,
+ const program_state *new_state) const final override;
bool is_unchecked_fd_p (state_t s) const;
bool is_valid_fd_p (state_t s) const;
@@ -210,7 +214,7 @@ public:
/* State for a file descriptor that we do not want to track anymore . */
state_t m_stop;
- /* Stashed constant values from the frontend. These could be NULL. */
+ /* Stashed constant values from the frontend. These could be NULL_TREE. */
tree m_O_ACCMODE;
tree m_O_RDONLY;
tree m_O_WRONLY;
@@ -257,7 +261,7 @@ private:
const svalue *fd_sval,
const supernode *node,
state_t old_state,
- bool *complained = NULL) const;
+ bool *complained = nullptr) const;
bool check_for_new_socket_fd (const call_details &cd,
bool successful,
sm_context &sm_ctxt,
@@ -397,11 +401,11 @@ public:
|| change.m_new_state == m_sm.m_new_datagram_socket
|| change.m_new_state == m_sm.m_new_stream_socket
|| change.m_new_state == m_sm.m_new_unknown_socket))
- return diagnostic_event::meaning (diagnostic_event::VERB_acquire,
- diagnostic_event::NOUN_resource);
+ return diagnostic_event::meaning (diagnostic_event::verb::acquire,
+ diagnostic_event::noun::resource);
if (change.m_new_state == m_sm.m_closed)
- return diagnostic_event::meaning (diagnostic_event::VERB_release,
- diagnostic_event::NOUN_resource);
+ return diagnostic_event::meaning (diagnostic_event::verb::release,
+ diagnostic_event::noun::resource);
return diagnostic_event::meaning ();
}
@@ -422,7 +426,7 @@ public:
fd_param_diagnostic (const fd_state_machine &sm, tree arg, tree callee_fndecl)
: fd_diagnostic (sm, arg), m_callee_fndecl (callee_fndecl),
- m_attr_name (NULL), m_arg_idx (-1)
+ m_attr_name (nullptr), m_arg_idx (-1)
{
}
@@ -477,7 +481,14 @@ protected:
class fd_leak : public fd_diagnostic
{
public:
- fd_leak (const fd_state_machine &sm, tree arg) : fd_diagnostic (sm, arg) {}
+ fd_leak (const fd_state_machine &sm, tree arg,
+ const program_state *final_state)
+ : fd_diagnostic (sm, arg),
+ m_final_state ()
+ {
+ if (final_state)
+ m_final_state = std::make_unique<program_state> (*final_state);
+ }
const char *
get_kind () const final override
@@ -543,8 +554,15 @@ public:
return true;
}
+ const program_state *
+ get_final_state () const final override
+ {
+ return m_final_state.get ();
+ }
+
private:
diagnostic_event_id_t m_open_event;
+ std::unique_ptr<program_state> m_final_state;
};
class fd_access_mode_mismatch : public fd_param_diagnostic
@@ -1296,7 +1314,7 @@ fd_state_machine::valid_to_unchecked_state (state_t state) const
return m_unchecked_read_only;
else
gcc_unreachable ();
- return NULL;
+ return nullptr;
}
void
@@ -1305,7 +1323,7 @@ fd_state_machine::mark_as_valid_fd (region_model *model,
const svalue *fd_sval,
const extrinsic_state &ext_state) const
{
- smap->set_state (model, fd_sval, m_valid_read_write, NULL, ext_state);
+ smap->set_state (model, fd_sval, m_valid_read_write, nullptr, ext_state);
}
bool
@@ -1528,7 +1546,7 @@ fd_state_machine::on_open (sm_context &sm_ctxt, const supernode *node,
else
{
sm_ctxt.warn (node, stmt, NULL_TREE,
- std::make_unique<fd_leak> (*this, NULL_TREE));
+ std::make_unique<fd_leak> (*this, NULL_TREE, nullptr));
}
}
@@ -1541,7 +1559,7 @@ fd_state_machine::on_creat (sm_context &sm_ctxt, const supernode *node,
sm_ctxt.on_transition (node, stmt, lhs, m_start, m_unchecked_write_only);
else
sm_ctxt.warn (node, stmt, NULL_TREE,
- std::make_unique<fd_leak> (*this, NULL_TREE));
+ std::make_unique<fd_leak> (*this, NULL_TREE, nullptr));
}
void
@@ -1792,7 +1810,7 @@ fd_state_machine::on_socket (const call_details &cd,
}
else
sm_ctxt.warn (node, &call, NULL_TREE,
- std::make_unique<fd_leak> (*this, NULL_TREE));
+ std::make_unique<fd_leak> (*this, NULL_TREE, nullptr));
}
else
{
@@ -1967,7 +1985,7 @@ fd_state_machine::on_bind (const call_details &cd,
if (successful)
{
- state_t next_state = NULL;
+ state_t next_state = nullptr;
if (old_state == m_new_stream_socket)
next_state = m_bound_stream_socket;
else if (old_state == m_new_datagram_socket)
@@ -2185,7 +2203,7 @@ fd_state_machine::on_accept (const call_details &cd,
}
else
sm_ctxt.warn (node, &call, NULL_TREE,
- std::make_unique<fd_leak> (*this, NULL_TREE));
+ std::make_unique<fd_leak> (*this, NULL_TREE, nullptr));
}
else
{
@@ -2223,7 +2241,7 @@ fd_state_machine::on_connect (const call_details &cd,
if (successful)
{
model->update_for_zero_return (cd, true);
- state_t next_state = NULL;
+ state_t next_state = nullptr;
if (old_state == m_new_stream_socket)
next_state = m_connected_stream_socket;
else if (old_state == m_new_datagram_socket)
@@ -2321,9 +2339,11 @@ fd_state_machine::can_purge_p (state_t s) const
}
std::unique_ptr<pending_diagnostic>
-fd_state_machine::on_leak (tree var) const
+fd_state_machine::on_leak (tree var,
+ const program_state *,
+ const program_state *new_state) const
{
- return std::make_unique<fd_leak> (*this, var);
+ return std::make_unique<fd_leak> (*this, var, new_state);
}
} // namespace
@@ -2361,7 +2381,7 @@ region_model::mark_as_valid_fd (const svalue *sval, region_model_context *ctxt)
{
sm_state_map *smap;
const fd_state_machine *fd_sm;
- if (!get_fd_state (ctxt, &smap, &fd_sm, NULL, NULL))
+ if (!get_fd_state (ctxt, &smap, &fd_sm, nullptr, nullptr))
return;
const extrinsic_state *ext_state = ctxt->get_ext_state ();
if (!ext_state)
@@ -2390,7 +2410,7 @@ public:
sm_state_map *smap;
const fd_state_machine *fd_sm;
std::unique_ptr<sm_context> sm_ctxt;
- if (!get_fd_state (ctxt, &smap, &fd_sm, NULL, &sm_ctxt))
+ if (!get_fd_state (ctxt, &smap, &fd_sm, nullptr, &sm_ctxt))
{
cd.set_any_lhs_with_defaults ();
return true;
@@ -2445,7 +2465,7 @@ public:
sm_state_map *smap;
const fd_state_machine *fd_sm;
std::unique_ptr<sm_context> sm_ctxt;
- if (!get_fd_state (ctxt, &smap, &fd_sm, NULL, &sm_ctxt))
+ if (!get_fd_state (ctxt, &smap, &fd_sm, nullptr, &sm_ctxt))
{
cd.set_any_lhs_with_defaults ();
return true;
@@ -2498,7 +2518,7 @@ class kf_listen : public known_function
sm_state_map *smap;
const fd_state_machine *fd_sm;
std::unique_ptr<sm_context> sm_ctxt;
- if (!get_fd_state (ctxt, &smap, &fd_sm, NULL, &sm_ctxt))
+ if (!get_fd_state (ctxt, &smap, &fd_sm, nullptr, &sm_ctxt))
{
cd.set_any_lhs_with_defaults ();
return true;
@@ -2552,7 +2572,7 @@ class kf_accept : public known_function
sm_state_map *smap;
const fd_state_machine *fd_sm;
std::unique_ptr<sm_context> sm_ctxt;
- if (!get_fd_state (ctxt, &smap, &fd_sm, NULL, &sm_ctxt))
+ if (!get_fd_state (ctxt, &smap, &fd_sm, nullptr, &sm_ctxt))
{
cd.set_any_lhs_with_defaults ();
return true;
@@ -2609,7 +2629,7 @@ public:
sm_state_map *smap;
const fd_state_machine *fd_sm;
std::unique_ptr<sm_context> sm_ctxt;
- if (!get_fd_state (ctxt, &smap, &fd_sm, NULL, &sm_ctxt))
+ if (!get_fd_state (ctxt, &smap, &fd_sm, nullptr, &sm_ctxt))
{
cd.set_any_lhs_with_defaults ();
return true;
@@ -2687,7 +2707,7 @@ class kf_isatty : public known_function
sm_state_map *smap;
const fd_state_machine *fd_sm;
std::unique_ptr<sm_context> sm_ctxt;
- if (!get_fd_state (ctxt, &smap, &fd_sm, NULL, &sm_ctxt))
+ if (!get_fd_state (ctxt, &smap, &fd_sm, nullptr, &sm_ctxt))
return true;
const extrinsic_state *ext_state = ctxt->get_ext_state ();
if (!ext_state)
diff --git a/gcc/analyzer/sm-file.cc b/gcc/analyzer/sm-file.cc
index d7dbe2f..4b1fc77 100644
--- a/gcc/analyzer/sm-file.cc
+++ b/gcc/analyzer/sm-file.cc
@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see
#include "analyzer/analyzer-selftests.h"
#include "analyzer/call-string.h"
#include "analyzer/program-point.h"
+#include "analyzer/program-state.h"
#include "analyzer/store.h"
#include "analyzer/region-model.h"
#include "analyzer/call-details.h"
@@ -72,7 +73,11 @@ public:
const svalue *rhs) const final override;
bool can_purge_p (state_t s) const final override;
- std::unique_ptr<pending_diagnostic> on_leak (tree var) const final override;
+
+ std::unique_ptr<pending_diagnostic>
+ on_leak (tree var,
+ const program_state *old_state,
+ const program_state *new_state) const final override;
/* State for a FILE * returned from fopen that hasn't been checked for
NULL.
@@ -156,11 +161,11 @@ public:
{
if (change.m_old_state == m_sm.get_start_state ()
&& change.m_new_state == m_sm.m_unchecked)
- return diagnostic_event::meaning (diagnostic_event::VERB_acquire,
- diagnostic_event::NOUN_resource);
+ return diagnostic_event::meaning (diagnostic_event::verb::acquire,
+ diagnostic_event::noun::resource);
if (change.m_new_state == m_sm.m_closed)
- return diagnostic_event::meaning (diagnostic_event::VERB_release,
- diagnostic_event::NOUN_resource);
+ return diagnostic_event::meaning (diagnostic_event::verb::release,
+ diagnostic_event::noun::resource);
return diagnostic_event::meaning ();
}
@@ -226,9 +231,14 @@ private:
class file_leak : public file_diagnostic
{
public:
- file_leak (const fileptr_state_machine &sm, tree arg)
- : file_diagnostic (sm, arg)
- {}
+ file_leak (const fileptr_state_machine &sm, tree arg,
+ const program_state *final_state)
+ : file_diagnostic (sm, arg),
+ m_final_state ()
+ {
+ if (final_state)
+ m_final_state = std::make_unique<program_state> (*final_state);
+ }
const char *get_kind () const final override { return "file_leak"; }
@@ -286,8 +296,15 @@ public:
return true;
}
+ const program_state *
+ get_final_state () const final override
+ {
+ return m_final_state.get ();
+ }
+
private:
diagnostic_event_id_t m_fopen_event;
+ std::unique_ptr<program_state> m_final_state;
};
/* fileptr_state_machine's ctor. */
@@ -492,9 +509,11 @@ fileptr_state_machine::can_purge_p (state_t s) const
state 'unchecked' and 'nonnull'. */
std::unique_ptr<pending_diagnostic>
-fileptr_state_machine::on_leak (tree var) const
+fileptr_state_machine::on_leak (tree var,
+ const program_state *,
+ const program_state *new_state) const
{
- return std::make_unique<file_leak> (*this, var);
+ return std::make_unique<file_leak> (*this, var, new_state);
}
} // anonymous namespace
diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index 333dfea..3581dbb 100644
--- a/gcc/analyzer/sm-malloc.cc
+++ b/gcc/analyzer/sm-malloc.cc
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-event-id.h"
#include "stringpool.h"
#include "attribs.h"
+#include "xml-printer.h"
#include "analyzer/analyzer-logging.h"
#include "analyzer/sm.h"
@@ -37,6 +38,7 @@ along with GCC; see the file COPYING3. If not see
#include "analyzer/checker-event.h"
#include "analyzer/exploded-graph.h"
#include "analyzer/inlining-iterator.h"
+#include "analyzer/ana-state-to-diagnostic-state.h"
#if ENABLE_ANALYZER
@@ -139,7 +141,7 @@ struct assumed_non_null_state : public allocation_state
assumed_non_null_state (const char *name, unsigned id,
const frame_region *frame)
: allocation_state (name, id, RS_ASSUMED_NON_NULL,
- NULL, NULL),
+ nullptr, nullptr),
m_frame (frame)
{
gcc_assert (m_frame);
@@ -290,7 +292,7 @@ struct deallocator_set_map_traits
static inline hashval_t hash (const key_type &k)
{
- gcc_assert (k != NULL);
+ gcc_assert (k != nullptr);
gcc_assert (k != reinterpret_cast<key_type> (1));
hashval_t result = 0;
@@ -324,7 +326,7 @@ struct deallocator_set_map_traits
template <typename T>
static inline void mark_empty (T &entry)
{
- entry.m_key = NULL;
+ entry.m_key = nullptr;
}
template <typename T>
static inline bool is_deleted (const T &entry)
@@ -334,7 +336,7 @@ struct deallocator_set_map_traits
template <typename T>
static inline bool is_empty (const T &entry)
{
- return entry.m_key == NULL;
+ return entry.m_key == nullptr;
}
static const bool empty_zero_p = false;
};
@@ -403,7 +405,11 @@ public:
const frame_region *) const final override;
bool can_purge_p (state_t s) const final override;
- std::unique_ptr<pending_diagnostic> on_leak (tree var) const final override;
+
+ std::unique_ptr<pending_diagnostic>
+ on_leak (tree var,
+ const program_state *old_state,
+ const program_state *new_state) const final override;
bool reset_when_passed_to_unknown_fn_p (state_t s,
bool is_mutable) const final override;
@@ -429,6 +435,11 @@ public:
const svalue *new_ptr_sval,
const extrinsic_state &ext_state) const;
+ void
+ add_state_to_xml (xml_state &out_xml,
+ const svalue &sval,
+ state_machine::state_t state) const final override;
+
standard_deallocator_set m_free;
standard_deallocator_set m_scalar_delete;
standard_deallocator_set m_vector_delete;
@@ -524,7 +535,7 @@ deallocator::deallocator (malloc_state_machine *sm,
enum wording wording)
: m_name (name),
m_wording (wording),
- m_freed (sm->add_state ("freed", RS_FREED, NULL, this))
+ m_freed (sm->add_state ("freed", RS_FREED, nullptr, this))
{
}
@@ -568,8 +579,8 @@ standard_deallocator::standard_deallocator (malloc_state_machine *sm,
deallocator_set::deallocator_set (malloc_state_machine *sm,
enum wording wording)
: m_wording (wording),
- m_unchecked (sm->add_state ("unchecked", RS_UNCHECKED, this, NULL)),
- m_nonnull (sm->add_state ("nonnull", RS_NONNULL, this, NULL))
+ m_unchecked (sm->add_state ("unchecked", RS_UNCHECKED, this, nullptr)),
+ m_nonnull (sm->add_state ("nonnull", RS_NONNULL, this, nullptr))
{
}
@@ -614,7 +625,7 @@ custom_deallocator_set::maybe_get_single () const
{
if (m_deallocator_vec.length () == 1)
return m_deallocator_vec[0];
- return NULL;
+ return nullptr;
}
void
@@ -662,14 +673,15 @@ standard_deallocator_set::dump_to_pp (pretty_printer *pp) const
pp_character (pp, '}');
}
-/* Return STATE cast to the custom state subclass, or NULL for the start state.
+/* Return STATE cast to the custom state subclass, or nullptr for the
+ start state.
Everything should be an allocation_state apart from the start state. */
static const allocation_state *
dyn_cast_allocation_state (state_machine::state_t state)
{
if (state->get_id () == 0)
- return NULL;
+ return nullptr;
return static_cast <const allocation_state *> (state);
}
@@ -808,11 +820,11 @@ public:
{
if (change.m_old_state == m_sm.get_start_state ()
&& unchecked_p (change.m_new_state))
- return diagnostic_event::meaning (diagnostic_event::VERB_acquire,
- diagnostic_event::NOUN_memory);
+ return diagnostic_event::meaning (diagnostic_event::verb::acquire,
+ diagnostic_event::noun::memory);
if (freed_p (change.m_new_state))
- return diagnostic_event::meaning (diagnostic_event::VERB_release,
- diagnostic_event::NOUN_memory);
+ return diagnostic_event::meaning (diagnostic_event::verb::release,
+ diagnostic_event::noun::memory);
return diagnostic_event::meaning ();
}
@@ -1414,8 +1426,14 @@ private:
class malloc_leak : public malloc_diagnostic
{
public:
- malloc_leak (const malloc_state_machine &sm, tree arg)
- : malloc_diagnostic (sm, arg) {}
+ malloc_leak (const malloc_state_machine &sm, tree arg,
+ const program_state *final_state)
+ : malloc_diagnostic (sm, arg),
+ m_final_state ()
+ {
+ if (final_state)
+ m_final_state = std::make_unique<program_state> (*final_state);
+ }
const char *get_kind () const final override { return "malloc_leak"; }
@@ -1475,8 +1493,15 @@ public:
return true;
}
+ const program_state *
+ get_final_state () const final override
+ {
+ return m_final_state.get ();
+ }
+
private:
diagnostic_event_id_t m_alloc_event;
+ std::unique_ptr<program_state> m_final_state;
};
class free_of_non_heap : public malloc_diagnostic
@@ -1571,9 +1596,9 @@ class deref_before_check : public malloc_diagnostic
public:
deref_before_check (const malloc_state_machine &sm, tree arg)
: malloc_diagnostic (sm, arg),
- m_deref_enode (NULL),
- m_deref_expr (NULL),
- m_check_enode (NULL)
+ m_deref_enode (nullptr),
+ m_deref_expr (nullptr),
+ m_check_enode (nullptr)
{
gcc_assert (arg);
}
@@ -1798,9 +1823,9 @@ malloc_state_machine::malloc_state_machine (logger *logger)
m_realloc (this, "realloc", WORDING_REALLOCATED)
{
gcc_assert (m_start->get_id () == 0);
- m_null = add_state ("null", RS_FREED, NULL, NULL);
- m_non_heap = add_state ("non-heap", RS_NON_HEAP, NULL, NULL);
- m_stop = add_state ("stop", RS_STOP, NULL, NULL);
+ m_null = add_state ("null", RS_FREED, nullptr, nullptr);
+ m_non_heap = add_state ("non-heap", RS_NON_HEAP, nullptr, nullptr);
+ m_stop = add_state ("stop", RS_STOP, nullptr, nullptr);
}
malloc_state_machine::~malloc_state_machine ()
@@ -1828,7 +1853,7 @@ malloc_state_machine::add_state (const char *name, enum resource_state rs,
return a custom_deallocator_set for them, consolidating them
to ensure uniqueness of the sets.
- Return NULL if it has no such attributes. */
+ Return nullptr if it has no such attributes. */
const custom_deallocator_set *
malloc_state_machine::
@@ -1837,7 +1862,7 @@ get_or_create_custom_deallocator_set (tree allocator_fndecl)
/* Early rejection of decls without attributes. */
tree attrs = DECL_ATTRIBUTES (allocator_fndecl);
if (!attrs)
- return NULL;
+ return nullptr;
/* Otherwise, call maybe_create_custom_deallocator_set,
memoizing the result. */
@@ -1855,7 +1880,7 @@ get_or_create_custom_deallocator_set (tree allocator_fndecl)
custom_deallocator_set for them, consolidating them
to ensure uniqueness of the sets.
- Return NULL if it has no such attributes.
+ Return nullptr if it has no such attributes.
Subroutine of get_or_create_custom_deallocator_set which
memoizes the result. */
@@ -1886,7 +1911,7 @@ maybe_create_custom_deallocator_set (tree allocator_fndecl)
/* If there weren't any deallocators, bail. */
if (deallocator_vec.length () == 0)
- return NULL;
+ return nullptr;
/* Consolidate, so that we reuse existing deallocator_set
instances. */
@@ -1991,7 +2016,7 @@ malloc_state_machine::maybe_assume_non_null (sm_context &sm_ctxt,
tree null_ptr_cst = build_int_cst (TREE_TYPE (ptr), 0);
tristate known_non_null
- = old_model->eval_condition (ptr, NE_EXPR, null_ptr_cst, NULL);
+ = old_model->eval_condition (ptr, NE_EXPR, null_ptr_cst, nullptr);
if (known_non_null.is_unknown ())
{
/* Cast away const-ness for cache-like operations. */
@@ -2172,19 +2197,27 @@ malloc_state_machine::on_stmt (sm_context &sm_ctxt,
unsigned int idx = TREE_INT_CST_LOW (TREE_VALUE (args)) - 1;
unsigned int idx2
= TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (args))) - 1;
+ unsigned int idx3 = idx2;
+ if (tree chain2 = TREE_CHAIN (TREE_CHAIN (args)))
+ idx3 = TREE_INT_CST_LOW (TREE_VALUE (chain2)) - 1;
if (idx < gimple_call_num_args (stmt)
- && idx2 < gimple_call_num_args (stmt))
+ && idx2 < gimple_call_num_args (stmt)
+ && idx3 < gimple_call_num_args (stmt))
{
tree arg = gimple_call_arg (stmt, idx);
tree arg2 = gimple_call_arg (stmt, idx2);
+ tree arg3 = gimple_call_arg (stmt, idx3);
if (TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE
|| !INTEGRAL_TYPE_P (TREE_TYPE (arg2))
- || integer_zerop (arg2))
+ || !INTEGRAL_TYPE_P (TREE_TYPE (arg3))
+ || integer_zerop (arg2)
+ || integer_zerop (arg3))
continue;
- if (integer_nonzerop (arg2))
+ if (integer_nonzerop (arg2) && integer_nonzerop (arg3))
;
else
- /* FIXME: Use ranger here to query arg2 range? */
+ /* FIXME: Use ranger here to query arg2 and arg3
+ ranges? */
continue;
handle_nonnull (sm_ctxt, node, stmt, fndecl, arg, idx);
}
@@ -2376,12 +2409,12 @@ malloc_state_machine::handle_free_of_non_heap (sm_context &sm_ctxt,
const deallocator *d) const
{
tree diag_arg = sm_ctxt.get_diagnostic_tree (arg);
- const region *freed_reg = NULL;
+ const region *freed_reg = nullptr;
if (const program_state *old_state = sm_ctxt.get_old_program_state ())
{
const region_model *old_model = old_state->m_region_model;
- const svalue *ptr_sval = old_model->get_rvalue (arg, NULL);
- freed_reg = old_model->deref_rvalue (ptr_sval, arg, NULL);
+ const svalue *ptr_sval = old_model->get_rvalue (arg, nullptr);
+ freed_reg = old_model->deref_rvalue (ptr_sval, arg, nullptr);
}
sm_ctxt.warn (node, &call, arg,
std::make_unique<free_of_non_heap>
@@ -2589,9 +2622,11 @@ malloc_state_machine::can_purge_p (state_t s) const
'nonnull'). */
std::unique_ptr<pending_diagnostic>
-malloc_state_machine::on_leak (tree var) const
+malloc_state_machine::on_leak (tree var,
+ const program_state *,
+ const program_state *new_state) const
{
- return std::make_unique<malloc_leak> (*this, var);
+ return std::make_unique<malloc_leak> (*this, var, new_state);
}
/* Implementation of state_machine::reset_when_passed_to_unknown_fn_p vfunc
@@ -2624,7 +2659,7 @@ malloc_state_machine::maybe_get_merged_states_nonequal (state_t state_a,
return m_start;
if (state_a == m_start && assumed_non_null_p (state_b))
return m_start;
- return NULL;
+ return nullptr;
}
/* Return true if calls to FNDECL are known to not affect this sm-state. */
@@ -2682,11 +2717,11 @@ on_realloc_with_move (region_model *model,
{
smap->set_state (model, old_ptr_sval,
m_free.m_deallocator.m_freed,
- NULL, ext_state);
+ nullptr, ext_state);
smap->set_state (model, new_ptr_sval,
m_free.m_nonnull,
- NULL, ext_state);
+ nullptr, ext_state);
}
/* Hook for get_or_create_region_for_heap_alloc for the case when we want
@@ -2697,7 +2732,31 @@ malloc_state_machine::transition_ptr_sval_non_null (region_model *model,
const svalue *new_ptr_sval,
const extrinsic_state &ext_state) const
{
- smap->set_state (model, new_ptr_sval, m_free.m_nonnull, NULL, ext_state);
+ smap->set_state (model, new_ptr_sval, m_free.m_nonnull, nullptr, ext_state);
+}
+
+void
+malloc_state_machine::add_state_to_xml (xml_state &out_xml,
+ const svalue &sval,
+ state_machine::state_t state) const
+{
+ if (const region *reg = sval.maybe_get_region ())
+ {
+ auto &reg_element = out_xml.get_or_create_element (*reg);
+ auto alloc_state = as_a_allocation_state (state);
+ gcc_assert (alloc_state);
+
+ reg_element.set_attr ("dynamic-alloc-state", state->get_name ());
+ if (alloc_state->m_deallocators)
+ {
+ pretty_printer pp;
+ alloc_state->m_deallocators->dump_to_pp (&pp);
+ reg_element.set_attr ("expected-deallocators", pp_formatted_text (&pp));
+ }
+ if (alloc_state->m_deallocator)
+ reg_element.set_attr ("deallocator",
+ alloc_state->m_deallocator->m_name);
+ }
}
} // anonymous namespace
diff --git a/gcc/analyzer/sm-pattern-test.cc b/gcc/analyzer/sm-pattern-test.cc
index f05ffe0..02b32ac 100644
--- a/gcc/analyzer/sm-pattern-test.cc
+++ b/gcc/analyzer/sm-pattern-test.cc
@@ -122,7 +122,7 @@ pattern_test_state_machine::on_condition (sm_context &sm_ctxt,
enum tree_code op,
const svalue *rhs) const
{
- if (stmt == NULL)
+ if (stmt == nullptr)
return;
tree rhs_cst = rhs->maybe_get_constant ();
diff --git a/gcc/analyzer/sm-sensitive.cc b/gcc/analyzer/sm-sensitive.cc
index 7bd5ef6..f8fcded 100644
--- a/gcc/analyzer/sm-sensitive.cc
+++ b/gcc/analyzer/sm-sensitive.cc
@@ -111,8 +111,8 @@ public:
const final override
{
if (change.m_new_state == m_sm.m_sensitive)
- return diagnostic_event::meaning (diagnostic_event::VERB_acquire,
- diagnostic_event::NOUN_sensitive);
+ return diagnostic_event::meaning (diagnostic_event::verb::acquire,
+ diagnostic_event::noun::sensitive);
return diagnostic_event::meaning ();
}
bool
diff --git a/gcc/analyzer/sm-signal.cc b/gcc/analyzer/sm-signal.cc
index 83f2808..5a4b384 100644
--- a/gcc/analyzer/sm-signal.cc
+++ b/gcc/analyzer/sm-signal.cc
@@ -173,7 +173,7 @@ private:
if (id_equal ("exit", DECL_NAME (m_unsafe_fndecl)))
return "_exit";
- return NULL;
+ return nullptr;
}
};
@@ -269,7 +269,7 @@ public:
state_entering_handler,
src_enode);
if (dst_enode)
- eg->add_edge (src_enode, dst_enode, NULL, /*state_change (),*/
+ eg->add_edge (src_enode, dst_enode, nullptr, /*state_change (),*/
true, /* assume does work */
std::make_unique<signal_delivery_edge_info_t> ());
}
diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc
index e782081..5c8cc7e 100644
--- a/gcc/analyzer/sm-taint.cc
+++ b/gcc/analyzer/sm-taint.cc
@@ -214,8 +214,8 @@ public:
const final override
{
if (change.m_new_state == m_sm.m_tainted)
- return diagnostic_event::meaning (diagnostic_event::VERB_acquire,
- diagnostic_event::NOUN_taint);
+ return diagnostic_event::meaning (diagnostic_event::verb::acquire,
+ diagnostic_event::noun::taint);
return diagnostic_event::meaning ();
}
@@ -934,7 +934,7 @@ public:
macro when we're describing them. */
return linemap_resolve_location (line_table, loc,
LRK_SPELLING_LOCATION,
- NULL);
+ nullptr);
else
return pending_diagnostic::fixup_location (loc, primary);
}
@@ -1060,12 +1060,12 @@ taint_state_machine::alt_get_inherited_state (const sm_state_map &map,
case BIT_AND_EXPR:
case RSHIFT_EXPR:
- return NULL;
+ return nullptr;
}
}
break;
}
- return NULL;
+ return nullptr;
}
/* Return true iff FNDECL should be considered to be an assertion failure
@@ -1175,7 +1175,7 @@ taint_state_machine::check_control_flow_arg_for_taint (sm_context &sm_ctxt,
tree expr) const
{
const region_model *old_model = sm_ctxt.get_old_region_model ();
- const svalue *sval = old_model->get_rvalue (expr, NULL);
+ const svalue *sval = old_model->get_rvalue (expr, nullptr);
state_t state = sm_ctxt.get_state (stmt, sval);
enum bounds b;
if (get_taint (state, TREE_TYPE (expr), &b))
@@ -1194,7 +1194,7 @@ taint_state_machine::on_condition (sm_context &sm_ctxt,
enum tree_code op,
const svalue *rhs) const
{
- if (stmt == NULL)
+ if (stmt == nullptr)
return;
if (lhs->get_kind () == SK_UNKNOWN
@@ -1492,7 +1492,7 @@ taint_state_machine::check_for_tainted_divisor (sm_context &sm_ctxt,
if (!INTEGRAL_TYPE_P (TREE_TYPE (divisor_expr)))
return;
- const svalue *divisor_sval = old_model->get_rvalue (divisor_expr, NULL);
+ const svalue *divisor_sval = old_model->get_rvalue (divisor_expr, nullptr);
state_t state = sm_ctxt.get_state (assign, divisor_sval);
enum bounds b;
@@ -1793,7 +1793,7 @@ region_model::mark_as_tainted (const svalue *sval,
if (!ext_state)
return;
- smap->set_state (this, sval, taint_sm.m_tainted, NULL, *ext_state);
+ smap->set_state (this, sval, taint_sm.m_tainted, nullptr, *ext_state);
}
/* Return true if SVAL could possibly be attacker-controlled. */
diff --git a/gcc/analyzer/sm.cc b/gcc/analyzer/sm.cc
index 0abbdd6..840806a 100644
--- a/gcc/analyzer/sm.cc
+++ b/gcc/analyzer/sm.cc
@@ -116,9 +116,11 @@ state_machine::get_state_by_name (const char *name) const
/* Base implementation of state_machine::on_leak. */
std::unique_ptr<pending_diagnostic>
-state_machine::on_leak (tree var ATTRIBUTE_UNUSED) const
+state_machine::on_leak (tree var ATTRIBUTE_UNUSED,
+ const program_state *old_state ATTRIBUTE_UNUSED,
+ const program_state *new_state ATTRIBUTE_UNUSED) const
{
- return NULL;
+ return nullptr;
}
/* Dump a multiline representation of this state machine to PP. */
@@ -158,6 +160,21 @@ state_machine::to_json () const
return sm_obj;
}
+void
+state_machine::add_state_to_xml (xml_state &out_xml,
+ const svalue &sval,
+ state_machine::state_t state) const
+{
+ // no-op
+}
+
+void
+state_machine::add_global_state_to_xml (xml_state &out_xml,
+ state_machine::state_t state) const
+{
+ // no-op
+}
+
/* class sm_context. */
const region_model *
@@ -166,7 +183,7 @@ sm_context::get_old_region_model () const
if (const program_state *old_state = get_old_program_state ())
return old_state->m_region_model;
else
- return NULL;
+ return nullptr;
}
/* Create instances of the various state machines, each using LOGGER,
diff --git a/gcc/analyzer/sm.h b/gcc/analyzer/sm.h
index a932765..6298fb6 100644
--- a/gcc/analyzer/sm.h
+++ b/gcc/analyzer/sm.h
@@ -28,6 +28,7 @@ namespace ana {
class state_machine;
class sm_context;
class pending_diagnostic;
+class xml_state;
extern bool any_pointer_p (tree expr);
extern bool any_pointer_p (const svalue *sval);
@@ -75,7 +76,7 @@ public:
const svalue *,
const extrinsic_state &) const
{
- return NULL;
+ return nullptr;
}
virtual bool
@@ -136,7 +137,9 @@ public:
/* Called when VAR leaks (and !can_purge_p). */
virtual std::unique_ptr<pending_diagnostic>
- on_leak (tree var ATTRIBUTE_UNUSED) const;
+ on_leak (tree var ATTRIBUTE_UNUSED,
+ const program_state *old_state,
+ const program_state *new_state) const;
/* Return true if S should be reset to "start" for values passed (or reachable
from) calls to unknown functions. IS_MUTABLE is true for pointers as
@@ -152,7 +155,7 @@ public:
}
/* Attempt to get a state for the merger of STATE_A and STATE_B,
- or return NULL if merging shouldn't occur, so that differences
+ or return nullptr if merging shouldn't occur, so that differences
between sm-state will lead to separate exploded nodes.
Most state machines will only merge equal states, but can
@@ -173,7 +176,7 @@ public:
state_t state_b ATTRIBUTE_UNUSED) const
{
/* By default, non-equal sm states should inhibit merger of enodes. */
- return NULL;
+ return nullptr;
}
void validate (state_t s) const;
@@ -184,6 +187,15 @@ public:
state_t get_start_state () const { return m_start; }
+ virtual void
+ add_state_to_xml (xml_state &out_xml,
+ const svalue &sval,
+ state_machine::state_t state) const;
+
+ virtual void
+ add_global_state_to_xml (xml_state &out_xml,
+ state_machine::state_t state) const;
+
protected:
state_t add_state (const char *name);
state_t add_custom_state (state *s)
@@ -318,7 +330,7 @@ public:
virtual path_context *get_path_context () const
{
- return NULL;
+ return nullptr;
}
/* Are we handling an external function with unknown side effects? */
diff --git a/gcc/analyzer/state-purge.cc b/gcc/analyzer/state-purge.cc
index 7a93cee..1371db9 100644
--- a/gcc/analyzer/state-purge.cc
+++ b/gcc/analyzer/state-purge.cc
@@ -659,7 +659,7 @@ state_purge_per_ssa_name::process_point (const function_point &point,
if (snode->entry_p ())
{
add_to_worklist
- (function_point::before_supernode (snode, NULL),
+ (function_point::before_supernode (snode, nullptr),
worklist, logger);
}
}
@@ -841,8 +841,8 @@ fully_overwrites_p (const gimple *stmt, tree decl,
We can't just check for equality; consider the case of
"s.field = EXPR;" where the stmt writes to the only field
of "s", and there's no padding. */
- const region *lhs_reg = model.get_lvalue (lhs, NULL);
- const region *decl_reg = model.get_lvalue (decl, NULL);
+ const region *lhs_reg = model.get_lvalue (lhs, nullptr);
+ const region *decl_reg = model.get_lvalue (decl, nullptr);
if (same_binding_p (lhs_reg, decl_reg,
model.get_manager ()->get_store_manager ()))
return true;
@@ -1074,7 +1074,7 @@ state_purge_annotator::add_node_annotations (graphviz_out *gv,
const supernode &n,
bool within_table) const
{
- if (m_map == NULL)
+ if (m_map == nullptr)
return false;
if (within_table)
@@ -1091,7 +1091,7 @@ state_purge_annotator::add_node_annotations (graphviz_out *gv,
Determine which points to dump. */
auto_vec<function_point> points;
if (n.entry_p () || n.m_returning_call)
- points.safe_push (function_point::before_supernode (&n, NULL));
+ points.safe_push (function_point::before_supernode (&n, nullptr));
else
for (auto inedge : n.m_preds)
points.safe_push (function_point::before_supernode (&n, inedge));
@@ -1153,7 +1153,7 @@ state_purge_annotator::add_stmt_annotations (graphviz_out *gv,
if (within_row)
return;
- if (m_map == NULL)
+ if (m_map == nullptr)
return;
if (stmt->code == GIMPLE_PHI)
diff --git a/gcc/analyzer/state-purge.h b/gcc/analyzer/state-purge.h
index bbe78a5..2bac564 100644
--- a/gcc/analyzer/state-purge.h
+++ b/gcc/analyzer/state-purge.h
@@ -109,7 +109,7 @@ public:
= const_cast <decl_map_t&> (m_decl_map).get (decl))
return *slot;
else
- return NULL;
+ return nullptr;
}
state_purge_per_decl &
diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc
index e6723c7..942c945 100644
--- a/gcc/analyzer/store.cc
+++ b/gcc/analyzer/store.cc
@@ -658,7 +658,7 @@ binding_map::operator== (const binding_map &other) const
const svalue *sval = (*iter).second;
const svalue **other_slot
= const_cast <map_t &> (other.m_map).get (key);
- if (other_slot == NULL)
+ if (other_slot == nullptr)
return false;
if (sval != *other_slot)
return false;
@@ -922,7 +922,7 @@ get_svalue_for_ctor_val (tree val, region_model_manager *mgr)
{
/* Reuse the get_rvalue logic from region_model. */
region_model m (mgr);
- return m.get_rvalue (path_var (val, 0), NULL);
+ return m.get_rvalue (path_var (val, 0), nullptr);
}
/* Bind values from CONSTRUCTOR to this map, relative to
@@ -1564,7 +1564,7 @@ binding_cluster::bind_compound_sval (store_manager *mgr,
void
binding_cluster::clobber_region (store_manager *mgr, const region *reg)
{
- remove_overlapping_bindings (mgr, reg, NULL, NULL);
+ remove_overlapping_bindings (mgr, reg, nullptr, nullptr);
}
/* Remove any bindings for REG within this cluster. */
@@ -1684,7 +1684,7 @@ binding_cluster::get_binding (store_manager *mgr,
const region *reg) const
{
if (reg->empty_p ())
- return NULL;
+ return nullptr;
const binding_key *reg_binding = binding_key::make (mgr, reg);
const svalue *sval = m_map.get (reg_binding);
if (sval)
@@ -1752,7 +1752,7 @@ binding_cluster::get_binding_recursive (store_manager *mgr,
return rmm_mgr->get_or_create_sub_svalue (reg->get_type (),
parent_sval, reg);
}
- return NULL;
+ return nullptr;
}
/* Get any value bound for REG within this cluster. */
@@ -1800,7 +1800,7 @@ binding_cluster::get_any_binding (store_manager *mgr,
return compound_sval;
/* Otherwise, the initial value, or uninitialized. */
- return NULL;
+ return nullptr;
}
/* Attempt to get a compound_svalue for the bindings within the cluster
@@ -1812,7 +1812,7 @@ binding_cluster::get_any_binding (store_manager *mgr,
For example, REG could be one element within an array of structs.
- Return the resulting compound_svalue, or NULL if there's a problem. */
+ Return the resulting compound_svalue, or nullptr if there's a problem. */
const svalue *
binding_cluster::maybe_get_compound_binding (store_manager *mgr,
@@ -1821,13 +1821,13 @@ binding_cluster::maybe_get_compound_binding (store_manager *mgr,
region_offset cluster_offset
= m_base_region->get_offset (mgr->get_svalue_manager ());
if (cluster_offset.symbolic_p ())
- return NULL;
+ return nullptr;
region_offset reg_offset = reg->get_offset (mgr->get_svalue_manager ());
if (reg_offset.symbolic_p ())
- return NULL;
+ return nullptr;
if (reg->empty_p ())
- return NULL;
+ return nullptr;
region_model_manager *sval_mgr = mgr->get_svalue_manager ();
@@ -1880,7 +1880,7 @@ binding_cluster::maybe_get_compound_binding (store_manager *mgr,
bit_size_t reg_bit_size;
if (!reg->get_bit_size (&reg_bit_size))
- return NULL;
+ return nullptr;
bit_range reg_range (reg_offset.get_bit_offset (),
reg_bit_size);
@@ -1909,7 +1909,7 @@ binding_cluster::maybe_get_compound_binding (store_manager *mgr,
it overlaps with offset_concrete_key. */
default_map.remove_overlapping_bindings (mgr,
offset_concrete_key,
- NULL, NULL, false);
+ nullptr, nullptr, false);
}
else if (bound_range.contains_p (reg_range, &subrange))
{
@@ -1943,16 +1943,16 @@ binding_cluster::maybe_get_compound_binding (store_manager *mgr,
it overlaps with overlap_concrete_key. */
default_map.remove_overlapping_bindings (mgr,
overlap_concrete_key,
- NULL, NULL, false);
+ nullptr, nullptr, false);
}
}
else
/* Can't handle symbolic bindings. */
- return NULL;
+ return nullptr;
}
if (result_map.elements () == 0)
- return NULL;
+ return nullptr;
/* Merge any bindings from default_map into result_map. */
for (auto iter : default_map)
@@ -2030,23 +2030,23 @@ binding_cluster::can_merge_p (const binding_cluster *cluster_a,
/* At least one of CLUSTER_A and CLUSTER_B are non-NULL, but either
could be NULL. Handle these cases. */
- if (cluster_a == NULL)
+ if (cluster_a == nullptr)
{
- gcc_assert (cluster_b != NULL);
+ gcc_assert (cluster_b != nullptr);
gcc_assert (cluster_b->m_base_region == out_cluster->m_base_region);
out_cluster->make_unknown_relative_to (cluster_b, out_store, mgr);
return true;
}
- if (cluster_b == NULL)
+ if (cluster_b == nullptr)
{
- gcc_assert (cluster_a != NULL);
+ gcc_assert (cluster_a != nullptr);
gcc_assert (cluster_a->m_base_region == out_cluster->m_base_region);
out_cluster->make_unknown_relative_to (cluster_a, out_store, mgr);
return true;
}
/* The "both inputs are non-NULL" case. */
- gcc_assert (cluster_a != NULL && cluster_b != NULL);
+ gcc_assert (cluster_a != nullptr && cluster_b != nullptr);
gcc_assert (cluster_a->m_base_region == out_cluster->m_base_region);
gcc_assert (cluster_b->m_base_region == out_cluster->m_base_region);
@@ -2319,7 +2319,7 @@ binding_cluster::get_representative_path_vars (const region_model *model,
}
}
-/* Get any svalue bound to KEY, or NULL. */
+/* Get any svalue bound to KEY, or nullptr. */
const svalue *
binding_cluster::get_any_value (const binding_key *key) const
@@ -2334,16 +2334,16 @@ binding_cluster::get_any_value (const binding_key *key) const
const svalue *
binding_cluster::maybe_get_simple_value (store_manager *mgr) const
{
- /* Fail gracefully if MGR is NULL to make it easier to dump store
+ /* Fail gracefully if MGR is nullptr to make it easier to dump store
instances in the debugger. */
- if (mgr == NULL)
- return NULL;
+ if (mgr == nullptr)
+ return nullptr;
if (m_map.elements () != 1)
- return NULL;
+ return nullptr;
if (m_base_region->empty_p ())
- return NULL;
+ return nullptr;
const binding_key *key = binding_key::make (mgr, m_base_region);
return get_any_value (key);
@@ -2467,7 +2467,7 @@ store::operator== (const store &other) const
binding_cluster *c = (*iter).second;
binding_cluster **other_slot
= const_cast <cluster_map_t &> (other.m_cluster_map).get (reg);
- if (other_slot == NULL)
+ if (other_slot == nullptr)
return false;
if (*c != **other_slot)
return false;
@@ -2520,7 +2520,7 @@ get_sorted_parent_regions (auto_vec<const region *> *out,
/* Dump a representation of this store to PP, using SIMPLE to control how
svalues and regions are printed.
- MGR is used for simplifying dumps if non-NULL, but can also be NULL
+ MGR is used for simplifying dumps if non-NULL, but can also be nullptr
(to make it easier to use from the debugger). */
void
@@ -2629,7 +2629,7 @@ DEBUG_FUNCTION void
store::dump (bool simple) const
{
tree_dump_pretty_printer pp (stderr);
- dump_to_pp (&pp, simple, true, NULL);
+ dump_to_pp (&pp, simple, true, nullptr);
pp_newline (&pp);
}
@@ -2761,7 +2761,7 @@ store::make_dump_widget (const text_art::dump_widget_info &dwi,
return store_widget;
}
-/* Get any svalue bound to REG, or NULL. */
+/* Get any svalue bound to REG, or nullptr. */
const svalue *
store::get_any_binding (store_manager *mgr, const region *reg) const
@@ -2770,7 +2770,7 @@ store::get_any_binding (store_manager *mgr, const region *reg) const
binding_cluster **cluster_slot
= const_cast <cluster_map_t &> (m_cluster_map).get (base_reg);
if (!cluster_slot)
- return NULL;
+ return nullptr;
return (*cluster_slot)->get_any_binding (mgr, reg);
}
@@ -2796,7 +2796,7 @@ store::set_value (store_manager *mgr, const region *lhs_reg,
{
/* Reject attempting to bind values into a symbolic region
for an unknown ptr; merely invalidate values below. */
- lhs_cluster = NULL;
+ lhs_cluster = nullptr;
/* The LHS of the write is *UNKNOWN. If the RHS is a pointer,
then treat the region being pointed to as having escaped. */
@@ -2818,7 +2818,7 @@ store::set_value (store_manager *mgr, const region *lhs_reg,
{
/* Reject attempting to bind values into an untracked region;
merely invalidate values below. */
- lhs_cluster = NULL;
+ lhs_cluster = nullptr;
}
/* Bindings to a cluster can affect other clusters if a symbolic
@@ -2838,7 +2838,7 @@ store::set_value (store_manager *mgr, const region *lhs_reg,
const region *iter_base_reg = (*iter).first;
binding_cluster *iter_cluster = (*iter).second;
if (iter_base_reg != lhs_base_reg
- && (lhs_cluster == NULL
+ && (lhs_cluster == nullptr
|| lhs_cluster->symbolic_p ()
|| iter_cluster->symbolic_p ()))
{
@@ -3097,7 +3097,7 @@ store::purge_state_involving (const svalue *sval,
purge_cluster (iter);
}
-/* Get the cluster for BASE_REG, or NULL (const version). */
+/* Get the cluster for BASE_REG, or nullptr (const version). */
const binding_cluster *
store::get_cluster (const region *base_reg) const
@@ -3108,10 +3108,10 @@ store::get_cluster (const region *base_reg) const
= const_cast <cluster_map_t &> (m_cluster_map).get (base_reg))
return *slot;
else
- return NULL;
+ return nullptr;
}
-/* Get the cluster for BASE_REG, or NULL (non-const version). */
+/* Get the cluster for BASE_REG, or nullptr (non-const version). */
binding_cluster *
store::get_cluster (const region *base_reg)
@@ -3121,7 +3121,7 @@ store::get_cluster (const region *base_reg)
if (binding_cluster **slot = m_cluster_map.get (base_reg))
return *slot;
else
- return NULL;
+ return nullptr;
}
/* Get the cluster for BASE_REG, creating it if doesn't already exist. */
@@ -3321,9 +3321,9 @@ store::remove_overlapping_bindings (store_manager *mgr, const region *reg,
delete cluster;
return;
}
- /* Pass NULL for the maybe_live_values here, as we don't want to
+ /* Pass nullptr for the maybe_live_values here, as we don't want to
record the old svalues as being maybe-bound. */
- cluster->remove_overlapping_bindings (mgr, reg, uncertainty, NULL);
+ cluster->remove_overlapping_bindings (mgr, reg, uncertainty, nullptr);
}
}
@@ -3566,7 +3566,7 @@ store::replay_call_summary_cluster (call_summary_replay &r,
caller_sval =
reg_mgr->get_or_create_unknown_svalue (summary_sval->get_type ());
set_value (mgr, caller_dest_reg,
- caller_sval, NULL /* uncertainty_t * */);
+ caller_sval, nullptr /* uncertainty_t * */);
}
break;
@@ -3591,7 +3591,7 @@ store::replay_call_summary_cluster (call_summary_replay &r,
caller_sval =
reg_mgr->get_or_create_unknown_svalue (summary_sval->get_type ());
set_value (mgr, caller_dest_reg,
- caller_sval, NULL /* uncertainty_t * */);
+ caller_sval, nullptr /* uncertainty_t * */);
}
break;
@@ -3786,7 +3786,7 @@ assert_disjoint (const location &loc,
static void
test_binding_key_overlap ()
{
- store_manager mgr (NULL);
+ store_manager mgr (nullptr);
/* Various 8-bit bindings. */
const concrete_binding *cb_0_7 = mgr.get_concrete_binding (0, 8);
diff --git a/gcc/analyzer/store.h b/gcc/analyzer/store.h
index 171324c..95d38e3 100644
--- a/gcc/analyzer/store.h
+++ b/gcc/analyzer/store.h
@@ -222,9 +222,9 @@ public:
static int cmp (const binding_key *, const binding_key *);
virtual const concrete_binding *dyn_cast_concrete_binding () const
- { return NULL; }
+ { return nullptr; }
virtual const symbolic_binding *dyn_cast_symbolic_binding () const
- { return NULL; }
+ { return nullptr; }
};
/* A concrete range of bits. */
@@ -299,6 +299,16 @@ struct bit_range
bool as_byte_range (byte_range *out) const;
+ bool
+ operator< (const bit_range &other) const
+ {
+ if (m_start_bit_offset < other.m_start_bit_offset)
+ return true;
+ if (m_start_bit_offset > other.m_start_bit_offset)
+ return false;
+ return (m_size_in_bits < other.m_size_in_bits);
+ }
+
bit_offset_t m_start_bit_offset;
bit_size_t m_size_in_bits;
};
@@ -482,10 +492,10 @@ public:
static int cmp_ptr_ptr (const void *, const void *);
void mark_deleted () { m_region = reinterpret_cast<const region *> (1); }
- void mark_empty () { m_region = NULL; }
+ void mark_empty () { m_region = nullptr; }
bool is_deleted () const
{ return m_region == reinterpret_cast<const region *> (1); }
- bool is_empty () const { return m_region == NULL; }
+ bool is_empty () const { return m_region == nullptr; }
private:
const region *m_region;
@@ -528,7 +538,7 @@ public:
if (slot)
return *slot;
else
- return NULL;
+ return nullptr;
}
bool put (const binding_key *k, const svalue *v)
{
diff --git a/gcc/analyzer/supergraph.cc b/gcc/analyzer/supergraph.cc
index de2c330..8592db7 100644
--- a/gcc/analyzer/supergraph.cc
+++ b/gcc/analyzer/supergraph.cc
@@ -48,7 +48,7 @@ get_ultimate_function_for_cgraph_edge (cgraph_edge *edge)
{
cgraph_node *ultimate_node = edge->callee->ultimate_alias_target ();
if (!ultimate_node)
- return NULL;
+ return nullptr;
return ultimate_node->get_fun ();
}
@@ -59,15 +59,15 @@ supergraph_call_edge (function *fun, const gimple *stmt)
{
const gcall *call = dyn_cast<const gcall *> (stmt);
if (!call)
- return NULL;
+ return nullptr;
cgraph_edge *edge
= cgraph_node::get (fun->decl)->get_edge (const_cast <gimple *> (stmt));
if (!edge)
- return NULL;
+ return nullptr;
if (!edge->callee)
- return NULL; /* e.g. for a function pointer. */
+ return nullptr; /* e.g. for a function pointer. */
if (!get_ultimate_function_for_cgraph_edge (edge))
- return NULL;
+ return nullptr;
return edge;
}
@@ -146,7 +146,8 @@ supergraph::supergraph (logger *logger)
FOR_ALL_BB_FN (bb, fun)
{
/* The initial supernode for the BB gets the phi nodes (if any). */
- supernode *node_for_stmts = add_node (fun, bb, NULL, phi_nodes (bb));
+ supernode *node_for_stmts
+ = add_node (fun, bb, nullptr, phi_nodes (bb));
m_bb_to_initial_node.put (bb, node_for_stmts);
for (gphi_iterator gpi = gsi_start_phis (bb); !gsi_end_p (gpi);
gsi_next (&gpi))
@@ -171,12 +172,12 @@ supergraph::supergraph (logger *logger)
m_stmt_to_node_t.put (stmt, node_for_stmts);
m_stmt_uids.make_uid_unique (stmt);
if (cgraph_edge *edge = supergraph_call_edge (fun, stmt))
- {
- m_cgraph_edge_to_caller_prev_node.put(edge, node_for_stmts);
- node_for_stmts = add_node (fun, bb, as_a <gcall *> (stmt),
- NULL);
- m_cgraph_edge_to_caller_next_node.put (edge, node_for_stmts);
- }
+ {
+ m_cgraph_edge_to_caller_prev_node.put(edge, node_for_stmts);
+ node_for_stmts = add_node (fun, bb, as_a <gcall *> (stmt),
+ nullptr);
+ m_cgraph_edge_to_caller_next_node.put (edge, node_for_stmts);
+ }
else
{
// maybe call is via a function pointer
@@ -187,13 +188,13 @@ supergraph::supergraph (logger *logger)
if (!edge || !edge->callee)
{
supernode *old_node_for_stmts = node_for_stmts;
- node_for_stmts = add_node (fun, bb, call, NULL);
+ node_for_stmts = add_node (fun, bb, call, nullptr);
superedge *sedge
= new callgraph_superedge (old_node_for_stmts,
node_for_stmts,
SUPEREDGE_INTRAPROCEDURAL_CALL,
- NULL);
+ nullptr);
add_edge (sedge);
}
}
@@ -984,25 +985,25 @@ superedge::to_json () const
}
/* If this is an intraprocedural superedge, return the associated
- CFG edge. Otherwise, return NULL. */
+ CFG edge. Otherwise, return nullptr. */
::edge
superedge::get_any_cfg_edge () const
{
if (const cfg_superedge *sub = dyn_cast_cfg_superedge ())
return sub->get_cfg_edge ();
- return NULL;
+ return nullptr;
}
/* If this is an interprocedural superedge, return the associated
- cgraph_edge *. Otherwise, return NULL. */
+ cgraph_edge *. Otherwise, return nullptr. */
cgraph_edge *
superedge::get_any_callgraph_edge () const
{
if (const callgraph_superedge *sub = dyn_cast_callgraph_superedge ())
return sub->m_cedge;
- return NULL;
+ return nullptr;
}
/* Build a description of this superedge (e.g. "true" for the true
diff --git a/gcc/analyzer/supergraph.h b/gcc/analyzer/supergraph.h
index 8796ab7..f64a2f4 100644
--- a/gcc/analyzer/supergraph.h
+++ b/gcc/analyzer/supergraph.h
@@ -274,7 +274,7 @@ class supernode : public dnode<supergraph_traits>
i.ptr = gimple_seq_first (*pseq);
i.seq = pseq;
- i.bb = i.ptr ? gimple_bb (i.ptr) : NULL;
+ i.bb = i.ptr ? gimple_bb (i.ptr) : nullptr;
return i;
}
@@ -287,15 +287,15 @@ class supernode : public dnode<supergraph_traits>
gimple *get_last_stmt () const
{
if (m_stmts.length () == 0)
- return NULL;
+ return nullptr;
return m_stmts[m_stmts.length () - 1];
}
gcall *get_final_call () const
{
gimple *stmt = get_last_stmt ();
- if (stmt == NULL)
- return NULL;
+ if (stmt == nullptr)
+ return nullptr;
return dyn_cast<gcall *> (stmt);
}
@@ -331,18 +331,18 @@ class superedge : public dedge<supergraph_traits>
enum edge_kind get_kind () const { return m_kind; }
- virtual cfg_superedge *dyn_cast_cfg_superedge () { return NULL; }
- virtual const cfg_superedge *dyn_cast_cfg_superedge () const { return NULL; }
- virtual const switch_cfg_superedge *dyn_cast_switch_cfg_superedge () const { return NULL; }
+ virtual cfg_superedge *dyn_cast_cfg_superedge () { return nullptr; }
+ virtual const cfg_superedge *dyn_cast_cfg_superedge () const { return nullptr; }
+ virtual const switch_cfg_superedge *dyn_cast_switch_cfg_superedge () const { return nullptr; }
virtual const eh_dispatch_cfg_superedge *dyn_cast_eh_dispatch_cfg_superedge () const { return nullptr; }
virtual const eh_dispatch_try_cfg_superedge *dyn_cast_eh_dispatch_try_cfg_superedge () const { return nullptr; }
virtual const eh_dispatch_allowed_cfg_superedge *dyn_cast_eh_dispatch_allowed_cfg_superedge () const { return nullptr; }
- virtual callgraph_superedge *dyn_cast_callgraph_superedge () { return NULL; }
- virtual const callgraph_superedge *dyn_cast_callgraph_superedge () const { return NULL; }
- virtual call_superedge *dyn_cast_call_superedge () { return NULL; }
- virtual const call_superedge *dyn_cast_call_superedge () const { return NULL; }
- virtual return_superedge *dyn_cast_return_superedge () { return NULL; }
- virtual const return_superedge *dyn_cast_return_superedge () const { return NULL; }
+ virtual callgraph_superedge *dyn_cast_callgraph_superedge () { return nullptr; }
+ virtual const callgraph_superedge *dyn_cast_callgraph_superedge () const { return nullptr; }
+ virtual call_superedge *dyn_cast_call_superedge () { return nullptr; }
+ virtual const call_superedge *dyn_cast_call_superedge () const { return nullptr; }
+ virtual return_superedge *dyn_cast_return_superedge () { return nullptr; }
+ virtual const return_superedge *dyn_cast_return_superedge () const { return nullptr; }
::edge get_any_cfg_edge () const;
cgraph_edge *get_any_callgraph_edge () const;
@@ -594,7 +594,7 @@ template <>
inline bool
is_a_helper <const switch_cfg_superedge *>::test (const superedge *sedge)
{
- return sedge->dyn_cast_switch_cfg_superedge () != NULL;
+ return sedge->dyn_cast_switch_cfg_superedge () != nullptr;
}
namespace ana {
@@ -653,7 +653,7 @@ template <>
inline bool
is_a_helper <const eh_dispatch_cfg_superedge *>::test (const superedge *sedge)
{
- return sedge->dyn_cast_eh_dispatch_cfg_superedge () != NULL;
+ return sedge->dyn_cast_eh_dispatch_cfg_superedge () != nullptr;
}
namespace ana {
@@ -703,7 +703,7 @@ template <>
inline bool
is_a_helper <const eh_dispatch_try_cfg_superedge *>::test (const superedge *sedge)
{
- return sedge->dyn_cast_eh_dispatch_try_cfg_superedge () != NULL;
+ return sedge->dyn_cast_eh_dispatch_try_cfg_superedge () != nullptr;
}
namespace ana {
@@ -753,7 +753,7 @@ template <>
inline bool
is_a_helper <const eh_dispatch_allowed_cfg_superedge *>::test (const superedge *sedge)
{
- return sedge->dyn_cast_eh_dispatch_allowed_cfg_superedge () != NULL;
+ return sedge->dyn_cast_eh_dispatch_allowed_cfg_superedge () != nullptr;
}
namespace ana {
diff --git a/gcc/analyzer/svalue.cc b/gcc/analyzer/svalue.cc
index f3f80d1..fbbd1d2 100644
--- a/gcc/analyzer/svalue.cc
+++ b/gcc/analyzer/svalue.cc
@@ -247,7 +247,7 @@ svalue::maybe_get_constant () const
}
/* If this svalue is a region_svalue, return the region it points to.
- Otherwise return NULL. */
+ Otherwise return nullptr. */
const region *
svalue::maybe_get_region () const
@@ -255,12 +255,12 @@ svalue::maybe_get_region () const
if (const region_svalue *region_sval = dyn_cast_region_svalue ())
return region_sval->get_pointee ();
else
- return NULL;
+ return nullptr;
}
/* If this svalue is a cast (i.e a unaryop NOP_EXPR or VIEW_CONVERT_EXPR),
return the underlying svalue.
- Otherwise return NULL. */
+ Otherwise return nullptr. */
const svalue *
svalue::maybe_undo_cast () const
@@ -271,7 +271,7 @@ svalue::maybe_undo_cast () const
if (op == NOP_EXPR || op == VIEW_CONVERT_EXPR)
return unaryop_sval->get_arg ();
}
- return NULL;
+ return nullptr;
}
/* If this svalue is an unmergeable decorator around another svalue, return
@@ -287,7 +287,7 @@ svalue::unwrap_any_unmergeable () const
}
/* Attempt to merge THIS with OTHER, returning the merged svalue.
- Return NULL if not mergeable. */
+ Return nullptr if not mergeable. */
const svalue *
svalue::can_merge_p (const svalue *other,
@@ -295,22 +295,22 @@ svalue::can_merge_p (const svalue *other,
model_merger *merger) const
{
if (!(get_type () && other->get_type ()))
- return NULL;
+ return nullptr;
if (!types_compatible_p (get_type (), other->get_type ()))
- return NULL;
+ return nullptr;
/* Reject attempts to merge unmergeable svalues. */
if ((get_kind () == SK_UNMERGEABLE)
|| (other->get_kind () == SK_UNMERGEABLE))
- return NULL;
+ return nullptr;
/* Reject attempts to merge poisoned svalues with other svalues
(either non-poisoned, or other kinds of poison), so that e.g.
we identify paths in which a variable is conditionally uninitialized. */
if (get_kind () == SK_POISONED
|| other->get_kind () == SK_POISONED)
- return NULL;
+ return nullptr;
/* Reject attempts to merge NULL pointers with not-NULL-pointers. */
if (POINTER_TYPE_P (get_type ()))
@@ -324,16 +324,16 @@ svalue::can_merge_p (const svalue *other,
if (zerop (cst1))
null1 = true;
if (null0 != null1)
- return NULL;
+ return nullptr;
}
/* Reject merging svalues that have non-purgable sm-state,
to avoid falsely reporting memory leaks by merging them
with something else. */
if (!merger->mergeable_svalue_p (this))
- return NULL;
+ return nullptr;
if (!merger->mergeable_svalue_p (other))
- return NULL;
+ return nullptr;
/* Widening. */
/* Merge: (new_cst, existing_cst) -> widen (existing, new). */
@@ -410,7 +410,7 @@ svalue::can_merge_p (const svalue *other,
/* Determine if this svalue is either within LIVE_SVALUES, or is implicitly
live with respect to LIVE_SVALUES and MODEL.
- LIVE_SVALUES can be NULL, in which case determine if this svalue is
+ LIVE_SVALUES can be nullptr, in which case determine if this svalue is
intrinsically live. */
bool
@@ -806,7 +806,7 @@ svalue::maybe_fold_bits_within (tree,
region_model_manager *) const
{
/* By default, don't fold. */
- return NULL;
+ return nullptr;
}
/* Base implementation of svalue::all_zeroes_p.
@@ -819,7 +819,7 @@ svalue::all_zeroes_p () const
}
/* If this svalue is a pointer, attempt to determine the base region it points
- to. Return NULL on any problems. */
+ to. Return nullptr on any problems. */
const region *
svalue::maybe_get_deref_base_region () const
@@ -830,7 +830,7 @@ svalue::maybe_get_deref_base_region () const
switch (iter->get_kind ())
{
default:
- return NULL;
+ return nullptr;
case SK_REGION:
{
@@ -852,9 +852,9 @@ svalue::maybe_get_deref_base_region () const
continue;
default:
- return NULL;
+ return nullptr;
}
- return NULL;
+ return nullptr;
}
}
}
@@ -1147,7 +1147,7 @@ constant_svalue::maybe_fold_bits_within (tree type,
}
/* Otherwise, don't fold. */
- return NULL;
+ return nullptr;
}
/* Implementation of svalue::all_zeroes_p for constant_svalue. */
@@ -1374,7 +1374,7 @@ initial_svalue::implicitly_live_p (const svalue_set *,
a popped stack frame. */
if (model->region_exists_p (m_reg))
{
- const svalue *reg_sval = model->get_store_value (m_reg, NULL);
+ const svalue *reg_sval = model->get_store_value (m_reg, nullptr);
if (reg_sval == this)
return true;
}
@@ -1384,7 +1384,7 @@ initial_svalue::implicitly_live_p (const svalue_set *,
live in the external caller. */
if (initial_value_of_param_p ())
if (const frame_region *frame_reg = m_reg->maybe_get_frame_region ())
- if (frame_reg->get_calling_frame () == NULL)
+ if (frame_reg->get_calling_frame () == nullptr)
return true;
return false;
@@ -1508,7 +1508,7 @@ unaryop_svalue::maybe_fold_bits_within (tree type,
break;
}
/* Otherwise, don't fold. */
- return NULL;
+ return nullptr;
}
/* class binop_svalue : public svalue. */
@@ -1837,7 +1837,7 @@ repeated_svalue::maybe_fold_bits_within (tree type,
}
}
- return NULL;
+ return nullptr;
}
/* class bits_within_svalue : public svalue. */
@@ -2393,7 +2393,7 @@ compound_svalue::maybe_fold_bits_within (tree type,
}
else
/* If we have any symbolic keys we can't get it as bits. */
- return NULL;
+ return nullptr;
}
return mgr->get_or_create_compound_svalue (type, result_map);
}
diff --git a/gcc/analyzer/svalue.h b/gcc/analyzer/svalue.h
index 7a27cb6..0ccb5ce 100644
--- a/gcc/analyzer/svalue.h
+++ b/gcc/analyzer/svalue.h
@@ -112,37 +112,37 @@ public:
const char *prefix = nullptr) const;
virtual const region_svalue *
- dyn_cast_region_svalue () const { return NULL; }
+ dyn_cast_region_svalue () const { return nullptr; }
virtual const constant_svalue *
- dyn_cast_constant_svalue () const { return NULL; }
+ dyn_cast_constant_svalue () const { return nullptr; }
virtual const poisoned_svalue *
- dyn_cast_poisoned_svalue () const { return NULL; }
+ dyn_cast_poisoned_svalue () const { return nullptr; }
virtual const setjmp_svalue *
- dyn_cast_setjmp_svalue () const { return NULL; }
+ dyn_cast_setjmp_svalue () const { return nullptr; }
virtual const initial_svalue *
- dyn_cast_initial_svalue () const { return NULL; }
+ dyn_cast_initial_svalue () const { return nullptr; }
virtual const unaryop_svalue *
- dyn_cast_unaryop_svalue () const { return NULL; }
+ dyn_cast_unaryop_svalue () const { return nullptr; }
virtual const binop_svalue *
- dyn_cast_binop_svalue () const { return NULL; }
+ dyn_cast_binop_svalue () const { return nullptr; }
virtual const sub_svalue *
- dyn_cast_sub_svalue () const { return NULL; }
+ dyn_cast_sub_svalue () const { return nullptr; }
virtual const repeated_svalue *
- dyn_cast_repeated_svalue () const { return NULL; }
+ dyn_cast_repeated_svalue () const { return nullptr; }
virtual const bits_within_svalue *
- dyn_cast_bits_within_svalue () const { return NULL; }
+ dyn_cast_bits_within_svalue () const { return nullptr; }
virtual const unmergeable_svalue *
- dyn_cast_unmergeable_svalue () const { return NULL; }
+ dyn_cast_unmergeable_svalue () const { return nullptr; }
virtual const widening_svalue *
- dyn_cast_widening_svalue () const { return NULL; }
+ dyn_cast_widening_svalue () const { return nullptr; }
virtual const compound_svalue *
- dyn_cast_compound_svalue () const { return NULL; }
+ dyn_cast_compound_svalue () const { return nullptr; }
virtual const conjured_svalue *
- dyn_cast_conjured_svalue () const { return NULL; }
+ dyn_cast_conjured_svalue () const { return nullptr; }
virtual const asm_output_svalue *
- dyn_cast_asm_output_svalue () const { return NULL; }
+ dyn_cast_asm_output_svalue () const { return nullptr; }
virtual const const_fn_result_svalue *
- dyn_cast_const_fn_result_svalue () const { return NULL; }
+ dyn_cast_const_fn_result_svalue () const { return nullptr; }
tree maybe_get_constant () const;
const region *maybe_get_region () const;
@@ -246,7 +246,7 @@ public:
: svalue (complexity (reg), id, type),
m_reg (reg)
{
- gcc_assert (m_reg != NULL);
+ gcc_assert (m_reg != nullptr);
}
enum svalue_kind get_kind () const final override { return SK_REGION; }
@@ -650,7 +650,7 @@ public:
initial_svalue (symbol::id_t id, tree type, const region *reg)
: svalue (complexity (reg), id, type), m_reg (reg)
{
- gcc_assert (m_reg != NULL);
+ gcc_assert (m_reg != nullptr);
}
enum svalue_kind get_kind () const final override { return SK_INITIAL; }
@@ -1547,15 +1547,15 @@ public:
&& m_idx == other.m_idx);
}
- /* Use m_stmt to mark empty/deleted, as m_type can be NULL for
+ /* Use m_stmt to mark empty/deleted, as m_type can be NULL_TREE for
legitimate instances. */
void mark_deleted () { m_stmt = reinterpret_cast<const gimple *> (1); }
- void mark_empty () { m_stmt = NULL; }
+ void mark_empty () { m_stmt = nullptr; }
bool is_deleted () const
{
return m_stmt == reinterpret_cast<const gimple *> (1);
}
- bool is_empty () const { return m_stmt == NULL; }
+ bool is_empty () const { return m_stmt == nullptr; }
tree m_type;
const gimple *m_stmt;
@@ -1568,7 +1568,7 @@ public:
: svalue (complexity (id_reg), id, type),
m_stmt (stmt), m_id_reg (id_reg), m_idx (idx)
{
- gcc_assert (m_stmt != NULL);
+ gcc_assert (m_stmt != nullptr);
}
enum svalue_kind get_kind () const final override { return SK_CONJURED; }
@@ -1668,15 +1668,15 @@ public:
return true;
}
- /* Use m_asm_string to mark empty/deleted, as m_type can be NULL for
+ /* Use m_asm_string to mark empty/deleted, as m_type can be NULL_TREE for
legitimate instances. */
void mark_deleted () { m_asm_string = reinterpret_cast<const char *> (1); }
- void mark_empty () { m_asm_string = NULL; }
+ void mark_empty () { m_asm_string = nullptr; }
bool is_deleted () const
{
return m_asm_string == reinterpret_cast<const char *> (1);
}
- bool is_empty () const { return m_asm_string == NULL; }
+ bool is_empty () const { return m_asm_string == nullptr; }
tree m_type;
const char *m_asm_string;
@@ -1813,12 +1813,12 @@ public:
/* Use m_fndecl to mark empty/deleted. */
void mark_deleted () { m_fndecl = reinterpret_cast<tree> (1); }
- void mark_empty () { m_fndecl = NULL; }
+ void mark_empty () { m_fndecl = NULL_TREE; }
bool is_deleted () const
{
return m_fndecl == reinterpret_cast<tree> (1);
}
- bool is_empty () const { return m_fndecl == NULL; }
+ bool is_empty () const { return m_fndecl == NULL_TREE; }
tree m_type;
tree m_fndecl;
diff --git a/gcc/analyzer/varargs.cc b/gcc/analyzer/varargs.cc
index 6ea0d29..4947271 100644
--- a/gcc/analyzer/varargs.cc
+++ b/gcc/analyzer/varargs.cc
@@ -205,7 +205,11 @@ public:
{
return s != m_started;
}
- std::unique_ptr<pending_diagnostic> on_leak (tree var) const final override;
+
+ std::unique_ptr<pending_diagnostic>
+ on_leak (tree var,
+ const program_state *old_state,
+ const program_state *new_state) const final override;
/* State for a va_list that is the result of a va_start or va_copy. */
state_t m_started;
@@ -294,15 +298,15 @@ get_stateful_arg (sm_context &sm_ctxt, const gcall &call, unsigned arg_idx)
if (const program_state *new_state = sm_ctxt.get_new_program_state ())
{
const region_model *new_model = new_state->m_region_model;
- const svalue *ptr_sval = new_model->get_rvalue (ap, NULL);
- const region *reg = new_model->deref_rvalue (ptr_sval, ap, NULL);
- const svalue *impl_sval = new_model->get_store_value (reg, NULL);
+ const svalue *ptr_sval = new_model->get_rvalue (ap, nullptr);
+ const region *reg = new_model->deref_rvalue (ptr_sval, ap, nullptr);
+ const svalue *impl_sval = new_model->get_store_value (reg, nullptr);
if (const svalue *cast = impl_sval->maybe_undo_cast ())
impl_sval = cast;
return impl_sval;
}
}
- return NULL;
+ return nullptr;
}
/* Abstract class for diagnostics relating to va_list_state_machine. */
@@ -335,11 +339,11 @@ public:
const final override
{
if (change.m_new_state == m_sm.m_started)
- return diagnostic_event::meaning (diagnostic_event::VERB_acquire,
- diagnostic_event::NOUN_resource);
+ return diagnostic_event::meaning (diagnostic_event::verb::acquire,
+ diagnostic_event::noun::resource);
if (change.m_new_state == m_sm.m_ended)
- return diagnostic_event::meaning (diagnostic_event::VERB_release,
- diagnostic_event::NOUN_resource);
+ return diagnostic_event::meaning (diagnostic_event::verb::release,
+ diagnostic_event::noun::resource);
return diagnostic_event::meaning ();
}
@@ -366,7 +370,7 @@ protected:
return "va_end";
}
}
- return NULL;
+ return nullptr;
}
const va_list_state_machine &m_sm;
@@ -460,10 +464,14 @@ class va_list_leak : public va_list_sm_diagnostic
{
public:
va_list_leak (const va_list_state_machine &sm,
- const svalue *ap_sval, tree ap_tree)
+ const svalue *ap_sval, tree ap_tree,
+ const program_state *final_state)
: va_list_sm_diagnostic (sm, ap_sval, ap_tree),
- m_start_event_fnname (NULL)
+ m_start_event_fnname (nullptr),
+ m_final_state ()
{
+ if (final_state)
+ m_final_state = std::make_unique<program_state> (*final_state);
}
int get_controlling_option () const final override
@@ -524,9 +532,16 @@ public:
return true;
}
+ const program_state *
+ get_final_state () const final override
+ {
+ return m_final_state.get ();
+ }
+
private:
diagnostic_event_id_t m_start_event;
const char *m_start_event_fnname;
+ std::unique_ptr<program_state> m_final_state;
};
/* Update state machine for a "va_start" call. */
@@ -562,7 +577,7 @@ va_list_state_machine::check_for_ended_va_list (sm_context &sm_ctxt,
/* Get the svalue with associated va_list_state_machine state for
ARG_IDX of CALL to va_copy, if SM_CTXT supports this,
- or NULL otherwise. */
+ or nullptr otherwise. */
static const svalue *
get_stateful_va_copy_arg (sm_context &sm_ctxt,
@@ -572,10 +587,10 @@ get_stateful_va_copy_arg (sm_context &sm_ctxt,
if (const program_state *new_state = sm_ctxt.get_new_program_state ())
{
const region_model *new_model = new_state->m_region_model;
- const svalue *arg = get_va_copy_arg (new_model, NULL, call, arg_idx);
+ const svalue *arg = get_va_copy_arg (new_model, nullptr, call, arg_idx);
return arg;
}
- return NULL;
+ return nullptr;
}
/* Update state machine for a "va_copy" call. */
@@ -633,9 +648,11 @@ va_list_state_machine::on_va_end (sm_context &sm_ctxt,
(for complaining about leaks of values in state 'started'). */
std::unique_ptr<pending_diagnostic>
-va_list_state_machine::on_leak (tree var) const
+va_list_state_machine::on_leak (tree var,
+ const program_state *,
+ const program_state *new_state) const
{
- return std::make_unique<va_list_leak> (*this, nullptr, var);
+ return std::make_unique<va_list_leak> (*this, nullptr, var, new_state);
}
} // anonymous namespace
@@ -723,7 +740,7 @@ kf_va_copy::impl_call_pre (const call_details &cd) const
in_va_list
= model->check_for_poison (in_va_list,
get_va_list_diag_arg (cd.get_arg_tree (1)),
- NULL,
+ nullptr,
cd.get_ctxt ());
const region *out_dst_reg
@@ -1003,14 +1020,14 @@ va_arg_compatible_types_p (tree lhs_type, tree arg_type, const svalue &arg_sval)
}
/* If AP_SVAL is a pointer to a var_arg_region, return that var_arg_region.
- Otherwise return NULL. */
+ Otherwise return nullptr. */
static const var_arg_region *
maybe_get_var_arg_region (const svalue *ap_sval)
{
if (const region *reg = ap_sval->maybe_get_region ())
return reg->dyn_cast_var_arg_region ();
- return NULL;
+ return nullptr;
}
/* Handler for "__builtin_va_arg". */