aboutsummaryrefslogtreecommitdiff
path: root/gcc/doc/analyzer.texi
AgeCommit message (Collapse)AuthorFilesLines
2023-03-24docs, analyzer: improvements to "Debugging the Analyzer"David Malcolm1-9/+116
gcc/ChangeLog: * doc/analyzer.texi (Debugging the Analyzer): Add notes on useful debugging options. (Special Functions for Debugging the Analyzer): Convert to a table, and rewrite in places. (Other Debugging Techniques): Add notes on how to compare two different exploded graphs. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-01-16Update copyright years.Jakub Jelinek1-1/+1
2022-12-06analyzer: update internal docsDavid Malcolm1-10/+0
gcc/ChangeLog: * doc/analyzer.texi: Drop out-of-date ideas for other checkers. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-15c, analyzer: support named constants in analyzer [PR106302]David Malcolm1-0/+17
The analyzer's file-descriptor state machine tracks the access mode of opened files, so that it can emit -Wanalyzer-fd-access-mode-mismatch. To do this, its symbolic execution needs to "know" the values of the constants "O_RDONLY", "O_WRONLY", and "O_ACCMODE". Currently analyzer/sm-fd.cc simply uses these values directly from the build-time header files, but these are the values on the host, not those from the target, which could be different (PR analyzer/106302). In an earlier discussion of this issue: https://gcc.gnu.org/pipermail/gcc/2022-June/238954.html we talked about adding a target hook for this. However, I've also been experimenting with extending the fd state machine to track sockets (PR analyzer/106140). For this, it's useful to "know" the values of the constants "SOCK_STREAM" and "SOCK_DGRAM". Unfortunately, these seem to have many arbitrary differences from target to target. For example: Linux/glibc general has SOCK_STREAM == 1, SOCK_DGRAM == 2, as does AIX, but annoyingly, e.g. Linux on MIPS has them the other way around. It seems to me that as the analyzer grows more ambitious modeling of the behavior of APIs (perhaps via plugins) it's more likely that the analyzer will need to know the values of named constants, which might not even exist on the host. For example, at LPC it was suggested to me that -fanalyzer could check rules about memory management inside the Linux kernel (probably via a plugin), but doing so involves a bunch of GFP_* flags (see PR 107472). So rather than trying to capture all this knowledge in a target hook, this patch attempts to get at named constant values from the user's source code. The patch adds an interface for frontends to call into the analyzer as the translation unit finishes. The analyzer can then call back into the frontend to ask about the values of the named constants it cares about whilst the frontend's data structures are still around. The patch implements this for the C frontend, which looks up the names by looking for named CONST_DECLs (which handles enum values). Failing that, it attempts to look up the values of macros but only the simplest cases are supported (a non-traditional macro with a single CPP_NUMBER token). It does this by building a buffer containing the macro definition and rerunning a lexer on it. The analyzer gracefully handles the cases where named values aren't found (such as anything more complicated than described above). The patch ports the analyzer to use this mechanism for "O_RDONLY", "O_WRONLY", and "O_ACCMODE". I have successfully tested my socket patch to also use this for "SOCK_STREAM" and "SOCK_DGRAM", so the technique seems to work. gcc/ChangeLog: PR analyzer/106302 * Makefile.in (ANALYZER_OBJS): Add analyzer/analyzer-language.o. (GTFILES): Add analyzer/analyzer-language.cc. * doc/analyzer.texi: Document __analyzer_dump_named_constant. gcc/analyzer/ChangeLog: PR analyzer/106302 * analyzer-language.cc: New file. * analyzer-language.h: New file. * analyzer.h (get_stashed_constant_by_name): New decl. (log_stashed_constants): New decl. * engine.cc (impl_run_checkers): Call log_stashed_constants. * region-model-impl-calls.cc (region_model::impl_call_analyzer_dump_named_constant): New. * region-model.cc (region_model::on_stmt_pre): Handle __analyzer_dump_named_constant. * region-model.h (region_model::impl_call_analyzer_dump_named_constant): New decl. * sm-fd.cc (fd_state_machine::m_O_ACCMODE): New. (fd_state_machine::m_O_RDONLY): New. (fd_state_machine::m_O_WRONLY): New. (fd_state_machine::fd_state_machine): Initialize the new fields. (fd_state_machine::get_access_mode_from_flag): Use the new fields, rather than using the host values. gcc/c/ChangeLog: PR analyzer/106302 * c-parser.cc: Include "analyzer/analyzer-language.h" and "toplev.h". (class ana::c_translation_unit): New. (c_parser_translation_unit): Call ana::on_finish_translation_unit. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/analyzer-decls.h (__analyzer_dump_named_constant): New decl. * gcc.dg/analyzer/fd-4.c (void): Likewise. (O_ACCMODE): Define. * gcc.dg/analyzer/fd-access-mode-enum.c: New test, based on . * gcc.dg/analyzer/fd-5.c: ...this. Rename to... * gcc.dg/analyzer/fd-access-mode-macros.c: ...this. (O_ACCMODE): Define. * gcc.dg/analyzer/fd-access-mode-target-headers.c: New test, also based on fd-5.c. (test_sm_fd_constants): New. * gcc.dg/analyzer/fd-dup-1.c (O_ACCMODE): Define. * gcc.dg/analyzer/named-constants-via-enum.c: New test. * gcc.dg/analyzer/named-constants-via-enum-and-macro.c: New test. * gcc.dg/analyzer/named-constants-via-macros-2.c: New test. * gcc.dg/analyzer/named-constants-via-macros.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-14Revert "sphinx: remove texinfo files"Martin Liska1-0/+569
This reverts commit 54ca4eef58661a7d7a511e2bbbe309bde1732abf.
2022-11-09sphinx: remove texinfo filesMartin Liska1-569/+0
gcc/d/ChangeLog: * gdc.texi: Removed. gcc/ChangeLog: * doc/analyzer.texi: Removed. * doc/avr-mmcu.texi: Removed. * doc/bugreport.texi: Removed. * doc/cfg.texi: Removed. * doc/collect2.texi: Removed. * doc/compat.texi: Removed. * doc/configfiles.texi: Removed. * doc/configterms.texi: Removed. * doc/contrib.texi: Removed. * doc/contribute.texi: Removed. * doc/cpp.texi: Removed. * doc/cppdiropts.texi: Removed. * doc/cppenv.texi: Removed. * doc/cppinternals.texi: Removed. * doc/cppopts.texi: Removed. * doc/cppwarnopts.texi: Removed. * doc/extend.texi: Removed. * doc/fragments.texi: Removed. * doc/frontends.texi: Removed. * doc/gcc.texi: Removed. * doc/gccint.texi: Removed. * doc/gcov-dump.texi: Removed. * doc/gcov-tool.texi: Removed. * doc/gcov.texi: Removed. * doc/generic.texi: Removed. * doc/gimple.texi: Removed. * doc/gnu.texi: Removed. * doc/gty.texi: Removed. * doc/headerdirs.texi: Removed. * doc/hostconfig.texi: Removed. * doc/implement-c.texi: Removed. * doc/implement-cxx.texi: Removed. * doc/include/fdl.texi: Removed. * doc/include/funding.texi: Removed. * doc/include/gcc-common.texi: Removed. * doc/include/gpl_v3.texi: Removed. * doc/install.texi: Removed. * doc/interface.texi: Removed. * doc/invoke.texi: Removed. * doc/languages.texi: Removed. * doc/libgcc.texi: Removed. * doc/loop.texi: Removed. * doc/lto-dump.texi: Removed. * doc/lto.texi: Removed. * doc/makefile.texi: Removed. * doc/match-and-simplify.texi: Removed. * doc/md.texi: Removed. * doc/objc.texi: Removed. * doc/optinfo.texi: Removed. * doc/options.texi: Removed. * doc/passes.texi: Removed. * doc/plugins.texi: Removed. * doc/poly-int.texi: Removed. * doc/portability.texi: Removed. * doc/rtl.texi: Removed. * doc/service.texi: Removed. * doc/sourcebuild.texi: Removed. * doc/standards.texi: Removed. * doc/tm.texi: Removed. * doc/tree-ssa.texi: Removed. * doc/trouble.texi: Removed. * doc/ux.texi: Removed. * doc/tm.texi.in: Removed. gcc/fortran/ChangeLog: * gfc-internals.texi: Removed. * gfortran.texi: Removed. * intrinsic.texi: Removed. * invoke.texi: Removed. gcc/go/ChangeLog: * gccgo.texi: Removed. libgomp/ChangeLog: * libgomp.texi: Removed. libiberty/ChangeLog: * at-file.texi: Removed. * copying-lib.texi: Removed. * functions.texi: Removed. * libiberty.texi: Removed. * obstacks.texi: Removed. libitm/ChangeLog: * libitm.texi: Removed. libquadmath/ChangeLog: * libquadmath.texi: Removed.
2022-10-05analyzer: fix ICEs seen with call summaries on PR 107060David Malcolm1-0/+4
This doesn't fix the various false positives seen with -fanalyzer-call-summaries on PR 107060, but stops it crashing at -O2. gcc/analyzer/ChangeLog: PR analyzer/107060 * call-summary.cc (call_summary_replay::convert_svalue_from_summary_1): Handle NULL results from convert_svalue_from_summary in SK_UNARY_OP and SK_BIN_OP. * engine.cc (impl_region_model_context::on_unknown_change): Bail out on svalues that can't have associated state. * region-model-impl-calls.cc (region_model::impl_call_analyzer_get_unknown_ptr): New. * region-model.cc (region_model::on_stmt_pre): Handle "__analyzer_get_unknown_ptr". * region-model.h (region_model::impl_call_analyzer_get_unknown_ptr): New decl. * store.cc (store::replay_call_summary_cluster): Avoid trying to create binding clusters for base regions that shouldn't have them. gcc/ChangeLog: PR analyzer/107060 * doc/analyzer.texi (__analyzer_get_unknown_ptr): Document. gcc/testsuite/ChangeLog: PR analyzer/107060 * gcc.dg/analyzer/analyzer-decls.h (__analyzer_get_unknown_ptr): New decl. * gcc.dg/analyzer/call-summaries-2.c (test_summarized_writes_param_to_ptr_unknown): New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-01-07analyzer: implement __analyzer_dump_escapedDavid Malcolm1-0/+8
PR analyzer/103546 seems to involve an issue in how the analyzer tracks which decls have escaped, so this patch adds a way to directly test this from DejaGnu. gcc/analyzer/ChangeLog: * region-model-impl-calls.cc (cmp_decls): New. (cmp_decls_ptr_ptr): New. (region_model::impl_call_analyzer_dump_escaped): New. * region-model.cc (region_model::on_stmt_pre): Handle __analyzer_dump_escaped. * region-model.h (region_model::impl_call_analyzer_dump_escaped): New decl. * store.h (binding_cluster::get_base_region): New accessor. gcc/ChangeLog: * doc/analyzer.texi (Special Functions for Debugging the Analyzer): Document __analyzer_dump_escaped. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/analyzer-decls.h (__analyzer_dump_escaped): New decl. * gcc.dg/analyzer/escaping-1.c: New test.
2022-01-07analyzer: add region::is_named_decl_pDavid Malcolm1-0/+10
This patch adds a debug function that I've found handy when debugging a problem with handling the decl "yy_buffer_stack" in PR analyzer/103546. gcc/analyzer/ChangeLog: * region.cc (region::is_named_decl_p): New. * region.h (region::is_named_decl_p): New decl. gcc/ChangeLog: * doc/analyzer.texi (Other Debugging Techniques): Document region::is_named_decl_p. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-01-03Update copyright years.Jakub Jelinek1-1/+1
2021-07-16analyzer: add __analyzer_dump_stateDavid Malcolm1-0/+9
gcc/analyzer/ChangeLog: * engine.cc (exploded_node::on_stmt_pre): Handle __analyzer_dump_state. * program-state.cc (extrinsic_state::get_sm_idx_by_name): New. (program_state::impl_call_analyzer_dump_state): New. * program-state.h (extrinsic_state::get_sm_idx_by_name): New decl. (program_state::impl_call_analyzer_dump_state): New decl. * region-model-impl-calls.cc (call_details::get_arg_string_literal): New. * region-model.h (call_details::get_arg_string_literal): New decl. gcc/ChangeLog: * doc/analyzer.texi: Add __analyzer_dump_state. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/analyzer-decls.h (__analyzer_dump_state): New. * gcc.dg/analyzer/dump-state.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2021-06-15analyzer: track dynamic extents of regionsDavid Malcolm1-0/+7
This patch extends region_model to add tracking of the sizes of dynamically-allocated regions, both on the heap (via malloc etc) and stack (via alloca). It adds enough purging of this state to avoid blowing up any existing analyzer test cases. The state can be queried via a new "__analyzer_dump_capacity" for use in DejaGnu tests but other than that doesn't do anything - I have various followup experiments that make use of this. gcc/analyzer/ChangeLog: * engine.cc (exploded_node::on_stmt): Handle __analyzer_dump_capacity. (exploded_node::on_stmt): Drop m_sm_changes from on_stmt_flags. (state_change_requires_new_enode_p): New function... (exploded_graph::process_node): Call it, rather than querying flags.m_sm_changes, so that dynamic-extent differences can also trigger the splitting of nodes. * exploded-graph.h (struct on_stmt_flags): Drop field m_sm_changes. * program-state.cc (program_state::detect_leaks): Purge dead heap-allocated regions from dynamic extents. (selftest::test_program_state_1): Fix type of "size_in_bytes". (selftest::test_program_state_merging): Likewise. * region-model-impl-calls.cc (region_model::impl_call_analyzer_dump_capacity): New. (region_model::impl_call_free): Remove dynamic extents from the freed region. * region-model-reachability.h (reachable_regions::begin_mutable_base_regs): New. (reachable_regions::end_mutable_base_regs): New. * region-model.cc: Include "tree-object-size.h". (region_model::region_model): Support new field m_dynamic_extents. (region_model::operator=): Likewise. (region_model::operator==): Likewise. (region_model::dump_to_pp): Dump sizes of dynamic regions. (region_model::handle_unrecognized_call): Purge dynamic extents from any regions that have escaped mutably:. (region_model::get_capacity): New function. (region_model::add_constraint): Unset dynamic extents when a heap-allocated region's address is NULL. (region_model::unbind_region_and_descendents): Purge dynamic extents of unbound regions. (region_model::can_merge_with_p): Call m_dynamic_extents.can_merge_with_p. (region_model::create_region_for_heap_alloc): Assert that size_in_bytes's type is compatible with size_type_node. Update for renaming of record_dynamic_extents to set_dynamic_extents. (region_model::create_region_for_alloca): Likewise. (region_model::record_dynamic_extents): Rename to... (region_model::set_dynamic_extents): ...this. Assert that size_in_bytes's type is compatible with size_type_node. Add it to the m_dynamic_extents map. (region_model::get_dynamic_extents): New. (region_model::unset_dynamic_extents): New. (selftest::test_state_merging): Fix type of "size". (selftest::test_malloc_constraints): Likewise. (selftest::test_malloc): Verify dynamic extents. (selftest::test_alloca): Likewise. * region-model.h (region_to_value_map::is_empty): New. (region_model::dynamic_extents_t): New typedef. (region_model::impl_call_analyzer_dump_capacity): New decl. (region_model::get_dynamic_extents): New function. (region_model::get_dynamic_extents): New decl. (region_model::set_dynamic_extents): New decl. (region_model::unset_dynamic_extents): New decl. (region_model::get_capacity): New decl. (region_model::record_dynamic_extents): Rename to set_dynamic_extents. (region_model::m_dynamic_extents): New field. gcc/ChangeLog: * doc/analyzer.texi (Special Functions for Debugging the Analyzer): Add __analyzer_dump_capacity. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/analyzer-decls.h (__analyzer_dump_capacity): New decl. * gcc.dg/analyzer/capacity-1.c: New test. * gcc.dg/analyzer/capacity-2.c: New test. * gcc.dg/analyzer/capacity-3.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2021-03-28doc: Update link to "Memory Model" paperGerald Pfeifer1-1/+1
gcc/ChangeLog: * doc/analyzer.texi (Analyzer Internals): Update link to "A Memory Model for Static Analysis of C Programs".
2021-03-11analyzer: new implementation of shortest feasible path [PR96374]David Malcolm1-11/+45
The analyzer builds an exploded graph of (point,state) pairs and when it finds a problem, records a diagnostic at the relevant exploded node. Once it has finished exploring the graph, the analyzer needs to generate the shortest feasible path through the graph to each diagnostic's node. This is used: - for rejecting diagnostics that are infeasible (due to impossible sets of constraints), - for use in determining which diagnostic to use in each deduplication set (the one with the shortest path), and - for building checker_paths for the "winning" diagnostics, giving a list of events Prior to this patch the analyzer simply found the shortest path to the node, and then checked it for feasibility, which could lead to falsely rejecting diagnostics: "the shortest path, if feasible" is not the same as "the shortest feasible path" (PR analyzer/96374). An example is PR analyzer/93355, where this issue causes the analyzer to fail to emit a leak warning for a missing fclose on an error-handling path in intl/localealias.c. This patch implements a new algorithm for finding the shortest feasible path to an exploded node: instead of simply finding the shortest path, the new algorithm uses a worklist to iteratively build a tree of path prefixes, which are feasible paths by construction, until a path to the target node is found. The worklist is prioritized, so that the first feasible path discovered is the shortest possible feasible path. The algorithm continues trying paths until the target node is reached or a limit is exceeded, in which case the diagnostic is treated as being infeasible (which could still be a false negative, but is much less likely to happen than before). Iteratively building a tree of paths allows for work to be reused, and the tree can be dumped in .dot form (via a new -fdump-analyzer-feasibility option), making it much easier to debug compared to other approaches I tried. Doing so fixes the missing leak warning for PR analyzer/93355 and various other test cases. Testing: - I manually verified that the behavior is determistic using 50 builds of pr93355-localealias.c. All dumps were identical. - I manually verified that it still builds with --disable-analyzer. - Lightly tested with valgrind; no additional issues. - Lightly performance tested, showing a slight speed regression to the analyzer relative to before the patch, but correctness for this issue is more important than the slight performance hit for the analyzer. gcc/ChangeLog: PR analyzer/96374 * Makefile.in (ANALYZER_OBJS): Add analyzer/feasible-graph.o and analyzer/trimmed-graph.o. * doc/analyzer.texi (Analyzer Paths): Rewrite description of feasibility checking to reflect new implementation. * doc/invoke.texi (-fdump-analyzer-feasibility): Document new option. * shortest-paths.h (shortest_paths::get_shortest_distance): New. gcc/analyzer/ChangeLog: PR analyzer/96374 * analyzer.opt (-param=analyzer-max-infeasible-edges=): New param. (fdump-analyzer-feasibility): New flag. * diagnostic-manager.cc: Include "analyzer/trimmed-graph.h" and "analyzer/feasible-graph.h". (epath_finder::epath_finder): Convert m_sep to a pointer and only create it if !flag_analyzer_feasibility. (epath_finder::~epath_finder): New. (epath_finder::m_sep): Convert to a pointer. (epath_finder::get_best_epath): Add param "diag_idx" and use it when logging. Rather than finding the shortest path and then checking feasibility, instead use explore_feasible_paths unless !flag_analyzer_feasibility, in which case simply use the shortest path, and note if it is infeasible. Update for m_sep becoming a pointer. (class feasible_worklist): New. (epath_finder::explore_feasible_paths): New. (epath_finder::process_worklist_item): New. (class dump_eg_with_shortest_path): New. (epath_finder::dump_trimmed_graph): New. (epath_finder::dump_feasible_graph): New. (saved_diagnostic::saved_diagnostic): Add "idx" param, using it on new field m_idx. (saved_diagnostic::to_json): Dump m_idx. (saved_diagnostic::calc_best_epath): Pass m_idx to get_best_epath. Remove assertion that m_problem was set when m_best_epath is NULL. (diagnostic_manager::add_diagnostic): Pass an index when created saved_diagnostic instances. * diagnostic-manager.h (saved_diagnostic::saved_diagnostic): Add "idx" param. (saved_diagnostic::get_index): New accessor. (saved_diagnostic::m_idx): New field. * engine.cc (exploded_node::dump_dot): Call args.dump_extra_info. Move code to... (exploded_node::dump_processed_stmts): ...this new function and... (exploded_node::dump_saved_diagnostics): ...this new function. Add index of each diagnostic. (exploded_edge::dump_dot): Move bulk of code to... (exploded_edge::dump_dot_label): ...this new function. * exploded-graph.h (eg_traits::dump_args_t::dump_extra_info): New vfunc. (exploded_node::dump_processed_stmts): New decl. (exploded_node::dump_saved_diagnostics): New decl. (exploded_edge::dump_dot_label): New decl. * feasible-graph.cc: New file. * feasible-graph.h: New file. * trimmed-graph.cc: New file. * trimmed-graph.h: New file. gcc/testsuite/ChangeLog: PR analyzer/96374 * gcc.dg/analyzer/dot-output.c: Add -fdump-analyzer-feasibility to options. * gcc.dg/analyzer/feasibility-1.c (test_6): Remove xfail. (test_7): New. * gcc.dg/analyzer/pr93355-localealias-feasibility-2.c: Remove xfail. * gcc.dg/analyzer/pr93355-localealias-feasibility-3.c: Remove xfails. * gcc.dg/analyzer/pr93355-localealias-feasibility.c: Remove -fno-analyzer-feasibility from options. * gcc.dg/analyzer/pr93355-localealias.c: Likewise. * gcc.dg/analyzer/unknown-fns-4.c: Remove xfail.
2021-01-04Update copyright years.Jakub Jelinek1-1/+1
2020-12-27doc: New source for "Memory Model for Static Analysis" paperGerald Pfeifer1-1/+1
gcc: 2020-12-27 Gerald Pfeifer <gerald@pfeifer.com> * doc/analyzer.texi (Analyzer Internals): Find a new source for the "A Memory Model for Static Analysis of C Programs" paper.
2020-09-23analyzer: add -fno-analyzer-feasibilityDavid Malcolm1-1/+2
This patch provides a new option "-fno-analyzer-feasibility" as a way to disable feasibility-checking of the constraints along the control flow paths for -fanalyzer diagnostics. I'm adding this in the hope of making it easier to debug issues involving the feasibility-checking logic. The patch adds a new rejected_constraint object which is captured if exploded_path::feasible_p fails, and adds logic that uses this to emit an additional custom_event within the checker_path for the diagnostic, showing where in the control flow path the diagnostic would have been rejected, and giving details of why. gcc/analyzer/ChangeLog: * analyzer.h (struct rejected_constraint): New decl. * analyzer.opt (fanalyzer-feasibility): New option. * diagnostic-manager.cc (path_builder::path_builder): Add "problem" param and use it to initialize new field. (path_builder::get_feasibility_problem): New accessor. (path_builder::m_feasibility_problem): New field. (dedupe_winners::add): Remove inversion of logic in "if" clause, swapping if/else suites. In the !feasible_p suite, inspect flag_analyzer_feasibility and add code to handle when this is off, accepting the infeasible path, but recording the feasibility_problem. (diagnostic_manager::emit_saved_diagnostic): Pass the feasibility_problem to the path_builder. (diagnostic_manager::add_events_for_eedge): If we have a feasibility_problem at this edge, use it to add a custom event. * engine.cc (exploded_path::feasible_p): Pass a rejected_constraint ** to model.maybe_update_for_edge and transfer ownership of any created instance to any feasibility_problem. (feasibility_problem::dump_to_pp): New. * exploded-graph.h (feasibility_problem::feasibility_problem): Drop "model" param; add rejected_constraint * param. (feasibility_problem::~feasibility_problem): New. (feasibility_problem::dump_to_pp): New decl. (feasibility_problem::m_model): Drop field. (feasibility_problem::m_rc): New field. * program-point.cc (function_point::get_location): Handle PK_BEFORE_SUPERNODE and PK_AFTER_SUPERNODE. * program-state.cc (program_state::on_edge): Pass NULL to new param of region_model::maybe_update_for_edge. * region-model.cc (region_model::add_constraint): New overload adding a rejected_constraint ** param. (region_model::maybe_update_for_edge): Add rejected_constraint ** param and pass it to the various apply_constraints_for_ calls. (region_model::apply_constraints_for_gcond): Add rejected_constraint ** param and pass it to add_constraint calls. (region_model::apply_constraints_for_gswitch): Likewise. (region_model::apply_constraints_for_exception): Likewise. (rejected_constraint::dump_to_pp): New. * region-model.h (region_model::maybe_update_for_edge): Add rejected_constraint ** param. (region_model::add_constraint): New overload adding a rejected_constraint ** param. (region_model::apply_constraints_for_gcond): Add rejected_constraint ** param. (region_model::apply_constraints_for_gswitch): Likewise. (region_model::apply_constraints_for_exception): Likewise. (struct rejected_constraint): New. gcc/ChangeLog: * doc/analyzer.texi (Analyzer Paths): Add note about -fno-analyzer-feasibility. * doc/invoke.texi (Static Analyzer Options): Add -fno-analyzer-feasibility. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/feasibility-2.c: New test.
2020-09-22analyzer: add -fdump-analyzer-jsonDavid Malcolm1-0/+3
I've found this useful for debugging state explosions in the analyzer. gcc/analyzer/ChangeLog: * analysis-plan.cc: Include "json.h". * analyzer.opt (fdump-analyzer-json): New. * call-string.cc: Include "json.h". (call_string::to_json): New. * call-string.h (call_string::to_json): New decl. * checker-path.cc: Include "json.h". * constraint-manager.cc: Include "json.h". (equiv_class::to_json): New. (constraint::to_json): New. (constraint_manager::to_json): New. * constraint-manager.h (equiv_class::to_json): New decl. (constraint::to_json): New decl. (constraint_manager::to_json): New decl. * diagnostic-manager.cc: Include "json.h". (saved_diagnostic::to_json): New. (diagnostic_manager::to_json): New. * diagnostic-manager.h (saved_diagnostic::to_json): New decl. (diagnostic_manager::to_json): New decl. * engine.cc: Include "json.h", <zlib.h>. (exploded_node::status_to_str): New. (exploded_node::to_json): New. (exploded_edge::to_json): New. (exploded_graph::to_json): New. (dump_analyzer_json): New. (impl_run_checkers): Call it. * exploded-graph.h (exploded_node::status_to_str): New decl. (exploded_node::to_json): New. (exploded_edge::to_json): New. (exploded_graph::to_json): New. * pending-diagnostic.cc: Include "json.h". * program-point.cc: Include "json.h". (program_point::to_json): New. * program-point.h (program_point::to_json): New decl. * program-state.cc: Include "json.h". (extrinsic_state::to_json): New. (sm_state_map::to_json): New. (program_state::to_json): New. * program-state.h (extrinsic_state::to_json): New decl. (sm_state_map::to_json): New decl. (program_state::to_json): New decl. * region-model-impl-calls.cc: Include "json.h". * region-model-manager.cc: Include "json.h". * region-model-reachability.cc: Include "json.h". * region-model.cc: Include "json.h". * region-model.h (svalue::to_json): New decl. (region::to_json): New decl. * region.cc: Include "json.h". (region::to_json: New. * sm-file.cc: Include "json.h". * sm-malloc.cc: Include "json.h". * sm-pattern-test.cc: Include "json.h". * sm-sensitive.cc: Include "json.h". * sm-signal.cc: Include "json.h". (signal_delivery_edge_info_t::to_json): New. * sm-taint.cc: Include "json.h". * sm.cc: Include "diagnostic.h", "tree-diagnostic.h", and "json.h". (state_machine::state::to_json): New. (state_machine::to_json): New. * sm.h (state_machine::state::to_json): New. (state_machine::to_json): New. * state-purge.cc: Include "json.h". * store.cc: Include "json.h". (binding_key::get_desc): New. (binding_map::to_json): New. (binding_cluster::to_json): New. (store::to_json): New. * store.h (binding_key::get_desc): New decl. (binding_map::to_json): New decl. (binding_cluster::to_json): New decl. (store::to_json): New decl. * supergraph.cc: Include "json.h". (supergraph::to_json): New. (supernode::to_json): New. (superedge::to_json): New. * supergraph.h (supergraph::to_json): New decl. (supernode::to_json): New decl. (superedge::to_json): New decl. * svalue.cc: Include "json.h". (svalue::to_json): New. gcc/ChangeLog: * doc/analyzer.texi (Other Debugging Techniques): Mention -fdump-analyzer-json. * doc/invoke.texi (Static Analyzer Options): Add -fdump-analyzer-json.
2020-08-14analyzer: document how to get gimple dump from an ICEDavid Malcolm1-0/+5
gcc/ChangeLog: * doc/analyzer.texi (Overview): Add tip about how to get a gimple dump if the analyzer ICEs.
2020-08-13analyzer: rewrite of region and value-handlingDavid Malcolm1-75/+35
This large patch reimplements how the analyzer tracks regions and values. Elimination of region_id and svalue_id ************************************** The patch eliminates region_id and svalue_id in favor of simply using pointers. I'd hoped that the ID classes would make it easier to compare states, avoiding having to compare long hexadecimal addresses in favor of small integers. Unfortunately it added lots of complexity, with the need to remap IDs when comparing or purging states, and the need to "canonicalize" when comparing states. Various "state explosion" bugs in the old implementation were due to failures in canonicalization, where two states that ought to be equal were non-equal due to differences in ID ordering. I spent a lot of time trying to fix canonicalization bugs, and there always seemed to be one more bug. By eliminating IDs in this new implementation, lots of tricky canonicalization goes away and no ID remapping should be needed; almost all of the old validation code becomes redundant. There's still some canonicalization in the new implementation, mostly in constraint_manager, but much less than before. Ownership of regions and svalues ******************************** In the old implementation, each region_model had its own copies of regions and svalues, so there was heap bloat and churn as lots of little objects were cloned when copying program_state instances. In the new implementation the regions and svalues are immutable and are shared thoughout the analysis, rather than being per region_model. They are owned by a manager class, and are effectively singletons. Region and svalue instances can now be compared by pointer rather than by comparing their fields (the manager class takes care of uniqueness). This is a huge simplification, and (I hope) will avoid lots of heap churn as states are copied; all mutable state from regions and svalues is now stored in a "store" class in the region_model. Changes to the meaning of a "region" ************************************ Region subclasses no longer represent internal structure, but instead represent how the regions are reached. So e.g. a global "struct coord c;" is now a decl_region, rather than a struct_region. In the old implementation, the values for each region were stored in the region instances, but in the new implementation the regions are immutable. Memory is now modeled in a new "store" class: a mapping from keys to svalues, where the keys are both concrete bit-offsets from the start of a "base region", and "symbolic" keys (thus hopefully making unions, casts, aliasing etc easier to deal with). So e.g. for assignments to the fields of a struct, it records the mapping from bit-offsets of e.g. field to the values; if that memory is cast to another type and written to, the appropriate clobbering of the bound values can happen. The concept of "what the current stack is" moves from the regions to being a field within the region_model ("m_current_frame"). Bugs fixed by this patch ************************ PR analyzer/93032 (missing leak diagnostic for zlib/contrib/minizip/mztools.c) PR analyzer/93938 (ICE in analyzer) PR analyzer/94011 (ICE in analyzer) PR analyzer/94099 (ICE in analyzer) PR analyzer/94399 (leak false positive with __attribute__((cleanup()))) PR analyzer/94458 (leak false positive) PR analyzer/94503 (ICE on C++ return-value-optimization) PR analyzer/94640 (leak false positive) PR analyzer/94688 (ICE in analyzer) PR analyzer/94689 ("arrays of functions are not meaningful" error) PR analyzer/94839 (leak false positive) PR analyzer/95026 (leak false positive) PR analyzer/95042 (ICE merging const and non-const C++ object instances) PR analyzer/95240 (leak false positive) gcc/ChangeLog: * Makefile.in (ANALYZER_OBJS): Add analyzer/region.o, analyzer/region-model-impl-calls.o, analyzer/region-model-manager.o, analyzer/region-model-reachability.o, analyzer/store.o, and analyzer/svalue.o. * doc/analyzer.texi: Update for changes to analyzer implementation. * tristate.h (tristate::get_value): New accessor. gcc/analyzer/ChangeLog: * analyzer-logging.cc: Ignore "-Wformat-diag". (logger::enter_scope): Use inc_indent in both overloads. (logger::exit_scope): Use dec_indent. * analyzer-logging.h (logger::inc_indent): New. (logger::dec_indent): New. * analyzer-selftests.cc (run_analyzer_selftests): Call analyzer_store_cc_tests. * analyzer-selftests.h (analyzer_store_cc_tests): New decl. * analyzer.cc (get_stmt_location): New function. * analyzer.h (class initial_svalue): New forward decl. (class unaryop_svalue): New forward decl. (class binop_svalue): New forward decl. (class sub_svalue): New forward decl. (class unmergeable_svalue): New forward decl. (class placeholder_svalue): New forward decl. (class widening_svalue): New forward decl. (class compound_svalue): New forward decl. (class conjured_svalue): New forward decl. (svalue_set): New typedef. (class map_region): Delete. (class array_region): Delete. (class frame_region): New forward decl. (class function_region): New forward decl. (class label_region): New forward decl. (class decl_region): New forward decl. (class element_region): New forward decl. (class offset_region): New forward decl. (class cast_region): New forward decl. (class field_region): New forward decl. (class string_region): New forward decl. (class region_model_manager): New forward decl. (class store_manager): New forward decl. (class store): New forward decl. (class call_details): New forward decl. (struct svalue_id_merger_mapping): Delete. (struct canonicalization): Delete. (class function_point): New forward decl. (class engine): New forward decl. (dump_tree): New function decl. (print_quoted_type): New function decl. (readability_comparator): New function decl. (tree_cmp): New function decl. (class path_var): Move here from region-model.h (bit_offset_t, bit_size_t, byte_size_t): New typedefs. (class region_offset): New class. (get_stmt_location): New decl. (struct member_function_hash_traits): New struct. (class consolidation_map): New class. Ignore "-Wformat-diag". * analyzer.opt (-param=analyzer-max-svalue-depth=): New param. (-param=analyzer-max-enodes-for-full-dump=): New param. * call-string.cc: Ignore -Wformat-diag. * checker-path.cc: Move includes of "analyzer/call-string.h" and "analyzer/program-point.h" to before "analyzer/region-model.h", and also include "analyzer/store.h" before it. (state_change_event::state_change_event): Replace "tree var" param with "const svalue *sval". Convert "origin" param from tree to "const svalue *". (state_change_event::get_desc): Call get_representative_tree to convert the var and origin from const svalue * to tree. Use svalue::get_desc rather than %qE when describing state changes. (checker_path::add_final_event): Use get_stmt_location. * checker-path.h (state_change_event::state_change_event): Port from tree to const svalue *. (state_change_event::get_lvalue): Delete. (state_change_event::get_dest_function): New. (state_change_event::m_var): Replace with... (state_change_event::m_sval): ...this. (state_change_event::m_origin): Convert from tree to const svalue *. * constraint-manager.cc: Include "analyzer/call-string.h", "analyzer/program-point.h", and "analyzer/store.h" before "analyzer/region-model.h". (struct bound, struct range): Move to constraint-manager.h. (compare_constants): New function. (range::dump): Rename to... (range::dump_to_pp): ...this. Support NULL constants. (range::dump): Reintroduce for dumping to stderr. (range::constrained_to_single_element): Return result, rather than writing to *OUT. (range::eval_condition): New. (range::below_lower_bound): New. (range::above_upper_bound): New. (equiv_class::equiv_class): Port from svalue_id to const svalue *. (equiv_class::print): Likewise. (equiv_class::hash): Likewise. (equiv_class::operator==): Port from svalue_id to const svalue *. (equiv_class::add): Port from svalue_id to const svalue *. Drop "cm" param. (equiv_class::del): Port from svalue_id to const svalue *. (equiv_class::get_representative): Likewise. (equiv_class::remap_svalue_ids): Delete. (svalue_id_cmp_by_id): Rename to... (svalue_cmp_by_ptr): ...this, porting from svalue_id to const svalue *. (equiv_class::canonicalize): Update qsort comparator. (constraint::implied_by): New. (constraint_manager::constraint_manager): Copy m_mgr in copy ctor. (constraint_manager::dump_to_pp): Add "multiline" param (constraint_manager::dump): Pass "true" for "multiline". (constraint_manager::add_constraint): Port from svalue_id to const svalue *. Split out second part into... (constraint_manager::add_unknown_constraint): ...this new function. Remove self-constraints when merging equivalence classes. (constraint_manager::add_constraint_internal): Remove constraints that would be implied by the new constraint. Port from svalue_id to const svalue *. (constraint_manager::get_equiv_class_by_sid): Rename to... (constraint_manager::get_equiv_class_by_svalue): ...this, porting from svalue_id to const svalue *. (constraint_manager::get_or_add_equiv_class): Port from svalue_id to const svalue *. (constraint_manager::eval_condition): Make const. Call compare_constants and return early if it provides a known result. (constraint_manager::get_ec_bounds): New. (constraint_manager::eval_condition): New overloads. Make existing one const, and use compare_constants. (constraint_manager::purge): Convert "p" param to a template rather that an abstract base class. Port from svalue_id to const svalue *. (class dead_svalue_purger): New class. (constraint_manager::remap_svalue_ids): Delete. (constraint_manager::on_liveness_change): New. (equiv_class_cmp): Port from svalue_id to const svalue *. (constraint_manager::canonicalize): Likewise. Combine with purging of redundant equivalence classes and constraints. (class cleaned_constraint_manager): Delete. (class merger_fact_visitor): Make "m_cm_b" const. Add "m_merger" field. (merger_fact_visitor::fact): Port from svalue_id to const svalue *. Add special case for widening. (constraint_manager::merge): Port from svalue_id to const svalue *. (constraint_manager::clean_merger_input): Delete. (constraint_manager::for_each_fact): Port from svalue_id to const svalue *. (constraint_manager::validate): Likewise. (selftest::test_constraint_conditions): Provide a region_model_manager when creating region_model instances. Add test for self-equality not creating equivalence classes. (selftest::test_transitivity): Provide a region_model_manager when creating region_model instances. Verify that EC-merging happens when constraints are implied. (selftest::test_constant_comparisons): Provide a region_model_manager when creating region_model instances. (selftest::test_constraint_impl): Likewise. Remove over-specified assertions. (selftest::test_equality): Provide a region_model_manager when creating region_model instances. (selftest::test_many_constants): Likewise. Provide a program_point when testing merging. (selftest::run_constraint_manager_tests): Move call to test_constant_comparisons to outside the transitivity guard. * constraint-manager.h (struct bound): Move here from constraint-manager.cc. (struct range): Likewise. (struct::eval_condition): New decl. (struct::below_lower_bound): New decl. (struct::above_upper_bound): New decl. (equiv_class::add): Port from svalue_id to const svalue *. (equiv_class::del): Likewise. (equiv_class::get_representative): Likewise. (equiv_class::remap_svalue_ids): Drop. (equiv_class::m_cst_sid): Convert to.. (equiv_class::m_cst_sval): ...this. (equiv_class::m_vars): Port from svalue_id to const svalue *. (constraint::bool implied_by): New decl. (fact_visitor::on_fact): Port from svalue_id to const svalue *. (constraint_manager::constraint_manager): Add mgr param. (constraint_manager::clone): Delete. (constraint_manager::maybe_get_constant): Delete. (constraint_manager::get_sid_for_constant): Delete. (constraint_manager::get_num_svalues): Delete. (constraint_manager::dump_to_pp): Add "multiline" param. (constraint_manager::get_equiv_class): Port from svalue_id to const svalue *. (constraint_manager::add_constraint): Likewise. (constraint_manager::get_equiv_class_by_sid): Rename to... (constraint_manager::get_equiv_class_by_svalue): ...this, porting from svalue_id to const svalue *. (constraint_manager::add_unknown_constraint): New decl. (constraint_manager::get_or_add_equiv_class): Port from svalue_id to const svalue *. (constraint_manager::eval_condition): Likewise. Add overloads. (constraint_manager::get_ec_bounds): New decl. (constraint_manager::purge): Convert to template. (constraint_manager::remap_svalue_ids): Delete. (constraint_manager::on_liveness_change): New decl. (constraint_manager::canonicalize): Drop param. (constraint_manager::clean_merger_input): Delete. (constraint_manager::m_mgr): New field. * diagnostic-manager.cc: Move includes of "analyzer/call-string.h" and "analyzer/program-point.h" to before "analyzer/region-model.h", and also include "analyzer/store.h" before it. (saved_diagnostic::saved_diagnostic): Add "sval" param. (diagnostic_manager::diagnostic_manager): Add engine param. (diagnostic_manager::add_diagnostic): Add "sval" param, passing it to saved_diagnostic ctor. Update overload to pass NULL for it. (dedupe_winners::dedupe_winners): Add engine param. (dedupe_winners::add): Add "eg" param. Pass m_engine to feasible_p. (dedupe_winner::m_engine): New field. (diagnostic_manager::emit_saved_diagnostics): Pass engine to dedupe_winners. Pass &eg when adding candidates. Pass svalue rather than tree to prune_path. Use get_stmt_location to get primary location of diagnostic. (diagnostic_manager::emit_saved_diagnostic): Likewise. (get_any_origin): Drop. (state_change_event_creator::on_global_state_change): Pass NULL const svalue * rather than NULL_TREE trees to state_change_event ctor. (state_change_event_creator::on_state_change): Port from tree and svalue_id to const svalue *. (for_each_state_change): Port from svalue_id to const svalue *. (struct null_assignment_sm_context): New. (diagnostic_manager::add_events_for_eedge): Add state change events for assignment to NULL. (diagnostic_manager::prune_path): Update param from tree to const svalue *. (diagnostic_manager::prune_for_sm_diagnostic): Port from tracking by tree to by const svalue *. * diagnostic-manager.h (saved_diagnostic::saved_diagnostic): Add sval param. (saved_diagnostic::m_sval): New field. (diagnostic_manager::diagnostic_manager): Add engine param. (diagnostic_manager::get_engine): New. (diagnostic_manager::add_diagnostic): Add "sval" param. (diagnostic_manager::prune_path): Likewise. (diagnostic_manager::prune_for_sm_diagnostic): New overload. (diagnostic_manager::m_eng): New field. * engine.cc: Move includes of "analyzer/call-string.h" and "analyzer/program-point.h" to before "analyzer/region-model.h", and also include "analyzer/store.h" before it. (impl_region_model_context::impl_region_model_context): Update for removal of m_change field. (impl_region_model_context::remap_svalue_ids): Delete. (impl_region_model_context::on_svalue_leak): New. (impl_region_model_context::on_svalue_purge): Delete. (impl_region_model_context::on_liveness_change): New. (impl_region_model_context::on_unknown_change): Update param from svalue_id to const svalue *. Add is_mutable param. (setjmp_svalue::compare_fields): Delete. (setjmp_svalue::accept): New. (setjmp_svalue::add_to_hash): Delete. (setjmp_svalue::dump_to_pp): New. (setjmp_svalue::print_details): Delete. (impl_sm_context::impl_sm_context): Drop "change" param. (impl_sm_context::get_fndecl_for_call): Drop "m_change". (impl_sm_context::on_transition): Drop ATTRIBUTE_UNUSED from "stmt" param. Drop m_change. Port from svalue_id to const svalue *. (impl_sm_context::warn_for_state): Drop m_change. Port from svalue_id to const svalue *. (impl_sm_context::get_readable_tree): Rename to... (impl_sm_context::get_diagnostic_tree): ...this. Port from svalue_id to const svalue *. (impl_sm_context::is_zero_assignment): New. (impl_sm_context::m_change): Delete field. (leak_stmt_finder::find_stmt): Handle m_var being NULL. (readability): Increase penalty for MEM_REF. For SSA_NAMEs, slightly favor the underlying var over the SSA name. Heavily penalize temporaries. Handle RESULT_DECL. (readability_comparator): Make non-static. Consider stack depths. (impl_region_model_context::on_state_leak): Convert from svalue_id to const svalue *, updating for region_model changes. Use id_equal. (impl_region_model_context::on_inherited_svalue): Delete. (impl_region_model_context::on_cast): Delete. (impl_region_model_context::on_condition): Drop m_change. (impl_region_model_context::on_phi): Likewise. (impl_region_model_context::on_unexpected_tree_code): Handle t being NULL. (point_and_state::validate): Update stack checking for region_model changes. (eg_traits::dump_args_t::show_enode_details_p): New. (exploded_node::exploded_node): Initialize m_num_processed_stmts. (exploded_node::get_processed_stmt): New function. (exploded_node::get_dot_fillcolor): Add more colors. (exploded_node::dump_dot): Guard the printing of the point and state with show_enode_details_p. Print the processed stmts for this enode after the initial state. (exploded_node::dump_to_pp): Pass true for new multiline param of program_state::dump_to_pp. (exploded_node::on_stmt): Drop "change" param. Log the stmt. Set input_location. Implement __analyzer_describe. Update implementation of __analyzer_dump and __analyzer_eval. Remove purging of sm-state for unknown fncalls from here. (exploded_node::on_edge): Drop "change" param. (exploded_node::on_longjmp): Port from region_id/svalue_id to const region */const svalue *. Call program_state::detect_leaks. Drop state_change. (exploded_node::detect_leaks): Update for changes to region_model. Call program_state::detect_leaks. (exploded_edge::exploded_edge): Drop ext_state and change params. (exploded_edge::dump_dot): "args" is no longer used. Drop dumping of m_change. (exploded_graph::exploded_graph): Pass engine to m_diagnostic_manager ctor. Use program_point::origin. (exploded_graph::add_function_entry): Drop ctxt. Use program_state::push_frame. Drop state_change. (exploded_graph::get_or_create_node): Drop "change" param. Add "enode_for_diag" param. Update dumping calls for API changes. Pass point to can_merge_with_p. Show enode indices within -Wanalyzer-too-complex diagnostic for hitting the per-point limit. (exploded_graph::add_edge): Drop "change" param. Log which nodes are being connected. Update for changes to exploded_edge ctor. (exploded_graph::get_per_program_point_data): New. (exploded_graph::process_worklist): Pass point to can_merge_with_p. Drop state_change. Update dumping call for API change. (exploded_graph::process_node): Drop state_change. Split the node in-place if an sm-state-change occurs. Update m_num_processed_stmts. Update dumping calls for API change. (exploded_graph::log_stats): Call engine::log_stats. (exploded_graph::dump_states_for_supernode): Update dumping call. (exploded_path::feasible_p): Add "eng" and "eg" params. Rename "i" to "end_idx". Pass the manager to the region_model ctor. Update for every processed stmt in the enode, not just the first. Keep track of which snodes have been visited, and call loop_replay_fixup when revisiting one. (enode_label::get_text): Update dump call for new param. (exploded_graph::dump_exploded_nodes): Likewise. (exploded_graph::get_node_by_index): New. (impl_run_checkers): Create engine instance and pass its address to extrinsic_state ctor. * exploded-graph.h (impl_region_model_context::impl_region_model_context): Drop "change" params. (impl_region_model_context::void remap_svalue_ids): Delete. (impl_region_model_context::on_svalue_purge): Delete. (impl_region_model_context::on_svalue_leak): New. (impl_region_model_context::on_liveness_change): New. (impl_region_model_context::on_state_leak): Update signature. (impl_region_model_context::on_inherited_svalue): Delete. (impl_region_model_context::on_cast): Delete. (impl_region_model_context::on_unknown_change): Update signature. (impl_region_model_context::m_change): Delete. (eg_traits::dump_args_t::show_enode_details_p): New. (exploded_node::on_stmt): Drop "change" param. (exploded_node::on_edge): Likewise. (exploded_node::get_processed_stmt): New decl. (exploded_node::m_num_processed_stmts): New field. (exploded_edge::exploded_edge): Drop ext_state and change params. (exploded_edge::m_change): Delete. (exploded_graph::get_engine): New accessor. (exploded_graph::get_or_create_node): Drop "change" param. Add "enode_for_diag" param. (exploded_graph::add_edge): Drop "change" param. (exploded_graph::get_per_program_point_data): New decl. (exploded_graph::get_node_by_index): New decl. (exploded_path::feasible_p): Add "eng" and "eg" params. * program-point.cc: Include "analyzer/store.h" before including "analyzer/region-model.h". (function_point::function_point): Move here from program-point.h. (function_point::get_function): Likewise. (function_point::from_function_entry): Likewise. (function_point::before_supernode): Likewise. (function_point::next_stmt): New function. * program-point.h (function_point::function_point): Move implementation from here to program-point.cc. (function_point::get_function): Likewise. (function_point::from_function_entry): Likewise. (function_point::before_supernode): Likewise. (function_point::next_stmt): New decl. (program_point::operator!=): New. (program_point::origin): New. (program_point::next_stmt): New. (program_point::m_function_point): Make non-const. * program-state.cc: Move includes of "analyzer/call-string.h" and "analyzer/program-point.h" to before "analyzer/region-model.h", and also include "analyzer/store.h" before it. (extrinsic_state::get_model_manager): New. (sm_state_map::sm_state_map): Pass in sm and sm_idx to ctor, rather than pass the around. (sm_state_map::clone_with_remapping): Delete. (sm_state_map::print): Remove "sm" param in favor of "m_sm". Add "simple" and "multiline" params and support multiline vs single line dumping. (sm_state_map::dump): Remove "sm" param in favor of "m_sm". Add "simple" param. (sm_state_map::hash): Port from svalue_id to const svalue *. (sm_state_map::operator==): Likewise. (sm_state_map::get_state): Likewise. Call canonicalize_svalue on input. Handle inheritance of sm-state. Call get_default_state. (sm_state_map::get_origin): Port from svalue_id to const svalue *. (sm_state_map::set_state): Likewise. Pass in ext_state. Reject attempts to set state on UNKNOWN. (sm_state_map::impl_set_state): Port from svalue_id to const svalue *. Pass in ext_state. Call canonicalize_svalue on input. (sm_state_map::purge_for_unknown_fncall): Delete. (sm_state_map::on_svalue_leak): New. (sm_state_map::remap_svalue_ids): Delete. (sm_state_map::on_liveness_change): New. (sm_state_map::on_unknown_change): Reimplement. (sm_state_map::on_svalue_purge): Delete. (sm_state_map::on_inherited_svalue): Delete. (sm_state_map::on_cast): Delete. (sm_state_map::validate): Delete. (sm_state_map::canonicalize_svalue): New. (program_state::program_state): Update to pass manager to region_model's ctor. Constify num_states and pass state machine and index to sm_state_map ctor. (program_state::print): Update for changes to dump API. (program_state::dump_to_pp): Ignore the summarize param. Add "multiline" param. (program_state::dump_to_file): Add "multiline" param. (program_state::dump): Pass "true" for new "multiline" param. (program_state::push_frame): New. (program_state::on_edge): Drop "change" param. Call program_state::detect_leaks. (program_state::prune_for_point): Add enode_for_diag param. Reimplement based on store class. Call detect_leaks (program_state::remap_svalue_ids): Delete. (program_state::get_representative_tree): Port from svalue_id to const svalue *. (program_state::can_merge_with_p): Add "point" param. Add early reject for sm-differences. Drop id remapping. (program_state::validate): Drop region model and sm_state_map validation. (state_change::sm_change::dump): Delete. (state_change::sm_change::remap_svalue_ids): Delete. (state_change::sm_change::on_svalue_purge): Delete. (log_set_of_svalues): New. (state_change::sm_change::validate): Delete. (state_change::state_change): Delete. (state_change::add_sm_change): Delete. (state_change::affects_p): Delete. (state_change::dump): Delete. (state_change::remap_svalue_ids): Delete. (state_change::on_svalue_purge): Delete. (state_change::validate): Delete. (selftest::assert_dump_eq): Delete. (ASSERT_DUMP_EQ): Delete. (selftest::test_sm_state_map): Update for changes to region_model and sm_state_map, porting from svalue_id to const svalue *. (selftest::test_program_state_dumping): Likewise. Drop test of dumping, renaming to... (selftest::test_program_state_1): ...this. (selftest::test_program_state_dumping_2): Likewise, renaming to... (selftest::test_program_state_2): ...this. (selftest::test_program_state_merging): Update for changes to region_model. (selftest::test_program_state_merging_2): Likewise. (selftest::analyzer_program_state_cc_tests): Update for renamed tests. * program-state.h (extrinsic_state::extrinsic_state): Add logger and engine params. (extrinsic_state::get_logger): New accessor. (extrinsic_state::get_engine): New accessor. (extrinsic_state::get_model_manager): New accessor. (extrinsic_state::m_logger): New field. (extrinsic_state::m_engine): New field. (struct default_hash_traits<svalue_id>): Delete. (pod_hash_traits<svalue_id>::hash): Delete. (pod_hash_traits<svalue_id>::equal): Delete. (pod_hash_traits<svalue_id>::mark_deleted): Delete. (pod_hash_traits<svalue_id>::mark_empty): Delete. (pod_hash_traits<svalue_id>::is_deleted): Delete. (pod_hash_traits<svalue_id>::is_empty): Delete. (sm_state_map::entry_t::entry_t): Port from svalue_id to const svalue *. (sm_state_map::entry_t::m_origin): Likewise. (sm_state_map::map_t): Likewise. (sm_state_map::sm_state_map): Add state_machine and index params. (sm_state_map::clone_with_remapping): Delete. (sm_state_map::print): Drop sm param; add simple and multiline params. (sm_state_map::dump): Drop sm param; add simple param. (sm_state_map::get_state): Port from svalue_id to const svalue *. Add ext_state param. (sm_state_map::get_origin): Likewise. (sm_state_map::set_state): Likewise. (sm_state_map::impl_set_state): Likewise. (sm_state_map::purge_for_unknown_fncall): Delete. (sm_state_map::remap_svalue_ids): Delete. (sm_state_map::on_svalue_purge): Delete. (sm_state_map::on_svalue_leak): New. (sm_state_map::on_liveness_change): New. (sm_state_map::on_inherited_svalue): Delete. (sm_state_map::on_cast): Delete. (sm_state_map::validate): Delete. (sm_state_map::on_unknown_change): Port from svalue_id to const svalue *. Add is_mutable and ext_state params. (sm_state_map::canonicalize_svalue): New. (sm_state_map::m_sm): New field. (sm_state_map::m_sm_idx): New field. (program_state::operator=): Delete. (program_state::dump_to_pp): Drop "summarize" param, adding "simple" and "multiline". (program_state::dump_to_file): Likewise. (program_state::dump): Rename "summarize" to "simple". (program_state::push_frame): New. (program_state::get_current_function): New. (program_state::on_edge): Drop "change" param. (program_state::prune_for_point): Likewise. Add enode_for_diag param. (program_state::remap_svalue_ids): Delete. (program_state::get_representative_tree): Port from svalue_id to const svalue *. (program_state::can_purge_p): Likewise. Pass ext_state to get_state. (program_state::can_merge_with_p): Add point param. (program_state::detect_leaks): New. (state_change_visitor::on_state_change): Port from tree and svalue_id to a pair of const svalue *. (class state_change): Delete. * region.cc: New file. * region-model-impl-calls.cc: New file. * region-model-manager.cc: New file. * region-model-reachability.cc: New file. * region-model-reachability.h: New file. * region-model.cc: Include "analyzer/call-string.h", "analyzer/program-point.h", and "analyzer/store.h" before "analyzer/region-model.h". Include "analyzer/region-model-reachability.h". (dump_tree): Make non-static. (dump_quoted_tree): Make non-static. (print_quoted_type): Make non-static. (path_var::dump): Delete. (dump_separator): Delete. (class impl_constraint_manager): Delete. (svalue_id::print): Delete. (svalue_id::dump_node_name_to_pp): Delete. (svalue_id::validate): Delete. (region_id::print): Delete. (region_id::dump_node_name_to_pp): Delete. (region_id::validate): Delete. (region_id_set::region_id_set): Delete. (svalue_id_set::svalue_id_set): Delete. (svalue::operator==): Delete. (svalue::hash): Delete. (svalue::print): Delete. (svalue::dump_dot_to_pp): Delete. (svalue::remap_region_ids): Delete. (svalue::walk_for_canonicalization): Delete. (svalue::get_child_sid): Delete. (svalue::maybe_get_constant): Delete. (region_svalue::compare_fields): Delete. (region_svalue::add_to_hash): Delete. (region_svalue::print_details): Delete. (region_svalue::dump_dot_to_pp): Delete. (region_svalue::remap_region_ids): Delete. (region_svalue::merge_values): Delete. (region_svalue::walk_for_canonicalization): Delete. (region_svalue::eval_condition): Delete. (constant_svalue::compare_fields): Delete. (constant_svalue::add_to_hash): Delete. (constant_svalue::merge_values): Delete. (constant_svalue::eval_condition): Move to svalue.cc. (constant_svalue::print_details): Delete. (constant_svalue::get_child_sid): Delete. (unknown_svalue::compare_fields): Delete. (unknown_svalue::add_to_hash): Delete. (unknown_svalue::print_details): Delete. (poison_kind_to_str): Move to svalue.cc. (poisoned_svalue::compare_fields): Delete. (poisoned_svalue::add_to_hash): Delete. (poisoned_svalue::print_details): Delete. (region_kind_to_str): Move to region.cc and reimplement. (region::operator==): Delete. (region::get_parent_region): Delete. (region::set_value): Delete. (region::become_active_view): Delete. (region::deactivate_any_active_view): Delete. (region::deactivate_view): Delete. (region::get_value): Delete. (region::get_inherited_child_sid): Delete. (region_model::copy_region): Delete. (region_model::copy_struct_region): Delete. (region_model::copy_union_region): Delete. (region_model::copy_array_region): Delete. (region::hash): Delete. (region::print): Delete. (region::dump_dot_to_pp): Delete. (region::dump_to_pp): Delete. (region::dump_child_label): Delete. (region::validate): Delete. (region::remap_svalue_ids): Delete. (region::remap_region_ids): Delete. (region::add_view): Delete. (region::get_view): Delete. (region::region): Move to region.cc. (region::add_to_hash): Delete. (region::print_fields): Delete. (region::non_null_p): Delete. (primitive_region::clone): Delete. (primitive_region::walk_for_canonicalization): Delete. (map_region::map_region): Delete. (map_region::compare_fields): Delete. (map_region::print_fields): Delete. (map_region::validate): Delete. (map_region::dump_dot_to_pp): Delete. (map_region::dump_child_label): Delete. (map_region::get_or_create): Delete. (map_region::get): Delete. (map_region::add_to_hash): Delete. (map_region::remap_region_ids): Delete. (map_region::unbind): Delete. (map_region::get_tree_for_child_region): Delete. (map_region::get_tree_for_child_region): Delete. (tree_cmp): Move to region.cc. (map_region::can_merge_p): Delete. (map_region::walk_for_canonicalization): Delete. (map_region::get_value_by_name): Delete. (struct_or_union_region::valid_key_p): Delete. (struct_or_union_region::compare_fields): Delete. (struct_region::clone): Delete. (struct_region::compare_fields): Delete. (union_region::clone): Delete. (union_region::compare_fields): Delete. (frame_region::compare_fields): Delete. (frame_region::clone): Delete. (frame_region::valid_key_p): Delete. (frame_region::print_fields): Delete. (frame_region::add_to_hash): Delete. (globals_region::compare_fields): Delete. (globals_region::clone): Delete. (globals_region::valid_key_p): Delete. (code_region::compare_fields): Delete. (code_region::clone): Delete. (code_region::valid_key_p): Delete. (array_region::array_region): Delete. (array_region::get_element): Delete. (array_region::clone): Delete. (array_region::compare_fields): Delete. (array_region::print_fields): Delete. (array_region::validate): Delete. (array_region::dump_dot_to_pp): Delete. (array_region::dump_child_label): Delete. (array_region::get_or_create): Delete. (array_region::get): Delete. (array_region::add_to_hash): Delete. (array_region::remap_region_ids): Delete. (array_region::get_key_for_child_region): Delete. (array_region::key_cmp): Delete. (array_region::walk_for_canonicalization): Delete. (array_region::key_from_constant): Delete. (array_region::constant_from_key): Delete. (function_region::compare_fields): Delete. (function_region::clone): Delete. (function_region::valid_key_p): Delete. (stack_region::stack_region): Delete. (stack_region::compare_fields): Delete. (stack_region::clone): Delete. (stack_region::print_fields): Delete. (stack_region::dump_child_label): Delete. (stack_region::validate): Delete. (stack_region::push_frame): Delete. (stack_region::get_current_frame_id): Delete. (stack_region::pop_frame): Delete. (stack_region::add_to_hash): Delete. (stack_region::remap_region_ids): Delete. (stack_region::can_merge_p): Delete. (stack_region::walk_for_canonicalization): Delete. (stack_region::get_value_by_name): Delete. (heap_region::heap_region): Delete. (heap_region::compare_fields): Delete. (heap_region::clone): Delete. (heap_region::walk_for_canonicalization): Delete. (root_region::root_region): Delete. (root_region::compare_fields): Delete. (root_region::clone): Delete. (root_region::print_fields): Delete. (root_region::validate): Delete. (root_region::dump_child_label): Delete. (root_region::push_frame): Delete. (root_region::get_current_frame_id): Delete. (root_region::pop_frame): Delete. (root_region::ensure_stack_region): Delete. (root_region::get_stack_region): Delete. (root_region::ensure_globals_region): Delete. (root_region::get_code_region): Delete. (root_region::ensure_code_region): Delete. (root_region::get_globals_region): Delete. (root_region::ensure_heap_region): Delete. (root_region::get_heap_region): Delete. (root_region::remap_region_ids): Delete. (root_region::can_merge_p): Delete. (root_region::add_to_hash): Delete. (root_region::walk_for_canonicalization): Delete. (root_region::get_value_by_name): Delete. (symbolic_region::symbolic_region): Delete. (symbolic_region::compare_fields): Delete. (symbolic_region::clone): Delete. (symbolic_region::walk_for_canonicalization): Delete. (symbolic_region::print_fields): Delete. (region_model::region_model): Add region_model_manager * param. Reimplement in terms of store, dropping impl_constraint_manager subclass. (region_model::operator=): Reimplement in terms of store (region_model::operator==): Likewise. (region_model::hash): Likewise. (region_model::print): Delete. (region_model::print_svalue): Delete. (region_model::dump_dot_to_pp): Delete. (region_model::dump_dot_to_file): Delete. (region_model::dump_dot): Delete. (region_model::dump_to_pp): Replace "summarize" param with "simple" and "multiline". Port to store-based implementation. (region_model::dump): Replace "summarize" param with "simple" and "multiline". (dump_vec_of_tree): Delete. (region_model::dump_summary_of_rep_path_vars): Delete. (region_model::validate): Delete. (svalue_id_cmp_by_constant_svalue_model): Delete. (svalue_id_cmp_by_constant_svalue): Delete. (region_model::canonicalize): Drop "ctxt" param. Reimplement in terms of store and constraints. (region_model::canonicalized_p): Remove NULL arg to canonicalize. (region_model::loop_replay_fixup): New. (poisoned_value_diagnostic::emit): Tweak wording of warnings. (region_model::check_for_poison): Delete. (region_model::get_gassign_result): New. (region_model::on_assignment): Port to store-based implementation. (region_model::on_call_pre): Delete calls to check_for_poison. Move implementations to region-model-impl-calls.c and port to store-based implementation. (region_model::on_call_post): Likewise. (class reachable_regions): Move to region-model-reachability.h/cc and port to store-based implementation. (region_model::handle_unrecognized_call): Port to store-based implementation. (region_model::get_reachable_svalues): New. (region_model::on_setjmp): Port to store-based implementation. (region_model::on_longjmp): Likewise. (region_model::handle_phi): Drop is_back_edge param and the logic using it. (region_model::get_lvalue_1): Port from region_id to const region *. (region_model::make_region_for_unexpected_tree_code): Delete. (assert_compat_types): If the check fails, use internal_error to show the types. (region_model::get_lvalue): Port from region_id to const region *. (region_model::get_rvalue_1): Port from svalue_id to const svalue *. (region_model::get_rvalue): Likewise. (region_model::get_or_create_ptr_svalue): Delete. (region_model::get_or_create_constant_svalue): Delete. (region_model::get_svalue_for_fndecl): Delete. (region_model::get_region_for_fndecl): Delete. (region_model::get_svalue_for_label): Delete. (region_model::get_region_for_label): Delete. (build_cast): Delete. (region_model::maybe_cast_1): Delete. (region_model::maybe_cast): Delete. (region_model::get_field_region): Delete. (region_model::get_store_value): New. (region_model::region_exists_p): New. (region_model::deref_rvalue): Port from svalue_id to const svalue *. (region_model::set_value): Likewise. (region_model::clobber_region): New. (region_model::purge_region): New. (region_model::zero_fill_region): New. (region_model::mark_region_as_unknown): New. (region_model::eval_condition): Port from svalue_id to const svalue *. (region_model::eval_condition_without_cm): Likewise. (region_model::compare_initial_and_pointer): New. (region_model::add_constraint): Port from svalue_id to const svalue *. (region_model::maybe_get_constant): Delete. (region_model::get_representative_path_var): New. (region_model::add_new_malloc_region): Delete. (region_model::get_representative_tree): Port to const svalue *. (region_model::get_representative_path_var): Port to const region *. (region_model::get_path_vars_for_svalue): Delete. (region_model::set_to_new_unknown_value): Delete. (region_model::update_for_phis): Don't pass is_back_edge to handle_phi. (region_model::update_for_call_superedge): Port from svalue_id to const svalue *. (region_model::update_for_return_superedge): Port to store-based implementation. (region_model::update_for_call_summary): Replace set_to_new_unknown_value with mark_region_as_unknown. (region_model::get_root_region): Delete. (region_model::get_stack_region_id): Delete. (region_model::push_frame): Delete. (region_model::get_current_frame_id): Delete. (region_model::get_current_function): Delete. (region_model::pop_frame): Delete. (region_model::on_top_level_param): New. (region_model::get_stack_depth): Delete. (region_model::get_function_at_depth): Delete. (region_model::get_globals_region_id): Delete. (region_model::add_svalue): Delete. (region_model::replace_svalue): Delete. (region_model::add_region): Delete. (region_model::get_svalue): Delete. (region_model::get_region): Delete. (make_region_for_type): Delete. (region_model::add_region_for_type): Delete. (region_model::on_top_level_param): New. (class restrict_to_used_svalues): Delete. (region_model::purge_unused_svalues): Delete. (region_model::push_frame): New. (region_model::remap_svalue_ids): Delete. (region_model::remap_region_ids): Delete. (region_model::purge_regions): Delete. (region_model::get_descendents): Delete. (region_model::delete_region_and_descendents): Delete. (region_model::poison_any_pointers_to_bad_regions): Delete. (region_model::can_merge_with_p): Delete. (region_model::get_current_function): New. (region_model::get_value_by_name): Delete. (region_model::convert_byte_offset_to_array_index): Delete. (region_model::pop_frame): New. (region_model::get_or_create_mem_ref): Delete. (region_model::get_stack_depth): New. (region_model::get_frame_at_index): New. (region_model::unbind_region_and_descendents): New. (struct bad_pointer_finder): New. (region_model::get_or_create_pointer_plus_expr): Delete. (region_model::poison_any_pointers_to_descendents): New. (region_model::get_or_create_view): Delete. (region_model::can_merge_with_p): New. (region_model::get_fndecl_for_call): Port from svalue_id to const svalue *. (struct append_ssa_names_cb_data): New. (get_ssa_name_regions_for_current_frame): New. (region_model::append_ssa_names_cb): New. (model_merger::dump_to_pp): Add "simple" param. Drop dumping of remappings. (model_merger::dump): Add "simple" param to both overloads. (model_merger::can_merge_values_p): Delete. (model_merger::record_regions): Delete. (model_merger::record_svalues): Delete. (svalue_id_merger_mapping::svalue_id_merger_mapping): Delete. (svalue_id_merger_mapping::dump_to_pp): Delete. (svalue_id_merger_mapping::dump): Delete. (region_model::create_region_for_heap_alloc): New. (region_model::create_region_for_alloca): New. (region_model::record_dynamic_extents): New. (canonicalization::canonicalization): Delete. (canonicalization::walk_rid): Delete. (canonicalization::walk_sid): Delete. (canonicalization::dump_to_pp): Delete. (canonicalization::dump): Delete. (inchash::add): Delete overloads for svalue_id and region_id. (engine::log_stats): New. (assert_condition): Add overload comparing svalues. (assert_dump_eq): Pass "true" for multiline. (selftest::test_dump): Update for rewrite of region_model. (selftest::test_dump_2): Rename to... (selftest::test_struct): ...this. Provide a region_model_manager when creating region_model instance. Remove dump test. Add checks for get_offset. (selftest::test_dump_3): Rename to... (selftest::test_array_1): ...this. Provide a region_model_manager when creating region_model instance. Remove dump test. (selftest::test_get_representative_tree): Port from svalue_id to new API. Add test coverage for various expressions. (selftest::test_unique_constants): Provide a region_model_manager for the region_model. Add test coverage for comparing const vs non-const. (selftest::test_svalue_equality): Delete. (selftest::test_region_equality): Delete. (selftest::test_unique_unknowns): New. (class purge_all_svalue_ids): Delete. (class purge_one_svalue_id): Delete. (selftest::test_purging_by_criteria): Delete. (selftest::test_initial_svalue_folding): New. (selftest::test_unaryop_svalue_folding): New. (selftest::test_binop_svalue_folding): New. (selftest::test_sub_svalue_folding): New. (selftest::test_purge_unused_svalues): Delete. (selftest::test_descendent_of_p): New. (selftest::test_assignment): Provide a region_model_manager for the region_model. Drop the dump test. (selftest::test_compound_assignment): Likewise. (selftest::test_stack_frames): Port to new implementation. (selftest::test_get_representative_path_var): Likewise. (selftest::test_canonicalization_1): Rename to... (selftest::test_equality_1): ...this. Port to new API, and add (selftest::test_canonicalization_2): Provide a region_model_manager when creating region_model instances. Remove redundant canicalization. (selftest::test_canonicalization_3): Provide a region_model_manager when creating region_model instances. Remove param from calls to region_model::canonicalize. (selftest::test_canonicalization_4): Likewise. (selftest::assert_region_models_merge): Constify out_merged_svalue. Port to new API. (selftest::test_state_merging): Provide a region_model_manager when creating region_model instances. Provide a program_point point when merging them. Replace set_to_new_unknown_value with usage of placeholder_svalues. Drop get_value_by_name. Port from svalue_id to const svalue *. Add test of heap allocation. (selftest::test_constraint_merging): Provide a region_model_manager when creating region_model instances. Provide a program_point point when merging them. Eliminate use of set_to_new_unknown_value. (selftest::test_widening_constraints): New. (selftest::test_iteration_1): New. (selftest::test_malloc_constraints): Port to store-based implementation. (selftest::test_var): New test. (selftest::test_array_2): New test. (selftest::test_mem_ref): New test. (selftest::test_POINTER_PLUS_EXPR_then_MEM_REF): New. (selftest::test_malloc): New. (selftest::test_alloca): New. (selftest::analyzer_region_model_cc_tests): Update for renamings. Call new functions. * region-model.h (class path_var): Move to analyzer.h. (class svalue_id): Delete. (class region_id): Delete. (class id_map): Delete. (svalue_id_map): Delete. (region_id_map): Delete. (id_map<T>::id_map): Delete. (id_map<T>::put): Delete. (id_map<T>::get_dst_for_src): Delete. (id_map<T>::get_src_for_dst): Delete. (id_map<T>::dump_to_pp): Delete. (id_map<T>::dump): Delete. (id_map<T>::update): Delete. (one_way_svalue_id_map): Delete. (one_way_region_id_map): Delete. (class region_id_set): Delete. (class svalue_id_set): Delete. (struct complexity): New. (class visitor): New. (enum svalue_kind): Add SK_SETJMP, SK_INITIAL, SK_UNARYOP, SK_BINOP, SK_SUB,SK_UNMERGEABLE, SK_PLACEHOLDER, SK_WIDENING, SK_COMPOUND, and SK_CONJURED. (svalue::operator==): Delete. (svalue::operator!=): Delete. (svalue::clone): Delete. (svalue::hash): Delete. (svalue::dump_dot_to_pp): Delete. (svalue::dump_to_pp): New. (svalue::dump): New. (svalue::get_desc): New. (svalue::dyn_cast_initial_svalue): New. (svalue::dyn_cast_unaryop_svalue): New. (svalue::dyn_cast_binop_svalue): New. (svalue::dyn_cast_sub_svalue): New. (svalue::dyn_cast_unmergeable_svalue): New. (svalue::dyn_cast_widening_svalue): New. (svalue::dyn_cast_compound_svalue): New. (svalue::dyn_cast_conjured_svalue): New. (svalue::maybe_undo_cast): New. (svalue::unwrap_any_unmergeable): New. (svalue::remap_region_ids): Delete (svalue::can_merge_p): New. (svalue::walk_for_canonicalization): Delete (svalue::get_complexity): New. (svalue::get_child_sid): Delete (svalue::accept): New. (svalue::live_p): New. (svalue::implicitly_live_p): New. (svalue::svalue): Add complexity param. (svalue::add_to_hash): Delete (svalue::print_details): Delete (svalue::m_complexity): New field. (region_svalue::key_t): New struct. (region_svalue::region_svalue): Port from region_id to const region_id *. Add complexity. (region_svalue::compare_fields): Delete. (region_svalue::clone): Delete. (region_svalue::dump_dot_to_pp): Delete. (region_svalue::get_pointee): Port from region_id to const region_id *. (region_svalue::remap_region_ids): Delete. (region_svalue::merge_values): Delete. (region_svalue::dump_to_pp): New. (region_svalue::accept): New. (region_svalue::walk_for_canonicalization): Delete. (region_svalue::eval_condition): Make params const. (region_svalue::add_to_hash): Delete. (region_svalue::print_details): Delete. (region_svalue::m_rid): Replace with... (region_svalue::m_reg): ...this. (is_a_helper <region_svalue *>::test): Convert to... (is_a_helper <const region_svalue *>::test): ...this. (template <> struct default_hash_traits<region_svalue::key_t>): New. (constant_svalue::constant_svalue): Add complexity. (constant_svalue::compare_fields): Delete. (constant_svalue::clone): Delete. (constant_svalue::add_to_hash): Delete. (constant_svalue::dump_to_pp): New. (constant_svalue::accept): New. (constant_svalue::implicitly_live_p): New. (constant_svalue::merge_values): Delete. (constant_svalue::eval_condition): Make params const. (constant_svalue::get_child_sid): Delete. (constant_svalue::print_details): Delete. (is_a_helper <constant_svalue *>::test): Convert to... (is_a_helper <const constant_svalue *>::test): ...this. (class unknown_svalue): Update leading comment. (unknown_svalue::unknown_svalue): Add complexity. (unknown_svalue::compare_fields): Delete. (unknown_svalue::add_to_hash): Delete. (unknown_svalue::dyn_cast_unknown_svalue): Delete. (unknown_svalue::print_details): Delete. (unknown_svalue::dump_to_pp): New. (unknown_svalue::accept): New. (poisoned_svalue::key_t): New struct. (poisoned_svalue::poisoned_svalue): Add complexity. (poisoned_svalue::compare_fields): Delete. (poisoned_svalue::clone): Delete. (poisoned_svalue::add_to_hash): Delete. (poisoned_svalue::dump_to_pp): New. (poisoned_svalue::accept): New. (poisoned_svalue::print_details): Delete. (is_a_helper <poisoned_svalue *>::test): Convert to... (is_a_helper <const poisoned_svalue *>::test): ...this. (template <> struct default_hash_traits<poisoned_svalue::key_t>): New. (setjmp_record::add_to_hash): New. (setjmp_svalue::key_t): New struct. (setjmp_svalue::compare_fields): Delete. (setjmp_svalue::clone): Delete. (setjmp_svalue::add_to_hash): Delete. (setjmp_svalue::setjmp_svalue): Add complexity. (setjmp_svalue::dump_to_pp): New. (setjmp_svalue::accept): New. (setjmp_svalue::void print_details): Delete. (is_a_helper <const setjmp_svalue *>::test): New. (template <> struct default_hash_traits<setjmp_svalue::key_t>): New. (class initial_svalue : public svalue): New. (is_a_helper <const initial_svalue *>::test): New. (class unaryop_svalue): New. (is_a_helper <const unaryop_svalue *>::test): New. (template <> struct default_hash_traits<unaryop_svalue::key_t>): New. (class binop_svalue): New. (is_a_helper <const binop_svalue *>::test): New. (template <> struct default_hash_traits<binop_svalue::key_t>): New. (class sub_svalue): New. (is_a_helper <const sub_svalue *>::test): New. (template <> struct default_hash_traits<sub_svalue::key_t>): New. (class unmergeable_svalue): New. (is_a_helper <const unmergeable_svalue *>::test): New. (class placeholder_svalue): New. (is_a_helper <placeholder_svalue *>::test): New. (class widening_svalue): New. (is_a_helper <widening_svalue *>::test): New. (template <> struct default_hash_traits<widening_svalue::key_t>): New. (class compound_svalue): New. (is_a_helper <compound_svalue *>::test): New. (template <> struct default_hash_traits<compound_svalue::key_t>): New. (class conjured_svalue): New. (is_a_helper <conjured_svalue *>::test): New. (template <> struct default_hash_traits<conjured_svalue::key_t>): New. (enum region_kind): Delete RK_PRIMITIVE, RK_STRUCT, RK_UNION, and RK_ARRAY. Add RK_LABEL, RK_DECL, RK_FIELD, RK_ELEMENT, RK_OFFSET, RK_CAST, RK_HEAP_ALLOCATED, RK_ALLOCA, RK_STRING, and RK_UNKNOWN. (region_kind_to_str): Delete. (region::~region): Move implementation to region.cc. (region::operator==): Delete. (region::operator!=): Delete. (region::clone): Delete. (region::get_id): New. (region::cmp_ids): New. (region::dyn_cast_map_region): Delete. (region::dyn_cast_array_region): Delete. (region::region_id get_parent): Delete. (region::get_parent_region): Convert to a simple accessor. (region::void set_value): Delete. (region::svalue_id get_value): Delete. (region::svalue_id get_value_direct): Delete. (region::svalue_id get_inherited_child_sid): Delete. (region::dyn_cast_frame_region): New. (region::dyn_cast_function_region): New. (region::dyn_cast_decl_region): New. (region::dyn_cast_field_region): New. (region::dyn_cast_element_region): New. (region::dyn_cast_offset_region): New. (region::dyn_cast_cast_region): New. (region::dyn_cast_string_region): New. (region::accept): New. (region::get_base_region): New. (region::base_region_p): New. (region::descendent_of_p): New. (region::maybe_get_frame_region): New. (region::maybe_get_decl): New. (region::hash): Delete. (region::rint): Delete. (region::dump_dot_to_pp): Delete. (region::get_desc): New. (region::dump_to_pp): Convert to vfunc, changing signature. (region::dump_child_label): Delete. (region::remap_svalue_ids): Delete. (region::remap_region_ids): Delete. (region::dump): New. (region::walk_for_canonicalization): Delete. (region::non_null_p): Drop region_model param. (region::add_view): Delete. (region::get_view): Delete. (region::get_active_view): Delete. (region::is_view_p): Delete. (region::cmp_ptrs): New. (region::validate): Delete. (region::get_offset): New. (region::get_byte_size): New. (region::get_bit_size): New. (region::get_subregions_for_binding): New. (region::region): Add complexity param. Convert parent from region_id to const region *. Drop svalue_id. Drop copy ctor. (region::symbolic_for_unknown_ptr_p): New. (region::add_to_hash): Delete. (region::print_fields): Delete. (region::get_complexity): New accessor. (region::become_active_view): Delete. (region::deactivate_any_active_view): Delete. (region::deactivate_view): Delete. (region::calc_offset): New. (region::m_parent_rid): Delete. (region::m_sval_id): Delete. (region::m_complexity): New. (region::m_id): New. (region::m_parent): New. (region::m_view_rids): Delete. (region::m_is_view): Delete. (region::m_active_view_rid): Delete. (region::m_cached_offset): New. (is_a_helper <region *>::test): Convert to... (is_a_helper <const region *>::test): ... this. (class primitive_region): Delete. (class space_region): New. (class map_region): Delete. (is_a_helper <map_region *>::test): Delete. (class frame_region): Reimplement. (template <> struct default_hash_traits<frame_region::key_t>): New. (class globals_region): Reimplement. (is_a_helper <globals_region *>::test): Convert to... (is_a_helper <const globals_region *>::test): ...this. (class struct_or_union_region): Delete. (is_a_helper <struct_or_union_region *>::test): Delete. (class code_region): Reimplement. (is_a_helper <const code_region *>::test): New. (class struct_region): Delete. (is_a_helper <struct_region *>::test): Delete. (class function_region): Reimplement. (is_a_helper <function_region *>::test): Convert to... (is_a_helper <const function_region *>::test): ...this. (class union_region): Delete. (is_a_helper <union_region *>::test): Delete. (class label_region): New. (is_a_helper <const label_region *>::test): New. (class scope_region): Delete. (class stack_region): Reimplement. (is_a_helper <stack_region *>::test): Convert to... (is_a_helper <const stack_region *>::test): ...this. (class heap_region): Reimplement. (is_a_helper <heap_region *>::test): Convert to... (is_a_helper <const heap_region *>::test): ...this. (class root_region): Reimplement. (is_a_helper <root_region *>::test): Convert to... (is_a_helper <const root_region *>::test): ...this. (class symbolic_region): Reimplement. (is_a_helper <const symbolic_region *>::test): New. (template <> struct default_hash_traits<symbolic_region::key_t>): New. (class decl_region): New. (is_a_helper <const decl_region *>::test): New. (class field_region): New. (template <> struct default_hash_traits<field_region::key_t>): New. (class array_region): Delete. (class element_region): New. (is_a_helper <array_region *>::test): Delete. (is_a_helper <const element_region *>::test): New. (template <> struct default_hash_traits<element_region::key_t>): New. (class offset_region): New. (is_a_helper <const offset_region *>::test): New. (template <> struct default_hash_traits<offset_region::key_t>): New. (class cast_region): New. (is_a_helper <const cast_region *>::test): New. (template <> struct default_hash_traits<cast_region::key_t>): New. (class heap_allocated_region): New. (class alloca_region): New. (class string_region): New. (is_a_helper <const string_region *>::test): New. (class unknown_region): New. (class region_model_manager): New. (struct append_ssa_names_cb_data): New. (class call_details): New. (region_model::region_model): Add region_model_manager param. (region_model::print_svalue): Delete. (region_model::dump_dot_to_pp): Delete. (region_model::dump_dot_to_file): Delete. (region_model::dump_dot): Delete. (region_model::dump_to_pp): Drop summarize param in favor of simple and multiline. (region_model::dump): Likewise. (region_model::summarize_to_pp): Delete. (region_model::summarize): Delete. (region_model::void canonicalize): Drop ctxt param. (region_model::void check_for_poison): Delete. (region_model::get_gassign_result): New. (region_model::impl_call_alloca): New. (region_model::impl_call_analyzer_describe): New. (region_model::impl_call_analyzer_eval): New. (region_model::impl_call_builtin_expect): New. (region_model::impl_call_calloc): New. (region_model::impl_call_free): New. (region_model::impl_call_malloc): New. (region_model::impl_call_memset): New. (region_model::impl_call_strlen): New. (region_model::get_reachable_svalues): New. (region_model::handle_phi): Drop is_back_edge param. (region_model::region_id get_root_rid): Delete. (region_model::root_region *get_root_region): Delete. (region_model::region_id get_stack_region_id): Delete. (region_model::push_frame): Convert from region_id and svalue_id to const region * and const svalue *. (region_model::get_current_frame_id): Replace with... (region_model::get_current_frame): ...this. (region_model::pop_frame): Convert from region_id to const region *. Drop purge and stats param. Add out_result. (region_model::function *get_function_at_depth): Delete. (region_model::get_globals_region_id): Delete. (region_model::add_svalue): Delete. (region_model::replace_svalue): Delete. (region_model::add_region): Delete. (region_model::add_region_for_type): Delete. (region_model::get_svalue): Delete. (region_model::get_region): Delete. (region_model::get_lvalue): Convert from region_id to const region *. (region_model::get_rvalue): Convert from svalue_id to const svalue *. (region_model::get_or_create_ptr_svalue): Delete. (region_model::get_or_create_constant_svalue): Delete. (region_model::get_svalue_for_fndecl): Delete. (region_model::get_svalue_for_label): Delete. (region_model::get_region_for_fndecl): Delete. (region_model::get_region_for_label): Delete. (region_model::get_frame_at_index (int index) const;): New. (region_model::maybe_cast): Delete. (region_model::maybe_cast_1): Delete. (region_model::get_field_region): Delete. (region_model::id deref_rvalue): Convert from region_id and svalue_id to const region * and const svalue *. Drop overload, passing in both a tree and an svalue. (region_model::set_value): Convert from region_id and svalue_id to const region * and const svalue *. (region_model::set_to_new_unknown_value): Delete. (region_model::clobber_region (const region *reg);): New. (region_model::purge_region (const region *reg);): New. (region_model::zero_fill_region (const region *reg);): New. (region_model::mark_region_as_unknown (const region *reg);): New. (region_model::copy_region): Convert from region_id to const region *. (region_model::eval_condition): Convert from svalue_id to const svalue *. (region_model::eval_condition_without_cm): Likewise. (region_model::compare_initial_and_pointer): New. (region_model:maybe_get_constant): Delete. (region_model::add_new_malloc_region): Delete. (region_model::get_representative_tree): Convert from svalue_id to const svalue *. (region_model::get_representative_path_var): Delete decl taking a region_id in favor of two decls, for svalue vs region, with an svalue_set to ensure termination. (region_model::get_path_vars_for_svalue): Delete. (region_model::create_region_for_heap_alloc): New. (region_model::create_region_for_alloca): New. (region_model::purge_unused_svalues): Delete. (region_model::remap_svalue_ids): Delete. (region_model::remap_region_ids): Delete. (region_model::purge_regions): Delete. (region_model::get_num_svalues): Delete. (region_model::get_num_regions): Delete. (region_model::get_descendents): Delete. (region_model::get_store): New. (region_model::delete_region_and_descendents): Delete. (region_model::get_manager): New. (region_model::unbind_region_and_descendents): New. (region_model::can_merge_with_p): Add point param. Drop svalue_id_merger_mapping. (region_model::get_value_by_name): Delete. (region_model::convert_byte_offset_to_array_index): Delete. (region_model::get_or_create_mem_ref): Delete. (region_model::get_or_create_pointer_plus_expr): Delete. (region_model::get_or_create_view): Delete. (region_model::get_lvalue_1): Convert from region_id to const region *. (region_model::get_rvalue_1): Convert from svalue_id to const svalue *. (region_model::get_ssa_name_regions_for_current_frame): New. (region_model::append_ssa_names_cb): New. (region_model::get_store_value): New. (region_model::copy_struct_region): Delete. (region_model::copy_union_region): Delete. (region_model::copy_array_region): Delete. (region_model::region_exists_p): New. (region_model::make_region_for_unexpected_tree_code): Delete. (region_model::loop_replay_fixup): New. (region_model::poison_any_pointers_to_bad_regions): Delete. (region_model::poison_any_pointers_to_descendents): New. (region_model::dump_summary_of_rep_path_vars): Delete. (region_model::on_top_level_param): New. (region_model::record_dynamic_extents): New. (region_model::m_mgr;): New. (region_model::m_store;): New. (region_model::m_svalues;): Delete. (region_model::m_regions;): Delete. (region_model::m_root_rid;): Delete. (region_model::m_current_frame;): New. (region_model_context::remap_svalue_ids): Delete. (region_model_context::can_purge_p): Delete. (region_model_context::on_svalue_leak): New. (region_model_context::on_svalue_purge): Delete. (region_model_context::on_liveness_change): New. (region_model_context::on_inherited_svalue): Delete. (region_model_context::on_cast): Delete. (region_model_context::on_unknown_change): Convert from svalue_id to const svalue * and add is_mutable. (class noop_region_model_context): Update for region_model_context changes. (model_merger::model_merger): Add program_point. Drop svalue_id_merger_mapping. (model_merger::dump_to_pp): Add "simple" param. (model_merger::dump): Likewise. (model_merger::get_region_a): Delete. (model_merger::get_region_b): Delete. (model_merger::can_merge_values_p): Delete. (model_merger::record_regions): Delete. (model_merger::record_svalues): Delete. (model_merger::m_point): New field. (model_merger::m_map_regions_from_a_to_m): Delete. (model_merger::m_map_regions_from_b_to_m): Delete. (model_merger::m_sid_mapping): Delete. (struct svalue_id_merger_mapping): Delete. (class engine): New. (struct canonicalization): Delete. (inchash::add): Delete decls for hashing svalue_id and region_id. (test_region_model_context::on_unexpected_tree_code): Require t to be non-NULL. (selftest::assert_condition): Add overload comparing a pair of const svalue *. * sm-file.cc: Include "tristate.h", "selftest.h", "analyzer/call-string.h", "analyzer/program-point.h", "analyzer/store.h", and "analyzer/region-model.h". (fileptr_state_machine::get_default_state): New. (fileptr_state_machine::on_stmt): Remove calls to get_readable_tree in favor of get_diagnostic_tree. * sm-malloc.cc: Include "tristate.h", "selftest.h", "analyzer/call-string.h", "analyzer/program-point.h", "analyzer/store.h", and "analyzer/region-model.h". (malloc_state_machine::get_default_state): New. (malloc_state_machine::reset_when_passed_to_unknown_fn_p): New. (malloc_diagnostic::describe_state_change): Handle change.m_expr being NULL. (null_arg::emit): Avoid printing "NULL '0'". (null_arg::describe_final_event): Avoid printing "(0) NULL". (malloc_leak::emit): Handle m_arg being NULL. (malloc_leak::describe_final_event): Handle ev.m_expr being NULL. (malloc_state_machine::on_stmt): Don't call get_readable_tree. Call get_diagnostic_tree when creating pending diagnostics. Update for is_zero_assignment becoming a member function of sm_ctxt. Don't transition to m_non_heap for ADDR_EXPR(MEM_REF()). (malloc_state_machine::reset_when_passed_to_unknown_fn_p): New vfunc implementation. * sm-sensitive.cc (sensitive_state_machine::warn_for_any_exposure): Call get_diagnostic_tree and pass the result to warn_for_state. * sm-signal.cc: Move includes of "analyzer/call-string.h" and "analyzer/program-point.h" to before "analyzer/region-model.h", and also include "analyzer/store.h" before it. (signal_unsafe_call::describe_state_change): Use get_dest_function to get handler. (update_model_for_signal_handler): Pass manager to region_model ctor. (register_signal_handler::impl_transition): Update for changes to get_or_create_node and add_edge. * sm-taint.cc (taint_state_machine::on_stmt): Remove calls to get_readable_tree, replacing them when calling warn_for_state with calls to get_diagnostic_tree. * sm.cc (is_zero_assignment): Delete. (any_pointer_p): Move to within namespace ana. * sm.h (is_zero_assignment): Remove decl. (any_pointer_p): Move decl to within namespace ana. (state_machine::get_default_state): New vfunc. (state_machine::reset_when_passed_to_unknown_fn_p): New vfunc. (sm_context::get_readable_tree): Rename to... (sm_context::get_diagnostic_tree): ...this. (sm_context::is_zero_assignment): New vfunc. * store.cc: New file. * store.h: New file. * svalue.cc: New file. gcc/testsuite/ChangeLog: PR analyzer/93032 PR analyzer/93938 PR analyzer/94011 PR analyzer/94099 PR analyzer/94399 PR analyzer/94458 PR analyzer/94503 PR analyzer/94640 PR analyzer/94688 PR analyzer/94689 PR analyzer/94839 PR analyzer/95026 PR analyzer/95042 PR analyzer/95240 * g++.dg/analyzer/pr93212.C: Add dg-warning for dangling reference. * g++.dg/analyzer/pr93950.C: Remove xfail. * g++.dg/analyzer/pr94011.C: New test. * g++.dg/analyzer/pr94028.C: Remove leak false positives; mark as failing on C++98. * g++.dg/analyzer/pr94503.C: New test. * g++.dg/analyzer/pr95042.C: New test. * gcc.dg/analyzer/CVE-2005-1689-dedupe-issue-2.c: New test. * gcc.dg/analyzer/CVE-2005-1689-dedupe-issue.c: Add xfail. * gcc.dg/analyzer/CVE-2005-1689-minimal.c: Include "analyzer-decls.h". (test_4, test_5, test_6, test_7, test_8): New tests. * gcc.dg/analyzer/abs-1.c: New test. * gcc.dg/analyzer/aliasing-1.c: New test. * gcc.dg/analyzer/aliasing-2.c: New test. * gcc.dg/analyzer/analyzer-decls.h (__analyzer_describe): New decl. (__analyzer_dump_num_heap_regions): Remove. * gcc.dg/analyzer/attribute-nonnull.c: Add dg-warnings for cases where NULL is directly used as an argument. * gcc.dg/analyzer/bzero-1.c: New test. * gcc.dg/analyzer/casts-1.c: New test. * gcc.dg/analyzer/casts-2.c: New test. * gcc.dg/analyzer/compound-assignment-1.c (test_4): Remove xfail from leak false positive. (called_by_test_5a): Add "allocated here" expected message. (called_by_test_5b): Make expected leak message more precise. * gcc.dg/analyzer/compound-assignment-3.c: Update expected leak message. * gcc.dg/analyzer/compound-assignment-4.c: New test. * gcc.dg/analyzer/compound-assignment-5.c: New test. * gcc.dg/analyzer/conditionals-notrans.c: Remove xfails. * gcc.dg/analyzer/data-model-1.c (test_12d): Update expected results. (test_13): Remove xfail. (test_14): Remove xfail. (test_15): Remove xfail. (test_16): Remove xfails. Add out-of-bounds access. (test_16_alt): Remove xfails. (test_23): Remove xfail. (test_24): Remove xfail. (test_25): Remove xfail. (test_26): Update expected result. Remove xfail. Add xfail. (test_27): Remove xfails. (test_29): Add __analyzer_eval pointer comparisons. (test_41): Generalize expected output for u.ptr comparison with NULL for targets where this could be known to be false. (test_42): Remove xfail. (test_51): Remove xfails. * gcc.dg/analyzer/data-model-13.c: Update for improvements to source location and wording of leak message. * gcc.dg/analyzer/data-model-14.c: Remove -fanalyzer-fine-grained. (test_1): Update for improvement to expected message. (test_2): Remove xfail. * gcc.dg/analyzer/data-model-18.c: Remove xfail. * gcc.dg/analyzer/data-model-20.c: New test. * gcc.dg/analyzer/data-model-5.c: Add dg-warning for deref of NULL. Add xfailing false leak. * gcc.dg/analyzer/data-model-5b.c: Add xfailing false leak. * gcc.dg/analyzer/data-model-5c.c: Update xfailing false leak. * gcc.dg/analyzer/data-model-5d.c: Reimplement. * gcc.dg/analyzer/data-model-6.c: Delete test. * gcc.dg/analyzer/data-model-8.c: Remove xfail. * gcc.dg/analyzer/describe-1.c: New test. * gcc.dg/analyzer/dot-output.c: Remove xfail. * gcc.dg/analyzer/explode-1.c: Add expected leak warning. * gcc.dg/analyzer/explode-2.c: Add expected leak warnings. Mark double-free warnings as xfail for now. * gcc.dg/analyzer/feasibility-1.c: New test. * gcc.dg/analyzer/first-field-1.c: New test. * gcc.dg/analyzer/first-field-2.c: New test. * gcc.dg/analyzer/init.c: New test. * gcc.dg/analyzer/leak-2.c: New test. * gcc.dg/analyzer/loop-0-up-to-n-by-1-with-iter-obj.c: New test. * gcc.dg/analyzer/loop-0-up-to-n-by-1.c: New test. * gcc.dg/analyzer/loop-2a.c: Update expected behavior. * gcc.dg/analyzer/loop-3.c: Mark use-after-free as xfail. Add expected warning about deref of unchecked pointer. * gcc.dg/analyzer/loop-4.c: Remove -fno-analyzer-state-purge. Update expected behavior. * gcc.dg/analyzer/loop-n-down-to-1-by-1.c: New test. * gcc.dg/analyzer/loop-start-down-to-end-by-1.c: New test. * gcc.dg/analyzer/loop-start-down-to-end-by-step.c: New test. * gcc.dg/analyzer/loop-start-to-end-by-step.c: New test. * gcc.dg/analyzer/loop-start-up-to-end-by-1.c: New test. * gcc.dg/analyzer/loop.c: Remove -fno-analyzer-state-purge. Update expected behavior. * gcc.dg/analyzer/malloc-1.c: Remove xfails from leak false positives. Update expected wording of global_link.m_ptr leak. (test_49): New test. * gcc.dg/analyzer/malloc-4.c: Remove leak false positive. Update expected wording of leak warning. * gcc.dg/analyzer/malloc-in-loop.c: New test. * gcc.dg/analyzer/malloc-ipa-8-double-free.c: Update expected path to show call to wrapped_malloc. * gcc.dg/analyzer/malloc-ipa-8-unchecked.c: Remove -fanalyzer-verbose-state-changes. * gcc.dg/analyzer/malloc-paths-9.c: Remove comment about duplicate warnings. Remove duplicate use-after-free paths. * gcc.dg/analyzer/malloc-vs-local-1a.c: Add dg-warning for deref of unchecked pointer. Update expected number of enodes. * gcc.dg/analyzer/malloc-vs-local-2.c: Likewise. * gcc.dg/analyzer/malloc-vs-local-3.c: Add dg-warning for deref of unchecked pointer. Update expected number of enodes. Avoid overspecifying the leak message. * gcc.dg/analyzer/memset-1.c: New test. * gcc.dg/analyzer/paths-3.c: Update expected number of enodes. * gcc.dg/analyzer/paths-4.c: Likewise. * gcc.dg/analyzer/paths-6.c: Likewise. * gcc.dg/analyzer/paths-7.c: Likewise. * gcc.dg/analyzer/pr93032-mztools-simplified.c: New test. * gcc.dg/analyzer/pr93032-mztools.c: New test. * gcc.dg/analyzer/pr93382.c: Mark taint tests as failing. * gcc.dg/analyzer/pr93938.c: New test. * gcc.dg/analyzer/pr94099.c: Replace uninit dg-warning with dg-warning for NULL dereference. * gcc.dg/analyzer/pr94399.c: New test. * gcc.dg/analyzer/pr94447.c: Add dg-warning for NULL dereference. * gcc.dg/analyzer/pr94458.c: New test. * gcc.dg/analyzer/pr94640.c: New test. * gcc.dg/analyzer/pr94688.c: New test. * gcc.dg/analyzer/pr94689.c: New test. * gcc.dg/analyzer/pr94839.c: New test. * gcc.dg/analyzer/pr95026.c: New test. * gcc.dg/analyzer/pr95240.c: New test. * gcc.dg/analyzer/refcounting-1.c: New test. * gcc.dg/analyzer/single-field.c: New test. * gcc.dg/analyzer/stale-frame-1.c: New test. * gcc.dg/analyzer/symbolic-1.c: New test. * gcc.dg/analyzer/symbolic-2.c: New test. * gcc.dg/analyzer/symbolic-3.c: New test. * gcc.dg/analyzer/symbolic-4.c: New test. * gcc.dg/analyzer/symbolic-5.c: New test. * gcc.dg/analyzer/symbolic-6.c: New test. * gcc.dg/analyzer/taint-1.c: Mark the "gets unchecked value" events as failing for now. Update dg-message directives to avoid relying on numbering. * gcc.dg/analyzer/torture/loop-inc-ptr-1.c: New test. * gcc.dg/analyzer/torture/loop-inc-ptr-2.c: New test. * gcc.dg/analyzer/torture/loop-inc-ptr-3.c: New test. * gcc.dg/analyzer/unknown-fns-2.c: New test. * gcc.dg/analyzer/unknown-fns-3.c: New test. * gcc.dg/analyzer/unknown-fns-4.c: New test. * gcc.dg/analyzer/unknown-fns.c: Update dg-warning to reflect fixed source location for leak diagnostic. * gcc.dg/analyzer/use-after-free.c: New test. * gcc.dg/analyzer/vla-1.c: New test. * gcc.dg/analyzer/zlib-4.c: Rewrite to avoid "exit" calls. Add expected leak warnings. * gfortran.dg/analyzer/pr93993.f90: Remove leak of tm warning, which seems to have been a false positive.
2020-02-05analyzer: add enode status and revamp __analyzer_dump_exploded_nodesDavid Malcolm1-4/+12
The analyzer recognizes __analyzer_dump_exploded_nodes as a "magic" function for use in DejaGnu tests: at the end of the pass, it issues a warning at each such call, dumping the count of exploded nodes seen at the call, which can be checked in test cases via dg-warning directives, along with the IDs of the enodes (which is helpful when debugging). My intent was to give a way of testing the results of the state-merging code. The state-merging code can generate duplicate exploded nodes at a point when state merging occurs, taking a pair of enodes from the worklist that share a program_point and sufficiently similar state. For these cases it generates a merged state, and adds edges from those enodes to the merged-state enode (potentially a new or a pre-existing enode); the input enodes don't have process_node called on them. This means that at a CFG join point there can be an unpredictable number of enodes that we don't care about, where the precise number depends on the details of the state-merger code, immediately followed by a more predictable number that we do care about. I've been papering over this in the analyzer DejaGnu tests somewhat by adding pairs of __analyzer_dump_exploded_nodes calls at CFG join points, where the output at the first call is somewhat arbitrary, and the second has the number we care about; the first number tends to change "at random" as I tweak the state merging code, in ways that aren't interesting, but require the tests to be updated. See e.g. gcc.dg/analyzer/paths-6.c which had: __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" } */ // FIXME: the above can vary between 2 and 3 exploded nodes __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 exploded node" } */ This patch remedies this situation by tracking which enodes are processed, and which are merely "merger" enodes. It updates the output for __analyzer_dump_exploded_nodes so that count of enodes only includes the *processed* enodes, and that the IDs are split into "processed" and "merger" enodes. The patch simplifies the testsuite by eliminating the redundant calls described above; the example above becomes: __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ where the output in question is now: warning: 1 processed enode: [EN: 94] merger(s): [EN: 93] The patch also adds various checks on the status of enodes, to ensure e.g. that each enode is processed at most once. gcc/analyzer/ChangeLog: * engine.cc (exploded_node::dump_dot): Show merger enodes. (worklist::add_node): Assert that the node's m_status is STATUS_WORKLIST. (exploded_graph::process_worklist): Likewise for nodes from the worklist. Set status of merged nodes to STATUS_MERGER. (exploded_graph::process_node): Set status of node to STATUS_PROCESSED. (exploded_graph::dump_exploded_nodes): Rework handling of "__analyzer_dump_exploded_nodes", splitting enodes by status into "processed" and "merger", showing the count of just the processed enodes at the call, rather than the count of all enodes. * exploded-graph.h (exploded_node::status): New enum. (exploded_node::exploded_node): Initialize m_status to STATUS_WORKLIST. (exploded_node::get_status): New getter. (exploded_node::set_status): New setter. (exploded_node::m_status): New field. gcc/ChangeLog: * doc/analyzer.texi (Special Functions for Debugging the Analyzer): Update description of __analyzer_dump_exploded_nodes. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/data-model-1.c: Update for changed output to __analyzer_dump_exploded_nodes, dropping redundant call at merger. * gcc.dg/analyzer/data-model-7.c: Likewise. * gcc.dg/analyzer/loop-2.c: Update for changed output format. * gcc.dg/analyzer/loop-2a.c: Likewise. * gcc.dg/analyzer/loop-4.c: Likewise. * gcc.dg/analyzer/loop.c: Likewise. * gcc.dg/analyzer/malloc-paths-10.c: Likewise; drop redundant call at merger. * gcc.dg/analyzer/malloc-vs-local-1a.c: Likewise. * gcc.dg/analyzer/malloc-vs-local-1b.c: Likewise. * gcc.dg/analyzer/malloc-vs-local-2.c: Likewise. * gcc.dg/analyzer/malloc-vs-local-3.c: Likewise. * gcc.dg/analyzer/paths-1.c: Likewise. * gcc.dg/analyzer/paths-1a.c: Likewise. * gcc.dg/analyzer/paths-2.c: Likewise. * gcc.dg/analyzer/paths-3.c: Likewise. * gcc.dg/analyzer/paths-4.c: Update for changed output format. * gcc.dg/analyzer/paths-5.c: Likewise. * gcc.dg/analyzer/paths-6.c: Likewise; drop redundant calls at merger. * gcc.dg/analyzer/paths-7.c: Likewise. * gcc.dg/analyzer/torture/conditionals-2.c: Update for changed output format. * gcc.dg/analyzer/zlib-1.c: Likewise; drop redundant calls. * gcc.dg/analyzer/zlib-5.c: Update for changed output format.
2020-01-30analyzer: fix ICE in __builtin_isnan (PR 93356)David Malcolm1-0/+2
PR analyzer/93356 reports an ICE handling __builtin_isnan due to a failing assertion: 674 gcc_assert (lhs_ec_id != rhs_ec_id); with op=UNORDERED_EXPR. when attempting to add an UNORDERED_EXPR constraint. This is an overzealous assertion, but underlying it are various forms of sloppiness regarding NaN within the analyzer: (a) the assumption in the constraint_manager that equivalence classes are reflexive (X == X), which isn't the case for NaN. (b) Hardcoding the "honor_nans" param to false when calling invert_tree_comparison throughout the analyzer. (c) Ignoring ORDERED_EXPR, UNORDERED_EXPR, and the UN-prefixed comparison codes. I wrote a patch for this which tracks the NaN-ness of floating-point values and uses this to address all of the above. However, to minimize changes in gcc 10 stage 4, here's a simpler patch which rejects attempts to query or add constraints on floating-point values, instead treating any floating-point comparison as "unknown", and silently dropping the constraints at edges. gcc/analyzer/ChangeLog: PR analyzer/93356 * region-model.cc (region_model::eval_condition): In both overloads, bail out immediately on floating-point types. (region_model::eval_condition_without_cm): Likewise. (region_model::add_constraint): Likewise. gcc/testsuite/ChangeLog: PR analyzer/93356 * gcc.dg/analyzer/conditionals-notrans.c (test_float_selfcmp): Add. * gcc.dg/analyzer/conditionals-trans.c: Mark floating point comparison test as failing. (test_float_selfcmp): Add. * gcc.dg/analyzer/data-model-1.c: Mark floating point comparison tests as failing. * gcc.dg/analyzer/torture/pr93356.c: New test. gcc/ChangeLog: PR analyzer/93356 * doc/analyzer.texi (Limitations): Note that constraints on floating-point values are currently ignored.
2020-01-17analyzer: prevent ICE on isnan (PR 93290)David Malcolm1-0/+3
PR analyzer/93290 reports an ICE on calls to isnan(). The root cause is that an UNORDERED_EXPR is passed to region_model::eval_condition_without_cm, and there's a stray gcc_unreachable () in the case where we're comparing an svalue against itself. I attempted a more involved patch that properly handled NaN in general but it seems I've baked the assumption of reflexivity too deeply into the constraint_manager code. For now, this patch avoids the ICE and documents the limitation. gcc/analyzer/ChangeLog: PR analyzer/93290 * region-model.cc (region_model::eval_condition_without_cm): Avoid gcc_unreachable for unexpected operations for the case where we're comparing an svalue against itself. gcc/ChangeLog * doc/analyzer.texi (Limitations): Add note about NaN. gcc/testsuite/ChangeLog: PR analyzer/93290 * gcc.dg/analyzer/pr93290.c: New test.
2020-01-15analyzer: add note about -fdump-ipa-analyzer to internal docsDavid Malcolm1-0/+2
gcc/ChangeLog: * doc/analyzer.texi (Overview): Add note about -fdump-ipa-analyzer.
2020-01-14Initial commit of analyzerDavid Malcolm1-0/+513
This patch adds a static analysis pass to the middle-end, focusing for this release on C code, and malloc/free issues in particular. See: https://gcc.gnu.org/wiki/DavidMalcolm/StaticAnalyzer gcc/ChangeLog: * Makefile.in (lang_opt_files): Add analyzer.opt. (ANALYZER_OBJS): New. (OBJS): Add digraph.o, graphviz.o, ordered-hash-map-tests.o, tristate.o and ANALYZER_OBJS. (TEXI_GCCINT_FILES): Add analyzer.texi. * common.opt (-fanalyzer): New driver option. * config.in: Regenerate. * configure: Regenerate. * configure.ac (--disable-analyzer, ENABLE_ANALYZER): New option. (gccdepdir): Also create depdir for "analyzer" subdir. * digraph.cc: New file. * digraph.h: New file. * doc/analyzer.texi: New file. * doc/gccint.texi ("Static Analyzer") New menu item. (analyzer.texi): Include it. * doc/invoke.texi ("Static Analyzer Options"): New list and new section. ("Warning Options"): Add static analysis warnings to the list. (-Wno-analyzer-double-fclose): New option. (-Wno-analyzer-double-free): New option. (-Wno-analyzer-exposure-through-output-file): New option. (-Wno-analyzer-file-leak): New option. (-Wno-analyzer-free-of-non-heap): New option. (-Wno-analyzer-malloc-leak): New option. (-Wno-analyzer-possible-null-argument): New option. (-Wno-analyzer-possible-null-dereference): New option. (-Wno-analyzer-null-argument): New option. (-Wno-analyzer-null-dereference): New option. (-Wno-analyzer-stale-setjmp-buffer): New option. (-Wno-analyzer-tainted-array-index): New option. (-Wno-analyzer-use-after-free): New option. (-Wno-analyzer-use-of-pointer-in-stale-stack-frame): New option. (-Wno-analyzer-use-of-uninitialized-value): New option. (-Wanalyzer-too-complex): New option. (-fanalyzer-call-summaries): New warning. (-fanalyzer-checker=): New warning. (-fanalyzer-fine-grained): New warning. (-fno-analyzer-state-merge): New warning. (-fno-analyzer-state-purge): New warning. (-fanalyzer-transitivity): New warning. (-fanalyzer-verbose-edges): New warning. (-fanalyzer-verbose-state-changes): New warning. (-fanalyzer-verbosity=): New warning. (-fdump-analyzer): New warning. (-fdump-analyzer-callgraph): New warning. (-fdump-analyzer-exploded-graph): New warning. (-fdump-analyzer-exploded-nodes): New warning. (-fdump-analyzer-exploded-nodes-2): New warning. (-fdump-analyzer-exploded-nodes-3): New warning. (-fdump-analyzer-supergraph): New warning. * doc/sourcebuild.texi (dg-require-dot): New. (dg-check-dot): New. * gdbinit.in (break-on-saved-diagnostic): New command. * graphviz.cc: New file. * graphviz.h: New file. * ordered-hash-map-tests.cc: New file. * ordered-hash-map.h: New file. * passes.def (pass_analyzer): Add before pass_ipa_whole_program_visibility. * selftest-run-tests.c (selftest::run_tests): Call selftest::ordered_hash_map_tests_cc_tests. * selftest.h (selftest::ordered_hash_map_tests_cc_tests): New decl. * shortest-paths.h: New file. * timevar.def (TV_ANALYZER): New timevar. (TV_ANALYZER_SUPERGRAPH): Likewise. (TV_ANALYZER_STATE_PURGE): Likewise. (TV_ANALYZER_PLAN): Likewise. (TV_ANALYZER_SCC): Likewise. (TV_ANALYZER_WORKLIST): Likewise. (TV_ANALYZER_DUMP): Likewise. (TV_ANALYZER_DIAGNOSTICS): Likewise. (TV_ANALYZER_SHORTEST_PATHS): Likewise. * tree-pass.h (make_pass_analyzer): New decl. * tristate.cc: New file. * tristate.h: New file. gcc/analyzer/ChangeLog: * ChangeLog: New file. * analyzer-selftests.cc: New file. * analyzer-selftests.h: New file. * analyzer.opt: New file. * analysis-plan.cc: New file. * analysis-plan.h: New file. * analyzer-logging.cc: New file. * analyzer-logging.h: New file. * analyzer-pass.cc: New file. * analyzer.cc: New file. * analyzer.h: New file. * call-string.cc: New file. * call-string.h: New file. * checker-path.cc: New file. * checker-path.h: New file. * constraint-manager.cc: New file. * constraint-manager.h: New file. * diagnostic-manager.cc: New file. * diagnostic-manager.h: New file. * engine.cc: New file. * engine.h: New file. * exploded-graph.h: New file. * pending-diagnostic.cc: New file. * pending-diagnostic.h: New file. * program-point.cc: New file. * program-point.h: New file. * program-state.cc: New file. * program-state.h: New file. * region-model.cc: New file. * region-model.h: New file. * sm-file.cc: New file. * sm-malloc.cc: New file. * sm-malloc.dot: New file. * sm-pattern-test.cc: New file. * sm-sensitive.cc: New file. * sm-signal.cc: New file. * sm-taint.cc: New file. * sm.cc: New file. * sm.h: New file. * state-purge.cc: New file. * state-purge.h: New file. * supergraph.cc: New file. * supergraph.h: New file. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/CVE-2005-1689-minimal.c: New test. * gcc.dg/analyzer/abort.c: New test. * gcc.dg/analyzer/alloca-leak.c: New test. * gcc.dg/analyzer/analyzer-decls.h: New header. * gcc.dg/analyzer/analyzer-verbosity-0.c: New test. * gcc.dg/analyzer/analyzer-verbosity-1.c: New test. * gcc.dg/analyzer/analyzer-verbosity-2.c: New test. * gcc.dg/analyzer/analyzer.exp: New suite. * gcc.dg/analyzer/attribute-nonnull.c: New test. * gcc.dg/analyzer/call-summaries-1.c: New test. * gcc.dg/analyzer/conditionals-2.c: New test. * gcc.dg/analyzer/conditionals-3.c: New test. * gcc.dg/analyzer/conditionals-notrans.c: New test. * gcc.dg/analyzer/conditionals-trans.c: New test. * gcc.dg/analyzer/data-model-1.c: New test. * gcc.dg/analyzer/data-model-2.c: New test. * gcc.dg/analyzer/data-model-3.c: New test. * gcc.dg/analyzer/data-model-4.c: New test. * gcc.dg/analyzer/data-model-5.c: New test. * gcc.dg/analyzer/data-model-5b.c: New test. * gcc.dg/analyzer/data-model-5c.c: New test. * gcc.dg/analyzer/data-model-5d.c: New test. * gcc.dg/analyzer/data-model-6.c: New test. * gcc.dg/analyzer/data-model-7.c: New test. * gcc.dg/analyzer/data-model-8.c: New test. * gcc.dg/analyzer/data-model-9.c: New test. * gcc.dg/analyzer/data-model-11.c: New test. * gcc.dg/analyzer/data-model-12.c: New test. * gcc.dg/analyzer/data-model-13.c: New test. * gcc.dg/analyzer/data-model-14.c: New test. * gcc.dg/analyzer/data-model-15.c: New test. * gcc.dg/analyzer/data-model-16.c: New test. * gcc.dg/analyzer/data-model-17.c: New test. * gcc.dg/analyzer/data-model-18.c: New test. * gcc.dg/analyzer/data-model-19.c: New test. * gcc.dg/analyzer/data-model-path-1.c: New test. * gcc.dg/analyzer/disabling.c: New test. * gcc.dg/analyzer/dot-output.c: New test. * gcc.dg/analyzer/double-free-lto-1-a.c: New test. * gcc.dg/analyzer/double-free-lto-1-b.c: New test. * gcc.dg/analyzer/double-free-lto-1.h: New header. * gcc.dg/analyzer/equivalence.c: New test. * gcc.dg/analyzer/explode-1.c: New test. * gcc.dg/analyzer/explode-2.c: New test. * gcc.dg/analyzer/factorial.c: New test. * gcc.dg/analyzer/fibonacci.c: New test. * gcc.dg/analyzer/fields.c: New test. * gcc.dg/analyzer/file-1.c: New test. * gcc.dg/analyzer/file-2.c: New test. * gcc.dg/analyzer/function-ptr-1.c: New test. * gcc.dg/analyzer/function-ptr-2.c: New test. * gcc.dg/analyzer/function-ptr-3.c: New test. * gcc.dg/analyzer/gzio-2.c: New test. * gcc.dg/analyzer/gzio-3.c: New test. * gcc.dg/analyzer/gzio-3a.c: New test. * gcc.dg/analyzer/gzio.c: New test. * gcc.dg/analyzer/infinite-recursion.c: New test. * gcc.dg/analyzer/loop-2.c: New test. * gcc.dg/analyzer/loop-2a.c: New test. * gcc.dg/analyzer/loop-3.c: New test. * gcc.dg/analyzer/loop-4.c: New test. * gcc.dg/analyzer/loop.c: New test. * gcc.dg/analyzer/malloc-1.c: New test. * gcc.dg/analyzer/malloc-2.c: New test. * gcc.dg/analyzer/malloc-3.c: New test. * gcc.dg/analyzer/malloc-callbacks.c: New test. * gcc.dg/analyzer/malloc-dce.c: New test. * gcc.dg/analyzer/malloc-dedupe-1.c: New test. * gcc.dg/analyzer/malloc-ipa-1.c: New test. * gcc.dg/analyzer/malloc-ipa-10.c: New test. * gcc.dg/analyzer/malloc-ipa-11.c: New test. * gcc.dg/analyzer/malloc-ipa-12.c: New test. * gcc.dg/analyzer/malloc-ipa-13.c: New test. * gcc.dg/analyzer/malloc-ipa-2.c: New test. * gcc.dg/analyzer/malloc-ipa-3.c: New test. * gcc.dg/analyzer/malloc-ipa-4.c: New test. * gcc.dg/analyzer/malloc-ipa-5.c: New test. * gcc.dg/analyzer/malloc-ipa-6.c: New test. * gcc.dg/analyzer/malloc-ipa-7.c: New test. * gcc.dg/analyzer/malloc-ipa-8-double-free.c: New test. * gcc.dg/analyzer/malloc-ipa-8-lto-a.c: New test. * gcc.dg/analyzer/malloc-ipa-8-lto-b.c: New test. * gcc.dg/analyzer/malloc-ipa-8-lto-c.c: New test. * gcc.dg/analyzer/malloc-ipa-8-lto.h: New test. * gcc.dg/analyzer/malloc-ipa-8-unchecked.c: New test. * gcc.dg/analyzer/malloc-ipa-9.c: New test. * gcc.dg/analyzer/malloc-macro-inline-events.c: New test. * gcc.dg/analyzer/malloc-macro-separate-events.c: New test. * gcc.dg/analyzer/malloc-macro.h: New header. * gcc.dg/analyzer/malloc-many-paths-1.c: New test. * gcc.dg/analyzer/malloc-many-paths-2.c: New test. * gcc.dg/analyzer/malloc-many-paths-3.c: New test. * gcc.dg/analyzer/malloc-paths-1.c: New test. * gcc.dg/analyzer/malloc-paths-10.c: New test. * gcc.dg/analyzer/malloc-paths-2.c: New test. * gcc.dg/analyzer/malloc-paths-3.c: New test. * gcc.dg/analyzer/malloc-paths-4.c: New test. * gcc.dg/analyzer/malloc-paths-5.c: New test. * gcc.dg/analyzer/malloc-paths-6.c: New test. * gcc.dg/analyzer/malloc-paths-7.c: New test. * gcc.dg/analyzer/malloc-paths-8.c: New test. * gcc.dg/analyzer/malloc-paths-9.c: New test. * gcc.dg/analyzer/malloc-vs-local-1a.c: New test. * gcc.dg/analyzer/malloc-vs-local-1b.c: New test. * gcc.dg/analyzer/malloc-vs-local-2.c: New test. * gcc.dg/analyzer/malloc-vs-local-3.c: New test. * gcc.dg/analyzer/malloc-vs-local-4.c: New test. * gcc.dg/analyzer/operations.c: New test. * gcc.dg/analyzer/params-2.c: New test. * gcc.dg/analyzer/params.c: New test. * gcc.dg/analyzer/paths-1.c: New test. * gcc.dg/analyzer/paths-1a.c: New test. * gcc.dg/analyzer/paths-2.c: New test. * gcc.dg/analyzer/paths-3.c: New test. * gcc.dg/analyzer/paths-4.c: New test. * gcc.dg/analyzer/paths-5.c: New test. * gcc.dg/analyzer/paths-6.c: New test. * gcc.dg/analyzer/paths-7.c: New test. * gcc.dg/analyzer/pattern-test-1.c: New test. * gcc.dg/analyzer/pattern-test-2.c: New test. * gcc.dg/analyzer/pointer-merging.c: New test. * gcc.dg/analyzer/pr61861.c: New test. * gcc.dg/analyzer/pragma-1.c: New test. * gcc.dg/analyzer/scope-1.c: New test. * gcc.dg/analyzer/sensitive-1.c: New test. * gcc.dg/analyzer/setjmp-1.c: New test. * gcc.dg/analyzer/setjmp-2.c: New test. * gcc.dg/analyzer/setjmp-3.c: New test. * gcc.dg/analyzer/setjmp-4.c: New test. * gcc.dg/analyzer/setjmp-5.c: New test. * gcc.dg/analyzer/setjmp-6.c: New test. * gcc.dg/analyzer/setjmp-7.c: New test. * gcc.dg/analyzer/setjmp-7a.c: New test. * gcc.dg/analyzer/setjmp-8.c: New test. * gcc.dg/analyzer/setjmp-9.c: New test. * gcc.dg/analyzer/signal-1.c: New test. * gcc.dg/analyzer/signal-2.c: New test. * gcc.dg/analyzer/signal-3.c: New test. * gcc.dg/analyzer/signal-4a.c: New test. * gcc.dg/analyzer/signal-4b.c: New test. * gcc.dg/analyzer/strcmp-1.c: New test. * gcc.dg/analyzer/switch.c: New test. * gcc.dg/analyzer/taint-1.c: New test. * gcc.dg/analyzer/zlib-1.c: New test. * gcc.dg/analyzer/zlib-2.c: New test. * gcc.dg/analyzer/zlib-3.c: New test. * gcc.dg/analyzer/zlib-4.c: New test. * gcc.dg/analyzer/zlib-5.c: New test. * gcc.dg/analyzer/zlib-6.c: New test. * lib/gcc-defs.exp (dg-check-dot): New procedure. * lib/target-supports.exp (check_dot_available): New procedure. (check_effective_target_analyzer): New. * lib/target-supports-dg.exp (dg-require-dot): New procedure.