Age | Commit message (Collapse) | Author | Files | Lines |
|
gcc/analyzer/ChangeLog:
* analyzer.cc (get_stmt_location): Handle null stmt.
* diagnostic-manager.cc (saved_diagnostic::saved_diagnostic): Copy
m_loc from ploc.
(saved_diagnostic::operator==): Compare m_loc.
(saved_diagnostic::calc_best_epath): Only use m_stmt_finder if
m_loc is unknown.
(dedupe_key::dedupe_key): Initialize m_loc.
(dedupe_key::operator==): Compare m_loc.
(dedupe_key::get_location): Use m_loc if it's known.
(dedupe_key::m_loc): New field.
(diagnostic_manager::emit_saved_diagnostic): Only call
get_emission_location if m_loc is unknown, preferring to use m_loc
if it's available.
* diagnostic-manager.h (saved_diagnostic::m_loc): New field.
(pending_location::pending_location): Initialize m_loc. Add
overload taking a location_t rather than a stmt/stmt_finder.
(pending_location::m_loc): New field.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
No functional change intended.
gcc/analyzer/ChangeLog:
* analyzer.h (struct pending_location): New forward decl.
* diagnostic-manager.cc (saved_diagnostic::saved_diagnostic):
Replace params "enode", "snode", "stmt", and "stmt_finder" with
"ploc".
(diagnostic_manager::add_diagnostic): Likewise for both overloads.
* diagnostic-manager.h (saved_diagnostic::saved_diagnostic):
Likewise.
(struct pending_location): New.
(diagnostic_manager::add_diagnostic): Replace params "enode",
"snode", "stmt", and "stmt_finder" with "ploc".
* engine.cc (impl_region_model_context::warn): Update call to
add_diagnostic for above change.
(impl_sm_context::warn): Likewise.
(impl_region_model_context::on_state_leak): Likewise.
* infinite-recursion.cc
(exploded_graph::detect_infinite_recursion): Likewise.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
* diagnostic-manager.cc (saved_diagnostic::add_event): New.
(saved_diagnostic::add_any_saved_events): New.
(diagnostic_manager::add_event): New.
(dedupe_winners::emit_best): New.
(diagnostic_manager::emit_saved_diagnostic): Make "sd" param
non-const. Call saved_diagnostic::add_any_saved_events.
* diagnostic-manager.h (saved_diagnostic::add_event): New decl.
(saved_diagnostic::add_any_saved_events): New decl.
(saved_diagnostic::m_saved_events): New field.
(diagnostic_manager::add_event): New decl.
(diagnostic_manager::emit_saved_diagnostic): Make "sd" param
non-const.
* engine.cc (impl_region_model_context::add_event): New.
* exploded-graph.h (impl_region_model_context::add_event): New decl.
* region-model.cc
(noop_region_model_context::add_event): New.
(region_model_context_decorator::add_event): New.
* region-model.h (region_model_context::add_event): New vfunc.
(noop_region_model_context::add_event): New decl.
(region_model_context_decorator::add_event): New decl.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
This patch introduces -fanalyzer-show-events-in-system-headers,
disabled by default.
This option reduces the noise of the analyzer emitted diagnostics
when dealing with system headers.
The new option only affects the display of the diagnostics,
but doesn't hinder the actual analysis.
Given a diagnostics path diving into a system header in the form
[
prefix events...,
system header call,
system header entry,
events within system headers...,
system header return,
suffix events...
]
then disabling the option (either by default or explicitly)
will shorten the path into:
[
prefix events...,
system header call,
system header return,
suffix events...
]
Signed-off-by: benjamin priour <priour.be@gmail.com>
gcc/analyzer/ChangeLog:
PR analyzer/110543
* analyzer.opt: Add new option.
* diagnostic-manager.cc
(diagnostic_manager::prune_path): Call prune_system_headers.
(prune_frame): New function that deletes all events in a frame.
(diagnostic_manager::prune_system_headers): New function.
* diagnostic-manager.h: Add prune_system_headers declaration.
gcc/ChangeLog:
PR analyzer/110543
* doc/invoke.texi: Add documentation of
fanalyzer-show-events-in-system-headers
gcc/testsuite/ChangeLog:
PR analyzer/110543
* g++.dg/analyzer/fanalyzer-show-events-in-system-headers-default.C:
New test.
* g++.dg/analyzer/fanalyzer-show-events-in-system-headers-no.C:
New test.
* g++.dg/analyzer/fanalyzer-show-events-in-system-headers.C:
New test.
|
|
|
|
In r13-2573-gc81b60b8c6ff3d I split up the analyzer's region-creation
events to describe the memory space and capacity of the region as two
separate events to avoid combinatorial explosion of message wordings.
However I didn't take into account r13-1405-ge6c3bb379f515b which
added a pending_diagnostic::describe_region_creation_event vfunc which
could change the wording of region creation events.
Hence for:
#include <stdlib.h>
#include <stdint.h>
void test ()
{
int32_t *ptr = malloc (1);
free (ptr);
}
trunk currently emits:
Compiler Explorer (x86_64 trunk): https://godbolt.org/z/e3Td7c9s5:
<source>: In function 'test':
<source>:6:18: warning: allocated buffer size is not a multiple of the pointee's size [CWE-131] [-Wanalyzer-allocation-size]
6 | int32_t *ptr = malloc (1);
| ^~~~~~~~~~
'test': events 1-3
|
| 6 | int32_t *ptr = malloc (1);
| | ^~~~~~~~~~
| | |
| | (1) allocated 1 bytes here
| | (2) allocated 1 bytes here
| | (3) assigned to 'int32_t *' {aka 'int *'} here; 'sizeof (int32_t {aka int})' is '4'
|
where events (1) and (2) are different region_creation_events that have
had their wording overridden (also, with a "1 bytes" issue).
This patch reorganizes region creation events so that each
pending_diagnostic instead creates the events that is appropriate for it,
and the events have responsibility for their own wording.
With this patch, the above emits:
<source>: In function 'test':
<source>:6:18: warning: allocated buffer size is not a multiple of the pointee's size [CWE-131] [-Wanalyzer-allocation-size]
6 | int32_t *ptr = malloc (1);
| ^~~~~~~~~~
'test': events 1-2
|
| 6 | int32_t *ptr = malloc (1);
| | ^~~~~~~~~~
| | |
| | (1) allocated 1 byte here
| | (2) assigned to 'int32_t *' {aka 'int *'} here; 'sizeof (int32_t {aka int})' is '4'
|
fixing the duplicate event, and fixing the singular/plural issue.
gcc/analyzer/ChangeLog:
PR analyzer/107851
* analyzer.cc (make_label_text_n): Convert param "n" from int to
unsigned HOST_WIDE_INT.
* analyzer.h (make_label_text_n): Likewise for decl.
* bounds-checking.cc: Include "analyzer/checker-event.h" and
"analyzer/checker-path.h".
(out_of_bounds::add_region_creation_events): New.
(concrete_past_the_end::describe_region_creation_event): Replace
with...
(concrete_past_the_end::add_region_creation_events): ...this.
(symbolic_past_the_end::describe_region_creation_event): Delete.
* checker-event.cc (region_creation_event::region_creation_event):
Update for dropping all member data.
(region_creation_event::get_desc): Delete, splitting out into
region_creation_event_memory_space::get_desc,
region_creation_event_capacity::get_desc, and
region_creation_event_debug::get_desc.
(region_creation_event_memory_space::get_desc): New.
(region_creation_event_capacity::get_desc): New.
(region_creation_event_allocation_size::get_desc): New.
(region_creation_event_debug::get_desc): New.
* checker-event.h: Include "analyzer/program-state.h".
(enum rce_kind): Delete.
(class region_creation_event): Drop all member data.
(region_creation_event::region_creation_event): Make protected.
(region_creation_event::get_desc): Delete.
(class region_creation_event_memory_space): New.
(class region_creation_event_capacity): New.
(class region_creation_event_allocation_size): New.
(class region_creation_event_debug): New.
* checker-path.cc (checker_path::add_region_creation_events): Add
"pd" param. Call pending_diangnostic::add_region_creation_events.
Update for conversion of RCE_DEBUG to region_creation_event_debug.
* checker-path.h (checker_path::add_region_creation_events): Add
"pd" param.
* diagnostic-manager.cc (diagnostic_manager::build_emission_path):
Pass pending_diagnostic to
emission_path::add_region_creation_events.
(diagnostic_manager::build_emission_path): Pass path_builder to
add_event_on_final_node.
(diagnostic_manager::add_event_on_final_node): Add "pb" param.
Pass pending_diagnostic to
emission_path::add_region_creation_events.
(diagnostic_manager::add_events_for_eedge): Pass
pending_diagnostic to emission_path::add_region_creation_events.
* diagnostic-manager.h
(diagnostic_manager::add_event_on_final_node): Add "pb" param.
* pending-diagnostic.cc
(pending_diagnostic::add_region_creation_events): New.
* pending-diagnostic.h (struct region_creation): Delete.
(pending_diagnostic::describe_region_creation_event): Delete.
(pending_diagnostic::add_region_creation_events): New vfunc.
* region-model.cc: Include "analyzer/checker-event.h" and
"analyzer/checker-path.h".
(dubious_allocation_size::dubious_allocation_size): Initialize
m_has_allocation_event.
(dubious_allocation_size::describe_region_creation_event): Delete.
(dubious_allocation_size::describe_final_event): Update for
replacement of m_allocation_event with m_has_allocation_event.
(dubious_allocation_size::add_region_creation_events): New.
(dubious_allocation_size::m_allocation_event): Replace with...
(dubious_allocation_size::m_has_allocation_event): ...this.
gcc/testsuite/ChangeLog:
PR analyzer/107851
* gcc.dg/analyzer/allocation-size-4.c: Update expected wording.
* gcc.dg/analyzer/allocation-size-multiline-1.c: New test.
* gcc.dg/analyzer/allocation-size-multiline-2.c: New test.
* gcc.dg/analyzer/out-of-bounds-multiline-1.c: Update expected
wording.
* gcc.dg/analyzer/out-of-bounds-multiline-2.c: New test.
* gcc.dg/analyzer/out-of-bounds-read-char-arr.c: Update expected
wording.
* gcc.dg/analyzer/out-of-bounds-read-int-arr.c: Likewise.
* gcc.dg/analyzer/out-of-bounds-write-char-arr.c: Likewise.
* gcc.dg/analyzer/out-of-bounds-write-int-arr.c: Likewise.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
* diagnostic-manager.cc: Include "make-unique.h".
Use std::unique_ptr for feasibility_problems and exploded_path.
Delete explicit saved_diagnostic dtor.
* diagnostic-manager.h: Likewise.
* engine.cc: Likewise.
* exploded-graph.h: Likewise.
* feasible-graph.cc: Likewise.
* feasible-graph.h: Likewise.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
* diagnostic-manager.cc (saved_diagnostic::saved_diagnostic): Make
stmt_finder const.
(saved_diagnostic::~saved_diagnostic): Remove explicit delete of
m_stmt_finder.
(diagnostic_manager::add_diagnostic): Make stmt_finder const.
* diagnostic-manager.h (saved_diagnostic::saved_diagnostic):
Likewise.
(saved_diagnostic::m_stmt_finder): Convert to std::unique_ptr.
(diagnostic_manager::add_diagnostic): Make stmt_finder const.
* engine.cc (impl_sm_context::impl_sm_context): Likewise.
(impl_sm_context::m_stmt_finder): Likewise.
(leak_stmt_finder::clone): Convert return type to std::unique_ptr.
* exploded-graph.h (stmt_finder::clone): Likewise.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
* call-info.cc: Add define of INCLUDE_MEMORY.
* call-summary.cc: Likewise.
* checker-path.cc: Likewise.
* constraint-manager.cc: Likewise.
* diagnostic-manager.cc: Likewise.
(saved_diagnostic::saved_diagnostic): Use std::unique_ptr for
param d and field m_d.
(saved_diagnostic::~saved_diagnostic): Remove explicit delete of m_d.
(saved_diagnostic::add_note): Use std::unique_ptr for
param pn.
(saved_diagnostic::get_pending_diagnostic): Update for conversion
of m_sd.m_d to unique_ptr.
(diagnostic_manager::add_diagnostic): Use std::unique_ptr for
param d. Remove explicit deletion.
(diagnostic_manager::add_note): Use std::unique_ptr for param pn.
(diagnostic_manager::emit_saved_diagnostic): Update for conversion
of m_sd.m_d to unique_ptr.
(null_assignment_sm_context::warn): Use std::unique_ptr for
param d. Remove explicit deletion.
* diagnostic-manager.h (saved_diagnostic::saved_diagnostic): Use
std::unique_ptr for param d.
(saved_diagnostic::add_note): Likewise for param pn.
(saved_diagnostic::m_d): Likewise.
(diagnostic_manager::add_diagnostic): Use std::unique_ptr for
param d.
(diagnostic_manager::add_note): Use std::unique_ptr for param pn.
* engine.cc: Include "make-unique.h".
(impl_region_model_context::warn): Update to use std::unique_ptr
for param, removing explicit deletion.
(impl_region_model_context::add_note): Likewise.
(impl_sm_context::warn): Update to use std::unique_ptr
for param.
(impl_region_model_context::on_state_leak): Likewise for result of
on_leak.
(exploded_node::on_longjmp): Use make_unique when creating
pending_diagnostic.
(exploded_graph::process_node): Likewise.
* exploded-graph.h (impl_region_model_context::warn): Update to
use std::unique_ptr for param.
(impl_region_model_context::add_note): Likewise.
* feasible-graph.cc: Add define of INCLUDE_MEMORY.
* pending-diagnostic.cc: Likewise.
* pending-diagnostic.h: Include analyzer.sm.h"
* program-point.cc: Add define of INCLUDE_MEMORY.
* program-state.cc: Likewise.
* region-model-asm.cc: Likewise.
* region-model-impl-calls.cc: Likewise. Include "make-unique.h".
(region_model::impl_call_putenv): Use make_unique when creating
pending_diagnostic.
* region-model-manager.cc: Add define of INCLUDE_MEMORY.
* region-model-reachability.cc: Likewise.
* region-model.cc: Likewise. Include "make-unique.h".
(region_model::get_gassign_result): Use make_unique when creating
pending_diagnostic.
(region_model::check_for_poison): Likewise.
(region_model::on_stmt_pre): Likewise.
(region_model::check_symbolic_bounds): Likewise.
(region_model::check_region_bounds): Likewise.
(annotating_ctxt: make_note): Use std::unique_ptr for result.
(region_model::deref_rvalue): Use make_unique when creating
pending_diagnostic.
(region_model::check_for_writable_region): Likewise.
(region_model::check_region_size): Likewise.
(region_model::check_dynamic_size_for_floats): Likewise.
(region_model::maybe_complain_about_infoleak): Likewise.
(noop_region_model_context::add_note): Use std::unique_ptr for
param. Remove explicit deletion.
* region-model.h: Include "analyzer/pending-diagnostic.h".
(region_model_context::warn): Convert param to std::unique_ptr.
(region_model_context::add_note): Likewise.
(noop_region_model_context::warn): Likewise.
(noop_region_model_context::add_note): Likewise.
(region_model_context_decorator::warn): Likewise.
(region_model_context_decorator::add_note): Likewise.
(note_adding_context::warn): Likewise.
(note_adding_context::make_note): Likewise for return type.
(test_region_model_context::warn): Convert param to
std::unique_ptr.
* region.cc: Add define of INCLUDE_MEMORY.
* sm-fd.cc: Likewise. Include "make-unique.h".
(fd_state_machine::check_for_fd_attrs): Use make_unique when
creating pending_diagnostics.
(fd_state_machine::on_open): Likewise.
(fd_state_machine::on_creat): Likewise.
(fd_state_machine::check_for_dup): Likewise.
(fd_state_machine::on_close): Likewise.
(fd_state_machine::check_for_open_fd): Likewise.
(fd_state_machine::on_leak): Likewise, converting return type to
std::unique_ptr.
* sm-file.cc: Add define of INCLUDE_MEMORY. Include
"make-unique.h".
(fileptr_state_machine::on_stmt): Use make_unique when creating
pending_diagnostic.
(fileptr_state_machine::on_leak): Likewise, converting return type
to std::unique_ptr.
* sm-malloc.cc: Add define of INCLUDE_MEMORY. Include
"make-unique.h".
(malloc_state_machine::on_stmt): Use make_unique when creating
pending_diagnostic.
(malloc_state_machine::handle_free_of_non_heap): Likewise.
(malloc_state_machine::on_deallocator_call): Likewise.
(malloc_state_machine::on_realloc_call): Likewise.
(malloc_state_machine::on_leak): Likewise, converting return type
to std::unique_ptr.
* sm-pattern-test.cc: Add define of INCLUDE_MEMORY. Include
"make-unique.h".
(pattern_test_state_machine::on_condition): Use make_unique when
creating pending_diagnostic.
* sm-sensitive.cc: Add define of INCLUDE_MEMORY. Include
"make-unique.h".
(sensitive_state_machine::warn_for_any_exposure): Use make_unique
when creating pending_diagnostic.
* sm-signal.cc: Add define of INCLUDE_MEMORY. Include
"make-unique.h".
(signal_state_machine::on_stmt): Use make_unique when creating
pending_diagnostic.
* sm-taint.cc: Add define of INCLUDE_MEMORY. Include
"make-unique.h".
(taint_state_machine::check_for_tainted_size_arg): Use make_unique
when creating pending_diagnostic.
(taint_state_machine::check_for_tainted_divisor): Likewise.
(region_model::check_region_for_taint): Likewise.
(region_model::check_dynamic_size_for_taint): Likewise.
* sm.cc: Add define of INCLUDE_MEMORY. Include
"analyzer/pending-diagnostic.h".
(state_machine::on_leak): Move here from sm.h, changing return
type to std::unique_ptr.
* sm.h (state_machine::on_leak): Change return type to
std::unique_ptr. Move defn of base impl to sm.cc
(sm_context::warn): Convert param d to std_unique_ptr.
* state-purge.cc: Add define of INCLUDE_MEMORY.
* store.cc: Likewise.
* svalue.cc: Likewise.
* trimmed-graph.cc: Likewise.
* varargs.cc: Likewise. Include "make-unique.h".
(va_list_state_machine::check_for_ended_va_list): Use make_unique
when creating pending_diagnostic.
(va_list_state_machine::on_leak): Likewise, converting return type
to std::unique_ptr.
(region_model::impl_call_va_arg): Use make_unique when creating
pending_diagnostic.
gcc/testsuite/ChangeLog:
* gcc.dg/plugin/analyzer_gil_plugin.c: Add define of
INCLUDE_MEMORY. Include "make-unique.h".
(gil_state_machine::check_for_pyobject_in_call): Use make_unique
when creating pending_diagnostic.
(gil_state_machine::on_stmt): Likewise.
(gil_state_machine::check_for_pyobject_usage_without_gil): Likewise.
* gcc.dg/plugin/analyzer_kernel_plugin.c: : Add define of
INCLUDE_MEMORY.
* gcc.dg/plugin/analyzer_known_fns_plugin.c: Likewise.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
This patch adds an checker that warns about code paths in which a buffer
is assigned to a incompatible type, i.e. when the allocated buffer size
is not a multiple of the pointee's size.
Regression-tested on x86_64 Linux. Also compiled coreutils, curl, openssh and
httpd with the patch enabled.
2022-07-01 Tim Lange <mail@tim-lange.me>
gcc/analyzer/ChangeLog:
PR analyzer/105900
* analyzer.opt: Added Wanalyzer-allocation-size.
* checker-path.cc (region_creation_event::get_desc): Added call to new
virtual function pending_diagnostic::describe_region_creation_event.
* checker-path.h: Added region_creation_event::get_desc.
* diagnostic-manager.cc (diagnostic_manager::add_event_on_final_node):
New function.
* diagnostic-manager.h:
Added diagnostic_manager::add_event_on_final_node.
* pending-diagnostic.h (struct region_creation): New event_desc struct.
(pending_diagnostic::describe_region_creation_event): Added virtual
function to overwrite description of a region creation.
* region-model.cc (class dubious_allocation_size): New class.
(capacity_compatible_with_type): New helper function.
(class size_visitor): New class.
(struct_or_union_with_inheritance_p): New helper function.
(is_any_cast_p): New helper function.
(region_model::check_region_size): New function.
(region_model::set_value): Added call to
region_model::check_region_size.
* region-model.h (class region_model): New function check_region_size.
* svalue.cc (region_svalue::accept): Changed to post-order traversal.
(initial_svalue::accept): Likewise.
(unaryop_svalue::accept): Likewise.
(binop_svalue::accept): Likewise.
(sub_svalue::accept): Likewise.
(repeated_svalue::accept): Likewise.
(bits_within_svalue::accept): Likewise.
(widening_svalue::accept): Likewise.
(unmergeable_svalue::accept): Likewise.
(compound_svalue::accept): Likewise.
(conjured_svalue::accept): Likewise.
(asm_output_svalue::accept): Likewise.
(const_fn_result_svalue::accept): Likewise.
gcc/ChangeLog:
PR analyzer/105900
* doc/invoke.texi: Added Wanalyzer-allocation-size.
gcc/testsuite/ChangeLog:
PR analyzer/105900
* gcc.dg/analyzer/pr96639.c: Changed buffer size to omit warning.
* gcc.dg/analyzer/allocation-size-1.c: New test.
* gcc.dg/analyzer/allocation-size-2.c: New test.
* gcc.dg/analyzer/allocation-size-3.c: New test.
* gcc.dg/analyzer/allocation-size-4.c: New test.
* gcc.dg/analyzer/allocation-size-5.c: New test.
Signed-off-by: Tim Lange <mail@tim-lange.me>
|
|
I've been using this tweak to the output of
-fdump-analyzer-exploded-graph in my working copies for a while;
the extra red nodes make it *much* easier to find the places where
diagnostics are being emitted (or rejected by the diagnostic_manager).
gcc/analyzer/ChangeLog:
* diagnostic-manager.cc (saved_diagnostic::dump_dot_id): New.
(saved_diagnostic::dump_as_dot_node): New.
* diagnostic-manager.h (saved_diagnostic::dump_dot_id): New decl.
(saved_diagnostic::dump_as_dot_node): New decl.
* engine.cc (exploded_node::dump_dot): Add nodes for saved
diagnostics.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
PR analyzer/104997
* diagnostic-manager.cc (diagnostic_manager::add_diagnostic):
Convert return type from "void" to "bool", reporting success vs
failure to caller, for both overloads.
* diagnostic-manager.h (diagnostic_manager::add_diagnostic):
Likewise.
* engine.cc (impl_region_model_context::warn): Propagate return
value from diagnostic_manager::add_diagnostic.
gcc/testsuite/ChangeLog:
PR analyzer/104997
* gcc.dg/analyzer/write-to-string-literal-4-disabled.c: New test,
adapted from write-to-string-literal-4.c.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
Avoid generating execution paths for warnings that are ultimately
rejected due to -Wno-analyzer-* flags.
This improves the test case from taking at least several minutes
(before I killed it) to taking under a second.
This doesn't fix the slowdown seen in PR analyzer/104955 with large
numbers of warnings when the warnings are still enabled.
gcc/analyzer/ChangeLog:
PR analyzer/104955
* diagnostic-manager.cc (get_emission_location): New.
(diagnostic_manager::diagnostic_manager): Initialize
m_num_disabled_diagnostics.
(diagnostic_manager::add_diagnostic): Reject diagnostics that
will eventually be rejected due to being disabled.
(diagnostic_manager::emit_saved_diagnostics): Log the number
of disabled diagnostics.
(diagnostic_manager::emit_saved_diagnostic): Split out logic for
determining emission location to get_emission_location.
* diagnostic-manager.h
(diagnostic_manager::m_num_disabled_diagnostics): New field.
* engine.cc (stale_jmp_buf::get_controlling_option): New.
(stale_jmp_buf::emit): Use it.
* pending-diagnostic.h
(pending_diagnostic::get_controlling_option): New vfunc.
* region-model.cc
(poisoned_value_diagnostic::get_controlling_option): New.
(poisoned_value_diagnostic::emit): Use it.
(shift_count_negative_diagnostic::get_controlling_option): New.
(shift_count_negative_diagnostic::emit): Use it.
(shift_count_overflow_diagnostic::get_controlling_option): New.
(shift_count_overflow_diagnostic::emit): Use it.
(dump_path_diagnostic::get_controlling_option): New.
(dump_path_diagnostic::emit): Use it.
(write_to_const_diagnostic::get_controlling_option): New.
(write_to_const_diagnostic::emit): Use it.
(write_to_string_literal_diagnostic::get_controlling_option): New.
(write_to_string_literal_diagnostic::emit): Use it.
* sm-file.cc (double_fclose::get_controlling_option): New.
(double_fclose::emit): Use it.
(file_leak::get_controlling_option): New.
(file_leak::emit): Use it.
* sm-malloc.cc (mismatching_deallocation::get_controlling_option):
New.
(mismatching_deallocation::emit): Use it.
(double_free::get_controlling_option): New.
(double_free::emit): Use it.
(possible_null_deref::get_controlling_option): New.
(possible_null_deref::emit): Use it.
(possible_null_arg::get_controlling_option): New.
(possible_null_arg::emit): Use it.
(null_deref::get_controlling_option): New.
(null_deref::emit): Use it.
(null_arg::get_controlling_option): New.
(null_arg::emit): Use it.
(use_after_free::get_controlling_option): New.
(use_after_free::emit): Use it.
(malloc_leak::get_controlling_option): New.
(malloc_leak::emit): Use it.
(free_of_non_heap::get_controlling_option): New.
(free_of_non_heap::emit): Use it.
* sm-pattern-test.cc (pattern_match::get_controlling_option): New.
(pattern_match::emit): Use it.
* sm-sensitive.cc
(exposure_through_output_file::get_controlling_option): New.
(exposure_through_output_file::emit): Use it.
* sm-signal.cc (signal_unsafe_call::get_controlling_option): New.
(signal_unsafe_call::emit): Use it.
* sm-taint.cc (tainted_array_index::get_controlling_option): New.
(tainted_array_index::emit): Use it.
(tainted_offset::get_controlling_option): New.
(tainted_offset::emit): Use it.
(tainted_size::get_controlling_option): New.
(tainted_size::emit): Use it.
(tainted_divisor::get_controlling_option): New.
(tainted_divisor::emit): Use it.
(tainted_allocation_size::get_controlling_option): New.
(tainted_allocation_size::emit): Use it.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/many-disabled-diagnostics.c: New test.
* gcc.dg/plugin/analyzer_gil_plugin.c
(gil_diagnostic::get_controlling_option): New.
(double_save_thread::emit): Use it.
(fncall_without_gil::emit): Likewise.
(pyobject_usage_without_gil::emit): Likewise.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
The previous patch extended
-Wanalyzer-write-to-const
-Wanalyzer-write-to-string-literal
to make use of __attribute__ ((access, ....), but the results could be
inscrutable.
This patch adds notes to such diagnostics to give the user a reason for
why the analyzer is complaining.
Example output:
test.c: In function 'main':
test.c:15:13: warning: write to string literal [-Wanalyzer-write-to-string-literal]
15 | if (getrandom((char *)test, sizeof(buf), GRND_RANDOM))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'main': event 1
|
| 15 | if (getrandom((char *)test, sizeof(buf), GRND_RANDOM))
| | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (1) write to string literal here
|
test.c:3:5: note: parameter 1 of 'getrandom' marked with attribute 'access (write_only, 1, 2)'
3 | int getrandom (void *__buffer, size_t __length,
| ^~~~~~~~~
Unfortunately we don't have location information for the attributes
themselves, just the function declaration, and there doesn't seem to be
a good way of getting at the location of the individual parameters from
the middle end (the C and C++ FEs both have get_fndecl_argument_location,
but the implementations are different).
gcc/analyzer/ChangeLog:
PR analyzer/104793
* analyzer.h (class pending_note): New forward decl.
* diagnostic-manager.cc (saved_diagnostic::saved_diagnostic):
Initialize m_notes.
(saved_diagnostic::operator==): Compare m_notes.
(saved_diagnostic::add_note): New.
(saved_diagnostic::emit_any_notes): New.
(diagnostic_manager::add_note): New.
(diagnostic_manager::emit_saved_diagnostic): Call emit_any_notes
after emitting the warning.
* diagnostic-manager.h (saved_diagnostic::add_note): New decl.
(saved_diagnostic::emit_any_notes): New decl.
(saved_diagnostic::m_notes): New field.
(diagnostic_manager::add_note): New decl.
* engine.cc (impl_region_model_context::add_note): New.
* exploded-graph.h (impl_region_model_context::add_note): New
decl.
* pending-diagnostic.h (class pending_note): New.
(class pending_note_subclass): New template.
* region-model.cc (class reason_attr_access): New.
(check_external_function_for_access_attr): Add class
annotating_ctxt and use it when checking region.
(noop_region_model_context::add_note): New.
* region-model.h (region_model_context::add_note): New vfunc.
(noop_region_model_context::add_note): New decl.
(class region_model_context_decorator): New.
(class note_adding_context): New.
gcc/testsuite/ChangeLog:
PR analyzer/104793
* gcc.dg/analyzer/write-to-const-2.c: Add dg-message directives
for expected notes.
* gcc.dg/analyzer/write-to-function-1.c: Likewise.
* gcc.dg/analyzer/write-to-string-literal-2.c: Likewise.
* gcc.dg/analyzer/write-to-string-literal-3.c: Likewise.
* gcc.dg/analyzer/write-to-string-literal-4.c: Likewise.
* gcc.dg/analyzer/write-to-string-literal-5.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
When reviewing the output of -fanalyzer on PR analyzer/104224 I noticed
that despite very verbose paths, the diagnostic paths for
-Wanalyzer-use-of-uninitialized-value
don't show where the uninitialized memory is allocated.
This patch adapts and simplifies material from
"[PATCH 3/6] analyzer: implement infoleak detection"
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/584377.html
in order to add region creation events for the pertinent region (whether
on the stack or heap).
For example, this patch extends:
malloc-1.c: In function 'test_40':
malloc-1.c:461:5: warning: use of uninitialized value '*p' [CWE-457] [-Wanalyzer-use-of-uninitialized-value]
461 | i = *p;
| ~~^~~~
'test_40': event 1
|
| 461 | i = *p;
| | ~~^~~~
| | |
| | (1) use of uninitialized value '*p' here
|
to:
malloc-1.c: In function 'test_40':
malloc-1.c:461:5: warning: use of uninitialized value '*p' [CWE-457] [-Wanalyzer-use-of-uninitialized-value]
461 | i = *p;
| ~~^~~~
'test_40': events 1-2
|
| 460 | int *p = (int*)malloc(sizeof(int*));
| | ^~~~~~~~~~~~~~~~~~~~
| | |
| | (1) region created on heap here
| 461 | i = *p;
| | ~~~~~~
| | |
| | (2) use of uninitialized value '*p' here
|
and this helps readability of the resulting warnings, especially in
more complicated cases.
gcc/analyzer/ChangeLog:
* checker-path.cc (event_kind_to_string): Handle
EK_REGION_CREATION.
(region_creation_event::region_creation_event): New.
(region_creation_event::get_desc): New.
(checker_path::add_region_creation_event): New.
* checker-path.h (enum event_kind): Add EK_REGION_CREATION.
(class region_creation_event): New subclass.
(checker_path::add_region_creation_event): New decl.
* diagnostic-manager.cc
(diagnostic_manager::emit_saved_diagnostic): Pass NULL for new
param to add_events_for_eedge when handling trailing eedge.
(diagnostic_manager::build_emission_path): Create an interesting_t
instance, allow the pending diagnostic to populate it, and pass it
to the calls to add_events_for_eedge.
(diagnostic_manager::add_events_for_eedge): Add "interest" param.
Use it to add region_creation_events for on-stack regions created
within at function entry, and when pertinent dynamically-sized
regions are created.
(diagnostic_manager::prune_for_sm_diagnostic): Add case for
EK_REGION_CREATION.
* diagnostic-manager.h (diagnostic_manager::add_events_for_eedge):
Add "interest" param.
* pending-diagnostic.cc: Include "selftest.h", "tristate.h",
"analyzer/call-string.h", "analyzer/program-point.h",
"analyzer/store.h", and "analyzer/region-model.h".
(interesting_t::add_region_creation): New.
(interesting_t::dump_to_pp): New.
* pending-diagnostic.h (struct interesting_t): New.
(pending_diagnostic::mark_interesting_stuff): New vfunc.
* region-model.cc
(poisoned_value_diagnostic::poisoned_value_diagnostic): Add
(poisoned_value_diagnostic::operator==): Compare m_pkind and
m_src_region fields.
(poisoned_value_diagnostic::mark_interesting_stuff): New.
(poisoned_value_diagnostic::m_src_region): New.
(region_model::check_for_poison): Call
get_region_for_poisoned_expr for uninit values and pass the resul
to the diagnostic.
(region_model::get_region_for_poisoned_expr): New.
(region_model::deref_rvalue): Pass NULL for
poisoned_value_diagnostic's src_region.
* region-model.h (region_model::get_region_for_poisoned_expr): New
decl.
* region.h (frame_region::get_fndecl): New.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/data-model-1.c: Add dg-message directives for
expected region creation events.
* gcc.dg/analyzer/malloc-1.c: Likewise.
* gcc.dg/analyzer/memset-CVE-2017-18549-1.c: Likewise.
* gcc.dg/analyzer/pr101547.c: Likewise.
* gcc.dg/analyzer/pr101875.c: Likewise.
* gcc.dg/analyzer/pr101962.c: Likewise.
* gcc.dg/analyzer/pr104224.c: Likewise.
* gcc.dg/analyzer/pr94047.c: Likewise.
* gcc.dg/analyzer/symbolic-1.c: Likewise.
* gcc.dg/analyzer/uninit-1.c: Likewise.
* gcc.dg/analyzer/uninit-4.c: Likewise.
* gcc.dg/analyzer/uninit-alloca.c: New test.
* gcc.dg/analyzer/uninit-pr94713.c: Add dg-message directive for
expected region creation event.
* gcc.dg/analyzer/uninit-pr94714.c: Likewise.
* gcc.dg/analyzer/zlib-3.c: Likewise.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
The initial gcc 10 era commit of the analyzer (in
757bf1dff5e8cee34c0a75d06140ca972bfecfa7) had an implementation of
-Wanalyzer-use-of-uninitialized-value, but was sufficiently buggy
that I removed it in 78b9783774bfd3540f38f5b1e3c7fc9f719653d7 before
the release of gcc 10.1
This patch reintroduces the warning, heavily rewritten, with (I hope)
a less buggy implementation this time, for GCC 12.
gcc/analyzer/ChangeLog:
PR analyzer/95006
PR analyzer/94713
PR analyzer/94714
* analyzer.cc (maybe_reconstruct_from_def_stmt): Split out
GIMPLE_ASSIGN case into...
(get_diagnostic_tree_for_gassign_1): New.
(get_diagnostic_tree_for_gassign): New.
* analyzer.h (get_diagnostic_tree_for_gassign): New decl.
* analyzer.opt (Wanalyzer-write-to-string-literal): New.
* constraint-manager.cc (class svalue_purger): New.
(constraint_manager::purge_state_involving): New.
* constraint-manager.h
(constraint_manager::purge_state_involving): New.
* diagnostic-manager.cc (saved_diagnostic::supercedes_p): New.
(dedupe_winners::handle_interactions): New.
(diagnostic_manager::emit_saved_diagnostics): Call it.
* diagnostic-manager.h (saved_diagnostic::supercedes_p): New decl.
* engine.cc (impl_region_model_context::warn): Convert return type
to bool. Return false if the diagnostic isn't saved.
(impl_region_model_context::purge_state_involving): New.
(impl_sm_context::get_state): Use NULL ctxt when querying old
rvalue.
(impl_sm_context::set_next_state): Use new sval when querying old
state.
(class dump_path_diagnostic): Move to region-model.cc
(exploded_node::on_stmt): Move to on_stmt_pre and on_stmt_post.
Remove call to purge_state_involving.
(exploded_node::on_stmt_pre): New, based on the above. Move most
of it to region_model::on_stmt_pre.
(exploded_node::on_stmt_post): Likewise, moving to
region_model::on_stmt_post.
(class stale_jmp_buf): Fix parent class to use curiously recurring
template pattern.
(feasibility_state::maybe_update_for_edge): Call on_call_pre and
on_call_post on gcalls.
* exploded-graph.h (impl_region_model_context::warn): Return bool.
(impl_region_model_context::purge_state_involving): New decl.
(exploded_node::on_stmt_pre): New decl.
(exploded_node::on_stmt_post): New decl.
* pending-diagnostic.h (pending_diagnostic::use_of_uninit_p): New.
(pending_diagnostic::supercedes_p): New.
* program-state.cc (sm_state_map::get_state): Inherit state for
conjured_svalue as well as initial_svalue.
(sm_state_map::purge_state_involving): Also support SK_CONJURED.
* region-model-impl-calls.cc (call_details::get_uncertainty):
Handle m_ctxt being NULL.
(call_details::get_or_create_conjured_svalue): New.
(region_model::impl_call_fgets): New.
(region_model::impl_call_fread): New.
* region-model-manager.cc
(region_model_manager::get_or_create_initial_value): Return an
uninitialized poisoned value for regions that can't have initial
values.
* region-model-reachability.cc
(reachable_regions::mark_escaped_clusters): Handle ctxt being
NULL.
* region-model.cc (region_to_value_map::purge_state_involving): New.
(poisoned_value_diagnostic::use_of_uninit_p): New.
(poisoned_value_diagnostic::emit): Handle POISON_KIND_UNINIT.
(poisoned_value_diagnostic::describe_final_event): Likewise.
(region_model::check_for_poison): New.
(region_model::on_assignment): Call it.
(class dump_path_diagnostic): Move here from engine.cc.
(region_model::on_stmt_pre): New, based on exploded_node::on_stmt.
(region_model::on_call_pre): Move the setting of the LHS to a
conjured svalue to before the checks for specific functions.
Handle "fgets", "fgets_unlocked", and "fread".
(region_model::purge_state_involving): New.
(region_model::handle_unrecognized_call): Handle ctxt being NULL.
(region_model::get_rvalue): Call check_for_poison.
(selftest::test_stack_frames): Use NULL for context when getting
uninitialized rvalue.
(selftest::test_alloca): Likewise.
* region-model.h (region_to_value_map::purge_state_involving): New
decl.
(call_details::get_or_create_conjured_svalue): New decl.
(region_model::on_stmt_pre): New decl.
(region_model::purge_state_involving): New decl.
(region_model::impl_call_fgets): New decl.
(region_model::impl_call_fread): New decl.
(region_model::check_for_poison): New decl.
(region_model_context::warn): Return bool.
(region_model_context::purge_state_involving): New.
(noop_region_model_context::warn): Return bool.
(noop_region_model_context::purge_state_involving): New.
(test_region_model_context:: warn): Return bool.
* region.cc (region::get_memory_space): New.
(region::can_have_initial_svalue_p): New.
(region::involves_p): New.
* region.h (enum memory_space): New.
(region::get_memory_space): New decl.
(region::can_have_initial_svalue_p): New decl.
(region::involves_p): New decl.
* sm-malloc.cc (use_after_free::supercedes_p): New.
* store.cc (binding_cluster::purge_state_involving): New.
(store::purge_state_involving): New.
* store.h (class symbolic_binding): New forward decl.
(binding_key::dyn_cast_symbolic_binding): New.
(symbolic_binding::dyn_cast_symbolic_binding): New.
(binding_cluster::purge_state_involving): New.
(store::purge_state_involving): New.
* svalue.cc (svalue::can_merge_p): Reject attempts to merge
poisoned svalues with other svalues, so that we identify
paths in which a variable is conditionally uninitialized.
(involvement_visitor::visit_conjured_svalue): New.
(svalue::involves_p): Also handle SK_CONJURED.
(poison_kind_to_str): Handle POISON_KIND_UNINIT.
(poisoned_svalue::maybe_fold_bits_within): New.
* svalue.h (enum poison_kind): Add POISON_KIND_UNINIT.
(poisoned_svalue::maybe_fold_bits_within): New decl.
gcc/ChangeLog:
PR analyzer/95006
PR analyzer/94713
PR analyzer/94714
* doc/invoke.texi: Add -Wanalyzer-use-of-uninitialized-value.
gcc/testsuite/ChangeLog:
PR analyzer/95006
PR analyzer/94713
PR analyzer/94714
* g++.dg/analyzer/pr93212.C: Update location of warning.
* g++.dg/analyzer/pr94011.C: Add
-Wno-analyzer-use-of-uninitialized-value.
* g++.dg/analyzer/pr94503.C: Likewise.
* gcc.dg/analyzer/clobbers-1.c: Convert "f" from a local to a
param to avoid uninitialized warning.
* gcc.dg/analyzer/data-model-1.c (test_12): Add test for
uninitialized value on result of alloca.
(test_12a): Add expected warning.
(test_12c): Likewise.
(test_19): Likewise.
(test_29b): Likewise.
(test_29c): Likewise.
(test_37): Remove xfail.
(test_37a): Likewise.
* gcc.dg/analyzer/data-model-20.c: Add warning about leak.
* gcc.dg/analyzer/explode-2.c: Remove params; add
-Wno-analyzer-too-complex, -Wno-analyzer-malloc-leak, and xfails.
Initialize the locals.
* gcc.dg/analyzer/explode-2a.c: Initialize the locals. Add
expected leak.
* gcc.dg/analyzer/fgets-1.c: New test.
* gcc.dg/analyzer/fread-1.c: New test.
* gcc.dg/analyzer/malloc-1.c (test_16): Add expected warning.
(test_40): Likewise.
* gcc.dg/analyzer/memset-CVE-2017-18549-1.c: Check for
uninitialized padding.
* gcc.dg/analyzer/pr93355-localealias-feasibility.c (fread): New
decl.
(read_alias_file): Call it.
* gcc.dg/analyzer/pr94047.c: Add expected warnings.
* gcc.dg/analyzer/pr94851-2.c: Likewise.
* gcc.dg/analyzer/pr96841.c: Convert local to a param.
* gcc.dg/analyzer/pr98628.c: Likewise.
* gcc.dg/analyzer/pr99042.c: Updated expected location of leak
diagnostics.
* gcc.dg/analyzer/symbolic-1.c: Add expected warnings.
* gcc.dg/analyzer/symbolic-7.c: Likewise.
* gcc.dg/analyzer/torture/pr93649.c: Add expected warning. Skip
with -fno-fat-lto-objects.
* gcc.dg/analyzer/uninit-1.c: New test.
* gcc.dg/analyzer/uninit-2.c: New test.
* gcc.dg/analyzer/uninit-3.c: New test.
* gcc.dg/analyzer/uninit-4.c: New test.
* gcc.dg/analyzer/uninit-pr94713.c: New test.
* gcc.dg/analyzer/uninit-pr94714.c: New test.
* gcc.dg/analyzer/use-after-free-2.c: New test.
* gcc.dg/analyzer/use-after-free-3.c: New test.
* gcc.dg/analyzer/zlib-3.c: Add expected warning.
* gcc.dg/analyzer/zlib-6.c: Convert locals to params to avoid
uninitialized warnings. Remove xfail.
* gcc.dg/analyzer/zlib-6a.c: New test, based on the old version
of the above.
* gfortran.dg/analyzer/pr97668.f: Add
-Wno-analyzer-use-of-uninitialized-value and
-Wno-analyzer-too-complex.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
Various places iterate through all of the saved_diagnostics to find
just the ones that are at a given enode. This patch adds a per-enode
record of the diagnostics that are at each node, to save iterating
through all of the diagnostics each time.
gcc/analyzer/ChangeLog:
* diagnostic-manager.cc (diagnostic_manager::add_diagnostic): Make
enode param non-constant, and call add_diagnostic on it. Add
enode index to log message.
(diagnostic_manager::add_diagnostic): Make enode param
non-constant.
* diagnostic-manager.h (diagnostic_manager::add_diagnostic):
Likewise for both decls.
* engine.cc
(impl_region_model_context::impl_region_model_context): Likewise
for enode_for_diag.
(impl_sm_context::impl_sm_context): Likewise.
(impl_sm_context::m_enode_for_diag): Likewise.
(exploded_node::dump_dot): Don't pass the diagnostic manager
to dump_saved_diagnostics.
(exploded_node::dump_saved_diagnostics): Drop param. Iterate
directly through all saved diagnostics for the enode, rather
than all saved diagnostics in the diagnostic_manager and
filtering.
(exploded_node::on_stmt): Make non-const.
(exploded_node::on_edge): Likewise.
(exploded_node::on_longjmp): Likewise.
(exploded_node::detect_leaks): Likewise.
(exploded_graph::get_or_create_node): Make enode_for_diag param
non-const.
(exploded_graph_annotator::print_enode): Iterate
directly through all saved diagnostics for the enode, rather
than all saved diagnostics in the diagnostic_manager and
filtering.
* exploded-graph.h
(impl_region_model_context::impl_region_model_context): Make
enode_for_diag param non-constant.
(impl_region_model_context::m_enode_for_diag): Likewise.
(exploded_node::dump_saved_diagnostics): Drop param.
(exploded_node::on_stmt): Make non-const.
(exploded_node::on_edge): Likewise.
(exploded_node::on_longjmp): Likewise.
(exploded_node::detect_leaks): Likewise.
(exploded_node::add_diagnostic): New.
(exploded_node::get_num_diagnostics): New.
(exploded_node::get_saved_diagnostic): New.
(exploded_node::m_saved_diagnostics): New.
(exploded_graph::get_or_create_node): Make enode_for_diag param
non-constant.
* feasible-graph.cc (feasible_node::dump_dot): Drop
diagnostic_manager from call to dump_saved_diagnostics.
* program-state.cc (program_state::on_edge): Convert enode param
to non-const pointer.
(program_state::prune_for_point): Likewise for enode_for_diag
param.
* program-state.h (program_state::on_edge): Convert enode param
to non-const pointer.
(program_state::prune_for_point): Likewise for enode_for_diag
param.
|
|
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.
|
|
In gcc/analyzer/diagnostic-manager.cc the code partitions
saved_diagnostic instances by dedupe_key, and tries to find the "best"
saved_diagnostic for each dedupe_key.
Ideally we would find the shortest feasible path for each
saved_diagnostic and pick the winner in each deduplication set.
Currently we merely approximate that by finding the shortest path for
each saved_diagnostic, and checking to see if it feasible, rejecting
the saved_diagnostic if it is not. The "shortest path, or nothing if
it's infeasible" is not the same as the "shortest feasible path", and
this leads to false negatives, where we reject valid diagnostics,
tracked as PR analyzer/96374.
I have been attempting various fixes for this, but in doing so I
found that the existing structure of the code makes things unnecessarily
awkward: each dedupe_set had a a dedupe_candidate which stored the
best epath for that set, creating it from the shortest path when that
dedupe_candidate was constructed.
This patch eliminates the dedupe_candidate, instead storing the best
epath for each saved_diagnostic within the saved_diagnostic itself,
along with any feasibility_problem, and eliminating a redundant "status"
field. The logic for finding the best epath is moved to a new
epath_finder::get_best_epath subroutine, introducing an epath_finder
class to give a place to cache state.
This patch merely copies over the existing logic to
epath_finder::get_best_epath, so no functional change is intended,
but the patch simplifies the logic and makes it much easier to
experiment with alternate implementations as I try to fix
PR analyzer/96374.
I attempted another version of this patch in which I added a dedupe_set
class and partitioned saved_diagnostics into them as the diagnostics were
added, but in this earlier iteration of the patch there were regressions
e.g. from gcc.dg/analyzer/zlib-4.c where 4 deduplication sets became 3.
The issue was that the deduplication logic needs source locations, which
need gimple statements, and the stmt_finder needs epaths to run. Finding
the epaths needs the full egraph (as opposed to the egraph in its state
at the time when the diagnostic is saved). Hence the partitioning needs to
happen after the egraph is fully explored. I backed up the earlier patch
kit to:
https://dmalcolm.fedorapeople.org/gcc/2021-02-23/feasibility-v0.3-relative-to-72d78655a91bb2f89ac4432cfd6374380d6f9987/
gcc/analyzer/ChangeLog:
PR analyzer/96374
* diagnostic-manager.cc (class epath_finder): New.
(epath_finder::get_best_epath): New.
(saved_diagnostic::saved_diagnostic): Update for replacement of
m_state and m_epath_length with m_best_epath.
(saved_diagnostic::~saved_diagnostic): Delete m_best_epath.
(saved_diagnostic::to_json): Update "path_length" to be optional.
(saved_diagnostic::calc_best_epath): New, based on
dedupe_winners::add and parts of dedupe_key::dedupe_key.
(saved_diagnostic::get_epath_length): New.
(saved_diagnostic::add_duplicate): New.
(dedupe_key::dedupe_key): Drop epath param. Move invocation of
stmt_finder to saved_diagnostic::calc_best_epath.
(class dedupe_candidate): Delete.
(class dedupe_hash_map_traits): Update to use saved_diagnotic *
rather than dedupe_candidate * as the value_type/compare_type.
(dedupe_winners::~dedupe_winners): Don't delete the values.
(dedupe_winners::add): Convert param from shortest_exploded_paths to
epath_finder. Drop "eg" param. Drop dedupe_candidate, moving
path generation and feasiblity checking to
epath_finder::get_best_epath. Update winner-selection for move
of epaths from dedupe_candidate to saved_diagnostic.
(dedupe_winners::emit_best): Update for removal of class
dedupe_candidate.
(dedupe_winners::map_t): Update to use saved_diagnotic * rather
than dedupe_candidate * as the value_type/compare_type.
(diagnostic_manager::emit_saved_diagnostics): Move
shortest_exploded_paths instance into epath_finder and pass that
around instead.
(diagnostic_manager::emit_saved_diagnostic): Drop epath, stmt
and num_dupes params, instead getting these from the
saved_diagnostic. Use correct location in inform_n call.
* diagnostic-manager.h (class epath_finder): New forward decl.
(saved_diagnostic::status): Drop enum.
(saved_diagnostic::set_feasible): Drop.
(saved_diagnostic::set_infeasible): Drop.
(saved_diagnostic::get_status): Drop.
(saved_diagnostic::calc_best_epath): New decl.
(saved_diagnostic::get_best_epath): New decl.
(saved_diagnostic::get_epath_length): New decl.
(saved_diagnostic::set_epath_length): Drop.
(saved_diagnostic::get_epath_length): Drop inline implementation.
(saved_diagnostic::add_duplicate): New.
(saved_diagnostic::get_num_dupes): New.
(saved_diagnostic::m_d): Document ownership.
(saved_diagnostic::m_trailing_eedge): Make const.
(saved_diagnostic::m_status): Drop field.
(saved_diagnostic::m_epath_length): Drop field.
(saved_diagnostic::m_best_epath): New field.
(saved_diagnostic::m_problem): Document ownership.
(saved_diagnostic::m_duplicates): New field.
(diagnostic_manager::emit_saved_diagnostic): Drop params epath,
stmt, and num_dupes.
* engine.cc (exploded_graph_annotator::print_saved_diagnostic):
Update for changes to saved_diagnostic class.
* exploded-graph.h (exploded_path::feasible_p): Drop unused
overloaded decl.
|
|
This patch adds a simplification to analyzer paths for
repeated CFG edges generated from compound conditionals.
For example, it simplifies:
| 5 | if (a && b && c)
| | ^~~~~~~~~~~~
| | | | |
| | | | (4) ...to here
| | | | (5) following ‘true’ branch (when ‘c != 0’)...
| | | (2) ...to here
| | | (3) following ‘true’ branch (when ‘b != 0’)...
| | (1) following ‘true’ branch (when ‘a != 0’)...
| 6 | __analyzer_dump_path ();
| | ~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (6) ...to here
to:
| 5 | if (a && b && c)
| | ^
| | |
| | (1) following ‘true’ branch...
| 6 | __analyzer_dump_path ();
| | ~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (2) ...to here
gcc/analyzer/ChangeLog:
* checker-path.cc (event_kind_to_string): Handle
EK_START_CONSOLIDATED_CFG_EDGES and
EK_END_CONSOLIDATED_CFG_EDGES.
(start_consolidated_cfg_edges_event::get_desc): New.
(checker_path::cfg_edge_pair_at_p): New.
* checker-path.h (enum event_kind): Add
EK_START_CONSOLIDATED_CFG_EDGES and
EK_END_CONSOLIDATED_CFG_EDGES.
(class start_consolidated_cfg_edges_event): New class.
(class end_consolidated_cfg_edges_event): New class.
(checker_path::delete_events): New.
(checker_path::replace_event): New.
(checker_path::cfg_edge_pair_at_p): New decl.
* diagnostic-manager.cc (diagnostic_manager::prune_path): Call
consolidate_conditions.
(same_line_as_p): New.
(diagnostic_manager::consolidate_conditions): New.
* diagnostic-manager.h
(diagnostic_manager::consolidate_conditions): New decl.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/combined-conditionals-1.c: New test.
|
|
|
|
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.
|
|
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.
|
|
This patch extends -fdump-analyzer-supergraph so that rather than just
dumping a DUMP_BASE_NAME.supergraph.dot at the start of analysis, it
also dumps a DUMP_BASE_NAME.supergraph-eg.dot at the end.
The new dump file contains a concise dump of the exploded_graph,
organized with respect to the supergraph and its statements. The
exploded nodes are colorized to show sm-state, but no other state
is shown. Per exploded_node saved_diagnostics are also shown,
along with feasibility of the paths to reach them.
I've been finding this a useful way of tracking down issues in
exploded_graphs that are sufficiently large that the output of
-fdump-analyzer-exploded-graph becomes unwieldy.
The patch extends feasiblity-testing so that if the exploded_path
for a saved_diagnostic is found to be infeasible, the reason is
saved and written into the saved_diagnostic, so it can be shown in the
dump. I've found this very useful when tracking down feasibility
issues.
I'm keeping the initial dump file as it's useful when tracking down
ICEs within the analyzer (which would stop the second dump file being
written).
gcc/analyzer/ChangeLog:
* analyzer.h (class feasibility_problem): New forward decl.
* diagnostic-manager.cc (saved_diagnostic::saved_diagnostic):
Initialize new fields m_status, m_epath_length, and m_problem.
(saved_diagnostic::~saved_diagnostic): Delete m_problem.
(dedupe_candidate::dedupe_candidate): Convert "sd" param from a
const ref to a mutable ptr.
(dedupe_winners::add): Convert "sd" param from a const ref to a
mutable ptr. Record the length of the exploded_path. Record the
feasibility/infeasibility of sd into sd, capturing a
feasibility_problem when feasible_p fails, and storing it in sd.
(diagnostic_manager::emit_saved_diagnostics): Update for pass by
ptr rather than by const ref.
* diagnostic-manager.h (class saved_diagnostic): Add new enum
status. Add fields m_status, m_epath_length and m_problem.
(saved_diagnostic::set_feasible): New member function.
(saved_diagnostic::set_infeasible): New member function.
(saved_diagnostic::get_feasibility_problem): New accessor.
(saved_diagnostic::get_status): New accessor.
(saved_diagnostic::set_epath_length): New member function.
(saved_diagnostic::get_epath_length): New accessor.
* engine.cc: Include "gimple-pretty-print.h".
(exploded_path::feasible_p): Add OUT param and, if non-NULL, write
a new feasibility_problem to it on failure.
(viz_callgraph_node::dump_dot): Convert begin_tr calls to
begin_trtd. Convert end_tr calls to end_tdtr.
(class exploded_graph_annotator): New subclass of dot_annotator.
(impl_run_checkers): Add a second -fdump-analyzer-supergraph dump
after the analysis runs, using exploded_graph_annotator. dumping
to DUMP_BASE_NAME.supergraph-eg.dot.
* exploded-graph.h (exploded_node::get_dot_fillcolor): Make
public.
(exploded_path::feasible_p): Add OUT param.
(class feasibility_problem): New class.
* state-purge.cc (state_purge_annotator::add_node_annotations):
Return a bool, add a "within_table" param.
(print_vec_of_names): Convert begin_tr calls to begin_trtd.
Convert end_tr calls to end_tdtr.
(state_purge_annotator::add_stmt_annotations): Add "within_row"
param.
* state-purge.h ((state_purge_annotator::add_node_annotations):
Return a bool, add a "within_table" param.
(state_purge_annotator::add_stmt_annotations): Add "within_row"
param.
* supergraph.cc (supernode::dump_dot): Call add_node_annotations
twice: as before, passing false for "within_table", then again
with true when within the TABLE element. Convert some begin_tr
calls to begin_trtd, and some end_tr calls to end_tdtr.
Repeat each add_stmt_annotations call, distinguishing between
calls that add TRs and those that add TDs to an existing TR.
Add a call to add_after_node_annotations.
* supergraph.h (dot_annotator::add_node_annotations): Add a
"within_table" param.
(dot_annotator::add_stmt_annotations): Add a "within_row" param.
(dot_annotator::add_after_node_annotations): New vfunc.
gcc/ChangeLog:
* doc/invoke.texi (-fdump-analyzer-supergraph): Document that this
now emits two .dot files.
* graphviz.cc (graphviz_out::begin_tr): Only emit a TR, not a TD.
(graphviz_out::end_tr): Only close a TR, not a TD.
(graphviz_out::begin_td): New.
(graphviz_out::end_td): New.
(graphviz_out::begin_trtd): New, replacing the old implementation
of graphviz_out::begin_tr.
(graphviz_out::end_tdtr): New, replacing the old implementation
of graphviz_out::end_tr.
* graphviz.h (graphviz_out::begin_td): New decl.
(graphviz_out::end_td): New decl.
(graphviz_out::begin_trtd): New decl.
(graphviz_out::end_tdtr): New decl.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/dot-output.c: Check that
dot-output.c.supergraph-eg.dot is valid.
|
|
PR analyzer/93993 reports another ICE within
diagnostic_manager::prune_for_sm_diagnostic in which the expression
of interest becomes a non-lvalue (similar to PR 93544, PR 93647, and
PR 93950), due to attempting to get an lvalue for a non-lvalue with a
NULL context, leading to an ICE when the failure is reported to
make_region_for_unexpected_tree_code. The tree in question is
an ADDR_EXPR of a VAR_DECL, due to:
event 11: switching var of interest from ‘tm’ in callee to ‘&qb’ in caller
This patch adds more bulletproofing to the routine by introducing
a tentative_region_model_context class that can be passed in such
circumstances which records that an error occurred, and then
checking to see if an error was recorded, thus avoiding the ICE.
This is papering over the problem, but a better solution seems more
like stage 1 material.
The patch also refactors the error-checking for CONSTANT_CLASS_P.
The testcase pr93993.f90 has a false positive:
pr93993.f90:19:0:
19 | allocate (tm) ! { dg-warning "dereference of possibly-NULL" }
|
Warning: dereference of possibly-NULL ‘_6’ [CWE-690] [-Wanalyzer-possible-null-dereference]
which appears to be a pre-existing bug affecting any allocate call in
Fortran, which I will fix in a followup.
gcc/analyzer/ChangeLog:
PR analyzer/93993
* checker-path.h (state_change_event::get_lvalue): Add ctxt param
and pass it to region_model::get_value call.
* diagnostic-manager.cc (get_any_origin): Pass a
tentative_region_model_context to the calls to get_lvalue and reject
the comparison if errors occur.
(can_be_expr_of_interest_p): New function.
(diagnostic_manager::prune_for_sm_diagnostic): Replace checks for
CONSTANT_CLASS_P with calls to update_for_unsuitable_sm_exprs.
Pass a tentative_region_model_context to the calls to
state_change_event::get_lvalue and reject the comparison if errors
occur.
(diagnostic_manager::update_for_unsuitable_sm_exprs): New.
* diagnostic-manager.h
(diagnostic_manager::update_for_unsuitable_sm_exprs): New decl.
* region-model.h (class tentative_region_model_context): New class.
gcc/testsuite/ChangeLog:
PR analyzer/93993
* gfortran.dg/analyzer/pr93993.f90: New test.
|
|
Paths emitted by the analyzer can be quite verbose at the default of
-fanalyzer-verbosity=2.
Consider the double-free in this example:
#include <stdlib.h>
int foo ();
int bar ();
void test (int a, int b, int c)
{
void *p = malloc (1024);
while (a)
foo ();
if (b)
foo ();
else
bar ();
if (c)
free (p);
free (p);
}
Previously, the analyzer would emit a checker_path containing all
control-flow information on the exploded_path leading to the
double-free:
test.c: In function 'test':
test.c:17:3: warning: double-'free' of 'p' [CWE-415] [-Wanalyzer-double-free]
17 | free (p);
| ^~~~~~~~
'test': events 1-9
|
| 8 | void *p = malloc (1024);
| | ^~~~~~~~~~~~~
| | |
| | (1) allocated here
| 9 | while (a)
| | ~
| | |
| | (2) following 'false' branch (when 'a == 0')...
| 10 | foo ();
| 11 | if (b)
| | ~
| | |
| | (3) ...to here
| | (4) following 'false' branch (when 'b == 0')...
|......
| 14 | bar ();
| | ~~~~~~
| | |
| | (5) ...to here
| 15 | if (c)
| | ~
| | |
| | (6) following 'true' branch (when 'c != 0')...
| 16 | free (p);
| | ~~~~~~~~
| | |
| | (7) ...to here
| | (8) first 'free' here
| 17 | free (p);
| | ~~~~~~~~
| | |
| | (9) second 'free' here; first 'free' was at (8)
|
despite the fact that only the "if (c)" is relevant to triggering the
double-free.
This patch implements pruning of control flow events at
-fanalyzer-verbosity=2, based on reachability information within the
exploded_graph.
The diagnostic_manager pre-computes reachability information about
which exploded_nodes can reach the exploded_node of the diagnostic,
and uses this to prune irrelvent control flow edges.
The patch also adds a -fanalyzer-verbosity=3 to preserve these edges,
so that the "show me everything" debugging level becomes
-fanalyzer-verbosity=4.
With these changes, the "while (a)" and "if (b)" edges are pruned from
the above example, leading to:
test.c: In function 'test':
test.c:17:3: warning: double-'free' of 'p' [CWE-415] [-Wanalyzer-double-free]
17 | free (p);
| ^~~~~~~~
'test': events 1-5
|
| 8 | void *p = malloc (1024);
| | ^~~~~~~~~~~~~
| | |
| | (1) allocated here
|......
| 15 | if (c)
| | ~
| | |
| | (2) following 'true' branch (when 'c != 0')...
| 16 | free (p);
| | ~~~~~~~~
| | |
| | (3) ...to here
| | (4) first 'free' here
| 17 | free (p);
| | ~~~~~~~~
| | |
| | (5) second 'free' here; first 'free' was at (4)
|
The above example is gcc.dg/analyzer/edges-2.c.
gcc/analyzer/ChangeLog:
* checker-path.cc (superedge_event::should_filter_p): Update
filter for empty descriptions to cover verbosity level 3 as well
as 2.
* diagnostic-manager.cc: Include "analyzer/reachability.h".
(class path_builder): New class.
(diagnostic_manager::emit_saved_diagnostic): Create a path_builder
and pass it to build_emission_path, rather passing eg; similarly
for add_events_for_eedge and ext_state.
(diagnostic_manager::build_emission_path): Replace "eg" param
with a path_builder, pass it to add_events_for_eedge.
(diagnostic_manager::add_events_for_eedge): Replace ext_state
param with path_builder; pass it to add_events_for_superedge.
(diagnostic_manager::significant_edge_p): New.
(diagnostic_manager::add_events_for_superedge): Add path_builder
param. Reject insignificant edges at verbosity levels below 3.
(diagnostic_manager::prune_for_sm_diagnostic): Update highest
verbosity level to 4.
* diagnostic-manager.h (class path_builder): New forward decl.
(diagnostic_manager::build_emission_path): Replace "eg" param
with a path_builder.
(diagnostic_manager::add_events_for_eedge): Replace ext_state
param with path_builder.
(diagnostic_manager::significant_edge_p): New.
(diagnostic_manager::add_events_for_superedge): Add path_builder
param.
* reachability.h: New file.
gcc/ChangeLog:
* doc/invoke.texi (-fanalyzer-verbosity=): "2" only shows
significant control flow events; add a "3" which shows all
control flow events; the old "3" becomes "4".
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/analyzer-verbosity-2a.c: New test.
* gcc.dg/analyzer/analyzer-verbosity-3.c: New test, based on
analyzer-verbosity-2.c
* gcc.dg/analyzer/analyzer-verbosity-3a.c: New test.
* gcc.dg/analyzer/edges-1.c: New test.
* gcc.dg/analyzer/edges-2.c: New test.
* gcc.dg/analyzer/file-paths-1.c: Add -fanalyzer-verbosity=3.
|
|
gcc/analyzer/ChangeLog:
* diagnostic-manager.h (diagnostic_manager::get_saved_diagnostic):
Add const overload.
* engine.cc (exploded_node::dump_dot): Dump saved_diagnostics.
* exploded-graph.h (exploded_graph::get_diagnostic_manager): Add
const overload.
|
|
PR analyzer/93307 reports that in an LTO bootstrap, there are ODR
violations between:
- the "region" type:
gcc/analyzer/region-model.h:792
vs:
gcc/sched-int.h:1443
- the "constraint" type:
gcc/analyzer/constraint-manager.h:121
vs:
gcc/tree-ssa-structalias.c:533
This patches solves this clash by putting all of the analyzer names
within a namespace. I chose "ana" as it is short (to save typing).
The analyzer selftests are moved from namespace "selftest" to
"ana::selftest".
There are various places where the namespace has to be closed
and reopened, to allow e.g. for specializations of templates
in the global namespace.
gcc/analyzer/ChangeLog:
PR analyzer/93307
* analysis-plan.h: Wrap everything namespace "ana".
* analyzer-logging.cc: Likewise.
* analyzer-logging.h: Likewise.
* analyzer-pass.cc (pass_analyzer::execute): Update for "ana"
namespace.
* analyzer-selftests.cc: Wrap everything namespace "ana".
* analyzer-selftests.h: Likewise.
* analyzer.h: Likewise for forward decls of types.
* call-string.h: Likewise.
* checker-path.cc: Likewise.
* checker-path.h: Likewise.
* constraint-manager.cc: Likewise.
* constraint-manager.h: Likewise.
* diagnostic-manager.cc: Likewise.
* diagnostic-manager.h: Likewise.
* engine.cc: Likewise.
* engine.h: Likewise.
* exploded-graph.h: Likewise.
* function-set.cc: Likewise.
* function-set.h: Likewise.
* pending-diagnostic.cc: Likewise.
* pending-diagnostic.h: Likewise.
* program-point.cc: Likewise.
* program-point.h: Likewise.
* program-state.cc: Likewise.
* program-state.h: Likewise.
* region-model.cc: Likewise.
* region-model.h: Likewise.
* sm-file.cc: Likewise.
* sm-malloc.cc: Likewise.
* sm-pattern-test.cc: Likewise.
* sm-sensitive.cc: Likewise.
* sm-signal.cc: Likewise.
* sm-taint.cc: Likewise.
* sm.cc: Likewise.
* sm.h: Likewise.
* state-purge.h: Likewise.
* supergraph.cc: Likewise.
* supergraph.h: Likewise.
gcc/ChangeLog:
PR analyzer/93307
* gdbinit.in (break-on-saved-diagnostic): Update for move of
diagnostic_manager into "ana" namespace.
* selftest-run-tests.c (selftest::run_tests): Update for move of
selftest::run_analyzer_selftests to
ana::selftest::run_analyzer_selftests.
|
|
Whilst analyzing the reproducer for detecting CVE-2005-1689
(krb5-1.4.1's src/lib/krb5/krb/recvauth.c), the analyzer reported
11 double-free diagnostics on lines of the form:
krb5_xfree(inbuf.data);
with no deduplication occcurring.
The root cause is that the diagnostics each have a COMPONENT_REF for
the inbuf.data, but they are different trees, and the de-duplication
logic was using pointer equality.
This patch replaces the pointer equality tests with calls to a new
pending_diagnostic::same_tree_p, implemented using simple_cst_equal.
With this patch, de-duplication occurs, and only 3 diagnostics are
reported. The 11 diagnostics are partitioned into 3 dedupe keys,
2 with 2 duplicates and 1 with 7 duplicates.
gcc/analyzer/ChangeLog:
* diagnostic-manager.cc (saved_diagnostic::operator==): Move here
from header. Replace pointer equality test on m_var with call to
pending_diagnostic::same_tree_p.
* diagnostic-manager.h (saved_diagnostic::operator==): Move to
diagnostic-manager.cc.
* pending-diagnostic.cc (pending_diagnostic::same_tree_p): New.
* pending-diagnostic.h (pending_diagnostic::same_tree_p): New.
* sm-file.cc (file_diagnostic::subclass_equal_p): Replace pointer
equality on m_arg with call to pending_diagnostic::same_tree_p.
* sm-malloc.cc (malloc_diagnostic::subclass_equal_p): Likewise.
(possible_null_arg::subclass_equal_p): Likewise.
(null_arg::subclass_equal_p): Likewise.
(free_of_non_heap::subclass_equal_p): Likewise.
* sm-pattern-test.cc (pattern_match::operator==): Likewise.
* sm-sensitive.cc (exposure_through_output_file::operator==):
Likewise.
* sm-taint.cc (tainted_array_index::operator==): Likewise.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/CVE-2005-1689-dedupe-issue.c: New test.
|
|
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.
|