PIPS
points-to.h File Reference
#include "points_to_private.h"
#include "effects.h"
+ Include dependency graph for points-to.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define SEQUENTIAL_POINTS_TO_SETS_SUFFIX   ".pt"
 Warning! Do not modify this file that is automatically generated! More...
 
#define USER_POINTS_TO_SETS_SUFFIX   ".upt"
 
#define pt_map_undefined   points_to_graph_undefined
 
#define pt_map_undefined_p(pt)   ((pt)==points_to_graph_undefined)
 
#define new_pt_map()   make_points_to_graph(false, set_generic_make(set_private, points_to_equal_p, points_to_rank))
 
#define new_simple_pt_map()   set_generic_make(set_private, points_to_equal_p, points_to_rank)
 
#define assign_pt_map(x, y)   ((void) set_assign(points_to_graph_set(x), points_to_graph_set(y)), (x))
 
#define clear_pt_map(pt)   set_clear(points_to_graph_set(pt))
 
#define free_pt_map(pt)   free_points_to_graph(pt)
 
#define print_pt_map(pt)   print_points_to_set("", points_to_graph_set(pt));
 
#define free_pt_maps   free_points_to_graph_sets
 
#define union_of_pt_maps(pt1, pt2, pt3)
 
#define difference_of_pt_maps(pt1, pt2, pt3)
 
#define empty_pt_map_p(s)   set_empty_p(points_to_graph_set(s))
 
#define consistent_pt_map_p(s)   consistent_points_to_graph_p(s)
 
#define source_in_pt_map_p(cell, set)   source_in_set_p(cell,points_to_graph_set(set))
 
#define remove_arc_from_pt_map(a, s)   (set_del_element((set) points_to_graph_set(s), (set) points_to_graph_set(s), (void *) a))
 
#define remove_arc_from_pt_map_(a, s)   (remove_arc_from_pt_map(a, s), (s))
 

Typedefs

typedef points_to_graph pt_map
 

Functions

int compare_entities_without_scope (const entity *, const entity *)
 cproto-generated files More...
 
entity location_entity (cell)
 
bool locations_equal_p (cell, cell)
 eturn true if two acces_path are equals More...
 
int points_to_equal_p (const void *, const void *)
 returns true if two points-to arcs "vpt1" and "vpt2" are equal. More...
 
_uint points_to_rank (const void *, size_t)
 create a key which is a concatenation of the source's name, the sink's name and the approximation of their relation(may or exact) More...
 
string points_to_name (const points_to)
 create a string which is a concatenation of the source's name, the sink's name and the approximation of their relation(may or exact). More...
 
string points_to_cell_name (cell)
 Create a string which is the cell reference in C syntax. More...
 
set points_to_set_block_projection (set, list, bool, bool)
 Remove from "pts" arcs based on at least one local entity in list "l" and preserve those based on static and global entities. More...
 
set points_to_source_projection (set, entity)
 Remove all arcs starting from e because e has been assigned a new value. More...
 
points_to_graph points_to_cell_source_projection (points_to_graph, cell)
 Remove all arcs in "ptg" starting from "c". More...
 
set remove_points_to_cell (cell, set)
 All arcs in relation "g" must be removed or updated if they use the node "c". More...
 
set remove_points_to_cells (list, set)
 All nodes, i.e. More...
 
list potential_to_effective_memory_leaks (list, set)
 A new list, "emll", is allocated. More...
 
set points_to_function_projection (set)
 "pts" is the points-to relation existing at the return point of a function. More...
 
bool cell_out_of_scope_p (cell)
 Return true if a cell is out of scope. More...
 
void print_or_dump_points_to (const points_to, bool)
 print a points-to arc for debug More...
 
void print_points_to (const points_to)
 
void dump_points_to (const points_to)
 
void print_or_dump_points_to_set (string, set, bool)
 Print a set of points-to for debug. More...
 
void print_points_to_set (string, set)
 
void dump_points_to_set (string, set)
 
bool source_in_set_p (cell, set)
 test if a cell appear as a source in a set of points-to More...
 
bool source_subset_in_set_p (cell, set)
 test if a cell "source" appears as a source in a set of points-to More...
 
bool source_in_graph_p (cell, points_to_graph)
 
bool sink_in_set_p (cell, set)
 test if a cell appear as a sink in a set of points-to More...
 
points_to find_arc_in_points_to_set (cell, cell, pt_map)
 The approximation is not taken into account. More...
 
list anywhere_source_to_sinks (cell, pt_map)
 source is assumed to be either nowhere/undefined or anywhere, it may be typed or not. More...
 
void print_points_to_path (list)
 For debugging. More...
 
bool type_compatible_with_points_to_cell_p (type, cell)
 A type "t" is compatible with a cell "c" if any of the enclosing cell "c'" of "c", including "c", is of type "t". More...
 
cell type_compatible_super_cell (type, cell)
 See if a super-cell of "c" exists witf type "t". More...
 
cell find_kth_points_to_node_in_points_to_path (list, type, int)
 Find the "k"-th node of type "t" in list "p". More...
 
bool node_in_points_to_path_p (cell, list)
 
points_to points_to_path_to_k_limited_points_to_path (list, int, type, bool, pt_map)
 "p" is a points-to path ending with a cell that points towards a new cell ot type "t". More...
 
points_to create_k_limited_stub_points_to (cell, type, bool, pt_map)
 Create a new node "sink" of type "t" and a new arc "pt" starting from node "source", if no path starting from any node and ending in "source", built with arcs in the points-to set "in", contains more than k nodes of type "t" (the type of the sink). More...
 
list sink_to_sources (cell, set, bool)
 Build a list of possible cell sources for cell "sink" in points-to graph "pts". More...
 
list stub_source_to_sinks (cell, pt_map, bool)
 
list scalar_stub_source_to_sinks (cell, pt_map, bool)
 
list array_stub_source_to_sinks (cell, pt_map, bool)
 
list generic_stub_source_to_sinks (cell, pt_map, bool, bool)
 
list points_to_cell_null_initialization (cell, pt_map)
 If required according to the property, create a new arc from cell "c" to "null". More...
 
list nowhere_source_to_sinks (cell, pt_map)
 
list null_source_to_sinks (cell, pt_map)
 
list formal_source_to_sinks (cell, pt_map, bool)
 Creation of a stub for a formal parameter or for a reference based on a formal parameter. More...
 
list global_source_to_sinks (cell, pt_map, bool)
 
list reference_to_points_to_translations (entity, list, pt_map)
 This function is designed to work properly for the translation of effects at call sites. More...
 
list points_to_reference_to_translation (reference, list, pt_map, bool)
 FI: easier it fresh_p is true... More...
 
list points_to_source_to_translations (cell, pt_map, bool)
 Use "ptm" as a translation map. More...
 
list generic_points_to_source_to_sinks (cell, pt_map, bool, bool, bool, bool)
 Build the sinks of source "source" according to the points-to graphs. More...
 
list points_to_source_to_sinks (cell, pt_map, bool)
 Build the sinks of source "source" according to the points-to graphs. More...
 
list points_to_source_to_effective_sinks (cell, pt_map, bool)
 
list points_to_source_to_some_sinks (cell, pt_map, bool)
 May not retrieve all sinks of the source. More...
 
list points_to_source_to_any_sinks (cell, pt_map, bool)
 Retrieve all possible sinks of the source. More...
 
list points_to_sink_to_sources (cell, pt_map, bool)
 Build the sources of sink "sink" according to the points-to graphs. More...
 
points_to points_to_sink_to_points_to (cell, pt_map)
 Return the points-to "fpt" ending in cell "sink" if it exists. More...
 
list points_to_source_name_to_sinks (string, pt_map, bool)
 Use "sn" as a source name to derive a list of sink cells according to the points-to graph ptm. More...
 
cell points_to_source_name_to_source_cell (string, pt_map, bool)
 
list generic_points_to_sources_to_sinks (list, pt_map, bool, bool)
 Build the union of the sinks of cells in "sources" according to the points-to graphs "ptm". More...
 
list points_to_sources_to_sinks (list, pt_map, bool)
 
list points_to_sources_to_effective_sinks (list, pt_map, bool)
 
list points_to_source_to_arcs (cell, pt_map, bool)
 Build the list of arcs whose source is "source" according to the points-to graphs "ptm". More...
 
int points_to_cell_to_number_of_unbounded_dimensions (cell)
 
int points_to_reference_to_number_of_unbounded_dimensions (reference)
 
int points_to_subscripts_to_number_of_unbounded_dimensions (list)
 
bool sinks_fully_matches_source_p (cell, list)
 Is there at least one cell "sink" in list "sinks" whose subscripts fully match the subscripts in cell "source"? More...
 
list source_to_sinks (cell, pt_map, bool)
 Return a list of cells, "sinks", that are sink for some arc whose source is "source" or related to "source" in set "pts". More...
 
list extended_source_to_sinks (cell, pt_map)
 
list extended_sources_to_sinks (list, pt_map)
 Same as extended_source_to_sinks, but for a set of cells, "pointed". More...
 
list any_source_to_sinks (cell, pt_map, bool)
 Generalization of source_to_sinks(). More...
 
list pointer_source_to_sinks (cell, pt_map)
 Returns the sinks for a source cell "sc" of type pointer according to the points-to relation "in". More...
 
list variable_to_sinks (entity, pt_map, bool)
 Return all cells in points-to set "pts" who source is based on entity "e". More...
 
list null_to_sinks (cell, pt_map)
 Create a list of null sinks and add a new null points-to relation to pts. More...
 
list sources_to_sinks (list, pt_map, bool)
 Same as source_to_sinks, but for a list of cells. More...
 
list reference_to_sinks (reference, pt_map, bool)
 
set merge_points_to_set (set, set)
 Merge two points-to sets. More...
 
set exact_to_may_points_to_set (set)
 Change the all the exact points-to relations to may relations. More...
 
bool cell_in_list_p (cell, const list)
 
bool cell_in_points_to_set_p (cell, set)
 Check if a cell c appears as source or sink in points-to set pts. More...
 
bool points_to_in_list_p (points_to, const list)
 
bool points_to_compare_cell (cell, cell)
 
bool points_to_compare_ptr_cell (const void *, const void *)
 
int points_to_compare_location (void *, void *)
 Order the two points-to relations according to the alphabetical order of the underlying variables. More...
 
bool consistent_points_to_arc_p (points_to, bool)
 
bool store_independent_points_to_arc_p (points_to)
 
bool dereferencing_free_points_to_arc_p (points_to)
 
bool consistent_points_to_set (set)
 make sure that set "s" does not contain redundant or contradictory elements More...
 
bool points_to_set_sharing_p (set)
 
void upgrade_approximations_in_points_to_set (pt_map)
 When arcs have been removed from a points-to relation, the approximations of remaining arcs may not correspond to the new points-to relation. More...
 
void remove_points_to_arcs (cell, cell, pt_map)
 
void points_to_cell_list_and (list *, const list)
 Compute A = A inter B: complexity in O(n2) More...
 
void free_points_to_graph_sets (points_to_graph,...)
 Free several sets in one call. More...
 
pt_map graph_assign_list (pt_map, list)
 FI: I add functions dealing with points_to_graph variable, i.e. More...
 
pt_map merge_points_to_graphs (pt_map, pt_map)
 
pt_map points_to_graph_assign (pt_map, pt_map)
 
points_to fuse_points_to_sink_cells (cell, list, pt_map)
 All vertices in "sink_l" are assumed to be sinks of vertex "source" in points-to graph "in". More...
 
int maximal_out_degree_of_points_to_graph (string *, pt_map)
 returns the cell vertex "mod_cell" with the maximal out_degree in graph "in", and its out-degree. More...
 
pt_map normalize_points_to_graph (pt_map)
 For the time being, control the out-degree of the vertices in points-to graph "ptg" and fuse the vertex with the maximal out-degree to reduce it if it is greater than an expected limit. More...
 
string points_to_cell_to_string (cell)
 
bool unreachable_points_to_cell_p (cell, pt_map)
 Can cell c be accessed via another cell? More...
 
pt_map generic_remove_unreachable_vertices_in_points_to_graph (pt_map, int code, bool)
 Remove arcs in points-to graph "ptg" when they start from a stub cell that is not reachable. More...
 
pt_map remove_unreachable_stub_vertices_in_points_to_graph (pt_map)
 
pt_map remove_unreachable_heap_vertices_in_points_to_graph (pt_map, bool)
 
pt_map remove_unreachable_vertices_in_points_to_graph (pt_map)
 This function looks pretty dangerous as variables can be reached by their names. More...
 
bool consistent_points_to_graph_p (points_to_graph)
 
void remove_impossible_arcs_to_null (list *, pt_map)
 You know that null and undefined cells in "*pL" are impossible because of the operation that is going to be performed on it. More...
 
bool arc_in_points_to_set_p (points_to, set)
 Check if points-to arc "spt" belongs to points-to set "pts". More...
 
pt_map get_points_to_graph_from_statement (statement)
 
void add_arc_to_pt_map (points_to, pt_map)
 Add a store independent points-to arc: source and destination references include no dereferencing nor varying subscript such as a[i]. More...
 
pt_map add_arc_to_pt_map_ (points_to, pt_map)
 
set add_arc_to_simple_pt_map (points_to, set)
 
set remove_arc_from_simple_pt_map (points_to, set)
 
set add_subscript_dependent_arc_to_simple_pt_map (points_to, set)
 The source and destination references imply no dereferencing but the subscripts may be any kind of expression, such as a[i]. More...
 
bool printed_points_to_list_undefined_p (void)
 points_to_prettyprint.c More...
 
void reset_printed_points_to_list (void)
 
void error_reset_printed_points_to_list (void)
 
void set_printed_points_to_list (statement_points_to)
 
statement_points_to get_printed_points_to_list (void)
 
void init_printed_points_to_list (void)
 
void close_printed_points_to_list (void)
 
void store_printed_points_to_list (statement, points_to_list)
 
void update_printed_points_to_list (statement, points_to_list)
 
points_to_list load_printed_points_to_list (statement)
 
points_to_list delete_printed_points_to_list (statement)
 
bool bound_printed_points_to_list_p (statement)
 
void store_or_update_printed_points_to_list (statement, points_to_list)
 
text text_points_to (entity, int, statement)
 
text text_code_points_to (statement)
 
bool print_code_points_to (const char *, string, string)
 
void print_points_to_list (points_to_list)
 
void print_points_to_graph (points_to_graph)
 
bool print_code_points_to_list (const char *)
 
list words_points_to (points_to)
 
text text_points_to_relation (points_to)
 text text_region(effect reg) input : a region output : a text consisting of several lines of commentaries, representing the region modifies : nothing More...
 
text text_points_to_relations (points_to_list, string)
 
void print_points_to_relation (points_to)
 print a points-to arc, print_points_to() or print_points_to_arc() More...
 
void print_points_to_relations (list)
 print a list of points-to arcs More...
 
text text_pt_to (entity, int, statement)
 
void points_to_forward_translation (void)
 points_to_init_analysis.c More...
 
void points_to_backward_translation (void)
 
set formal_points_to_parameter (cell)
 We want a recursive descent on the type of the formal parameter, once we found a pointer type we beguin a recursive descent until founding a basic case. More...
 
entity create_stub_entity (entity, string, type)
 Allocate a stub entity "stub" for entity "e" and with type "t". More...
 
cell create_scalar_stub_sink_cell (entity, type, type, int, list, string)
 Create a stub entity "se" for entity "v" with type "t" and return a cell based on a reference to the stub entity "se" with "d" unbounded subscripts to account for the dimension of the source and a zero subscript for implicit array. More...
 
int points_to_indices_to_array_index_number (list)
 Count the number of array indices and ignore the field subscripts. More...
 
void points_to_indices_to_unbounded_indices (list)
 FI: probably a duplicate... More...
 
list points_to_indices_to_subscript_indices (list)
 Generate a new subscript list. More...
 
string reference_to_field_disambiguator (reference)
 Build an ASCII string to disambiguate the different field paths that may exist in similar references. More...
 
points_to create_stub_points_to (cell, type, bool)
 
points_to create_advanced_stub_points_to (cell, type, bool)
 Take into account the POINTS_TO_STRICT_POINTER_TYPE to allocate a sink cell of type "t" if the strictness is requested and of type "array of t" if not. More...
 
points_to create_pointer_to_array_stub_points_to (cell, type, bool)
 To create the points-to stub associated to the formal parameter, the sink name is a concatenation of the formal parmater and the POINTS_TO_MODULE_NAME. More...
 
set pointer_formal_parameter_to_stub_points_to (type, cell)
 Input : a formal parameter which is a pointer and its type. More...
 
set derived_formal_parameter_to_stub_points_to (type, cell)
 Input : a formal parameter which has a derived type (FI, I guess). More...
 
set typedef_formal_parameter_to_stub_points_to (type, cell)
 Input : a formal parameter which is a typedef. More...
 
set array_formal_parameter_to_stub_points_to (type, cell)
 Type "t" is supposed to be a concrete type. More...
 
set full_copy_simple_pt_map (set)
 statement.c More...
 
pt_map full_copy_pt_map (pt_map)
 
void init_statement_points_to_context (void)
 
void push_statement_points_to_context (statement, pt_map)
 
void add_arc_to_statement_points_to_context (points_to)
 
void update_statement_points_to_context_with_arc (points_to)
 
int points_to_context_statement_line_number (void)
 
pt_map points_to_context_statement_in (void)
 
pt_map pop_statement_points_to_context (void)
 
void reset_statement_points_to_context (void)
 
bool statement_points_to_context_defined_p (void)
 
pt_map statement_to_points_to (statement, pt_map)
 See points_to_statement() More...
 
pt_map declaration_statement_to_points_to (statement, pt_map)
 See points_to_init() More...
 
pt_map instruction_to_points_to (instruction, pt_map)
 See points_to_statement() More...
 
pt_map sequence_to_points_to (sequence, pt_map)
 
void equalize_points_to_domains (points_to_graph, points_to_graph)
 Make sure that pt_t and pt_f have the same definition domain except if one of them is bottom. More...
 
pt_map test_to_points_to (test, pt_map)
 Computing the points-to information after a test. More...
 
pt_map loop_to_points_to (loop, pt_map)
 FI: I assume that pointers and pointer arithmetic cannot appear in a do loop, "do p=q, r, 1" is possible with "p", "q" and "r" pointing towards the same array... More...
 
pt_map whileloop_to_points_to (whileloop, pt_map)
 
pt_map any_loop_to_points_to (statement, expression, expression, expression, pt_map)
 Perform the same k-limiting scheme for all kinds of loops. More...
 
pt_map new_any_loop_to_points_to (statement, expression, expression, expression, pt_map)
 Perform the same k-limiting scheme for all kinds of loops. More...
 
pt_map k_limit_points_to (pt_map, int)
 
pt_map unstructured_to_points_to (unstructured, pt_map)
 
pt_map multitest_to_points_to (multitest, pt_map)
 
pt_map forloop_to_points_to (forloop, pt_map)
 
void subscripted_reference_to_points_to (reference, list, pt_map)
 expression.c More...
 
pt_map expression_to_points_to (expression, pt_map, bool)
 Update pt_in and pt_out according to expression e. More...
 
pt_map expressions_to_points_to (list, pt_map, bool)
 Compute the points-to information pt_out that results from the evaluation of a possibly empty list of expression. More...
 
pt_map reference_to_points_to (reference, pt_map, bool)
 The subscript expressions may impact the points-to information. More...
 
pt_map range_to_points_to (range, pt_map, bool)
 
pt_map call_to_points_to (call, pt_map, list, bool)
 Three different kinds of calls are distinguished: More...
 
pt_map constant_call_to_points_to (call, pt_map)
 
pt_map intrinsic_call_to_points_to (call, pt_map, bool)
 
pt_map pointer_arithmetic_to_points_to (expression, expression, pt_map)
 Update the sink locations associated to the source "lhs" under points-to information pt_map by "delta". More...
 
void offset_array_reference (reference, expression, type)
 Side effect on reference "r". More...
 
void offset_cells (cell, list, expression, type, pt_map)
 Each cell in sinks is replaced by a cell located "delta" elements further up in the memory. More...
 
points_to offset_cell (points_to, expression, type)
 Allocate and return a new points-to "npt", copy of "pt", with an offset of "delta" on the sink. More...
 
void offset_points_to_cells (list, expression, type)
 Each cell in sinks is replaced by a cell located "delta" elements further up in the memory. More...
 
void offset_points_to_cell (cell, expression, type, bool)
 
pt_map assignment_to_points_to (expression, expression, pt_map)
 
void check_type_of_points_to_cells (list, type, bool)
 Check that all cells in list "sinks" are compatible with type "ct" if "eval_p" is false, and with the type pointed by "st" if eval_p is true. More...
 
void check_rhs_value_types (expression, expression, list)
 
pt_map internal_pointer_assignment_to_points_to (expression, expression, pt_map)
 Any abstract location of the lhs in L is going to point to any sink of any abstract location of the rhs in R. More...
 
pt_map pointer_assignment_to_points_to (expression, expression, pt_map)
 
list freeable_points_to_cells (list)
 Remove from points-to cell list R cells that certainly cannot be freed. More...
 
pt_map freed_list_to_points_to (expression, list, list, pt_map)
 Error detections on "L" and "R" have already been performed. More...
 
pt_map freed_pointer_to_points_to (expression, pt_map, bool)
 Any abstract location of the lhs in L is going to point to nowhere, maybe. More...
 
cell reduce_cell_to_pointer_type (cell)
 Remove last subscripts of cell c till its type becomes a scalar pointer. More...
 
list reduce_cells_to_pointer_type (list)
 Undo the extra eval performed when stubs are generated: 0 subscripts are added when arrays are involved. More...
 
list points_to_cell_to_pointer_cells (cell)
 
list points_to_cell_to_useful_pointer_cells (cell, set)
 
list points_to_cells_to_pointer_cells (list)
 Convert cells in l into derived pointer cells when possible. More...
 
pt_map memory_leak_to_more_memory_leaks (cell, pt_map)
 Cell "l" has been memory leaked for sure and is not referenced any more in "in". More...
 
pt_map list_assignment_to_points_to (list, list, pt_map)
 Update "pt_out" when any element of L can be assigned any element of R. More...
 
pt_map struct_initialization_to_points_to (expression, expression, pt_map)
 
pt_map struct_assignment_to_points_to (expression, expression, pt_map)
 pt_in is modified by side-effects and returned as pt_out More...
 
pt_map application_to_points_to (application, pt_map, bool)
 
pt_map condition_to_points_to (expression, pt_map, bool)
 Update points-to set "in" according to the content of the expression using side effects. More...
 
pt_map reference_condition_to_points_to (reference, pt_map, bool)
 Handle conditions such as "if(p)". More...
 
pt_map call_condition_to_points_to (call, pt_map, list, bool)
 Handle any condition that is a call such as "if(p!=q)", "if(*p)", "if(foo(p=q))"... More...
 
pt_map intrinsic_call_condition_to_points_to (call, pt_map, bool)
 We can break down the intrinsics according to their arity or according to their kinds... More...
 
pt_map user_call_condition_to_points_to (call, pt_map, list, bool)
 
pt_map boolean_intrinsic_call_condition_to_points_to (call, pt_map, bool)
 Deal with "!", "&&", "||" etc. More...
 
bool cell_is_less_than_or_equal_to_p (cell, cell)
 See if you can decide that the addresses linked to c1 are smaller than the addresses linked to c2. More...
 
bool cell_is_less_than_p (cell, cell)
 
bool cell_is_greater_than_or_equal_to_p (cell, cell)
 
bool cell_is_greater_than_p (cell, cell)
 
pt_map null_equal_condition_to_points_to (expression, pt_map)
 The condition is e==NULL. More...
 
pt_map null_non_equal_condition_to_points_to (expression, pt_map)
 The condition is e!=NULL. More...
 
pt_map equal_condition_to_points_to (list, pt_map)
 The expression list "al" contains exactly two arguments, "lhs" and "rhs". More...
 
pt_map non_equal_condition_to_points_to (list, pt_map)
 The expression list "al" contains exactly two arguments. More...
 
pt_map order_condition_to_points_to (entity, list, bool, pt_map)
 The expression list "al" contains exactly two arguments. More...
 
pt_map relational_intrinsic_call_condition_to_points_to (call, pt_map, bool)
 Update the points-to information "in" according to the validity of the condition. More...
 
void points_to_storage (set, statement, bool)
 passes.c More...
 
void fi_points_to_storage (pt_map, statement, bool)
 
pt_map points_to_to_context_points_to (pt_map)
 Return the subset of "in" that is related to formal parameters and stubs. More...
 
void init_points_to_context (pt_map)
 
void reset_points_to_context (void)
 
pt_map update_points_to_graph_with_arc (points_to, pt_map)
 Instead of simply adding the new arc, make sure the consistency is not broken. More...
 
void add_arc_to_points_to_context (points_to)
 FI: it should rather work the other way round, with add_arc_to_statement_points_to_context() calling add_arc_to_points_to_context(). More...
 
void update_points_to_context_with_arc (points_to)
 Same as , but be careful about the arc before adding it to the points-to context. More...
 
pt_map get_points_to_context (void)
 
void clean_up_points_to_stubs (entity)
 
bool init_points_to_analysis (char *)
 
bool interprocedural_points_to_analysis_p (void)
 
bool fast_interprocedural_points_to_analysis_p (void)
 
bool intraprocedural_points_to_analysis (char *)
 
bool interprocedural_points_to_analysis (char *)
 
bool fast_interprocedural_points_to_analysis (char *)
 
bool initial_points_to (char *)
 Retrieve points-to that are statically initialized, especially in compilation units. More...
 
bool program_points_to (char *)
 
list entity_to_sinks (entity)
 sinks.c More...
 
cell entity_to_cell (entity)
 
list points_to_null_sinks (void)
 
cell make_null_cell (void)
 
list points_to_anywhere_sinks (type)
 
list call_to_points_to_sinks (call, type, pt_map, bool, bool)
 
list intrinsic_call_to_points_to_sinks (call, pt_map, bool, bool)
 
list unary_intrinsic_call_to_points_to_sinks (call, pt_map, bool, bool)
 
list binary_intrinsic_call_to_points_to_sinks (call, pt_map, bool)
 
list expression_to_points_to_sinks_with_offset (expression, expression, pt_map)
 
list ternary_intrinsic_call_to_points_to_sinks (call, pt_map, bool, bool)
 
list nary_intrinsic_call_to_points_to_sinks (call, pt_map)
 
reference simplified_reference (reference)
 Return NULL as sink. More...
 
list pointer_reference_to_points_to_sinks (reference, pt_map, bool)
 What to do when a pointer "p" is dereferenced within a reference "r". More...
 
list reference_to_points_to_sinks (reference, type, pt_map, bool, bool)
 Returns a list of memory cells "sinks" possibly accessed by the evaluation of reference "r". More...
 
list cast_to_points_to_sinks (cast, type, pt_map, bool)
 
list sizeofexpression_to_points_to_sinks (sizeofexpression, type, pt_map)
 
void init_heap_model (statement)
 
void reset_heap_model (void)
 
statement get_heap_statement (void)
 
int get_heap_counter (void)
 
list malloc_to_points_to_sinks (expression, pt_map)
 Heap modelling. More...
 
list unique_malloc_to_points_to_sinks (expression)
 FI->AM: is "unique" multiple when ALIASING_ACROSS_TYPE is set to false? More...
 
list insensitive_malloc_to_points_to_sinks (expression)
 FI->AM: what's the difference with the previous option? Reference to your dissertation? More...
 
list flow_sensitive_malloc_to_points_to_sinks (expression)
 
list application_to_points_to_sinks (application, type, pt_map)
 
expression pointer_subscript_to_expression (cell, list)
 Allocate a new expression based on the reference in "c" and the subscript list "csl". More...
 
list subscript_to_points_to_sinks (subscript, type, pt_map, bool)
 Generate the corresponding points-to reference(s). More...
 
list range_to_points_to_sinks (range, pt_map)
 
list expression_to_points_to_cells (expression, pt_map, bool, bool)
 Return a possibly empty list of abstract locations whose addresses are possible value of expression "e" evaluated with points-to information "in". More...
 
list expression_to_points_to_sinks (expression, pt_map)
 The returned list contains cells used in "in". More...
 
list expression_to_points_to_sources (expression, pt_map)
 expression_to_points_to_sources() does not always work, especially with pointer arithmetic or subscripting because p[3], for instance, is not recognized as a valid source: it is not a constant path More...
 
bool reference_must_points_to_null_p (reference, pt_map)
 
bool reference_may_points_to_null_p (reference, pt_map)
 
bool control_in_set_p (control, set)
 unstructured.c More...
 
bool control_equal_p (const void *, const void *)
 
_uint control_rank (const void *, size_t)
 create a key which is the statement number More...
 
bool Ready_p (control, set, set)
 A node is ready to be processed if its predecessors are not reachable or processed. More...
 
set ready_to_be_processed_set (control, set, set)
 A set containing all the successors of n that are ready to be processed. More...
 
pt_map new_points_to_unstructured (unstructured, pt_map, bool)
 
list variable_to_pointer_locations (entity)
 variable.c More...
 
list struct_variable_to_pointer_locations (entity, entity)
 return list of cells for pointers declared directly or indirecltly in variable "e" of type struct defined by entity "ee" and its type. More...
 
list struct_variable_to_pointer_subscripts (cell, entity)
 returns a list of cells to reach pointers depending on field f. More...
 
list points_to_cells_parameters (list)
 interprocedural.c More...
 
list points_to_cells_pointer_arguments (list)
 Transform a list of arguments of type "expression" to a list of cells. More...
 
points_to_graph user_call_to_points_to (call, points_to_graph, list)
 FI: limited to the interprocedural option. More...
 
list user_call_to_points_to_sinks (call, type, pt_map, bool)
 
void remove_arcs_from_pt_map (points_to, set)
 
pt_map user_call_to_points_to_fast_interprocedural (call, pt_map, list)
 
bool recursive_filter_formal_context_according_to_actual_context (list, set, set, set, set)
 This function looks for successors of elements of list "fcl" both in points-to relations "pt_in" and "pt_binded". More...
 
set filter_formal_context_according_to_actual_context (list, set, set, set)
 Filter "pt_in" according to "pt_binded". More...
 
set new_filter_formal_context_according_to_actual_context (list, set, set, set)
 
set filter_formal_out_context_according_to_formal_in_context (set, set, list, entity)
 If an address has not been written, i.e. More...
 
void points_to_translation_of_struct_formal_parameter (cell, cell, approximation, type, set)
 
bool points_to_translation_mapping_is_typed_p (set)
 
void points_to_translation_of_formal_parameters (list, list, pt_map, set)
 List al and fpcl are assumed consistent, and consistent with the formal parameter ranks. More...
 
void add_implicitly_killed_arcs_to_kill_set (set, list, set, set, set, entity)
 Initial comments: add arcs of set "pt_caller" to set "pt_kill" if their origin cells are not in the list of written pointers "wpl" but is the origin of some exact arc in "pt_out_callee_filtered". More...
 
list translation_transitive_closure (cell, set)
 
bool aliased_translation_p (list, set)
 See if two cells in "fpcl" point toward the same location via the transitive closure of "translation". More...
 
set user_call_to_points_to_interprocedural_binding_set (call, pt_map)
 Compute the binding relations in a complete interprocedural way: be as accurate as possible. More...
 
pt_map user_call_to_points_to_interprocedural (call, pt_map)
 Compute the points-to relations in a complete interprocedural way: be as accurate as possible. More...
 
pt_map user_call_to_points_to_intraprocedural (call, pt_map, list)
 
set compute_points_to_kill_set (list, set, set)
 
list points_to_cell_translation (cell, set, entity)
 Compute the list of cells that correspond to cell "sr1" according to the translation mapping "bm" when function "f" is called. More...
 
list generic_points_to_cells_translation (list, set, entity, bool)
 Allocate a new list with the translations of the cells in cl, when their translation make sense. More...
 
list points_to_cells_translation (list, set, entity)
 Allocate a new list with the translations of the cells in cl, when their translation make sense. More...
 
list points_to_cells_exact_translation (list, set, entity)
 Allocate a new list with the translations of the cells in cl, when their translation make sense and is unique (one-to-one mapping). More...
 
set compute_points_to_gen_set (set, list, set, entity)
 Translate the out set in the scope of the caller using the binding information, but eliminate irrelevant arcs using Written and the type of the source. More...
 
set points_to_binding_arguments (cell, cell, set, set)
 Recursively find all the arcs, "ai", starting from the argument "c1" using "in", find all the arcs, "aj", starting from the parameter "c2" using "pt_binded", map each node "ai" to its corresponding "aj" and store the "ai->aj" arc in a new set, "bm". More...
 
list written_pointers_set (list)
 Filter out written effects on pointers. More...
 
list certainly_written_pointers_set (list)
 Filter out certainly written effects on pointers. More...
 
set compute_points_to_binded_set (entity, list, set, bool *)
 For each actual argument "r" and its corresponding formal one "f", create the assignment "f = r;" and then compute the points-to set "s" generated by the assignment. More...
 
set points_to_binding (list, set, set)
 Apply points_to_binding_arguments() to each pair (, complete the process of binding each element of "in" to its corresponding memory address at the call site. More...
 
list generic_points_to_set_to_stub_cell_list (entity, set, list)
 Add cells referencing a points-to stub found in parameter "s" are copied and added to list "osl". More...
 
list points_to_set_to_stub_cell_list (set, list)
 
list points_to_set_to_module_stub_cell_list (entity, set, list)
 
cell points_to_source_alias (points_to, set)
 Let "pt_binded" be the results of assignments of actual arguments to formal arguments (see compute_points_to_binded_set()). More...
 
pt_map dereferencing_subscript_to_points_to (subscript, pt_map)
 dereferencing.c More...
 
pt_map dereferencing_to_points_to (expression, pt_map)
 Make sure that expression p can be dereferenced in points-to graph "in". More...
 
bool pointer_points_to_reference_p (reference)
 
void pointer_reference_dereferencing_to_points_to (reference, pt_map)
 
pt_map reference_dereferencing_to_points_to (reference, pt_map, bool, bool)
 Can we execute the reference r in points-to context "in" without segfaulting? More...
 
bool expression_to_points_to_cell_p (expression)
 Can expression e be reduced to a reference, without requiring an evaluation? More...
 
list dereferencing_to_sinks (expression, pt_map, bool)
 Returns "sinks", the list of cells pointed to by expression "a" according to points-to graph "in". More...
 
cell make_nowhere_cell (void)
 constant-path-utils.c More...
 
cell make_typed_nowhere_cell (type)
 
cell cell_to_nowhere_sink (cell)
 assuming source is a reference to a pointer, build the corresponding sink when the pointer is not initialized, i.e. More...
 
set points_to_anywhere_typed (list, set)
 Already exists in points_to_general_algorithm.c, to be removed later... More...
 
set points_to_anywhere (list, set)
 
list array_to_constant_paths (expression, set)
 
cell max_module (cell, cell)
 we define operator max fot the lattice Module which has any_module as top and a bottom which is not yet clearly defined (maybe no_module) max_module : Module * Module -> Module Side effects on m1 if we have an anywhere location to return. More...
 
bool entity_any_module_p (entity)
 operator kill for the dimension Module: More...
 
bool opkill_may_module (cell, cell)
 
bool opkill_must_module (cell, cell)
 
cell op_gen_module (cell, cell)
 
bool opkill_may_name (cell, cell)
 We define operators for the lattice Name which can be a: -variable of a the program -malloc -NULL /0 -STATIC/STACK/DYNAMIC/HEAP/FORMAL -nowhere/anywhere. More...
 
bool opkill_must_name (cell, cell)
 
type max_type (type, type)
 
bool opkill_may_type (type, type)
 
bool opkill_must_type (type, type)
 opkill_must_type is the same as op_kill_may_type... More...
 
type opgen_may_type (type, type)
 
type opgen_must_type (type, type)
 the same as opgen_may_type More...
 
bool opkill_may_reference (cell, cell)
 
bool opkill_must_reference (cell, cell)
 
bool opkill_may_vreference (cell, cell)
 FI: really weird and unefficient. More...
 
bool opkill_must_vreference (cell, cell)
 returns true if c2 must kills c1 because of the subscript expressions More...
 
bool opkill_may_constant_path (cell, cell)
 
bool opkill_must_constant_path (cell, cell)
 returns true if c2 kills c1 More...
 
set kill_may_set (list, set)
 Compute the set of arcs in the input points-to relation "in" whose approximation must be changed from "exact" to "may". More...
 
set kill_must_set (list, set)
 Generate the subset of arcs that must be removed from the points-to graph "in". More...
 
set points_to_may_filter (set)
 returns a set which contains all the MAY points to More...
 
set points_to_must_filter (set)
 returns a set which contains all the EXACT points to More...
 
bool address_of_expression_p (expression)
 shoud be moved to expression.c More...
 
bool subscript_expression_p (expression)
 
set gen_may_set (list, list, set, bool *)
 Should be moved to anywhere_abstract_locations.c. More...
 
set gen_must_set (list, list, set, bool *)
 
bool unique_location_cell_p (cell)
 Does cell "c" represent a unique memory location or a set of memory locations? More...
 
set gen_may_constant_paths (cell, list, set, bool *, int)
 
set gen_must_constant_paths (cell, list, set, bool *, int)
 Build a set of arcs from cell l towards cells in list R if *address_p is true, or towards cells pointed by cells in list R if not. More...
 
points_to opgen_may_constant_path (cell, cell)
 
points_to opgen_must_constant_path (cell, cell)
 
bool opgen_may_module (entity, entity)
 
bool opgen_must_module (entity, entity)
 
bool opgen_may_name (entity, entity)
 
bool opgen_must_name (entity, entity)
 
bool opgen_may_vreference (list, list)
 
bool atomic_constant_path_p (cell)
 Could be replaced by abstract_location_p() but this later don't take into account the null location. More...
 
set opgen_null_location (set, cell)
 
set points_to_independent_store (set)
 
bool equal_must_vreference (cell, cell)
 
set points_to_nowhere (list, set)
 arg1: list of cells arg2: set of points-to Create a points-to set with elements of lhs_list as source and NOWHERE as sink. More...
 

Macro Definition Documentation

◆ assign_pt_map

#define assign_pt_map (   x,
 
)    ((void) set_assign(points_to_graph_set(x), points_to_graph_set(y)), (x))

Definition at line 77 of file points-to.h.

◆ clear_pt_map

#define clear_pt_map (   pt)    set_clear(points_to_graph_set(pt))

Definition at line 78 of file points-to.h.

◆ consistent_pt_map_p

#define consistent_pt_map_p (   s)    consistent_points_to_graph_p(s)

Definition at line 95 of file points-to.h.

◆ difference_of_pt_maps

#define difference_of_pt_maps (   pt1,
  pt2,
  pt3 
)
Value:
set set_difference(set, const set, const set)
Definition: set.c:256
#define points_to_graph_set(x)

Definition at line 88 of file points-to.h.

◆ empty_pt_map_p

#define empty_pt_map_p (   s)    set_empty_p(points_to_graph_set(s))

Definition at line 93 of file points-to.h.

◆ free_pt_map

#define free_pt_map (   pt)    free_points_to_graph(pt)

Definition at line 80 of file points-to.h.

◆ free_pt_maps

#define free_pt_maps   free_points_to_graph_sets

Definition at line 83 of file points-to.h.

◆ new_pt_map

Definition at line 75 of file points-to.h.

◆ new_simple_pt_map

#define new_simple_pt_map ( )    set_generic_make(set_private, points_to_equal_p, points_to_rank)

Definition at line 76 of file points-to.h.

◆ print_pt_map

#define print_pt_map (   pt)    print_points_to_set("", points_to_graph_set(pt));

Definition at line 81 of file points-to.h.

◆ pt_map_undefined

#define pt_map_undefined   points_to_graph_undefined

Definition at line 73 of file points-to.h.

◆ pt_map_undefined_p

#define pt_map_undefined_p (   pt)    ((pt)==points_to_graph_undefined)

Definition at line 74 of file points-to.h.

◆ remove_arc_from_pt_map

#define remove_arc_from_pt_map (   a,
 
)    (set_del_element((set) points_to_graph_set(s), (set) points_to_graph_set(s), (void *) a))

Definition at line 105 of file points-to.h.

◆ remove_arc_from_pt_map_

#define remove_arc_from_pt_map_ (   a,
 
)    (remove_arc_from_pt_map(a, s), (s))

Definition at line 106 of file points-to.h.

◆ SEQUENTIAL_POINTS_TO_SETS_SUFFIX

#define SEQUENTIAL_POINTS_TO_SETS_SUFFIX   ".pt"

Warning! Do not modify this file that is automatically generated!

Modify src/Libs/points-to/points-to-local.h instead, to add your own modifications. header file built by cproto points_to-local.h

Definition at line 34 of file points-to.h.

◆ source_in_pt_map_p

#define source_in_pt_map_p (   cell,
  set 
)    source_in_set_p(cell,points_to_graph_set(set))

Definition at line 97 of file points-to.h.

◆ union_of_pt_maps

#define union_of_pt_maps (   pt1,
  pt2,
  pt3 
)
Value:
set set_union(set, const set, const set)
Definition: set.c:211

Definition at line 85 of file points-to.h.

◆ USER_POINTS_TO_SETS_SUFFIX

#define USER_POINTS_TO_SETS_SUFFIX   ".upt"

Definition at line 35 of file points-to.h.

Typedef Documentation

◆ pt_map

Definition at line 72 of file points-to.h.

Function Documentation

◆ add_arc_to_points_to_context()

void add_arc_to_points_to_context ( points_to  pt)

FI: it should rather work the other way round, with add_arc_to_statement_points_to_context() calling add_arc_to_points_to_context().

Parameters
ptt

Definition at line 268 of file passes.c.

269 {
270  pips_assert("points_to_context is defined",
272  //(void) update_points_to_graph_with_arc(pt, points_to_context);
274  pips_assert("in is consistent", consistent_pt_map_p(points_to_context));
275  points_to npt = copy_points_to(pt);
277 }
points_to copy_points_to(points_to p)
POINTS_TO.
#define add_arc_to_pt_map(a, s)
#define pt_map_undefined_p(pt)
#define consistent_pt_map_p(s)
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
static pt_map points_to_context
Definition: passes.c:149
void add_arc_to_statement_points_to_context(points_to)
Definition: statement.c:104

References add_arc_to_pt_map, add_arc_to_statement_points_to_context(), consistent_pt_map_p, copy_points_to(), pips_assert, points_to_context, and pt_map_undefined_p.

Referenced by dereferencing_subscript_to_points_to(), formal_source_to_sinks(), generic_stub_source_to_sinks(), global_source_to_sinks(), and null_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ add_arc_to_pt_map()

void add_arc_to_pt_map ( points_to  a,
pt_map  s 
)

Add a store independent points-to arc: source and destination references include no dereferencing nor varying subscript such as a[i].

Definition at line 3555 of file points_to_set.c.

3556 {
3557  // consistent_points_to_arc_p() does not return with a non-consistent arc;
3558  bool consistent_p = store_independent_points_to_arc_p(a);
3559  if(consistent_p)
3561  (set) points_to_graph_set(s),
3562  (void *) a);
3563 }
set set_add_element(set, const set, const void *)
Definition: set.c:152
bool store_independent_points_to_arc_p(points_to a)
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59

References points_to_graph_set, set_add_element(), and store_independent_points_to_arc_p().

Referenced by fuse_points_to_sink_cells(), normalize_points_to_graph(), source_to_sinks(), and upgrade_approximations_in_points_to_set().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ add_arc_to_pt_map_()

pt_map add_arc_to_pt_map_ ( points_to  a,
pt_map  s 
)

Definition at line 3565 of file points_to_set.c.

3566 {
3567  // consistent_points_to_arc_p() does not return with a non-consistent arc;
3568  bool consistent_p = store_independent_points_to_arc_p(a);
3569  if(consistent_p)
3571  (set) points_to_graph_set(s),
3572  (void *) a);
3573  return s;
3574 }

References points_to_graph_set, set_add_element(), and store_independent_points_to_arc_p().

Referenced by anywhere_source_to_sinks(), assignment_to_points_to(), formal_source_to_sinks(), generic_stub_source_to_sinks(), global_source_to_sinks(), and null_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ add_arc_to_simple_pt_map()

set add_arc_to_simple_pt_map ( points_to  a,
set  s 
)

Definition at line 3576 of file points_to_set.c.

3577 {
3578  // consistent_points_to_arc_p() does not return with a non-consistent arc;
3579  bool consistent_p = store_independent_points_to_arc_p(a);
3580  if(consistent_p)
3581  s = set_add_element(s, s, (void *) a);
3582  return s;
3583 }

References set_add_element(), and store_independent_points_to_arc_p().

Referenced by points_to_set_block_projection(), and remove_points_to_cell().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ add_arc_to_statement_points_to_context()

void add_arc_to_statement_points_to_context ( points_to  pt)
Parameters
ptt

Definition at line 104 of file statement.c.

105 {
107  add_arc_to_pt_map(pt, in);
108  //update_points_to_graph_with_arc(pt, in);
109  pips_assert("in is consistent", consistent_pt_map_p(in));
110 }
void * stack_head(const stack)
returns the item on top of stack s
Definition: stack.c:420
static stack statement_points_to_context
The input points-to information of a statement is updated by the analysis of the statement because of...
Definition: statement.c:87

References add_arc_to_pt_map, consistent_pt_map_p, pips_assert, stack_head(), and statement_points_to_context.

Referenced by add_arc_to_points_to_context(), and dereferencing_subscript_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ add_implicitly_killed_arcs_to_kill_set()

void add_implicitly_killed_arcs_to_kill_set ( set  pt_kill,
list  wpl,
set  pt_caller,
set  pt_out_callee_filtered,
set  binding,
entity  f 
)

Initial comments: add arcs of set "pt_caller" to set "pt_kill" if their origin cells are not in the list of written pointers "wpl" but is the origin of some exact arc in "pt_out_callee_filtered".

This is beneficial when "pt_out" is more precise than "pt_caller" because of a free or a test. This is detrimental when "pt_caller" is more precise than "pt_out_callee_filtered" because the intraprocedural analysis of the callee had to assume a possible NULL pointer that did not really exist (see Mensi.sub/struct_inter03.c). So it would be better to compute the intersection of "pt_caller" and "translation(pt_out, binding)" and to kill all arcs in "pt_caller" minus this intersection... if they are related in some way to the callee... Some more thinking needed.

Equations retrieved from the C code

K = { c | \exits pt c=source(pt) !\in Written ^ |translation(source(pt), binding, f)|==1 ^ atomic(translation(source(pt), binding, f) }

pt_kill = {pt in pt_caller | \exists c \in K binding(c)==source(pt)}

K is a set of cells defined in the frame of the callee and pt_kill a set of points-to defined in the frame of the caller.

Examples:

Indirect free of a pointed cell

"main() {p = malloc(); * my_free(p);}" with "my_free(int * p) {free(p);}".

p->heap in pt_caller must be removed from pt_end, hence p->heap belongs to pt_kill

Other possibilities must be linked to tests and executions errors.

void foo(int * ap) {bar(ap);}

void bar(int * fp) { *p = 1;}

As a result ap->_ap_1, EXACT because ap->NULL has been killed

void bar(int * fp) {if(fp==NULL) exit(1); return;}

The result should be the same as above.

Arc out_pt has been implicitly obtained

Parameters
pt_killt_kill
wplpl
pt_callert_caller
pt_out_callee_filteredt_out_callee_filtered
bindinginding

Definition at line 1663 of file interprocedural.c.

1669 {
1670  SET_FOREACH(points_to, out_pt, pt_out_callee_filtered) {
1671  cell source = points_to_source(out_pt);
1672  if(!points_to_cell_in_list_p(source, wpl)) {
1673  /* Arc out_pt has been implicitly obtained */
1675  // FI: let's assume that approximation subsumes atomicity
1676  if(approximation_exact_p(a)) {
1677  // source is defined in the formal context
1678  //points_to_graph binding_g =
1679  // make_points_to_graph(false, binding);
1680  // list tl = points_to_source_to_sinks(source, binding_g, false);
1681  list tl = points_to_cell_translation(source, binding, f);
1682  int ntl = (int) gen_length(tl);
1683  cell t_source = cell_undefined;
1684  if(ntl==1) {
1685  t_source = CELL(CAR(tl));
1686  if(generic_atomic_points_to_cell_p(t_source, false)) {
1687  SET_FOREACH(points_to, pt, pt_caller) {
1688  cell pt_source = points_to_source(pt);
1689  if(points_to_cell_equal_p(t_source, pt_source)) {
1690  // FI: do not worry about sharing of arcs
1691  add_arc_to_simple_pt_map(pt, pt_kill);
1692  }
1693  }
1694  }
1695  gen_free_list(tl);
1696  }
1697  }
1698  }
1699  }
1700 }
#define add_arc_to_simple_pt_map(a, s)
void const char const char const int
bool points_to_cell_equal_p(cell, cell)
Definition: points_to.c:916
bool generic_atomic_points_to_cell_p(cell, bool)
Is it a unique concrete memory location?
Definition: points_to.c:452
bool points_to_cell_in_list_p(cell, list)
Definition: points_to.c:117
#define cell_undefined
Definition: effects.h:430
#define approximation_exact_p(x)
Definition: effects.h:369
#define CELL(x)
CELL.
Definition: effects.h:424
size_t gen_length(const list l)
Definition: list.c:150
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
list points_to_cell_translation(cell sr1, set binding, entity f)
Compute the list of cells that correspond to cell "sr1" according to the translation mapping "bm" whe...
#define points_to_approximation(x)
#define points_to_source(x)
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

References add_arc_to_simple_pt_map, approximation_exact_p, CAR, CELL, cell_undefined, f(), gen_free_list(), gen_length(), generic_atomic_points_to_cell_p(), int, points_to_approximation, points_to_cell_equal_p(), points_to_cell_in_list_p(), points_to_cell_translation(), points_to_source, and SET_FOREACH.

Referenced by user_call_to_points_to_interprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ add_subscript_dependent_arc_to_simple_pt_map()

set add_subscript_dependent_arc_to_simple_pt_map ( points_to  a,
set  s 
)

The source and destination references imply no dereferencing but the subscripts may be any kind of expression, such as a[i].

This is not possible in general, but may be useful at a specific statement level. This used to handle precisely the backward translation at call sites, especially for simple and convex effects backward translation.

Definition at line 3599 of file points_to_set.c.

3600 {
3601  // consistent_points_to_arc_p() does not return with a non-consistent arc;
3602  bool consistent_p = dereferencing_free_points_to_arc_p(a);
3603  if(consistent_p)
3604  s = set_add_element(s, s, (void *) a);
3605  return s;
3606 }
bool dereferencing_free_points_to_arc_p(points_to a)

References dereferencing_free_points_to_arc_p(), and set_add_element().

Referenced by compute_points_to_binded_set(), filter_formal_context_according_to_actual_context(), new_filter_formal_context_according_to_actual_context(), and points_to_translation_of_formal_parameters().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ address_of_expression_p()

bool address_of_expression_p ( expression  e)

shoud be moved to expression.c

Definition at line 741 of file constant-path-utils.c.

742 {
743  bool address_of_p = false;
744  syntax s = expression_syntax(e);
745  if (syntax_call_p(s)) {
746  if (entity_an_operator_p(call_function(syntax_call(s)), ADDRESS_OF))
747  address_of_p = true;
748  }
749  return address_of_p;
750 }
#define entity_an_operator_p(e, name)
macros
#define call_function(x)
Definition: ri.h:709
#define syntax_call_p(x)
Definition: ri.h:2734
#define syntax_call(x)
Definition: ri.h:2736
#define expression_syntax(x)
Definition: ri.h:1247

References call_function, entity_an_operator_p, expression_syntax, syntax_call, and syntax_call_p.

◆ aliased_translation_p()

bool aliased_translation_p ( list  fpcl,
set  translation 
)

See if two cells in "fpcl" point toward the same location via the transitive closure of "translation".

| must_conflict_p

Print the transitive closures

Clean up the hash-table...

Parameters
fpclpcl
translationranslation

Definition at line 1735 of file interprocedural.c.

1736 {
1737  bool alias_p = false;
1738  hash_table closure = hash_table_make(hash_pointer, 0);
1739  list c_fpcl = fpcl;
1740  list p_fpcl = fpcl;
1741 
1742  for( ; !ENDP(c_fpcl); POP(c_fpcl)) {
1743  cell c = CELL(CAR(c_fpcl));
1744  list succ_l = translation_transitive_closure(c, translation);
1745  hash_put(closure, (void *) c, (void *) succ_l);
1746  for(p_fpcl = fpcl; p_fpcl!=c_fpcl; POP(p_fpcl)) {
1747  cell p_c = CELL(CAR(p_fpcl));
1748  list p_succ_l = (list) hash_get(closure, (void *) p_c);
1749  list c_succ_l = gen_copy_seq(succ_l);
1750  // FI: this is not sufficient, conflicts between cells should be
1751  // checked to take into account abstract locations.
1752  // gen_list_and(&c_succ_l, p_succ_l);
1753  bool may_conflict_p = points_to_cell_lists_may_conflict_p(c_succ_l, p_succ_l);
1754  bool must_conflict_p = points_to_cell_lists_must_conflict_p(c_succ_l, p_succ_l);
1755  //if(!ENDP(c_succ_l)) {
1756  if(may_conflict_p /*|| must_conflict_p*/ ) { // must implies may I guess
1757  alias_p = true;
1758  gen_free_list(c_succ_l);
1761 
1763  pips_user_warning("%saliasing detected between formal parameters "
1764  "\"%s\" and \"%s\" at line %d.\n",
1765  must_conflict_p? "" : "possible ",
1766  entity_user_name(fp1),
1767  entity_user_name(fp2),
1769  else {
1770  // In case this function is used in an effect context
1771  pips_user_warning("%saliasing detected between formal parameters "
1772  "\"%s\" and \"%s\".\n",
1773  must_conflict_p? "" : "possible ",
1774  entity_user_name(fp1),
1775  entity_user_name(fp2));
1776  }
1777  break;
1778  }
1779  gen_free_list(c_succ_l);
1780  }
1781  }
1782 
1783  if(alias_p) {
1784  /* Print the transitive closures */
1785  HASH_MAP(c, succs,
1787  fprintf(stderr, "\"%s\" -> ", entity_user_name(fp));
1788  print_points_to_cells((list) succs);
1789  fprintf(stderr, "\n");
1790  }, closure);
1791  }
1792 
1793  /* Clean up the hash-table... */
1794  HASH_MAP(c, succs, {gen_free_list((list) succs);}, closure);
1795 
1796  hash_table_free(closure);
1797  return alias_p;
1798 }
reference cell_any_reference(cell)
API for reference.
Definition: effects.c:77
bool points_to_cell_lists_must_conflict_p(list l1, list l2)
Same as above, but for lists.
Definition: conflicts.c:729
bool points_to_cell_lists_may_conflict_p(list l1, list l2)
Same as above, but for lists.
Definition: conflicts.c:703
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501
hash_table hash_table_make(hash_key_type key_type, size_t size)
Definition: hash.c:294
void * hash_get(const hash_table htp, const void *key)
this function retrieves in the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:449
void hash_put(hash_table htp, const void *key, const void *val)
This functions stores a couple (key,val) in the hash table pointed to by htp.
Definition: hash.c:364
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
#define pips_user_warning
Definition: misc-local.h:146
#define HASH_MAP(k, v, code, ht)
Definition: newgen_hash.h:60
@ hash_pointer
Definition: newgen_hash.h:32
struct cons * list
Definition: newgen_types.h:106
list translation_transitive_closure(cell c, set translation)
bool statement_points_to_context_defined_p(void)
Definition: statement.c:145
int points_to_context_statement_line_number(void)
Definition: statement.c:120
#define print_points_to_cells(x)
Definition: print.c:379
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
#define reference_variable(x)
Definition: ri.h:2326
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...

References CAR, CELL, cell_any_reference(), ENDP, entity_user_name(), fprintf(), gen_copy_seq(), gen_free_list(), hash_get(), HASH_MAP, hash_pointer, hash_put(), hash_table_free(), hash_table_make(), pips_user_warning, points_to_cell_lists_may_conflict_p(), points_to_cell_lists_must_conflict_p(), points_to_context_statement_line_number(), POP, print_points_to_cells, reference_variable, statement_points_to_context_defined_p(), and translation_transitive_closure().

Referenced by user_call_to_points_to_interprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ any_loop_to_points_to()

pt_map any_loop_to_points_to ( statement  b,
expression  init,
expression  c,
expression  inc,
pt_map  pt_in 
)

Perform the same k-limiting scheme for all kinds of loops.

The do while loop must use an external special treatment for the first iteration.

Derived from points_to_forloop() and from Amira's work.

pt_in is modified by side effects.

First, enter or skip the loop: initialization + condition check

Comput pt_out as loop invariant: pt_out holds at the beginning of the loop body.

pt_out(i) = f(pt_out(i-1)) U pt_out(i-1)

prev = pt_out(i-1)

Note: the pt_out variable is also used to carry the loop exit points-to set.

prev receives the current points-to information, pt_out

Depending on the kind of loops, execute the body and then possibly the incrementation and the condition

Merge the previous resut and the current result.

Check convergence

Add the last iteration to obtain the pt_out holding when exiting the loop

FI: I suppose that p[i] is replaced by p[*] and that MAY/MUST information is changed accordingly.

Parameters
initnit
incnc
pt_int_in

Definition at line 653 of file statement.c.

658 {
659  pt_map pt_out = pt_in;
660 
661  if(points_to_graph_bottom(pt_in)) {
662  (void) statement_to_points_to(b, pt_in);
663  }
664  else {
665  int i = 0;
666  // FI: k is linked to the cycles in points-to graph, and should not
667  // be linked to the number of convergence iterations. I assume here
668  // that the minimal number of iterations is greater than the
669  // k-limiting factor
670  int k = get_int_property("POINTS_TO_PATH_LIMIT")
671  + get_int_property("POINTS_TO_SUBSCRIPT_LIMIT")
672  + get_int_property("POINTS_TO_OUT_DEGREE_LIMIT")
673  +10; // Safety margin: might be set to max of both properties + 1 or 2...
674 
675  /* First, enter or skip the loop: initialization + condition check */
677  pt_out = expression_to_points_to(init, pt_out, true);
678  pt_map pt_out_skip = full_copy_pt_map(pt_out);
679  if(!expression_undefined_p(c)) {
680  pt_out = expression_to_points_to(c, pt_out, true);
681  pt_out = condition_to_points_to(c, pt_out, true);
682  pt_out_skip = condition_to_points_to(c, pt_out_skip, false);
683  }
684 
685  /* Comput pt_out as loop invariant: pt_out holds at the beginning of
686  * the loop body.
687  *
688  * pt_out(i) = f(pt_out(i-1)) U pt_out(i-1)
689  *
690  * prev = pt_out(i-1)
691  *
692  * Note: the pt_out variable is also used to carry the loop exit
693  * points-to set.
694  */
695  pt_map prev = new_pt_map();
696  // FI: it should be a while loop to reach convergence
697  // FI: I keep it a for loop for safety
698  bool fix_point_p = false;
699  for(i = 0; i<k+2 ; i++) {
700  /* prev receives the current points-to information, pt_out */
701  clear_pt_map(prev);
702  prev = assign_pt_map(prev, pt_out);
703  clear_pt_map(pt_out);
704 
705  /* Depending on the kind of loops, execute the body and then
706  possibly the incrementation and the condition */
707  // FI: here, storage_p would be useful to avoid unnecessary
708  // storage and update for each substatement at each iteration k
709  pt_out = statement_to_points_to(b, prev);
710  if(!expression_undefined_p(inc))
711  pt_out = expression_to_points_to(inc, pt_out, true);
712  // FI: should be condition_to_points_to() for conditions such as
713  // while(p!=q);
714  // The condition is not always defined (do loops)
715  if(!expression_undefined_p(c)) {
716  pt_out = condition_to_points_to(c, pt_out, true);
718  }
719 
720  /* Merge the previous resut and the current result. */
721  // FI: move to pt_map
722  pt_out = merge_points_to_graphs(prev, pt_out);
723 
724  pt_out = normalize_points_to_graph(pt_out);
726 
727  // pips_assert("", consistent_points_to_graph_p(pt_out));
728 
729  /* Check convergence */
731  fix_point_p = true;
732  /* Add the last iteration to obtain the pt_out holding when
733  exiting the loop */
734  pt_out = statement_to_points_to(b, prev);
735 
737  if(!expression_undefined_p(inc))
738  pt_out = expression_to_points_to(inc, pt_out, true);
739 
741  if(!expression_undefined_p(c))
742  pt_out = condition_to_points_to(c, pt_out, false);
743 
745  break;
746  }
747  else {
748  ifdebug(1) {
749  pips_debug(1, "\n\nAt iteration i=%d:\n\n", i);
750  print_points_to_set("Loop points-to set prev:\n",
751  points_to_graph_set(prev));
752  print_points_to_set("Loop points-to set pt_out:\n",
753  points_to_graph_set(pt_out));
754  }
755  }
756  }
757 
758  if(!fix_point_p) {
759  print_points_to_set("Loop points-to set prev:\n", points_to_graph_set(prev));
760  print_points_to_set("Loop points-to set pt_out:\n", points_to_graph_set(pt_out));
761  pips_internal_error("Loop convergence not reached in %d iterations.\n", i);
762  }
763 
764  /* FI: I suppose that p[i] is replaced by p[*] and that MAY/MUST
765  information is changed accordingly. */
767 
768  // pips_assert("", consistent_points_to_graph_p(pt_out));
769 
770  pt_out = merge_points_to_graphs(pt_out, pt_out_skip);
771  }
772 
773  // pips_assert("", consistent_points_to_graph_p(pt_out));
774 
775  return pt_out;
776 }
int get_int_property(const string)
#define clear_pt_map(pt)
#define assign_pt_map(x, y)
#define new_pt_map()
set points_to_independent_store(set s)
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_internal_error
Definition: misc-local.h:149
bool set_equal_p(const set, const set)
returns whether s1 == s2
Definition: set.c:316
pt_map condition_to_points_to(expression c, pt_map in, bool true_p)
Update points-to set "in" according to the content of the expression using side effects.
Definition: expression.c:2512
pt_map expression_to_points_to(expression e, pt_map pt_in, bool side_effect_p)
Update pt_in and pt_out according to expression e.
Definition: expression.c:115
pt_map full_copy_pt_map(pt_map in)
Definition: statement.c:67
pt_map statement_to_points_to(statement s, pt_map pt_in)
See points_to_statement()
Definition: statement.c:154
void upgrade_approximations_in_points_to_set(pt_map)
When arcs have been removed from a points-to relation, the approximations of remaining arcs may not c...
pt_map normalize_points_to_graph(pt_map)
For the time being, control the out-degree of the vertices in points-to graph "ptg" and fuse the vert...
void print_points_to_set(string, set)
pt_map remove_unreachable_stub_vertices_in_points_to_graph(pt_map)
bool consistent_points_to_graph_p(points_to_graph)
pt_map merge_points_to_graphs(pt_map, pt_map)
#define points_to_graph_bottom(x)
static int init
Maximal value set for Fortran 77.
Definition: entity.c:320
#define expression_undefined_p(x)
Definition: ri.h:1224
#define ifdebug(n)
Definition: sg.c:47

References assign_pt_map, clear_pt_map, condition_to_points_to(), consistent_points_to_graph_p(), expression_to_points_to(), expression_undefined_p, full_copy_pt_map(), get_int_property(), ifdebug, init, merge_points_to_graphs(), new_pt_map, normalize_points_to_graph(), pips_assert, pips_debug, pips_internal_error, points_to_graph_bottom, points_to_graph_set, points_to_independent_store(), print_points_to_set(), remove_unreachable_stub_vertices_in_points_to_graph(), set_equal_p(), statement_to_points_to(), and upgrade_approximations_in_points_to_set().

Referenced by forloop_to_points_to(), loop_to_points_to(), and whileloop_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ any_source_to_sinks()

list any_source_to_sinks ( cell  source,
pt_map  pts,
bool  fresh_p 
)

Generalization of source_to_sinks().

The source does not have to be a pointer.

Parameters
sourceource
ptsts
fresh_presh_p

Definition at line 2404 of file points_to_set.c.

2405 {
2406  list sinks = NIL;
2407  bool to_be_freed;
2408  type source_t = points_to_cell_to_type(source, & to_be_freed);
2409  type c_source_t = compute_basic_concrete_type(source_t);
2410 
2411  if(pointer_type_p(c_source_t))
2412  sinks = source_to_sinks(source, pts, fresh_p);
2413  else if(struct_type_p(c_source_t)) {
2414  list fl = derived_type_to_fields(c_source_t);
2415  FOREACH(ENTITY, f, fl) {
2417  if(pointer_type_p(f_t) || struct_type_p(f_t)
2418  || array_of_pointers_type_p(f_t)
2419  || array_of_struct_type_p(f_t)) {
2420  cell n_source = copy_cell(source);
2422  sinks = any_source_to_sinks(n_source, pts, fresh_p);
2423  free_cell(n_source);
2424  }
2425  }
2426  }
2427  else if(array_of_pointers_type_p(c_source_t)) {
2428  cell n_source = copy_cell(source);
2430  sinks = source_to_sinks(source, pts, fresh_p);
2431  free_cell(n_source);
2432  }
2433  else if(array_of_struct_type_p(c_source_t)) {
2434  cell n_source = copy_cell(source);
2436  sinks = any_source_to_sinks(source, pts, fresh_p);
2437  free_cell(n_source);
2438  }
2439 
2440  return sinks;
2441 }
void free_cell(cell p)
Definition: effects.c:249
cell copy_cell(cell p)
CELL.
Definition: effects.c:246
type points_to_cell_to_type(cell, bool *)
FI: I need more generality than is offered by cell_to_type()
Definition: type.c:665
cell points_to_cell_add_field_dimension(cell, entity)
Functions about points-to cells - There is no cell.c file.
Definition: effects.c:1444
void points_to_cell_add_unbounded_subscripts(cell)
Definition: effects.c:1632
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
list source_to_sinks(cell source, pt_map pts, bool fresh_p)
Return a list of cells, "sinks", that are sink for some arc whose source is "source" or related to "s...
list any_source_to_sinks(cell source, pt_map pts, bool fresh_p)
Generalization of source_to_sinks().
bool array_of_pointers_type_p(type)
Definition: type.c:3025
type entity_basic_concrete_type(entity)
retrieves or computes and then returns the basic concrete type of an entity
Definition: type.c:3677
bool pointer_type_p(type)
Check for scalar pointers.
Definition: type.c:2993
list derived_type_to_fields(type)
Definition: type.c:5381
bool struct_type_p(type)
Returns true if t is of type derived and if the derived type is a struct.
Definition: type.c:3121
type compute_basic_concrete_type(type)
computes a new type which is the basic concrete type of the input type (this new type is not stored i...
Definition: type.c:3556
bool array_of_struct_type_p(type)
Definition: type.c:3133
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755

References any_source_to_sinks(), array_of_pointers_type_p(), array_of_struct_type_p(), compute_basic_concrete_type(), copy_cell(), derived_type_to_fields(), ENTITY, entity_basic_concrete_type(), f(), FOREACH, free_cell(), NIL, pointer_type_p(), points_to_cell_add_field_dimension(), points_to_cell_add_unbounded_subscripts(), points_to_cell_to_type(), source_to_sinks(), and struct_type_p().

Referenced by any_source_to_sinks(), and recursive_filter_formal_context_according_to_actual_context().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ anywhere_source_to_sinks()

list anywhere_source_to_sinks ( cell  source,
pt_map  pts 
)

source is assumed to be either nowhere/undefined or anywhere, it may be typed or not.

Shouldn't we create NULL pointers if the corresponding property is set? Does it matter for anywhere/nowhere?

pts must be updated with the new arc(s).

FI: we should return an anywhere cell with the proper type

FI: should we add the corresponding arcs in pts?

FI: should we take care of typed anywhere as well?

Parameters
sourceource
ptsts

Definition at line 718 of file points_to_set.c.

719 {
720  /* FI: we should return an anywhere cell with the proper type */
721  /* FI: should we add the corresponding arcs in pts? */
722  /* FI: should we take care of typed anywhere as well? */
723 
724  list sinks = NIL;
725  // reference r = cell_any_reference(source);
726  // entity v = reference_variable(r);
727  // FI: it would be better to print the reference... words_reference()...
728  // FI: sinks==NIL would be interpreted as a bug...
729  // If we dereference a nowhere/undefined, we should end up
730  // anywhere to please gcc and Fabien Coelho
731  // type vt = ultimate_type(entity_type(v));
732  bool to_be_freed;
733  type ct = points_to_cell_to_type(source, &to_be_freed);
735  if(type_variable_p(vt)) {
736  if(pointer_type_p(vt)) {
737  // FI: should nt be freed?
738  type nt = type_to_pointed_type(vt);
740  sinks = CONS(CELL, c, NIL);
741  points_to pt = make_points_to(copy_cell(source), c,
744  pts = add_arc_to_pt_map_(pt, pts);
745  }
746  else if(struct_type_p(vt)) {
747  variable vrt = type_variable(vt);
748  basic b = variable_basic(vrt);
749  entity se = basic_derived(b);
750  type st = entity_type(se);
751  pips_assert("se is an internal struct", type_struct_p(st));
752  list fl = type_struct(st);
753  FOREACH(ENTITY, f, fl) {
754  type ft = entity_type(f);
755  type uft = compute_basic_concrete_type(ft); // FI: to be freed...
756  if(pointer_type_p(uft)) {
757  cell nsource = copy_cell(source); // FI: memory leak?
758  nsource = points_to_cell_add_field_dimension(nsource, f);
759  type nt = type_to_pointed_type(uft);
761  points_to pt = make_points_to(nsource, nsink,
764  pts = add_arc_to_pt_map_(pt, pts);
765  //sinks = source_to_sinks(source, pts, false);
766  sinks = CONS(CELL, nsink, NIL);
767  }
768  else if(struct_type_p(uft)) {
769  cell nsource = copy_cell(source); // FI: memory leak?
770  nsource = points_to_cell_add_field_dimension(nsource, f);
771  sinks = anywhere_source_to_sinks(nsource, pts);
772  //pips_internal_error("Not implemented yet.\n");
773  }
774  else if(array_type_p(uft)) {
775  variable uftv = type_variable(uft);
776  basic uftb = variable_basic(uftv);
777  if(basic_pointer_p(uftb)) {
778  cell nsource = copy_cell(source); // FI: memory leak?
779  reference r = cell_any_reference(nsource);
781  type nt = ultimate_type(uft); // FI: get rid of the dimensions
783  points_to pt = make_points_to(nsource, nsink,
786  pts = add_arc_to_pt_map_(pt, pts);
787  sinks = CONS(CELL, nsink, NIL);
788  }
789  }
790  }
791  }
792  else if(array_type_p(vt)) {
793  variable uftv = type_variable(vt);
794  basic uftb = variable_basic(uftv);
795  if(basic_pointer_p(uftb)) {
796  cell nsource = copy_cell(source); // FI: memory leak?
797  reference r = cell_any_reference(nsource);
799  }
800  }
801  else if(overloaded_type_p(vt)) {
803  sinks = CONS(CELL, c, NIL);
804  points_to pt = make_points_to(copy_cell(source), c,
807  pts = add_arc_to_pt_map_(pt, pts);
808  }
809  else
810  // FI: struct might be dereferenced?
811  // FI: should this be tested when entering this function rather
812  // than expecting that the caller is safe
813  pips_internal_error("Unexpected dereferenced type.\n");
814  }
815  else if(type_area_p(vt)) {
816  // FI: this should be removed using type_overloaded for the
817  // "untyped" anywhere
819  reference r = make_reference(e, NIL);
820  cell c = make_cell_reference(r);
821  sinks = CONS(CELL, c, NIL);
822  points_to pt = make_points_to(copy_cell(source), c,
825  pts = add_arc_to_pt_map_(pt, pts);
826  }
827  else {
828  pips_internal_error("Unexpected dereferenced type.\n");
829  }
830 
831  if(to_be_freed) free_type(ct);
832 
833  return sinks;
834 }
cell make_cell_reference(reference _field_)
Definition: effects.c:293
approximation make_approximation_may(void)
Definition: effects.c:179
descriptor make_descriptor_none(void)
Definition: effects.c:442
points_to make_points_to(cell a1, cell a2, approximation a3, descriptor a4)
type copy_type(type p)
TYPE.
Definition: ri.c:2655
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
void free_type(type p)
Definition: ri.c:2658
entity entity_anywhere_locations()
cell make_anywhere_points_to_cell(type)
Function storing points to information attached to a statement.
Definition: points_to.c:87
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
pt_map add_arc_to_pt_map_(points_to a, pt_map s)
list anywhere_source_to_sinks(cell source, pt_map pts)
source is assumed to be either nowhere/undefined or anywhere, it may be typed or not.
void reference_add_zero_subscripts(reference r, type t)
Definition: expression.c:261
type ultimate_type(type)
Definition: type.c:3466
bool array_type_p(type)
Definition: type.c:2942
type type_to_pointed_type(type)
returns t if t is not a pointer type, and the pointed type if t is a pointer type.
Definition: type.c:5265
bool overloaded_type_p(type)
Returns true if t is a variable type with a basic overloaded.
Definition: type.c:2666
#define type_struct(x)
Definition: ri.h:2964
#define type_struct_p(x)
Definition: ri.h:2962
#define basic_derived(x)
Definition: ri.h:640
#define type_variable(x)
Definition: ri.h:2949
#define basic_pointer_p(x)
Definition: ri.h:635
#define type_area_p(x)
Definition: ri.h:2944
#define entity_type(x)
Definition: ri.h:2792
#define type_variable_p(x)
Definition: ri.h:2947
#define variable_basic(x)
Definition: ri.h:3120

References add_arc_to_pt_map_(), anywhere_source_to_sinks(), array_type_p(), basic_derived, basic_pointer_p, CELL, cell_any_reference(), compute_basic_concrete_type(), CONS, copy_cell(), copy_type(), ENTITY, entity_anywhere_locations(), entity_type, f(), FOREACH, free_type(), make_anywhere_points_to_cell(), make_approximation_may(), make_cell_reference(), make_descriptor_none(), make_points_to(), make_reference(), NIL, overloaded_type_p(), pips_assert, pips_internal_error, pointer_type_p(), points_to_cell_add_field_dimension(), points_to_cell_to_type(), reference_add_zero_subscripts(), struct_type_p(), type_area_p, type_struct, type_struct_p, type_to_pointed_type(), type_variable, type_variable_p, ultimate_type(), and variable_basic.

Referenced by anywhere_source_to_sinks(), nowhere_source_to_sinks(), null_source_to_sinks(), and source_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ application_to_points_to()

pt_map application_to_points_to ( application  a,
pt_map  pt_in,
bool  side_effect_p 
)

FI: We should also identify the possibly called functions and update the points-to according to the possible call sites.

Parameters
pt_int_in
side_effect_pide_effect_p

Definition at line 2490 of file expression.c.

2491 {
2493  list al = application_arguments(a);
2494  pt_map pt_out = expression_to_points_to(f, pt_in, side_effect_p);
2495 
2496  pt_out = expressions_to_points_to(al, pt_out, side_effect_p);
2497  /* FI: We should also identify the possibly called functions and
2498  update the points-to according to the possible call sites. */
2499  pips_internal_error("Not implemented yet for application\n");
2500 
2501  return pt_out;
2502 }
pt_map expressions_to_points_to(list el, pt_map pt_in, bool side_effect_p)
Compute the points-to information pt_out that results from the evaluation of a possibly empty list of...
Definition: expression.c:243
#define application_arguments(x)
Definition: ri.h:510
#define application_function(x)
Definition: ri.h:508

References application_arguments, application_function, expression_to_points_to(), expressions_to_points_to(), f(), and pips_internal_error.

Referenced by expression_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ application_to_points_to_sinks()

list application_to_points_to_sinks ( application  ,
type  ,
pt_map   
)

◆ arc_in_points_to_set_p()

bool arc_in_points_to_set_p ( points_to  spt,
set  pts 
)

Check if points-to arc "spt" belongs to points-to set "pts".

Parameters
sptpt
ptsts

Definition at line 3518 of file points_to_set.c.

3519 {
3520  bool in_p = false;
3521  SET_FOREACH(points_to, pt, pts) {
3522  if(points_to_equal_p(spt, pt)) {
3523  in_p = true;
3524  break;
3525  }
3526  }
3527  return in_p;
3528 }
int points_to_equal_p(const void *vpt1, const void *vpt2)
returns true if two points-to arcs "vpt1" and "vpt2" are equal.
Definition: points_to_set.c:98

References points_to_equal_p(), and SET_FOREACH.

Referenced by filter_formal_context_according_to_actual_context(), and new_filter_formal_context_according_to_actual_context().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ array_formal_parameter_to_stub_points_to()

set array_formal_parameter_to_stub_points_to ( type  t,
cell  c 
)

Type "t" is supposed to be a concrete type.

Type "t" may be modified: no.

Cell "c" is copied.

The dimensions of type "t" are forgotten. They are retrieved later from the type of the entity references in cell "c".

Add an artificial dimension for pointer arithmetic

Definition at line 1116 of file points_to_init_analysis.c.

1117 {
1120  points_to_rank);
1122 
1123  if(basic_pointer_p(fpb)) {
1125  entity e = reference_variable(r);
1126  reference ref = make_reference(e, NULL);
1128  cell cel = make_cell_reference(ref);
1129  type pt = copy_type(basic_pointer(fpb));
1130 
1131  bool strict_p = get_bool_property("POINTS_TO_STRICT_POINTER_TYPES");
1132  if(scalar_type_p(pt) && !strict_p) {
1133  /* Add an artificial dimension for pointer arithmetic */
1136  dimension d = make_dimension(l, u, NIL);
1137  variable ptv = type_variable(pt);
1138  variable_dimensions(ptv) = CONS(DIMENSION, d, NIL);
1139  }
1140 
1141  bool exact_p = !get_bool_property("POINTS_TO_NULL_POINTER_INITIALIZATION");
1142  points_to pt_to = create_stub_points_to(cel, pt, exact_p);
1143  //cell source = points_to_source(pt_to);
1144  pt_in = set_add_element(pt_in, pt_in,
1145  (void*) pt_to );
1146  }
1147 
1148  return pt_in;
1149 
1150 }
bool reference_consistent_p(reference p)
Definition: ri.c:2056
dimension make_dimension(expression a1, expression a2, list a3)
Definition: ri.c:565
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
set set_generic_make(set_type, hash_equals_t, hash_rank_t)
what about this replacement? #define SET_MAP(the_item, the_code, the_set) \ { SET_FOREACH(void *,...
Definition: set.c:83
@ set_private
Definition: newgen_set.h:45
_uint points_to_rank(const void *, size_t)
create a key which is a concatenation of the source's name, the sink's name and the approximation of ...
int points_to_equal_p(const void *, const void *)
returns true if two points-to arcs "vpt1" and "vpt2" are equal.
Definition: points_to_set.c:98
points_to create_stub_points_to(cell c, type unused_st __attribute__((__unused__)), bool exact_p)
points_to create_stub_points_to(cell c, bool exact_p)
expression make_unbounded_expression()
Definition: expression.c:4339
expression make_zero_expression(void)
Make a zero expression.
Definition: expression.c:1212
bool scalar_type_p(type)
Definition: type.c:2955
#define basic_pointer(x)
Definition: ri.h:637
#define variable_dimensions(x)
Definition: ri.h:3122

References basic_pointer, basic_pointer_p, cell_any_reference(), CONS, copy_type(), create_stub_points_to(), DIMENSION, get_bool_property(), make_cell_reference(), make_dimension(), make_reference(), make_unbounded_expression(), make_zero_expression(), NIL, points_to_equal_p(), points_to_rank(), ref, reference_consistent_p(), reference_variable, scalar_type_p(), set_add_element(), set_generic_make(), set_private, type_variable, variable_basic, and variable_dimensions.

Referenced by formal_points_to_parameter().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ array_stub_source_to_sinks()

list array_stub_source_to_sinks ( cell  source,
pt_map  pts,
bool  fresh_p 
)
Parameters
sourceource
ptsts
fresh_presh_p

Definition at line 1171 of file points_to_set.c.

1172 {
1173  list sinks = generic_stub_source_to_sinks(source, pts, true, fresh_p);
1174  return sinks;
1175 }
list generic_stub_source_to_sinks(cell source, pt_map pts, bool array_p, bool fresh_p)

References generic_stub_source_to_sinks().

Referenced by stub_source_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ array_to_constant_paths()

list array_to_constant_paths ( expression  ,
set   
)

◆ assignment_to_points_to()

pt_map assignment_to_points_to ( expression  lhs,
expression  rhs,
pt_map  pt_in 
)

It is not obvious that you are allowed to evaluate this before the sink of lhs, but the standard probably forbid stupid side effects.

Can occur in a declaration

When more precision is needed, the BRACE_INTRINSIC arguments will have to be analyzed...

Parameters
lhshs
rhshs
pt_int_in

Definition at line 1163 of file expression.c.

1164 {
1165  pt_map pt_out = pt_in;
1166  // FI: lhs and rhs have already been used to update pt_in
1167  //pt_map pt_out = expression_to_points_to(lhs, pt_in);
1168  /* It is not obvious that you are allowed to evaluate this before
1169  the sink of lhs, but the standard probably forbid stupid side
1170  effects. */
1171  //pt_out = expression_to_points_to(lhs, pt_out);
1172  bool to_be_freed = false;
1173  type t = points_to_expression_to_type(lhs, &to_be_freed);
1174 
1176  if(pointer_type_p(ut))
1177  pt_out = pointer_assignment_to_points_to(lhs, rhs, pt_out);
1178  else if(struct_type_p(ut))
1179  pt_out = struct_assignment_to_points_to(lhs, rhs, pt_out);
1180  // FI: unions are not dealt with...
1181  else if(array_of_pointers_type_p(ut)) {
1182  /* Can occur in a declaration */
1183  /* When more precision is needed, the BRACE_INTRINSIC arguments
1184  will have to be analyzed... */
1185  pips_assert("lhs is a reference", expression_reference_p(lhs));
1187  list sl = reference_indices(r);
1188  pips_assert("The array reference has no indices", ENDP(sl));
1193  points_to a = make_points_to(source, sink,
1196  pt_out = add_arc_to_pt_map_(a, pt_in);
1197  }
1198  else if(array_of_struct_type_p(ut)) {
1199  pips_internal_error("Initialization of array of structs not implemented yet.\n");
1200  }
1201  else
1202  pt_out = pt_in; // What else?
1203 
1204  if(to_be_freed)
1205  free_type(t);
1206 
1207  return pt_out;
1208 }
reference copy_reference(reference p)
REFERENCE.
Definition: ri.c:2047
type points_to_expression_to_type(expression, bool *)
FI: I need more generality than is offered by expression_to_type() because fields are assimilated to ...
Definition: type.c:592
pt_map struct_assignment_to_points_to(expression lhs, expression rhs, pt_map pt_in)
pt_in is modified by side-effects and returned as pt_out
Definition: expression.c:2319
pt_map pointer_assignment_to_points_to(expression lhs, expression rhs, pt_map pt_in)
Definition: expression.c:1437
pt_map add_arc_to_pt_map_(points_to, pt_map)
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
#define reference_indices(x)
Definition: ri.h:2328

References add_arc_to_pt_map_(), array_of_pointers_type_p(), array_of_struct_type_p(), basic_pointer, compute_basic_concrete_type(), copy_reference(), ENDP, expression_reference(), expression_reference_p(), free_type(), make_anywhere_points_to_cell(), make_approximation_may(), make_cell_reference(), make_descriptor_none(), make_points_to(), pips_assert, pips_internal_error, pointer_assignment_to_points_to(), pointer_type_p(), points_to_cell_add_unbounded_subscripts(), points_to_expression_to_type(), reference_indices, struct_assignment_to_points_to(), struct_type_p(), type_variable, and variable_basic.

Referenced by compute_points_to_binded_set(), declaration_statement_to_points_to(), intrinsic_call_to_points_to(), struct_assignment_to_points_to(), and struct_initialization_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ atomic_constant_path_p()

bool atomic_constant_path_p ( cell  cp)

Could be replaced by abstract_location_p() but this later don't take into account the null location.

Parameters
cpp

Definition at line 1243 of file constant-path-utils.c.

1244 {
1245  bool atomic_cp_p = true;
1247  entity e = reference_variable(r);
1248 
1250  atomic_cp_p = false;
1251  return atomic_cp_p;
1252 }
bool entity_null_locations_p(entity e)
test if an entity is the NULL POINTER
bool entity_abstract_location_p(entity al)
Pvecteur cp
pointeur sur l'egalite ou l'inegalite courante
Definition: sc_read.c:87

References cell_any_reference(), cp, entity_abstract_location_p(), entity_null_locations_p(), and reference_variable.

+ Here is the call graph for this function:

◆ binary_intrinsic_call_to_points_to_sinks()

list binary_intrinsic_call_to_points_to_sinks ( call  c,
pt_map  in,
bool  eval_p 
)

FI: it might be better to integrate this update in points_to_cell_add_field_dimension() in order to exploit available information directly and to return a consistent cell. Anyway, seems useless here

Already performed elsewhere. The value returned by expression

Parameters
inn
eval_pval_p

Definition at line 327 of file sinks.c.

328 {
329  entity f = call_function(c);
330  list al = call_arguments(c);
331  expression a1 = EXPRESSION(CAR(al));
332  expression a2 = EXPRESSION(CAR(CDR(al)));
333  list sinks = NIL;
334 
335  pips_assert("in is consistent on entry or undefined",
338 
339  if(ENTITY_ASSIGN_P(f)) {
340  // FI: you need to dereference this according to in...
341  // See assignment01.c
342  sinks = expression_to_points_to_sinks(a1, in);
343  }
344  else if(ENTITY_POINT_TO_P(f)) { // p->a
345  // FI: allocation of a fully fresh list? Theroretically...
346  if(pt_map_undefined_p(in)) {
348  cell c = make_anywhere_cell(t);
349  sinks = CONS(CELL, c, NIL);
350  }
351  else {
354  pips_assert("in is consistent after computing L",
356  // a2 must be a field entity
358  FOREACH(CELL, pc, L) {
359  if(null_cell_p(pc)) {
360  ; // FI: should be an execution error if gen_length(L)==1
361  }
362  else if(nowhere_cell_p(pc)) {
363  ; // FI: same, and, at least, pc should be removed from L
364  }
365  else if(anywhere_cell_p(pc)) {
367  // FI: we should assert ALIASING_ACROSS_TYPES==false..
371  reference_variable(r) = ne;
372  }
373  else {
374  ; // do nothing
375  }
376  }
377  else {
378  // FI: side effect or allocation of a new cell?
379  cell npc = copy_cell(pc);
380  if(!heap_cell_p(npc))
383  // FI: does this call allocate a full new list?
385  if(eval_p && !array_type_p(ft)) {
386  list dL = source_to_sinks(npc, in, true);
387  pips_assert("in is consistent after computing dL",
389  free_cell(npc);
390  if(ENDP(dL)) {// FI: this might mean dead code...
391  pips_internal_error("Dereferencing error or user error?\n");
392  if(ENDP(sinks)) {
393  pips_user_warning("Some kind of execution error has been encountered at line %d.\n", points_to_context_statement_line_number());
394  clear_pt_map(in);
395  points_to_graph_bottom(in) = true;
396  }
397  }
398  else {
399  FOREACH(CELL, ec, dL) {
400  // (void) cell_add_field_dimension(ec, f);
401  // FI: should we allocate new cells? Done
402  sinks = gen_nconc(sinks, CONS(CELL, ec, NIL));
403  }
404  }
405  }
406  else
407  sinks = gen_nconc(sinks, CONS(CELL, npc, NIL));
408  }
409  }
410  }
411  }
412  else if(ENTITY_FIELD_P(f)) { // p.1
413  // Seems to have no impact whatsoever
416  // FI: memory leak, but you need a copy to add the field
417  list L = gen_full_copy_list(oL);
418  // a2 must be a field entity
421  FOREACH(CELL, pc, L) {
422  // FI: there may cells that should
423  // not be processed, such as an anywhere non type
424  if(null_cell_p(pc)) {
425  // FI: Should we removed the arc generating a NULL as it is
426  // incompatible with the program execution?
427  ;
428  }
429  else if(anywhere_cell_p(pc)) {
430  // Leave it unmodified
431  ;
432  }
433  else if(cell_typed_anywhere_locations_p(pc)) {
434  // The type of the anywhere location must be updated
436  if(cell_reference_p(pc)) {
438  cell_reference(pc) = r;
439  }
440  else if(cell_preference_p(pc))
441  pips_internal_error("prefrence unexpected in cell.\n");
442  else if(cell_gap_p(pc))
443  pips_internal_error("gap unexpected in cell.\n");
444  else
445  pips_internal_error("tag %d unexpected in cell.\n", cell_tag(pc));
446  }
447  else {
448  (void) points_to_cell_add_field_dimension(pc, fe);
449  /* FI: it might be better to integrate this update in
450  * points_to_cell_add_field_dimension() in order to exploit available
451  * information directly and to return a consistent cell.
452  * Anyway, seems useless here
453  */
455  }
456  }
457  if(eval_p && !array_type_p(ft)) {
458  FOREACH(CELL, pc, L) {
459  // No need to check that LL is not empty: NULL might be one of
460  // the cells in L, but there may be other cells
461  list LL = source_to_sinks(pc, in, true);
462  sinks = gen_nconc(sinks, LL);
463  }
465  }
466  else
467  sinks = L;
468  }
469  // The internal conversion from PLUS_C to PLUS pays attention to
470  // pointers but not to arrays
471  else if(ENTITY_PLUS_C_P(f) || ENTITY_PLUS_P(f)) { // p+1, a+1
472  // FI: this should be conditioned by eval_p==true; else, no sink exists...
473  // FI: but we do need something for our lhs expressions, not
474  // matter what eval specifies
475  if(true || eval_p)
476  sinks = expression_to_points_to_sinks_with_offset(a1, a2, in);
477  else {
478  // pips_internal_error("The request cannot be satisfied.\n");
479  if(false && zero_expression_p(a2)) {
480  sinks = expression_to_points_to_sources(a1, in);
481  }
482  else { //FI: an exception or an error code should be raised
483  sinks = NIL;
484  }
485  }
486  }
487  else if(ENTITY_MINUS_C_P(f) || ENTITY_MINUS_P(f)) {
490  sinks = expression_to_points_to_sinks_with_offset(a1, ma2, in);
491  free_expression(ma2);
492  }
493  else if(ENTITY_PLUS_UPDATE_P(f)) {
494  sinks = expression_to_points_to_sinks(a1, in);
495  // offset_cells(sinks, a2);
496  }
497  else if(ENTITY_MINUS_UPDATE_P(f)) {
498  sinks = expression_to_points_to_sinks(a1, in);
499  /// Already performed elsewhere. The value returned by expression
500  // "p -= e" is simply "p", here "a1"
501  //entity um = FindOrCreateTopLevelEntity(UNARY_MINUS_OPERATOR_NAME);
502  //expression ma2 = MakeUnaryCall(um, copy_expression(a2));
503  //offset_cells(sinks, ma2);
504  //free_expression(ma2);
505  }
506  else if (ENTITY_CALLOC_SYSTEM_P(f)) { // CALLOC has two arguments
507  // FI: we need a calloc_to_points_to_sinks() to exploit both arguments...
509  copy_expression(a1),
510  copy_expression(a2));
511  sinks = malloc_to_points_to_sinks(e, in);
512  free_expression(e);
513  }
514  else if (ENTITY_REALLOC_SYSTEM_P(f)) { // REALLOC has two arguments
515  // FI: see man realloc() for its complexity:-(
516  // FI: we need a realloc_to_points_to_sinks() to exploit both arguments...
517  sinks = malloc_to_points_to_sinks(a2, in);
518  }
519  else if(ENTITY_FOPEN_P(f)) {
520  entity io_files = MakeIoFileArray(f);
522  reference r = make_reference(io_files, CONS(EXPRESSION, s, NIL));
523  cell ac = make_cell_reference(r);
524  // Since fopen() may fail, a NULL can also be returned
525  cell nc = make_null_cell();
526  sinks = CONS(CELL, ac, CONS(CELL, nc, NIL));
527  }
528  else {
529  // FI: two options, 1) generate an anywhere as sink to be always safe,
530  // 2) raise an internal error to speed up developement...
531  // But do not let go as the caller will block...
532  pips_internal_error("Unrecognized operator or function.\n");
533  ; // Nothing to do
534  }
535  if(ENDP(sinks)) {
536  pips_user_warning("Some kind of execution error has been encountered.\n");
537  clear_pt_map(in);
538  points_to_graph_bottom(in) = true;
539  }
540  pips_assert("in is consistent or undefined when returning",
543  return sinks;
544 }
void free_reference(reference p)
Definition: ri.c:2050
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
void free_expression(expression p)
Definition: ri.c:853
entity entity_typed_anywhere_locations(type t)
bool cell_typed_anywhere_locations_p(cell c)
test if a cell is the bottom of the lattice
reference make_anywhere_reference(type t)
This function should be located somewhere in effect-util in or near abstract locations.
cell make_anywhere_cell(type t)
entity MakeIoFileArray(entity f)
This array is pointed by FILE * pointers returned or used by fopen, fclose,...
Definition: bootstrap.c:5705
bool anywhere_cell_p(cell)
Is it an anywhere cell?
Definition: effects.c:367
type points_to_expression_to_concrete_type(expression)
The type returned is stored in a hash-table.
Definition: type.c:617
bool nowhere_cell_p(cell)
Target of an undefined pointer.
Definition: effects.c:455
bool null_cell_p(cell)
Definition: effects.c:466
void points_to_cell_add_zero_subscripts(cell)
Definition: effects.c:1615
bool heap_cell_p(cell)
Any heap cell, more or less abstract or typed.
Definition: effects.c:420
#define cell_reference(x)
Definition: effects.h:469
#define cell_reference_p(x)
Definition: effects.h:467
#define cell_gap_p(x)
Definition: effects.h:473
#define cell_tag(x)
Definition: effects.h:466
#define cell_preference_p(x)
Definition: effects.h:470
void gen_full_free_list(list l)
Definition: genClib.c:1023
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
void remove_impossible_arcs_to_null(list *, pt_map)
You know that null and undefined cells in "*pL" are impossible because of the operation that is going...
list source_to_sinks(cell, pt_map, bool)
Return a list of cells, "sinks", that are sink for some arc whose source is "source" or related to "s...
#define points_to_graph_undefined_p(x)
#define ENTITY_PLUS_UPDATE_P(e)
#define ENTITY_CALLOC_SYSTEM_P(e)
#define ENTITY_ASSIGN_P(e)
#define ENTITY_MINUS_P(e)
#define ENTITY_PLUS_P(e)
#define ENTITY_POINT_TO_P(e)
#define ENTITY_FOPEN_P(e)
#define ENTITY_REALLOC_SYSTEM_P(e)
#define binary_intrinsic_expression(name, e1, e2)
#define ENTITY_PLUS_C_P(e)
#define ENTITY_FIELD_P(e)
C data structure and pointer management.
#define ENTITY_MINUS_C_P(e)
#define UNARY_MINUS_OPERATOR_NAME
#define ENTITY_MINUS_UPDATE_P(e)
#define MULTIPLY_OPERATOR_NAME
entity FindOrCreateTopLevelEntity(const char *name)
Return a top-level entity.
Definition: entity.c:1603
bool zero_expression_p(expression e)
Definition: expression.c:1217
expression MakeUnaryCall(entity f, expression a)
Creates a call expression to a function with one argument.
Definition: expression.c:342
#define syntax_reference(x)
Definition: ri.h:2730
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define call_arguments(x)
Definition: ri.h:711
list malloc_to_points_to_sinks(expression e, pt_map in)
Heap modelling.
Definition: sinks.c:1231
cell make_null_cell(void)
Definition: sinks.c:95
list expression_to_points_to_sources(expression e, pt_map in)
expression_to_points_to_sources() does not always work, especially with pointer arithmetic or subscri...
Definition: sinks.c:1805
list expression_to_points_to_sinks_with_offset(expression a1, expression a2, pt_map in)
Definition: sinks.c:546
list expression_to_points_to_sinks(expression e, pt_map in)
The returned list contains cells used in "in".
Definition: sinks.c:1795
Definition: pip__tab.h:30

References anywhere_cell_p(), array_type_p(), binary_intrinsic_expression, call_arguments, call_function, CAR, CDR, CELL, cell_any_reference(), cell_gap_p, cell_preference_p, cell_reference, cell_reference_p, cell_tag, cell_typed_anywhere_locations_p(), clear_pt_map, CONS, consistent_points_to_graph_p(), copy_cell(), copy_expression(), ENDP, ENTITY_ASSIGN_P, entity_basic_concrete_type(), ENTITY_CALLOC_SYSTEM_P, ENTITY_FIELD_P, ENTITY_FOPEN_P, ENTITY_MINUS_C_P, ENTITY_MINUS_P, ENTITY_MINUS_UPDATE_P, ENTITY_PLUS_C_P, ENTITY_PLUS_P, ENTITY_PLUS_UPDATE_P, ENTITY_POINT_TO_P, ENTITY_REALLOC_SYSTEM_P, entity_typed_anywhere_locations(), EXPRESSION, expression_syntax, expression_to_points_to_sinks(), expression_to_points_to_sinks_with_offset(), expression_to_points_to_sources(), f(), FindOrCreateTopLevelEntity(), FOREACH, free_cell(), free_expression(), free_reference(), gen_full_copy_list(), gen_full_free_list(), gen_nconc(), heap_cell_p(), make_anywhere_cell(), make_anywhere_reference(), make_cell_reference(), make_null_cell(), make_reference(), make_unbounded_expression(), MakeIoFileArray(), MakeUnaryCall(), malloc_to_points_to_sinks(), MULTIPLY_OPERATOR_NAME, NIL, nowhere_cell_p(), null_cell_p(), pips_assert, pips_internal_error, pips_user_warning, points_to_cell_add_field_dimension(), points_to_cell_add_zero_subscripts(), points_to_context_statement_line_number(), points_to_expression_to_concrete_type(), points_to_graph_bottom, points_to_graph_undefined_p, pt_map_undefined_p, reference_variable, remove_impossible_arcs_to_null(), source_to_sinks(), syntax_reference, UNARY_MINUS_OPERATOR_NAME, and zero_expression_p().

Referenced by intrinsic_call_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ boolean_intrinsic_call_condition_to_points_to()

pt_map boolean_intrinsic_call_condition_to_points_to ( call  c,
pt_map  in,
bool  true_p 
)

Deal with "!", "&&", "||" etc.

Combine the conditions

Merge the results of the different conditions...

Parameters
inn
true_prue_p

Definition at line 2695 of file expression.c.

2696 {
2697  entity f = call_function(c);
2698  list al = call_arguments(c);
2699  pt_map out = in;
2700  if(ENTITY_NOT_P(f)) {
2701  expression nc = EXPRESSION(CAR(al));
2702  out = condition_to_points_to(nc, in, !true_p);
2703  }
2704  else if((ENTITY_AND_P(f) && true_p) || (ENTITY_OR_P(f) && !true_p)) {
2705  /* Combine the conditions */
2706  expression nc1 = EXPRESSION(CAR(al));
2707  out = condition_to_points_to(nc1, in, true_p);
2708  expression nc2 = EXPRESSION(CAR(CDR(al)));
2709  out = condition_to_points_to(nc2, out, true_p);
2710  }
2711  else if((ENTITY_AND_P(f) && !true_p) || (ENTITY_OR_P(f) && true_p)) {
2712  /* Merge the results of the different conditions... */
2713  pt_map in2 = full_copy_pt_map(in);
2714  expression nc1 = EXPRESSION(CAR(al));
2715  pt_map out1 = condition_to_points_to(nc1, in, true_p);
2716  expression nc2 = EXPRESSION(CAR(CDR(al)));
2717  pt_map out2 = condition_to_points_to(nc2, in2, true_p);
2718  // FI: memory leak? Does merge_points_to_set() allocated a new set?
2719  out = merge_points_to_graphs(out1, out2);
2720  clear_pt_map(out2); // FI: you do no want to free the arcs
2721  free_pt_map(out2);
2722  }
2723  else
2724  pips_internal_error("Not implemented yet for boolean operator \"%s\".\n",
2725  entity_local_name(f));
2726  pips_assert("out is consistent", points_to_graph_consistent_p(out));
2727  return out;
2728 }
bool points_to_graph_consistent_p(points_to_graph p)
#define free_pt_map(pt)
static FILE * out
Definition: alias_check.c:128
pt_map full_copy_pt_map(pt_map)
Definition: statement.c:67
#define ENTITY_OR_P(e)
#define ENTITY_AND_P(e)
#define ENTITY_NOT_P(e)
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
static FILE * out2

References call_arguments, call_function, CAR, CDR, clear_pt_map, condition_to_points_to(), ENTITY_AND_P, entity_local_name(), ENTITY_NOT_P, ENTITY_OR_P, EXPRESSION, f(), free_pt_map, full_copy_pt_map(), merge_points_to_graphs(), out, out2, pips_assert, pips_internal_error, and points_to_graph_consistent_p().

Referenced by intrinsic_call_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ bound_printed_points_to_list_p()

bool bound_printed_points_to_list_p ( statement  )

Referenced by text_points_to().

+ Here is the caller graph for this function:

◆ call_condition_to_points_to()

pt_map call_condition_to_points_to ( call  c,
pt_map  in,
list  el,
bool  true_p 
)

Handle any condition that is a call such as "if(p!=q)", "if(*p)", "if(foo(p=q))"...

Parameters
inn
ell
true_prue_p

Definition at line 2595 of file expression.c.

2596 {
2597  pt_map out = in;
2598  entity f = call_function(c);
2599  value fv = entity_initial(f);
2600  if(value_intrinsic_p(fv))
2601  out = intrinsic_call_condition_to_points_to(c, in, true_p);
2602  else if(value_code_p(fv))
2603  out = user_call_condition_to_points_to(c, in, el, true_p);
2604  else if(value_constant_p(fv)) {
2605  // For instance "if(1)"
2606  ; // do nothing
2607  }
2608  else
2609  // FI: you might have an apply on a functional pointer?
2610  pips_internal_error("Not implemented yet.\n");
2611  pips_assert("out is consistent", points_to_graph_consistent_p(out));
2612  return out;
2613 }
pt_map user_call_condition_to_points_to(call c, pt_map in, list el, bool true_p)
Definition: expression.c:2679
pt_map intrinsic_call_condition_to_points_to(call c, pt_map in, bool true_p)
We can break down the intrinsics according to their arity or according to their kinds....
Definition: expression.c:2618
#define value_code_p(x)
Definition: ri.h:3065
#define value_intrinsic_p(x)
Definition: ri.h:3074
#define value_constant_p(x)
Definition: ri.h:3071
#define entity_initial(x)
Definition: ri.h:2796

References call_function, entity_initial, f(), intrinsic_call_condition_to_points_to(), out, pips_assert, pips_internal_error, points_to_graph_consistent_p(), user_call_condition_to_points_to(), value_code_p, value_constant_p, and value_intrinsic_p.

Referenced by condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ call_to_points_to()

pt_map call_to_points_to ( call  c,
pt_map  pt_in,
list  el,
bool  side_effect_p 
)

Three different kinds of calls are distinguished:

  • calls to constants, e.g. NULL,
  • calls to intrinsics, e.g. ++ or malloc(),
  • and calls to a user function.

"el" is the effect list associated to the call site

points-to updates due to arguments

Must be a pointer to a function

I do not know if nft must be freed later

points-to updates due to arguments

Parameters
pt_int_in
ell
side_effect_pide_effect_p

Definition at line 306 of file expression.c.

307 {
308  pt_map pt_out = pt_in;
309  if(!points_to_graph_bottom(pt_in)) {
310  tag tt;
311  entity f = call_function(c);
312  list al = call_arguments(c);
313  type ft = entity_type(f);
314  type rt = type_undefined;
315  if(type_functional_p(ft)) {
316  functional ff = type_functional(ft);
317  rt = functional_result(ff);
318 
319  // FI: we might have to handle here return?, exit, abort, (stop)
320  // if(ENTITY_STOP_P(e)||ENTITY_ABORT_SYSTEM_P(e)||ENTITY_EXIT_SYSTEM_P(e)
321  // It is done somewhere else
322 
323  /* points-to updates due to arguments */
324  // FI: this cannot be delayed but it is unfortunately applied
325  // again when going down? See arithmetic08 and 09?
326  // This is necessary but cannot be placed here because of the
327  // recursive calls
328  // FI: we are in trouble for post increment and post decrement...
329  // We should update the target a second time in sinks.c!
330  if(!ENTITY_CONDITIONAL_P(f)) {
331  // FI: This is OK only if all subexpressions are always evaluated
332  pt_out = expressions_to_points_to(al, pt_in, side_effect_p);
333  }
334  else
335  pt_out = expression_to_points_to(EXPRESSION(CAR(al)), pt_in, side_effect_p);
336 
337  if(!points_to_graph_bottom(pt_out)) {
338  switch( tt = value_tag(entity_initial(f))) {
339  case is_value_code:{
340  pips_assert("f is a user-defined function", value_code_p(entity_initial(f)));
341  pt_out = user_call_to_points_to(c, pt_out, el);
342  }
343  break;
344  case is_value_unknown:
345  pips_internal_error("function %s has an unknown value\n",
346  entity_name(f));
347  break;
348  case is_value_intrinsic:
349  pt_out = intrinsic_call_to_points_to(c, pt_in, side_effect_p);
350  break;
351  case is_value_constant:
352  pt_out = pt_in; // FI?
353  break;
354  case is_value_symbolic:{
355  value v = entity_initial(f);
356  symbolic s = value_symbolic(v);
358  pt_out = expression_to_points_to(ex, pt_in, side_effect_p);
359  }
360  break;
361  case is_value_expression:{
362  value v = entity_initial(f);
364  pt_out = expression_to_points_to(ex, pt_in, side_effect_p);
365  }
366  break;
367  default:
368  pips_internal_error("unknown tag %d\n", tt);
369  break;
370  }
371  }
372  }
373  else if(type_variable_p(ft)) {
374  /* Must be a pointer to a function */
375  if(pointer_type_p(ft)) {
376  /* I do not know if nft must be freed later */
377  type nft = type_to_pointed_type(ft);
378  pips_assert("Must be a function", type_functional_p(nft));
379  functional nff = type_functional(nft);
380  rt = functional_result(nff);
381  }
382  else
383  pips_internal_error("Unexpected type.\n");
384  }
385  else if(type_void_p(rt))
386  /* points-to updates due to arguments */
387  pt_out = expressions_to_points_to(al, pt_in, side_effect_p);
388  else
389  pips_internal_error("Unexpected type.\n");
390  }
391 
392  pips_assert("pt_out is consistent and defined",
394  && !points_to_graph_undefined_p(pt_out));
395 
396  return pt_out;
397 }
int tag
TAG.
Definition: newgen_types.h:92
pt_map intrinsic_call_to_points_to(call c, pt_map pt_in, bool side_effect_p)
Definition: expression.c:411
points_to_graph user_call_to_points_to(call c, points_to_graph pt_in, list el)
FI: limited to the interprocedural option.
#define ENTITY_CONDITIONAL_P(e)
#define type_functional_p(x)
Definition: ri.h:2950
#define value_tag(x)
Definition: ri.h:3064
#define functional_result(x)
Definition: ri.h:1444
#define type_functional(x)
Definition: ri.h:2952
@ is_value_intrinsic
Definition: ri.h:3034
@ is_value_unknown
Definition: ri.h:3035
@ is_value_expression
Definition: ri.h:3036
@ is_value_constant
Definition: ri.h:3033
@ is_value_code
Definition: ri.h:3031
@ is_value_symbolic
Definition: ri.h:3032
#define value_symbolic(x)
Definition: ri.h:3070
#define type_void_p(x)
Definition: ri.h:2959
#define entity_name(x)
Definition: ri.h:2790
#define type_undefined
Definition: ri.h:2883
#define symbolic_expression(x)
Definition: ri.h:2597
#define value_expression(x)
Definition: ri.h:3082

References call_arguments, call_function, CAR, ENTITY_CONDITIONAL_P, entity_initial, entity_name, entity_type, EXPRESSION, expression_to_points_to(), expressions_to_points_to(), f(), functional_result, intrinsic_call_to_points_to(), is_value_code, is_value_constant, is_value_expression, is_value_intrinsic, is_value_symbolic, is_value_unknown, pips_assert, pips_internal_error, pointer_type_p(), points_to_graph_bottom, points_to_graph_consistent_p(), points_to_graph_undefined_p, symbolic_expression, type_functional, type_functional_p, type_to_pointed_type(), type_undefined, type_variable_p, type_void_p, user_call_to_points_to(), value_code_p, value_expression, value_symbolic, and value_tag.

Referenced by dereferencing_to_points_to(), expression_to_points_to(), and instruction_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ call_to_points_to_sinks()

list call_to_points_to_sinks ( call  c,
type  et,
pt_map  in,
bool  eval_p,
bool  constant_p 
)

No check, but all elements of sinks should be of a type compatible with type "et".

Parameters
ett
inn
eval_pval_p
constant_ponstant_p

Definition at line 112 of file sinks.c.

113 {
114  list sinks = NIL;
115  entity f = call_function(c);
116  //list al = call_arguments(c);
117  value v = entity_initial(f);
118  tag tt = value_tag(v);
119  switch (tt) {
120  case is_value_code:
121  sinks = user_call_to_points_to_sinks(c, et, in, eval_p);
122  break;
123  case is_value_symbolic:
124  break;
125  case is_value_constant: {
126  constant zero = value_constant(v);
127  if(constant_int_p(zero) && constant_int(zero)==0)
128  sinks = points_to_null_sinks(); // et could be used according to PJ
129  else {
131  if(string_type_p(t)) {
132  // FI: we could generate a special location for each string
133  // FI: we could reuse the constant function
134  // FI: we could use the static area of the current module
135  // FI: we can always use anywhere...
136  // FI: does not depend oneval_p... involution...
138  cell c = make_cell_reference(r);
139  sinks = CONS(CELL, c, NIL);
140  }
141  else {
142  sinks = points_to_anywhere_sinks(t);
143  }
144  }
145  }
146  break;
147  case is_value_unknown:
148  pips_internal_error("function %s has an unknown value\n",
149  entity_name(f));
150  break;
151  case is_value_intrinsic:
152  // FI: here is the action, &p, *p, p->q, p.q, etc...
153  sinks = intrinsic_call_to_points_to_sinks(c, in, eval_p, constant_p);
154  break;
155  default:
156  pips_internal_error("unknown value tag %d\n", tt);
157  break;
158  }
159 
160  /* No check, but all elements of sinks should be of a type
161  compatible with type "et". */
162 
163  return sinks;
164 }
list user_call_to_points_to_sinks(call c, type et __attribute__((unused)), pt_map in __attribute__((unused)), bool eval_p)
FI: I assume we do not need the eval_p parameter here.
static bool constant_p(entity e)
This function return a bool indicating if related entity e represents a constant.
bool string_type_p(type)
Definition: type.c:2854
type type_to_returned_type(type)
returns t if t is not a functoional type, and the returned type if t is a functional type.
Definition: type.c:5316
#define value_constant(x)
Definition: ri.h:3073
#define constant_int(x)
Definition: ri.h:850
#define constant_int_p(x)
Definition: ri.h:848
list points_to_null_sinks()
Definition: sinks.c:87
list points_to_anywhere_sinks(type t)
Definition: sinks.c:102
list intrinsic_call_to_points_to_sinks(call c, pt_map in, bool eval_p, bool constant_p)
Definition: sinks.c:172

References call_function, CELL, CONS, constant_int, constant_int_p, constant_p(), entity_initial, entity_name, entity_type, f(), intrinsic_call_to_points_to_sinks(), is_value_code, is_value_constant, is_value_intrinsic, is_value_symbolic, is_value_unknown, make_cell_reference(), make_reference(), NIL, pips_internal_error, points_to_anywhere_sinks(), points_to_null_sinks(), string_type_p(), type_to_returned_type(), user_call_to_points_to_sinks(), value_constant, and value_tag.

Referenced by expression_to_points_to_cells().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cast_to_points_to_sinks()

list cast_to_points_to_sinks ( cast  ,
type  ,
pt_map  ,
bool   
)

◆ cell_in_list_p()

bool cell_in_list_p ( cell  c,
const  list 
)

found!

else no found

Parameters
listx

Definition at line 2613 of file points_to_set.c.

2614 {
2615  list l = (list) lx;
2616  for (; !ENDP(l); POP(l))
2617  if (points_to_compare_cell(CELL(CAR(l)), c)) return true; /* found! */
2618 
2619  return false; /* else no found */
2620 }
bool points_to_compare_cell(cell c1, cell c2)

References CAR, CELL, ENDP, points_to_compare_cell(), and POP.

Referenced by null_equal_condition_to_points_to(), null_non_equal_condition_to_points_to(), and order_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cell_in_points_to_set_p()

bool cell_in_points_to_set_p ( cell  c,
set  pts 
)

Check if a cell c appears as source or sink in points-to set pts.

If set pts is undefined, it is assumed that cell c is in it.

Parameters
ptsts

Definition at line 2626 of file points_to_set.c.

2627 {
2628  bool in_p = false;
2629  if(set_undefined_p(pts)) {
2630  in_p = true;
2631  }
2632  else {
2633  SET_FOREACH(points_to, pt, pts) {
2634  cell s = points_to_source(pt);
2635  in_p = points_to_compare_cell(s,c);
2636  if(!in_p) {
2637  cell d = points_to_sink(pt);
2638  in_p = points_to_compare_cell(d,c);
2639  }
2640  if(in_p)
2641  break;
2642  }
2643  }
2644  return in_p;
2645 }
#define set_undefined_p(s)
Definition: newgen_set.h:49
#define points_to_sink(x)

References points_to_compare_cell(), points_to_sink, points_to_source, SET_FOREACH, and set_undefined_p.

Referenced by generic_points_to_cell_to_useful_pointer_cells().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cell_is_greater_than_or_equal_to_p()

bool cell_is_greater_than_or_equal_to_p ( cell  c1,
cell  c2 
)
Parameters
c11
c22

Definition at line 2830 of file expression.c.

2831 {
2832  return cell_is_xxx_p(c1, c2, GREATER_THAN_OR_EQUAL_TO);
2833 }
static bool cell_is_xxx_p(cell c1, cell c2, int xxx)
Definition: expression.c:2742
#define GREATER_THAN_OR_EQUAL_TO
Definition: expression.c:2740

References cell_is_xxx_p(), and GREATER_THAN_OR_EQUAL_TO.

Referenced by order_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cell_is_greater_than_p()

bool cell_is_greater_than_p ( cell  c1,
cell  c2 
)
Parameters
c11
c22

Definition at line 2835 of file expression.c.

2836 {
2837  return cell_is_xxx_p(c1, c2, GREATER_THAN);
2838 }
#define GREATER_THAN
Definition: expression.c:2739

References cell_is_xxx_p(), and GREATER_THAN.

Referenced by order_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cell_is_less_than_or_equal_to_p()

bool cell_is_less_than_or_equal_to_p ( cell  c1,
cell  c2 
)

See if you can decide that the addresses linked to c1 are smaller than the addresses linked to c2.

True is returned when a decision can be made.

False is returned when no decision can be made.

Parameters
c11
c22

Definition at line 2820 of file expression.c.

2821 {
2822  return cell_is_xxx_p(c1, c2, LESS_THAN_OR_EQUAL_TO);
2823 }
#define LESS_THAN_OR_EQUAL_TO
Definition: expression.c:2738

References cell_is_xxx_p(), and LESS_THAN_OR_EQUAL_TO.

Referenced by order_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cell_is_less_than_p()

bool cell_is_less_than_p ( cell  c1,
cell  c2 
)
Parameters
c11
c22

Definition at line 2825 of file expression.c.

2826 {
2827  return cell_is_xxx_p(c1, c2, LESS_THAN);
2828 }
#define LESS_THAN
See if you can decide that the addresses linked to c1 are xxx than the addresses linked to c2.
Definition: expression.c:2737

References cell_is_xxx_p(), and LESS_THAN.

Referenced by order_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cell_out_of_scope_p()

bool cell_out_of_scope_p ( cell  c)

Return true if a cell is out of scope.

FI: I add formal parameters as in scope variables...

FI: I remove formal parameters because this function is used to compute the OUT set. The modified or not values of formal parameter are not relevant. If they have not been modified, the useful information is already available in the IN set (oops, see next comment below). If they have been modified, they are no longer reachable and must be projected.

FI: Unfortunately, some information gathered about the input parametrs during the function analysis is lost. For instance, a pointer must be different from NULL (e.g. see argv03.c). But if you do not know if the pointer has been written or not, you do not know if the information is usable or not. This is also an issue for interprocedural analysis: can the result always be trusted for any actual input context?

| formal_parameter_p(e)

Definition at line 560 of file points_to_set.c.

561 {
563  entity e = reference_variable(r);
564  return !(variable_static_p(e) || entity_stub_sink_p(e) || top_level_entity_p(e) || entity_heap_location_p(e) /*|| formal_parameter_p(e)*/ );
565 }
bool entity_heap_location_p(entity b)
package abstract location.
bool entity_stub_sink_p(entity e)
test if an entity is a stub sink for a formal parameter e.g.
reference cell_to_reference(cell)
FI: probably to be moved elsewhere in ri-util.
Definition: effects.c:1326
bool top_level_entity_p(entity e)
Check if the scope of entity e is global.
Definition: entity.c:1130
bool variable_static_p(entity)
true if v appears in a SAVE statement, or in a DATA statement, or is declared static i C.
Definition: variable.c:1579

References cell_to_reference(), entity_heap_location_p(), entity_stub_sink_p(), reference_variable, top_level_entity_p(), and variable_static_p().

Referenced by points_to_function_projection().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cell_to_nowhere_sink()

cell cell_to_nowhere_sink ( cell  source)

assuming source is a reference to a pointer, build the corresponding sink when the pointer is not initialized, i.e.

is undefined.

Parameters
sourceource

Definition at line 55 of file constant-path-utils.c.

56 {
57  bool type_sensitive_p = !get_bool_property("ALIASING_ACROSS_TYPES");
58  cell sink = cell_undefined;
59  if(type_sensitive_p) {
60  // FI: let's hope we create neither sharing nor memory leak
61  bool to_be_freed_p = true;
62  type t = type_to_pointed_type(cell_to_type(source, &to_be_freed_p));
64  if(to_be_freed_p) free_type(t);
65  }
66  else
67  sink = make_nowhere_cell();
68  return sink;
69 }
cell make_nowhere_cell()
This file contains all the operators defining constant paths :
cell make_typed_nowhere_cell(type t)
type cell_to_type(cell, bool *)
Definition: type.c:513

References cell_to_type(), cell_undefined, copy_type(), free_type(), get_bool_property(), make_nowhere_cell(), make_typed_nowhere_cell(), and type_to_pointed_type().

Referenced by declaration_statement_to_points_to(), malloc_to_points_to_sinks(), and user_call_to_points_to_fast_interprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ certainly_written_pointers_set()

list certainly_written_pointers_set ( list  eff)

Filter out certainly written effects on pointers.

Parameters
effff

Definition at line 2614 of file interprocedural.c.

2614  {
2615  return generic_written_pointers_set(eff, true);
2616 }
static list generic_written_pointers_set(list eff, bool exact_p)
Filter out written effects on pointers.

References generic_written_pointers_set().

Referenced by user_call_to_points_to_interprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ check_rhs_value_types()

void check_rhs_value_types ( expression  ,
expression  ,
list   
)

◆ check_type_of_points_to_cells()

void check_type_of_points_to_cells ( list  sinks,
type  ct,
bool  eval_p 
)

Check that all cells in list "sinks" are compatible with type "ct" if "eval_p" is false, and with the type pointed by "st" if eval_p is true.

Adding the zero subscripts may muddle the type issue because "&a[0]" has not the same type as "a" although we normalize every cell into "a[0]".

Take care of the constant strings like "hello"

Take care of void

Parameters
sinksinks
ctt
eval_pval_p

Definition at line 1214 of file expression.c.

1215 {
1216  type st = type_undefined;
1217 
1218  if(!ENDP(sinks)) {
1219  if(eval_p) {
1220  if(pointer_type_p(ct))
1221  st = copy_type(type_to_pointed_type(ct));
1222  else if(array_type_p(ct)) {
1224  }
1225  else
1226  pips_internal_error("Unexpected \"ct\" argument.\n");
1227  }
1228  else
1229  st = copy_type(ct);
1230  }
1231 
1232  FOREACH(CELL, c, sinks) {
1233  if(!null_cell_p(c)
1234  && !anywhere_cell_p(c)
1236  && !nowhere_cell_p(c)) {
1237  bool to_be_freed;
1238  type est = points_to_cell_to_type(c, &to_be_freed);
1239  type cest = compute_basic_concrete_type(est);
1240  //if(!array_pointer_type_equal_p(cest, st)
1241  //if(!concrete_type_equal_p(cest, st)
1242  if(!type_structurally_equal_p(cest, st)
1243  /* Adding the zero subscripts may muddle the type issue
1244  because "&a[0]" has not the same type as "a" although we
1245  normalize every cell into "a[0]". */
1246  && !(array_type_p(st)
1247  && array_pointer_type_equal_p(cest, st))
1248  //array_type_to_element_type(st)))
1249  /* Take care of the constant strings like "hello" */
1251  /* Take care of void */
1252  && !type_void_p(st) // cest could be checked as overloaded
1253  && !overloaded_type_p(cest)
1254  ) {
1255  pips_user_warning("Maybe an issue with a dynamic memory allocation.\n");
1256  pips_user_error("At line %d, "
1257  // "the type returned for the value of expression \"%s\"="
1258  "the type returned for the cell"
1259  "\"%s\", "
1260  "\"%s\", is not the expected type, \"%s\".\n",
1262  // expression_to_string(rhs),
1264  // copied from ri-util/type.c, print_type()
1265  string_of_type(cest),
1266  string_of_type(st));
1267  }
1268  }
1269  }
1270 }
string effect_reference_to_string(reference)
Definition: prettyprint.c:155
#define pips_user_error
Definition: misc-local.h:147
string string_of_type(const type)
Definition: type.c:56
bool char_star_constant_function_type_p(type)
Beware of typedefs.
Definition: type.c:5787
type array_type_to_sub_array_type(type)
Allocate a new type, the sub-array type of "t".
Definition: type.c:5718
bool type_structurally_equal_p(type, type)
Type t1 and t2 are equal if their basic concrete components are equal.
Definition: type.c:586
bool array_pointer_type_equal_p(type, type)
assume that a pointer to type x is equal to a 1-D array of x
Definition: type.c:609
bool char_type_p(type)
return true whether ‘t’ is a char or an unsigned char
Definition: type.c:2877

References anywhere_cell_p(), array_pointer_type_equal_p(), array_type_p(), array_type_to_sub_array_type(), CELL, cell_any_reference(), cell_typed_anywhere_locations_p(), char_star_constant_function_type_p(), char_type_p(), compute_basic_concrete_type(), copy_type(), effect_reference_to_string(), ENDP, FOREACH, nowhere_cell_p(), null_cell_p(), overloaded_type_p(), pips_internal_error, pips_user_error, pips_user_warning, pointer_type_p(), points_to_cell_to_type(), points_to_context_statement_line_number(), string_of_type(), type_structurally_equal_p(), type_to_pointed_type(), type_undefined, and type_void_p.

Referenced by check_rhs_value_types(), reference_to_points_to_sinks(), and subscript_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ clean_up_points_to_stubs()

void clean_up_points_to_stubs ( entity  module)

Beware of location entities that might depend on the soon to be deleted stub entities.

Parameters
moduleodule

Definition at line 303 of file passes.c.

304 {
306  list dl = code_declarations(c);
307  list sl = NIL;
308 
309  FOREACH(ENTITY, v, dl) {
311  sl = CONS(ENTITY, v, sl);
312  fprintf(stderr, "Removed stub: \"%s\"\n", entity_name(v));
313  }
314  }
315 
316  /* Beware of location entities that might depend on the soon to be
317  * deleted stub entities.
318  */
319  if(!ENDP(dl) && get_bool_property("SEMANTICS_ANALYZE_CONSTANT_PATH")) {
320  FOREACH(ENTITY, v, dl) {
322  value val = entity_initial(v);
323  reference r = value_reference(val); // guarded by location_entity_p()
324  entity rv = reference_variable(r);
325  if(gen_in_list_p(rv, dl)) {
326  sl = CONS(ENTITY, v, sl);
327  fprintf(stderr, "Removed location: \"%s\"\n", entity_name(v));
328  }
329  }
330  }
331  }
332 
334 
335  GenericCleanEntities(sl, module, false);
336 
337  gen_free_list(sl);
338 }
bool stub_entity_of_module_p(entity s, entity m)
void GenericCleanEntities(list el, entity function, bool fortran_p)
Useful when the user edit a source file and parse it again or when a program transformation is perfor...
Definition: clean.c:63
bool location_entity_of_module_p(entity, entity)
Definition: locations.c:360
void gen_list_and_not(list *a, const list b)
Compute A = A inter non B:
Definition: list.c:963
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734
static char * module
Definition: pips.c:74
#define value_reference(x)
Definition: ri.h:3085
#define code_declarations(x)
Definition: ri.h:784
#define value_code(x)
Definition: ri.h:3067

References code_declarations, CONS, ENDP, ENTITY, entity_heap_location_p(), entity_initial, entity_name, FOREACH, fprintf(), gen_free_list(), gen_in_list_p(), gen_list_and_not(), GenericCleanEntities(), get_bool_property(), location_entity_of_module_p(), module, NIL, reference_variable, stub_entity_of_module_p(), value_code, and value_reference.

Referenced by generic_points_to_analysis().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ close_printed_points_to_list()

void close_printed_points_to_list ( void  )

◆ compare_entities_without_scope()

int compare_entities_without_scope ( const entity pe1,
const entity pe2 
)

cproto-generated files

points_to_set.c

FI: Which sorting do you want?

Parameters
pe1e1
pe2e2

Definition at line 60 of file points_to_set.c.

61 {
62  int
63  null_1 = (*pe1==(entity)NULL),
64  null_2 = (*pe2==(entity)NULL);
65 
66  if (null_1 || null_2)
67  return(null_2-null_1);
68  else {
69  /* FI: Which sorting do you want? */
70 
71  string s1 = entity_name(*pe1);
72  string s2 = entity_name(*pe2);
73 
74  return strcmp(s1,s2);
75  }
76 }
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
s1
Definition: set.c:247

References entity_name, and s1.

◆ compute_points_to_binded_set()

set compute_points_to_binded_set ( entity  called_func,
list  real_args,
set  pt_caller,
bool success_p 
)

For each actual argument "r" and its corresponding formal one "f", create the assignment "f = r;" and then compute the points-to set "s" generated by the assignment.

The result is the union of "pt_caller" and "s".

Be careful with vararags

This is not sufficient to handle varargs. Much more thinking needed. And corect examples.

C does not support array assignments...

This may happen with a constant string as actual parameter and an array, bounded or not, as formal parameter.

A formal array can be called with a dereferencing expression

See Pointers/Mensi.sub/array_pointer_free01: array fp is associated to &p[0] or to p->q or to c.a ...

It would be nice to build an assignment of rhs to fp and to let it deal with the many possible kinds of assignments. But if it is a pure points-to function, the symbolic subscripts are going to be lost. This is fine for points-to translation, but not OK for effects translation.

In the short term, build the assignment...

The assignment failed because the call site is not compatible with the caller.

Parameters
called_funcalled_func
real_argseal_args
pt_callert_caller
success_puccess_p

Definition at line 2623 of file interprocedural.c.

2627 {
2629  points_to_rank);
2631  points_to_rank);
2632 
2633  *success_p = true; // default value
2634 
2635  /* Be careful with vararags
2636  *
2637  * This is not sufficient to handle varargs. Much more thinking
2638  * needed. And corect examples.
2639  */
2640  type ft = entity_basic_concrete_type(called_func); // function type
2641  functional fft = type_functional(ft);
2642  list ptl = functional_parameters(fft); // parameter type list
2643  int mnp = (int) gen_length(ptl); // maximum number of formal parameters
2644  if(!ENDP(ptl)) {
2645  // last parameter type
2646  type lpt = parameter_type(PARAMETER(CAR(gen_last(ptl))));
2647  if(type_varargs_p(lpt))
2648  mnp--;
2649  }
2650 
2651  cons *pc;
2652  int ipc;
2653  s = set_assign(s, pt_caller);
2654  for (ipc = 1, pc = real_args; pc != NIL; pc = CDR(pc), ipc++) {
2655  expression rhs = EXPRESSION(CAR(pc));
2656  int tr = ipc>mnp? mnp : ipc;
2657  entity fp = find_ith_parameter(called_func, tr);
2658  type fpt = entity_basic_concrete_type(fp);
2659  if(array_type_p(fpt)) {
2660  /* C does not support array assignments... */
2661  if(expression_reference_p(rhs)) {
2663  entity v = reference_variable(r);
2664  list nptl = NIL; // New points-to list
2665  SET_FOREACH(points_to, pt, pt_caller) {
2666  cell c = points_to_source(pt);
2667  reference cr = cell_any_reference(c);
2668  entity cv = reference_variable(cr);
2669  if(cv==v) {
2670  points_to npt = copy_points_to(pt);
2671  cell nc = points_to_source(npt);
2672  reference ncr = cell_any_reference(nc);
2673  reference_variable(ncr) = fp;
2674  nptl = CONS(POINTS_TO, npt, nptl);
2675  }
2676  }
2677  FOREACH(POINTS_TO, npt, nptl)
2678  add_arc_to_simple_pt_map(npt, s);
2679  gen_free_list(nptl);
2680  }
2681  else if(expression_call_p(rhs) && expression_string_constant_p(rhs)) {
2682  /* This may happen with a constant string as actual parameter
2683  and an array, bounded or not, as formal parameter. */
2684  ; // Nothing to do: the constant string does not point to anything
2685  }
2686  else if(expression_call_p(rhs)) {
2687  type et = array_type_to_element_type(fpt);
2688  if(struct_type_p(et)) {
2689  /* A formal array can be called with a dereferencing expression
2690  *
2691  * See Pointers/Mensi.sub/array_pointer_free01: array fp is
2692  * associated to &p[0] or to p->q or to c.a ...
2693  */
2694  call c = expression_call(rhs);
2695  entity f = call_function(c);
2696  pips_internal_error("Not implemented yet. Function \"%s\".\n",
2697  entity_user_name(f));
2698  }
2699  else if(pointer_type_p(et)) {
2700  call c = expression_call(rhs);
2701  entity f = call_function(c);
2702  pips_internal_error("Not implemented yet. Function \"%s\".\n",
2703  entity_user_name(f));
2704  }
2705  else {
2706  // No pointer related information
2707  ;
2708  }
2709  }
2710  else
2711  pips_internal_error("Not implemented yet.\n");
2712  }
2713  else {
2714  /* It would be nice to build an assignment of rhs to fp and to
2715  let it deal with the many possible kinds of assignments. But
2716  if it is a pure points-to function, the symbolic subscripts
2717  are going to be lost. This is fine for points-to translation,
2718  but not OK for effects translation. */
2719 
2720  if(pointer_type_p(fpt)) {
2721  points_to_graph s_g = make_points_to_graph(false, s);
2722  list sinks = expression_to_points_to_cells(rhs, s_g, true, false);
2723  int nsinks = (int) gen_length(sinks);
2724  FOREACH(CELL, sink, sinks) {
2726  cell d = copy_cell(sink);
2727  bool anywhere_p = anywhere_cell_p(d)
2729  bool heap_p = heap_cell_p(d);
2730  approximation a = (nsinks==1 && !anywhere_p && !heap_p) ? make_approximation_exact() :
2733  points_to pt = make_points_to(o, d, a, desc);
2735  }
2736  }
2737  else if(struct_type_p(fpt)) {
2738  /* In the short term, build the assignment... */
2739  expression lhs = entity_to_expression(fp);
2740  points_to_graph s_g = make_points_to_graph(false, s);
2741  points_to_graph a_g = assignment_to_points_to(lhs, rhs, s_g);
2742  if(points_to_graph_bottom(a_g)) {
2743  /* The assignment failed because the call site is not
2744  compatible with the caller. */
2745  *success_p = false;
2746  }
2747  else {
2748  s = set_assign(s, points_to_graph_set(a_g));
2749  }
2750  }
2751  else {
2752  ; // do nothing for other types
2753  }
2754  }
2755  }
2756 
2757  SET_FOREACH(points_to, pt, s) {
2759  entity e = reference_variable(r);
2760  if(stub_entity_of_module_p(e, called_func))
2761  s = set_del_element(s,s,(void*)pt);
2762  }
2763  pt_binded = set_union(pt_binded, s, pt_caller);
2764  return pt_binded;
2765 }
approximation make_approximation_exact(void)
Definition: effects.c:185
points_to_graph make_points_to_graph(bool a1, set a2)
list gen_last(list l)
Return the last element of a list.
Definition: list.c:578
set set_del_element(set, const set, const void *)
Definition: set.c:265
set set_assign(set, const set)
Assign a set with the content of another set.
Definition: set.c:129
pt_map assignment_to_points_to(expression lhs, expression rhs, pt_map pt_in)
Definition: expression.c:1163
set add_subscript_dependent_arc_to_simple_pt_map(points_to, set)
The source and destination references imply no dereferencing but the subscripts may be any kind of ex...
list expression_to_points_to_cells(expression, pt_map, bool, bool)
Return a possibly empty list of abstract locations whose addresses are possible value of expression "...
Definition: sinks.c:1650
#define POINTS_TO(x)
POINTS_TO.
bool expression_call_p(expression e)
Definition: expression.c:415
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
bool expression_string_constant_p(expression exp)
Definition: expression.c:2398
call expression_call(expression e)
Definition: expression.c:445
type array_type_to_element_type(type)
returns the type of the elements of an array type, as a newly allocated type.
Definition: type.c:5700
entity find_ith_parameter(entity, int)
Definition: util.c:93
#define parameter_type(x)
Definition: ri.h:1819
#define functional_parameters(x)
Definition: ri.h:1442
#define PARAMETER(x)
PARAMETER.
Definition: ri.h:1788
#define type_varargs_p(x)
Definition: ri.h:2953

References add_arc_to_simple_pt_map, add_subscript_dependent_arc_to_simple_pt_map(), anywhere_cell_p(), array_type_p(), array_type_to_element_type(), assignment_to_points_to(), call_function, CAR, CDR, CELL, cell_any_reference(), cell_typed_anywhere_locations_p(), CONS, copy_cell(), copy_points_to(), ENDP, entity_basic_concrete_type(), entity_to_expression(), entity_user_name(), EXPRESSION, expression_call(), expression_call_p(), expression_reference(), expression_reference_p(), expression_string_constant_p(), expression_to_points_to_cells(), f(), find_ith_parameter(), FOREACH, functional_parameters, gen_free_list(), gen_last(), gen_length(), heap_cell_p(), int, make_approximation_exact(), make_approximation_may(), make_cell_reference(), make_descriptor_none(), make_points_to(), make_points_to_graph(), make_reference(), NIL, PARAMETER, parameter_type, pips_internal_error, pointer_type_p(), POINTS_TO, points_to_equal_p(), points_to_graph_bottom, points_to_graph_set, points_to_rank(), points_to_sink, points_to_source, reference_variable, set_assign(), set_del_element(), SET_FOREACH, set_generic_make(), set_private, set_union(), struct_type_p(), stub_entity_of_module_p(), type_functional, and type_varargs_p.

Referenced by user_call_to_points_to_fast_interprocedural(), user_call_to_points_to_interprocedural(), and user_call_to_points_to_interprocedural_binding_set().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compute_points_to_gen_set()

set compute_points_to_gen_set ( set  pt_out,
list  Written,
set  binding,
entity  f 
)

Translate the out set in the scope of the caller using the binding information, but eliminate irrelevant arcs using Written and the type of the source.

This is pt_gen_1 in Amira Mensi's dissertation.

Also, pay attention to translation errors because they are related to programming bugs, such as pointer arithmetic applied to pointers to scalar.

Consider all points-to arcs "(sr1, sk1)" in "pt_out"

Keep arcs whose source is:

  • an array, because it has certainly not been passed by copy;
  • not a scalar formal parameter: again, no copy passing;
  • not written by the procedure, because, even if it passed by copy, the actual parameter is aliased.

In other word, get rid of scalar formal parameter that are written.

Translate sr1

Translate sk1 if needed

The translation of pt's sink failed.

Note: the piece of code below is replicated

The caller does not have to have counterparts for all hypothetical stubs that may be developped in callee.

The translation of pt's source failed. This may occur because the callee had to assume a pointer points to an array, whereas the call site associates it to a scalar.

See for instance Pointers/formal_parameter01.c

But this may also occur because the formal parameter cannot be translated because the effective argument is an address_of expression. See for instance EffectsWithPointsTO/call01.c.

We have no way to guess here the reason for the translation failure...

Could be a user error, but you may prefer to go on with the points-to analysis to perform some dead code elimination later...

Parameters
pt_outt_out
Writtenritten
bindinginding

Definition at line 2342 of file interprocedural.c.

2346 {
2347  set gen = new_simple_pt_map();
2348  // To avoid redundant error messages
2349  list translation_failures = NIL;
2350 
2351  /* Consider all points-to arcs "(sr1, sk1)" in "pt_out" */
2352  SET_FOREACH(points_to, p, pt_out) {
2353  cell sr1 = points_to_source(p);
2354  reference r_1 = cell_any_reference(sr1);
2355  entity v_1 = reference_variable(r_1);
2356  type t_1 = entity_basic_concrete_type(v_1);
2357  /* Keep arcs whose source is:
2358  *
2359  * - an array, because it has certainly not been passed by copy;
2360  *
2361  * - not a scalar formal parameter: again, no copy passing;
2362  *
2363  * - not written by the procedure, because, even if it passed by
2364  * copy, the actual parameter is aliased.
2365  *
2366  * In other word, get rid of scalar formal parameter that are written.
2367  */
2368  if(array_type_p(t_1)
2369  || !formal_parameter_p(v_1)
2370  || !points_to_cell_in_list_p(sr1, Written)) {
2371  list new_sk_l = NIL;
2373  cell sk1 = points_to_sink(p);
2374 
2375  /* Translate sr1 */
2376  list new_sr_l = points_to_cell_translation(sr1, binding, f);
2377 
2378  if(!ENDP(new_sr_l)) {
2379  /* Translate sk1 if needed */
2380  reference r_2 = cell_any_reference(sk1);
2381  entity v_2 = reference_variable(r_2);
2382  if (null_cell_p(sk1) || nowhere_cell_p(sk1) || heap_cell_p(sk1)
2384  || entity_to_module_entity(v_2)!=f) {
2385  cell new_sk = copy_cell(sk1);
2386  new_sk_l = CONS(CELL, new_sk, new_sk_l);
2387  }
2388  else
2389  new_sk_l = points_to_cell_translation(sk1, binding, f);
2390 
2391  if(!ENDP(new_sk_l)) {
2392  int new_sk_n = (int) gen_length(new_sk_l);
2393  FOREACH(CELL, new_sr, new_sr_l) {
2395  if(!atomic_points_to_cell_p(new_sr)
2396  || new_sk_n>1
2397  || (new_sk_n==1
2398  && !atomic_points_to_cell_p(CELL(CAR(new_sk_l))))) {
2399  na = make_approximation_may();
2400  }
2401  else
2402  na = copy_approximation(a);
2403  FOREACH(CELL, new_sk, new_sk_l) {
2404  points_to new_pt = make_points_to(copy_cell(new_sr),
2405  copy_cell(new_sk),
2406  na,
2408  set_add_element(gen, gen, (void*)new_pt);
2409  }
2410  }
2411  // gen_full_free_list(new_sr_l);
2412  // gen_full_free_list(new_sk_l);
2413  free_approximation(a);
2414  }
2415  else {
2416  /* The translation of pt's sink failed. */
2417  /* Note: the piece of code below is replicated */
2419  if(approximation_may_p(a)) {
2420  if(!points_to_cell_in_list_p(sk1, translation_failures)) {
2421  /* The caller does not have to have counterparts for all
2422  hypothetical stubs that *may* be developped in
2423  callee. */
2424  pips_user_warning("Points-to sink cell sk1=\"%s\" could not be translated.\n",
2425  points_to_cell_name(sk1));
2426  translation_failures = CONS(CELL, sk1, translation_failures);
2427  }
2428  }
2429  else {
2430  pips_user_warning("Points-to sink cell sk1=\"%s\" could not be translated but has to be.\n",
2431  points_to_cell_name(sk1));
2432  set_free(gen);
2433  gen = set_undefined;
2434  break;
2435  }
2436  }
2437  }
2438  else {
2439  /* The translation of pt's source failed. This may occur
2440  * because the callee had to assume a pointer points to an
2441  * array, whereas the call site associates it to a scalar.
2442  *
2443  * See for instance Pointers/formal_parameter01.c
2444  *
2445  * But this may also occur because the formal parameter cannot
2446  * be translated because the effective argument is an
2447  * address_of expression. See for instance
2448  * EffectsWithPointsTO/call01.c.
2449  *
2450  * We have no way to guess here the reason for the translation
2451  * failure...
2452  */
2454  // FI: we should check that it is a formal parameter of "f"...
2455  if(!formal_parameter_p(v)) {
2457  if(approximation_may_p(a)) {
2458  if(!points_to_cell_in_list_p(sr1, translation_failures)) {
2459  pips_user_warning("Points-to source cell sr1=\"%s\" could not be translated.\n",
2460  points_to_cell_name(sr1));
2461  translation_failures = CONS(CELL, sr1, translation_failures);
2462  }
2463  }
2464  else {
2465  /* Could be a user error, but you may prefer to go on with
2466  * the points-to analysis to perform some dead code
2467  * elimination later...
2468  */
2469  pips_user_warning("Points-to source cell sr1=\"%s\" could not be translated but has to be.\n",
2470  points_to_cell_name(sr1));
2471  set_free(gen);
2472  gen = set_undefined;
2473  break;
2474  }
2475  }
2476  }
2477  }
2478  }
2479 
2480  gen_free_list(translation_failures);
2481 
2482  ifdebug(1) {
2483  if(set_undefined_p(gen))
2484  fprintf(stderr, "pt_gen is bottom\n");
2485  else
2486  print_points_to_set("pt_gen_1", gen);
2487  }
2488 
2489  return gen;
2490 }
approximation copy_approximation(approximation p)
APPROXIMATION.
Definition: effects.c:132
void free_approximation(approximation p)
Definition: effects.c:135
#define new_simple_pt_map()
bool atomic_points_to_cell_p(cell)
Is it a unique concrete memory location?
Definition: points_to.c:423
#define approximation_may_p(x)
Definition: effects.h:363
#define approximation_undefined
Definition: effects.h:326
#define set_undefined
Definition: newgen_set.h:48
void set_free(set)
Definition: set.c:332
string points_to_cell_name(cell)
Create a string which is the cell reference in C syntax.
static statement gen(int what, entity src, entity trg, entity lid, entity proc, entity(*create_src)(), entity(*create_trg)(), Psysteme sr, list ldiff)
arguments: all that may be useful to generate some code
Definition: remapping.c:498
entity entity_to_module_entity(entity e)
Find the enclosing module of an entity.
Definition: entity.c:2053
bool formal_parameter_p(entity)
Definition: variable.c:1489

References anywhere_cell_p(), approximation_may_p, approximation_undefined, array_type_p(), atomic_points_to_cell_p(), CAR, CELL, cell_any_reference(), cell_typed_anywhere_locations_p(), CONS, copy_approximation(), copy_cell(), ENDP, entity_basic_concrete_type(), entity_to_module_entity(), f(), FOREACH, formal_parameter_p(), fprintf(), free_approximation(), gen(), gen_free_list(), gen_length(), heap_cell_p(), ifdebug, int, make_approximation_may(), make_descriptor_none(), make_points_to(), new_simple_pt_map, NIL, nowhere_cell_p(), null_cell_p(), pips_user_warning, points_to_approximation, points_to_cell_in_list_p(), points_to_cell_name(), points_to_cell_translation(), points_to_sink, points_to_source, print_points_to_set(), reference_variable, set_add_element(), SET_FOREACH, set_free(), set_undefined, and set_undefined_p.

Referenced by user_call_to_points_to_interprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compute_points_to_kill_set()

set compute_points_to_kill_set ( list  ,
set  ,
set   
)

◆ condition_to_points_to()

pt_map condition_to_points_to ( expression  c,
pt_map  in,
bool  true_p 
)

Update points-to set "in" according to the content of the expression using side effects.

Use "true_p" to know if the condition must be met or not.

FI: the side effects should not be taken into account because this function is often called twice, once for the true branch and once for the false branch of a test.

For instance, C short cut "if(p)" for "if(p!=NULL)"

Parameters
inn
true_prue_p

Definition at line 2512 of file expression.c.

2513 {
2514  pt_map out = in;
2515  if(!points_to_graph_bottom(in)) {
2516  syntax cs = expression_syntax(c);
2517 
2518  if(syntax_reference_p(cs)) {
2519  /* For instance, C short cut "if(p)" for "if(p!=NULL)" */
2520  //out = reference_condition_to_points_to(syntax_reference(cs), in, true_p);
2522  }
2523  else if(syntax_call_p(cs)) {
2524  //list el = expression_to_proper_constant_path_effects(c);
2525  list el = NIL;
2526  out = call_condition_to_points_to(syntax_call(cs), in, el, true_p);
2527  //gen_full_free_list(el);
2528  }
2529  else {
2530  pips_internal_error("Not implemented yet.\n");
2531  }
2532  }
2533  pips_assert("out is consistent", points_to_graph_consistent_p(out));
2534  return out;
2535 }
pt_map reference_condition_to_points_to(reference r, pt_map in, bool true_p)
Handle conditions such as "if(p)".
Definition: expression.c:2538
pt_map call_condition_to_points_to(call c, pt_map in, list el, bool true_p)
Handle any condition that is a call such as "if(p!=q)", "if(*p)", "if(foo(p=q))".....
Definition: expression.c:2595
#define syntax_reference_p(x)
Definition: ri.h:2728

References call_condition_to_points_to(), expression_syntax, NIL, out, pips_assert, pips_internal_error, points_to_graph_bottom, points_to_graph_consistent_p(), reference_condition_to_points_to(), syntax_call, syntax_call_p, syntax_reference, and syntax_reference_p.

Referenced by any_loop_to_points_to(), boolean_intrinsic_call_condition_to_points_to(), intrinsic_call_condition_to_points_to(), intrinsic_call_to_points_to(), new_any_loop_to_points_to(), ternary_intrinsic_call_to_points_to_sinks(), and test_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ consistent_points_to_arc_p()

bool consistent_points_to_arc_p ( points_to  a,
bool  constant_subscript_p 
)

I: two issue:

  • st should be the type of the variable entity used in the source (or the destination)
  • type_depth() is the maximal depth value; the depth depends on the fields followed in a struct. A more careful analysis of the subscript would be needed to check the subscripts.
Parameters
constant_subscript_ponstant_subscript_p

Definition at line 2822 of file points_to_set.c.

2823 {
2824  bool consistent_p = true;
2825 
2826  consistent_p = consistent_p && points_to_consistent_p(a);
2827  cell s = points_to_source(a);
2828  reference sr = cell_any_reference(s);
2829  if(constant_subscript_p) {
2830  consistent_p = consistent_p && store_independent_points_to_reference_p(sr);
2831  if(!consistent_p)
2832  pips_internal_error("Store dependent points-to source.\n");
2833  }
2834  else {
2835  consistent_p = consistent_p && !memory_dereferencing_p(sr);
2836  if(!consistent_p)
2837  pips_internal_error("Dereferencing points-to source.\n");
2838  }
2839 
2840  /*FI: two issue:
2841  *
2842  * - st should be the type of the variable entity used in the source
2843  * (or the destination)
2844  *
2845  * - type_depth() is the maximal depth value; the depth depends on
2846  * the fields followed in a struct. A more careful analysis of the
2847  * subscript would be needed to check the subscripts.
2848  */
2849 #if false
2851  int sn = type_depth(st);
2852  list ssl = reference_indices(sr);
2853  consistent_p = sn==(int) gen_length(ssl);
2854 
2855  if(!consistent_p)
2856  pips_internal_error("Unexpected number of subscripts for points-to source.\n");
2857 #endif
2858 
2859  cell d = points_to_sink(a);
2860  reference dr = cell_any_reference(d);
2861  if(constant_subscript_p) {
2862  consistent_p = consistent_p && store_independent_points_to_reference_p(dr);
2863  if(!consistent_p)
2864  pips_internal_error("Store dependent points-to sink.\n");
2865  }
2866  else {
2867  // memory_dereferencing_p() could be replaced by
2868  // effect_reference_dereferencing_p()
2869  consistent_p = consistent_p && !memory_dereferencing_p(dr);
2870  // consistent_p = consistent_p && !effect_reference_dereferencing_p(dr);
2871  if(!consistent_p)
2872  pips_internal_error("Dereferencing points-to sink.\n");
2873  }
2874 
2875 #if false
2877  int dn = type_depth(dt);
2878  list dsl = reference_indices(dr);
2879  consistent_p = dn<=(int) gen_length(dsl);
2880 
2881  if(!consistent_p)
2882  pips_internal_error("Unexpected number of subscripts for points-to source.\n");
2883 #endif
2884 
2885  return consistent_p;
2886 }
bool points_to_consistent_p(points_to p)
type points_to_reference_to_concrete_type(reference)
Definition: type.c:685
bool memory_dereferencing_p(reference)
Does the set of locations referenced by r depend on a pointer dereferencing?
Definition: effects.c:92
bool store_independent_points_to_reference_p(reference)
Functions for points-to references, the kind of references used in points-to cells.
Definition: points_to.c:1247
size_t type_depth(type)
Number of steps to access the lowest leave of type t without dereferencing.
Definition: type.c:4880

References cell_any_reference(), gen_length(), int, memory_dereferencing_p(), pips_internal_error, points_to_consistent_p(), points_to_reference_to_concrete_type(), points_to_sink, points_to_source, reference_indices, store_independent_points_to_reference_p(), and type_depth().

Referenced by dereferencing_free_points_to_arc_p(), and store_independent_points_to_arc_p().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ consistent_points_to_graph_p()

bool consistent_points_to_graph_p ( points_to_graph  ptg)
Parameters
ptgtg

Definition at line 3475 of file points_to_set.c.

3476 {
3477  bool consistent_p;
3478  set ptg_s = points_to_graph_set(ptg);
3479  if(points_to_graph_bottom(ptg)) {
3480  consistent_p = set_empty_p(ptg_s);
3481  if(!consistent_p)
3482  pips_internal_error("Bottom graph is not empty.\n");
3483  }
3484  else {
3485  consistent_p = consistent_points_to_set(ptg_s);
3486  }
3487  return consistent_p;
3488 }
bool set_empty_p(const set)
tell whether set s is empty.
Definition: set.c:367
bool consistent_points_to_set(set s)
make sure that set "s" does not contain redundant or contradictory elements

References consistent_points_to_set(), pips_internal_error, points_to_graph_bottom, points_to_graph_set, and set_empty_p().

Referenced by any_loop_to_points_to(), binary_intrinsic_call_to_points_to_sinks(), internal_pointer_assignment_to_points_to(), list_assignment_to_points_to(), and whileloop_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ consistent_points_to_set()

bool consistent_points_to_set ( set  s)

make sure that set "s" does not contain redundant or contradictory elements

Check the consistency of each arc

Check the validity of the approximations

Make sure that the element of set "s" belong to "s" (issue with side effects performed on subscript expressions).

Check that no sharing exists between arcs at the cell and reference levels

Definition at line 2900 of file points_to_set.c.

2901 {
2902  bool consistent_p = true;
2903 
2904  /* Check the consistency of each arc */
2905  SET_FOREACH(points_to, a, s) {
2906  consistent_p = consistent_p && store_independent_points_to_arc_p(a);
2907  }
2908 
2909  /* Check the validity of the approximations */
2910  SET_FOREACH(points_to, pt1, s) {
2912  SET_FOREACH(points_to, pt2, s) {
2913  if(pt1!=pt2) {
2914  //same source
2915  cell c1 = points_to_source(pt1);
2916  cell c2 = points_to_source(pt2);
2917  bool cmp1 = locations_equal_p(c1,c2);
2918 
2919  if(cmp1 && approximation_exact_p(a1)) {
2920  fprintf(stderr,
2921  "Contradictory points-to arcs: incompatible approximation\n");
2922  print_points_to(pt1);
2923  print_points_to(pt2);
2924  consistent_p = false;
2925  }
2926 
2927  // same sink
2928  cell c3 = points_to_sink(pt1);
2929  cell c4 = points_to_sink(pt2);
2930  bool cmp2 = locations_equal_p(c3,c4);
2931  if(cmp1&&cmp2) {
2932  // same approximation
2935  // FI: must is forgotten...
2936  //bool cmp3 = (approximation_exact_p(a1) && approximation_exact_p(a2))
2937  // || ( approximation_may_p(a1) && approximation_may_p(a2));
2938  // FI: should we identify "exact" and "must"?
2939  bool cmp3 = (approximation_tag(a1)==approximation_tag(a2));
2940  if(cmp3) {
2941  fprintf(stderr, "Redundant points-to arc:\n");
2942  print_points_to(pt1);
2943  consistent_p = false;
2944  }
2945  else {
2946  fprintf(stderr, "Contradictory points-to arcs: incompatible approximation\n");
2947  print_points_to(pt1);
2948  print_points_to(pt2);
2949  consistent_p = false;
2950  }
2951  }
2952  }
2953  }
2954  }
2955 
2956  /* Make sure that the element of set "s" belong to "s" (issue with
2957  * side effects performed on subscript expressions).
2958  */
2959  SET_FOREACH(points_to, pt, s) {
2960  if(!set_belong_p(s,pt)) {
2961  fprintf(stderr, "Points-to %p ", pt);
2962  print_points_to(pt);
2963  fprintf(stderr, " is in set s but does not belong to it!\n");
2964  consistent_p = false;
2965  }
2966  }
2967 
2968  /* Check that no sharing exists between arcs at the cell and
2969  reference levels */
2970  if(consistent_p) {
2971  consistent_p = !points_to_set_sharing_p(s);
2972  if(!consistent_p)
2973  fprintf(stderr, "Sharing detected\n");
2974  }
2975  return consistent_p;
2976 }
#define approximation_tag(x)
Definition: effects.h:362
bool set_belong_p(const set, const void *)
Definition: set.c:194
bool points_to_set_sharing_p(set s)
bool locations_equal_p(cell acc1, cell acc2)
eturn true if two acces_path are equals
Definition: points_to_set.c:89
void print_points_to(const points_to pt)

References approximation_exact_p, approximation_tag, fprintf(), locations_equal_p(), points_to_approximation, points_to_set_sharing_p(), points_to_sink, points_to_source, print_points_to(), set_belong_p(), SET_FOREACH, and store_independent_points_to_arc_p().

Referenced by consistent_points_to_graph_p(), list_assignment_to_points_to(), merge_points_to_set(), and user_call_to_points_to_interprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ constant_call_to_points_to()

pt_map constant_call_to_points_to ( call  ,
pt_map   
)

◆ control_equal_p()

bool control_equal_p ( const void *  vc1,
const void *  vc2 
)
Parameters
vc1c1
vc2c2

Definition at line 71 of file unstructured.c.

72 {
73  control c1 = (control)vc1;
74  control c2 = (control)vc2;
77 
79 
80 }
struct _newgen_struct_control_ * control
#define statement_ordering(x)
Definition: ri.h:2454
#define control_statement(x)
Definition: ri.h:941

References control_statement, s1, and statement_ordering.

Referenced by new_points_to_unstructured().

+ Here is the caller graph for this function:

◆ control_in_set_p()

bool control_in_set_p ( control  c,
set  s 
)

unstructured.c

unstructured.c

Definition at line 61 of file unstructured.c.

62 {
63  bool in_p = false;
64  SET_FOREACH(control, n, s) {
66  in_p = true;
67  }
68  return in_p;
69 }
static bool statement_equal_p(statement s1, statement s2)
Definition: unstructured.c:55

References control_statement, SET_FOREACH, and statement_equal_p().

Referenced by new_points_to_unstructured().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ control_rank()

_uint control_rank ( const void *  vc,
size_t  size 
)

create a key which is the statement number

Parameters
vcc
sizeize

Definition at line 83 of file unstructured.c.

84 {
85  control c = (control)vc;
87  // FI: use asprintf?
88  extern char * int2a(int);
89  string key = strdup(int2a(statement_ordering(s)));
90  return hash_string_rank(key,size);
91 }
_uint hash_string_rank(const void *, size_t)
en s'inspirant vaguement de Fast Hashing of Variable-Length Text Strings Peter K.
Definition: hash.c:642
char * strdup()
char * int2a(int)
util.c
Definition: util.c:42

References control_statement, hash_string_rank(), int2a(), statement_ordering, and strdup().

Referenced by new_points_to_unstructured().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ create_advanced_stub_points_to()

points_to create_advanced_stub_points_to ( cell  c,
type  t,
bool  exact_p 
)

Take into account the POINTS_TO_STRICT_POINTER_TYPE to allocate a sink cell of type "t" if the strictness is requested and of type "array of t" if not.

assume that pointers to scalars always points towards an array of unknown dimension.

Parameters
exact_pxact_p

Definition at line 688 of file points_to_init_analysis.c.

689 {
690  pips_internal_error("This function is no longer used. Functionality moved into create_stub_points_to directly...\n");
692  bool strict_p = get_bool_property("POINTS_TO_STRICT_POINTER_TYPES");
693  if(true || strict_p || array_type_p(t))
694  pt = create_stub_points_to(c, t, exact_p);
695  else {
696  /* assume that pointers to scalars always points towards an array
697  of unknown dimension. */
698  type at = type_to_array_type(t);
699  pt = create_stub_points_to(c, at, exact_p);
700  // FI: I do not know if we should free t [and/or at]
701  }
702  return pt;
703 }
#define points_to_undefined
type type_to_array_type(type)
convert a type "t" into a newly allocated array type "at" whose elements are of type "t",...
Definition: type.c:5653

References array_type_p(), create_stub_points_to(), get_bool_property(), pips_internal_error, points_to_undefined, and type_to_array_type().

+ Here is the call graph for this function:

◆ create_k_limited_stub_points_to()

points_to create_k_limited_stub_points_to ( cell  source,
type  t,
bool  array_p,
pt_map  in 
)

Create a new node "sink" of type "t" and a new arc "pt" starting from node "source", if no path starting from any node and ending in "source", built with arcs in the points-to set "in", contains more than k nodes of type "t" (the type of the sink).

If k nodes of type "t" are already in the path, create a new arc "pt" between the "source" and the k-th node in the path.

Parameter "array_p" indicates if the source is an array or a scalar. Different models can be chosen. For instance, Beatrice Creusillet wants to have an array as target and obtain something like argv[*]->_argv_1[*] although argv[*]->_argv-1 might also be a correct model if _argv_1 is an abstract location representing lots of different physical locations.

Parameter k is defined by a property.

FI: not to clear about what is going to happen when "source" is the final node of several paths.

Also, beware of circular paths.

Efficiency is not yet a goal...

& od>=odl

No cycle could be created, the paths can safely be made longer.

Parameters
sourceource
array_prray_p
inn

Definition at line 1077 of file points_to_set.c.

1078 {
1079  int k = get_int_property("POINTS_TO_PATH_LIMIT");
1080  pips_assert("k is greater than one", k>=1);
1082 
1083  // FI: the vertex with an excessive out-degree does not have to be
1084  // source and is not source in list05 case... The test below is useless
1085 
1086  // We should check the out-degree of each source in "in" and see if
1087  // any is beyond limit.
1088 
1089  //list sink_l = points_to_source_to_sinks(source, in, false);
1090  //int od = (int) gen_length(sink_l);
1091  //string mod_cell_name = string_undefined; // maximum out-degree cell
1092  //int od = maximal_out_degree_of_points_to_graph(&mod_cell_name, in);
1093  // list sink_l = points_to_source_to_sinks(mod_cell_name, in, false);
1094  //list sink_l = points_to_source_name_to_sinks(mod_cell_name, in, false);
1095  if(false /*&& od>=odl*/ ) {
1096  // FI: not too sure about argument "true"
1097  //cell mod_cell = points_to_source_name_to_source_cell(mod_cell_name, in, true);
1098  //pt = fuse_points_to_sink_cells(mod_cell, sink_l, in);
1099  ;
1100  }
1101  else {
1102  list p = CONS(CELL, source, NIL); // points-to path...
1103 
1104  // FI: not to sure about he possible memory leaks...
1105  pt = points_to_path_to_k_limited_points_to_path(p, k, t, array_p, in);
1106 
1107  /* No cycle could be created, the paths can safely be made longer. */
1108  if(points_to_undefined_p(pt)) {
1109  // exact or not?
1110  // FI: the points-to towards NULL will be added later by a caller...
1111  bool exact_p = !get_bool_property("POINTS_TO_NULL_POINTER_INITIALIZATION");
1112  pt = create_stub_points_to(source, t, exact_p);
1113  }
1114  gen_free_list(p);
1115  }
1116  return pt;
1117 }
points_to create_stub_points_to(cell, type, bool)
#define points_to_undefined_p(x)
points_to points_to_path_to_k_limited_points_to_path(list p, int k, type t, bool array_p, pt_map in)
"p" is a points-to path ending with a cell that points towards a new cell ot type "t".

References CELL, CONS, create_stub_points_to(), gen_free_list(), get_bool_property(), get_int_property(), NIL, pips_assert, points_to_path_to_k_limited_points_to_path(), points_to_undefined, and points_to_undefined_p.

Referenced by formal_source_to_sinks(), generic_stub_source_to_sinks(), and global_source_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ create_pointer_to_array_stub_points_to()

points_to create_pointer_to_array_stub_points_to ( cell  c,
type  t,
bool  exact_p 
)

To create the points-to stub associated to the formal parameter, the sink name is a concatenation of the formal parmater and the POINTS_TO_MODULE_NAME.

Parameters
exact_pxact_p

Definition at line 709 of file points_to_init_analysis.c.

710 {
711  list l_ind = NIL;
712  basic bb = basic_undefined;
716  reference sink_ref = reference_undefined;
717  cell source_cell = copy_cell(c);
718  reference r = cell_any_reference(source_cell);
719  entity e = reference_variable(r);
720  const char * en = entity_user_name(e);
721  string s = NULL;
722  if( formal_parameter_p(e) ) {
724  int off = formal_offset(f);
725  s = strdup(concatenate("_", en,"_", int2a(off), NULL));
726  }
727  else {
728  char *suffix = strrchr(en,'_');
729  s = strdup(concatenate( en, suffix, NULL ));
730  }
731 
732  string formal_name = strdup(concatenate(get_current_module_name() ,MODULE_SEP_STRING, s, NULL));
733  entity stub_entity = gen_find_entity(formal_name);
734  type pt = type_undefined;
735  bool type_strict_p = get_bool_property("POINTS_TO_STRICT_POINTER_TYPES");
736  bb = variable_basic(type_variable(t));
738  basic base = copy_basic(bb);
739  FOREACH(DIMENSION, d, l_dim){
740  l = dimension_lower(d);
741  u = dimension_upper(d);
742  l_ind = CONS(EXPRESSION, l, NIL);
743  l_ind = gen_nconc(l_ind, (CONS(EXPRESSION, u, NIL)));
744  }
745 
746 
747  if(type_strict_p)
748  pt = make_type_variable(
750  CONS(DIMENSION,
752  ex,
753  NIL),
754  NIL),
755  NIL));
756  else
757  pt = copy_type(t);
758 
759  if(entity_undefined_p(stub_entity)) {
762  // FI->AM: weird, it is redone when the entity already exists
765  DummyTarget,
767  stub_entity = make_entity(formal_name,
768  pt,
769  // FI->AM: if it is made rom, then
770  // the entitY is no longer
771  // recognized by entity_stub_sink_p()
772  // make_storage_rom(),
773  rs,
775  }
776 
777  if(type_strict_p)
778  sink_ref = make_reference(stub_entity, CONS(EXPRESSION, int_to_expression(0), NIL));
779  else if((int)gen_length(l_dim)>1){
780  sink_ref = make_reference(stub_entity,l_ind);
781  }
782  else {
783  // sink_ref = make_reference(stub_entity, CONS(EXPRESSION, int_to_expression(0), NIL));
784  // FI: no reason to index an array; see "p = &a;"
785  sink_ref = make_reference(stub_entity, NIL);
786  }
787 
788  cell sink_cell = make_cell_reference(sink_ref);
789  approximation rel =
791  points_to pt_to = make_points_to(source_cell, sink_cell, rel,
793  pointer_index ++;
794  return pt_to;
795 }
value make_value_unknown(void)
Definition: ri.c:2847
type make_type_variable(variable _field_)
Definition: ri.c:2715
entity gen_find_entity(char *s)
Definition: ri.c:2551
basic copy_basic(basic p)
BASIC.
Definition: ri.c:104
ram make_ram(entity a1, entity a2, intptr_t a3, list a4)
Definition: ri.c:1999
variable make_variable(basic a1, list a2, list a3)
Definition: ri.c:2895
storage make_storage_ram(ram _field_)
Definition: ri.c:2279
bdt base
Current expression.
Definition: bdt_read_paf.c:100
const char * get_current_module_name(void)
Get the name of the current module.
Definition: static.c:121
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
#define POINTER_DUMMY_TARGETS_AREA_LOCAL_NAME
Definition: naming-local.h:77
#define MODULE_SEP_STRING
Definition: naming-local.h:30
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
static int pointer_index
#define make_entity(n, t, s, i)
#define UNKNOWN_RAM_OFFSET
@ ENTITY_POINTER_DUMMY_TARGETS_AREA
entity FindOrCreateEntity(const char *package, const char *local_name)
Problem: A functional global entity may be referenced without parenthesis or CALL keyword in a functi...
Definition: entity.c:1586
expression int_to_expression(_int i)
transform an int into an expression and generate the corresponding entity if necessary; it is not cle...
Definition: expression.c:1188
#define formal_offset(x)
Definition: ri.h:1408
#define reference_undefined
Definition: ri.h:2302
#define dimension_lower(x)
Definition: ri.h:980
#define entity_storage(x)
Definition: ri.h:2794
#define storage_formal(x)
Definition: ri.h:2524
#define basic_undefined
Definition: ri.h:556
#define entity_undefined_p(x)
Definition: ri.h:2762
#define expression_undefined
Definition: ri.h:1223
#define dimension_upper(x)
Definition: ri.h:982
#define entity_kind(x)
Definition: ri.h:2798

References base, basic_undefined, cell_any_reference(), concatenate(), CONS, copy_basic(), copy_cell(), copy_type(), DIMENSION, dimension_lower, dimension_upper, entity_kind, ENTITY_POINTER_DUMMY_TARGETS_AREA, entity_storage, entity_undefined_p, entity_user_name(), EXPRESSION, expression_undefined, f(), FindOrCreateEntity(), FOREACH, formal_offset, formal_parameter_p(), gen_find_entity(), gen_length(), gen_nconc(), get_bool_property(), get_current_module_entity(), get_current_module_name(), int2a(), int_to_expression(), make_approximation_exact(), make_approximation_may(), make_cell_reference(), make_descriptor_none(), make_dimension(), make_entity, make_points_to(), make_ram(), make_reference(), make_storage_ram(), make_type_variable(), make_unbounded_expression(), make_value_unknown(), make_variable(), MODULE_SEP_STRING, NIL, POINTER_DUMMY_TARGETS_AREA_LOCAL_NAME, pointer_index, reference_undefined, reference_variable, storage_formal, strdup(), type_undefined, type_variable, UNKNOWN_RAM_OFFSET, variable_basic, and variable_dimensions.

Referenced by pointer_formal_parameter_to_stub_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ create_scalar_stub_sink_cell()

cell create_scalar_stub_sink_cell ( entity  v,
type  st,
type  pt,
int  d,
list  sl,
string  fs 
)

Create a stub entity "se" for entity "v" with type "t" and return a cell based on a reference to the stub entity "se" with "d" unbounded subscripts to account for the dimension of the source and a zero subscript for implicit array.

Type "pt" is the theoretically expected type for the reference "sink_ref" within the returned cell, "sink_cell". We assert "pt==points_to_cell_to_type(sink_cell)".

Type "t" must account for the extra "d" dimensions.

The type strictness is handled by the caller.

The name of the function is misleading. It should be "create_stub_sink_cell"... but in fact is does not handle the struct case because struct can contain may different pointers, directly or indirectly, depending on fields. This function is ok if v a pointer or an array of pointers, but not if v is a struct.

The function is called four times from create_stub_points_to().

When scalars are used, we should have "d==0" and "td==0" and hence "sl==NIL"

FI: use 0 for all proper target dimensions

FI: adding 0 subscripts is similar to a dereferencing. We do not know at this level if the dereferencing has been requested. See pointer_reference02. The handling fo eval_p must be modified correspondingly by adding 0 subscripts when the source is an array. Or evaluation must be skipped.

Parameters
stt
ptt
sll
fss

Definition at line 267 of file points_to_init_analysis.c.

273 {
274  //type vt = entity_basic_concrete_type(v);
275  //pips_assert("v is not a struct", !struct_type_p(vt));
276  type t = type_undefined;
277 
278  if(type_void_p(st))
279  t = MakeTypeOverloaded();
280  else
281  t = copy_type(st);
282 
283  entity stub_entity = create_stub_entity(v, fs, t);
284  reference sink_ref = reference_undefined;
285 
286  ifdebug(1) {
287  pips_debug(1, "Entity \"%s\"\n", entity_local_name(v));
288  pips_debug(1, "Stub type: "); print_type(t);
289  fprintf(stderr, "\n");
290  pips_debug(1, "Pointed type: "); print_type(pt);
291  fprintf(stderr, "\n");
292  pips_debug(1, "Number of source dimensions: %d\n", d);
293  fprintf(stderr, "\n");
294  }
295 
296  if(type_functional_p(t)) {
297  pips_assert("The source dimension is zero if the target is not an array", d==0);
298  sink_ref = make_reference(stub_entity, NIL);
299  }
300  else if(type_variable_p(t)) {
301  /* When scalars are used, we should have "d==0" and "td==0" and hence "sl==NIL" */
303  pips_assert("The target dimension is greater than or equal to the source dimension", d<=td);
304  int i;
305  //if(false) {
306  if(true) {
307  list tl = NIL;
308  /* FI: use 0 for all proper target dimensions */
309  /* FI: adding 0 subscripts is similar to a dereferencing. We do
310  not know at this level if the dereferencing has been
311  requested. See pointer_reference02. The handling fo eval_p must
312  be modified correspondingly by adding 0 subscripts when the
313  source is an array. Or evaluation must be skipped. */
314  for(i=d;i<td;i++) {
315  tl = CONS(EXPRESSION, make_zero_expression(), tl);
316  }
317  sl = gen_nconc(sl, tl);
318  sink_ref = make_reference(stub_entity, sl);
319  }
320  else {
321  sink_ref = make_reference(stub_entity, sl);
322  bool e_to_be_freed;
323  type ept = points_to_reference_to_type(sink_ref, &e_to_be_freed);
324  i = d;
325  while(!array_pointer_type_equal_p(pt, ept)
326  && !(type_void_p(pt) && overloaded_type_p(ept))
327  && i<td) {
328  if(e_to_be_freed) free_type(ept);
330  reference_indices(sink_ref) =
331  gen_nconc(reference_indices(sink_ref), tl);
332  ept = points_to_reference_to_type(sink_ref, &e_to_be_freed);
333  i++;
334  }
335  if(!array_pointer_type_equal_p(pt, ept)
336  && !(type_void_p(pt) && overloaded_type_p(ept)))
337  pips_internal_error("The stub and expected types are incompatible.\n");
338  else {
339  ;
340  }
341  if(e_to_be_freed) free_type(ept);
342  }
343  }
344  else if(type_void_p(t)) {
345  pips_assert("Implemented", false);
346  }
347 
348  cell sink_cell = make_cell_reference(sink_ref);
349 
350  ifdebug(1) {
351  type ept = points_to_cell_to_concrete_type(sink_cell);
352  if(!array_pointer_type_equal_p(pt, ept)
353  && !(type_void_p(pt) || overloaded_type_p(ept))) {
354  bool ok_p = false;
355  if(array_type_p(pt)) {
356  if(!array_type_p(ept)) {
357  // FI: do not forget the [0] subscript added...
359  basic bept = variable_basic(type_variable(ept));
360  if(basic_equal_p(bpt, bept))
361  ok_p = true; // to be able to breakpointx
362  }
363  }
364  if(!ok_p) {
365  pips_debug(1, "pt = "); print_type(pt);
366  fprintf(stderr, "\n");
367  pips_debug(1, "ept = "); print_type(ept);
368  fprintf(stderr, "\n");
369  pips_internal_error("Effective type of sink cell does not match its expected type\n");
370  }
371  }
372  pips_debug(1, "source entity: \"%s\", sink_cell: ", entity_user_name(v));
373  print_points_to_cell(sink_cell);
374  fprintf(stderr, "\n");
375  pips_assert("sink_cell is consistent", cell_consistent_p(sink_cell));
376  }
377 
378  return sink_cell;
379 }
bool cell_consistent_p(cell p)
Definition: effects.c:255
type points_to_cell_to_concrete_type(cell)
Definition: type.c:676
type points_to_reference_to_type(reference, bool *)
FI: I need more generality than is offered by cell_to_type()
Definition: type.c:527
entity create_stub_entity(entity e, string fs, type t)
Allocate a stub entity "stub" for entity "e" and with type "t".
#define print_points_to_cell(x)
Definition: print.c:377
void print_type(type)
For debugging.
Definition: type.c:111
int variable_dimension_number(variable)
Definition: type.c:5632
bool basic_equal_p(basic, basic)
Definition: type.c:927
type MakeTypeOverloaded(void)
Definition: type.c:107

References array_pointer_type_equal_p(), array_type_p(), basic_equal_p(), cell_consistent_p(), CONS, copy_type(), create_stub_entity(), entity_local_name(), entity_user_name(), EXPRESSION, fprintf(), free_type(), gen_nconc(), ifdebug, make_cell_reference(), make_reference(), make_zero_expression(), MakeTypeOverloaded(), NIL, overloaded_type_p(), pips_assert, pips_debug, pips_internal_error, points_to_cell_to_concrete_type(), points_to_reference_to_type(), print_points_to_cell, print_type(), reference_indices, reference_undefined, type_functional_p, type_undefined, type_variable, type_variable_p, type_void_p, variable_basic, and variable_dimension_number().

Referenced by create_stub_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ create_stub_entity()

entity create_stub_entity ( entity  e,
string  fs,
type  t 
)

Allocate a stub entity "stub" for entity "e" and with type "t".

Abort if "stub" already exists.

It seems that type "t" could be derived from "e" since it should be the pointed type of "e"'s type, but it is not at all the case in general. Variable e is used to build a reference and the type pointed by the reference may be different when arrays of structs of arrays of structs are involved.

FI: I assume all unknown offsets defined in ri-util-local.h to be strictly negative.

FI: we could use a 0 as default offset for clarity?

FI: we are in deep trouble because the stub entity has already been created... but we have no idea if it is or not the entity we wanted as it depends on field names in the reference. And the reference is not available from this function.

Parameters
fss

Definition at line 151 of file points_to_init_analysis.c.

152 {
153  // local name for the stub
154  string s = string_undefined;
155  string en = (string) entity_user_name(e);
156 
157  // FI: guarantee about *local* new name uniqueness?
158  if(formal_parameter_p(e)) {
159  // Naming for sinks of formal parameters: use their offsets
161  int off = formal_offset(f);
162  s = strdup(concatenate("_", en, fs,"_", int2a(off), NULL));
163  }
164  else if(top_level_entity_p(e) && !entity_stub_sink_p(e)) {
165  // FI: global_variable_p()
166  // Naming for sinks of global variables: use their offsets
167  int off = ram_offset(storage_ram(entity_storage(e)));
168  /* FI: I assume all unknown offsets defined in ri-util-local.h to
169  be strictly negative. */
170  if(off>=0)
171  s = strdup(concatenate("_", en, fs, "_", int2a(off), NULL));
172  else
173  /* FI: we could use a 0 as default offset for clarity? */
174  s = strdup(concatenate("_", en, fs, "_", NULL));
175  }
176  else if(static_global_variable_p(e)){ // "static int i;"
177  // Naming for sinks of static global variable: use their offsets
178  int off = ram_offset(storage_ram(entity_storage(e)));
179  s = strdup(concatenate("_", en, fs,"_", int2a(off), NULL));
180  }
181  else if(entity_stub_sink_p(e)) {
182  // Naming for sinks of stubs: repeat their last suffix
183  char *suffix = strrchr(en,'_');
184  s = strdup(concatenate( en, fs, suffix, NULL ));
185  }
186 
187  // FI: the stub entity already exists?
188 
189  // This is not OK in an interprocedural setting
190  //entity m = get_current_module_entity();
191  // entity m = entity_to_module_entity(e);
193 
194  //string formal_name = strdup(concatenate(get_current_module_name(),
195  // MODULE_SEP_STRING, s, NULL));
196  string formal_name = strdup(concatenate(entity_local_name(m),
197  MODULE_SEP_STRING, s, NULL));
198  entity stub = gen_find_entity(formal_name);
199  // FI: I expect here a pips_assert("The stub cannot exist",
200  // entity_undefined_p(stub));
201 
202  // If entity "stub" does not already exist, create it.
203  if(entity_undefined_p(stub)) {
206  if(type_undefined_p(entity_type(fa))) {
207  // entity a = module_to_heap_area(f);
209 
210  //ram r = make_ram(f, a, DYNAMIC_RAM_OFFSET, NIL);
213  // FI: DO we want to declare it abstract location?
215  //entity_kind(fa) = ENTITY_FORMAL_AREA;
217  }
218  stub = make_entity(formal_name,
219  copy_type(t),
222  (void) add_C_variable_to_area(fa, stub);
223 
224  AddEntityToDeclarations(stub, m);
225  }
226  else {
227  /* FI: we are in deep trouble because the stub entity has already
228  * been created... but we have no idea if it is or not the entity we
229  * wanted as it depends on field names in the reference. And the
230  * reference is not available from this function.
231  */
232  type st = entity_basic_concrete_type(stub);
233  if(array_pointer_type_equal_p(st, t)) {
234  // This may happen when evaluating conditions on demand because
235  // they are evaluated twice, once true and once false.
236  ;
237  }
238  else
239  // Should be an internal error...
240  pips_internal_error("Type incompatible request for a stub.\n");
241  }
242 
243  return stub;
244 }
storage make_storage_rom(void)
Definition: ri.c:2285
value make_value(enum value_utype tag, void *val)
Definition: ri.c:2832
area make_area(intptr_t a1, list a2)
Definition: ri.c:98
type make_type(enum type_utype tag, void *val)
Definition: ri.c:2706
#define FORMAL_AREA_LOCAL_NAME
Definition: naming-local.h:76
#define string_undefined
Definition: newgen_types.h:40
char * string
STRING.
Definition: newgen_types.h:39
#define UU
Definition: newgen_types.h:98
#define DYNAMIC_RAM_OFFSET
FI: I would have assumed that it is used for the stack area, but I must be wrong.....
@ ENTITY_FORMAL_AREA
@ ABSTRACT_LOCATION
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
const char * entity_module_name(entity e)
See comments about module_name().
Definition: entity.c:1092
void AddEntityToDeclarations(entity, entity)
END_EOLE.
Definition: variable.c:108
bool static_global_variable_p(entity)
Is v a global variable declared local to a C file such "static int i;".
Definition: variable.c:1498
int add_C_variable_to_area(entity, entity)
Definition: variable.c:1381
#define type_undefined_p(x)
Definition: ri.h:2884
#define storage_ram(x)
Definition: ri.h:2521
@ is_type_area
Definition: ri.h:2899
#define ram_offset(x)
Definition: ri.h:2251

References ABSTRACT_LOCATION, add_C_variable_to_area(), AddEntityToDeclarations(), array_pointer_type_equal_p(), concatenate(), copy_type(), DYNAMIC_RAM_OFFSET, entity_basic_concrete_type(), ENTITY_FORMAL_AREA, entity_initial, entity_kind, entity_local_name(), entity_module_name(), entity_storage, entity_stub_sink_p(), entity_type, entity_undefined_p, entity_user_name(), f(), FindOrCreateEntity(), FORMAL_AREA_LOCAL_NAME, formal_offset, formal_parameter_p(), gen_find_entity(), int2a(), is_type_area, is_value_unknown, make_area(), make_entity, make_ram(), make_storage_ram(), make_storage_rom(), make_type(), make_value(), make_value_unknown(), module_name_to_entity(), MODULE_SEP_STRING, NIL, pips_internal_error, ram_offset, static_global_variable_p(), storage_formal, storage_ram, strdup(), string_undefined, top_level_entity_p(), type_undefined_p, and UU.

Referenced by create_scalar_stub_sink_cell().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ create_stub_points_to()

points_to create_stub_points_to ( cell  ,
type  ,
bool   
)

◆ declaration_statement_to_points_to()

pt_map declaration_statement_to_points_to ( statement  s,
pt_map  pt_in 
)

See points_to_init()

pt_in is modified by side-effects and returned

generate points-to due to the initialisation

AM/FI: abnormal sharing (lhs); the reference may be reused in the cel...

free_expression(lhs);

The initialization expression may use pointers, directly or indirectly via struct and arrays.

Take care of expressions in array sizing (see array12.c)

Parameters
pt_int_in

Definition at line 262 of file statement.c.

263 {
264  pt_map pt_out = pt_in;
265  //set pt_out = set_generic_make(set_private, points_to_equal_p, points_to_rank);
266  list l = NIL;
267  //bool type_sensitive_p = !get_bool_property("ALIASING_ACROSS_TYPES");
268 
269  list l_decls = statement_declarations(s);
270 
271  pips_debug(1, "declaration statement \n");
272 
273  FOREACH(ENTITY, e, l_decls) {
275  if(pointer_type_p(et)
277  || struct_type_p(et)
278  || array_of_struct_type_p(et)) {
279  if( !storage_rom_p(entity_storage(e)) ) {
280  // FI: could be simplified with variable_initial_expression()
281  value v_init = entity_initial(e);
282  /* generate points-to due to the initialisation */
283  if(value_expression_p(v_init)){
284  expression exp_init = value_expression(v_init);
287  // See C standard for type compatibility + PIPS idiosyncrasies
288  // This should be extended to cope with the C type hierarchy
289  // accept side effects
290  pt_out = expression_to_points_to(exp_init, pt_out, true);
291  //if(array_pointer_type_equal_p(et, it)
292  //if(concrete_type_equal_p(et, it)
293  if(type_structurally_equal_p(et, it)
294  || array_pointer_type_equal_p(et, it)
295  || type_void_star_p(et) || type_void_star_p(it)
296  || integer_type_p(it)
297  || (char_star_type_p(et) && string_type_p(it))
298  || overloaded_type_p(it)) // PIPS own compatibility...
299  pt_out = assignment_to_points_to(lhs,
300  exp_init,
301  pt_out);
302  else {
303  pips_user_warning("Type mismatch for initialization of \"%s\" at line %d.\n",
304  entity_user_name(e),
306  clear_pt_map(pt_out);
307  points_to_graph_bottom(pt_out) = true;
308  }
309  /* AM/FI: abnormal sharing (lhs); the reference may be
310  reused in the cel... */
311  /* free_expression(lhs); */
312  }
313  else {
315  // C Standard: if e is a static pointer, it is implicly
316  // initialized to NULL
317  if(pointer_type_p(et) && variable_static_p(e)) {
318  cell source = CELL(CAR(l));
319  cell sink = make_null_cell();
320  points_to pt = make_points_to(source, sink,
323  add_arc_to_pt_map(pt, pt_out);
324  // The declared variable is local
325  // add_arc_to_points_to_context(copy_points_to(pt));
326  }
327  else {
328  FOREACH(CELL, source, l) {
329  cell sink = cell_to_nowhere_sink(source);
330  points_to pt = make_points_to(source, sink,
333  add_arc_to_pt_map(pt, pt_out);
334  // The declared variable is local
335  // add_arc_to_points_to_context(copy_points_to(pt));
336  }
337  }
338  }
339  }
340  }
341  else {
342  /* The initialization expression may use pointers, directly or
343  indirectly via struct and arrays. */
345  if(!expression_undefined_p(ie)) {
346  pt_out = expression_to_points_to(ie, pt_out, true);
347  free_expression(ie);
348  }
349  }
350  /* Take care of expressions in array sizing (see array12.c) */
351  if(array_type_p(et)) {
352  variable ev = type_variable(et);
353  list dl = variable_dimensions(ev);
354  FOREACH(DIMENSION, d, dl) {
357  pt_out = expression_to_points_to(l, pt_out, true);
358  pt_out = expression_to_points_to(u, pt_out, true);
359  }
360  }
361  }
362 
363  return pt_out;
364 }
cell cell_to_nowhere_sink(cell source)
assuming source is a reference to a pointer, build the corresponding sink when the pointer is not ini...
int points_to_context_statement_line_number()
Definition: statement.c:120
cell make_null_cell(void)
Definition: sinks.c:95
list variable_to_pointer_locations(entity)
variable.c
Definition: variable.c:66
bool type_void_star_p(type)
Definition: type.c:5765
type expression_to_type(expression)
For an array declared as int a[10][20], the type returned for a[i] is int [20].
Definition: type.c:2486
bool integer_type_p(type)
Definition: type.c:3298
expression variable_initial_expression(entity)
Returns a copy of the initial (i.e.
Definition: variable.c:1899
bool char_star_type_p(type)
Beware of typedefs.
Definition: type.c:5774
#define statement_declarations(x)
Definition: ri.h:2460
#define storage_rom_p(x)
Definition: ri.h:2525
#define value_expression_p(x)
Definition: ri.h:3080

References add_arc_to_pt_map, array_of_pointers_type_p(), array_of_struct_type_p(), array_pointer_type_equal_p(), array_type_p(), assignment_to_points_to(), CAR, CELL, cell_to_nowhere_sink(), char_star_type_p(), clear_pt_map, compute_basic_concrete_type(), DIMENSION, dimension_lower, dimension_upper, ENTITY, entity_basic_concrete_type(), entity_initial, entity_storage, entity_to_expression(), entity_user_name(), expression_to_points_to(), expression_to_type(), expression_undefined_p, FOREACH, free_expression(), integer_type_p(), make_approximation_exact(), make_descriptor_none(), make_null_cell(), make_points_to(), NIL, overloaded_type_p(), pips_debug, pips_user_warning, pointer_type_p(), points_to_context_statement_line_number(), points_to_graph_bottom, statement_declarations, storage_rom_p, string_type_p(), struct_type_p(), type_structurally_equal_p(), type_variable, type_void_star_p(), value_expression, value_expression_p, variable_dimensions, variable_initial_expression(), variable_static_p(), and variable_to_pointer_locations().

Referenced by statement_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ delete_printed_points_to_list()

points_to_list delete_printed_points_to_list ( statement  )

◆ dereferencing_free_points_to_arc_p()

bool dereferencing_free_points_to_arc_p ( points_to  a)

Definition at line 2893 of file points_to_set.c.

2894 {
2895  return consistent_points_to_arc_p(a, false);
2896 }
bool consistent_points_to_arc_p(points_to a, bool constant_subscript_p)

References consistent_points_to_arc_p().

Referenced by add_subscript_dependent_arc_to_simple_pt_map().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dereferencing_subscript_to_points_to()

pt_map dereferencing_subscript_to_points_to ( subscript  sub,
pt_map  in 
)

dereferencing.c

dereferencing.c

But all pointer values must be generated, whether they point to pointers or anything else.

This piece of code is designed to handle pointer19.c, and hence pointer14.c, where arrays of pointers toward arrays of pointers are used.

It generates too many arcs, useless arcs, when the subscript list is broken down into many subscript constructs by PIPS C parser. This shows in Pointers/pointer14, 15 and 19.

a cannot evaluate to null or undefined

FI: we may need a special case for stubs...

We have to take "sel" into account since only the base of the target array is pointed to.

We have to bother with the source if it is an array, not if it is simply a pointer dereferenced by some subscripts as in dereferencing18.c.

Look for points-to arcs that must be duplicated using the subscripts as offsets

We must generate a new source with the offset defined by sel, and a new sink, with or without a an offset

Update the source cell

Is the source cell already known in the points-to relation?

Update the sink cell if necessary

Build the new points-to arc

Do not update set "in" while you are enumerating its elements

Update sets "in" with the new arcs. The arc must pre-exist the reference for the effects to be able to translate a non-constant effect. Thus, it should pre-exist the call site.

FI: I am not sure this is useful...

Parameters
subub
inn

Definition at line 71 of file dereferencing.c.

72 {
73  expression a = subscript_array(sub);
74  type at = expression_to_type(a);
75  type apt = type_to_pointed_type(at);
76  list sel = subscript_indices(sub);
77  /* a cannot evaluate to null or undefined */
78  /* FI: we may need a special case for stubs... */
79  in = dereferencing_to_points_to(a, in);
80  /* We have to take "sel" into account since only the base of the
81  target array is pointed to. */
82  list source_l = expression_to_points_to_sources(a, in);
83  list n_arc_l = NIL;
84 
85  FOREACH(CELL, source, source_l) {
86  /* We have to bother with the source if it is an array, not if it
87  is simply a pointer dereferenced by some subscripts as in
88  dereferencing18.c. */
89  reference source_r = cell_any_reference(source);
90  entity source_v = reference_variable(source_r);
91  type source_v_t = entity_basic_concrete_type(source_v);
92 
93  if(array_type_p(source_v_t)) {
94  /* Look for points-to arcs that must be duplicated using the
95  subscripts as offsets */
97  cell pt_source = points_to_source(pt);
98  //if(points_to_cell_in_list_p(pt_source, source_l)) {
99  if(points_to_cell_equal_p(pt_source, source)) {
100  /* We must generate a new source with the offset defined by sel,
101  and a new sink, with or without a an offset */
102  cell pt_sink = points_to_sink(pt);
103  cell n_source = cell_undefined;
104 
105  /* Update the source cell */
106  if(null_cell_p(pt_source)) {
107  pips_internal_error("NULL cannot be a source cell.\n");;
108  }
109  else if(anywhere_cell_p(pt_source)
110  || cell_typed_anywhere_locations_p(pt_source)) {
111  pips_internal_error("Not sure what should be done here!\n");
112  }
113  else {
114  n_source = copy_cell(pt_source);
115  reference n_source_r = cell_any_reference(n_source);
116  if(adapt_reference_to_type(n_source_r, at,
118  reference_indices(n_source_r) = gen_nconc(reference_indices(n_source_r),
119  gen_full_copy_list(sel));
121  }
122  else
123  pips_internal_error("No idea how to deal with this source cell.\n");
124  }
125 
126  /* Is the source cell already known in the points-to relation? */
127 
128  if(!cell_undefined_p(n_source) && !source_in_pt_map_p(n_source, in)) {
129  cell n_sink = copy_cell(pt_sink);
130 
131  /* Update the sink cell if necessary */
132  if(null_cell_p(pt_sink)) {
133  ;
134  }
135  else if(anywhere_cell_p(pt_sink)
136  || cell_typed_anywhere_locations_p(pt_sink)) {
137  ;
138  }
139  else {
140  reference n_sink_r = cell_any_reference(n_sink);
141  if(adapt_reference_to_type(n_sink_r, apt,
143  reference_indices(n_sink_r) = gen_nconc(reference_indices(n_sink_r),
144  gen_full_copy_list(sel));
146  }
147  else
148  pips_internal_error("No idea how to deal with this sink cell.\n");
149  }
150 
151  /* Build the new points-to arc */
153  points_to n_pt = make_points_to(n_source, n_sink, ap,
155  /* Do not update set "in" while you are enumerating its elements */
156  n_arc_l = CONS(POINTS_TO, n_pt, n_arc_l);
157  }
158  else
159  free_cell(n_source);
160  }
161  }
162  }
163  }
164 
165  /* Update sets "in" with the new arcs. The arc must pre-exist the
166  reference for the effects to be able to translate a non-constant
167  effect. Thus, it should pre-exist the call site. */
168  FOREACH(POINTS_TO, n_pt, n_arc_l) {
169  add_arc_to_pt_map(n_pt, in);
172  }
173  gen_free_list(n_arc_l);
174 
175  /* FI: I am not sure this is useful... */
176  in = expression_to_points_to(a, in, false); // side effects
177 
178  in = expressions_to_points_to(sel, in, false);
179 
180  free_type(at);
181  return in;
182 }
#define source_in_pt_map_p(cell, set)
pt_map dereferencing_to_points_to(expression p, pt_map in)
Make sure that expression p can be dereferenced in points-to graph "in".
bool adapt_reference_to_type(reference, type, int(*)(void))
FI: a really stupid function...
Definition: type.c:1327
void complete_points_to_reference_with_zero_subscripts(reference)
Definition: points_to.c:745
#define cell_undefined_p(x)
Definition: effects.h:431
void add_arc_to_points_to_context(points_to pt)
FI: it should rather work the other way round, with add_arc_to_statement_points_to_context() calling ...
Definition: passes.c:268
list expression_to_points_to_sources(expression, pt_map)
expression_to_points_to_sources() does not always work, especially with pointer arithmetic or subscri...
Definition: sinks.c:1805
#define subscript_indices(x)
Definition: ri.h:2563
#define subscript_array(x)
Definition: ri.h:2561

References adapt_reference_to_type(), add_arc_to_points_to_context(), add_arc_to_pt_map, add_arc_to_statement_points_to_context(), anywhere_cell_p(), array_type_p(), CELL, cell_any_reference(), cell_typed_anywhere_locations_p(), cell_undefined, cell_undefined_p, complete_points_to_reference_with_zero_subscripts(), CONS, copy_approximation(), copy_cell(), copy_points_to(), dereferencing_to_points_to(), entity_basic_concrete_type(), expression_to_points_to(), expression_to_points_to_sources(), expression_to_type(), expressions_to_points_to(), FOREACH, free_cell(), free_type(), gen_free_list(), gen_full_copy_list(), gen_nconc(), make_descriptor_none(), make_points_to(), NIL, null_cell_p(), pips_internal_error, POINTS_TO, points_to_approximation, points_to_cell_equal_p(), points_to_context_statement_line_number(), points_to_graph_set, points_to_sink, points_to_source, reference_indices, reference_variable, SET_FOREACH, source_in_pt_map_p, subscript_array, subscript_indices, and type_to_pointed_type().

Referenced by dereferencing_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dereferencing_to_points_to()

pt_map dereferencing_to_points_to ( expression  p,
pt_map  in 
)

Make sure that expression p can be dereferenced in points-to graph "in".

Handling of NULL pointers according to property.

Handling of undefined pointers according to property.

"in" is modified by side effects. Arcs certainly incompatible with a dereferencing are removed. If dereferencing of p is no longer possible, return an empty points-to "in" as the expression cannot be evaluated.

This is conditional to two properties.

ut =

You must take care of s.tab, which is encoded by a call

EffectsWithPointsTo/struct08.c: ae = (e.champ)[i], fe = p

For side effects on "in"

Parameters
inn

Definition at line 198 of file dereferencing.c.

199 {
200  //pt_map out = in;
201  bool null_dereferencing_p
202  = get_bool_property("POINTS_TO_NULL_POINTER_DEREFERENCING");
203  bool nowhere_dereferencing_p
204  = get_bool_property("POINTS_TO_UNINITIALIZED_POINTER_DEREFERENCING");
205  // FI: we cannot use expression_to_points_to_sources or sinks
206  // because side effects are taken into acount each time they are
207  // called.
208  if(!nowhere_dereferencing_p && !null_dereferencing_p) {
209  syntax s = expression_syntax(p);
210  tag t = syntax_tag(s);
211 
212  switch(t) {
213  case is_syntax_reference: {
215  /*out = */reference_dereferencing_to_points_to(r, in,
216  nowhere_dereferencing_p,
217  null_dereferencing_p);
218  break;
219  }
220  case is_syntax_range: {
221  //range r = syntax_range(s);
222  // out = range_to_points_to(r, in);
223  break;
224  }
225  case is_syntax_call: {
226  call c = syntax_call(s);
227  list al = call_arguments(c);
228 
229  // FI: you do not want to apply side-effects twice...
230  // But you then miss the detection of pointers that are not NULL
231  // because they are dereferenced and you miss the recursive descent
232  //in = expressions_to_points_to(al, in, false);
233  //in = call_to_points_to(c, in, el, false);
234 
235  /* You must take care of s.tab, which is encoded by a call */
236  entity f = call_function(c);
237  if(ENTITY_FIELD_P(f)) {
238  expression ae = EXPRESSION(CAR(al));
239  expression fe = EXPRESSION(CAR(CDR(al)));
240  /* EffectsWithPointsTo/struct08.c: ae = (e.champ)[i], fe = p*/
241  //pips_assert("ae and fe are references",
242  // expression_reference_p(ae) && expression_reference_p(fe));
243  pips_assert("fe is a reference", expression_reference_p(fe));
245  entity fv = reference_variable(fr);
247  if(pointer_type_p(ft) || struct_type_p(ft)
249  || array_of_struct_type_p(ft)) {
250  in = dereferencing_to_points_to(ae, in);
251  /* For side effects on "in" */
252  list sink_l = expression_to_points_to_sinks(p, in);
253  gen_free_list(sink_l);
254  }
255  }
256  else {
257  // Do not take side-effects into account or they will be applied twice
258  in = expressions_to_points_to(al, in, false);
259  in = call_to_points_to(c, in, NIL, false);
261  gen_free_list(sl);
262  }
263  break;
264  }
265  case is_syntax_cast: {
266  //cast c = syntax_cast(s);
267  //expression ce = cast_expression(c);
268  //out = expression_to_points_to(ce, in);
269  break;
270  }
272  //sizeofexpression soe = syntax_sizeofexpression(s);
273  //if(sizeofexpression_type_p(soe))
274  //; // in is not modified
275  //else {
276  // expression ne = sizeofexpression_expression(soe);
277  // FI: we have a problem because sizeof(*p) does not imply that
278  // *p is evaluated...
279  // out = expression_to_points_to(ne, in);
280  //;
281  //}
282  break;
283  }
284  case is_syntax_subscript: {
285  subscript sub = syntax_subscript(s);
287  break;
288  }
289  case is_syntax_application: {
290  // FI: we might have to go down here...
291  //application a = syntax_application(s);
292  //out = application_to_points_to(a, out);
293  break;
294  }
295  case is_syntax_va_arg: {
296  // The call to va_arg() does not create a points-to per se
297  //list soel = syntax_va_arg(s);
298  //sizeofexpression soe1 = SIZEOFEXPRESSION(CAR(soel));
299  //sizeofexpression soe2 = SIZEOFEXPRESSION(CAR(CDR(soel)));
300  //expression se = sizeofexpression_expression(soe1);
301  // type t = sizeofexpression_type(soe2);
302  //out = expression_to_points_to(se, out);
303  break;
304  }
305  default:
306  ;
307  }
308  }
309  return in;
310 }
pt_map reference_dereferencing_to_points_to(reference r, pt_map in, bool nowhere_dereferencing_p, bool null_dereferencing_p)
Can we execute the reference r in points-to context "in" without segfaulting?
pt_map dereferencing_subscript_to_points_to(subscript sub, pt_map in)
FI: As usual in dereferencing.c, it is not clear that this piece of code has not been implemented som...
Definition: dereferencing.c:71
pt_map call_to_points_to(call c, pt_map pt_in, list el, bool side_effect_p)
Three different kinds of calls are distinguished:
Definition: expression.c:306
list expression_to_points_to_sinks(expression, pt_map)
The returned list contains cells used in "in".
Definition: sinks.c:1795
#define syntax_tag(x)
Definition: ri.h:2727
@ is_syntax_range
Definition: ri.h:2692
@ is_syntax_application
Definition: ri.h:2697
@ is_syntax_cast
Definition: ri.h:2694
@ is_syntax_call
Definition: ri.h:2693
@ is_syntax_va_arg
Definition: ri.h:2698
@ is_syntax_reference
Definition: ri.h:2691
@ is_syntax_sizeofexpression
Definition: ri.h:2695
@ is_syntax_subscript
Definition: ri.h:2696
#define syntax_subscript(x)
Definition: ri.h:2745

References array_of_pointers_type_p(), array_of_struct_type_p(), call_arguments, call_function, call_to_points_to(), CAR, CDR, dereferencing_subscript_to_points_to(), entity_basic_concrete_type(), ENTITY_FIELD_P, EXPRESSION, expression_reference(), expression_reference_p(), expression_syntax, expression_to_points_to_sinks(), expressions_to_points_to(), f(), gen_free_list(), get_bool_property(), is_syntax_application, is_syntax_call, is_syntax_cast, is_syntax_range, is_syntax_reference, is_syntax_sizeofexpression, is_syntax_subscript, is_syntax_va_arg, NIL, pips_assert, pointer_type_p(), reference_dereferencing_to_points_to(), reference_variable, struct_type_p(), syntax_call, syntax_reference, syntax_subscript, and syntax_tag.

Referenced by dereferencing_subscript_to_points_to(), expression_to_points_to(), intrinsic_call_condition_to_points_to(), intrinsic_call_to_points_to(), and reference_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dereferencing_to_sinks()

list dereferencing_to_sinks ( expression  a,
pt_map  in,
bool  eval_p 
)

Returns "sinks", the list of cells pointed to by expression "a" according to points-to graph "in".

If eval_p is true, perform a second dereferencing on the cells obtained with the first dereferencing.

Manage NULL and undefined (nowhere) cells.

Possibly update the points-to graph when some arcs are incompatible with the request, assuming the analyzed code is correct.

Locate the pointer, no dereferencing yet... unless no pointer can be found as in *(p+2) in which case an evaluation occurs/might occur/used to occur in expression_to_points_to_sources().

lse

Finds what it is pointing to, memory(p)

Do we want to dereference c?

Do not create sharing between elements of "in" and elements of "sinks".

The sinks list is empty, whether eval_p is true or not...

FI: New cells have been allocated by source_to_sinks(): side-effects are OK. In theory... The source code of source_to_sinks() seems to show that fresh_p is not exploited in all situations.

Parameters
inn
eval_pval_p

Definition at line 432 of file dereferencing.c.

433 {
434  list sinks = NIL;
435  /* Locate the pointer, no dereferencing yet... unless no pointer can
436  be found as in *(p+2) in which case an evaluation occurs/might
437  occur/used to occur in expression_to_points_to_sources(). */
439  if(ENDP(cl)) {
440  // The source may not be found, e.g. *(p+i)
441  //sinks = expression_to_points_to_sinks(a, in);
442  cl = expression_to_points_to_sinks(a, in);
443  }
444  /*else*/ { // Some sources have been found
446  bool evaluated_p = !expression_to_points_to_cell_p(a);
447  // evaluated_p = false;
448  if(!evaluated_p || eval_p) {
449  bool null_dereferencing_p
450  = get_bool_property("POINTS_TO_NULL_POINTER_DEREFERENCING");
451  bool nowhere_dereferencing_p
452  = get_bool_property("POINTS_TO_UNINITIALIZED_POINTER_DEREFERENCING");
453 
454  /* Finds what it is pointing to, memory(p) */
455  FOREACH(CELL, c, cl) {
456  /* Do we want to dereference c? */
457  if( (null_dereferencing_p || !null_cell_p(c))
458  && (nowhere_dereferencing_p || !nowhere_cell_p(c))) {
459  list o_pointed = source_to_sinks(c, in, true);
460  remove_impossible_arcs_to_null(&o_pointed, in);
461  /* Do not create sharing between elements of "in" and elements of
462  "sinks". */
463  // list pointed = source_to_sinks(c, in, true);
464  list pointed = gen_full_copy_list(o_pointed);
465  gen_free_list(o_pointed);
466  if(ENDP(pointed)) {
468  entity v = reference_variable(r);
469  string words_to_string(list);
470  pips_user_warning("No pointed location for variable \"%s\" and reference \"%s\"\n",
471  entity_user_name(v),
473  /* The sinks list is empty, whether eval_p is true or not... */
474  }
475  else {
476  if(!evaluated_p && eval_p) {
477  FOREACH(CELL, sc, pointed) {
478  bool to_be_freed;
479  type t = points_to_cell_to_type(sc, &to_be_freed);
480  if(!pointer_type_p(t)) {
481  // FI: it might be necessary to allocate a new copy of sc
482  sinks = gen_nconc(sinks, CONS(CELL, sc, NIL));
483  }
484  else if(array_type_p(t) || struct_type_p(t)) {
485  /* FI: New cells have been allocated by
486  source_to_sinks(): side-effects are OK. In
487  theory... The source code of source_to_sinks() seems
488  to show that fresh_p is not exploited in all
489  situations. */
490  //cell nsc = copy_cell(sc);
491  //points_to_cell_add_zero_subscripts(nsc);
492  //sinks = gen_nconc(sinks, CONS(CELL, nsc, NIL));
493  pips_internal_error("sc assume saturated with 0 subscripts and/or field susbscripts.\n");
494  }
495  else {
496  list starpointed = pointer_source_to_sinks(sc, in);
497  // sinks = gen_nconc(sinks, starpointed);
498  sinks = merge_points_to_cell_lists(sinks, starpointed);
499  }
500  if(to_be_freed) free_type(t);
501  }
502  }
503  else
504  sinks = gen_nconc(sinks, pointed);
505  }
506  }
507  }
508  }
509  else
510  sinks = cl;
511  }
512 
513  return sinks;
514 }
bool expression_to_points_to_cell_p(expression e)
Can expression e be reduced to a reference, without requiring an evaluation?
list merge_points_to_cell_lists(list, list)
Add in "l1" elements of "l2" that are not yet in "l1".
Definition: points_to.c:134
list pointer_source_to_sinks(cell, pt_map)
Returns the sinks for a source cell "sc" of type pointer according to the points-to relation "in".
string reference_to_string(reference r)
Definition: expression.c:87
string words_to_string(cons *lw)
Definition: print.c:211

References array_type_p(), CELL, cell_any_reference(), CONS, ENDP, entity_user_name(), expression_to_points_to_cell_p(), expression_to_points_to_sinks(), expression_to_points_to_sources(), FOREACH, free_type(), gen_free_list(), gen_full_copy_list(), gen_nconc(), get_bool_property(), merge_points_to_cell_lists(), NIL, nowhere_cell_p(), null_cell_p(), pips_internal_error, pips_user_warning, pointer_source_to_sinks(), pointer_type_p(), points_to_cell_to_type(), reference_to_string(), reference_variable, remove_impossible_arcs_to_null(), source_to_sinks(), struct_type_p(), and words_to_string().

Referenced by unary_intrinsic_call_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ derived_formal_parameter_to_stub_points_to()

set derived_formal_parameter_to_stub_points_to ( type  pt,
cell  c 
)

Input : a formal parameter which has a derived type (FI, I guess).

output : a set of points-to where sinks are stub points-to.

FI: a lot of rewrite needed to simplify. Also, do not forget that NULL maybe the received value.

maybe should be removed if we have already called ultimate type in formal_points_to_parameter()

We ignore dimensions for the time being, descriptors are not implemented yet...Amira Mensi

ultimate_type() returns a wrong type for arrays. For example for type int*[10] it returns int*[10] instead of int[10].

In fact, there should be a FOREACH to scan all elements of l_ef

free the spine

Parameters
ptt

Definition at line 952 of file points_to_init_analysis.c.

953 {
956  bool exact_p = !get_bool_property("POINTS_TO_NULL_POINTER_INITIALIZATION");
961  /* maybe should be removed if we have already called ultimate type
962  * in formal_points_to_parameter() */
963 
964  type upt = type_to_pointed_type(pt);
965  r = cell_any_reference(c);
966  e = reference_variable(r);
967 
968  if(type_variable_p(upt)){
969  if(array_entity_p(e)){
970  /* We ignore dimensions for the time being, descriptors are not
971  * implemented yet...Amira Mensi*/
972  ;
973  /* ultimate_type() returns a wrong type for arrays. For
974  * example for type int*[10] it returns int*[10] instead of int[10]. */
975  }
976  else {
977  basic fpb = variable_basic(type_variable(upt));
978  if( basic_derived_p(fpb)) {
981  if(type_variable_p(t)){
983  if(basic_derived_p(vb)){
984  entity ed = basic_derived(vb);
985  type et = entity_type(ed);
986  if(type_struct_p(et)){
987  list l1 = type_struct(et);
988  FOREACH(ENTITY, i, l1){
989 
991  if(expression_pointer_p(ef)){
992  type ent_type = entity_type(i);
993  fpb = variable_basic(type_variable(ent_type));
995  ex,
996  ef);
999  list l_ef = NIL;
1001  true);
1002  ef = EFFECT(CAR(l_ef)); /* In fact, there should be a FOREACH to scan all elements of l_ef */
1003  gen_free_list(l_ef); /* free the spine */
1004 
1005  reference source_ref = effect_any_reference(ef);
1006  effects_free(l1);
1008  type p_ent_type = compute_basic_concrete_type(type_to_pointed_type(ent_type));
1009  cell source_cell = make_cell_reference(source_ref);
1010  pt_to = create_stub_points_to(source_cell, p_ent_type, exact_p);
1011  pt_in = set_add_element(pt_in, pt_in,
1012  (void*) pt_to );
1013  }
1014 
1015  }
1016  }
1017  }
1018  }
1019  }
1020  }
1021  }
1022 
1023  return pt_in;
1024 
1025 
1026 }
list generic_proper_effects_of_complex_address_expression(expression, list *, int)
void effects_free(list)
void generic_effects_reset_all_methods(void)
void set_methods_for_proper_simple_effects(void)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
#define effect_undefined
Definition: effects.h:614
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
#define FIELD_OPERATOR_NAME
Definition: ri-util-local.h:91
bool array_entity_p(entity e)
Definition: entity.c:793
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
expression MakeBinaryCall(entity f, expression eg, expression ed)
Creates a call expression to a function with 2 arguments.
Definition: expression.c:354
bool expression_pointer_p(expression e)
we get the type of the expression by calling expression_to_type() which allocates a new one.
Definition: expression.c:506
#define basic_derived_p(x)
Definition: ri.h:638
#define entity_undefined
Definition: ri.h:2761

References array_entity_p(), basic_derived, basic_derived_p, CAR, cell_any_reference(), compute_basic_concrete_type(), create_stub_points_to(), EFFECT, effect_any_reference, effect_undefined, effects_free(), ENTITY, entity_intrinsic(), entity_to_expression(), entity_type, entity_undefined, expression_pointer_p(), FIELD_OPERATOR_NAME, FOREACH, gen_free_list(), generic_effects_reset_all_methods(), generic_proper_effects_of_complex_address_expression(), get_bool_property(), make_cell_reference(), MakeBinaryCall(), NIL, points_to_equal_p(), points_to_rank(), points_to_undefined, reference_undefined, reference_variable, set_add_element(), set_generic_make(), set_methods_for_proper_simple_effects(), set_private, type_struct, type_struct_p, type_to_pointed_type(), type_variable, type_variable_p, ultimate_type(), and variable_basic.

Referenced by formal_points_to_parameter().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dump_points_to()

void dump_points_to ( const  points_to)
Parameters
points_tot

Definition at line 609 of file points_to_set.c.

610 {
611  print_or_dump_points_to(pt, false);
612 }
void print_or_dump_points_to(const points_to pt, bool print_p)
print a points-to arc for debug

References print_or_dump_points_to().

Referenced by points_to_set_sharing_p(), and print_or_dump_points_to_set().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dump_points_to_set()

void dump_points_to_set ( string  what,
set  s 
)
Parameters
whathat

Definition at line 640 of file points_to_set.c.

641 {
642  print_or_dump_points_to_set(what, s, false);
643 }
void print_or_dump_points_to_set(string what, set s, bool print_p)
Print a set of points-to for debug.

References print_or_dump_points_to_set().

+ Here is the call graph for this function:

◆ entity_any_module_p()

bool entity_any_module_p ( entity  e)

operator kill for the dimension Module:

  • modules should be different from any_module otherwise we return false
  • when modules are different from any_module we test the equality of their names opkill_may_module : Module * Module -> Bool opkill_must_module : Module * Module -> Bool test if a module is the any_module location, to be moved to anywhere_abstract_locations.c later...

Definition at line 234 of file constant-path-utils.c.

235 {
236  bool any_module_p;
238 
239  return any_module_p;
240 }
#define ANY_MODULE_NAME
#define same_string_p(s1, s2)

References ANY_MODULE_NAME, entity_module_name(), and same_string_p.

Referenced by opgen_may_module(), opgen_must_module(), opkill_may_module(), and opkill_must_module().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ entity_to_cell()

cell entity_to_cell ( entity  e)

Definition at line 80 of file sinks.c.

81 {
82  reference nr = make_reference(e, NIL);
83  cell nc = make_cell_reference(nr);
84  return nc;
85 }

References make_cell_reference(), make_reference(), and NIL.

Referenced by make_null_cell().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ entity_to_sinks()

list entity_to_sinks ( entity  e)

sinks.c

sinks.c

No check on e for the time being

Definition at line 72 of file sinks.c.

73 {
74  reference nr = make_reference(e, NIL);
75  cell nc = make_cell_reference(nr);
76  list sinks = CONS(CELL, nc, NIL);
77  return sinks;
78 }

References CELL, CONS, make_cell_reference(), make_reference(), and NIL.

Referenced by points_to_anywhere_sinks(), points_to_null_sinks(), and user_call_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ equal_condition_to_points_to()

pt_map equal_condition_to_points_to ( list  al,
pt_map  in 
)

The expression list "al" contains exactly two arguments, "lhs" and "rhs".

Check if "lhs==rhs" may return true.

If these expressions are pointers, "in" is modified by removing arcs that are not compatible with the equality. If no arc is left, a bottom "out" is returned.

If one of these two expressions cannot be evaluated according to the C standard, i.e. its value is undefined, a bottom graph is returned.

"out" is "in", modified by side-effects.

This function has many commonalities with non_equal_condition_to_points_to(). They were developped independently to avoid mistakes when dealing with negations of quantifiers. They could now be unified.

Is it impossible to evaluate lhs?

The check is too low. The message will be emitted twice because conditions are often evaluated as true and false.

Is it impossible to evaluate rhs?

Is the condition feasible?

Parameters
all
inn

Definition at line 2986 of file expression.c.

2987 {
2988  pt_map out = in;
2989  expression lhs = EXPRESSION(CAR(al));
2990  expression rhs = EXPRESSION(CAR(CDR(al)));
2991 
2992  // FI: in fact, any integer could be used in a pointer comparison...
2993  if(expression_null_p(lhs))
2995  else if(expression_null_p(rhs))
2997  else {
2998  type lhst = expression_to_type(lhs);
2999  type rhst = expression_to_type(rhs);
3000  if(pointer_type_p(lhst) && pointer_type_p(rhst)) {
3002  int nL = (int) gen_length(L);
3003  /* Is it impossible to evaluate lhs?
3004  *
3005  * The check is too low. The message will be emitted twice
3006  * because conditions are often evaluated as true and false.
3007  */
3008  if(nL==1 && nowhere_cell_p(CELL(CAR(L)))) {
3009  clear_pt_map(out);
3010  points_to_graph_bottom(out) = true;
3011  pips_user_warning("Unitialized pointer is used to evaluate expression"
3012  " \"%s\" at line %d.\n", expression_to_string(lhs),
3014  }
3015  else {
3016  /* Is it impossible to evaluate rhs? */
3017  list R = expression_to_points_to_sinks(rhs, in);
3018  int nR = (int) gen_length(R);
3019  if(nR==1 && nowhere_cell_p(CELL(CAR(R)))) {
3020  clear_pt_map(out);
3021  points_to_graph_bottom(out) = true;
3022  pips_user_warning("Unitialized pointer is used to evaluate expression"
3023  " \"%s\".\n", expression_to_string(rhs),
3025  }
3026  else {
3027  /* Is the condition feasible? */
3028  bool equal_p = false;
3029  FOREACH(CELL, cl, L) {
3030  FOREACH(CELL, cr, R) {
3031  if(points_to_cells_intersect_p(cl, cr)) {
3032  equal_p = true;
3033  break;
3034  }
3035  }
3036  if(equal_p)
3037  break;
3038  }
3039  if(!equal_p) {
3040  // lhs==rhs is impossible
3041  clear_pt_map(out);
3042  points_to_graph_bottom(out) = true;
3043  }
3044  else {
3045  // It is possible to remove some arcs? if18.c
3046  int nL = (int) gen_length(L);
3047  int nR = (int) gen_length(R);
3048  cell c = cell_undefined;
3049  list O = list_undefined;
3050  if(nL==1 && atomic_points_to_cell_p(CELL(CAR(L)))) {
3051  c = CELL(CAR(L));
3053  }
3054  else if(nR==1 && atomic_points_to_cell_p(CELL(CAR(R)))) {
3055  c = CELL(CAR(R));
3057  }
3058  if(!cell_undefined_p(c)) {
3059  if((int) gen_length(O)==1) {
3060  cell oc = CELL(CAR(O));
3063  copy_cell(c),
3066  add_arc_to_pt_map(pt, out);
3067  }
3068  }
3069  }
3070  }
3071  }
3072  }
3073  free_type(lhst), free_type(rhst);
3074  }
3075  return out;
3076 }
bool points_to_cells_intersect_p(cell, cell)
points-to cells use abstract addresses, hence the proper comparison is an intersection.
Definition: points_to.c:532
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
pt_map null_equal_condition_to_points_to(expression e, pt_map in)
The condition is e==NULL.
Definition: expression.c:2849
points_to_graph points_to_cell_source_projection(points_to_graph, cell)
Remove all arcs in "ptg" starting from "c".
string expression_to_string(expression e)
Definition: expression.c:77
bool expression_null_p(expression exp)
returns true if the expression is equal to zero or NULL (even if there is a cast before such as in (v...
Definition: expression.c:2611
static list expression_to_points_to_sources(_UNUSED_ expression e, _UNUSED_ points_to_graph in)
Definition: expression.c:108
static list expression_to_points_to_sinks(_UNUSED_ expression e, _UNUSED_ points_to_graph in)
Definition: expression.c:100

References add_arc_to_pt_map, atomic_points_to_cell_p(), CAR, CDR, CELL, cell_undefined, cell_undefined_p, clear_pt_map, copy_cell(), EXPRESSION, expression_null_p(), expression_to_points_to_sinks(), expression_to_points_to_sources(), expression_to_string(), expression_to_type(), FOREACH, free_type(), gen_length(), int, list_undefined, make_approximation_exact(), make_descriptor_none(), make_points_to(), nowhere_cell_p(), null_equal_condition_to_points_to(), out, pips_user_warning, pointer_type_p(), points_to_cell_source_projection(), points_to_cells_intersect_p(), points_to_context_statement_line_number(), and points_to_graph_bottom.

Referenced by relational_intrinsic_call_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ equal_must_vreference()

bool equal_must_vreference ( cell  c1,
cell  c2 
)
Parameters
c11
c22

Definition at line 1292 of file constant-path-utils.c.

1293 {
1294  int i = 0;
1295  bool changed = false;
1297  c1 = simple_cell_to_store_independent_cell(c1, &changed);
1298  c2 = simple_cell_to_store_independent_cell(c2, &changed);
1300  reference r1 = cell_any_reference(c1);
1301  reference r2 = cell_any_reference(c2);
1302  entity v1 = reference_variable(r1);
1303  entity v2 = reference_variable(r2);
1304  list sl1 = NIL, sl2 = NIL;
1305  // FI: memory leak? generation of a new string?
1306  extern const char* entity_minimal_user_name(entity);
1307 
1309  if (i==0) {
1310  sl1 = reference_indices(r1);
1311  sl2 = reference_indices(r2);
1312  if( (int)gen_length(sl1) == (int)gen_length(sl2) ) {
1313  for (;i==0 && !ENDP(sl1) && ! ENDP(sl2) ; POP(sl1), POP(sl2)){
1314  expression se1 = EXPRESSION(CAR(sl1));
1315  expression se2 = EXPRESSION(CAR(sl2));
1316  if( unbounded_expression_p(se1) ){
1317  i = 0;
1318  }
1319  else if (expression_constant_p(se1) && expression_constant_p(se2)){
1320  int i1 = expression_to_int(se1);
1321  int i2 = expression_to_int(se2);
1322  i = i2>i1? 1 : (i2<i1? -1 : 0);
1323  if (i==0){
1324  // FI: why not use expression_equal_p()? + memory leak
1325  string s1 = expression_to_string(se1);
1326  string s2 = expression_to_string(se2);
1327  i = strcmp(s1, s2);
1328  }
1329  }
1330  else {
1331  string s1 = expression_to_string(se1);
1332  string s2 = expression_to_string(se2);
1333  i = strcmp(s1, s2);
1334  }
1335  }
1336  }
1337  else
1338  i = 1;
1339  }
1340 
1341  return (i==0? true: false);
1342 }
cell simple_cell_to_store_independent_cell(cell, bool *)
bool expression_constant_p(expression)
HPFC module by Fabien COELHO.
Definition: expression.c:2453
const char * entity_minimal_user_name(entity e)
Do not preserve scope information.
Definition: naming.c:223
int expression_to_int(expression exp)
================================================================
Definition: expression.c:2205
bool unbounded_expression_p(expression e)
Definition: expression.c:4329

References CAR, cell_any_reference(), ENDP, entity_minimal_user_name(), EXPRESSION, expression_constant_p(), expression_to_int(), expression_to_string(), gen_length(), generic_effects_reset_all_methods(), NIL, POP, reference_indices, reference_variable, s1, set_methods_for_proper_simple_effects(), simple_cell_to_store_independent_cell(), and unbounded_expression_p().

Referenced by gen_may_constant_paths(), and gen_must_constant_paths().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ equalize_points_to_domains()

void equalize_points_to_domains ( points_to_graph  pt_t,
points_to_graph  pt_f 
)

Make sure that pt_t and pt_f have the same definition domain except if one of them is bottom.

Parameters
pt_tt_t
pt_ft_f

Definition at line 479 of file statement.c.

480 {
481  if(!points_to_graph_bottom(pt_t)) {
482  if(!points_to_graph_bottom(pt_f)) {
483  expand_points_to_domain(pt_t, pt_f);
484  expand_points_to_domain(pt_f, pt_t);
485  }
486  }
487 }
static void expand_points_to_domain(points_to_graph pt_t, points_to_graph pt_f)
expand the domain of pt_f according to the domain of pt_t
Definition: statement.c:450

References expand_points_to_domain(), and points_to_graph_bottom.

Referenced by test_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ error_reset_printed_points_to_list()

void error_reset_printed_points_to_list ( void  )

◆ exact_to_may_points_to_set()

set exact_to_may_points_to_set ( set  s)

Change the all the exact points-to relations to may relations.

Definition at line 2603 of file points_to_set.c.

2604 {
2605  SET_FOREACH ( points_to, pt, s ) {
2608  }
2609  return s;
2610 }

References approximation_exact_p, make_approximation_may(), points_to_approximation, and SET_FOREACH.

+ Here is the call graph for this function:

◆ expression_to_points_to()

pt_map expression_to_points_to ( expression  e,
pt_map  pt_in,
bool  side_effect_p 
)

Update pt_in and pt_out according to expression e.

Ignore side effects due to pointer arithmetic and assignment and function calls if side_effet_p is not set. This may be useful when conditions are evaluated twice, once for true and once for false.

Some idea, but points-to information should rather be used

list el = expression_to_proper_constant_path_effects(e);

Also, this would be computed before we know if it is useful because we need an expression and not a call to have a function to compute effects. And we do not know if we want an inter or an intraprocedural points-to analysis.

The alternative is too always compute points-to information interprocedurally, which makes sense as it is done for for memory effects and since points-to information is at a lower level than memory effects...

a cannot evaluate to null or undefined

FI: we may need a special case for stubs...

Parameters
pt_int_in
side_effect_pide_effect_p

Definition at line 115 of file expression.c.

116 {
117  pt_map pt_out = pt_in;
118  if(!points_to_graph_bottom(pt_in)) {
119  syntax s = expression_syntax(e);
120  tag t = syntax_tag(s);
121 
122  switch(t) {
123  case is_syntax_reference: {
125  list sl = reference_indices(r);
126  entity v = reference_variable(r);
128  // FI: call16.c shows that the C parser does not generate the
129  // right construct, a subscript, when a scalar pointer is indexed
130  if(!ENDP(sl)) {
131  if(pointer_type_p(vt)) {
132  // expression tmp = entity_to_expression(v);
133  // pt_out = dereferencing_to_points_to(tmp, pt_in);
134  // pt_out = expressions_to_points_to(sl, pt_out, side_effect_p);
135  // free_expression(tmp);
136  reference nr = make_reference(v, NIL);
137  subscripted_reference_to_points_to(nr, sl, pt_in);
138  }
139  else if(array_of_pointers_type_p(vt)) {
140  int td = type_depth(vt);
141  int sn = (int) gen_length(sl);
142  if(sn<=td) {
143  ; // Nothing to do: a standard array subscript list
144  }
145  else
146  pips_internal_error("Not implemented yet.\n");
147  }
148  }
149  pt_out = reference_to_points_to(r, pt_in, side_effect_p);
150  break;
151  }
152  case is_syntax_range: {
153  range r = syntax_range(s);
154  pt_out = range_to_points_to(r, pt_in, side_effect_p);
155  break;
156  }
157  case is_syntax_call: {
158  call c = syntax_call(s);
159  /* Some idea, but points-to information should rather be used
160  *
161  * list el = expression_to_proper_constant_path_effects(e);
162  *
163  * Also, this would be computed before we know if it is useful
164  * because we need an expression and not a call to have a function
165  * to compute effects. And we do not know if we want an inter or
166  * an intraprocedural points-to analysis.
167  *
168  * The alternative is too always compute points-to information
169  * interprocedurally, which makes sense as it is done for for
170  * memory effects and since points-to information is at a lower
171  * level than memory effects...
172  */
173  // Now, "el" is a useless parameter
174  list el = NIL;
175  pt_out = call_to_points_to(c, pt_in, el, side_effect_p);
176  gen_full_free_list(el);
177  break;
178  }
179  case is_syntax_cast: {
180  cast c = syntax_cast(s);
181  expression ce = cast_expression(c);
182  pt_out = expression_to_points_to(ce, pt_in, side_effect_p);
183  break;
184  }
187  if(sizeofexpression_type_p(soe))
188  ; // pt_in is not modified
189  else {
190  // expression ne = sizeofexpression_expression(soe);
191  // FI: we have a problem because sizeof(*p) does not imply that
192  // *p is evaluated...
193  // pt_out = expression_to_points_to(ne, pt_in);
194  ;
195  }
196  break;
197  }
198  case is_syntax_subscript: {
199  subscript sub = syntax_subscript(s);
200  expression a = subscript_array(sub);
201  list sel = subscript_indices(sub);
202  /* a cannot evaluate to null or undefined */
203  /* FI: we may need a special case for stubs... */
204  pt_out = dereferencing_to_points_to(a, pt_in);
205  pt_out = expression_to_points_to(a, pt_out, side_effect_p);
206  pt_out = expressions_to_points_to(sel, pt_out, side_effect_p);
207  break;
208  }
209  case is_syntax_application: {
211  pt_out = application_to_points_to(a, pt_out, side_effect_p);
212  break;
213  }
214  case is_syntax_va_arg: {
215  // The call to va_arg() does not create a points-to per se
216  list soel = syntax_va_arg(s);
217  sizeofexpression soe1 = SIZEOFEXPRESSION(CAR(soel));
218  //sizeofexpression soe2 = SIZEOFEXPRESSION(CAR(CDR(soel)));
220  // type t = sizeofexpression_type(soe2);
221  pt_out = expression_to_points_to(se, pt_out, side_effect_p);
222  break;
223  }
224  default:
225  ;
226  }
227  }
228  pips_assert("pt_out is consistent and defined",
230  && !points_to_graph_undefined_p(pt_out));
231  return pt_out;
232 }
pt_map application_to_points_to(application a, pt_map pt_in, bool side_effect_p)
Definition: expression.c:2490
void subscripted_reference_to_points_to(reference r, list sl, pt_map pt_in)
FI: what is this function supposed to do? Just update "pt_in" to make sure that "r" can be dereferenc...
Definition: expression.c:57
pt_map range_to_points_to(range r, pt_map pt_in, bool side_effect_p)
Definition: expression.c:284
pt_map reference_to_points_to(reference r, pt_map pt_in, bool side_effect_p)
The subscript expressions may impact the points-to information.
Definition: expression.c:262
#define SIZEOFEXPRESSION(x)
SIZEOFEXPRESSION.
Definition: ri.h:2364
#define sizeofexpression_expression(x)
Definition: ri.h:2409
#define syntax_cast(x)
Definition: ri.h:2739
#define syntax_application(x)
Definition: ri.h:2748
#define syntax_va_arg(x)
Definition: ri.h:2751
#define syntax_range(x)
Definition: ri.h:2733
#define cast_expression(x)
Definition: ri.h:747
#define syntax_sizeofexpression(x)
Definition: ri.h:2742
#define sizeofexpression_type_p(x)
Definition: ri.h:2404

References application_to_points_to(), array_of_pointers_type_p(), call_to_points_to(), CAR, cast_expression, dereferencing_to_points_to(), ENDP, entity_basic_concrete_type(), expression_syntax, expressions_to_points_to(), gen_full_free_list(), gen_length(), int, is_syntax_application, is_syntax_call, is_syntax_cast, is_syntax_range, is_syntax_reference, is_syntax_sizeofexpression, is_syntax_subscript, is_syntax_va_arg, make_reference(), NIL, pips_assert, pips_internal_error, pointer_type_p(), points_to_graph_bottom, points_to_graph_consistent_p(), points_to_graph_undefined_p, range_to_points_to(), reference_indices, reference_to_points_to(), reference_variable, SIZEOFEXPRESSION, sizeofexpression_expression, sizeofexpression_type_p, subscript_array, subscript_indices, subscripted_reference_to_points_to(), syntax_application, syntax_call, syntax_cast, syntax_range, syntax_reference, syntax_sizeofexpression, syntax_subscript, syntax_tag, syntax_va_arg, and type_depth().

Referenced by any_loop_to_points_to(), application_to_points_to(), call_to_points_to(), declaration_statement_to_points_to(), dereferencing_subscript_to_points_to(), expressions_to_points_to(), freed_pointer_to_points_to(), instruction_to_points_to(), intrinsic_call_to_points_to(), loop_to_points_to(), new_any_loop_to_points_to(), pointer_reference_dereferencing_to_points_to(), range_to_points_to(), test_to_points_to(), and whileloop_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ expression_to_points_to_cell_p()

bool expression_to_points_to_cell_p ( expression  e)

Can expression e be reduced to a reference, without requiring an evaluation?

For instance expression "p" can be reduced to reference "p".

Expression "p+i" cannot be reduced to a source reference, unless i==0.

Ad'hoc development for dereferencing_to_sinks.

Definition at line 406 of file dereferencing.c.

407 {
408  bool source_p = true;
409  syntax s = expression_syntax(e);
410  if(syntax_reference_p(s))
411  source_p = true;
412  else if(syntax_call_p(s)) {
413  call c = syntax_call(s);
414  entity f = call_function(c);
415  if(ENTITY_PLUS_C_P(f))
416  source_p = false;
417  }
418  return source_p;
419 }

References call_function, ENTITY_PLUS_C_P, expression_syntax, f(), syntax_call, syntax_call_p, and syntax_reference_p.

Referenced by dereferencing_to_sinks(), and expression_to_points_to_sources().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ expression_to_points_to_cells()

list expression_to_points_to_cells ( expression  e,
pt_map  in,
bool  eval_p,
bool  constant_p 
)

Return a possibly empty list of abstract locations whose addresses are possible value of expression "e" evaluated with points-to information "in".

Expression "e" is assumed to evaluate as a lhs, i.e. some memory address. If not, an empty list is returned.

Additional information could be passed in a second pass analysis, e.g. preconditions.

The generated sinks are all constant memory paths. A more advanced analysis could use storage-sentitive information, that would have to be updated with effects and transformers.

The list returned should be fully allocated with no sharing between it and the in points-to set. Hopefully...

reference + range + call + cast + sizeofexpression + subscript + application

This test does not make sense for pointer19.c. Since the sink_cell is saturated with indices, its type is double. e_c_t is a 3-D array of pointers to double, f_e_t is a pointer towards a 2-D array of pointers to double... What could be checked here?

This test does not make sence for pointer22.c either. We only need to check that the sink reference can be modified by dropping a few subscript to match the pointer type.

Parameters
inn
eval_pval_p
constant_ponstant_p

Definition at line 1650 of file sinks.c.

1654 {
1655  /* reference + range + call + cast + sizeofexpression + subscript +
1656  application*/
1657  list sinks = NIL;
1658  //bool to_be_freed;
1659  //type et = points_to_expression_to_type(e, &to_be_freed);
1660  //type cet = compute_basic_concrete_type(et);
1661  //if(to_be_freed) free_type(et);
1663  tag tt ;
1664  syntax s = expression_syntax(e);
1665 
1666  switch (tt = syntax_tag(s)) {
1667  case is_syntax_reference: {
1668  reference r = syntax_reference(s);
1669  sinks = reference_to_points_to_sinks(r, cet, in, eval_p, constant_p);
1670  break;
1671  }
1672  case is_syntax_range: {
1673  range r = syntax_range(s);
1674  sinks = range_to_points_to_sinks(r, in);
1675  break;
1676  }
1677  case is_syntax_call: {
1678  call c = syntax_call(s);
1679  sinks = call_to_points_to_sinks(c, cet, in, eval_p, constant_p);
1680  break;
1681  }
1682  case is_syntax_cast: {
1683  cast c = syntax_cast(s);
1684  sinks = cast_to_points_to_sinks(c, cet, in, eval_p);
1685  break;
1686  }
1688  // FI: no sink should be returned...
1689  //sinks = sizeofexpression_to_points_to_sinks(st, rhs, lhs, in);
1690  break;
1691  }
1692  case is_syntax_subscript: {
1693  subscript sub = syntax_subscript(s);
1694  sinks = subscript_to_points_to_sinks(sub, cet, in, eval_p);
1695  break;
1696  }
1697  case is_syntax_application: {
1699  sinks = application_to_points_to_sinks(a, cet, in);
1700  break;
1701  }
1702  case is_syntax_va_arg: {
1703  // FI: useful?
1704  //pips_internal_error("Not implemented yet\n");
1705  list soel = syntax_va_arg(s);
1706  //sizeofexpression soev = SIZEOFEXPRESSION(CAR(soel));
1707  sizeofexpression soet = SIZEOFEXPRESSION(CAR(CDR(soel)));
1708  sinks = sizeofexpression_to_points_to_sinks(soet, cet, in);
1709  break;
1710  }
1711  default:
1712  pips_internal_error("unknown expression tag %d\n", tt);
1713  break;
1714  }
1715 
1716  ifdebug(1) {
1717  type e_t = expression_to_type(e);
1718  type e_c_t = compute_basic_concrete_type(e_t);
1719  type f_e_t = e_c_t;
1720  bool free_f_e_t = false;
1721  if(eval_p) {
1722  if(pointer_type_p(e_c_t))
1723  f_e_t = type_to_pointed_type(e_c_t);
1724  else if(array_type_p(e_c_t)) {
1725  // free_f_e_t = true;
1726  // f_e_t = array_type_to_pointer_type(e_c_t);
1727  type et = array_type_to_element_type(e_c_t);
1728  if(pointer_type_p(et)) {
1729  f_e_t = type_to_pointed_type(et);
1730  }
1731  else {
1732  pips_internal_error("could be a struct - not implemented");
1733  }
1734  }
1735  }
1736  FOREACH(CELL, s, sinks) {
1737  if(!null_cell_p(s)) {
1739  /* This test does not make sense for pointer19.c. Since the
1740  sink_cell is saturated with indices, its type is
1741  double. e_c_t is a 3-D array of pointers to double, f_e_t is a
1742  pointer towards a 2-D array of pointers to double... What
1743  could be checked here? */
1744  /* This test does not make sence for pointer22.c either. We
1745  only need to check that the sink reference can be modified
1746  by dropping a few subscript to match the pointer type. */
1747  if(!array_pointer_string_type_equal_p(f_e_t, s_t)) {
1748  if(array_type_p(f_e_t)) {
1749  type et = array_type_to_element_type(e_c_t);
1750  if(pointer_type_p(et)) {
1751  type pet = type_to_pointed_type(et);
1752  if(!array_pointer_string_type_equal_p(pet, s_t)) {
1755  ; // pips_internal_error("Possible type discrepancy\n");
1756  }
1757  free_reference(sink_r);
1758  }
1759  else {
1760  ; // We are fine
1761  }
1762  }
1763  else {
1764  if(!array_pointer_string_type_equal_p(et, s_t)) {
1765  pips_internal_error("Type discrepancy\n");
1766  }
1767  else {
1768  ; // We are fine
1769  }
1770  }
1771  }
1772  else {
1773  if((char_star_type_p(e_t) || string_type_p(e_t))
1775  ;
1776  else
1777  pips_internal_error("Type discrepancy\n");
1778  }
1779  }
1780  }
1781  }
1782  free_type(e_t);
1783  if(free_f_e_t) free_type(f_e_t);
1784  }
1785 
1786  return sinks;
1787 }
bool array_pointer_string_type_equal_p(type, type)
Assume that a pointer to type x is equal to a 1-D array of x.
Definition: type.c:658
list reference_to_points_to_sinks(reference r, type et, pt_map in, bool eval_p, bool constant_p)
Returns a list of memory cells "sinks" possibly accessed by the evaluation of reference "r".
Definition: sinks.c:755
list range_to_points_to_sinks(range r, pt_map in)
Definition: sinks.c:1626
list subscript_to_points_to_sinks(subscript s, type et, pt_map in, bool eval_p)
Generate the corresponding points-to reference(s).
Definition: sinks.c:1451
list cast_to_points_to_sinks(cast ce, type et __attribute__((unused)), pt_map in, bool eval_p)
Handling of cast: play it safe! Either the cast is partly redundant and can be ignored or anywhere is...
Definition: sinks.c:1091
list sizeofexpression_to_points_to_sinks(sizeofexpression soe, type et __attribute__((unused)), pt_map in)
Definition: sinks.c:1139
list application_to_points_to_sinks(application a, type et __attribute__((unused)), pt_map in)
Definition: sinks.c:1388
list call_to_points_to_sinks(call c, type et, pt_map in, bool eval_p, bool constant_p)
Definition: sinks.c:112

References adapt_reference_to_type(), application_to_points_to_sinks(), array_pointer_string_type_equal_p(), array_type_p(), array_type_to_element_type(), call_to_points_to_sinks(), CAR, cast_to_points_to_sinks(), CDR, CELL, cell_any_reference(), char_star_constant_function_type_p(), char_star_type_p(), compute_basic_concrete_type(), constant_p(), copy_reference(), expression_syntax, expression_to_type(), FOREACH, free_reference(), free_type(), ifdebug, is_syntax_application, is_syntax_call, is_syntax_cast, is_syntax_range, is_syntax_reference, is_syntax_sizeofexpression, is_syntax_subscript, is_syntax_va_arg, NIL, null_cell_p(), pips_internal_error, pointer_type_p(), points_to_cell_to_concrete_type(), points_to_context_statement_line_number(), points_to_expression_to_concrete_type(), range_to_points_to_sinks(), reference_to_points_to_sinks(), SIZEOFEXPRESSION, sizeofexpression_to_points_to_sinks(), string_type_p(), subscript_to_points_to_sinks(), syntax_application, syntax_call, syntax_cast, syntax_range, syntax_reference, syntax_subscript, syntax_tag, syntax_va_arg, and type_to_pointed_type().

Referenced by compute_points_to_binded_set(), expression_to_points_to_sinks(), expression_to_points_to_sources(), ternary_intrinsic_call_to_points_to_sinks(), and unary_intrinsic_call_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ expression_to_points_to_sinks()

list expression_to_points_to_sinks ( expression  e,
pt_map  in 
)

The returned list contains cells used in "in".

They should be copied if they must be changed by side effects or "in" will become inconsistent.

This function computes the possible constant values of a pointer expression.

Parameters
inn

Definition at line 1795 of file sinks.c.

1796 {
1797  list sinks = expression_to_points_to_cells(e, in, true, true);
1798 
1799  return sinks;
1800 }
list expression_to_points_to_cells(expression e, pt_map in, bool eval_p, bool constant_p)
Return a possibly empty list of abstract locations whose addresses are possible value of expression "...
Definition: sinks.c:1650

References expression_to_points_to_cells().

Referenced by binary_intrinsic_call_to_points_to_sinks(), cast_to_points_to_sinks(), dereferencing_to_points_to(), dereferencing_to_sinks(), expression_to_points_to_sinks_with_offset(), global_source_to_sinks(), intrinsic_call_to_points_to_sinks(), pointer_reference_to_points_to_sinks(), points_to_translation_of_formal_parameters(), sizeofexpression_to_points_to_sinks(), and unary_intrinsic_call_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ expression_to_points_to_sinks_with_offset()

list expression_to_points_to_sinks_with_offset ( expression  a1,
expression  a2,
pt_map  in 
)
Parameters
a11
a22
inn

Definition at line 546 of file sinks.c.

547 {
548  list sinks = NIL;
549  type t1 = expression_to_type(a1);
550  type t2 = expression_to_type(a2);
551  // FI: the first two cases should be unified with a=a1 or a2
553  // expression_to_points_to_sinks() returns pointers to arcs in the
554  // points-to graph. No side effect is then possible.
555  list e_sinks = expression_to_points_to_sinks(a1, in);
556  sinks = gen_full_copy_list(e_sinks);
557  gen_free_list(e_sinks);
559  offset_points_to_cells(sinks, a2, t);
560  }
561  else if(pointer_type_p(t2) && (scalar_integer_type_p(t1) || unbounded_expression_p(a1))) {
562  list e_sinks = expression_to_points_to_sinks(a2, in);
563  sinks = gen_full_copy_list(e_sinks);
564  gen_free_list(e_sinks);
566  offset_points_to_cells(sinks, a1, t);
567  }
568  else if(array_type_p(t1) && scalar_integer_type_p(t2)) {
569  list e_sinks = expression_to_points_to_sources(a1, in);
570  sinks = gen_full_copy_list(e_sinks);
571  gen_free_list(e_sinks);
573  offset_points_to_cells(sinks, a2, t);
574  }
575  else if(array_type_p(t2) && scalar_integer_type_p(t1)) {
576  list e_sinks = expression_to_points_to_sources(a2, in);
577  sinks = gen_full_copy_list(e_sinks);
578  gen_free_list(e_sinks);
580  offset_points_to_cells(sinks, a1, t);
581  }
582  else {
583  // These types do not lead to sources or sinks
584  //pips_internal_error("Not implemented for \"%s\" and \"%s\" and %p\n",
585  // expression_to_string(a1), expression_to_string(a2), in);
586  ; // ignore
587  }
588  free_type(t1);
589  free_type(t2);
590  return sinks;
591 }
type points_to_expression_to_pointed_type(expression)
Return a new allocated type "t" of the address pointed by expression "e", if expression "e" denotes a...
Definition: type.c:631
void offset_points_to_cells(list sinks, expression delta, type t)
Each cell in sinks is replaced by a cell located "delta" elements further up in the memory.
Definition: expression.c:1020
bool scalar_integer_type_p(type)
Definition: type.c:3276

References array_type_p(), expression_to_points_to_sinks(), expression_to_points_to_sources(), expression_to_type(), free_type(), gen_free_list(), gen_full_copy_list(), NIL, offset_points_to_cells(), pointer_type_p(), points_to_expression_to_pointed_type(), scalar_integer_type_p(), and unbounded_expression_p().

Referenced by binary_intrinsic_call_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ expression_to_points_to_sources()

list expression_to_points_to_sources ( expression  e,
pt_map  in 
)

expression_to_points_to_sources() does not always work, especially with pointer arithmetic or subscripting because p[3], for instance, is not recognized as a valid source: it is not a constant path

Scalar pointers are expected but [0] subscript may have been added

Trouble for fread04... An array element, _line_3[0], is reduced to an array, _line_3, and you want to capture its address

A useless [0] may have been added, but it is supposed to be taken care of above... by callers of this function.

Parameters
inn

Definition at line 1805 of file sinks.c.

1806 {
1807  list sinks = expression_to_points_to_cells(e, in, false, true);
1808 
1809  /* Scalar pointers are expected but [0] subscript may have been added */
1811  /* Trouble for fread04... An array element, _line_3[0], is reduced
1812  to an array, _line_3, and you want to capture its address */
1813  // sinks = reduce_cells_to_pointer_type(sinks);
1814  ;
1815  }
1816 
1817  ifdebug(1) {
1818  bool to_be_freed;
1819  type tmp_t = points_to_expression_to_type(e, &to_be_freed);
1820  type et = compute_basic_concrete_type(tmp_t);
1821  FOREACH(CELL, c, sinks) {
1822  if(!null_cell_p(c)) {
1823  bool to_be_freed2;
1824  type ct = points_to_cell_to_type(c, &to_be_freed2);
1826  // Type compatibility check. To be improved with integer used
1827  // as pointer values...
1828  if(!array_pointer_type_equal_p(et, cct)
1829  // Dereferencement via a subscript
1830  && !array_element_type_p(et, cct)
1831  // Constant strings such as "hello"
1832  && !((char_star_type_p(et) || string_type_p(et))
1834  // Dereferencement forced by the syntax of the expression
1835  && !(pointer_type_p(et)
1837  /* A useless [0] may have been added, but it is supposed to
1838  be taken care of above... by callers of this function. */
1839  ifdebug(1) {
1840  pips_debug(1, "Type mismatch for expression: "); print_expression(e);
1841  fprintf(stderr, " with type: "); print_type(et);
1842  fprintf(stderr, "\nand cell: "); print_points_to_cell(c);
1843  fprintf(stderr, " with type: "); print_type(cct);
1844  fprintf(stderr, "\n");
1845 
1846  }
1847  print_expression(e);
1848  pips_internal_error("Type error for an expression\n.");
1849  }
1850  if(to_be_freed2) free_type(ct);
1851  }
1852  }
1853  if(to_be_freed) free_type(tmp_t);
1854  }
1855 
1856  return sinks;
1857 }
void print_expression(expression e)
no file descriptor is passed to make is easier to use in a debugging stage.
Definition: expression.c:58
bool array_element_type_p(type, type)
is "et" the type of an element of an array of type "at"?
Definition: type.c:684

References array_element_type_p(), array_pointer_type_equal_p(), CELL, char_star_constant_function_type_p(), char_star_type_p(), compute_basic_concrete_type(), expression_to_points_to_cell_p(), expression_to_points_to_cells(), FOREACH, fprintf(), free_type(), ifdebug, null_cell_p(), pips_debug, pips_internal_error, pointer_type_p(), points_to_cell_to_type(), points_to_expression_to_type(), print_expression(), print_points_to_cell, print_type(), string_type_p(), and type_to_pointed_type().

Referenced by binary_intrinsic_call_to_points_to_sinks(), cast_to_points_to_sinks(), dereferencing_subscript_to_points_to(), dereferencing_to_sinks(), expression_to_points_to_sinks_with_offset(), pointer_reference_to_points_to_sinks(), points_to_translation_of_formal_parameters(), subscript_to_points_to_sinks(), and user_call_to_points_to_intraprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ expressions_to_points_to()

pt_map expressions_to_points_to ( list  el,
pt_map  pt_in,
bool  side_effect_p 
)

Compute the points-to information pt_out that results from the evaluation of a possibly empty list of expression.

A new data structure is allocated.

Ignore side-effects unless side_effect_p is set to true.

The result is correct only if you are sure that all expressions in "el" are always evaluated.

Parameters
ell
pt_int_in
side_effect_pide_effect_p

Definition at line 243 of file expression.c.

244 {
245  pt_map pt_out = pt_in;
246  FOREACH(EXPRESSION, e, el) {
247  if(points_to_graph_bottom(pt_out))
248  break;
249  pt_out = expression_to_points_to(e, pt_out, side_effect_p);
250  }
251 
252  return pt_out;
253 }

References EXPRESSION, expression_to_points_to(), FOREACH, and points_to_graph_bottom.

Referenced by application_to_points_to(), call_to_points_to(), dereferencing_subscript_to_points_to(), dereferencing_to_points_to(), expression_to_points_to(), reference_condition_to_points_to(), and reference_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ extended_source_to_sinks()

list extended_source_to_sinks ( cell  sc,
pt_map  in 
)

Do not create sharing between elements of "in" and elements of "sinks".

Parameters
scc
inn

Definition at line 2359 of file points_to_set.c.

2360 {
2361  list sinks = NIL;
2362  bool null_dereferencing_p
2363  = get_bool_property("POINTS_TO_NULL_POINTER_DEREFERENCING");
2364  bool nowhere_dereferencing_p
2365  = get_bool_property("POINTS_TO_UNINITIALIZED_POINTER_DEREFERENCING");
2366  if( (null_dereferencing_p || !null_cell_p(sc))
2367  && (nowhere_dereferencing_p || !nowhere_cell_p(sc))) {
2368  /* Do not create sharing between elements of "in" and
2369  elements of "sinks". */
2370  cell nsc = copy_cell(sc);
2371  list starpointed = source_to_sinks(nsc, in, true);
2372  free_cell(nsc);
2373 
2374  if(ENDP(starpointed)) {
2375  reference sr = cell_any_reference(sc);
2376  entity sv = reference_variable(sr);
2377  string words_to_string(list);
2378  pips_internal_error("No pointed location for variable \"%s\" and reference \"%s\"\n",
2379  entity_user_name(sv),
2380  reference_to_string(sr));
2381  }
2382  sinks = gen_nconc(sinks, starpointed);
2383  }
2384  // FI: I'd like a few else clauses to remove arcs that
2385  // cannot exist if the code is correct. E.g. p->i, p->NULL
2386  // if card(cl)==1, remove arc(c->sc)?
2387  return sinks;
2388 }

References cell_any_reference(), copy_cell(), ENDP, entity_user_name(), free_cell(), gen_nconc(), get_bool_property(), NIL, nowhere_cell_p(), null_cell_p(), pips_internal_error, reference_to_string(), reference_variable, source_to_sinks(), and words_to_string().

Referenced by extended_sources_to_sinks(), and pointer_source_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ extended_sources_to_sinks()

list extended_sources_to_sinks ( list  pointed,
pt_map  in 
)

Same as extended_source_to_sinks, but for a set of cells, "pointed".

Dereference the pointer(s) to find the sinks, memory(memory(p))

Parameters
pointedointed
inn

Definition at line 2391 of file points_to_set.c.

2392 {
2393  list sinks = NIL;
2394  /* Dereference the pointer(s) to find the sinks, memory(memory(p)) */
2395  FOREACH(CELL, sc, pointed) {
2396  list starpointed = extended_source_to_sinks(sc, in);
2397  sinks = gen_nconc(sinks, starpointed);
2398  }
2399  return sinks;
2400 }
list extended_source_to_sinks(cell sc, pt_map in)

References CELL, extended_source_to_sinks(), FOREACH, gen_nconc(), and NIL.

+ Here is the call graph for this function:

◆ fast_interprocedural_points_to_analysis()

bool fast_interprocedural_points_to_analysis ( char *  module_name)
Parameters
module_nameodule_name

Definition at line 574 of file passes.c.

575 {
579 }
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
static bool fast_interprocedural_points_to_p
Definition: passes.c:549
static bool generic_points_to_analysis(char *module_name)
Pass INTRAPROCEDURAL_POINTS_TO_ANALYSIS.
Definition: passes.c:345
static bool interprocedural_points_to_p
Definition: passes.c:548

References fast_interprocedural_points_to_p, generic_points_to_analysis(), interprocedural_points_to_p, and module_name().

+ Here is the call graph for this function:

◆ fast_interprocedural_points_to_analysis_p()

bool fast_interprocedural_points_to_analysis_p ( void  )

Definition at line 555 of file passes.c.

556 {
558 }

References fast_interprocedural_points_to_p.

Referenced by user_call_to_points_to(), and user_call_to_points_to_sinks().

+ Here is the caller graph for this function:

◆ fi_points_to_storage()

void fi_points_to_storage ( pt_map  ptm,
statement  s,
bool  store 
)
Parameters
ptmtm
storetore

Definition at line 97 of file passes.c.

97  {
98  list pt_list = NIL, tmp_l;
100  set pts_to_set = points_to_graph_set(ptm);
101  bool bottom_p = points_to_graph_bottom(ptm);
102 
103  if ( !set_empty_p(pts_to_set) && store == true ) {
104 
105  pt_list = set_to_sorted_list(pts_to_set,
106  (int(*)(const void*, const void*))
108  tmp_l = gen_full_copy_list(pt_list);
109  new_pt_list = make_points_to_list(bottom_p, tmp_l);
110  points_to_list_consistent_p(new_pt_list);
111  store_or_update_pt_to_list(s, new_pt_list);
112  }
113  else if(set_empty_p(pts_to_set)){
114  tmp_l = gen_full_copy_list(pt_list);
115  new_pt_list = make_points_to_list(bottom_p, tmp_l);
116  store_or_update_pt_to_list(s, new_pt_list);
117  }
118  gen_free_list(pt_list);
119 }
points_to_list make_points_to_list(bool a1, list a2)
bool points_to_list_consistent_p(points_to_list p)
void store_or_update_pt_to_list(statement, points_to_list)
int points_to_compare_cells(const void *, const void *)
Comparison of two points-to arcs based on their source and sink nodes.
Definition: prettyprint.c:295
list set_to_sorted_list(const set, gen_cmp_func_t)
Definition: set.c:447
#define points_to_list_undefined

References gen_free_list(), gen_full_copy_list(), make_points_to_list(), NIL, points_to_compare_cells(), points_to_graph_bottom, points_to_graph_set, points_to_list_consistent_p(), points_to_list_undefined, set_empty_p(), set_to_sorted_list(), and store_or_update_pt_to_list().

Referenced by statement_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ filter_formal_context_according_to_actual_context()

set filter_formal_context_according_to_actual_context ( list  fpcl,
set  pt_in,
set  pt_binded,
set  binding 
)

Filter "pt_in" according to "pt_binded".

For instance, a formal parameter can point to NULL in "pt_in" only if it also points to NULL in "pt_binded". In the same way, a formal parameter can point to a points-to stub in "pt_in" only if it points to a non-NULL target in "pt_binded". Also, a formal parameter cannot points exactly to UNDEFINED in "pt_binded" as it would be useless (not clear if we can remove such an arc when it is a may arc...). Finally, each formal parameter must still point to something.

The context of the caller may be insufficiently developped because its does not use explictly a pointer that is a formal parameter for it. For instance:

foo(int ***p) {bar(int ***p);}

The formal context of "foo()" must be developped when the formal context of "bar()" is imported. For instance, *p, **p and ***p may be accessed in "bar()", generating points-to stub in "bar". Similar stubs must be generated here for "foo()" before the translation can be performed.

This is also true for global variables. pt_in may contain arcs that should exist in pt_binded, and hence pt_caller. It may also contain arcs that deny the existence of some arcs in pt_caller.

Copy arcs "pt" from "pt_in" into the "filtered" set if they are compatible with "pt_binded". The set "pt_in" is reduced.

Do we have the same arc in pt_binded?

We have to deal recursively with stubs of the formal context and first with the global variables...although they, or their stubs, do not require any translation? Why is the points-to information about q lost in the translation of the call site to call03 in main (PointersWithEffects/call03.c)

FI: I do not understand why I have to do this for EffectsWithPointsTo/pointer_modif04.c. Because the arc "pt" in "pt_in" is more precise than the information available in "pt_caller". For instance, "pt_in" may contain "stderr->_stderr_0[0], Exact", while "pt_caller" may contain "stderr->_stderr_0[0], May", "stderr->NULL, May". Basically, we have not thought about the kill set generated for the global variables.

Useless when called from effects... In fact, it should never be called from effects...

FI: we do not know what we really do here... An arc is not taken into account, but it might be taken into account recursively below.

Compute the binding relation for sinks of the formal arguments and global variables

We have to handle constant strings such as "Hello!" and not to forget functional parameters.

If "fc" is not a pointer, look for pointers in "fc"

Now, we have to call about the same function recursively on the list of formal sinks

Some arcs have been removed, so other arcs may be promoted from "may" to "exact".

Parameters
fpclpcl
pt_int_in
pt_bindedt_binded
bindinginding

Definition at line 582 of file interprocedural.c.

586 {
587  bool ok_p = true;
588  set filtered = new_simple_pt_map();
589  // list gvcl = NIL; // global variable cell list
590 
591  /* Copy arcs "pt" from "pt_in" into the "filtered" set if they are
592  compatible with "pt_binded". The set "pt_in" is reduced. */
593  SET_FOREACH(points_to, pt, pt_in) {
594  cell source = points_to_source(pt);
595  if(related_points_to_cell_in_list_p(source, fpcl)) {
596  cell sink = points_to_sink(pt);
597  if(null_cell_p(sink)) {
598  /* Do we have the same arc in pt_binded? */
599  if(arc_in_points_to_set_p(pt, pt_binded)) {
600  points_to npt = copy_points_to(pt);
601  add_arc_to_simple_pt_map(npt, filtered);
602  }
603  else {
604  ; // do not copy this arc in filtered set
605  }
606  }
607  else {
608  if(cell_points_to_non_null_sink_in_set_p(source, pt_binded)) {
609  points_to npt = copy_points_to(pt);
610  add_arc_to_simple_pt_map(npt, filtered);
611  }
612  else {
613  ; // do not copy this arc in filtered set
614  }
615  }
616  }
617  else {
618  /* We have to deal recursively with stubs of the formal context
619  and first with the global variables...although they, or their
620  stubs, do not require any translation? Why is the points-to
621  information about q lost in the translation of the call site
622  to call03 in main (PointersWithEffects/call03.c) */
623  reference r = cell_any_reference(source);
624  entity v = reference_variable(r);
625  if(!arc_in_points_to_set_p(pt, pt_binded)) {
626  // FI: necessary for Pointers/global10
628  //gvcl = CONS(CELL, source, gvcl);
629  points_to npt = copy_points_to(pt);
630  add_arc_to_simple_pt_map(npt, filtered);
631  /* FI: I do not understand why I have to do this for
632  EffectsWithPointsTo/pointer_modif04.c. Because the arc "pt"
633  in "pt_in" is more precise than the information available
634  in "pt_caller". For instance, "pt_in" may contain
635  "stderr->_stderr_0[0], Exact", while "pt_caller" may
636  contain "stderr->_stderr_0[0], May", "stderr->NULL,
637  May". Basically, we have not thought about the kill set
638  generated for the global variables. */
640  /* Useless when called from effects... In fact, it should
641  never be called from effects... */
642  //add_arc_to_points_to_context(npt);
644  }
645  else {
646  // pips_internal_error("This function should not reach this point"
647  // " when called from effects, simple or generic.");
648  // update_points_to_context_with_arc(npt);
649  ; // Do nothing
650  }
651  }
652  else {
653  /* FI: we do not know what we really do here... An arc is not
654  taken into account, but it might be taken into account
655  recursively below. */
656  ;
657  }
658  }
659  }
660  }
661 
662  /* Compute the binding relation for sinks of the formal
663  arguments and global variables */
664  //list fpgvcl = gen_nconc(fpcl, gvcl);
665  list fcl = NIL;
666  points_to_graph filtered_g = make_points_to_graph(false, filtered);
667  points_to_graph pt_binded_g = make_points_to_graph(false, pt_binded);
668  FOREACH(CELL, c, fpcl) {
669  //FOREACH(CELL, c, fpgvcl) {
670  list fl = points_to_source_to_any_sinks(c, filtered_g, false); // formal list
671  list al = points_to_source_to_any_sinks(c, pt_binded_g, false); // actual list
672  int nfl = (int) gen_length(fl);
673  int nal = (int) gen_length(al);
675 
676  // FI: que fait-on avec nfl==0, comme dans
677  // Pointers/StrictTyping.sub/struct08.c ou nfl vaut 0 parce que le
678  // parametre effectif est undefined?
679 
680  if(nfl==1 && nal==1)
681  approx = make_approximation_exact();
682  else
683  approx = make_approximation_may();
684  FOREACH(CELL, fc, fl) {
685  if(!null_cell_p(fc)) {
686  FOREACH(CELL, ac, al) {
687  if(!null_cell_p(ac) && !nowhere_cell_p(ac)) {
691  /* We have to handle constant strings such as "Hello!"
692  and not to forget functional parameters. */
693  if(type_functional_p(ac_t)) {
694  reference ar = cell_any_reference(ac);
695  entity a = reference_variable(ar);
696  if(constant_string_entity_p(a)) {
697  ac_t = functional_result(type_functional(iac_t));
698  }
699  }
700  // FI: which type equality should be chosen ?
701  // if(!type_structurally_equal_p(fc_t, ac_t)
702  if(!array_pointer_string_type_equal_p(fc_t, ac_t)
703  && !overloaded_type_p(ac_t)) {
704  if(array_type_p(ac_t)) {
707  if(!type_structurally_equal_p(fc_t, ac_nt) && !overloaded_type_p(ac_nt)) {
708  // Pointers/pointer14.c
709  // FI: I am not sure it is the best translation
710  // It might be better to remove some zero subscripts from fc
713  if(!type_structurally_equal_p(fc_t, ac_nnt) && !overloaded_type_p(ac_nnt))
714  pips_internal_error("translation failure for an array.\n");
715  }
716  }
717  else {
718  reference fr = cell_any_reference(fc);
720  ;
721  else {
723  reference ar = cell_any_reference(ac);
724  semantics_user_warning("Type \"%s\" for formal reference \"%s\" is incompatible with type \"%s\" for actual reference \"%s\".\n",
728  reference_to_string(ar));
729  if(get_bool_property("POINTS_TO_STRICT_POINTER_TYPES")) {
731  ("Translation failure for actual parameter \"%s\" at line %d.\n"
732  "Maybe property POINTS_TO_STRICT_POINTER_TYPES should be reset.\n",
735  // pips_internal_error("translation failure.\n");
736  }
737  else {
739  ("Translation failure for actual parameter \"%s\" at line %d.\n",
742  }
743  }
744  }
745  }
747  copy_cell(ac),
748  copy_approximation(approx),
751  }
752  }
753  /* If "fc" is not a pointer, look for pointers in "fc" */
755  fcl = gen_nconc(fcl, pcl);
756  //fcl = CONS(CELL, fc, fcl);
757  }
758  }
759  free_approximation(approx);
760  }
761 
762  ifdebug(8) {
763  pips_debug(8, "First filtered IN set for callee at call site:\n");
764  print_points_to_set("", filtered);
765  pips_debug(8, "First translation mapping for call site:\n");
766  print_points_to_set("", binding);
767  }
768 
769  pips_assert("The points-to translation mapping is well typed",
771 
772  /* Now, we have to call about the same function recursively on the
773  list of formal sinks */
774  if(!ENDP(fcl)) {
776  (fcl, pt_in, pt_binded, binding, filtered);
777  gen_free_list(fcl);
778  }
779 
780  if(ok_p) {
781  /* Some arcs have been removed, so other arcs may be promoted from
782  "may" to "exact". */
784  }
785  else {
786  set_free(filtered);
787  filtered = set_undefined;
788  }
789 
790  ifdebug(8) {
791  pips_debug(8, "Final filtered IN set for callee at call site:\n");
792  print_points_to_set("", filtered);
793  pips_debug(8, "Final mapping for call site:\n");
794  print_points_to_set("", binding);
795  }
796 
797  return filtered;
798 }
bool constant_string_entity_p(entity e)
Definition: constant.c:356
bool related_points_to_cell_in_list_p(cell, list)
Two cells are related if they are based on the same entity.
Definition: points_to.c:149
void points_to_cell_complete_with_zero_subscripts(cell)
Definition: effects.c:1626
bool cell_points_to_non_null_sink_in_set_p(cell, set)
A set of functions called cell_points_to_xxxx(cell s, set pts) where set pts is a points-to relation ...
Definition: points_to.c:822
void points_to_cell_add_zero_subscript(cell)
Definition: effects.c:1620
void update_points_to_context_with_arc(points_to pt)
Same as , but be careful about the arc before adding it to the points-to context.
Definition: passes.c:285
list points_to_cell_to_useful_pointer_cells(cell c, set pts)
Definition: expression.c:1905
static type constant_string_type_to_string_type(type t)
We have to handle constant strings such as "Hello!" and not to forget functional parameters or other ...
bool points_to_translation_mapping_is_typed_p(set translation)
bool recursive_filter_formal_context_according_to_actual_context(list fcl, set pt_in, set pt_binded, set binding, set filtered)
This function looks for successors of elements of list "fcl" both in points-to relations "pt_in" and ...
list points_to_source_to_any_sinks(cell, pt_map, bool)
Retrieve all possible sinks of the source.
bool arc_in_points_to_set_p(points_to, set)
Check if points-to arc "spt" belongs to points-to set "pts".
string type_to_full_string_definition(type)
type.c
Definition: type.c:45
bool global_variable_p(entity)
Is v a global variable such as "int i;".
Definition: variable.c:1510
#define semantics_user_warning

References adapt_reference_to_type(), add_arc_to_simple_pt_map, add_subscript_dependent_arc_to_simple_pt_map(), approximation_undefined, arc_in_points_to_set_p(), array_pointer_string_type_equal_p(), array_type_p(), CELL, cell_any_reference(), cell_points_to_non_null_sink_in_set_p(), constant_string_entity_p(), constant_string_type_to_string_type(), copy_approximation(), copy_cell(), copy_points_to(), ENDP, FOREACH, free_approximation(), functional_result, gen_free_list(), gen_length(), gen_nconc(), get_bool_property(), global_variable_p(), ifdebug, int, make_approximation_exact(), make_approximation_may(), make_descriptor_none(), make_points_to(), make_points_to_graph(), new_simple_pt_map, NIL, nowhere_cell_p(), null_cell_p(), overloaded_type_p(), pips_assert, pips_debug, pips_internal_error, pips_user_error, points_to_cell_add_zero_subscript(), points_to_cell_complete_with_zero_subscripts(), points_to_cell_to_concrete_type(), points_to_cell_to_useful_pointer_cells(), points_to_context_statement_line_number(), points_to_reference_to_concrete_type(), points_to_sink, points_to_source, points_to_source_to_any_sinks(), points_to_translation_mapping_is_typed_p(), print_points_to_set(), recursive_filter_formal_context_according_to_actual_context(), reference_to_string(), reference_variable, related_points_to_cell_in_list_p(), semantics_user_warning, SET_FOREACH, set_free(), set_undefined, statement_points_to_context_defined_p(), static_global_variable_p(), type_functional, type_functional_p, type_structurally_equal_p(), type_to_full_string_definition(), update_points_to_context_with_arc(), and upgrade_approximations_in_points_to_set().

+ Here is the call graph for this function:

◆ filter_formal_out_context_according_to_formal_in_context()

set filter_formal_out_context_according_to_formal_in_context ( set  out,
set  in,
list  wpl,
entity  f 
)

If an address has not been written, i.e.

it is not in list "wpl", then the points-to information is the intersection of the in and out information.

The set "in" may be modified by side effect. A new set, "filtered_out" is computed. By definition, they are equivalent for the addresses that are not in list "wpl".

The arcs are shared by the different sets. But I may allocate new ones: yet another potential memory leak...

First, filter out according to in

The source of the arc may not have been modified but the sink probably has been freed: the arc must be preserved

The source of the arc has been modified: the arc must be preserved

the arc defining the return value must be preserved: no!

Is this points-to arc also in set "in"? With or without the same approximation?

Second, filter set "in" with respect to new set "filtered_out".

Is this points-to arc also in set "in"? With or without the same approximation?

Parameters
outut
inn
wplpl

Definition at line 1263 of file interprocedural.c.

1265 {
1266  set out_filtered = new_simple_pt_map();
1267 
1268  /* First, filter out according to in */
1269  SET_FOREACH(points_to, pt, out) {
1270  cell source = points_to_source(pt);
1273  cell sink = points_to_sink(pt);
1274  if(nowhere_cell_p(sink)) {
1275  /* The source of the arc may not have been modified but the sink
1276  probably has been freed: the arc must be preserved */
1277  add_arc_to_simple_pt_map(pt, out_filtered);
1278  }
1279  else if(points_to_cell_in_list_p(source, wpl)) {
1280  /* The source of the arc has been modified: the arc must be preserved */
1281  add_arc_to_simple_pt_map(pt, out_filtered);
1282  }
1283  else if(se==rv) {
1284  /* the arc defining the return value must be preserved: no! */
1285  add_arc_to_simple_pt_map(pt, out_filtered);
1286  }
1287  else {
1288  /* Is this points-to arc also in set "in"? With or without the
1289  same approximation? */
1291  if(similar_arc_in_points_to_set_p(pt, in, &a)) {
1293  if(approximation_exact_p(oa)) {
1294  add_arc_to_simple_pt_map(pt, out_filtered);
1295  }
1296  else if(approximation_exact_p(a)) {
1297  cell nsource = copy_cell(source);
1298  cell nsink = copy_cell(points_to_sink(pt));
1300  points_to npt = make_points_to(nsource, nsink, na,
1302  add_arc_to_simple_pt_map(npt, out_filtered);
1303  }
1304  else {
1305  add_arc_to_simple_pt_map(pt, out_filtered);
1306  }
1307  }
1308  else {
1309  ; // This arc cannot be preserved in "out_filtered"
1310  }
1311  }
1312  }
1313 
1314  /* Second, filter set "in" with respect to new set "filtered_out". */
1315  list to_be_removed = NIL;
1316  list to_be_added = NIL; // FI: why do you want to add stuff?
1317  SET_FOREACH(points_to, ipt, in) {
1318  /*
1319  hash_table _hash_ = set_private_get_hash_table(in);
1320  void * _point_ = NULL;
1321  for (points_to ipt;
1322  (_point_ = hash_table_scan(_hash_, _point_, (void **) &ipt, NULL));) {
1323  */
1324  cell source = points_to_source(ipt);
1325  if(points_to_cell_in_list_p(source, wpl))
1326  ; // do nothing
1327  else {
1328  /* Is this points-to arc also in set "in"? With or without the
1329  same approximation? */
1331  if(similar_arc_in_points_to_set_p(ipt, out, &a)) {
1333  if(approximation_exact_p(oa)) {
1334  ; // Do nothing
1335  }
1336  else if(approximation_exact_p(a)) {
1337  cell nsource = copy_cell(source);
1338  cell nsink = copy_cell(points_to_sink(ipt));
1340  points_to npt = make_points_to(nsource, nsink, na,
1342  //add_arc_to_simple_pt_map(npt, in);
1343  to_be_added = CONS(POINTS_TO, npt, to_be_added);
1344  to_be_removed = CONS(POINTS_TO, ipt, to_be_removed);
1345  }
1346  else {
1347  ; // do nothing
1348  }
1349  }
1350  else {
1351  to_be_removed = CONS(POINTS_TO, ipt, to_be_removed);
1352  }
1353  }
1354  }
1355 
1356  FOREACH(POINTS_TO, pt, to_be_removed)
1358 
1359  FOREACH(POINTS_TO, pt, to_be_added)
1360  add_arc_to_simple_pt_map(pt, in);
1361 
1362  return out_filtered;
1363 }
#define remove_arc_from_simple_pt_map(a, s)
bool similar_arc_in_points_to_set_p(points_to, set, approximation *)
See if an arc like "spt" exists in set "in", regardless of its approximation.
Definition: points_to.c:929
entity any_function_to_return_value(entity m)
Same as function_to_return_value(), but returns value_undefined when m is a C void function or a Fort...
Definition: module.c:516

References add_arc_to_simple_pt_map, any_function_to_return_value(), approximation_exact_p, approximation_undefined, cell_any_reference(), CONS, copy_approximation(), copy_cell(), f(), FOREACH, make_descriptor_none(), make_points_to(), new_simple_pt_map, NIL, nowhere_cell_p(), out, POINTS_TO, points_to_approximation, points_to_cell_in_list_p(), points_to_sink, points_to_source, reference_variable, remove_arc_from_simple_pt_map, SET_FOREACH, and similar_arc_in_points_to_set_p().

Referenced by user_call_to_points_to_interprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ find_arc_in_points_to_set()

points_to find_arc_in_points_to_set ( cell  source,
cell  sink,
pt_map  ptm 
)

The approximation is not taken into account.

It might be faster to look up the different points-to arcs that can be made with source, sink and any approximation.

Parameters
sourceource
sinkink
ptmtm

Definition at line 695 of file points_to_set.c.

696 {
697  // FI: no longer compatible with definition of pt_map as set
698  set s = points_to_graph_set(ptm);
700  SET_FOREACH(points_to, pt, s) {
701  if(cell_equal_p(points_to_source(pt), source)
702  && cell_equal_p(points_to_sink(pt), sink) ) {
703  fpt = pt;
704  break;
705  }
706  }
707  return fpt;
708 }
bool cell_equal_p(cell, cell)
CELLS.
Definition: effects.c:1226

References cell_equal_p(), points_to_graph_set, points_to_sink, points_to_source, points_to_undefined, and SET_FOREACH.

Referenced by offset_cells().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ find_kth_points_to_node_in_points_to_path()

cell find_kth_points_to_node_in_points_to_path ( list  p,
type  t,
int  k 
)

Find the "k"-th node of type "t" in list "p".

Beware of cycles? No reason since "p" is bounded... The problem must be addressed when "p" is built.

An issue with "t": the nodes are references and they carry multiple types, one for each number of subscripts or fields they have. So for instance, s1 and s1.next denote the same location.

Definition at line 960 of file points_to_set.c.

961 {
962  int count = 0;
963  cell kc = cell_undefined;
964  FOREACH(CELL, c, p) {
965  // bool to_be_freed;
966  // type ct = cell_to_type(c, &to_be_freed);
967  // if(type_equal_p(t, ct)) {
969  count++;
970  if(count==k) {
971  kc = type_compatible_super_cell(t,c);
972  break;
973  }
974  }
975  }
976  ifdebug(8) {
977  pips_debug(8, "Could not find %d nodes of type \"%s\" in path \"", k,
980  fprintf(stderr, "\"\n");
981  }
982  return kc;
983 }
static int count
Definition: SDG.c:519
cell type_compatible_super_cell(type t, cell c)
See if a super-cell of "c" exists witf type "t".
void print_points_to_path(list p)
For debugging.
bool type_compatible_with_points_to_cell_p(type t, cell c)
A type "t" is compatible with a cell "c" if any of the enclosing cell "c'" of "c",...

References CELL, cell_undefined, count, FOREACH, fprintf(), ifdebug, pips_debug, print_points_to_path(), type_compatible_super_cell(), type_compatible_with_points_to_cell_p(), and type_to_full_string_definition().

Referenced by points_to_path_to_k_limited_points_to_path().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ flow_sensitive_malloc_to_points_to_sinks()

list flow_sensitive_malloc_to_points_to_sinks ( expression  e)

The type of me may en array type because of

int * p = (int *) malloc(nb*sizeof(int))

or int (*p)[nb] = (int (*)[nb]) malloc(sizeof(int[nb]))

In both case the heap object is an array.

We need the heap reference to be compatible with the pointer type. Adding a [0] subscript or not should be decided later, when the points-to arc is built. Or we might be able to guess right in case the first dimension is unbounded...

See Points-to/dereference19.c, line 19 for case 1, and line 17 for case 2.

Definition at line 1321 of file sinks.c.

1322 {
1323  // expression sizeof_exp = EXPRESSION (CAR(call_arguments(expression_call(rhs))));
1324  // FI: kind of dumb since it is int or size_t
1325  // FI: the expected type should be passed down all these function calls...
1326  // type t = expression_to_type(e);
1327  /*
1328  reference nr = original_malloc_to_abstract_location(e,
1329  type_undefined,
1330  type_undefined,
1331  e,
1332  get_current_module_entity(),
1333  get_heap_statement());
1334  */
1335 
1336  // FI: the heap number is not yet used
1340  NIL);
1341 
1342  // FI: why use &si instead of si?
1343  entity me = malloc_to_abstract_location(e, &si);
1344 
1346  /* The type of me may en array type because of
1347  *
1348  * int * p = (int *) malloc(nb*sizeof(int))
1349  *
1350  * or int (*p)[nb] = (int (*)[nb]) malloc(sizeof(int[nb]))
1351  *
1352  * In both case the heap object is an array.
1353  *
1354  * We need the heap reference to be compatible with the pointer
1355  * type. Adding a [0] subscript or not should be decided later, when
1356  * the points-to arc is built. Or we might be able to guess right in
1357  * case the first dimension is unbounded...
1358  *
1359  * See Points-to/dereference19.c, line 19 for case 1, and line 17
1360  * for case 2.
1361  */
1362  if(!entity_array_p(me)) {
1363  mr = make_reference(me, NIL);
1364  }
1365  else {
1366  type t = entity_type(me);
1367  variable v = type_variable(t);
1368  list dl = variable_dimensions(v);
1369  dimension d = DIMENSION(CAR(dl));
1370  expression u = dimension_upper(d);
1371  if(unbounded_expression_p(u))
1373  else
1374  mr = make_reference(me, NIL);
1375  }
1376 
1377  cell mc = make_cell_reference(mr);
1378  list sinks = CONS(CELL, mc, NIL);
1379 
1380  if(!get_bool_property("POINTS_TO_SUCCESSFUL_MALLOC_ASSUMED")) {
1381  cell nc = make_null_cell();
1382  sinks = CONS(CELL, nc, sinks);
1383  }
1384 
1385  return sinks;
1386 }
sensitivity_information make_sensitivity_information(statement current_stmt, entity current_module, list enclosing_flow)
entity malloc_to_abstract_location(expression malloc_exp, sensitivity_information *psi)
generate an abstract heap location entity
bool entity_array_p(entity e)
Is e a variable with an array type?
Definition: entity.c:754
statement get_heap_statement()
Definition: sinks.c:1191

References CAR, CELL, CONS, DIMENSION, dimension_upper, entity_array_p(), entity_type, EXPRESSION, get_bool_property(), get_current_module_entity(), get_heap_statement(), int_to_expression(), make_cell_reference(), make_null_cell(), make_reference(), make_sensitivity_information(), malloc_to_abstract_location(), NIL, reference_undefined, type_variable, unbounded_expression_p(), and variable_dimensions.

Referenced by insensitive_malloc_to_points_to_sinks(), malloc_to_points_to_sinks(), and unique_malloc_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ forloop_to_points_to()

pt_map forloop_to_points_to ( forloop  fl,
pt_map  pt_in 
)
Parameters
fll
pt_int_in

Definition at line 974 of file statement.c.

975 {
976  pt_map pt_out = pt_in;
977  statement b = forloop_body(fl);
980  expression inc = forloop_increment(fl);
981 
982  pt_out = any_loop_to_points_to(b, init, c, inc, pt_in);
983  return pt_out;
984 }
pt_map any_loop_to_points_to(statement b, expression init, expression c, expression inc, pt_map pt_in)
Perform the same k-limiting scheme for all kinds of loops.
Definition: statement.c:653
#define forloop_initialization(x)
Definition: ri.h:1366
#define forloop_increment(x)
Definition: ri.h:1370
#define forloop_condition(x)
Definition: ri.h:1368
#define forloop_body(x)
Definition: ri.h:1372

References any_loop_to_points_to(), forloop_body, forloop_condition, forloop_increment, forloop_initialization, and init.

Referenced by instruction_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ formal_points_to_parameter()

set formal_points_to_parameter ( cell  c)

We want a recursive descent on the type of the formal parameter, once we found a pointer type we beguin a recursive descent until founding a basic case.

Then we beguin the ascent and the creation gradually of the points_to_stub by calling pointer_formal_parameter_to_stub_points_to().

FI->AM: as I would rather work on-demand, this function should be useless. I fixed it nevertheless because it seems better for EffectsWithPointsTo, which does not seem to allocate the new points-to stubs it needs.

fpt = entity_basic_concrete_type(e);

We ignor dimensions for the time being, descriptors are not implemented yet...Amira Mensi

what about storage

Definition at line 85 of file points_to_init_analysis.c.

86 {
88  type fpt = type_undefined;
92 
93  r = cell_to_reference(c);
94  bool to_be_freed = false;
95  /* fpt = entity_basic_concrete_type(e); */
96  fpt = cell_reference_to_type(r,&to_be_freed);
97  if(type_variable_p(fpt)){
98  /* We ignor dimensions for the time being, descriptors are not
99  * implemented yet...Amira Mensi*/
100  basic fpb = variable_basic(type_variable(fpt));
101  if(array_type_p(fpt)) {
102  pt_in = set_union(pt_in, pt_in, array_formal_parameter_to_stub_points_to(fpt,c));
103  }
104  else {
105  switch(basic_tag(fpb)){
106  case is_basic_int:
107  break;
108  case is_basic_float:
109  break;
110  case is_basic_logical:
111  break;
112  case is_basic_overloaded:
113  break;
114  case is_basic_complex:
115  break;
116  case is_basic_pointer:{
117  pt_in = set_union(pt_in, pt_in, pointer_formal_parameter_to_stub_points_to(fpt,c));
118  /* what about storage*/
119  break;
120  }
121  case is_basic_derived:{
122  pt_in = set_union(pt_in, pt_in, derived_formal_parameter_to_stub_points_to(fpt,c));
123  break;
124  }
125  case is_basic_string:
126  break;
127  case is_basic_typedef:{
128  pt_in = set_union(pt_in, pt_in, typedef_formal_parameter_to_stub_points_to(fpt,c));
129  break;
130  }
131  case is_basic_bit:
132  break;
133  default: pips_internal_error("unexpected tag %d", basic_tag(fpb));
134  }
135  }
136  }
137  if (to_be_freed) free_type(fpt);
138  return pt_in;
139 
140 }
type cell_reference_to_type(reference, bool *)
computes the type of a cell reference representing a memory access path.
Definition: type.c:466
set array_formal_parameter_to_stub_points_to(type t, cell c)
Type "t" is supposed to be a concrete type.
set pointer_formal_parameter_to_stub_points_to(type pt, cell c)
Input : a formal parameter which is a pointer and its type.
set derived_formal_parameter_to_stub_points_to(type pt, cell c)
Input : a formal parameter which has a derived type (FI, I guess).
set typedef_formal_parameter_to_stub_points_to(type pt, cell c)
Input : a formal parameter which is a typedef.
@ is_basic_derived
Definition: ri.h:579
@ is_basic_string
Definition: ri.h:576
@ is_basic_float
Definition: ri.h:572
@ is_basic_bit
Definition: ri.h:577
@ is_basic_pointer
Definition: ri.h:578
@ is_basic_overloaded
Definition: ri.h:574
@ is_basic_int
Definition: ri.h:571
@ is_basic_logical
Definition: ri.h:573
@ is_basic_typedef
Definition: ri.h:580
@ is_basic_complex
Definition: ri.h:575
#define basic_tag(x)
Definition: ri.h:613

References array_formal_parameter_to_stub_points_to(), array_type_p(), basic_tag, cell_reference_to_type(), cell_to_reference(), derived_formal_parameter_to_stub_points_to(), free_type(), is_basic_bit, is_basic_complex, is_basic_derived, is_basic_float, is_basic_int, is_basic_logical, is_basic_overloaded, is_basic_pointer, is_basic_string, is_basic_typedef, pips_internal_error, pointer_formal_parameter_to_stub_points_to(), points_to_equal_p(), points_to_rank(), reference_undefined, set_generic_make(), set_private, set_union(), type_undefined, type_variable, type_variable_p, typedef_formal_parameter_to_stub_points_to(), and variable_basic.

Referenced by init_points_to_analysis().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ formal_source_to_sinks()

list formal_source_to_sinks ( cell  source,
pt_map  pts,
bool  fresh_p 
)

Creation of a stub for a formal parameter or for a reference based on a formal parameter.

The formal parameter may be a pointer, an array of something or a struct of something and so on recursively.

New dimensions may have to be added to the sink type if the source entity type is an array or if the types are assumed not strict for pointer arithmetic. This is a general issue for stub generation and dealt with at a lower level.

Because references must be considered, it is not clear that formal parameters must be handled differently from stubs or global variables. The initial decision was made, I believe, because they were assumed references in a very simple way, for instance as simple direct references.

Test cases: argv03.c

Parameters
sourceource
ptsts
fresh_presh_p

Definition at line 1380 of file points_to_set.c.

1381 {
1382  list sinks = NIL;
1383 
1384  bool null_initialization_p =
1385  get_bool_property("POINTS_TO_NULL_POINTER_INITIALIZATION");
1386  // bool strict_p = get_bool_property("POINTS_TO_STRICT_POINTER_TYPES");
1387 
1388  reference r = cell_any_reference(source);
1389  entity v = reference_variable(r);
1390  //type vt = compute_basic_concrete_type(entity_type(v));
1392  //bool to_be_freed;
1393  //type source_t =
1394  // compute_basic_concrete_type(points_to_cell_to_type(source, &to_be_freed));
1395  type source_t = points_to_cell_to_concrete_type(source);
1396 
1397  pips_assert("The source type is a pointer type", C_pointer_type_p(source_t));
1399 
1400  // FI: the type retrieval must be improved for arrays & Co
1401  // FI: This is not going to work with typedefs...
1402  // FI: You need array_p to depend on the dimensionality of the
1403  // reference as it may have arrays at several level, intertwinned with
1404  // structs.
1405  bool array_p = array_type_p(vt);
1406  // Should be points_to_cell_dimension(), counting the number of
1407  // numerical or unbounded dimensions.
1408 
1409  // Beware of void *: it is hard to declare an array of "void", make it "char"
1410  // But this is performed at a lower level
1411  /*
1412  type ast = type_undefined;
1413  if(type_void_p(st))
1414  ast = make_scalar_integer_type(DEFAULT_CHARACTER_TYPE_SIZE);
1415  else
1416  ast = copy_type(st);
1417  */
1418 
1419  points_to pt = create_k_limited_stub_points_to(source, st, array_p, pts);
1420 
1421  //free_type(ast);
1422 
1423  if(null_initialization_p) {
1426  }
1427  pts = add_arc_to_pt_map_(pt, pts);
1429  sinks = source_to_sinks(source, pts, fresh_p);
1430  if(null_initialization_p){
1431  list ls = null_to_sinks(source, pts);
1432  sinks = gen_nconc(ls, sinks);
1433  }
1434 
1435  return sinks;
1436 }
points_to create_k_limited_stub_points_to(cell source, type t, bool array_p, pt_map in)
Create a new node "sink" of type "t" and a new arc "pt" starting from node "source",...
list null_to_sinks(cell source, pt_map ptm)
Create a list of null sinks and add a new null points-to relation to pts.
bool C_pointer_type_p(type)
Returns OK for "char[]" as well as for "char *".
Definition: type.c:3011

References add_arc_to_points_to_context(), add_arc_to_pt_map_(), array_type_p(), C_pointer_type_p(), cell_any_reference(), compute_basic_concrete_type(), copy_points_to(), create_k_limited_stub_points_to(), entity_basic_concrete_type(), free_approximation(), gen_nconc(), get_bool_property(), make_approximation_may(), NIL, null_to_sinks(), pips_assert, points_to_approximation, points_to_cell_to_concrete_type(), reference_variable, source_to_sinks(), and type_to_pointed_type().

Referenced by source_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ free_points_to_graph_sets()

void free_points_to_graph_sets ( points_to_graph  s,
  ... 
)

Free several sets in one call.

Useful when many sets are used simultaneously.

Analyze in args the variadic arguments that may be after t:

Since a variadic function in C must have at least 1 non variadic argument (here the s), just skew the varargs analysis:

Get the next argument

Release the variadic analysis

Definition at line 3150 of file points_to_set.c.

3151 {
3152  va_list args;
3153 
3154  /* Analyze in args the variadic arguments that may be after t: */
3155  va_start(args, s);
3156  /* Since a variadic function in C must have at least 1 non variadic
3157  argument (here the s), just skew the varargs analysis: */
3158  do {
3160  /* Get the next argument */
3161  //s = va_arg(args, points_to_graph);
3162  s = va_arg(args, pt_map);
3163  } while(s!=NULL);
3164  /* Release the variadic analysis */
3165  va_end(args);
3166 }
void free_points_to_graph(points_to_graph p)

References free_points_to_graph().

+ Here is the call graph for this function:

◆ freeable_points_to_cells()

list freeable_points_to_cells ( list  R)

Remove from points-to cell list R cells that certainly cannot be freed.


if c is a heap location with indices other than zero then we have bumped into a non-legal free

Definition at line 1457 of file expression.c.

1458 {
1459  list nhl = NIL; // No heap list: cannot be freed
1460  FOREACH(CELL, c, R) {
1461  if(heap_cell_p(c) || stub_points_to_cell_p(c)) {
1463  list inds = reference_indices(r);
1464  /* if c is a heap location with indices other than zero then we
1465  have bumped into a non-legal free */
1466  if(!ENDP(inds)) {
1467  expression ind = EXPRESSION (CAR(inds));
1468  // No offset allowed for a free()
1469  if(!expression_null_p(ind))
1470  nhl = CONS(CELL, c, nhl);
1471  }
1472  // gen_free_list(inds);
1473  }
1474  else if(!heap_cell_p(c)
1475  && !stub_points_to_cell_p(c)
1477  nhl = CONS(CELL, c, nhl);
1478  }
1479  gen_list_and_not(&R, nhl);
1480  gen_free_list(nhl);
1481  return R;
1482 }
bool stub_points_to_cell_p(cell)
Definition: points_to.c:108

References CAR, CELL, cell_any_reference(), cell_typed_anywhere_locations_p(), CONS, ENDP, EXPRESSION, expression_null_p(), FOREACH, gen_free_list(), gen_list_and_not(), heap_cell_p(), NIL, reference_indices, and stub_points_to_cell_p().

Referenced by freed_pointer_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ freed_list_to_points_to()

pt_map freed_list_to_points_to ( expression  lhs,
list  L,
list  R,
pt_map  pt_in 
)

Error detections on "L" and "R" have already been performed.

R only contains heap locations or stub locations, i.e. potential heap locations. Neither L nor R are empty. "lhs" is provided for other error messages.

First level memory leaks

Build a nowhere cell - Should we check a property to type it or not?

Remove Kill_1 if it is not empty by definition

Memory leak detection... Must be computed early, before pt_out has been (too?) modified. Transitive closure not performed... If one cell has been freed and if it has become unreachable, then arcs starting from it have become useless and other cells that were pointed by it may also have become unreachable.

Add Gen_2, which is not conditionned by gen_length(R) or atomicity.

Compute and add Gen_2

Do not notify the user that the source of the new nowhere points to relation is a dangling pointer because it is only a may information. Exact alias information or a more precise heap model would be necessary to have exact information about dangling pointers.

Remove Kill_2 if it is not empty by definition... which it is if heap(r) is true, but not if stub(r). Has to be done after Gen_2, or modification of pt_out should be delayed, which would avoid the internal modification of pt_out_s and make the code easier to understand...

Remove Kill_3 if it is not empty by definition: with the current heap model, it is always empty. Unreachable cells are dealt somewhere else. They can be tested with points_to_sink_to_sources().

FI: Must be placed after gen_1 in case the assignment makes the cell reachable? Nonsense?

Add Gen_1 - Not too late since pt_out has aready been modified?

Add Gen_2: useless, already performed by Kill_2

More memory leaks?

Clean up the resulting graph

Parameters
lhshs
pt_int_in

Definition at line 1489 of file expression.c.

1490 {
1491  pt_map pt_out = pt_in;
1492  list ML = NIL; /* First level memory leaks */
1493 
1494  pips_assert("L is not empty", !ENDP(L));
1495  pips_assert("R is not empty", !ENDP(R));
1496 
1497  /* Build a nowhere cell - Should we check a property to type it or not? */
1498  //list N = CONS(CELL, make_nowhere_cell(), NIL);
1502 
1503  /* Remove Kill_1 if it is not empty by definition */
1504  if(gen_length(L)==1 && atomic_points_to_cell_p(CELL(CAR(L)))) {
1505  set pt_out_s = points_to_graph_set(pt_out);
1506  SET_FOREACH(points_to, pts, pt_out_s) {
1507  cell l = points_to_source(pts);
1508  // FI: use the CP lattice and its operators instead?
1509  //if(related_points_to_cell_in_list_p(l, L)) {
1510  if(points_to_cell_in_list_p(l, L)) {
1511  // FI: assuming you can perform the removal inside the loop...
1512  remove_arc_from_pt_map(pts, pt_out);
1513  }
1514  }
1515  }
1516 
1517  /* Memory leak detection... Must be computed early, before pt_out
1518  has been (too?) modified. Transitive closure not performed... If
1519  one cell has been freed and if it has become unreachable, then
1520  arcs starting from it have become useless and other cells that
1521  were pointed by it may also have become unreachable. */
1522  if(gen_length(R)==1 && unreachable_points_to_cell_p(CELL(CAR(R)),pt_out)) {
1523  cell c = CELL(CAR(R));
1525  if(pointer_type_p(ct) || struct_type_p(ct)
1527  || array_of_struct_type_p(ct)) {
1528  // FI: this might not work for arrays of pointers?
1529  // Many forms of "source" can be developped when we are dealing
1530  // struct and arrays
1531  // FI: do we need a specific version of source_to_sinks()?
1533  //cell nc = make_cell_reference(make_reference(v, NIL));
1534  list PML = variable_to_sinks(v, pt_out, true);
1535  FOREACH(CELL, m, PML) {
1536  if(heap_cell_p(m)) {
1538  pips_user_warning("Memory leak for bucket \"%s\".\n",
1539  entity_name(b));
1540  ML = CONS(CELL, m, ML);
1541  }
1542  }
1543  }
1544  }
1545 
1546  /* Add Gen_2, which is not conditionned by gen_length(R) or atomicity. */
1547  set pt_out_s = points_to_graph_set(pt_out);
1548  SET_FOREACH(points_to, pts, pt_out_s) {
1549  cell r = points_to_sink(pts);
1550  if(points_to_cell_in_list_p(r, R)) {
1551  if(!null_cell_p(r) && !anywhere_cell_p(r) && !nowhere_cell_p(r)) {
1552  /* Compute and add Gen_2 */
1553  cell source = points_to_source(pts);
1554  // FI: it should be a make_typed_nowhere_cell()
1557  cell sink = make_typed_nowhere_cell(pt);
1558  // FI: why may? because heap cells are always abstract locations
1559  //approximation a = make_approximation_may();
1561  points_to npt = make_points_to(copy_cell(source), sink, a,
1563  add_arc_to_pt_map(npt, pt_out);
1564  /* Do not notify the user that the source of the new
1565  nowhere points to relation is a dangling pointer
1566  because it is only a may information. Exact alias
1567  information or a more precise heap model would be
1568  necessary to have exact information about dangling
1569  pointers. */
1570  if(stub_points_to_cell_p(r)) {
1572  pips_user_warning("Dangling pointer \"%s\" has been detected at line %d.\n",
1573  entity_user_name(b),
1575  }
1576  }
1577  }
1578  }
1579 
1580 
1581  /* Remove Kill_2 if it is not empty by definition... which it is if
1582  heap(r) is true, but not if stub(r). Has to be done after Gen_2,
1583  or modification of pt_out should be delayed, which would avoid
1584  the internal modification of pt_out_s and make the code easier to
1585  understand... */
1586  if(gen_length(R)==1 && generic_atomic_points_to_cell_p(CELL(CAR(R)), false)) {
1587  set pt_out_s = points_to_graph_set(pt_out);
1588  cell r = CELL(CAR(R));
1589  if(!null_cell_p(r) && !anywhere_cell_p(r) && !nowhere_cell_p(r)) {
1590  SET_FOREACH(points_to, pts, pt_out_s) {
1591  cell s = points_to_sink(pts);
1592  if(points_to_cell_equal_p(r, s)) {
1593  // FI: pv_whileloop05, lots of related cells to remove after a free...
1594  // FI: assuming you can perform the removal inside the loop...
1595  remove_arc_from_pt_map(pts, pt_out);
1596  }
1597  }
1598  }
1599  }
1600 
1601  /* Remove Kill_3 if it is not empty by definition: with the
1602  current heap model, it is always empty. Unreachable cells are
1603  dealt somewhere else. They can be tested with
1604  points_to_sink_to_sources().
1605 
1606  FI: Must be placed after gen_1 in case the assignment makes the cell
1607  reachable? Nonsense?
1608  */
1609  if(gen_length(R)==1
1610  && (atomic_points_to_cell_p(CELL(CAR(R)))
1611  || unreachable_points_to_cell_p(CELL(CAR(R)), pt_out))) {
1612  cell c = CELL(CAR(R));
1613  list S = points_to_sink_to_sources(c, pt_out, false);
1614  if(ENDP(S) || atomic_points_to_cell_p(c)) {
1615  set pt_out_s = points_to_graph_set(pt_out);
1616  SET_FOREACH(points_to, pts, pt_out_s) {
1617  cell l = points_to_source(pts);
1619  // Potentially memory leaked cell:
1620  cell r = points_to_sink(pts);
1621  pt_out = memory_leak_to_more_memory_leaks(r, pt_out);
1622  remove_arc_from_pt_map(pts, pt_out);
1623  }
1624  }
1625  }
1626  else
1627  gen_free_list(S);
1628  }
1629 
1630  /* Add Gen_1 - Not too late since pt_out has aready been modified? */
1631  pt_out = list_assignment_to_points_to(L, N, pt_out);
1632 
1633  /* Add Gen_2: useless, already performed by Kill_2 */
1634 
1635  /*
1636  * Other pointers may or must now be dangling because their target
1637  * has been freed. Already detected at the level of Gen_2.
1638  */
1639 
1640  /* More memory leaks? */
1641  FOREACH(CELL, m, ML)
1642  pt_out = memory_leak_to_more_memory_leaks(m, pt_out);
1643  gen_free_list(ML);
1644 
1645  /* Clean up the resulting graph */
1646  // pt_out = remove_unreachable_heap_vertices_in_points_to_graph(pt_out, true);
1647  return pt_out;
1648 }
#define remove_arc_from_pt_map(a, s)
pt_map list_assignment_to_points_to(list L, list R, pt_map pt_out)
Update "pt_out" when any element of L can be assigned any element of R.
Definition: expression.c:2029
pt_map memory_leak_to_more_memory_leaks(cell l, pt_map in)
Cell "l" has been memory leaked for sure and is not referenced any more in "in".
Definition: expression.c:1929
bool unreachable_points_to_cell_p(cell, pt_map)
Can cell c be accessed via another cell?
list variable_to_sinks(entity, pt_map, bool)
Return all cells in points-to set "pts" who source is based on entity "e".
list points_to_sink_to_sources(cell, pt_map, bool)
Build the sources of sink "sink" according to the points-to graphs.
Base of the parameters.
Definition: pip_interface.c:89

References add_arc_to_pt_map, anywhere_cell_p(), array_of_pointers_type_p(), array_of_struct_type_p(), atomic_points_to_cell_p(), CAR, CELL, cell_any_reference(), compute_basic_concrete_type(), CONS, copy_approximation(), copy_cell(), ENDP, entity_name, entity_user_name(), FOREACH, gen_free_list(), gen_length(), generic_atomic_points_to_cell_p(), heap_cell_p(), list_assignment_to_points_to(), make_descriptor_none(), make_points_to(), make_typed_nowhere_cell(), memory_leak_to_more_memory_leaks(), NIL, nowhere_cell_p(), null_cell_p(), pips_assert, pips_user_warning, pointer_type_p(), points_to_approximation, points_to_cell_equal_p(), points_to_cell_in_list_p(), points_to_cell_to_concrete_type(), points_to_context_statement_line_number(), points_to_expression_to_concrete_type(), points_to_graph_set, points_to_sink, points_to_sink_to_sources(), points_to_source, reference_variable, related_points_to_cell_in_list_p(), remove_arc_from_pt_map, SET_FOREACH, struct_type_p(), stub_points_to_cell_p(), type_to_pointed_type(), unreachable_points_to_cell_p(), and variable_to_sinks().

Referenced by freed_pointer_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ freed_pointer_to_points_to()

pt_map freed_pointer_to_points_to ( expression  lhs,
pt_map  pt_in,
bool  side_effect_p 
)

Any abstract location of the lhs in L is going to point to nowhere, maybe.

Any source in pt_in pointing towards any location in lhs may or Must now points towards nowhere (malloc07).

New points-to information must be added when a formal parameter is dereferenced.

Equations for "free(e);":

Let L = expression_to_sources(e,in)

and R_1 = (expression_to_sinks(e,in) ^ (HEAP U STUBS)) - {undefined}

where ^ denotes the set intersection.

If R_1 is empty, an execution error must occur.

If R_1={NULL}, nothing happens. Let R=R_1-{NULL}.

Any location "l" corresponding to "e" can now point to nowhere/undefined:

Gen_1 = {pts=(l,nowhere,a) | l in L}

Any location source that pointed to a location r in the heap, pointed to by some l by definition, can now point to nowhere/undefined also:

Gen_2 = {pts=(source,nowhere,a) | exists r in R && r in Heap or Stubs && exists pts'=(source,r,a') in in}

If e corresponds to a unique (non-abstract?) location l, any arc starting from l can be removed:

Kill_1 = {pts=(l,r,a) in in | l in L && |L|=1 && atomic(l)}

If the freed location r is precisely known, any arc pointing towards it can be removed:

Kill_2 = {pts=(l,r,a) in in | r in R && |R|=1 && atomic(r)}

If the freed location r is precisely known or if it can no longer be reached, any arc pointing from it can be removed:

Kill_3 = {pts=(r,d,a) in in | r in R && |R|=1 && (atomic(r) v unreachable_p(r, in)}

Then the set PML = { d | heap(d) ^ (r,d,a) in Kill_3} becomes a set of potential meory leaks. They are leaked if they become unreachable in the new points-to relation out (see below) and they generate recursively new potential memory leaks and an updated points-to relation.

Since our current heap model only use abstract locations and since we do not keep any alias information, the predicate atomic should always return false and the sets Kill_2 and Kill_3 should always be empty, except if a stub is freed: locally the stub is atomic.

So, after the execution of "free(e);", the points-to relation is:

out = (in - Kill_1 - Kill_2 - Kill_3) U Gen_1 U Gen_2

Warnings for potential dangling pointers:

DP = {r|exists pts=(r,l,a) in Gen_2} // To be checked

No warning is issued as those are only potential.

Memory leaks: the freed bucket may be the only bucket containing pointers towards another bucket:

PML = {source_to_sinks(r)|r in R} ML = {m|m in PML && heap_cell_p(m) && !reachable(m, out)}

Note: for DP and ML, we could compute may and must/exact sets. We only compute must/exact sets to avoid swamping the log file with false alarms.

FI->FC: it might be better to split the problem according to |R|. If |R|=1, you know which bucket is destroyed, unless it is an abstract bucket... which we do not really know even at the intraprocedural level. In that case, you could remove all edges starting from r and then substitute r by nowhere/undefined.

If |R| is greater than 1, then a new node nowhere/undefined must be added and any arc ending up in R must be duplicated with a similar arc ending up in the new node.

The cardinal of |L| does not seem to have an impact: it does, see Kill_1

Remove cells from R_1 that do not belong to Heap: they cannot be freed

A execution error is certain

Free(NULL) has no effect

Remove from R locations that cannot be freed

We have bumped into a non-legal free such as free(p[10]). See test case malloc10.c

Parameters
lhshs
pt_int_in
side_effect_pide_effect_p

Definition at line 1741 of file expression.c.

1742 {
1743  // FI: is this redundant with processing already performed by callers?
1744  // A test case is needed...
1745  pt_map pt_out = expression_to_points_to(lhs, pt_in, side_effect_p);
1746  list PML = NIL;
1747 
1748  list R_1 = expression_to_points_to_sinks(lhs, pt_out);
1749  list R = NIL;
1750  /* Remove cells from R_1 that do not belong to Heap: they cannot be
1751  freed */
1752  FOREACH(CELL,r, R_1) {
1753  if(heap_cell_p(r)
1754  || stub_points_to_cell_p(r)
1756  || null_cell_p(r))
1757  R = CONS(CELL, r, R);
1758  }
1759  gen_free_list(R_1);
1760 
1761  if(ENDP(R)) {
1762  /* A execution error is certain */
1763  pips_user_warning("Expression \"%s\" at line %d cannot be freed.\n",
1764  expression_to_string(lhs),
1766  clear_pt_map(pt_out);
1767  points_to_graph_bottom(pt_out) = true;
1768  }
1769  else if(gen_length(R)==1 && null_cell_p(CELL(CAR(R)))) {
1770  /* Free(NULL) has no effect*/
1771  ;
1772  }
1773  else {
1774  /* Remove from R locations that cannot be freed */
1775  R = freeable_points_to_cells(R);
1776 
1777  if(ENDP(R)) {
1778  /* We have bumped into a non-legal free such as free(p[10]). See test
1779  case malloc10.c */
1780  pips_user_warning("Free of a non-heap allocated address pointed "
1781  "by \"%s\" at line %d.\n"
1782  "Or bug in the points-to analysis...\n",
1783  expression_to_string(lhs),
1785  clear_pt_map(pt_out);
1786  points_to_graph_bottom(pt_out) = true;
1787  }
1788  else {
1789  list L = expression_to_points_to_sources(lhs, pt_out);
1790  pips_assert("L is not empty", !ENDP(L));
1791  pt_out = freed_list_to_points_to(lhs, L, R, pt_in);
1792  gen_free_list(L);
1793  }
1794  }
1795 
1796  // FI: memory leak(s) in this function?
1797  //gen_free_list(N);
1798  gen_full_free_list(R);
1799  gen_free_list(PML);
1800 
1801  return pt_out;
1802 }
pt_map freed_list_to_points_to(expression lhs, list L, list R, pt_map pt_in)
Error detections on "L" and "R" have already been performed.
Definition: expression.c:1489
list freeable_points_to_cells(list R)
Remove from points-to cell list R cells that certainly cannot be freed.
Definition: expression.c:1457

References anywhere_cell_p(), CAR, CELL, cell_typed_anywhere_locations_p(), clear_pt_map, CONS, ENDP, expression_to_points_to(), expression_to_points_to_sinks(), expression_to_points_to_sources(), expression_to_string(), FOREACH, freeable_points_to_cells(), freed_list_to_points_to(), gen_free_list(), gen_full_free_list(), gen_length(), heap_cell_p(), NIL, null_cell_p(), pips_assert, pips_user_warning, points_to_context_statement_line_number(), points_to_graph_bottom, and stub_points_to_cell_p().

Referenced by intrinsic_call_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ full_copy_pt_map()

pt_map full_copy_pt_map ( pt_map  in)
Parameters
inn

Definition at line 67 of file statement.c.

68 {
69  // Dynamic type check
71  pips_assert("\"in\" is a points_to_graph", n==points_to_graph_domain);
72  pt_map out = new_pt_map();
73  set in_s = points_to_graph_set(in);
74  set out_s = points_to_graph_set(out);
75  SET_FOREACH(points_to, pt, in_s) {
76  points_to npt = copy_points_to(pt);
77  set_add_element(out_s, out_s, (void *) npt);
78  }
80  return out;
81 }
#define points_to_graph_domain_number(x)
#define points_to_graph_domain
Definition: print.c:373

References copy_points_to(), new_pt_map, out, pips_assert, points_to_graph_bottom, points_to_graph_domain, points_to_graph_domain_number, points_to_graph_set, set_add_element(), and SET_FOREACH.

Referenced by any_loop_to_points_to(), boolean_intrinsic_call_condition_to_points_to(), init_points_to_context(), intrinsic_call_to_points_to(), new_any_loop_to_points_to(), new_points_to_unstructured(), statement_to_points_to(), ternary_intrinsic_call_to_points_to_sinks(), and test_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ full_copy_simple_pt_map()

set full_copy_simple_pt_map ( set  m)

statement.c

statement.c

If elements are shared, it quickly becomes impossible to deep free any set.

Definition at line 50 of file statement.c.

51 {
53  /*
54  HASH_MAP(k, v, {
55  points_to pt = (points_to) k;
56  points_to npt = copy_points_to(pt);
57  hash_put( out->table, (void *) npt, (void *) npt );
58  }, m->table);
59  */
60  SET_FOREACH(points_to, pt, m) {
61  points_to npt = copy_points_to(pt);
62  set_add_element(out, out, (void *) npt);
63  }
64  return out;
65 }

References copy_points_to(), new_simple_pt_map, out, set_add_element(), and SET_FOREACH.

+ Here is the call graph for this function:

◆ fuse_points_to_sink_cells()

points_to fuse_points_to_sink_cells ( cell  source,
list  sink_l,
pt_map  in 
)

All vertices in "sink_l" are assumed to be sinks of vertex "source" in points-to graph "in".

These vertices must be replaced by a unique vertex, their minimum upper bound in the abstract address lattice. And their own out-going arcs must also be rearranged.

Clearly, some abstract addresses high in the lattice should be allowed large out-degree numbers.

A newly allocated points-to arc is returned. It could be integrated directly in "in", but the integration is performed by a caller.

Find the minimal upper bound of "sink_l"

Compute the sinks of the vertex "mupc" as the union of the sinks of cells in "sink_l" and add the corresponding arcs to "out".

Find the incoming arcs on cells of "sink_l" and replace them by arcs towards copies of mupc.

Finds it sources

Find the set of points-to arcs to destroy and remove them from the points-to graph "in".

Create an arc from "source" to "mupc"

Parameters
sourceource
sink_link_l
inn

Definition at line 3214 of file points_to_set.c.

3215 {
3216  pt_map out = in;
3217 
3218  pips_assert("\"in\" is consistent", consistent_pt_map_p(in));
3219 
3220  /* Find the minimal upper bound of "sink_l" */
3222 
3223  /* Compute the sinks of the vertex "mupc" as the union of the sinks
3224  * of cells in "sink_l" and add the corresponding arcs to "out".
3225  */
3226  list iptl = points_to_sources_to_sinks(sink_l, in, true); // indirect points-to
3227  FOREACH(CELL, sink, iptl) {
3228  cell mupcc = copy_cell(mupc);
3229  points_to pta = make_points_to(mupcc, sink,
3232  add_arc_to_pt_map(pta, in);
3233  }
3234  gen_free_list(iptl);
3235 
3236  /* Find the incoming arcs on cells of "sink_l" and replace them by arcs
3237  towards copies of mupc. */
3238  list new = NIL, old = NIL;
3239  FOREACH(CELL, sink, sink_l) {
3240  if(!null_cell_p(sink) && !nowhere_cell_p(sink)) {
3241  /* Finds it sources */
3243  cell oc = points_to_source(pt);
3244  cell dc = points_to_sink(pt);
3245  if(points_to_cell_equal_p(dc, sink)) {
3246  points_to npt = make_points_to(copy_cell(oc), copy_cell(mupc),
3249  //add_arc_to_pt_map(npt, in);
3250  new = CONS(POINTS_TO, npt, new);
3251  // remove_arc_from_pt_map(pt, in);
3252  old = CONS(POINTS_TO, pt, old);
3253  }
3254  }
3255  }
3256  }
3257  FOREACH(POINTS_TO, npt, new)
3258  add_arc_to_pt_map(npt, in);
3259  FOREACH(POINTS_TO, pt, old)
3260  remove_arc_from_pt_map(pt, in);
3261  gen_free_list(new), gen_free_list(old);
3262  // pips_internal_error("not implemented yet.\n");
3263 
3264  /* Find the set of points-to arcs to destroy and remove them from
3265  * the points-to graph "in".
3266  */
3267  list ptal = points_to_source_to_arcs(source, in, false);
3268  FOREACH(POINTS_TO, pta, ptal) {
3269  cell sink = points_to_sink(pta);
3270  if(!null_cell_p(sink) && !nowhere_cell_p(sink))
3271  if(!points_to_cell_equal_p(sink, mupc))
3272  remove_arc_from_pt_map(pta, in);
3273  }
3274  gen_free_list(ptal);
3275 
3276  /* Create an arc from "source" to "mupc" */
3277  points_to pta = make_points_to(source, mupc,
3280  // add_arc_to_pt_map(pta, in); Might be done by the calller?
3281 
3282  pips_assert("\"out\" is consistent", consistent_pt_map_p(out));
3283 
3284  return pta;
3285 }
cell points_to_cells_minimal_upper_bound(list)
#define false
Definition: newgen_types.h:80
list points_to_sources_to_sinks(list sources, pt_map ptm, bool fresh_p)
void add_arc_to_pt_map(points_to a, pt_map s)
Add a store independent points-to arc: source and destination references include no dereferencing nor...
list points_to_source_to_arcs(cell source, pt_map ptm, bool fresh_p)
Build the list of arcs whose source is "source" according to the points-to graphs "ptm".

References add_arc_to_pt_map(), CELL, CONS, consistent_pt_map_p, copy_cell(), FOREACH, gen_free_list(), make_approximation_may(), make_descriptor_none(), make_points_to(), NIL, nowhere_cell_p(), null_cell_p(), out, pips_assert, POINTS_TO, points_to_cell_equal_p(), points_to_cells_minimal_upper_bound(), points_to_graph_set, points_to_sink, points_to_source, points_to_source_to_arcs(), points_to_sources_to_sinks(), remove_arc_from_pt_map, and SET_FOREACH.

Referenced by normalize_points_to_graph().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ gen_may_constant_paths()

set gen_may_constant_paths ( cell  l,
list  R,
set  in_may,
bool address_of_p,
int  Lc 
)

here we have x = y, then we generate (x,y1,a)|(y,y1,a) as points to relation

locations_equal_p

&& !entity_abstract_location_p(el)

Should be replaced by opgen_constant_path(l,r)

if(reference_unbounded_indices_p(ref))

a = make_approximation_may();

Make sure the types are compatible...

Parameters
in_mayn_may
address_of_pddress_of_p
Lcc

Definition at line 1003 of file constant-path-utils.c.

1008 {
1010  points_to_rank);
1012  if(!(*address_of_p)){
1013  pips_internal_error("address_of_p should always be true in the new implementation/.\n");
1014  /* here we have x = y, then we generate (x,y1,a)|(y,y1,a) as
1015  points to relation */
1016  FOREACH(cell, r, R){
1017  SET_FOREACH(points_to, i, in_may){
1018  if (/* locations_equal_p */equal_must_vreference(r, points_to_source(i)) /* && !entity_abstract_location_p(el) */ ){
1019  cell nl = copy_cell(l);
1020  pt = make_points_to(nl,
1024  }
1027  bool t_to_be_freed = false;
1028  type t = points_to_reference_to_type(ref, &t_to_be_freed);
1029  if(pointer_type_p(t)) {
1030  cell nl = copy_cell(l);
1032  }
1033  else {
1034  cell nl = copy_cell(l);
1036  }
1037  if (t_to_be_freed) free_type(t);
1038  }
1039  if(!points_to_undefined_p(pt)) {
1040  set_add_element(gen_may_cps, gen_may_cps, (void*) pt);
1041  }
1042  }
1043  }
1044  }
1045  else {
1046  int Rc = (int) gen_length(R);
1047  FOREACH(cell, r, R){
1048  // FI: check the unicity of the locations
1049  // FI: relationship with atomic_points_to_cell_p()?
1050  approximation a = (Lc+Rc>2
1051  || !unique_location_cell_p(l)
1052  || !unique_location_cell_p(r)) ?
1054  /* Should be replaced by opgen_constant_path(l,r) */
1055  //reference ref = cell_any_reference(r);
1056  /* if(reference_unbounded_indices_p(ref)) */
1057  /* a = make_approximation_may(); */
1058  cell nl = copy_cell(l);
1059  /* Make sure the types are compatible... */
1061  pt = make_points_to(nl, copy_cell(r), a, make_descriptor_none());
1062  set_add_element(gen_may_cps, gen_may_cps, (void*)pt);
1063  }
1064  }
1065 
1066  return gen_may_cps;
1067 }
bool unique_location_cell_p(cell c)
Does cell "c" represent a unique memory location or a set of memory locations?
bool equal_must_vreference(cell c1, cell c2)
void points_to_cell_types_compatibility(cell, cell)
Make sure that cell l can points towards cell r.
Definition: type.c:985

References array_entity_p(), cell_any_reference(), copy_cell(), equal_must_vreference(), FOREACH, free_type(), gen_length(), int, make_approximation_exact(), make_approximation_may(), make_descriptor_none(), make_points_to(), pips_internal_error, pointer_type_p(), points_to_cell_types_compatibility(), points_to_equal_p(), points_to_rank(), points_to_reference_to_type(), points_to_sink, points_to_source, points_to_undefined, points_to_undefined_p, ref, reference_variable, set_add_element(), SET_FOREACH, set_generic_make(), set_private, and unique_location_cell_p().

Referenced by gen_may_set().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ gen_may_set()

set gen_may_set ( list  L,
list  R,
set  in_may,
bool address_of_p 
)

Should be moved to anywhere_abstract_locations.c.

‍**If the source is not precisely known *‍/

It is easier not to have to maintain the consistency between gen_may1 and kill_may.

Parameters
in_mayn_may
address_of_pddress_of_p

Definition at line 813 of file constant-path-utils.c.

814 {
821  int len = (int) gen_length(L);
822 
823  //if(len > 1) {
824  ///* If the source is not precisely known */
825  /* It is easier not to have to maintain the consistency between
826  gen_may1 and kill_may. */
827  if(false) {
828  FOREACH(cell, l, L) {
829  SET_FOREACH(points_to, pt, in_may){
831  //if(!atomic_points_to_cell_p(points_to_source(pt))) {
832  //if(points_to_compare_cell(points_to_source(pt),l)) {
834  // FI: it would be much easier/efficient to modify the approximation of pt
835  // But it is incompatible with the implementation of sets...
840  set_add_element(gen_may1, gen_may1, (void*)npt);
841  //set_del_element(gen_may1, gen_may1, (void*)pt);
842  }
843  // }
844  }
845  }
846  }
847  }
848 
849  // Possibly generate an error for dereferencing an undefined pointer
850  bool error_p =
851  !get_bool_property("POINTS_TO_UNINITIALIZED_POINTER_DEREFERENCING");
852  int lc = (int) gen_length(L);
853  FOREACH(cell, l, L){
855  entity lv = reference_variable(lr);
856  bool null_p = entity_null_locations_p(lv);
857  bool nowhere_p = entity_typed_nowhere_locations_p(lv)
859  string bug = null_p? "a null" : "";
860  bug = nowhere_p? "an undefined" : "";
861  // Can the lhs be accessed?
862  if(null_p || nowhere_p) {
863  // No: two options; either a user_error() for dereferencing an
864  // unitialized pointer or a conversion to anywhere, typed or not
865  // FI: why be tolerant of NULL pointer dereferencing? For may information
866  if(lc==1) {
867  if(error_p)
868  pips_user_error("Dereferencing of %s pointer.\n", bug);
869  else {
870  pips_user_warning("Dereferencing of %s pointer.\n", bug);
871  }
872  }
873  else {
874  pips_user_warning("Possible dereferencing of %s pointer.\n", bug);
875  }
876  type t = entity_type(lv);
878  set gen_l = gen_may_constant_paths(nl, R, in_may, address_of_p, len);
879  set_union(gen_may2, gen_may2, gen_l);
880  }
881  else {
882  // FI: memory leak due to call to call to gen_may_constant_paths()
883  set gen_l = gen_may_constant_paths(l, R, in_may, address_of_p, len);
884  // FI: be careful, the union does not preserve consistency because
885  // the same arc may appear with different approximations
886  set_union(gen_may2, gen_may2, gen_l);
887  // free_set(gen_l);
888  }
889  }
890 
891  set_union(gen_may2, gen_may2, gen_may1);
892  set_union(gen_may2, gen_may2, gen_may3);
893 
894  return gen_may2;
895 }
bool entity_nowhere_locations_p(entity e)
test if an entity is the bottom of the lattice
bool entity_typed_nowhere_locations_p(entity e)
test if an entity is the bottom of the lattice
set gen_may_constant_paths(cell l, list R, set in_may, bool *address_of_p, int Lc)
bool cells_may_conflict_p(cell c1, cell c2)
Check if two cell may conflict.
Definition: conflicts.c:696

References approximation_exact_p, cell_any_reference(), cells_may_conflict_p(), copy_cell(), entity_nowhere_locations_p(), entity_null_locations_p(), entity_type, entity_typed_nowhere_locations_p(), FOREACH, gen_length(), gen_may_constant_paths(), get_bool_property(), int, make_anywhere_points_to_cell(), make_approximation_may(), make_descriptor_none(), make_points_to(), pips_user_error, pips_user_warning, points_to_approximation, points_to_equal_p(), points_to_rank(), points_to_sink, points_to_source, reference_variable, set_add_element(), SET_FOREACH, set_generic_make(), set_private, and set_union().

Referenced by list_assignment_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ gen_must_constant_paths()

set gen_must_constant_paths ( cell  l,
list  R,
set  in_must,
bool address_of_p,
int  Lc 
)

Build a set of arcs from cell l towards cells in list R if *address_p is true, or towards cells pointed by cells in list R if not.

Approximation is must if Lc==1. Lc is the cardinal of L, a set containing l.

FI->AM: I do not understand why the cardinal of R is not used too when deciding if the approximation is may or must. I decide to change the semantics of this function although it is used by the initial analysis.

FI: since *address_of_p is not modified, I do not understand why a pointer is passed.

FI->AM: sharing of a... A new approximation must be generated for each new arc

if we have x = &y then we generate (x,y,a) as points to relation

Should be replaced by opgen_constant_path(l,r)

if(reference_unbounded_indices_p(ref))

a = make_approximation_may();

here we have x = y, then we generate (x,y1,a)|(y,y1,a) as points to relation

locations_equal_p

&& !entity_abstract_location_p(el)

if(array_entity_p(reference_variable(cell_any_reference(r)))){

reference ref = cell_any_reference(r);

expression ex = reference_to_expression(ref);

if(!expression_pointer_p(ex))

pt = make_points_to(l, r, a, make_descriptor_none());

else

pt = make_points_to(l, points_to_sink(i), a, make_descriptor_none());

}

if(!points_to_undefined_p(pt))

set_add_element(gen_must_cps, gen_must_cps, (void*) pt);

if(reference_unbounded_indices_p(ref))

a = make_approximation_may();

Parameters
in_mustn_must
address_of_pddress_of_p
Lcc

Definition at line 1088 of file constant-path-utils.c.

1093 {
1095  points_to_rank);
1097  //approximation a = approximation_undefined;
1098  bool changed = false;
1099  int Rc = (int) gen_length(R);
1100 
1101  // Rc = 0;
1102  if(*address_of_p){
1103  /* if we have x = &y then we generate (x,y,a) as points to relation*/
1104  FOREACH(cell, r, R){
1105  /* Should be replaced by opgen_constant_path(l,r) */
1106  //reference ref = cell_any_reference(r);
1107  /* if(reference_unbounded_indices_p(ref)) */
1108  /* a = make_approximation_may(); */
1109  approximation a = (Lc+Rc>2
1110  || !unique_location_cell_p(l)
1111  || !unique_location_cell_p(r))?
1113  pt = make_points_to(l, r, a, make_descriptor_none());
1114  set_add_element(gen_must_cps, gen_must_cps, (void*)pt);
1115  }
1116  }
1117  else {
1118  /* here we have x = y, then we generate (x,y1,a)|(y,y1,a) as
1119  points to relation */
1120  FOREACH(cell, r, R){
1121  SET_FOREACH(points_to, i, in_must) {
1122  if (/* locations_equal_p */equal_must_vreference(r, points_to_source(i))/* && !entity_abstract_location_p(el) */){
1124  l = simple_cell_to_store_independent_cell(l, &changed);
1126  approximation a = (Lc+Rc>2)?
1129 
1130 
1131  /* if(array_entity_p(reference_variable(cell_any_reference(r)))){ */
1132  /* reference ref = cell_any_reference(r); */
1133  /* expression ex = reference_to_expression(ref); */
1134 
1135  /* if(!expression_pointer_p(ex)) */
1136  /* pt = make_points_to(l, r, a, make_descriptor_none()); */
1137  /* else */
1138  /* pt = make_points_to(l, points_to_sink(i), a, make_descriptor_none()); */
1139  /* } */
1140 
1141  /* if(!points_to_undefined_p(pt)) */
1142  /* set_add_element(gen_must_cps, gen_must_cps, (void*) pt); */
1143 
1146  bool t_to_be_freed = false;
1147  type t = points_to_reference_to_type(ref, &t_to_be_freed);
1148  /* if(reference_unbounded_indices_p(ref)) */
1149  /* a = make_approximation_may(); */
1150  if(!pointer_type_p(t))
1151  pt = make_points_to(l, r, a, make_descriptor_none());
1152  else
1154 
1155  if (t_to_be_freed) free_type(t);
1156  }
1157  if(!points_to_undefined_p(pt))
1158  set_add_element(gen_must_cps, gen_must_cps, (void*) pt);
1159  }
1160  }
1161  }
1162  }
1163 
1164  return gen_must_cps;
1165 }

References array_entity_p(), cell_any_reference(), equal_must_vreference(), FOREACH, free_type(), gen_length(), generic_effects_reset_all_methods(), int, make_approximation_exact(), make_approximation_may(), make_descriptor_none(), make_points_to(), pointer_type_p(), points_to_equal_p(), points_to_rank(), points_to_reference_to_type(), points_to_sink, points_to_source, points_to_undefined, points_to_undefined_p, ref, reference_variable, set_add_element(), SET_FOREACH, set_generic_make(), set_methods_for_proper_simple_effects(), set_private, simple_cell_to_store_independent_cell(), and unique_location_cell_p().

Referenced by gen_must_set().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ gen_must_set()

set gen_must_set ( list  L,
list  R,
set  in_must,
bool address_of_p 
)

if len > 1 we must iterate over in_must and change all points-to relations having L as lhs into may relations

Parameters
in_mustn_must
address_of_pddress_of_p

Definition at line 908 of file constant-path-utils.c.

909 {
914  int len = (int) gen_length(L);
915 
916  /* if len > 1 we must iterate over in_must and change all points-to
917  relations having L as lhs into may relations */
918  if(len > 1){
919  FOREACH(cell, l, L){
920  SET_FOREACH(points_to, pt, in_must){
925  set_add_element(gen_must1, gen_must1, (void*)npt);
926  }
927  }
928  }
929  }
930 
931  bool error_p = false; // generate an error for dereferencing an undefined pointer
932  int lc = (int) gen_length(L);
933  FOREACH(cell, l, L){
934  // Can the lhs be accessed?
936  entity lv = reference_variable(lr);
937  bool null_p = entity_null_locations_p(lv);
938  bool nowhere_p = entity_typed_nowhere_locations_p(lv)
940  string bug = null_p? "a null" : "";
941  bug = nowhere_p? "an undefined" : "";
942  if(null_p || nowhere_p) {
943  // No: two options; either a user_error() for dereferencing an
944  // unitialized pointer or a conversion to anywhere, typed or not
945  if(lc==1) {
946  if(error_p)
947  pips_user_error("Dereferencing of %s pointer.\n", bug);
948  else {
949  pips_user_warning("Dereferencing of %s pointer.\n", bug);
950  }
951  }
952  else {
953  pips_user_warning("Possible dereferencing of %s pointer.\n", bug);
954  }
955  type t = entity_type(lv);
957  set must_l = gen_must_constant_paths(nl, R, in_must, address_of_p, len);
958  set_union(gen_must2, gen_must2, must_l);
959  }
960  else {
961  set must_l = gen_must_constant_paths(l, R, in_must, address_of_p, len);
962  set_union(gen_must2, gen_must2, must_l);
963  // FI: shouldn't must_l be freed?
964  }
965  }
966  set_union(gen_must2, gen_must2,gen_must1);
967 
968  return gen_must2;
969 }
set gen_must_constant_paths(cell l, list R, set in_must, bool *address_of_p, int Lc)
Build a set of arcs from cell l towards cells in list R if *address_p is true, or towards cells point...
bool points_to_compare_cell(cell, cell)

References cell_any_reference(), entity_nowhere_locations_p(), entity_null_locations_p(), entity_type, entity_typed_nowhere_locations_p(), FOREACH, gen_length(), gen_must_constant_paths(), int, make_anywhere_points_to_cell(), make_approximation_may(), make_descriptor_none(), make_points_to(), pips_user_error, pips_user_warning, points_to_compare_cell(), points_to_equal_p(), points_to_rank(), points_to_sink, points_to_source, reference_variable, set_add_element(), SET_FOREACH, set_generic_make(), set_private, and set_union().

+ Here is the call graph for this function:

◆ generic_points_to_cells_translation()

list generic_points_to_cells_translation ( list  cl,
set  binding,
entity  f,
bool  exact_p 
)

Allocate a new list with the translations of the cells in cl, when their translation make sense.

Effects on copied parameters are discarded.

If exact_p is required, translate only cells that can be translated exactly.

Parameters
cll
bindinginding
exact_pxact_p

Definition at line 2286 of file interprocedural.c.

2287 {
2288  list tcl = NIL;
2289  FOREACH(CELL, c, cl) {
2291  entity v = reference_variable(r);
2292  list ptcl = NIL;
2293  if(formal_parameter_p(v)) {
2295  if(array_type_p(t)) {
2296  // Passing by reference
2297  ptcl = points_to_cell_translation(c, binding, f);
2298  }
2299  else {
2300  // Passing by value: no need to translate information about a copy
2301  ;
2302  }
2303  }
2304  else
2305  ptcl = points_to_cell_translation(c, binding, f);
2306  if(exact_p && gen_length(ptcl)>1)
2307  gen_free_list(ptcl);
2308  else
2309  tcl = gen_nconc(tcl, ptcl);
2310  }
2311  return tcl;
2312 }

References array_type_p(), CELL, cell_any_reference(), entity_basic_concrete_type(), f(), FOREACH, formal_parameter_p(), gen_free_list(), gen_length(), gen_nconc(), NIL, points_to_cell_translation(), and reference_variable.

Referenced by points_to_cells_exact_translation(), and points_to_cells_translation().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generic_points_to_set_to_stub_cell_list()

list generic_points_to_set_to_stub_cell_list ( entity  f,
set  s,
list  osl 
)

Add cells referencing a points-to stub found in parameter "s" are copied and added to list "osl".

The stubs are returned as cells not as entities.

New cells are allocated. No sharing is created between parameter "s" and result "sl".

Parameters
oslsl

Definition at line 2829 of file interprocedural.c.

2830 {
2831  list sl = osl;
2832  SET_FOREACH(points_to, pt, s) {
2833  cell sink = points_to_sink(pt);
2834  reference r1 = cell_any_reference(sink);
2835  entity e1 = reference_variable(r1);
2836  if( ( (entity_undefined_p(f) && entity_stub_sink_p(e1))
2837  || stub_entity_of_module_p(e1, f) )
2838  && !points_to_cell_in_list_p(sink, sl) )
2839  sl = CONS(CELL, copy_cell(sink), sl);
2840 
2841  cell source = points_to_source(pt);
2842  reference r2 = cell_any_reference(source);
2843  entity e2 = reference_variable(r2);
2844  if( ( (entity_undefined_p(f) && entity_stub_sink_p(e2))
2845  || stub_entity_of_module_p(e2, f) )
2846  && !points_to_cell_in_list_p(source, sl) )
2847  sl = CONS(CELL, copy_cell(source), sl);
2848  }
2849 
2852  return sl;
2853 }
void gen_sort_list(list l, gen_cmp_func_t compare)
Sorts a list of gen_chunks in place, to avoid allocations...
Definition: list.c:796
int(* gen_cmp_func_t)(const void *, const void *)
Definition: newgen_types.h:114
bool points_to_compare_ptr_cell(const void *, const void *)
return(s1)

References CELL, cell_any_reference(), CONS, copy_cell(), entity_stub_sink_p(), entity_undefined_p, f(), gen_sort_list(), ifdebug, points_to_cell_in_list_p(), points_to_compare_ptr_cell(), points_to_sink, points_to_source, print_points_to_cells, reference_variable, SET_FOREACH, and stub_entity_of_module_p().

Referenced by points_to_set_to_module_stub_cell_list(), and points_to_set_to_stub_cell_list().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generic_points_to_source_to_sinks()

list generic_points_to_source_to_sinks ( cell  source,
pt_map  ptm,
bool  fresh_p,
bool  strict_p,
bool  all_p,
bool  effective_p 
)

Build the sinks of source "source" according to the points-to graphs.

If "source" is not found in the graph, return an empty list "sinks". If "fresh_p", allocate copies. If not, return pointers to the destination vertices in "ptm".

It is not clear how much the abstract address lattice must be used to retrieve sinks... If source = a[34], clearly a[*] is an OK equivalent source if a[34] is not a vertex of "ptm".

If !strict_p, "a[34]" is considered a source for "a[*]". This should always be the case. So strict_p should always be false.

If all_p, look for all possible sinks. For instance, if a[34] and a[*] have different sinks, return their union. If !all_p, stop the search if a[34] has sinks. This should now be obsolete thanks to exact_p. So all_p should always be true.

effective_p: you only want sinks that are not NULL and not UNDEFINED/NOWHERE. For instance, because you know you will dereference it.

Note: we must also take into account the approximations of the arcs...

This is a key point of Amira's dissertation, but it has not been handled properly yet...

  1. See if cell "source" is the starting vertex of a points-to arc.
  2. Much harder... See if source is contained in one of the many abstract sources. Step 1 is subsumed by Step 2... but is much faster.
  3. Much harder... See if source contains one of the many abstract sources.
Parameters
sourceource
ptmtm
fresh_presh_p
strict_ptrict_p
all_pll_p
effective_pffective_p

Definition at line 1823 of file points_to_set.c.

1828 {
1829  list sinks = NIL;
1830  set pts = points_to_graph_set(ptm);
1831 
1832  /* 1. See if cell "source" is the starting vertex of a points-to arc. */
1833  bool exact_p = false;
1834  SET_FOREACH( points_to, pt, pts) {
1835  if(cell_equal_p(source, points_to_source(pt))) {
1836  cell sink = points_to_sink(pt);
1837  if(!effective_p || (!nowhere_cell_p(sink) && !null_cell_p(sink))) {
1839  cell sc = fresh_p? copy_cell(sink) : sink;
1840  sinks = CONS(CELL, sc, sinks);
1842  if(exact_p)
1843  pips_internal_error("Two contradictory arcs in ptm\n");
1844  else
1845  exact_p = true;
1846  }
1847  }
1848  }
1849  }
1850 
1851  /* 2. Much harder... See if source is contained in one of the many
1852  abstract sources. Step 1 is subsumed by Step 2... but is much faster. */
1853  if(ENDP(sinks) || (all_p && !exact_p)) {
1854  SET_FOREACH(points_to, pt, pts) {
1855  if(cell_included_p(source, points_to_source(pt))) {
1856  cell sink = points_to_sink(pt);
1857  if(!effective_p || (!nowhere_cell_p(sink) && !null_cell_p(sink))) {
1858  // FI: memory leak forced because of refine_points_to_cell_subscripts
1859  cell sc = (true||fresh_p)? copy_cell(sink) : sink;
1860  // FI->AM: if "source" is stricly included in
1861  // "points_to_source(pt)", the subscript expression of sc
1862  // might have to be cleaned up
1863  //
1864  // Which implies to allocate a new copy of sc no matter what
1865  // fresh_p prescribes...
1867  if(!points_to_cell_in_list_p(sc, sinks))
1868  sinks = CONS(CELL, sc, sinks);
1869  }
1870  }
1871  }
1872  }
1873 
1874  /* 3. Much harder... See if source contains one of the many
1875  abstract sources. */
1876  if((ENDP(sinks) && !strict_p) || all_p) {
1877  SET_FOREACH(points_to, pt, pts) {
1878  if(cell_included_p(points_to_source(pt), source)) {
1879  cell sink = points_to_sink(pt);
1880  if(!effective_p || (!nowhere_cell_p(sink) && !null_cell_p(sink))) {
1881  // FI: memory leak forced because of refine_points_to_cell_subscripts
1882  cell sc = (true||fresh_p)? copy_cell(sink) : sink;
1883  // FI->AM: if "source" is stricly included in
1884  // "points_to_source(pt)", the subscript expression of sc
1885  // might have to be cleaned up
1886  //
1887  // Which implies to allocate a new copy of sc no matter what
1888  // fresh_p prescribes...
1890  if(!points_to_cell_in_list_p(sc, sinks))
1891  sinks = CONS(CELL, sc, sinks);
1892  }
1893  }
1894  }
1895  }
1896 
1897  return sinks;
1898 }
bool cell_included_p(cell, cell)
Check that all memory locations denoted by cell "c1" are included in cell "c2".
Definition: effects.c:1294
#define approximation_must_p(x)
Definition: effects.h:366
static void refine_points_to_cell_subscripts(cell sc, cell ec, cell fc)
If the subscripts of the effective cell source "ec" are more precise than the subscripts of the cell ...

References approximation_exact_p, approximation_must_p, CELL, cell_equal_p(), cell_included_p(), CONS, copy_cell(), ENDP, NIL, nowhere_cell_p(), null_cell_p(), pips_internal_error, points_to_approximation, points_to_cell_in_list_p(), points_to_graph_set, points_to_sink, points_to_source, refine_points_to_cell_subscripts(), and SET_FOREACH.

Referenced by generic_points_to_sources_to_sinks(), points_to_source_to_any_sinks(), points_to_source_to_effective_sinks(), points_to_source_to_sinks(), and points_to_source_to_some_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generic_points_to_sources_to_sinks()

list generic_points_to_sources_to_sinks ( list  sources,
pt_map  ptm,
bool  fresh_p,
bool  effective_p 
)

Build the union of the sinks of cells in "sources" according to the points-to graphs "ptm".

Allocate new cells if "fresh_p". No specific order in the returned list.

If effective_p, eliminate NULL and NOWHERE/UNDEFINED as targets

Parameters
sourcesources
ptmtm
fresh_presh_p
effective_pffective_p

Definition at line 2050 of file points_to_set.c.

2051 {
2052  list sinks = NIL;
2053  FOREACH(CELL, source, sources) {
2054  list subl = generic_points_to_source_to_sinks(source, ptm, fresh_p, true, false, effective_p);
2055  sinks = gen_nconc(sinks, subl); // to ease debugging... Could be CONS
2056  }
2057 
2058  return sinks;
2059 }
list generic_points_to_source_to_sinks(cell source, pt_map ptm, bool fresh_p, bool strict_p, bool all_p, bool effective_p)
Build the sinks of source "source" according to the points-to graphs.

References CELL, FOREACH, gen_nconc(), generic_points_to_source_to_sinks(), and NIL.

Referenced by points_to_sources_to_effective_sinks(), and points_to_sources_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generic_remove_unreachable_vertices_in_points_to_graph()

pt_map generic_remove_unreachable_vertices_in_points_to_graph ( pt_map  ptg,
int  code,
bool  verbose_p 
)

Remove arcs in points-to graph "ptg" when they start from a stub cell that is not reachable.

Points-to graph "ptg" is modified by side-effects and returned.

This clean-up should be performed each time a projection is performed, and even potentially, each time an arc is removed.

Note: see also freed_pointer_to_points_to() for a recursive implementation of the arc elimination. The current clean-up is not recursive. This function should be called repeatedly till the results converge to a fix point...

Find arcs whose origin vertex is an unreachable stub.

Remove arcs in ual.

Parameters
ptgtg
verbose_perbose_p

Definition at line 3414 of file points_to_set.c.

3415 {
3416  set ptg_s = points_to_graph_set(ptg);
3417  list ual = NIL; // unreachable arc list
3418 
3419  pips_assert("pts is consistent before unreachable arc removal",
3420  consistent_pt_map_p(ptg));
3421 
3422  /* Find arcs whose origin vertex is an unreachable stub. */
3423  SET_FOREACH(points_to, pt, ptg_s) {
3424  cell source = points_to_source(pt);
3425  reference r = cell_any_reference(source);
3426  entity e = reference_variable(r);
3427  if(code == 3
3428  || ((code & 1) == 1 && entity_stub_sink_p(e))
3429  || ((code & 2) == 2 && entity_heap_location_p(e))) {
3430  // list S = points_to_source_to_sinks(source, ptg);
3431  list S = points_to_sink_to_sources(source, ptg, false);
3432  if(ENDP(S)) {
3433  if(verbose_p)
3434  pips_user_warning("Unreachable cell \"%s\" removed.\n",
3435  points_to_cell_to_string(source));
3436  ual = CONS(POINTS_TO, pt, ual);
3437  }
3438  gen_free_list(S);
3439  }
3440  }
3441 
3442  /* Remove arcs in ual. */
3443  FOREACH(POINTS_TO, pt, ual) {
3444  remove_arc_from_pt_map(pt, ptg);
3445  }
3446 
3447  //gen_full_free_list(ual);
3448 
3449  pips_assert("pts is consistent after unreachable arc removal",
3450  consistent_pt_map_p(ptg));
3451 
3452  return ptg;
3453 }
string points_to_cell_to_string(cell c)
list points_to_sink_to_sources(cell sink, pt_map ptm, bool fresh_p)
Build the sources of sink "sink" according to the points-to graphs.

References cell_any_reference(), CONS, consistent_pt_map_p, ENDP, entity_heap_location_p(), entity_stub_sink_p(), FOREACH, gen_free_list(), NIL, pips_assert, pips_user_warning, POINTS_TO, points_to_cell_to_string(), points_to_graph_set, points_to_sink_to_sources(), points_to_source, reference_variable, remove_arc_from_pt_map, and SET_FOREACH.

Referenced by remove_unreachable_heap_vertices_in_points_to_graph(), remove_unreachable_stub_vertices_in_points_to_graph(), and remove_unreachable_vertices_in_points_to_graph().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generic_stub_source_to_sinks()

list generic_stub_source_to_sinks ( cell  source,
pt_map  pts,
bool  array_p,
bool  fresh_p 
)

The source type cannot contain a pointer field: for instance, int or char

Parameters
sourceource
ptsts
array_prray_p
fresh_presh_p

Definition at line 1177 of file points_to_set.c.

1178 {
1179  list sinks = NIL;
1180  bool null_initialization_p =
1181  get_bool_property("POINTS_TO_NULL_POINTER_INITIALIZATION");
1182  //type ost = ultimate_type(entity_type(v));
1183  bool to_be_freed; // FI: memory leak for the time being
1184  type rt = cell_to_type(source, &to_be_freed); // reference type
1185  if(pointer_type_p(rt)) {
1186  // bool array_p = array_type_p(rt); FI: always false if pointer_type_p(rt)
1187  type nst = type_to_pointed_type(rt);
1188  points_to pt = create_k_limited_stub_points_to(source, nst, array_p, pts);
1189  pts = add_arc_to_pt_map_(pt, pts);
1191  sinks = source_to_sinks(source, pts, fresh_p);
1192  if(null_initialization_p) {
1193  // FI: I'm lost here... both with the meaning of null
1194  // initialization_p and with the insertion of a
1195  // corresponding arc in "pts"
1196  list ls = null_to_sinks(source, pts);
1197  sinks = gen_nconc(ls, sinks);
1198  }
1199  }
1200  else if(struct_type_p(rt)) {
1201  // FI FI FI - to be really programmed with the field type
1202  // FI->AM: I am really confused about what I am doing here...
1203  variable vrt = type_variable(rt);
1204  basic b = variable_basic(vrt);
1205  entity se = basic_derived(b);
1206  type st = entity_type(se);
1207  pips_assert("se is an internal struct", type_struct_p(st));
1208  list fl = type_struct(st);
1209  FOREACH(ENTITY, f, fl) {
1210  type ft = entity_type(f);
1211  type uft = ultimate_type(ft);
1212  bool array_p = array_type_p(ft); // not consistent with ultimate_type()
1213  points_to pt = create_k_limited_stub_points_to(source, uft, array_p, pts);
1214  pts = add_arc_to_pt_map_(pt, pts);
1216  sinks = source_to_sinks(source, pts, fresh_p);
1217  }
1218  }
1219  else if(array_type_p(rt)) {
1220  if(array_of_pointers_type_p(rt)) {
1221  cell ns = copy_cell(source);
1225  type nspt = type_to_pointed_type(nst);
1226  bool array_p = true;
1227  points_to pt = create_k_limited_stub_points_to(ns, nspt, array_p, pts);
1228  pts = add_arc_to_pt_map_(pt, pts);
1230  // sinks = source_to_sinks(source, pts, false); should be ns instead of source
1232  sinks = source_to_sinks(source, pts, fresh_p);
1233  //sinks = source_to_sinks(ns, pts, false);
1234  //sinks = CONS(CELL, copy_cell(points_to_sink(pt)), NIL);
1235  // FI: this is usually dealt with at the source_to_sinks() level...
1236  list nsinks = points_to_cell_null_initialization(ns, pts);
1237  sinks = gen_nconc(sinks, nsinks);
1238  }
1239  else {
1240  reference r = cell_any_reference(source);
1241  entity v = reference_variable(r);
1242  printf("Entity \"%s\"\n", entity_local_name(v));
1243  pips_internal_error("Not implemented yet.\n");
1244  }
1245  }
1246  else {
1247  /* The source type cannot contain a pointer field: for instance,
1248  int or char */
1249  fprintf(stderr, "Type of source: \"");
1250  print_type(rt);
1251  fprintf(stderr, "\"\n");
1252  pips_internal_error("Type of source is incompatible with a source\n");
1253  }
1254  return sinks;
1255 }
list points_to_cell_null_initialization(cell c, pt_map pts)
If required according to the property, create a new arc from cell "c" to "null".
int printf()

References add_arc_to_points_to_context(), add_arc_to_pt_map_(), array_of_pointers_type_p(), array_type_p(), basic_derived, cell_any_reference(), cell_to_type(), copy_basic(), copy_cell(), copy_points_to(), create_k_limited_stub_points_to(), ENTITY, entity_local_name(), entity_type, f(), FOREACH, fprintf(), gen_nconc(), get_bool_property(), make_type_variable(), make_variable(), NIL, null_to_sinks(), pips_assert, pips_internal_error, pointer_type_p(), points_to_cell_add_unbounded_subscripts(), points_to_cell_add_zero_subscripts(), points_to_cell_null_initialization(), print_type(), printf(), reference_variable, source_to_sinks(), struct_type_p(), type_struct, type_struct_p, type_to_pointed_type(), type_variable, ultimate_type(), and variable_basic.

Referenced by array_stub_source_to_sinks(), and scalar_stub_source_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_heap_counter()

int get_heap_counter ( void  )

Definition at line 1197 of file sinks.c.

1198 {
1199  return ++malloc_counter;
1200 }
static int malloc_counter
Definition: sinks.c:1177

References malloc_counter.

◆ get_heap_statement()

statement get_heap_statement ( void  )

Definition at line 1191 of file sinks.c.

1192 {
1194  return s;
1195 }
static statement malloc_statement
Heap modelling.
Definition: sinks.c:1175

References malloc_statement.

Referenced by flow_sensitive_malloc_to_points_to_sinks().

+ Here is the caller graph for this function:

◆ get_points_to_context()

pt_map get_points_to_context ( void  )

Definition at line 298 of file passes.c.

299 {
300  return points_to_context;
301 }

References points_to_context.

Referenced by generic_points_to_analysis().

+ Here is the caller graph for this function:

◆ get_points_to_graph_from_statement()

pt_map get_points_to_graph_from_statement ( statement  st)
Parameters
stt

Definition at line 3530 of file points_to_set.c.

3530  {
3532 
3533  if (!statement_unstructured_p(st)) {
3534  points_to_list ptl_in = load_pt_to_list(st);
3535  pt_in = new_pt_map();
3536  if(!points_to_list_bottom(ptl_in)) {
3537  pt_in = graph_assign_list(pt_in, points_to_list_list(ptl_in));
3538 
3539  ifdebug(7) {
3540  pips_debug(7, "\n print_points_to_graph \n");
3541  ifdebug(7) print_points_to_graph(pt_in);
3542  pips_debug(7, "in statement : ");
3543  ifdebug(7) print_statement(st);
3544  }
3545  }
3546  }
3547 
3548  return pt_in;
3549 }
points_to_list load_pt_to_list(statement)
bool statement_unstructured_p(statement)
Definition: statement.c:369
#define points_to_graph_undefined
#define points_to_list_list(x)
#define points_to_list_bottom(x)
pt_map graph_assign_list(pt_map ptm, list l)
FI: I add functions dealing with points_to_graph variable, i.e.
#define print_points_to_graph(x)
Definition: print.c:383
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98

References graph_assign_list(), ifdebug, load_pt_to_list(), new_pt_map, pips_debug, points_to_graph_undefined, points_to_list_bottom, points_to_list_list, print_points_to_graph, print_statement(), and statement_unstructured_p().

+ Here is the call graph for this function:

◆ get_printed_points_to_list()

statement_points_to get_printed_points_to_list ( void  )

◆ global_source_to_sinks()

list global_source_to_sinks ( cell  source,
pt_map  pts,
bool  fresh_p 
)

Add an implicit dimension for pointer arithmetic

Add these new arcs to the context

Do we have to ignore an initialization?

Parameters
sourceource
ptsts
fresh_presh_p

Definition at line 1438 of file points_to_set.c.

1439 {
1440  bool null_initialization_p =
1441  get_bool_property("POINTS_TO_NULL_POINTER_INITIALIZATION");
1442  reference r = cell_any_reference(source);
1443  entity v = reference_variable(r);
1444  type t = entity_type(v);
1445  list sinks = NIL;
1447  type st = type_undefined;
1449 
1450  bool strict_p = get_bool_property("POINTS_TO_STRICT_POINTER_TYPES");
1451  if(scalar_type_p(ist) && !strict_p) {
1452  /* Add an implicit dimension for pointer arithmetic */
1453  st = type_to_array_type(ist);
1454  }
1455  else
1456  st = copy_type(ist);
1457 
1458  if(const_variable_p(v)) {
1460  sinks = expression_to_points_to_sinks(init, pts);
1462  /* Add these new arcs to the context */
1463  bool exact_p = gen_length(sinks)==1;
1464  FOREACH(CELL, sink, sinks) {
1465  cell nsource = copy_cell(source);
1466  cell nsink = copy_cell(sink);
1467  approximation na = exact_p? make_approximation_exact():
1469  points_to npt = make_points_to(nsource, nsink, na,
1471  pts = add_arc_to_pt_map_(npt, pts);
1473  }
1474  }
1475  else {
1476  /* Do we have to ignore an initialization? */
1477  value val = entity_initial(v);
1478  if(!value_unknown_p(val))
1479  pips_user_warning("Initialization of global variable \"%s\" is ignored "
1480  "because the \"const\" qualifier is not used.\n",
1481 
1482  entity_user_name(v));
1483  //bool array_p = array_type_p(st);
1484  bool array_p = array_type_p(t); // array_p is related to the source
1485  pt = create_k_limited_stub_points_to(source, st, array_p, pts);
1486 
1487  // FI: cut-and-pasted from line 945
1488  if(null_initialization_p) {
1491  }
1492  pts = add_arc_to_pt_map_(pt, pts);
1494  sinks = source_to_sinks(source, pts, fresh_p);
1495  if(null_initialization_p){
1496  list ls = null_to_sinks(source, pts);
1497  sinks = gen_nconc(ls, sinks);
1498  }
1499  }
1500 
1501  return sinks;
1502 }
bool const_variable_p(entity)
Definition: variable.c:1687
#define value_unknown_p(x)
Definition: ri.h:3077

References add_arc_to_points_to_context(), add_arc_to_pt_map_(), array_type_p(), CELL, cell_any_reference(), const_variable_p(), copy_cell(), copy_points_to(), copy_type(), create_k_limited_stub_points_to(), entity_basic_concrete_type(), entity_initial, entity_type, entity_user_name(), expression_to_points_to_sinks(), FOREACH, free_approximation(), free_expression(), gen_length(), gen_nconc(), get_bool_property(), init, make_approximation_exact(), make_approximation_may(), make_descriptor_none(), make_points_to(), NIL, null_to_sinks(), pips_user_warning, points_to_approximation, points_to_undefined, reference_variable, scalar_type_p(), source_to_sinks(), type_to_array_type(), type_to_pointed_type(), type_undefined, value_unknown_p, and variable_initial_expression().

Referenced by source_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ graph_assign_list()

pt_map graph_assign_list ( pt_map  ptm,
list  l 
)

FI: I add functions dealing with points_to_graph variable, i.e.

pt_map

Parameters
ptmtm

Definition at line 3170 of file points_to_set.c.

3171 {
3172  bool b = points_to_graph_bottom(ptm);
3173  if(b) {
3174  // FI: I am in trouble here; what should be the semantics?
3175  pips_debug(1, "Impossible initialization of a bottom graph\n");
3176  pips_internal_error("Mismanaged points-to graph\n");
3177  }
3178  else
3180  return ptm;
3181 }
set set_assign_list(set, const list)
assigns a list contents to a set all duplicated elements are lost
Definition: set.c:474

References pips_debug, pips_internal_error, points_to_graph_bottom, points_to_graph_set, and set_assign_list().

Referenced by generic_points_to_analysis(), get_points_to_graph_from_statement(), and statement_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ init_heap_model()

void init_heap_model ( statement  s)

Definition at line 1179 of file sinks.c.

1180 {
1181  malloc_statement = s;
1182  malloc_counter = 0;
1183 }

References malloc_counter, and malloc_statement.

Referenced by statement_to_points_to().

+ Here is the caller graph for this function:

◆ init_points_to_analysis()

bool init_points_to_analysis ( char *  module_name)

Properties

Parameters
module_nameodule_name

Definition at line 483 of file passes.c.

484 {
485  entity module;
486  type t;
487  list pt_list = NIL, dl = NIL;
488  set pts_to_set = set_generic_make(set_private,
490  set formal_set = set_generic_make(set_private,
494 
495  t = entity_type(module);
496 
497  debug_on("POINTS_TO_DEBUG_LEVEL");
498 
499  pips_debug(1, "considering module \"%s\"\n", module_name);
500 
501  /* Properties */
502  if(get_bool_property("ALIASING_ACROSS_FORMAL_PARAMETERS"))
503  pips_user_warning("Property ALIASING_ACROSS_FORMAL_PARAMETERS"
504  " is ignored\n");
505  if(get_bool_property("ALIASING_ACROSS_TYPES"))
506  pips_user_warning("Property ALIASING_ACROSS_TYPES"
507  " is ignored\n");
508  if(get_bool_property("ALIASING_INSIDE_DATA_STRUCTURE"))
509  pips_user_warning("Property ALIASING_INSIDE_DATA_STRUCTURE"
510  " is ignored\n");
511 
512  if(type_functional_p(t)){
514 
515  FOREACH(ENTITY, fp, dl) {
516  if(formal_parameter_p(fp)) {
517  reference r = make_reference(fp, NIL);
518  cell c = make_cell_reference(r);
519  formal_set = formal_points_to_parameter(c);
520  pts_to_set = set_union(pts_to_set, pts_to_set,
521  formal_set);
522  }
523  }
524 
525  }
526  else
527  pips_user_error("The module %s is not a function.\n", module_name);
528 
529  pt_list = set_to_sorted_list(pts_to_set,
530  (int(*)
531  (const void*,const void*))
533  points_to_list init_pts_to_list = make_points_to_list(false, pt_list);
534  points_to_list_consistent_p(init_pts_to_list);
536  (DBR_INIT_POINTS_TO_LIST, module_name, init_pts_to_list);
538  set_clear(pts_to_set);
539  set_clear(pts_to_set);
540  set_free(pts_to_set);
541  set_free(formal_set);
542  debug_off();
543 
544  bool good_result_p = true;
545  return (good_result_p);
546 }
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66
#define debug_on(env)
Definition: misc-local.h:157
#define debug_off()
Definition: misc-local.h:160
set set_clear(set)
Assign the empty set to s s := {}.
Definition: set.c:326
set formal_points_to_parameter(cell)
We want a recursive descent on the type of the formal parameter, once we found a pointer type we begu...

References code_declarations, DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, ENTITY, entity_initial, entity_type, FOREACH, formal_parameter_p(), formal_points_to_parameter(), get_bool_property(), get_current_module_entity(), make_cell_reference(), make_points_to_list(), make_reference(), module, module_name(), module_name_to_entity(), NIL, pips_debug, pips_user_error, pips_user_warning, points_to_compare_cells(), points_to_equal_p(), points_to_list_consistent_p(), points_to_rank(), reset_current_module_entity(), set_clear(), set_current_module_entity(), set_free(), set_generic_make(), set_private, set_to_sorted_list(), set_union(), type_functional_p, and value_code.

+ Here is the call graph for this function:

◆ init_points_to_context()

void init_points_to_context ( pt_map  init)
Parameters
initnit

Definition at line 151 of file passes.c.

152 {
153  pips_assert("points_to_context is undefined",
156 }

References full_copy_pt_map(), init, pips_assert, points_to_context, and pt_map_undefined_p.

Referenced by generic_points_to_analysis().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ init_printed_points_to_list()

void init_printed_points_to_list ( void  )

◆ init_statement_points_to_context()

void init_statement_points_to_context ( void  )

Definition at line 90 of file statement.c.

91 {
92  pips_assert("statement_points_to_context is undefined",
96 }
stack stack_make(int, int, int)
allocation
Definition: stack.c:246
#define stack_undefined_p(s)
Definition: newgen_stack.h:56
static stack current_statement_points_to_context
Definition: statement.c:88
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362

References current_statement_points_to_context, pips_assert, points_to_graph_domain, stack_make(), stack_undefined_p, statement_domain, and statement_points_to_context.

Referenced by generic_points_to_analysis().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ initial_points_to()

bool initial_points_to ( char *  name)

Retrieve points-to that are statically initialized, especially in compilation units.

At least, useful for debugging

Could we retrieve initializations of static variables?

Parameters
nameame

Definition at line 582 of file passes.c.

583 {
586 
587  debug_on("POINTS_TO_DEBUG_LEVEL");
588 
589  /* At least, useful for debugging */
591  //set_current_module_statement( (statement)
592  // db_get_memory_resource(DBR_CODE, name, true));
593 
594  if(compilation_unit_p(name)) {
595  points_to_list ptl_out =
596  (points_to_list) db_get_memory_resource(DBR_POINTS_TO_OUT, name, true);
597  ptl_init = copy_points_to_list(ptl_out);
598  }
599  else {
600  /* Could we retrieve initializations of static variables? */
601  ptl_init = make_points_to_list(true, NIL);
602  }
603 
604  DB_PUT_MEMORY_RESOURCE(DBR_INITIAL_POINTS_TO, strdup(name), (char*) ptl_init);
605 
607  //reset_current_module_statement();
608 
609  debug_off();
610  return true;
611 }
points_to_list copy_points_to_list(points_to_list p)
POINTS_TO_LIST.
bool compilation_unit_p(const char *module_name)
The names of PIPS entities carry information about their nature.
Definition: entity_names.c:56
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755
struct _newgen_struct_points_to_list_ * points_to_list

References compilation_unit_p(), copy_points_to_list(), db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, make_points_to_list(), module, module_name_to_entity(), NIL, points_to_list_undefined, reset_current_module_entity(), set_current_module_entity(), and strdup().

+ Here is the call graph for this function:

◆ insensitive_malloc_to_points_to_sinks()

list insensitive_malloc_to_points_to_sinks ( expression  e)

FI->AM: what's the difference with the previous option? Reference to your dissertation?

Definition at line 1312 of file sinks.c.

1313 {
1314  list m = NIL;
1315  // FI: I'm waiting for this error to happen
1316  pips_internal_error("Not implemented yet?");
1318  return m;
1319 }
list flow_sensitive_malloc_to_points_to_sinks(expression e)
Definition: sinks.c:1321

References flow_sensitive_malloc_to_points_to_sinks(), NIL, and pips_internal_error.

Referenced by malloc_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ instruction_to_points_to()

pt_map instruction_to_points_to ( instruction  i,
pt_map  pt_in 
)

See points_to_statement()

pt_in is modified by side-effects and returned

Parameters
pt_int_in

Definition at line 370 of file statement.c.

371 {
372  pt_map pt_out = pt_in;
373  tag it = instruction_tag(i);
374  switch(it) {
377  pt_out = sequence_to_points_to(seq, pt_in);
378  break;
379  }
380  case is_instruction_test: {
381  test t = instruction_test(i);
382  pt_out = test_to_points_to(t, pt_in);
383  break;
384  }
385  case is_instruction_loop: {
386  loop l = instruction_loop(i);
387  pt_out = loop_to_points_to(l, pt_in);
388  break;
389  }
392  pt_out = whileloop_to_points_to(wl, pt_in);
393  break;
394  }
395  case is_instruction_goto: {
396  pips_internal_error("Go to instructions should have been removed "
397  "before the analysis is started\n");
398  break;
399  }
400  case is_instruction_call: {
401  call c = instruction_call(i);
402  if(points_to_graph_bottom(pt_in))
403  pt_out = pt_in;
404  else
405  pt_out = call_to_points_to(c, pt_out, NIL, true);
406  break;
407  }
410  pt_out = unstructured_to_points_to(u, pt_in);
411  break;
412  }
414  pips_internal_error("Not implemented\n");
415  break;
416  }
417  case is_instruction_forloop: {
419  pt_out = forloop_to_points_to(fl, pt_in);
420  break;
421  }
424  if(points_to_graph_bottom(pt_in))
425  pt_out = pt_in;
426  else
427  pt_out = expression_to_points_to(e, pt_in, true);
428  break;
429  }
430  default:
431  pips_internal_error("Unexpected instruction tag %d\n", it);
432  }
433  return pt_out;
434 }
pt_map loop_to_points_to(loop l, pt_map pt_in)
FI: I assume that pointers and pointer arithmetic cannot appear in a do loop, "do p=q,...
Definition: statement.c:573
pt_map whileloop_to_points_to(whileloop wl, pt_map pt_in)
Definition: statement.c:604
pt_map sequence_to_points_to(sequence seq, pt_map pt_in)
Definition: statement.c:436
pt_map forloop_to_points_to(forloop fl, pt_map pt_in)
Definition: statement.c:974
pt_map unstructured_to_points_to(unstructured u, pt_map pt_in)
Definition: statement.c:958
pt_map test_to_points_to(test t, pt_map pt_in)
Computing the points-to information after a test.
Definition: statement.c:496
#define instruction_loop(x)
Definition: ri.h:1520
@ is_instruction_goto
Definition: ri.h:1473
@ is_instruction_unstructured
Definition: ri.h:1475
@ is_instruction_whileloop
Definition: ri.h:1472
@ is_instruction_expression
Definition: ri.h:1478
@ is_instruction_test
Definition: ri.h:1470
@ is_instruction_multitest
Definition: ri.h:1476
@ is_instruction_call
Definition: ri.h:1474
@ is_instruction_sequence
Definition: ri.h:1469
@ is_instruction_forloop
Definition: ri.h:1477
@ is_instruction_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#define instruction_sequence(x)
Definition: ri.h:1514
#define instruction_forloop(x)
Definition: ri.h:1538
#define instruction_expression(x)
Definition: ri.h:1541
#define instruction_whileloop(x)
Definition: ri.h:1523
#define instruction_call(x)
Definition: ri.h:1529
#define instruction_test(x)
Definition: ri.h:1517
#define instruction_unstructured(x)
Definition: ri.h:1532

References call_to_points_to(), expression_to_points_to(), forloop_to_points_to(), instruction_call, instruction_expression, instruction_forloop, instruction_loop, instruction_sequence, instruction_tag, instruction_test, instruction_unstructured, instruction_whileloop, is_instruction_call, is_instruction_expression, is_instruction_forloop, is_instruction_goto, is_instruction_loop, is_instruction_multitest, is_instruction_sequence, is_instruction_test, is_instruction_unstructured, is_instruction_whileloop, loop_to_points_to(), NIL, pips_internal_error, points_to_graph_bottom, sequence_to_points_to(), test_to_points_to(), unstructured_to_points_to(), and whileloop_to_points_to().

Referenced by statement_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ internal_pointer_assignment_to_points_to()

pt_map internal_pointer_assignment_to_points_to ( expression  lhs,
expression  rhs,
pt_map  pt_in 
)

Any abstract location of the lhs in L is going to point to any sink of any abstract location of the rhs in R.

New points-to information must be added when a formal parameter is dereferenced.

Store independence must be checked.

Beware of points-to cell lattice: e.g. add a[*] to a[1]

This is not the right place to take the lattice into account. As a result, a[1] woud not kill a[1] anymore. The problem must be taken care of by the equations used in list_assignment_to_points_to().

Make sure all cells in L are pointers: l may be an array of pointers

FI: I am not sure it is useful here because the conversion to an array due to property POINTS_TO_STRICT_POINTER_TYPES may not have occured yet

Retrieve the memory locations that might be reached by the rhs

Update the real "pt_in", the calling context, and "pt_out" by adding new stubs linked directly or indirectly to the formal parameters and global variables if necessary.

We must be in a dead-code portion. If not pleased, adjust properties...

The C99 standard does not preclude the propagation of indeterminate values. It is often used in our test cases when structs are assigned.

clear_pt_map(pt_out); points_to_graph_bottom(pt_out) = true;

Parameters
lhshs
rhshs
pt_int_in

Definition at line 1315 of file expression.c.

1318 {
1319  pt_map pt_out = pt_in;
1320 
1321  pips_assert("pt_out is consistent on entry",
1323 
1324  list L = expression_to_points_to_sources(lhs, pt_out);
1325  /* Beware of points-to cell lattice: e.g. add a[*] to a[1] */
1326  /* This is not the right place to take the lattice into account. As
1327  a result, a[1] woud not kill a[1] anymore. The problem must be
1328  taken care of by the equations used in
1329  list_assignment_to_points_to(). */
1330  // L = points_to_cells_to_upper_bound_points_to_cells(L);
1331 
1332  pips_assert("pt_out is consistent after computing L",
1334 
1335  /* Make sure all cells in L are pointers: l may be an array of pointers */
1336  /* FI: I am not sure it is useful here because the conversion to an
1337  array due to property POINTS_TO_STRICT_POINTER_TYPES may not have
1338  occured yet */
1339  FOREACH(CELL, l, L) {
1340  bool to_be_freed;
1341  type lt = points_to_cell_to_type(l, &to_be_freed);
1342  if(array_type_p(lt)) {
1343  cell nl = copy_cell(l);
1344  // For Pointers/properties04.c, you want a zero subscript for
1345  // the lhs
1347  // FI: since it is an array, most of the pointers will be unchanged
1348  // FI: this should be useless, but it has an impact because
1349  // points-to stubs are computed on demand; see Pointers/assignment12.c
1351  list os = source_to_sinks(nl, pt_out, true);
1352  list nll = CONS(CELL, nl, NIL);
1353  pt_out = list_assignment_to_points_to(nll, os, pt_out);
1354  gen_free_list(nll);
1355  }
1356  if(to_be_freed) free_type(lt);
1357  }
1358 
1359  pips_assert("pt_out is consistent after cells are dangerously updated",
1361 
1362  /* Retrieve the memory locations that might be reached by the rhs
1363  *
1364  * Update the real "pt_in", the calling context, and "pt_out" by
1365  * adding new stubs linked directly or indirectly to the formal
1366  * parameters and global variables if necessary.
1367  */
1368  list R = expression_to_points_to_sinks(rhs, pt_out);
1369 
1370  check_rhs_value_types(lhs, rhs, R);
1371 
1372  pips_assert("pt_out is consistent after computing R",
1374 
1375  if(ENDP(L) || ENDP(R)) {
1376  //pips_assert("Left hand side reference list is not empty.\n", !ENDP(L));
1377  //pips_assert("Right hand side reference list is not empty.\n", !ENDP(R));
1378 
1379  // FI: where do we want to check for dereferencement of
1380  // nowhere/undefined and NULL? Here? Or within
1381  // list_assignment_to_points_to?
1382 
1383  /* We must be in a dead-code portion. If not pleased, adjust properties... */
1384  if(ENDP(L)) {
1386  pips_user_warning("Expression \"%s\" could not be dereferenced at line %d.\n",
1387  expression_to_string(lhs),
1389  else
1390  pips_user_warning("Expression \"%s\" could not be dereferenced.\n",
1391  expression_to_string(lhs));
1392  }
1393  if(ENDP(R)) {
1395  pips_user_warning("Expression \"%s\" could not be dereferenced at line %d.\n",
1396  expression_to_string(rhs),
1398  else
1399  pips_user_warning("Expression \"%s\" could not be dereferenced.\n",
1400  expression_to_string(rhs));
1401  }
1402  clear_pt_map(pt_out);
1403  points_to_graph_bottom(pt_out) = true;
1404  }
1405  else {
1406  // We are in trouble if L=={null} or R=={nowhere)...
1407  // We are not sure what to do if null in L or if nowhere in R
1408  int nR = (int) gen_length(R);
1409  if(nR==1 && nowhere_cell_p(CELL(CAR(R)))) {
1411  pips_user_warning("Assignment of an undefined value to \"%s\" at line %d.\n",
1412  expression_to_string(lhs),
1414  else
1415  pips_user_warning("Assignment of an undefined value to \"%s\".\n",
1416  expression_to_string(lhs));
1417  /* The C99 standard does not preclude the propagation of
1418  indeterminate values. It is often used in our test cases when
1419  structs are assigned.
1420 
1421  clear_pt_map(pt_out);
1422  points_to_graph_bottom(pt_out) = true;
1423  */
1424  pt_out = list_assignment_to_points_to(L, R, pt_out);
1425  }
1426  else
1427  pt_out = list_assignment_to_points_to(L, R, pt_out);
1428  }
1429 
1430  // FI: memory leak(s)?
1431 
1432  pips_assert("pt_out is consistent", consistent_points_to_graph_p(pt_out));
1433 
1434  return pt_out;
1435 }
void check_rhs_value_types(expression lhs, expression rhs __attribute__((unused)), list sinks)
Check that the cells in list "sinks" have types compatible with the expression on the left-hand side,...
Definition: expression.c:1277

References array_type_p(), CAR, CELL, check_rhs_value_types(), clear_pt_map, CONS, consistent_points_to_graph_p(), copy_cell(), ENDP, expression_to_points_to_sinks(), expression_to_points_to_sources(), expression_to_string(), FOREACH, free_type(), gen_free_list(), gen_length(), int, list_assignment_to_points_to(), NIL, nowhere_cell_p(), pips_assert, pips_user_warning, points_to_cell_add_unbounded_subscripts(), points_to_cell_add_zero_subscripts(), points_to_cell_to_type(), points_to_context_statement_line_number(), points_to_graph_bottom, source_to_sinks(), and statement_points_to_context_defined_p().

Referenced by pointer_assignment_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ interprocedural_points_to_analysis()

bool interprocedural_points_to_analysis ( char *  module_name)
Parameters
module_nameodule_name

Definition at line 567 of file passes.c.

References fast_interprocedural_points_to_p, generic_points_to_analysis(), interprocedural_points_to_p, and module_name().

+ Here is the call graph for this function:

◆ interprocedural_points_to_analysis_p()

bool interprocedural_points_to_analysis_p ( void  )

Definition at line 550 of file passes.c.

551 {
553 }

References interprocedural_points_to_p.

Referenced by user_call_to_points_to(), and user_call_to_points_to_sinks().

+ Here is the caller graph for this function:

◆ intraprocedural_points_to_analysis()

bool intraprocedural_points_to_analysis ( char *  module_name)
Parameters
module_nameodule_name

Definition at line 560 of file passes.c.

561 {
565 }

References fast_interprocedural_points_to_p, generic_points_to_analysis(), interprocedural_points_to_p, and module_name().

+ Here is the call graph for this function:

◆ intrinsic_call_condition_to_points_to()

pt_map intrinsic_call_condition_to_points_to ( call  c,
pt_map  in,
bool  true_p 
)

We can break down the intrinsics according to their arity or according to their kinds...

or according to both conditions...

Make sure that all dereferencements are possible? Might be included in intrinsic_call_to_points_to()...

Parameters
inn
true_prue_p

Definition at line 2618 of file expression.c.

2619 {
2620  pt_map out = in;
2621  entity f = call_function(c);
2622 
2625  else if(ENTITY_LOGICAL_OPERATOR_P(f))
2627  else if(ENTITY_ASSIGN_P(f)) {
2628  // Evaluate side effects only once...
2629  out = intrinsic_call_to_points_to(c, in, true_p);
2631  //bool to_be_freed;
2633  //type lhs_t = compute_basic_concrete_type(t);
2634  //if(to_be_freed) free_type(t);
2635  if(pointer_type_p(lhs_t)) {
2638  if(cells_must_point_to_null_p(R) && true_p) {
2639  pips_user_warning("Dead code detected.\n");
2640  clear_pt_map(out);
2641  points_to_graph_bottom(out) = true;
2642  }
2643  else if(cells_may_not_point_to_null_p(R) && !true_p) {
2644  pips_user_warning("Dead code detected.\n");
2645  clear_pt_map(out);
2646  points_to_graph_bottom(out) = true;
2647  }
2648  gen_free_list(R);
2649  }
2650  }
2651  else {
2656  /* Make sure that all dereferencements are possible? Might be
2657  included in intrinsic_call_to_points_to()... */
2658  //bool to_be_freed;
2660  if(pointer_type_p(et)) {
2662  out = condition_to_points_to(p, out, true_p);
2663  }
2664  //if(to_be_freed) free_type(et);
2665  }
2666  // Take care of side effects as in "if(*p++)"
2667  // We must take care of side effects only once...
2668  // Let say, when the condition is evaluated for true
2669  // Not too sure about side effects in condtions
2670  // We might also use "false" as last actual parameter...
2671  // FI: no, this has been taken care of earlier
2672  out = intrinsic_call_to_points_to(c, in, false);
2673  //pips_internal_error("Not implemented yet.\n");
2674  }
2675  pips_assert("out is consistent", points_to_graph_consistent_p(out));
2676  return out;
2677 }
bool cells_may_not_point_to_null_p(list)
Definition: points_to.c:763
bool cells_must_point_to_null_p(list)
Definition: points_to.c:750
pt_map relational_intrinsic_call_condition_to_points_to(call c, pt_map in, bool true_p)
Update the points-to information "in" according to the validity of the condition.
Definition: expression.c:3274
pt_map boolean_intrinsic_call_condition_to_points_to(call c, pt_map in, bool true_p)
Deal with "!", "&&", "||" etc.
Definition: expression.c:2695
#define ENTITY_RELATIONAL_OPERATOR_P(e)
#define ENTITY_DEREFERENCING_P(e)
#define ENTITY_PRE_DECREMENT_P(e)
#define ENTITY_POST_DECREMENT_P(e)
#define ENTITY_POST_INCREMENT_P(e)
#define ENTITY_PRE_INCREMENT_P(e)
#define ENTITY_LOGICAL_OPERATOR_P(e)
Attention : This definition is different with the Fortran Standard where the logical operators are th...

References boolean_intrinsic_call_condition_to_points_to(), call_arguments, call_function, CAR, CDR, cells_may_not_point_to_null_p(), cells_must_point_to_null_p(), clear_pt_map, condition_to_points_to(), dereferencing_to_points_to(), ENTITY_ASSIGN_P, ENTITY_DEREFERENCING_P, ENTITY_LOGICAL_OPERATOR_P, ENTITY_POINT_TO_P, ENTITY_POST_DECREMENT_P, ENTITY_POST_INCREMENT_P, ENTITY_PRE_DECREMENT_P, ENTITY_PRE_INCREMENT_P, ENTITY_RELATIONAL_OPERATOR_P, EXPRESSION, expression_to_points_to_sinks(), f(), gen_free_list(), intrinsic_call_to_points_to(), out, pips_assert, pips_user_warning, pointer_type_p(), points_to_expression_to_concrete_type(), points_to_graph_bottom, points_to_graph_consistent_p(), and relational_intrinsic_call_condition_to_points_to().

Referenced by call_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ intrinsic_call_to_points_to()

pt_map intrinsic_call_to_points_to ( call  c,
pt_map  pt_in,
bool  side_effect_p 
)

Is the dereferenced pointer null or undefined?

Is the dereferenced pointer null or undefined?

|| ENTITY_ASSERT_FAIL_SYSTEM_P(f)

Check the FILE * parameter, when it exists, and the char * format parameter, as well as the char * other actual arguments since they may be dereferenced or not, depending on the format content. With a p, the pointer is not referenced, with a s, it is.

attempt at using an undefined value

Expression a may be dereferenced or not depending on the corresponding format specification, s or p.

We could try to analyze the format when it is available to decide if a dereferencing must occur with s or not.

possible attempt at using an undefined value

it is assumed that only one return is present in any module code because internal returns are replaced by gotos

Parameters
pt_int_in
side_effect_pide_effect_p

Definition at line 411 of file expression.c.

412 {
413  pt_map pt_out = pt_in;
414  entity f = call_function(c);
415 
416  list al = call_arguments(c);
417 
418  //set_methods_for_proper_simple_effects();
419  //list el = call_to_proper_effects(c);
420  //generic_effects_reset_all_methods();
421 
422  pips_debug(5, "intrinsic function \"%s\"\n", entity_name(f));
423 
424  // FI: short term version
425  // pt_out = points_to_intrinsic(statement_undefined, c, f, al, pt_in, el);
426  // return pt_out;
427 
428  // FI: Where should we check that the update is linked to a pointer?
429  // Should we go down because a pointer assignment may be hidden anywhere...
430  // Or have we already taken care of this in call_to_points_to()
431 
432  if(ENTITY_ASSIGN_P(f)) {
433  expression lhs = EXPRESSION(CAR(al));
434  expression rhs = EXPRESSION(CAR(CDR(al)));
435  pt_out = assignment_to_points_to(lhs, rhs, pt_out);
436  }
437  else if (ENTITY_FREE_SYSTEM_P(f)) {
438  expression lhs = EXPRESSION(CAR(al));
439  pt_out = freed_pointer_to_points_to(lhs, pt_out, side_effect_p);
440  }
441  // According to C standard, pointer arithmetics does not change
442  // the targeted object.
443  else if(ENTITY_PLUS_UPDATE_P(f)) {
444  expression lhs = EXPRESSION(CAR(al));
445  type lhst = expression_to_type(lhs);
446  if(pointer_type_p(lhst)) {
447  expression delta = EXPRESSION(CAR(CDR(al)));
448  pt_out = pointer_arithmetic_to_points_to(lhs, delta, pt_out);
449  }
450  free_type(lhst);
451  }
452  else if(ENTITY_MINUS_UPDATE_P(f)) {
453  expression lhs = EXPRESSION(CAR(al));
454  type lhst = expression_to_type(lhs);
455  if(C_pointer_type_p(lhst)) {
456  expression rhs = EXPRESSION(CAR(CDR(al)));
458  expression delta = MakeUnaryCall(um, copy_expression(rhs));
459  pt_out = pointer_arithmetic_to_points_to(lhs, delta, pt_out);
460  free_expression(delta);
461  }
462  free_type(lhst);
463  }
465  expression lhs = EXPRESSION(CAR(al));
466  type lhst = expression_to_type(lhs);
467  if(C_pointer_type_p(lhst) && side_effect_p) {
468  expression delta = int_to_expression(1);
469  pt_out = pointer_arithmetic_to_points_to(lhs, delta, pt_out);
470  free_expression(delta);
471  }
472  free_type(lhst);
473  }
475  expression lhs = EXPRESSION(CAR(al));
476  type lhst = expression_to_type(lhs);
477  if(C_pointer_type_p(lhst)) {
478  expression delta = int_to_expression(-1);
479  pt_out = pointer_arithmetic_to_points_to(lhs, delta, pt_out);
480  free_expression(delta);
481  }
482  free_type(lhst);
483  }
485  /* Is the dereferenced pointer null or undefined? */
486  expression p = EXPRESSION(CAR(al));
487  pt_out = dereferencing_to_points_to(p, pt_out);
488  }
489  else if(ENTITY_PLUS_C_P(f) || ENTITY_MINUS_C_P(f)) {
490  /* Is the dereferenced pointer null or undefined? */
491  expression p1 = EXPRESSION(CAR(al));
492  type t1 = expression_to_type(p1);
493  if(pointer_type_p(t1))
494  pt_out = dereferencing_to_points_to(p1, pt_out);
495  else {
496  expression p2 = EXPRESSION(CAR(CDR(al)));
497  type t2 = expression_to_type(p2);
498  if(pointer_type_p(t2))
499  pt_out = dereferencing_to_points_to(p2, pt_out);
500  }
501  }
502  else if(ENTITY_ASSERT_FAIL_SYSTEM_P(f)) {
503  // FI: no return from assert failure
504  clear_pt_map(pt_out);
505  points_to_graph_bottom(pt_out) = true;
506  }
508  /* || ENTITY_ASSERT_FAIL_SYSTEM_P(f) */) {
509  clear_pt_map(pt_out);
510  points_to_graph_bottom(pt_out) = true;
511  }
512 #if 0
516  || ENTITY_ISOC99_SCANF_P(f)) {
517  FOREACH(EXPRESSION, a, al) {
519  if(C_pointer_type_p(at)) {
520  // For the side-effects on pt_out
521  list sinks = expression_to_points_to_sinks(a, pt_out);
522  if(gen_length(sinks)==1 && nowhere_cell_p(CELL(CAR(sinks)))) {
523  /* attempt at using an undefined value */
524  pips_user_warning("Undefined value \"%s\" is used at line %d.\n",
527 
528  clear_pt_map(pt_out);
529  points_to_graph_bottom(pt_out) = true;
530  }
531  gen_free_list(sinks);
532  // FI: there is no reason to dereference arguments beyond FILE * and format
533  pt_out = dereferencing_to_points_to(a, pt_out);
534  }
535  }
536  // FI: this is already overperformed by the previous loop
537  if(!points_to_graph_bottom(pt_out)
539  || ENTITY_ISOC99_FSCANF_P(f))) {
540  /* stdin, stdout, stderr, fd... must be defined and not NULL */
541  expression a1 = EXPRESSION(CAR(al));
542  if(expression_reference_p(a1)) {
543  expression d =
545  copy_expression(a1));
546  pt_out = expression_to_points_to(d, pt_out, false);
547  free_expression(d);
548  }
549  }
550  }
551 #endif
552  else if(ENTITY_FPRINTF_P(f)
553  || ENTITY_SPRINTF_P(f)
554  || ENTITY_FSCANF_P(f)
555  || ENTITY_SSCANF_P(f)
558  || ENTITY_PRINTF_P(f)
559  || ENTITY_SCANF_P(f)
560  || ENTITY_ISOC99_SCANF_P(f)) {
561  /* Check the FILE * parameter, when it exists, and the char *
562  * format parameter, as well as the char * other actual arguments
563  * since they may be dereferenced or not, depending on the format
564  * content. With a %p, the pointer is not referenced, with a %s,
565  * it is.
566  */
567  int n = 1;
568  int m = 2; // Number of mandatory parameters before the vararg part
569  if(ENTITY_PRINTF_P(f)
570  || ENTITY_SCANF_P(f)
572  m = 1;
573  FOREACH(EXPRESSION, a, al) {
575  if(n<=m) {
576  if(C_pointer_type_p(at)) {
577  // For the side-effects on pt_out
578  list sinks = expression_to_points_to_sinks(a, pt_out);
579  if(gen_length(sinks)==1 && nowhere_cell_p(CELL(CAR(sinks)))) {
580  /* attempt at using an undefined value */
581  pips_user_warning("Undefined value \"%s\" is used at line %d.\n",
584 
585  clear_pt_map(pt_out);
586  points_to_graph_bottom(pt_out) = true;
587  }
588  gen_free_list(sinks);
589  pt_out = dereferencing_to_points_to(a, pt_out);
590  }
591  else {
592  pips_user_error("Argument %d of intrinsics \"%s\" should be a "
593  "pointer and not \"%s\".\n",
594  n,
597  }
598  }
599  else { // The vararg part of the IO call site
600  if(char_star_type_p(at)) {
601  /* Expression a may be dereferenced or not depending on the
602  * corresponding format specification, %s or %p.
603  *
604  * We could try to analyze the format when it is available
605  * to decide if a dereferencing must occur with %s or not.
606  */
607  list sinks = expression_to_points_to_sinks(a, pt_out);
608  if(gen_length(sinks)==1 && nowhere_cell_p(CELL(CAR(sinks)))) {
609  /* possible attempt at using an undefined value */
610  pips_user_warning("Undefined value \"%s\" might be used at line %d.\n",
613 
614  }
615  gen_free_list(sinks);
616  pt_map pt_no = pt_out;
617  pt_map pt_yes = copy_points_to_graph(pt_out);
618  pt_yes = dereferencing_to_points_to(a, pt_yes);
619  pt_out = merge_points_to_graphs(pt_no, pt_yes);
622  free_pt_map(pt_yes), free_pt_map(pt_no);
623  }
624  }
625  n++;
626  }
627  if(n==1)
628  pips_user_error("IO intrinsics \"%s\" requires at least one argument",
630  else if(n==2 && m==2)
631  pips_user_error("IO intrinsics \"%s\" requires at least two arguments",
633  }
634  else if(ENTITY_C_RETURN_P(f)) {
635  /* it is assumed that only one return is present in any module
636  code because internal returns are replaced by gotos */
637  if(ENDP(al)) {
638  // clear_pt_map(pt_out);
639  ; // the necessary projections are performed elsewhere
640  }
641  else {
642  expression rhs = EXPRESSION(CAR(al));
643  type rhst = expression_to_type(rhs);
644  // FI: should we use the type of the current module?
645  if(pointer_type_p(rhst) || struct_type_p(rhst)) {
648  pt_out = assignment_to_points_to(lhs, rhs, pt_out);
649  }
650  free_type(rhst);
651  }
652  }
653  else if(ENTITY_FCLOSE_P(f)) {
654  expression lhs = EXPRESSION(CAR(al));
655  // pt_out = freed_pointer_to_points_to(lhs, pt_out, side_effect_p);
656  list lhc = expression_to_points_to_sources(lhs, pt_out);
657  cell uc = make_nowhere_cell();
658  list rhc = CONS(CELL, uc, NIL);
659  pt_out = list_assignment_to_points_to(lhc, rhc, pt_out);
660  }
661  else if(ENTITY_CONDITIONAL_P(f)) {
662  // FI: I needs this piece of code for assert();
663  expression c = EXPRESSION(CAR(al));
664  pt_map in_t = full_copy_pt_map(pt_out);
665  pt_map in_f = full_copy_pt_map(pt_out);
666  // FI: issue with the notion of pt_in
667  // stubs created when computing in_t should also be added in in_f
668  // or they are going to seem to be reallocated ambiguously in
669  // create_stub_entity(). Same issue I guess for the "if" construct
670  in_t = condition_to_points_to(c, in_t, true);
671  in_f = condition_to_points_to(c, in_f, false);
672  expression e1 = EXPRESSION(CAR(CDR(al)));
673  expression e2 = EXPRESSION(CAR(CDR(CDR(al))));
674  pt_map out_t = pt_map_undefined;
675 
676  if(!points_to_graph_bottom(in_t))
677  out_t = expression_to_points_to(e1, in_t, side_effect_p);
678 
679  pt_map out_f = pt_map_undefined;
680  // FI: should be factored out in a more general merge function...
681  if(!points_to_graph_bottom(in_f))
682  out_f = expression_to_points_to(e2, in_f, side_effect_p);
683 
684  if(points_to_graph_bottom(in_t))
685  pt_out = out_f;
686  else if(points_to_graph_bottom(in_f))
687  pt_out = out_t;
688  else
689  pt_out = merge_points_to_graphs(out_t, out_f);
690  // FI: this destroys pt_out for test case pointer02, Memory leaks...
691  //free_pt_map(in_t), free_pt_map(in_f), free_pt_map(out_t), free_pt_map(out_f);
692  }
693  else if(ENTITY_FOPEN_P(f)) {
694  expression e1 = EXPRESSION(CAR(al));
695  pt_out = dereferencing_to_points_to(e1, pt_out);
696  expression e2 = EXPRESSION(CAR(CDR(al)));
697  pt_out = dereferencing_to_points_to(e2, pt_out);
698  }
699  else if(ENTITY_FDOPEN_P(f)) {
700  expression e2 = EXPRESSION(CAR(CDR(al)));
701  pt_out = dereferencing_to_points_to(e2, pt_out);
702  }
703  else if(ENTITY_FREOPEN_P(f)) {
704  expression e1 = EXPRESSION(CAR(al));
705  pt_out = dereferencing_to_points_to(e1, pt_out);
706  expression e2 = EXPRESSION(CAR(CDR(al)));
707  pt_out = dereferencing_to_points_to(e2, pt_out);
708  expression e3 = EXPRESSION(CAR(CDR(CDR(al))));
709  pt_out = dereferencing_to_points_to(e3, pt_out);
710  }
711  else if(ENTITY_FREAD_P(f) || ENTITY_FWRITE_P(f)) {
712  expression e1 = EXPRESSION(CAR(al));
713  pt_out = dereferencing_to_points_to(e1, pt_out);
714  expression e4 = EXPRESSION(CAR(CDR(CDR(CDR(al)))));
715  pt_out = dereferencing_to_points_to(e4, pt_out);
716  }
717  else if(ENTITY_CLEARERR_P(f) || ENTITY_FEOF_P(f)
719  expression e1 = EXPRESSION(CAR(al));
720  pt_out = dereferencing_to_points_to(e1, pt_out);
721  }
724  expression e1 = EXPRESSION(CAR(al));
725  pt_out = dereferencing_to_points_to(e1, pt_out);
726  expression e2 = EXPRESSION(CAR(CDR(al)));
727  pt_out = dereferencing_to_points_to(e2, pt_out);
728  // FI: we might need to do more for e3 in strncat case
729  }
730  else {
731  // FI: fopen(), fclose() should be dealt with
732  // fopen implies that its path argument is not NULL, just like a test
733  // fclose implies that its fp argument is not NULL on input and
734  // points to undefined on output.
735 
736  // Not safe till all previous tests are defined
737  // It is assumed that other intrinsics do not generate points-to arcs...
738  // pips_internal_error("Not implemented yet\n");
739  pt_out = pt_in;
740  }
741 
742  pips_assert("pt_out is consistent and defined",
744  && !points_to_graph_undefined_p(pt_out));
745 
746  return pt_out;
747 }
points_to_graph copy_points_to_graph(points_to_graph p)
POINTS_TO_GRAPH.
#define pt_map_undefined
pt_map pointer_arithmetic_to_points_to(expression lhs, expression delta, pt_map pt_in)
Update the sink locations associated to the source "lhs" under points-to information pt_map by "delta...
Definition: expression.c:760
pt_map freed_pointer_to_points_to(expression lhs, pt_map pt_in, bool side_effect_p)
Any abstract location of the lhs in L is going to point to nowhere, maybe.
Definition: expression.c:1741
#define ENTITY_STRCMP_SYSTEM_P(e)
include <string.h>
#define ENTITY_FSCANF_P(e)
#define ENTITY_FWRITE_P(e)
#define ENTITY_FREE_SYSTEM_P(e)
#define ENTITY_STOP_P(e)
#define ENTITY_SCANF_P(e)
#define ENTITY_STRNCMP_SYSTEM_P(e)
#define ENTITY_FEOF_P(e)
#define ENTITY_ISOC99_SSCANF_P(e)
#define ENTITY_PRINTF_P(e)
o functions: C library and system io.Amira Mensi
#define DEREFERENCING_OPERATOR_NAME
Definition: ri-util-local.h:93
#define ENTITY_EXIT_SYSTEM_P(e)
#define ENTITY_FCLOSE_P(e)
#define ENTITY_ISOC99_SCANF_P(e)
#define unary_intrinsic_expression(name, e)
Building quickly bool expressions, FC.
#define ENTITY_FREAD_P(e)
#define ENTITY_SPRINTF_P(e)
#define ENTITY_SSCANF_P(e)
#define ENTITY_FREOPEN_P(e)
#define ENTITY_FERROR_P(e)
#define ENTITY_STRNCAT_SYSTEM_P(e)
#define ENTITY_ABORT_SYSTEM_P(e)
#define ENTITY_FDOPEN_P(e)
#define ENTITY_C_RETURN_P(e)
#define ENTITY_ISOC99_FSCANF_P(e)
#define ENTITY_FPRINTF_P(e)
#define ENTITY_FILENO_P(e)
#define ENTITY_CLEARERR_P(e)
#define ENTITY_STRCAT_SYSTEM_P(e)
#define ENTITY_ASSERT_FAIL_SYSTEM_P(e)
entity function_to_return_value(entity m)
Returns the entity rv that carries the value returned by module m, when m is not a C void function or...
Definition: module.c:509

References assignment_to_points_to(), C_pointer_type_p(), call_arguments, call_function, CAR, CDR, CELL, char_star_type_p(), clear_pt_map, condition_to_points_to(), CONS, copy_expression(), copy_points_to_graph(), DEREFERENCING_OPERATOR_NAME, dereferencing_to_points_to(), ENDP, ENTITY_ABORT_SYSTEM_P, ENTITY_ASSERT_FAIL_SYSTEM_P, ENTITY_ASSIGN_P, ENTITY_C_RETURN_P, ENTITY_CLEARERR_P, ENTITY_CONDITIONAL_P, ENTITY_DEREFERENCING_P, ENTITY_EXIT_SYSTEM_P, ENTITY_FCLOSE_P, ENTITY_FDOPEN_P, ENTITY_FEOF_P, ENTITY_FERROR_P, ENTITY_FILENO_P, ENTITY_FOPEN_P, ENTITY_FPRINTF_P, ENTITY_FREAD_P, ENTITY_FREE_SYSTEM_P, ENTITY_FREOPEN_P, ENTITY_FSCANF_P, ENTITY_FWRITE_P, ENTITY_ISOC99_FSCANF_P, ENTITY_ISOC99_SCANF_P, ENTITY_ISOC99_SSCANF_P, ENTITY_MINUS_C_P, ENTITY_MINUS_UPDATE_P, entity_name, ENTITY_PLUS_C_P, ENTITY_PLUS_UPDATE_P, ENTITY_POINT_TO_P, ENTITY_POST_DECREMENT_P, ENTITY_POST_INCREMENT_P, ENTITY_PRE_DECREMENT_P, ENTITY_PRE_INCREMENT_P, ENTITY_PRINTF_P, ENTITY_SCANF_P, ENTITY_SPRINTF_P, ENTITY_SSCANF_P, ENTITY_STOP_P, ENTITY_STRCAT_SYSTEM_P, ENTITY_STRCMP_SYSTEM_P, ENTITY_STRNCAT_SYSTEM_P, ENTITY_STRNCMP_SYSTEM_P, entity_to_expression(), entity_user_name(), EXPRESSION, expression_reference_p(), expression_to_points_to(), expression_to_points_to_sinks(), expression_to_points_to_sources(), expression_to_string(), expression_to_type(), f(), FindOrCreateTopLevelEntity(), FOREACH, free_expression(), free_pt_map, free_type(), freed_pointer_to_points_to(), full_copy_pt_map(), function_to_return_value(), gen_free_list(), gen_length(), get_current_module_entity(), int_to_expression(), list_assignment_to_points_to(), make_nowhere_cell(), MakeUnaryCall(), merge_points_to_graphs(), NIL, nowhere_cell_p(), pips_assert, pips_debug, pips_user_error, pips_user_warning, pointer_arithmetic_to_points_to(), pointer_type_p(), points_to_context_statement_line_number(), points_to_expression_to_concrete_type(), points_to_graph_bottom, points_to_graph_consistent_p(), points_to_graph_set, points_to_graph_undefined_p, pt_map_undefined, set_clear(), struct_type_p(), type_to_full_string_definition(), unary_intrinsic_expression, and UNARY_MINUS_OPERATOR_NAME.

Referenced by call_to_points_to(), and intrinsic_call_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ intrinsic_call_to_points_to_sinks()

list intrinsic_call_to_points_to_sinks ( call  c,
pt_map  in,
bool  eval_p,
bool  constant_p 
)
Parameters
inn
eval_pval_p
constant_ponstant_p

Definition at line 172 of file sinks.c.

174 {
175  list sinks = NIL;
176  entity f = call_function(c);
177  list al = call_arguments(c);
178  int nary = (int) gen_length(al);
179 
180  // You do not know the number of arguments for the comma operator
181  if(ENTITY_COMMA_P(f)) {
182  expression e = EXPRESSION(CAR(gen_last(al)));
183  sinks = expression_to_points_to_sinks(e, in);
184  }
185  else {
186  // Switch on number of arguments to avoid long switch on character
187  // string or memoizing of intrinsics
188  switch(nary) {
189  case 0:
190  pips_internal_error("Probably a constant or a symbolic. Not handled here\n");
191  break;
192  case 1:
193  sinks = unary_intrinsic_call_to_points_to_sinks(c, in, eval_p, constant_p);
194  break;
195  case 2:
196  sinks = binary_intrinsic_call_to_points_to_sinks(c, in, eval_p);
197  break;
198  case 3:
200  break;
201  default:
203  break;
204  }
205  }
206 
207  return sinks;
208 }
#define ENTITY_COMMA_P(e)
list unary_intrinsic_call_to_points_to_sinks(call c, pt_map in, bool eval_p, bool constant_p)
Definition: sinks.c:216
list nary_intrinsic_call_to_points_to_sinks(call c, pt_map in)
Definition: sinks.c:640
list binary_intrinsic_call_to_points_to_sinks(call c, pt_map in, bool eval_p)
Definition: sinks.c:327
list ternary_intrinsic_call_to_points_to_sinks(call c, pt_map in, bool eval_p, bool constant_p)
Definition: sinks.c:594

References binary_intrinsic_call_to_points_to_sinks(), call_arguments, call_function, CAR, constant_p(), ENTITY_COMMA_P, EXPRESSION, expression_to_points_to_sinks(), f(), gen_last(), gen_length(), int, nary_intrinsic_call_to_points_to_sinks(), NIL, pips_internal_error, ternary_intrinsic_call_to_points_to_sinks(), and unary_intrinsic_call_to_points_to_sinks().

Referenced by call_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ k_limit_points_to()

pt_map k_limit_points_to ( pt_map  pt_out,
int  k 
)
Parameters
pt_outt_out

Definition at line 912 of file statement.c.

913 {
914  //bool type_sensitive_p = !get_bool_property("ALIASING_ACROSS_TYPES");
915  //entity anywhere = entity_undefined;
916  set pt_out_s = points_to_graph_set(pt_out);
917 
918  SET_FOREACH(points_to, pt, pt_out_s){
919  cell sc = points_to_source(pt);
920  reference sr = cell_any_reference(sc);
921  list sl = reference_indices(sr);
922 
923  cell kc = points_to_sink(pt);
924  reference kr = cell_any_reference(kc);
925  list kl = reference_indices(kr);
926 
927  if((int)gen_length(sl)>k){
928  bool to_be_freed = false;
929  type sc_type = cell_to_type(sc, &to_be_freed);
930  sc = make_anywhere_cell(sc_type);
931  if(to_be_freed) free_type(sc_type);
932  }
933 
934  if((int)gen_length(kl)>k){
935  bool to_be_freed = false;
936  type kc_type = cell_to_type(kc, &to_be_freed);
937  kc = make_anywhere_cell(kc_type);
938  if(to_be_freed) free_type(kc_type);
939  }
940 
941  points_to npt = make_points_to(sc, kc,
944  if(!points_to_equal_p(npt,pt)){
945  // FC: why assigning pt_out to itself?
946  pt_out = remove_arc_from_pt_map_(pt, pt_out);
947  pt_out = remove_arc_from_pt_map_(npt, pt_out);
948  }
949  else {
950  // FI: memory leak
951  // free_points_to(npt);
952  }
953  }
954  return pt_out;
955 }
#define remove_arc_from_pt_map_(a, s)

References cell_any_reference(), cell_to_type(), copy_approximation(), free_type(), gen_length(), make_anywhere_cell(), make_descriptor_none(), make_points_to(), points_to_approximation, points_to_equal_p(), points_to_graph_set, points_to_sink, points_to_source, reference_indices, remove_arc_from_pt_map_, and SET_FOREACH.

+ Here is the call graph for this function:

◆ kill_may_set()

set kill_may_set ( list  L,
set  in_may 
)

Compute the set of arcs in the input points-to relation "in" whose approximation must be changed from "exact" to "may".

This set is linked to set "gen_may1", although consistency would be easier to maintain if only "kill_may" were used to generate the new arcs...

kill_may = { pt in "in"| exact(pt) ^ \exists l in L conflict(l, source(pt))}

The restriction to !atomic does not seem useful.

Parameters
in_mayn_may

Definition at line 668 of file constant-path-utils.c.

669 {
672  FOREACH(cell, l, L) {
673  SET_FOREACH(points_to, pt, in_may) {
674  cell pt_source = points_to_source(pt);
675  if (opkill_may_constant_path(pt_source,l)) {
676  points_to npt = make_points_to(pt_source,
677  points_to_sink(pt),
680  set_add_element(kill_may, kill_may, (void*)npt);
681  }
682  }
683  }
684  return kill_may;
685 }
bool opkill_may_constant_path(cell c1, cell c2)

References FOREACH, make_approximation_exact(), make_descriptor_none(), make_points_to(), opkill_may_constant_path(), points_to_equal_p(), points_to_rank(), points_to_sink, points_to_source, set_add_element(), SET_FOREACH, set_generic_make(), and set_private.

Referenced by list_assignment_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ kill_must_set()

set kill_must_set ( list  L,
set  in 
)

Generate the subset of arcs that must be removed from the points-to graph "in".

Set "in_must" is the subset of set "in" with exact points-to arcs only.

kill_1 = kill_must = {pt in "in" | source(pt) in L ^ |L|=1 ^ atomic(L) }

where "atomic(L)" is a short cut for "atomic(l) forall l in L"

Here, correctly, the atomicity is not checked directly, but properly, using an operator of the lattice.

Parameters
inn

Definition at line 700 of file constant-path-utils.c.

701 {
702  set kill_must = new_simple_pt_map();
703  int nL = (int) gen_length(L);
704 
705  if(nL==1) {
706  cell l = CELL(CAR(L));
707  SET_FOREACH(points_to, s, in) {
709  set_add_element(kill_must, kill_must,(void*)s);
710  }
711  }
712  return kill_must;
713 }
bool opkill_must_constant_path(cell c1, cell c2)
returns true if c2 kills c1

References CAR, CELL, gen_length(), int, new_simple_pt_map, opkill_must_constant_path(), points_to_source, set_add_element(), and SET_FOREACH.

Referenced by list_assignment_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ list_assignment_to_points_to()

pt_map list_assignment_to_points_to ( list  L,
list  R,
pt_map  pt_out 
)

Update "pt_out" when any element of L can be assigned any element of R.

FI->AM: Potential and sure memory leaks are not (yet) detected.

FI->AM: the distinction between may and must sets used in the implementation seem useless.

Old description by Amira:

KILL_MAY = kill_may_set() KILL_MUST= kill_must_set()

GEN_MAY = gen_may_set() GEN_MUST= gen_must_set()

KILL = KILL_MAY U KILL_MUST GEN = GEN_MAY U GEN_MUST PT_OUT = (PT_OUT - KILL) U GEN

This function is used to model a C pointer assignment "e1 = e2;"

Let L = expression_to_sources(e1) and R = expression_to_sinks(e2).

Let "in" be the points-to relation before executing the assignment.

Gen(L,R) = {pts| exist l in L exists r in R s.t. pts=(l,r,|L|=1)

Kill(L,in) = {pts=(l,sink,must)| l in L}

Let K=Kill(L,in) and out = (in-K) U gen(L,R)

For memory leaks, let

ML(K,out) = {c in Heap | exists pts=(l,c,a) in K && !(exists pts'=(l',c,a') in out)}

For error dereferencing, such as nowhere/undefined and NULL, check the content of L.

This function is described in Amira Mensi's dissertation.

Test cases designed to check the behavior of this function: ?!?

Check possible dereferencing errors

For arrays, an extra eval has been applied by adding 0 subscripts

What do we want to do when the left hand side is NULL or UNDEFINED?

The code cannot be executed

Compute the data-flow equation for the may and the must edges...

out = (in - kill) U gen ?

Extract MAY/MUST points to relations from the input set "pt_out"

Check kill_must for potential memory leaks

FI: this error message may be wrong in case of a call to realloc(); see Pointers/hyantes02.c, hyantes03.c

FI: this error message may deal with a bucket that does not really exist because its allocation was conditional.

To make things worse, the warning is emitted in an iterative loop analysis.

Look for a chain of memory leaks. Since they are also "related" to "d", this must be done before the next step.

Look for related lost arcs. See Pointers/malloc18.c

en_must,

kill,

Parameters
pt_outt_out

Definition at line 2029 of file expression.c.

2030 {
2031  pips_assert("This function is not called with a bottom points-to",
2032  !points_to_graph_bottom(pt_out));
2033 
2034  pips_assert("pt_out is consistent on entry",
2036 
2037  /* Check possible dereferencing errors */
2038  list ndl = NIL; // null dereferencing error list
2039  list udl = NIL; // undefined dereferencing error list
2040  // FI->AM: you have no way to know if stubs are atomic or not...
2041  // I am not sure the atomic predicate takes this into account
2042  // but it does not really matter intraprocedurally: stubs are atomic
2043  bool singleton_p = (gen_length(L)==1
2044  && generic_atomic_points_to_cell_p(CELL(CAR(L)), false));
2045  FOREACH(CELL, c, L) {
2046  if(nowhere_cell_p(c)){
2047  udl = CONS(CELL, c, udl);
2048  if(singleton_p)
2049  // Not necessarily a user error if the code is dead
2050  // Should be controlled by an extra property...
2051  pips_user_warning("Dereferencing of an undefined pointer \"%s\" at line %d.\n",
2054  else
2055  pips_user_warning("Possible dereferencing of an undefined pointer.\n");
2056  }
2057  else if(null_cell_p(c)) {
2058  ndl = CONS(CELL, c, ndl);
2059  if(singleton_p)
2060  // Not necessarily a user error if the code is dead
2061  // Should be controlled by an extra property...
2062  pips_user_warning("Dereferencing of a null pointer \"%s\" at line %d.\n",
2065  else
2066  pips_user_warning("Possible dereferencing of a null pointer \"%s\" at line %d.\n",
2069  }
2070  else {
2071  /* For arrays, an extra eval has been applied by adding 0 subscripts */
2072  cell nc = copy_cell(c); // FI: for debugging purpose
2075  if(!C_pointer_type_p(ct) && !overloaded_type_p(ct)) {
2076  fprintf(stderr, "nc=");
2078  fprintf(stderr, "\nc=");
2080  pips_internal_error("\nSource cell cannot really be a source cell\n");
2081  }
2082  free_cell(nc);
2083  }
2084  }
2085 
2086  pips_assert("pt_out is consistent", consistent_points_to_graph_p(pt_out));
2087 
2088  if(!ENDP(ndl) || !ENDP(udl)) {
2089  if(!ENDP(ndl))
2090  pips_user_warning("Possible NULL pointer dereferencing.\n");
2091  else
2092  pips_user_warning("Possible undefined pointer dereferencing.\n");
2093 
2094  /* What do we want to do when the left hand side is NULL or UNDEFINED? */
2095  bool null_dereferencing_p
2096  = get_bool_property("POINTS_TO_NULL_POINTER_DEREFERENCING");
2097  bool nowhere_dereferencing_p
2098  = get_bool_property("POINTS_TO_UNINITIALIZED_POINTER_DEREFERENCING");
2099  if(!null_dereferencing_p) {
2100  gen_list_and_not(&L, ndl);
2101  if(!nowhere_dereferencing_p) {
2102  gen_list_and_not(&L, udl);
2103  }
2104 
2105  // FI: I guess all undefined and nowhere cells in L should be
2106  // removed and replaced by only one anywhere cell
2107  // FI: it should be typed according to the content of the cells in del
2108 
2109  if(!ENDP(ndl) && null_dereferencing_p) {
2110  cell nc = CELL(CAR(ndl));
2113  gen_list_and_not(&L, ndl);
2114  L = CONS(CELL, c, L);
2115  }
2116 
2117  if(!ENDP(udl) && nowhere_dereferencing_p) {
2118  cell nc = CELL(CAR(udl));
2121  gen_list_and_not(&L, udl);
2122  L = CONS(CELL, c, L);
2123  }
2124 
2125  gen_free_list(ndl), gen_free_list(udl);
2126  }
2127  }
2128 
2129  if(ENDP(L)) {
2130  /* The code cannot be executed */
2131  clear_pt_map(pt_out);
2132  points_to_graph_bottom(pt_out) = true;
2133  }
2134  else {
2135  /* Compute the data-flow equation for the may and the must edges...
2136  *
2137  * out = (in - kill) U gen ?
2138  */
2139 
2140  /* Extract MAY/MUST points to relations from the input set "pt_out" */
2141  set pt_out_s = points_to_graph_set(pt_out);
2142  set in_may = points_to_may_filter(pt_out_s);
2143  set in_must = points_to_must_filter(pt_out_s);
2144  //set kill_may = kill_may_set(L, in_may);
2145  // Arcs whose approximation must be changed
2146  set kill_may = kill_may_set(L, in_must);
2147  // Arcs that are definitely killed
2148  set kill_must = kill_must_set(L, pt_out_s);
2149  // FI: easiest way to find the proper set "kill_may"
2150  kill_may = set_difference(kill_may, kill_may, kill_must);
2151  bool address_of_p = true;
2152  // gen_may = gen_2 in the dissertation
2153  set gen_may = gen_may_set(L, R, pt_out_s, &address_of_p);
2154  // set gen_must = gen_must_set(L, R, in_must, &address_of_p);
2155  //set kill/* = new_pt_map()*/;
2156  set kill = new_simple_pt_map();
2157  // FI->AM: do we really want to keep the same arc with two different
2158  // approximations? The whole business of may/must does not seem
2159  // useful.
2160  //kill = set_union(kill, kill_may, kill_must);
2161  // kill_may is handled direclty below
2162  kill = kill_must;
2164  //set_union(gen, gen_may, gen_must);
2165  set_assign(gen, gen_may);
2166 
2167  pips_assert("\"gen\" is consistent", consistent_points_to_set(gen));
2168 
2169  if(set_empty_p(gen)) {
2170  bool type_sensitive_p = !get_bool_property("ALIASING_ACROSS_TYPES");
2171  if(type_sensitive_p)
2172  gen = points_to_anywhere_typed(L, pt_out_s);
2173  else
2174  gen = points_to_anywhere(L, pt_out_s);
2175  }
2176 
2177  // FI->AM: shouldn't it be a kill_must here?
2178  set_difference(pt_out_s, pt_out_s, kill);
2179 
2180  pips_assert("After removing the kill set, pt_out is consistent",
2182 
2183  set_union(pt_out_s, pt_out_s, gen);
2184 
2185  // FI->AM: use kill_may to reduce the precision of these arcs
2186  // Easier than to make sure than "gen_may1", i.e. "gen_1" in the
2187  // dissertation, is consistent with "kill_may", i.e. kill_2 in the
2188  // dissertation
2189 
2190  SET_FOREACH(points_to, pt, kill_may) {
2192  if(approximation_exact_p(a)) {
2197  remove_arc_from_pt_map(pt, pt_out);
2198  add_arc_to_pt_map(npt, pt_out);
2199  }
2200  }
2201 
2202  pips_assert("After union and approximation updates pt_out is consistent",
2204 
2205  /* Check kill_must for potential memory leaks */
2206  SET_FOREACH(points_to, kpt, kill_must) {
2207  cell d = points_to_sink(kpt);
2208  //approximation ap = points_to_approximation(kpt);
2209  // approximation_exact_p(ap) && : this is incompatible with heap_cell_p
2210  if(heap_cell_p(d)
2211  && unreachable_points_to_cell_p(d, pt_out)) {
2212  /* FI: this error message may be wrong in case of a call to
2213  * realloc(); see Pointers/hyantes02.c, hyantes03.c
2214  *
2215  * FI: this error message may deal with a bucket that does not
2216  * really exist because its allocation was conditional.
2217  *
2218  * To make things worse, the warning is emitted in an
2219  * iterative loop analysis.
2220  */
2221  pips_user_warning("Heap bucket \"%s\" %sleaked at line %d.\n",
2223  set_size(kill_must)>1? "possibly " : "",
2225 
2226  /* Look for a chain of memory leaks. Since they are also
2227  "related" to "d", this must be done before the next
2228  step. */
2229  pt_out = memory_leak_to_more_memory_leaks(d, pt_out);
2230 
2231  /* Look for related lost arcs. See Pointers/malloc18.c */
2232  reference dr = cell_any_reference(d);
2233  entity dv = reference_variable(dr);
2234  // cell nd = make_cell_reference(make_reference(dv, NIL));
2235  //points_to_cell_add_unbounded_subscripts(nd);
2236  list dal = NIL; // Deleted arc list
2237  SET_FOREACH(points_to, pt, pt_out_s) {
2238  cell s = points_to_source(pt);
2239  reference sr = cell_any_reference(s);
2240  entity sv = reference_variable(sr);
2241  if(dv==sv) {
2242  if(unreachable_points_to_cell_p(s, pt_out))
2243  dal = CONS(POINTS_TO, pt, dal);
2244  }
2245  }
2246  FOREACH(POINTS_TO, da, dal)
2247  remove_arc_from_pt_map(da, pt_out);
2248  gen_free_list(dal);
2249  }
2250  }
2251 
2252  sets_free(in_may, in_must,
2253  kill_may, kill_must,
2254  gen_may, /*gen_must,*/
2255  gen,/* kill,*/ NULL);
2256  // clear_pt_map(pt_out); // FI: why not free?
2257  }
2258 
2259  return pt_out;
2260 }
descriptor copy_descriptor(descriptor p)
DESCRIPTOR.
Definition: effects.c:389
set kill_must_set(list L, set in)
Generate the subset of arcs that must be removed from the points-to graph "in".
set points_to_may_filter(set in)
returns a set which contains all the MAY points to
set kill_may_set(list L, set in_may)
Compute the set of arcs in the input points-to relation "in" whose approximation must be changed from...
set points_to_must_filter(set in)
returns a set which contains all the EXACT points to
set gen_may_set(list L, list R, set in_may, bool *address_of_p)
Should be moved to anywhere_abstract_locations.c.
set points_to_anywhere(list lhs_list, set input)
set points_to_anywhere_typed(list lhs_list, set input)
Already exists in points_to_general_algorithm.c, to be removed later...
void sets_free(set,...)
Free several sets in one call.
Definition: set.c:340
int set_size(const set)
returns the number of items in s.
Definition: set.c:359
cell reduce_cell_to_pointer_type(cell c)
Remove last subscripts of cell c till its type becomes a scalar pointer.
Definition: expression.c:1809
bool consistent_points_to_set(set)
make sure that set "s" does not contain redundant or contradictory elements
string points_to_cell_to_string(cell)
#define points_to_descriptor(x)

References add_arc_to_pt_map, approximation_exact_p, C_pointer_type_p(), CAR, CELL, cell_any_reference(), clear_pt_map, CONS, consistent_points_to_graph_p(), consistent_points_to_set(), copy_cell(), copy_descriptor(), effect_reference_to_string(), ENDP, entity_type, FOREACH, fprintf(), free_cell(), gen(), gen_free_list(), gen_length(), gen_list_and_not(), gen_may_set(), generic_atomic_points_to_cell_p(), get_bool_property(), heap_cell_p(), kill_may_set(), kill_must_set(), make_anywhere_points_to_cell(), make_approximation_may(), make_points_to(), memory_leak_to_more_memory_leaks(), new_simple_pt_map, NIL, nowhere_cell_p(), null_cell_p(), overloaded_type_p(), pips_assert, pips_internal_error, pips_user_warning, POINTS_TO, points_to_anywhere(), points_to_anywhere_typed(), points_to_approximation, points_to_cell_to_concrete_type(), points_to_cell_to_string(), points_to_context_statement_line_number(), points_to_descriptor, points_to_graph_bottom, points_to_graph_set, points_to_may_filter(), points_to_must_filter(), points_to_sink, points_to_source, print_points_to_cell, reduce_cell_to_pointer_type(), reference_variable, remove_arc_from_pt_map, set_assign(), set_difference(), set_empty_p(), SET_FOREACH, set_size(), set_union(), sets_free(), and unreachable_points_to_cell_p().

Referenced by freed_list_to_points_to(), internal_pointer_assignment_to_points_to(), and intrinsic_call_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ load_printed_points_to_list()

points_to_list load_printed_points_to_list ( statement  )

Referenced by text_points_to(), and text_pt_to().

+ Here is the caller graph for this function:

◆ location_entity()

entity location_entity ( cell  c)

Definition at line 78 of file points_to_set.c.

79 {
82 
83  return e;
84 }

References cell_to_reference(), and reference_variable.

+ Here is the call graph for this function:

◆ locations_equal_p()

bool locations_equal_p ( cell  acc1,
cell  acc2 
)

eturn true if two acces_path are equals

Parameters
acc1cc1
acc2cc2

Definition at line 89 of file points_to_set.c.

90 {
91  return cell_equal_p(acc1, acc2);
92 }

References cell_equal_p().

Referenced by consistent_points_to_set(), and points_to_equal_p().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ loop_to_points_to()

pt_map loop_to_points_to ( loop  l,
pt_map  pt_in 
)

FI: I assume that pointers and pointer arithmetic cannot appear in a do loop, "do p=q, r, 1" is possible with "p", "q" and "r" pointing towards the same array...

Let's hope the do loop conversion does not catch such cases.

loop range expressions may require some points-to information See for instance Pointers/Mensi.sub/array_init02.c

Side effects might have to be taken into account... But side effects should also prevent PIPS from transforming a for loop into a do loop.

Parameters
pt_int_in

Definition at line 573 of file statement.c.

574 {
575  pt_map pt_out = pt_in;
576  statement b = loop_body(l);
577  //bool store = false;
578  //pt_out = points_to_loop(l, pt_in, store);
579 
580  /* loop range expressions may require some points-to information
581  * See for instance Pointers/Mensi.sub/array_init02.c
582  *
583  * Side effects might have to be taken into account... But side
584  * effects should also prevent PIPS from transforming a for loop
585  * into a do loop.
586  */
587  range r = loop_range(l);
589  expression bound = range_upper(r);
590  expression inc = range_increment(r);
591  pt_in = expression_to_points_to(init, pt_in, false);
592  pt_in = expression_to_points_to(bound, pt_in, false);
593  pt_in = expression_to_points_to(inc, pt_in, false);
594 
595  pt_out = any_loop_to_points_to(b,
599  pt_in);
600 
601  return pt_out;
602 }
#define loop_body(x)
Definition: ri.h:1644
#define range_upper(x)
Definition: ri.h:2290
#define range_increment(x)
Definition: ri.h:2292
#define range_lower(x)
Definition: ri.h:2288
#define loop_range(x)
Definition: ri.h:1642

References any_loop_to_points_to(), expression_to_points_to(), expression_undefined, init, loop_body, loop_range, range_increment, range_lower, and range_upper.

Referenced by instruction_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ make_nowhere_cell()

cell make_nowhere_cell ( void  )

constant-path-utils.c

constant-path-utils.c

CP = Mdodule * Name * Type *Vref. To calculate the lattice PC operators we define these operators first on each of its dimensions. Each dimension represents a lattice with a bottom and a top.

Definition at line 35 of file constant-path-utils.c.

36 {
39  cell sink = make_cell_reference(r);
40  return sink;
41 }
entity entity_all_xxx_locations(string xxx)
return ANY_MODULE:xxx
#define NOWHERE_LOCATION

References entity_all_xxx_locations(), make_cell_reference(), make_reference(), NIL, and NOWHERE_LOCATION.

Referenced by cell_to_nowhere_sink(), intrinsic_call_to_points_to(), points_to_nowhere(), remove_points_to_cell(), and unary_intrinsic_call_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ make_null_cell()

cell make_null_cell ( void  )

Definition at line 95 of file sinks.c.

96 {
98  cell c = entity_to_cell(ne);
99  return c;
100 }
entity entity_null_locations()
return TOP-LEVEL:NULL_POINTER The NULL pointer should be a global variable, unique for all modules FI...
cell entity_to_cell(entity e)
Definition: sinks.c:80

References entity_null_locations(), and entity_to_cell().

Referenced by binary_intrinsic_call_to_points_to_sinks(), declaration_statement_to_points_to(), flow_sensitive_malloc_to_points_to_sinks(), and null_equal_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ make_typed_nowhere_cell()

cell make_typed_nowhere_cell ( type  t)

Definition at line 43 of file constant-path-utils.c.

44 {
47  cell sink = make_cell_reference(r);
48  return sink;
49 }
entity entity_all_xxx_locations_typed(string xxx, type t)
FI->AM: the predicate entity_all_xxx_locations_typed_p() is missing...

References entity_all_xxx_locations_typed(), make_cell_reference(), make_reference(), NIL, and NOWHERE_LOCATION.

Referenced by cell_to_nowhere_sink(), freed_list_to_points_to(), points_to_set_block_projection(), and remove_points_to_cell().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ malloc_to_points_to_sinks()

list malloc_to_points_to_sinks ( expression  e,
pt_map  in 
)

Heap modelling.

FI: lots of issues here; the potential cast is lost...

FI: the high-level switch I have added to understand the management of options is performed at a much much lower level, which may be good or not. I do not think it's good for readbility, but factoring is good. See malloc_to_abstract_location()

e is the arguments of the malloc call...

Basic heap modelling

ABSTRACT_HEAP_LOCATIONS:

"unique": do not generate heap abstract locations for each line number...

"insensitive": control path are not taken into account; all malloc() located in one function are equivalent.

"flow-sensitive": take into account the line number or the occurence number?

"context-sensitive": take into account the call stack; not implemented

ALIASING_ACROSS_TYPE: you should have one heap per type if aliasing across type is forbidden. The impact of its composition with the previous property is not specified...

The C standard specifies that all pointers that are allocated in the heap have the value "indeterminate".

Parameters
inn

Definition at line 1231 of file sinks.c.

1233 {
1234  list sinks = NIL;
1235  const char * opt = get_string_property("ABSTRACT_HEAP_LOCATIONS");
1236  //bool type_sensitive_p = !get_bool_property("ALIASING_ACROSS_TYPES");
1237 
1238  if(same_string_p(opt, "unique")) {
1240  }
1241  else if(same_string_p(opt, "insensitive")) {
1243  }
1244  else if(same_string_p(opt, "flow-sensitive")) {
1246  }
1247  else if(same_string_p(opt, "context-sensitive")) {
1248  // Context sensitivity is dealt with in the translation functions, not here
1250  }
1251  else {
1252  pips_user_error("Unexpected value \"%s\" for Property ABSTRACT_HEAP_LOCATION."
1253  "Possible values are \"unique\", \"insensitive\","
1254  "\"flow-sensitive\", \"context-sensitive\".\n", opt);
1255  }
1256 
1257  /* The C standard specifies that all pointers that are allocated in
1258  the heap have the value "indeterminate". */
1259  FOREACH(CELL, c, sinks) {
1261  entity v = reference_variable(r);
1263  FOREACH(CELL, source, l) {
1264  list psl = points_to_source_to_sinks(source, in, false);
1265  cell sink = cell_to_nowhere_sink(source);
1267  if(ENDP(psl)) {
1268  pt = make_points_to(source, sink,
1271  }
1272  else {
1273  pt = make_points_to(source, sink,
1276  gen_free_list(psl);
1277  }
1278  add_arc_to_pt_map(pt, in);
1279  }
1280  }
1281 
1282  return sinks;
1283 }
char * get_string_property(const char *)
list points_to_source_to_sinks(cell, pt_map, bool)
Build the sinks of source "source" according to the points-to graphs.
list unique_malloc_to_points_to_sinks(expression e)
FI->AM: is "unique" multiple when ALIASING_ACROSS_TYPE is set to false?
Definition: sinks.c:1292
list insensitive_malloc_to_points_to_sinks(expression e)
FI->AM: what's the difference with the previous option? Reference to your dissertation?
Definition: sinks.c:1312

References add_arc_to_pt_map, CELL, cell_any_reference(), cell_to_nowhere_sink(), ENDP, flow_sensitive_malloc_to_points_to_sinks(), FOREACH, gen_free_list(), get_string_property(), insensitive_malloc_to_points_to_sinks(), make_approximation_exact(), make_approximation_may(), make_descriptor_none(), make_points_to(), NIL, pips_user_error, points_to_source_to_sinks(), points_to_undefined, reference_variable, same_string_p, unique_malloc_to_points_to_sinks(), and variable_to_pointer_locations().

Referenced by binary_intrinsic_call_to_points_to_sinks(), and unary_intrinsic_call_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ max_module()

cell max_module ( cell  m1,
cell  m2 
)

we define operator max fot the lattice Module which has any_module as top and a bottom which is not yet clearly defined (maybe no_module) max_module : Module * Module -> Module Side effects on m1 if we have an anywhere location to return.

Parameters
m11
m22

Definition at line 207 of file constant-path-utils.c.

208 {
209  reference r1 = cell_any_reference(m1);
210  reference r2 = cell_any_reference(m2);
211  entity e1 = reference_variable(r1);
212  entity e2 = reference_variable(r2);
213 
215  return m1;
216  else {
217  e1 = entity_all_locations();
218  r1 = make_reference(e1,NIL);
219  m1 = make_cell_reference(r1);
220  }
221  return m1;
222 }
entity entity_all_locations()
eturn ANY_MODULE:ANYWHERE (the top of the lattice)

References cell_any_reference(), entity_all_locations(), entity_name, make_cell_reference(), make_reference(), NIL, reference_variable, and same_string_p.

+ Here is the call graph for this function:

◆ max_type()

type max_type ( type  t1,
type  t2 
)
Parameters
t11
t22

Definition at line 411 of file constant-path-utils.c.

412 {
413  if (!type_unknown_p(t1) && ! type_unknown_p(t2) && type_equal_p(t1,t2))
414  return t1;
415  else {
416  type t = MakeTypeUnknown();
417  return t;
418  }
419 }
type MakeTypeUnknown(void)
Definition: type.c:97
bool type_equal_p(type, type)
Definition: type.c:547
#define type_unknown_p(x)
Definition: ri.h:2956

References MakeTypeUnknown(), type_equal_p(), and type_unknown_p.

+ Here is the call graph for this function:

◆ maximal_out_degree_of_points_to_graph()

int maximal_out_degree_of_points_to_graph ( string mod_cell,
pt_map  in 
)

returns the cell vertex "mod_cell" with the maximal out_degree in graph "in", and its out-degree.

When several cells have the same maximal out-degree, return any of them.

Parameters
mod_cellod_cell
inn

Definition at line 3293 of file points_to_set.c.

3294 {
3295  hash_table cell_out_degree = hash_table_make(hash_string, 0);
3296 
3298  cell source = points_to_source(pt);
3299  string name = points_to_cell_name(source);
3300  long long int i =
3301  (long long int) hash_get(cell_out_degree, (void *) name);
3302  if(i== (long long int) HASH_UNDEFINED_VALUE) {
3303  i = 1;
3304  hash_put(cell_out_degree, (void *) name, (void *) i);
3305  }
3306  else {
3307  i++;
3308  hash_update(cell_out_degree, (void *) name, (void *) i);
3309  }
3310  }
3311 
3312  long long int m = 0;
3313  HASH_MAP(k, v, {
3314  if((long long int) v > m) {
3315  m = (long long int) v;
3316  *mod_cell = strdup((string) k);
3317  }
3318  }, cell_out_degree);
3319  hash_table_free(cell_out_degree);
3320  return (int) m;
3321 }
void hash_update(hash_table htp, const void *key, const void *val)
update key->val in htp, that MUST be pre-existent.
Definition: hash.c:491
@ hash_string
Definition: newgen_hash.h:32
#define HASH_UNDEFINED_VALUE
value returned by hash_get() when the key is not found; could also be called HASH_KEY_NOT_FOUND,...
Definition: newgen_hash.h:56
string points_to_cell_name(cell source)
Create a string which is the cell reference in C syntax.

References hash_get(), HASH_MAP, hash_put(), hash_string, hash_table_free(), hash_table_make(), HASH_UNDEFINED_VALUE, hash_update(), int, points_to_cell_name(), points_to_graph_set, points_to_source, SET_FOREACH, and strdup().

Referenced by normalize_points_to_graph().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ memory_leak_to_more_memory_leaks()

pt_map memory_leak_to_more_memory_leaks ( cell  l,
pt_map  in 
)

Cell "l" has been memory leaked for sure and is not referenced any more in "in".

Its successors may be leaked too.

Remove useless unreachable arcs

Look for a chain of memory leaks

Parameters
inn

Definition at line 1929 of file expression.c.

1930 {
1931  pt_map out = in;
1932  // potential memory leaks
1934  FOREACH(CELL, c, pml) {
1935  // This first test is probably useless because if has been
1936  // partially or fully performed by the caller
1937  if(heap_cell_p(c) && unreachable_points_to_cell_p(c, in)) {
1938  /* Remove useless unreachable arcs */
1939  list dl = NIL, npml = NIL;
1940  set out_s = points_to_graph_set(out);
1941  SET_FOREACH(points_to, pt, out_s) {
1942  cell source = points_to_source(pt);
1943  // FI: a weaker test based on the lattice is needed
1944  if(points_to_cell_equal_p(source, c)) {
1945  dl = CONS(POINTS_TO, pt, dl);
1946  cell sink = points_to_sink(pt);
1947  npml = CONS(CELL, sink, npml);
1948  // FI: we need to remove pt before we can test for unreachability...
1949  /*
1950  if(heap_cell_p(sink) && unreachable_points_to_cell_p(sink, out)) {
1951  pips_user_warning("Heap bucket \"%s\" leaked at line %d.\n",
1952  points_to_cell_to_string(sink),
1953  points_to_context_statement_line_number());
1954  */
1955  }
1956  }
1957  FOREACH(POINTS_TO, d, dl)
1959  gen_free_list(dl);
1960 
1961  FOREACH(CELL, sink, npml) {
1962  if(heap_cell_p(sink) && unreachable_points_to_cell_p(sink, out)) {
1963  if(false)
1964  pips_user_warning("Heap bucket \"%s\" leaked.\n",
1965  points_to_cell_to_string(sink));
1966  else
1967  pips_user_warning("Heap bucket \"%s\" leaked at line %d.\n",
1970  /* Look for a chain of memory leaks */
1971  //if(!points_to_cell_equal_p(c, l))
1973  }
1974  }
1975  gen_free_list(npml);
1976  }
1977  }
1978  return out;
1979 }
list points_to_cell_to_pointer_cells(cell c)
Definition: expression.c:1900

References CELL, CONS, FOREACH, gen_free_list(), heap_cell_p(), NIL, out, pips_user_warning, POINTS_TO, points_to_cell_equal_p(), points_to_cell_to_pointer_cells(), points_to_cell_to_string(), points_to_context_statement_line_number(), points_to_graph_set, points_to_sink, points_to_source, remove_arc_from_pt_map, SET_FOREACH, and unreachable_points_to_cell_p().

Referenced by freed_list_to_points_to(), list_assignment_to_points_to(), and points_to_set_block_projection().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ merge_points_to_graphs()

pt_map merge_points_to_graphs ( pt_map  s1,
pt_map  s2 
)
Parameters
s11
s22

Definition at line 3183 of file points_to_set.c.

3184 {
3186  points_to_graph_set(s2));
3187  pt_map pt_merged = new_pt_map();
3188  points_to_graph_set(pt_merged) = merged;
3190  points_to_graph_bottom(pt_merged) = true;
3191  return pt_merged;
3192 }
set merge_points_to_set(set s1, set s2)
Merge two points-to sets.

References merge_points_to_set(), new_pt_map, points_to_graph_bottom, points_to_graph_set, and s1.

Referenced by any_loop_to_points_to(), boolean_intrinsic_call_condition_to_points_to(), control_to_points_to(), intrinsic_call_to_points_to(), new_any_loop_to_points_to(), new_points_to_unstructured(), statement_to_points_to(), and test_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ merge_points_to_set()

set merge_points_to_set ( set  s1,
set  s2 
)

Merge two points-to sets.

This function is required to compute the points-to set resulting of an if control statements.

A new set is allocated but it reuses the elements of "s1" and "s2".

Parameters
s11
s22

Definition at line 2544 of file points_to_set.c.

2544  {
2546  points_to_rank);
2547 
2548  pips_assert("Consistent set s1", consistent_points_to_set(s1));
2549  pips_assert("Consistent set s2", consistent_points_to_set(s2));
2550 
2551  if(set_empty_p(s1))
2552  set_assign(Merge_set, s2);
2553  else if(set_empty_p(s2))
2554  set_assign(Merge_set, s1);
2555  else {
2557  points_to_rank);
2559  points_to_rank);
2560  set Intersection_set = set_generic_make(set_private, points_to_equal_p,
2561  points_to_rank);
2563  points_to_rank);
2564 
2565  Intersection_set = set_intersection(Intersection_set, s1, s2);
2566  Union_set = set_union(Union_set, s1, s2);
2567 
2568  SET_FOREACH ( points_to, i, Intersection_set ) {
2571  Definite_set = set_add_element(Definite_set,Definite_set,
2572  (void*) i );
2573  }
2574 
2575  SET_FOREACH ( points_to, j, Union_set ) {
2576  if ( ! set_belong_p(Definite_set, (void*)j) ) {
2580  Possible_set = set_add_element(Possible_set, Possible_set,(void*) pt);
2581  }
2582  }
2583 
2584  Merge_set = set_clear(Merge_set);
2585  Merge_set = set_union(Merge_set, Possible_set, Definite_set);
2586 
2587  set_clear(Intersection_set);
2588  set_clear(Union_set);
2589  set_clear(Possible_set);
2590  set_clear(Definite_set);
2591  set_free(Definite_set);
2592  set_free(Possible_set);
2593  set_free(Intersection_set);
2594  set_free(Union_set);
2595  }
2596 
2597  pips_assert("Consistent merged set", consistent_points_to_set(Merge_set));
2598 
2599  return Merge_set;
2600 }
set set_intersection(set, const set, const set)
Definition: set.c:229
_uint points_to_rank(const void *vpt, size_t size)
create a key which is a concatenation of the source's name, the sink's name and the approximation of ...

References approximation_exact_p, approximation_must_p, consistent_points_to_set(), make_approximation_may(), make_descriptor_none(), make_points_to(), pips_assert, points_to_approximation, points_to_equal_p(), points_to_rank(), points_to_sink, points_to_source, s1, set_add_element(), set_assign(), set_belong_p(), set_clear(), set_empty_p(), SET_FOREACH, set_free(), set_generic_make(), set_intersection(), set_private, and set_union().

Referenced by merge_points_to_graphs(), and ternary_intrinsic_call_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ multitest_to_points_to()

pt_map multitest_to_points_to ( multitest  mt,
pt_map  pt_in 
)
Parameters
mtt
pt_int_in

Definition at line 967 of file statement.c.

968 {
969  pt_map pt_out = pt_in;
970  pips_internal_error("Not implemented yet for multitest %p\n", mt);
971  return pt_out;
972 }

References pips_internal_error.

◆ nary_intrinsic_call_to_points_to_sinks()

list nary_intrinsic_call_to_points_to_sinks ( call  c,
pt_map  in 
)
Parameters
inn

Definition at line 640 of file sinks.c.

641 {
642  entity f = call_function(c);
643  list sinks = NIL;
644  pips_internal_error("Not implemented for %p and %p\n", c, in);
645  if(ENTITY_COMMA_P(f)) {
646  ;
647  }
648  return sinks;
649 }

References call_function, ENTITY_COMMA_P, f(), NIL, and pips_internal_error.

Referenced by intrinsic_call_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ new_any_loop_to_points_to()

pt_map new_any_loop_to_points_to ( statement  b,
expression  init,
expression  c,
expression  inc,
pt_map  pt_in 
)

Perform the same k-limiting scheme for all kinds of loops.

The do while loop must use an external special treatment for the first iteration.

Derived from the initial any_loop_to_points_to(): the iteration scheme is slighlty different but we end up with the same final iteration with all unioned states. Seems problematic at least in the presence of calls to free() because iter() is never normalized and always introduces new vertices and arcs in "pt_out". See list05.c.

pt_in is modified by side effects.

First, enter or skip the loop: initialization + condition check

Compute pt_out as loop invariant: pt_out holds at the beginning of the loop body.

pt_out(i) = pt_out(i-1) U pt_iter(i)

pt_iter(i) = f(pt_iter(i-1))

pt_prev == pt_iter(i-1), pt_out_prev == pt_out(i-1)

Note: the pt_out variable is also used to carry the loop exit points-to set.

prev receives the current points-to information, pt_iter

Depending on the kind of loop, execute the body and then possibly the incrementation and the condition

Merge the previous resut and the current result.

Check convergence

Add the last iteration to obtain the pt_out holding when exiting the loop

FI: I suppose that p[i] is replaced by p[*] and that MAY/MUST information is changed accordingly.

Parameters
initnit
incnc
pt_int_in

Definition at line 792 of file statement.c.

797 {
798  // return old_any_loop_to_points_to(b, init, c, inc, pt_in);
799  pt_map pt_out = pt_in;
800 
801  if(points_to_graph_bottom(pt_in)) {
802  (void) statement_to_points_to(b, pt_in);
803  }
804  else {
805  int i = 0;
806  // FI: k is linked to the cycles in points-to graph, and should not
807  // be linked to the number of convergence iterations. I assume here
808  // that the minimal number of iterations is greater than the
809  // k-limiting factor
810  int k = get_int_property("POINTS_TO_PATH_LIMIT")
811  + get_int_property("POINTS_TO_SUBSCRIPT_LIMIT")
812  + get_int_property("POINTS_TO_OUT_DEGREE_LIMIT")
813  +10; // Safety margin: might be set to max of both properties + 1 or 2...
814 
815  /* First, enter or skip the loop: initialization + condition check */
817  pt_out = expression_to_points_to(init, pt_out, true);
818  pt_map pt_out_skip = full_copy_pt_map(pt_out);
819  if(!expression_undefined_p(c)) {
820  pt_out = condition_to_points_to(c, pt_out, true);
821  pt_out_skip = condition_to_points_to(c, pt_out_skip, false);
822  }
823 
824  /* Compute pt_out as loop invariant: pt_out holds at the beginning of
825  * the loop body.
826  *
827  * pt_out(i) = pt_out(i-1) U pt_iter(i)
828  *
829  * pt_iter(i) = f(pt_iter(i-1))
830  *
831  * pt_prev == pt_iter(i-1), pt_out_prev == pt_out(i-1)
832  *
833  * Note: the pt_out variable is also used to carry the loop exit
834  * points-to set.
835  */
836  pt_map pt_out_prev = new_pt_map();
837  pt_map prev = new_pt_map();
838  pt_map pt_iter = new_pt_map();
839  pt_iter = assign_pt_map(pt_iter, pt_out);
840 
841  // FI: it should be a while loop to reach convergence
842  // FI: I keep it a for loop for safety
843  bool fix_point_p = false;
844  for(i = 0; i<k+2 ; i++) {
845  /* prev receives the current points-to information, pt_iter */
846  clear_pt_map(prev);
847  prev = assign_pt_map(prev, pt_iter);
848  clear_pt_map(pt_iter);
849 
850  /* Depending on the kind of loop, execute the body and then
851  possibly the incrementation and the condition */
852  // FI: here, storage_p would be useful to avoid unnecessary
853  // storage and update for each substatement at each iteration k
854  pt_iter = statement_to_points_to(b, prev);
855  if(!expression_undefined_p(inc))
856  pt_iter = expression_to_points_to(inc, pt_iter, true);
857  // FI: should be condition_to_points_to() for conditions such as
858  // while(p!=q);
859  // The condition is not always defined (do loops)
860  if(!expression_undefined_p(c))
861  pt_iter = condition_to_points_to(c, pt_iter, true);
862 
863  /* Merge the previous resut and the current result. */
864  // FI: move to pt_map
865  pt_out_prev = assign_pt_map(pt_out_prev, pt_out);
866  pt_out = merge_points_to_graphs(pt_out, pt_iter);
867 
868  pt_out = normalize_points_to_graph(pt_out);
869 
870  /* Check convergence */
871  if(set_equal_p(points_to_graph_set(pt_out_prev),
872  points_to_graph_set(pt_out))) {
873  fix_point_p = true;
874  /* Add the last iteration to obtain the pt_out holding when
875  exiting the loop */
876  pt_out = statement_to_points_to(b, pt_out_prev);
877  if(!expression_undefined_p(inc))
878  pt_out = expression_to_points_to(inc, pt_out, true);
879  if(!expression_undefined_p(c))
880  pt_out = condition_to_points_to(c, pt_out, false);
881  break;
882  }
883  else {
884  //ifdebug(1) {
885  if(true) {
886  pips_debug(1, "\n\nAt iteration i=%d:\n\n", i);
887  print_points_to_set("Loop points-to set pt_out_prev:\n",
888  points_to_graph_set(pt_out_prev));
889  print_points_to_set("Loop points-to set pt_out:\n",
890  points_to_graph_set(pt_out));
891  }
892  }
893  }
894 
895  if(!fix_point_p) {
896  print_points_to_set("Loop points-to set pt_out:\n", points_to_graph_set(pt_out));
897  print_points_to_set("Loop points-to set pt_out_prev:\n", points_to_graph_set(pt_out_prev));
898  pips_internal_error("Loop convergence not reached after %d iterations.\n", k+2);
899  }
900 
901  /* FI: I suppose that p[i] is replaced by p[*] and that MAY/MUST
902  information is changed accordingly. */
903  points_to_graph_set(pt_out) =
905 
906  pt_out = merge_points_to_graphs(pt_out, pt_out_skip);
907  }
908 
909  return pt_out;
910 }

References assign_pt_map, clear_pt_map, condition_to_points_to(), expression_to_points_to(), expression_undefined_p, full_copy_pt_map(), get_int_property(), init, merge_points_to_graphs(), new_pt_map, normalize_points_to_graph(), pips_debug, pips_internal_error, points_to_graph_bottom, points_to_graph_set, points_to_independent_store(), print_points_to_set(), set_equal_p(), and statement_to_points_to().

+ Here is the call graph for this function:

◆ new_filter_formal_context_according_to_actual_context()

set new_filter_formal_context_according_to_actual_context ( list  fpcl,
set  pt_in,
set  pt_binded,
set  binding 
)

Copy arcs "pt" from "pt_in" into the "filtered" set if they are compatible with "pt_binded". The set "filtered" is a subset of "pt_in".

Do we have the same arc in pt_binded?

We have to deal recursively with stubs of the formal context and first with the global variables... although they, or their stubs, do not require any translation? Why is the points-to information about q lost in the translation of the call site to call03 in main (PointersWithEffects/call03.c)

FI: I do not understand why I have to do this for EffectsWithPointsTo/pointer_modif04.c. Because the arc "pt" in "pt_in" is more precise than the information available in "pt_caller". For instance, "pt_in" may contain "stderr->_stderr_0[0], Exact", while "pt_caller" may contain "stderr->_stderr_0[0], May", "stderr->NULL, May". Basically, we have not thought about the kill set generated for the global variables.

Useless when called from effects... In fact, it should never be called from effects...

FI: we do not know what we really do here... An arc is not taken into account, but it might be taken into account recursively below.

Compute the binding relation for sinks of the formal arguments and global variables

We have to handle constant strings such as "Hello!" and not to forget functional parameters.

Some arcs have been removed, so other arcs may be promoted from "may" to "exact".

Parameters
fpclpcl
pt_int_in
pt_bindedt_binded
bindinginding

Definition at line 1039 of file interprocedural.c.

1043 {
1044  bool ok_p = true;
1045  set filtered = new_simple_pt_map();
1046 
1047  /* Copy arcs "pt" from "pt_in" into the "filtered" set if they are
1048  compatible with "pt_binded". The set "filtered" is a subset of
1049  "pt_in". */
1050  SET_FOREACH(points_to, pt, pt_in) {
1051  cell source = points_to_source(pt);
1052  if(related_points_to_cell_in_list_p(source, fpcl)) {
1053  cell sink = points_to_sink(pt);
1054  if(null_cell_p(sink)) {
1055  /* Do we have the same arc in pt_binded? */
1056  if(arc_in_points_to_set_p(pt, pt_binded)) {
1057  points_to npt = copy_points_to(pt);
1058  add_arc_to_simple_pt_map(npt, filtered);
1059  }
1060  else {
1061  ; // do not copy this arc in filtered set
1062  }
1063  }
1064  else {
1065  if(cell_points_to_non_null_sink_in_set_p(source, pt_binded)) {
1066  points_to npt = copy_points_to(pt);
1067  add_arc_to_simple_pt_map(npt, filtered);
1068  }
1069  else {
1070  ; // do not copy this arc in filtered set
1071  }
1072  }
1073  }
1074  else {
1075  /* We have to deal recursively with stubs of the formal context
1076  and first with the global variables... although they, or their
1077  stubs, do not require any translation? Why is the points-to
1078  information about q lost in the translation of the call site
1079  to call03 in main (PointersWithEffects/call03.c) */
1080  reference r = cell_any_reference(source);
1081  entity v = reference_variable(r);
1082  if(!arc_in_points_to_set_p(pt, pt_binded)) {
1083  // FI: necessary for Pointers/global10
1085  //gvcl = CONS(CELL, source, gvcl);
1086  points_to npt = copy_points_to(pt);
1087  add_arc_to_simple_pt_map(npt, filtered);
1088  /* FI: I do not understand why I have to do this for
1089  EffectsWithPointsTo/pointer_modif04.c. Because the arc "pt"
1090  in "pt_in" is more precise than the information available
1091  in "pt_caller". For instance, "pt_in" may contain
1092  "stderr->_stderr_0[0], Exact", while "pt_caller" may
1093  contain "stderr->_stderr_0[0], May", "stderr->NULL,
1094  May". Basically, we have not thought about the kill set
1095  generated for the global variables. */
1097  /* Useless when called from effects... In fact, it should
1098  never be called from effects... */
1099  //add_arc_to_points_to_context(npt);
1101  }
1102  else {
1103  // pips_internal_error("This function should not reach this point"
1104  // " when called from effects, simple or generic.");
1105  // update_points_to_context_with_arc(npt);
1106  ; // Do nothing
1107  }
1108  }
1109  else {
1110  /* FI: we do not know what we really do here... An arc is not
1111  taken into account, but it might be taken into account
1112  recursively below. */
1113  ;
1114  }
1115  }
1116  }
1117  }
1118 
1119  /* Compute the binding relation for sinks of the formal arguments
1120  and global variables */
1121  points_to_graph filtered_g = make_points_to_graph(false, filtered);
1122  points_to_graph pt_binded_g = make_points_to_graph(false, pt_binded);
1123  FOREACH(CELL, c, fpcl) {
1124  list fl = points_to_source_to_any_sinks(c, filtered_g, false); // formal list
1125  list al = points_to_source_to_any_sinks(c, pt_binded_g, false); // actual list
1126  int nfl = (int) gen_length(fl);
1127  int nal = (int) gen_length(al);
1129 
1130  // FI: que fait-on avec nfl==0, comme dans
1131  // Pointers/StrictTyping.sub/struct08.c ou nfl vaut 0 parce que le
1132  // parametre effectif est undefined?
1133 
1134  if(nfl==1 && nal==1)
1135  approx = make_approximation_exact();
1136  else
1137  approx = make_approximation_may();
1138  FOREACH(CELL, fc, fl) {
1139  if(!null_cell_p(fc)) {
1140  FOREACH(CELL, ac, al) {
1141  if(!null_cell_p(ac) && !nowhere_cell_p(ac)) {
1145  /* We have to handle constant strings such as "Hello!"
1146  and not to forget functional parameters. */
1147  if(type_functional_p(ac_t)) {
1148  reference ar = cell_any_reference(ac);
1149  entity a = reference_variable(ar);
1150  if(constant_string_entity_p(a)) {
1151  ac_t = functional_result(type_functional(iac_t));
1152  }
1153  }
1154  // FI: which type equality should be chosen ?
1155  // if(!type_structurally_equal_p(fc_t, ac_t)
1156  if(!array_pointer_string_type_equal_p(fc_t, ac_t)
1157  && !overloaded_type_p(ac_t)) {
1158  if(array_type_p(ac_t)) {
1161  if(!type_structurally_equal_p(fc_t, ac_nt) && !overloaded_type_p(ac_nt)) {
1162  // Pointers/pointer14.c
1163  // FI: I am not sure it is the best translation
1164  // It might be better to remove some zero subscripts from fc
1167  if(!type_structurally_equal_p(fc_t, ac_nnt) && !overloaded_type_p(ac_nnt))
1168  pips_internal_error("translation failure for an array.\n");
1169  }
1170  }
1171  else {
1172  reference fr = cell_any_reference(fc);
1174  ;
1175  else {
1177  reference ar = cell_any_reference(ac);
1178  semantics_user_warning("Type \"%s\" for formal reference \"%s\" is incompatible with type \"%s\" for actual reference \"%s\".\n",
1180  reference_to_string(fr),
1182  reference_to_string(ar));
1183  if(get_bool_property("POINTS_TO_STRICT_POINTER_TYPES")) {
1185  ("Translation failure for actual parameter \"%s\" at line %d.\n"
1186  "Maybe property POINTS_TO_STRICT_POINTER_TYPES should be reset.\n",
1187  reference_to_string(ar),
1189  // pips_internal_error("translation failure.\n");
1190  }
1191  else {
1193  ("Translation failure for actual parameter \"%s\" at line %d.\n",
1194  reference_to_string(ar),
1196  }
1197  }
1198  }
1199  }
1201  copy_cell(ac),
1202  copy_approximation(approx),
1206  (fc, ac, approx, pt_in, pt_binded, binding, filtered);
1207  }
1208  else if(null_cell_p(ac)) {
1209  ; // What should be done?
1210  }
1211  else {
1212  // nowhere_cell_p(ac)
1213  ; // What should be done?
1214  }
1215  }
1216  }
1217  }
1218 
1219  free_approximation(approx);
1220  }
1221 
1222  ifdebug(8) {
1223  pips_debug(8, "First filtered IN set for callee at call site:\n");
1224  print_points_to_set("", filtered);
1225  pips_debug(8, "First translation mapping for call site:\n");
1226  print_points_to_set("", binding);
1227  }
1228 
1229  pips_assert("The points-to translation mapping is well typed",
1231 
1232  if(ok_p) {
1233  /* Some arcs have been removed, so other arcs may be promoted from
1234  "may" to "exact". */
1236  }
1237  else {
1238  set_free(filtered);
1239  filtered = set_undefined;
1240  }
1241 
1242  ifdebug(8) {
1243  pips_debug(8, "Final filtered IN set for callee at call site:\n");
1244  print_points_to_set("", filtered);
1245  pips_debug(8, "Final mapping for call site:\n");
1246  print_points_to_set("", binding);
1247  }
1248 
1249  return filtered;
1250 }
static bool new_recursive_filter_formal_context_according_to_actual_context(cell fc, cell ac, approximation ap, set pt_in, set pt_binded, set binding, set filtered)
The code is derived from generic_points_to_cell_to_useful_pointer_cell() with no filtering and a dire...

References adapt_reference_to_type(), add_arc_to_simple_pt_map, add_subscript_dependent_arc_to_simple_pt_map(), approximation_undefined, arc_in_points_to_set_p(), array_pointer_string_type_equal_p(), array_type_p(), CELL, cell_any_reference(), cell_points_to_non_null_sink_in_set_p(), constant_string_entity_p(), constant_string_type_to_string_type(), copy_approximation(), copy_cell(), copy_points_to(), FOREACH, free_approximation(), functional_result, gen_length(), get_bool_property(), global_variable_p(), ifdebug, int, make_approximation_exact(), make_approximation_may(), make_descriptor_none(), make_points_to(), make_points_to_graph(), new_recursive_filter_formal_context_according_to_actual_context(), new_simple_pt_map, nowhere_cell_p(), null_cell_p(), overloaded_type_p(), pips_assert, pips_debug, pips_internal_error, pips_user_error, points_to_cell_add_zero_subscript(), points_to_cell_complete_with_zero_subscripts(), points_to_cell_to_concrete_type(), points_to_context_statement_line_number(), points_to_reference_to_concrete_type(), points_to_sink, points_to_source, points_to_source_to_any_sinks(), points_to_translation_mapping_is_typed_p(), print_points_to_set(), reference_to_string(), reference_variable, related_points_to_cell_in_list_p(), semantics_user_warning, SET_FOREACH, set_free(), set_undefined, statement_points_to_context_defined_p(), static_global_variable_p(), type_functional, type_functional_p, type_structurally_equal_p(), type_to_full_string_definition(), update_points_to_context_with_arc(), and upgrade_approximations_in_points_to_set().

Referenced by user_call_to_points_to_interprocedural(), and user_call_to_points_to_interprocedural_binding_set().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ new_points_to_unstructured()

pt_map new_points_to_unstructured ( unstructured  ,
pt_map  ,
bool   
)

Referenced by unstructured_to_points_to().

+ Here is the caller graph for this function:

◆ node_in_points_to_path_p()

bool node_in_points_to_path_p ( cell  n,
list  p 
)

Definition at line 985 of file points_to_set.c.

986 {
987  bool in_path_p = false;
988  FOREACH(CELL, c, p) {
989  if(cell_equal_p(c, n)) {
990  in_path_p = true;
991  break;
992  }
993  }
994  return in_path_p;
995 }

References CELL, cell_equal_p(), and FOREACH.

Referenced by points_to_path_to_k_limited_points_to_path().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ non_equal_condition_to_points_to()

pt_map non_equal_condition_to_points_to ( list  al,
pt_map  in 
)

The expression list "al" contains exactly two arguments.

If these expressions are pointers, "in" is modified by removing arcs that are not compatible with the equality. If no arc is left, a bottom "in" is returned.

"out" is "in", modified by side-effects.

Is the condition lhs!=rhs certainly impossible to evaluate? If not, is it always false?

Parameters
all
inn

Definition at line 3086 of file expression.c.

3087 {
3088  // FI: this code is almost identical to the code above
3089  // It should be shared with a more general test first and then a
3090  // precise test to decide if you add or remove arcs
3091  pt_map out = in;
3092  expression lhs = EXPRESSION(CAR(al));
3093  expression rhs = EXPRESSION(CAR(CDR(al)));
3094 
3095  // FI: in fact, any integer could be used in a pointer comparison...
3096  if(expression_null_p(lhs))
3098  else if(expression_null_p(rhs))
3100  else {
3101  type lhst = expression_to_type(lhs);
3102  type rhst = expression_to_type(rhs);
3103  if(pointer_type_p(lhst) && pointer_type_p(rhst)) {
3105  list R = expression_to_points_to_sinks(rhs, in);
3106  //bool equal_p = false;
3107  int nL = (int) gen_length(L);
3108  int nR = (int) gen_length(R);
3109  pips_assert("The two expressions can be dereferenced", nL>=1 && nR>=1);
3110  if(nL==1 && nR==1) {
3111  cell cl = CELL(CAR(L));
3112  cell cr = CELL(CAR(R));
3113  /* Is the condition lhs!=rhs certainly impossible to evaluate?
3114  * If not, is it always false? */
3115  if((atomic_points_to_cell_p(cl)
3117  && points_to_cell_equal_p(cl, cr))
3118  || nowhere_cell_p(cl)
3119  || nowhere_cell_p(cr)) {
3120  // one or more expressions is not evaluable or the condition
3121  // is not feasible
3122  clear_pt_map(out);
3123  points_to_graph_bottom(out) = true;
3124  if(nowhere_cell_p(cl))
3125  pips_user_warning("Unitialized pointer is used to evaluate expression"
3126  " \"%s\" at line %d.\n",
3127  expression_to_string(lhs),
3129  if(nowhere_cell_p(cr))
3130  pips_user_warning("Unitialized pointer is used to evaluate expression"
3131  " \"%s\" at line %d.\n",
3132  expression_to_string(rhs),
3134  }
3135  }
3136  else {
3137  // It is possible to remove some arcs? if18.c
3138  int nL = (int) gen_length(L);
3139  int nR = (int) gen_length(R);
3140  cell c = cell_undefined;
3141  list O = list_undefined;
3142  if(nL==1 && atomic_points_to_cell_p(CELL(CAR(L)))) {
3143  c = CELL(CAR(L));
3145  }
3146  else if(nR==1 && atomic_points_to_cell_p(CELL(CAR(R)))) {
3147  c = CELL(CAR(R));
3149  }
3150  if(!cell_undefined_p(c)) {
3151  if((int) gen_length(O)==1) {
3152  cell oc = CELL(CAR(O));
3154  copy_cell(c),
3158  // Should we free pt? Or is it done by remove_arc_from_pt_map()?
3159  }
3160  }
3161  }
3162  }
3163  free_type(lhst), free_type(rhst);
3164  }
3165  return in;
3166 }
pt_map null_non_equal_condition_to_points_to(expression e, pt_map in)
The condition is e!=NULL.
Definition: expression.c:2927

References atomic_points_to_cell_p(), CAR, CDR, CELL, cell_undefined, cell_undefined_p, clear_pt_map, copy_cell(), EXPRESSION, expression_null_p(), expression_to_points_to_sinks(), expression_to_points_to_sources(), expression_to_string(), expression_to_type(), free_type(), gen_length(), int, list_undefined, make_approximation_may(), make_descriptor_none(), make_points_to(), nowhere_cell_p(), null_non_equal_condition_to_points_to(), out, pips_assert, pips_user_warning, pointer_type_p(), points_to_cell_equal_p(), points_to_context_statement_line_number(), points_to_graph_bottom, and remove_arc_from_pt_map.

Referenced by relational_intrinsic_call_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ normalize_points_to_graph()

pt_map normalize_points_to_graph ( pt_map  ptg)

For the time being, control the out-degree of the vertices in points-to graph "ptg" and fuse the vertex with the maximal out-degree to reduce it if it is greater than an expected limit.

Points-to graph "ptg" i modified by side-effects and returned.

The out-degree limit must take the subscript limit sl into account as well as possible NULL and NOWHERE values (+2). The unbounded susbcript must also be added because it does not necessarily subsume all integer subscripts (+1). The subscript limit will kick in anyway later. Subscripts are limited to the range [-sl,sl], which contains 2*sl+1 values.

Parameters
ptgtg

Definition at line 3329 of file points_to_set.c.

3330 {
3331  int odl = get_int_property("POINTS_TO_OUT_DEGREE_LIMIT");
3332  int sl = get_int_property("POINTS_TO_SUBSCRIPT_LIMIT");
3333 
3334  /* The out-degree limit must take the subscript limit sl into
3335  account as well as possible NULL and NOWHERE values (+2). The
3336  unbounded susbcript must also be added because it does not
3337  necessarily subsume all integer subscripts (+1). The subscript
3338  limit will kick in anyway later. Subscripts are limited to the
3339  range [-sl,sl], which contains 2*sl+1 values. */
3340  if(odl<2*sl+1+2) odl = 2*sl+1+2+1;
3341 
3342  pips_assert("odl is greater than one", odl>=1);
3343  string mod_cell_name = string_undefined; // maximum out-degree cell
3344  int od = maximal_out_degree_of_points_to_graph(&mod_cell_name, ptg);
3345  if(od>odl) {
3346  ifdebug(1) {
3347  pips_debug(1, "Normalization takes place for graph \"ptg\" with \"od\"=%d and \"odl\"=%d:\n", od, odl);
3348  print_points_to_set("Loop points-to set ptg:\n",
3349  points_to_graph_set(ptg));
3350  }
3351  // FI: not too sure about argument "true"
3352  cell mod_cell = points_to_source_name_to_source_cell(mod_cell_name, ptg, true);
3353  if(cell_undefined_p(mod_cell))
3354  pips_internal_error("Inconsistent result for ptg.\n");
3355  list sink_l = points_to_source_name_to_sinks(mod_cell_name, ptg, false);
3356  points_to pt = fuse_points_to_sink_cells(mod_cell, sink_l, ptg);
3357  add_arc_to_pt_map(pt, ptg);
3358  ifdebug(1) {
3359  pips_debug(1, "After normalization, \"ptg\":\n");
3360  print_points_to_set("Loop points-to set ptg:\n",
3361  points_to_graph_set(ptg));
3362  }
3363  }
3364  return ptg;
3365 }
points_to fuse_points_to_sink_cells(cell source, list sink_l, pt_map in)
All vertices in "sink_l" are assumed to be sinks of vertex "source" in points-to graph "in".
cell points_to_source_name_to_source_cell(string sn, pt_map ptm, bool fresh_p)
list points_to_source_name_to_sinks(string sn, pt_map ptm, bool fresh_p)
Use "sn" as a source name to derive a list of sink cells according to the points-to graph ptm.
void print_points_to_set(string what, set s)
int maximal_out_degree_of_points_to_graph(string *mod_cell, pt_map in)
returns the cell vertex "mod_cell" with the maximal out_degree in graph "in", and its out-degree.

References add_arc_to_pt_map(), cell_undefined_p, fuse_points_to_sink_cells(), get_int_property(), ifdebug, maximal_out_degree_of_points_to_graph(), pips_assert, pips_debug, pips_internal_error, points_to_graph_set, points_to_source_name_to_sinks(), points_to_source_name_to_source_cell(), print_points_to_set(), and string_undefined.

Referenced by any_loop_to_points_to(), and new_any_loop_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nowhere_source_to_sinks()

list nowhere_source_to_sinks ( cell  source,
pt_map  pts 
)
Parameters
sourceource
ptsts

Definition at line 1329 of file points_to_set.c.

1330 {
1331  list sinks = NIL;
1332  bool uninitialized_dereferencing_p =
1333  get_bool_property("POINTS_TO_UNINITIALIZED_POINTER_DEREFERENCING");
1334 
1335  if(uninitialized_dereferencing_p) {
1336  reference r = cell_any_reference(source);
1337  entity v = reference_variable(r);
1338  pips_user_warning("Possibly undefined pointer \"%s\" is dereferenced.\n",
1339  entity_local_name(v));
1340  sinks = anywhere_source_to_sinks(source, pts);
1341  }
1342 
1343  return sinks;
1344 }

References anywhere_source_to_sinks(), cell_any_reference(), entity_local_name(), get_bool_property(), NIL, pips_user_warning, and reference_variable.

Referenced by source_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ null_equal_condition_to_points_to()

pt_map null_equal_condition_to_points_to ( expression  e,
pt_map  in 
)

The condition is e==NULL.

e==NULL may be true if exists c in sinks(e) s.t. {NULL} is included in c. else e==NULL must be false.

Some arcs in in may be removed: forall c in sources(e):

out = in - {pt=(a,b) in in | a in sources(e) and b=NULL}

May the condition be true under "in"?

If NULL initialization is not performed, a stub can represent a NULL.

Remove arcs incompatible with the condition e==NULL and add the arc e->NULL

All arcs starting from fc can be removed and replaced by one arc from fc to NULL.

Parameters
inn

Definition at line 2849 of file expression.c.

2850 {
2851  pt_map out = in;
2852  type et = expression_to_type(e);
2853  if(pointer_type_p(et)) {
2855  bool null_initialization_p
2856  = get_bool_property("POINTS_TO_NULL_POINTER_INITIALIZATION");
2857 
2858  if(ENDP(R)) {
2859  // Maybe, a dereferencement user error occured?
2860  pips_internal_error("A dereferencement should always succeed.\n");
2861  }
2862 
2863  /* May the condition be true under "in"? */
2864  bool found_p = false;
2865  FOREACH(CELL, c, R) {
2866  if(null_cell_p(c)
2867  || anywhere_cell_p(c)
2869  /* If NULL initialization is not performed, a stub can
2870  represent a NULL. */
2871  || (!null_initialization_p && stub_points_to_cell_p(c))) {
2872  found_p = true;
2873  break;
2874  }
2875  }
2876  if(!found_p) {
2877  clear_pt_map(out);
2878  points_to_graph_bottom(out) = true;
2879  }
2880  else {
2881  /* Remove arcs incompatible with the condition e==NULL and add
2882  the arc e->NULL */
2884  pips_assert("A lhs expression has at least one source", !ENDP(L));
2885  int nL = (int) gen_length(L);
2886  cell fc = CELL(CAR(L));
2887  if(nL==1 && atomic_points_to_cell_p(fc)) {
2888  /* All arcs starting from fc can be removed and replaced by
2889  one arc from fc to NULL. */
2892  make_null_cell(),
2895  add_arc_to_pt_map(pt, out);
2896  }
2897  else {
2899  cell source = points_to_source(pt);
2900  if(cell_in_list_p(source, L)) {
2901  cell sink = points_to_sink(pt);
2902  if(!(null_cell_p(sink)
2903  || anywhere_cell_p(sink)
2904  || cell_typed_anywhere_locations_p(sink))) {
2906  }
2907  }
2908  }
2909  }
2910  }
2911  gen_free_list(R); // FI: should be full?
2912  }
2913  return out;
2914 }
bool cell_in_list_p(cell, const list)

References add_arc_to_pt_map, anywhere_cell_p(), atomic_points_to_cell_p(), CAR, CELL, cell_in_list_p(), cell_typed_anywhere_locations_p(), clear_pt_map, copy_cell(), ENDP, expression_to_points_to_sinks(), expression_to_points_to_sources(), expression_to_type(), FOREACH, gen_free_list(), gen_length(), get_bool_property(), int, make_approximation_exact(), make_descriptor_none(), make_null_cell(), make_points_to(), null_cell_p(), out, pips_assert, pips_internal_error, pointer_type_p(), points_to_cell_source_projection(), points_to_graph_bottom, points_to_graph_set, points_to_sink, points_to_source, remove_arc_from_pt_map_, SET_FOREACH, and stub_points_to_cell_p().

Referenced by equal_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ null_non_equal_condition_to_points_to()

pt_map null_non_equal_condition_to_points_to ( expression  e,
pt_map  in 
)

The condition is e!=NULL.

e!=NULL may be true if exists c in sinks(e) s.t. c != {NULL}

e!=NULL is false if forall c in sinks(e) c is included in {NULL}

Arcs that can be removed:

FI: I decided not to merge this function with the previous one till they are both fully defined and tested.

May the condition be true under "in"?

Remove arcs incompatible with the condition e!=NULL

Parameters
inn

Definition at line 2927 of file expression.c.

2928 {
2929  pt_map out = in;
2930  type et = expression_to_type(e);
2931  if(pointer_type_p(et)) {
2933 
2934  if(ENDP(L)) {
2935  // Maybe, a dereferencement user error occured?
2936  pips_internal_error("A dereferencement should always succeed.\n");
2937  }
2938 
2939  /* May the condition be true under "in"? */
2940  bool found_p = false;
2941  FOREACH(CELL, c, L) {
2942  if(!null_cell_p(c)) {
2943  found_p = true;
2944  break;
2945  }
2946  }
2947  if(!found_p) {
2948  clear_pt_map(out);
2949  points_to_graph_bottom(out) = true;
2950  }
2951  else {
2952  /* Remove arcs incompatible with the condition e!=NULL */
2955  cell source = points_to_source(pt);
2956  if(cell_in_list_p(source, L)) {
2957  cell sink = points_to_sink(pt);
2958  if(null_cell_p(sink)) {
2960  }
2961  }
2962  }
2963  }
2964  }
2965  return out;
2966 }

References CELL, cell_in_list_p(), clear_pt_map, ENDP, expression_to_points_to_sinks(), expression_to_points_to_sources(), expression_to_type(), FOREACH, null_cell_p(), out, pips_internal_error, pointer_type_p(), points_to_graph_bottom, points_to_graph_set, points_to_sink, points_to_source, remove_arc_from_pt_map_, and SET_FOREACH.

Referenced by non_equal_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ null_source_to_sinks()

list null_source_to_sinks ( cell  source,
pt_map  pts 
)
Parameters
sourceource
ptsts

Definition at line 1346 of file points_to_set.c.

1347 {
1348  list sinks = NIL;
1349  bool null_dereferencing_p =
1350  get_bool_property("POINTS_TO_NULL_POINTER_DEREFERENCING");
1351 
1352  if(null_dereferencing_p) {
1353  reference r = cell_any_reference(source);
1354  entity v = reference_variable(r);
1355  pips_user_warning("Possibly null pointer \"%s\" is dereferenced.\n",
1356  entity_local_name(v));
1357  sinks = anywhere_source_to_sinks(source, pts);
1358  }
1359 
1360  return sinks;
1361 }

References anywhere_source_to_sinks(), cell_any_reference(), entity_local_name(), get_bool_property(), NIL, pips_user_warning, and reference_variable.

Referenced by source_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ null_to_sinks()

list null_to_sinks ( cell  source,
pt_map  ptm 
)

Create a list of null sinks and add a new null points-to relation to pts.

pts is modified by side effect.

Parameters
sourceource
ptmtm

Definition at line 2505 of file points_to_set.c.

2506 {
2507  cell nsource = copy_cell(source);
2509  points_to npt = make_points_to(nsource, nsink,
2512  ptm = add_arc_to_pt_map_(npt, ptm);
2514  list sinks = CONS(CELL, copy_cell(nsink), NIL);
2515  return sinks;
2516 }
cell make_null_pointer_value_cell(void)

References add_arc_to_points_to_context(), add_arc_to_pt_map_(), CELL, CONS, copy_cell(), copy_points_to(), make_approximation_may(), make_descriptor_none(), make_null_pointer_value_cell(), make_points_to(), and NIL.

Referenced by formal_source_to_sinks(), generic_stub_source_to_sinks(), global_source_to_sinks(), and points_to_cell_null_initialization().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ offset_array_reference()

void offset_array_reference ( reference  r,
expression  delta,
type  et 
)

Side effect on reference "r".

r is assumed to be a reference to an array.

The offset is applied to the last suscript.

Parameters
deltaelta
ett

Definition at line 802 of file expression.c.

803 {
804  value v = EvalExpression(delta);
805  list rsl = reference_indices(r);
807  int dv = constant_int(value_constant(v));
808  if(ENDP(rsl)) {
809  // FI: oops, we are in trouble; assume 0...
810  expression se = int_to_expression(dv);
812  }
813  else {
814  // Select the index that should be subscripted
816  expression lse = EXPRESSION(CAR(sl));
817  value vlse = EvalExpression(lse);
818  if(value_constant_p(vlse) && constant_int_p(value_constant(vlse))) {
819  int ov = constant_int(value_constant(vlse));
820  int k = get_int_property("POINTS_TO_SUBSCRIPT_LIMIT");
821  if(-k <= ov && ov <= k) {
822  expression nse = int_to_expression(dv+ov);
823  //EXPRESSION_(CAR(gen_last(sl))) = nse;
824  EXPRESSION_(CAR(sl)) = nse;
825  }
826  else {
828  //EXPRESSION_(CAR(gen_last(sl))) = nse;
829  EXPRESSION_(CAR(sl)) = nse;
830  }
831  free_expression(lse);
832  }
833  else {
834  // FI: assume * is used... UNBOUNDED_DIMENSION
836  //EXPRESSION_(CAR(gen_last(sl))) = nse;
837  EXPRESSION_(CAR(sl)) = nse;
838  free_expression(lse);
839  }
840  }
841  }
842  else {
843  if(ENDP(rsl)) {
845  reference_indices(r) = CONS(EXPRESSION, nse, NIL);
846  }
847  else {
849  expression ose = EXPRESSION(CAR(sl));
851  EXPRESSION_(CAR(sl)) = nse;
852  free_expression(ose);
853  }
854  }
855 }
list points_to_reference_to_typed_index(reference, type)
Look for the index in "r" that corresponds to a pointer of type "t" and return the corresponding elem...
Definition: points_to.c:361
value EvalExpression(expression e)
Evaluate statically an expression.
Definition: eval.c:108
#define EXPRESSION_(x)
Definition: ri.h:1220

References CAR, CONS, constant_int, constant_int_p, ENDP, EvalExpression(), EXPRESSION, EXPRESSION_, free_expression(), get_int_property(), int_to_expression(), make_unbounded_expression(), NIL, points_to_reference_to_typed_index(), reference_indices, value_constant, and value_constant_p.

Referenced by offset_cell().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ offset_cell()

points_to offset_cell ( points_to  pt,
expression  delta,
type  et 
)

Allocate and return a new points-to "npt", copy of "pt", with an offset of "delta" on the sink.

"et" is used to determine which index should be offseted.

Some kind of k-limiting should be performed here to avoid creating too many new nodes in the points-to graph, such as t[0], t[1],... A fix point t[*] should be used when too may nodes already exist.

Since "sink" is used to compute the key in the hash table used to represent set "in", it is not possible to perform a side effect on "sink" without removing and reinserting the corresponding arc.

FI: I am not sure we have the necessary information to know which subscript must be updated when more than one is available. This is bad for multidimensional arrays and worse for references to stub that may include fields (or not) as subscript as well as lots of articificial dimensions due to the source.

I assumed gen_last() to start with, but it is unlikely in general!

"&a[i]" should be transformed into "&a[i+eval(delta)]" when "delta" can be statically evaluated

| !get_bool_property("POINTS_TO_STRICT_POINTER_TYPES")

Parameters
ptt
deltaelta
ett

Definition at line 937 of file expression.c.

938 {
939  /* "&a[i]" should be transformed into "&a[i+eval(delta)]" when
940  "delta" can be statically evaluated */
941  points_to npt = copy_points_to(pt);
942  cell sink = points_to_sink(npt);
943  reference r = cell_any_reference(sink);
944  entity v = reference_variable(r);
945  if(nowhere_cell_p(sink))
946  ; // user error: possible incrementation of an uninitialized pointer
947  else if(null_cell_p(sink))
948  ; // Impossible: possible incrementation of a NULL pointer
949  else if(anywhere_cell_p(sink))
950  ; // It is already fuzzy no need to add more
951  // FI: it might be necessary to exclude *HEAP* too when a minimal
952  // heap model is used (ABSTRACT_HEAP_LOCATIONS = "unique")
953  else {
955  // FI: I do not understand why this is based on the type of v and
956  // not on the ype of r
957  if(array_type_p(vt)
958  // FI: the property should have been taken care of earlier when
959  // building sink
960  /*|| !get_bool_property("POINTS_TO_STRICT_POINTER_TYPES")*/) {
961  cell source = points_to_source(npt);
962  bool to_be_freed;
963  type source_t = points_to_cell_to_type(source, &to_be_freed);
964  type c_source_t = compute_basic_concrete_type(source_t);
965  if(to_be_freed) free_type(source_t);
966  type pt = type_to_pointed_type(c_source_t);
967  type e_sink_t = compute_basic_concrete_type(pt);
968  if(array_pointer_type_equal_p(vt, e_sink_t)
969  && get_bool_property("POINTS_TO_STRICT_POINTER_TYPES"))
970  pips_user_error("Use of pointer arithmetic on \"%s\" at line %d via reference \"%s\" is not "
971  "standard-compliant.\n"
972  "Reset property \"POINTS_TO_STRICT_POINTER_TYPES\""
973  " for usual non-standard compliant C code.\n",
974  entity_user_name(v),
977  else
978  offset_array_reference(r, delta, et);
979  }
980  else if(struct_type_p(vt)) {
981  // The struct may contain an array field.
982  // FI: should we check the existence of the field in the subscripts?
983  offset_array_reference(r, delta, et);
984  }
986  // FI: waiting for ROM buffers containing the constant strings...
987  offset_array_reference(r, delta, et);
988  }
989  // FI to be extended to pointers and points-to stubs
990  else {
991  cell source = points_to_source(npt);
992  if(get_bool_property("POINTS_TO_STRICT_POINTER_TYPES")) {
993  pips_user_error("Use of pointer arithmetic on \"%s\" at line %d via reference \"%s\" is not "
994  "standard-compliant.\n"
995  "Reset property \"POINTS_TO_STRICT_POINTER_TYPES\""
996  " for usual non-standard compliant C code.\n",
997  entity_user_name(v),
1000  }
1001  else {
1002  pips_user_error("Use of pointer arithmetic on \"%s\" at line %d via reference \"%s\" is not "
1003  "standard-compliant.\n",
1004  entity_user_name(v),
1007  }
1008  }
1009  }
1010  return npt;
1011 }
void offset_array_reference(reference r, expression delta, type et)
Side effect on reference "r".
Definition: expression.c:802

References anywhere_cell_p(), array_pointer_type_equal_p(), array_type_p(), cell_any_reference(), char_star_constant_function_type_p(), compute_basic_concrete_type(), copy_points_to(), effect_reference_to_string(), entity_basic_concrete_type(), entity_user_name(), free_type(), get_bool_property(), nowhere_cell_p(), null_cell_p(), offset_array_reference(), pips_user_error, points_to_cell_to_type(), points_to_context_statement_line_number(), points_to_sink, points_to_source, reference_variable, struct_type_p(), and type_to_pointed_type().

Referenced by offset_cells().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ offset_cells()

void offset_cells ( cell  source,
list  sinks,
expression  delta,
type  et,
pt_map  in 
)

Each cell in sinks is replaced by a cell located "delta" elements further up in the memory.

In some cases, the same points-to are removed and added. For instance, t[0],t[1] -> t[1],t[2] because of a p++, and t[1] is removed and added.

If the source may point to null, the corresponding arc is removed. If the source points only to null, the resulting graph is bottom.

This procedure must be used when cells in "sinks" are components of points-to arcs stored in a points-to set.

Parameters
sourceource
sinksinks
deltaelta
ett
inn

Definition at line 869 of file expression.c.

870 {
871  // FI: it would be easier to use two lists of arcs rather than sets.
872  // FI: should we assert that expression delta!=0?
873  pt_map old = new_pt_map();
874  pt_map new = new_pt_map();
875  bool unfeasible_p = false;
876  FOREACH(CELL, sink, sinks) {
877  if(!anywhere_cell_p(sink) && !cell_typed_anywhere_locations_p(sink)) {
878  points_to pt = find_arc_in_points_to_set(source, sink, in);
879  // FI: the arc may not be found; for instance, you know that
880  // _pp_1[1] points towards *NULL_POINTER*, but this is due to an arc
881  // _pp_1[*]->*NULL_POINTER*; this arc does not have to be updated
882  if(!points_to_undefined_p(pt)) {
883  if(null_cell_p(sink)) {
884  add_arc_to_pt_map(pt, old);
885  if(gen_length(sinks)==1) {
886  semantics_user_warning("Arithmetic operation performed on NULL pointer \"%s\".\n", points_to_cell_to_string(source));
887  unfeasible_p = true;
888  }
889  else
890  semantics_user_warning("Arithmetic operation performed on \"%s\", which might be a NULL pointer.\n", points_to_cell_to_string(source));
891  }
892  else {
893  add_arc_to_pt_map(pt, old);
894  points_to npt = offset_cell(pt, delta, et);
895  add_arc_to_pt_map(npt, new);
896  }
897  }
898  else {
899  // Another option would be to generate nothing in this case
900  // since it is taken care of by the lattice...
901 
902  // Since pt has not been found in "in", the approximation must be may
903  pt = make_points_to(copy_cell(source), copy_cell(sink),
906  points_to npt = offset_cell(pt, delta, et);
907  add_arc_to_pt_map(npt, new);
908  }
909  }
910  }
911  difference_of_pt_maps(in, in, old);
912  union_of_pt_maps(in, in, new);
913  if(unfeasible_p)
914  points_to_graph_bottom(in) = true;
915 }
#define difference_of_pt_maps(pt1, pt2, pt3)
#define union_of_pt_maps(pt1, pt2, pt3)
points_to offset_cell(points_to pt, expression delta, type et)
Allocate and return a new points-to "npt", copy of "pt", with an offset of "delta" on the sink.
Definition: expression.c:937
points_to find_arc_in_points_to_set(cell, cell, pt_map)
The approximation is not taken into account.

References add_arc_to_pt_map, anywhere_cell_p(), CELL, cell_typed_anywhere_locations_p(), copy_cell(), difference_of_pt_maps, find_arc_in_points_to_set(), FOREACH, gen_length(), make_approximation_may(), make_descriptor_none(), make_points_to(), new_pt_map, null_cell_p(), offset_cell(), points_to_cell_to_string(), points_to_graph_bottom, points_to_undefined_p, semantics_user_warning, and union_of_pt_maps.

Referenced by pointer_arithmetic_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ offset_points_to_cell()

void offset_points_to_cell ( cell  ,
expression  ,
type  ,
bool   
)

◆ offset_points_to_cells()

void offset_points_to_cells ( list  sinks,
expression  delta,
type  t 
)

Each cell in sinks is replaced by a cell located "delta" elements further up in the memory.

Similar to offset_cells(), but, in spite of the name, cannot be used with points-to cells that are part of a points-to belonging to a points-to set.

Parameters
sinksinks
deltaelta

Definition at line 1020 of file expression.c.

1021 {
1022  FOREACH(CELL, sink, sinks) {
1023  offset_points_to_cell(sink, delta, t, ENDP(CDR(sinks)));
1024  }
1025 }
void offset_points_to_cell(cell sink, expression delta, type t, bool unique_p __attribute__((__unused__)))
FI: offset_cell() has been derived from this function.
Definition: expression.c:1036

References CDR, CELL, ENDP, FOREACH, and offset_points_to_cell().

Referenced by expression_to_points_to_sinks_with_offset(), and unary_intrinsic_call_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ op_gen_module()

cell op_gen_module ( cell  ,
cell   
)

◆ opgen_may_constant_path()

points_to opgen_may_constant_path ( cell  ,
cell   
)

◆ opgen_may_module()

bool opgen_may_module ( entity  e1,
entity  e2 
)
Parameters
e11
e22

Definition at line 1179 of file constant-path-utils.c.

1180 {
1181  const char* m1 = entity_module_name(e1);
1182  const char* m2 = entity_module_name(e2);
1183 
1185  return true;
1186  else
1187  return same_string_p(m1, m2);
1188 }
bool entity_any_module_p(entity e)
operator kill for the dimension Module:

References entity_any_module_p(), entity_module_name(), and same_string_p.

+ Here is the call graph for this function:

◆ opgen_may_name()

bool opgen_may_name ( entity  e1,
entity  e2 
)
Parameters
e11
e22

Definition at line 1201 of file constant-path-utils.c.

1202 {
1203  string n1 = entity_name(e1);
1204  string n2 = entity_name(e2);
1205 
1207  return true;
1208  else
1209  return same_string_p(n1, n2);
1210 }

References entity_abstract_location_p(), entity_name, and same_string_p.

+ Here is the call graph for this function:

◆ opgen_may_type()

type opgen_may_type ( type  t1,
type  t2 
)
Parameters
t11
t22

Definition at line 437 of file constant-path-utils.c.

438 {
439  if (!type_unknown_p(t1)&& ! type_unknown_p(t2))
440  return t1;
441  else {
442  type t = MakeTypeUnknown();
443  return t;
444  }
445 }

References MakeTypeUnknown(), and type_unknown_p.

Referenced by opgen_must_type().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ opgen_may_vreference()

bool opgen_may_vreference ( list  vr1,
list  vr2 
)
Parameters
vr1r1
vr2r2

Definition at line 1223 of file constant-path-utils.c.

1224 {
1225  bool gen_may_p = true;
1226 
1227  if(ENDP(vr1) || ENDP(vr2))
1228  return gen_may_p;
1229  else{
1230  FOREACH(expression, e, vr1){
1232  gen_may_p = false;
1233  break;
1234  }
1235  }
1236  }
1237 
1238  return gen_may_p;
1239 }
bool extended_integer_constant_expression_p(expression e)
More extensive than next function.
Definition: expression.c:858

References ENDP, extended_integer_constant_expression_p(), and FOREACH.

+ Here is the call graph for this function:

◆ opgen_must_constant_path()

points_to opgen_must_constant_path ( cell  ,
cell   
)

◆ opgen_must_module()

bool opgen_must_module ( entity  e1,
entity  e2 
)
Parameters
e11
e22

Definition at line 1190 of file constant-path-utils.c.

1191 {
1192  const char* m1 = entity_module_name(e1);
1193  const char* m2 = entity_module_name(e2);
1194 
1196  return false;
1197  else
1198  return same_string_p(m1, m2);
1199 }

References entity_any_module_p(), entity_module_name(), and same_string_p.

+ Here is the call graph for this function:

◆ opgen_must_name()

bool opgen_must_name ( entity  e1,
entity  e2 
)
Parameters
e11
e22

Definition at line 1212 of file constant-path-utils.c.

1213 {
1214  string n1 = entity_name(e1);
1215  string n2 = entity_name(e2);
1216 
1218  return false;
1219  else
1220  return same_string_p(n1, n2);
1221 }

References entity_abstract_location_p(), entity_name, and same_string_p.

+ Here is the call graph for this function:

◆ opgen_must_type()

type opgen_must_type ( type  t1,
type  t2 
)

the same as opgen_may_type

Parameters
t11
t22

Definition at line 448 of file constant-path-utils.c.

449 {
450  return opgen_may_type(t1,t2);
451 }
type opgen_may_type(type t1, type t2)

References opgen_may_type().

+ Here is the call graph for this function:

◆ opgen_null_location()

set opgen_null_location ( set  L,
cell  r 
)

Definition at line 1254 of file constant-path-utils.c.

1255 {
1257  points_to_rank);
1258  SET_FOREACH(cell, l, L){
1260  set_add_element(gen_null, gen_null, (void*) pt);
1261  }
1262 
1263  return gen_null;
1264 }
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752

References gen_null(), make_approximation_exact(), make_descriptor_none(), make_points_to(), points_to_equal_p(), points_to_rank(), set_add_element(), SET_FOREACH, set_generic_make(), and set_private.

+ Here is the call graph for this function:

◆ opkill_may_constant_path()

bool opkill_may_constant_path ( cell  c1,
cell  c2 
)
Parameters
c11
c22

Definition at line 601 of file constant-path-utils.c.

602 {
603  bool kill_may_p;
604  reference r1 = cell_any_reference(c1);
605  reference r2 = cell_any_reference(c2);
606  type t1 = type_undefined;
607  type t2 = type_undefined;
608  entity v1 = reference_variable(r1);
609  entity v2 = reference_variable(r2);
610  bool type_equal_p = true;
611 
612  if (! type_area_p(entity_type(v1)) && !type_area_p(entity_type(v2))){
613  bool to_be_freed1, to_be_freed2;
614  t1 = points_to_reference_to_type(r1,&to_be_freed1);
615  t2 = points_to_reference_to_type(r2,&to_be_freed2);
616  type_equal_p = opkill_may_type(t1,t2);
617  if(to_be_freed1) free_type(t1);
618  if(to_be_freed2) free_type(t2);
619  }
620  kill_may_p = opkill_may_module(c1,c2) && opkill_may_name(c1,c2) &&
622 
623  return kill_may_p;
624 }
bool opkill_may_module(cell m1, cell m2)
bool opkill_may_vreference(cell c1, cell c2)
FI: really weird and unefficient.
bool opkill_may_type(type t1, type t2)
bool opkill_may_name(cell n1, cell n2)
We define operators for the lattice Name which can be a: -variable of a the program -malloc -NULL /0 ...

References cell_any_reference(), entity_type, free_type(), opkill_may_module(), opkill_may_name(), opkill_may_type(), opkill_may_vreference(), points_to_reference_to_type(), reference_variable, type_area_p, type_equal_p(), and type_undefined.

Referenced by kill_may_set().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ opkill_may_module()

bool opkill_may_module ( cell  m1,
cell  m2 
)

if the lhs or the rhs is a nowhere location or a null/0 value we generate a pips_user_warning

Parameters
m11
m22

Definition at line 242 of file constant-path-utils.c.

243 {
244  reference r1 = cell_any_reference(m1);
245  reference r2 = cell_any_reference(m2);
246  entity e1 = reference_variable(r1);
247  entity e2 = reference_variable(r2);
248  bool kill_may_p;
249 
250  /* if the lhs or the rhs is a nowhere location or a null/0 value we
251  generate a pips_user_warning */
253  kill_may_p = true;
254  else
255  kill_may_p = same_string_p(entity_name(e1),entity_name(e2));
256 
257  return kill_may_p;
258 }

References cell_any_reference(), entity_any_module_p(), entity_name, reference_variable, and same_string_p.

Referenced by opkill_may_constant_path().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ opkill_may_name()

bool opkill_may_name ( cell  n1,
cell  n2 
)

We define operators for the lattice Name which can be a: -variable of a the program -malloc -NULL /0 -STATIC/STACK/DYNAMIC/HEAP/FORMAL -nowhere/anywhere.

We define the max between 2 names according to the order established by the lattice Name, already done by entity_locations_max() but we have to add a new abstract location for Formal area opkill for the lattice Name tests if 2 names are : -variables of the program then we return the result of the comparison their names. -abstract locations so we return FALSE. Name * Name-> Bool

if(entity_malloc_p(e2)) kill_may_p = false// function entity_malloc_p() have to be defined and different from entity_heap_location_p()

if(entity_malloc_p(e1)) kill_may_p = true// function entity_malloc_p() have to be defined and different from entity_heap_location_p()

Parameters
n11
n22

Definition at line 310 of file constant-path-utils.c.

311 {
312  reference r1 = cell_any_reference(n1);
313  reference r2 = cell_any_reference(n2);
314  entity e1 = reference_variable(r1);
315  entity e2 = reference_variable(r2);
316  bool kill_may_p;
317 
320  pips_user_error("NULL or ANYWHERE locations can't appear as an lvalue\n");
321 
322  if (entity_abstract_location_p(e2)) {
323  if (entity_all_locations_p(e2))
324  kill_may_p = true;
325  if (entity_abstract_location_p(e1)) {
326  if (entity_all_locations_p(e1))
327  kill_may_p = true;
328  else
329  kill_may_p = same_string_p(entity_name(e1), entity_name(e2));
330  }
331  else {
332  /* if(entity_malloc_p(e2)) kill_may_p = false// function
333  entity_malloc_p() have to be defined and different from
334  entity_heap_location_p() */
336  r1 = make_reference(e1,NIL);
337  n1 = make_cell_reference(r1);
338  kill_may_p = opkill_may_name(n1, n2);
339  }
340  }
341  else if ( entity_abstract_location_p(e1) ) {
342  if (entity_all_locations_p(e1))
343  kill_may_p = true;
344  else {
345  /* if(entity_malloc_p(e1)) kill_may_p = true// function
346  entity_malloc_p() have to be defined and different from
347  entity_heap_location_p() */
349  r2 = make_reference(e2,NIL);
350  n2 = make_cell_reference(r2);
351  kill_may_p = opkill_may_name(n1, n2);
352  }
353  }
354  else
355  kill_may_p = same_string_p(entity_name(e1), entity_name(e2));
356 
357  return kill_may_p ;
358 }
entity variable_to_abstract_location(entity v)
returns the smallest abstract locations containing the location of variable v.
bool entity_all_locations_p(entity e)
test if an entity is the top of the lattice

References cell_any_reference(), entity_abstract_location_p(), entity_all_locations_p(), entity_name, entity_nowhere_locations_p(), entity_null_locations_p(), make_cell_reference(), make_reference(), NIL, pips_user_error, reference_variable, same_string_p, and variable_to_abstract_location().

Referenced by opkill_may_constant_path(), and opkill_must_name().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ opkill_may_reference()

bool opkill_may_reference ( cell  c1,
cell  c2 
)
Parameters
c11
c22

Definition at line 454 of file constant-path-utils.c.

455 {
458  bool kill_may_p = true;
459 
460  if (cell_reference_p(c1))
461  r1 = cell_reference(c1);
462  else
464  if (cell_reference_p(c2))
465  r2 = cell_reference(c2);
466  else
468 
470  return kill_may_p;
471  else {
472  kill_may_p = reference_equal_p(r1,r2);
473  return kill_may_p;
474  }
475 }
#define cell_preference(x)
Definition: effects.h:472
bool reference_equal_p(reference r1, reference r2)
Definition: expression.c:1500
bool store_independent_reference_p(reference r)
Does this reference define the same set of memory locations regardless of the current (environment an...
Definition: expression.c:3108
#define preference_reference(x)
Definition: ri.h:2102

References cell_preference, cell_reference, cell_reference_p, preference_reference, reference_equal_p(), reference_undefined, and store_independent_reference_p().

+ Here is the call graph for this function:

◆ opkill_may_type()

bool opkill_may_type ( type  t1,
type  t2 
)
Parameters
t11
t22

Definition at line 422 of file constant-path-utils.c.

423 {
424  if (!type_unknown_p(t1) && ! type_unknown_p(t2))
425  return type_equal_p(t1,t2);
426  else
427  return false;
428 
429 }

References type_equal_p(), and type_unknown_p.

Referenced by opkill_may_constant_path(), and opkill_must_type().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ opkill_may_vreference()

bool opkill_may_vreference ( cell  c1,
cell  c2 
)

FI: really weird and unefficient.

Also I asummed that vreference was limited to the subscript list... FI->AM: to be checked wrt your dissertation.

Parameters
c11
c22

Definition at line 496 of file constant-path-utils.c.

497 {
498  int i = 0;
499  reference r1 = cell_any_reference(c1);
500  reference r2 = cell_any_reference(c2);
501  entity v1 = reference_variable(r1);
502  entity v2 = reference_variable(r2);
503  list sl1 = NIL, sl2 = NIL;
504  // FI: memory leak? generation of a new string?
505  extern const char* entity_minimal_user_name(entity);
506 
507  // FI: why not compare the entities v1==v2?
509  if ( i==0 ) {
510  sl1 = reference_indices(r1);
511  sl2 = reference_indices(r2);
512  for (;i==0 && !ENDP(sl1) && ! ENDP(sl2) ; POP(sl1), POP(sl2)) {
513  expression se1 = EXPRESSION(CAR(sl1));
514  expression se2 = EXPRESSION(CAR(sl2));
516  i = 0;
517  else if (unbounded_expression_p(se1) && expression_constant_p(se2))
518  i = 0;
519  else if (expression_constant_p(se1) && expression_constant_p(se2) ) {
520  int i1 = expression_to_int(se1);
521  int i2 = expression_to_int(se2);
522  i = i2>i1? 1 : (i2<i1? -1 : 0);
523 
524  // FI: this piece of code seems out of place, if i==0, i==0
525  if ( i==0 ) {
526  string s1 = expression_to_string(se1);
527  string s2 = expression_to_string(se2);
528  i = strcmp(s1, s2);
529  }
530  }
531  else if(field_expression_p(se1) && field_expression_p(se2))
532  i = expression_equal_p(se1,se2)? 0 : 1;
533  }
534  }
535 
536  return (i==0? true: false);
537 }
bool field_expression_p(expression e)
The expression is of kind "a", where "a" is a field of some struct "s".
Definition: expression.c:498
bool expression_equal_p(expression e1, expression e2)
Syntactic equality e1==e2.
Definition: expression.c:1347

References CAR, cell_any_reference(), ENDP, entity_minimal_user_name(), EXPRESSION, expression_constant_p(), expression_equal_p(), expression_to_int(), expression_to_string(), field_expression_p(), NIL, POP, reference_indices, reference_variable, s1, and unbounded_expression_p().

Referenced by opkill_may_constant_path().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ opkill_must_constant_path()

bool opkill_must_constant_path ( cell  c1,
cell  c2 
)

returns true if c2 kills c1

if (! type_area_p(entity_type(v1)) && !type_area_p(entity_type(v2))){

if (entity_abstract_location_p(v1))

t1 = entity_type(v1);

else

t1 = simple_effect_reference_type(r1);

if (entity_abstract_location_p(v2))

t2 = entity_type(v2);

else

t2 = simple_effect_reference_type(r2);

type_equal_p = opkill_must_type(t1,t2);

}

Parameters
c11
c22

Definition at line 627 of file constant-path-utils.c.

628 {
629  bool kill_must_p;
630  reference r1 = cell_any_reference(c1);
631  reference r2 = cell_any_reference(c2);
632  type t1 = type_undefined;
633  type t2 = type_undefined;
634  //entity v1 = reference_variable(r1);
635  //entity v2 = reference_variable(r2);
636  bool equal_p = true;
637  t1 = points_to_reference_to_type(r1,&equal_p);
638  t2 = points_to_reference_to_type(r2, &equal_p);
639  equal_p = type_equal_p(t1,t2);
640  /* if (! type_area_p(entity_type(v1)) && !type_area_p(entity_type(v2))){ */
641  /* if (entity_abstract_location_p(v1)) */
642  /* t1 = entity_type(v1); */
643  /* else */
644  /* t1 = simple_effect_reference_type(r1); */
645  /* if (entity_abstract_location_p(v2)) */
646  /* t2 = entity_type(v2); */
647  /* else */
648  /* t2 = simple_effect_reference_type(r2); */
649  /* type_equal_p = opkill_must_type(t1,t2); */
650  /* } */
651  kill_must_p = opkill_must_module(c1,c2) && opkill_must_name(c1,c2) &&
652  equal_p && opkill_must_vreference(c1,c2);
653 
654  return kill_must_p;
655 }
bool opkill_must_module(cell m1, cell m2)
bool opkill_must_vreference(cell c1, cell c2)
returns true if c2 must kills c1 because of the subscript expressions
bool opkill_must_name(cell n1, cell n2)

References cell_any_reference(), opkill_must_module(), opkill_must_name(), opkill_must_vreference(), points_to_reference_to_type(), type_equal_p(), and type_undefined.

Referenced by kill_must_set().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ opkill_must_module()

bool opkill_must_module ( cell  m1,
cell  m2 
)
Parameters
m11
m22

Definition at line 260 of file constant-path-utils.c.

261 {
262  reference r1 = cell_any_reference(m1);
263  reference r2 = cell_any_reference(m2);
264  entity e1 = reference_variable(r1);
265  entity e2 = reference_variable(r2);
266  bool kill_must_p;
267 
269  kill_must_p = false;
270  else
271  kill_must_p = same_string_p(entity_name(e1),entity_name(e2));
272 
273  return kill_must_p;
274 }

References cell_any_reference(), entity_any_module_p(), entity_name, reference_variable, and same_string_p.

Referenced by opkill_must_constant_path().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ opkill_must_name()

bool opkill_must_name ( cell  n1,
cell  n2 
)

if(entity_malloc_p(e2)) kill_may_p = false// function entity_malloc_p() have to be defined and different from entity_heap_location_p()

if(entity_malloc_p(e1)) kill_may_p = true// function entity_malloc_p() have to be defined and different from entity_heap_location_p()

Parameters
n11
n22

Definition at line 361 of file constant-path-utils.c.

362 {
363  reference r1 = cell_any_reference(n1);
364  reference r2 = cell_any_reference(n2);
365  entity e1 = reference_variable(r1);
366  entity e2 = reference_variable(r2);
367  bool kill_must_p;
368 
371  pips_user_error("NULL or ANYWHERE locations can't appear as an lvalue\n");
372 
373  if (entity_abstract_location_p(e2)) {
374  if (entity_all_locations_p(e2))
375  kill_must_p = false;
376  if (entity_abstract_location_p(e1)) {
377  if(entity_all_locations_p(e1))
378  kill_must_p = false;
379  else
380  kill_must_p = same_string_p(entity_name(e1), entity_name(e2));
381  }
382  else {
383  /* if(entity_malloc_p(e2)) kill_may_p = false// function
384  entity_malloc_p() have to be defined and different from
385  entity_heap_location_p() */
387  r1 = make_reference(e1,NIL);
388  n1 = make_cell_reference(r1);
389  kill_must_p = opkill_may_name(n1, n2);
390  }
391  }
392  else if ( entity_abstract_location_p(e1) ) {
393  if (entity_all_locations_p(e1))
394  kill_must_p = false;
395  else {
396  /* if(entity_malloc_p(e1)) kill_may_p = true// function
397  entity_malloc_p() have to be defined and different from
398  entity_heap_location_p() */
400  r2 = make_reference(e2,NIL);
401  n2 = make_cell_reference(r2);
402  kill_must_p = opkill_may_name(n1, n2);
403  }
404  }
405  else
406  kill_must_p = same_string_p(entity_name(e1), entity_name(e2));
407 
408  return kill_must_p ;
409 }

References cell_any_reference(), entity_abstract_location_p(), entity_all_locations_p(), entity_name, entity_nowhere_locations_p(), entity_null_locations_p(), make_cell_reference(), make_reference(), NIL, opkill_may_name(), pips_user_error, reference_variable, same_string_p, and variable_to_abstract_location().

Referenced by opkill_must_constant_path().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ opkill_must_reference()

bool opkill_must_reference ( cell  c1,
cell  c2 
)
Parameters
c11
c22

Definition at line 478 of file constant-path-utils.c.

479 {
480  reference r1 = cell_any_reference(c1);
481  reference r2 = cell_any_reference(c2);
482  bool kill_must_p = false;
483 
485  return kill_must_p;
486  else {
487  kill_must_p = reference_equal_p(r1,r2);
488  return kill_must_p;
489  }
490 }

References cell_any_reference(), reference_equal_p(), and store_independent_reference_p().

+ Here is the call graph for this function:

◆ opkill_must_type()

bool opkill_must_type ( type  t1,
type  t2 
)

opkill_must_type is the same as op_kill_may_type...

Parameters
t11
t22

Definition at line 432 of file constant-path-utils.c.

433 {
434  return opkill_may_type(t1,t2);
435 }

References opkill_may_type().

+ Here is the call graph for this function:

◆ opkill_must_vreference()

bool opkill_must_vreference ( cell  c1,
cell  c2 
)

returns true if c2 must kills c1 because of the subscript expressions

This function should be rewritten from scratch, with a defined semantics for "*" as a subscript and possibly a larger use of expression_equal_p(). Also, we need to specify if the scopes for each rereference are equal or not.

Parameters
c11
c22

Definition at line 546 of file constant-path-utils.c.

547 {
548  int i = 0;
549  reference r1 = cell_any_reference(c1);
550  reference r2 = cell_any_reference(c2);
551  entity v1 = reference_variable(r1);
552  entity v2 = reference_variable(r2);
553  list sl1 = NIL, sl2 = NIL;
554  // FI: memory leak? generation of a new string?
555  extern const char* entity_minimal_user_name(entity);
556 
557  // FI: this step could be assumed performed earlier
559  if (i==0) {
560  sl1 = reference_indices(r1);
561  sl2 = reference_indices(r2);
562  for (;i==0 && !ENDP(sl1) && ! ENDP(sl2) ; POP(sl1), POP(sl2)){
563  expression se1 = EXPRESSION(CAR(sl1));
564  expression se2 = EXPRESSION(CAR(sl2));
566  //i = 0;
567  i = 1;
568  }
569  else if(expression_constant_p(se1) && unbounded_expression_p(se2)){
570  //i = 0; could be true if * is interpreted as "forall"
571  i = 1;
572  }
573  else if (expression_constant_p(se1) && expression_constant_p(se2)){
574  int i1 = expression_to_int(se1);
575  int i2 = expression_to_int(se2);
576  i = i2>i1? 1 : (i2<i1? -1 : 0);
577  if (i==0){ // FI->AM: I do not understand this step
578  string s1 = expression_to_string(se1);
579  string s2 = expression_to_string(se2);
580  i = strcmp(s1, s2);
581  }
582  }
583  else {
584  // FI->AM: very dangerous; only true if both references appear
585  // exactly in the same scope; and "*" were not dealt with!
587  i = 1;
588  else {
589  i = expression_equal_p(se1, se2)? 0 : 1;
590  }
591  }
592  }
593  }
594 
595  return (i==0? true: false);
596 }

References CAR, cell_any_reference(), ENDP, entity_minimal_user_name(), EXPRESSION, expression_constant_p(), expression_equal_p(), expression_to_int(), expression_to_string(), NIL, POP, reference_indices, reference_variable, s1, and unbounded_expression_p().

Referenced by opkill_must_constant_path().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ order_condition_to_points_to()

pt_map order_condition_to_points_to ( entity  f,
list  al,
bool  true_p,
pt_map  in 
)

The expression list "al" contains exactly two arguments.

If these expressions are pointers, "in" is modified by removing arcs that are not compatible with the equality. If no arc is left, a bottom "in" is returned.

"out" is "in", modified by side-effects.

The condition cannot violate an exact arc.

The condition cannot violate an exact arc.

Parameters
all
true_prue_p
inn

Definition at line 3176 of file expression.c.

3177 {
3178  pt_map out = in;
3179  bool (*cmp_function)(cell, cell);
3180 
3181  if((ENTITY_LESS_OR_EQUAL_P(f) && true_p)
3182  || (ENTITY_GREATER_THAN_P(f) && !true_p)) {
3183  // cmp_function = cell_is_less_than_or_equal_to_p;
3184  cmp_function = cell_is_greater_than_p;
3185  }
3186  else if((ENTITY_LESS_OR_EQUAL_P(f) && !true_p)
3187  || (ENTITY_GREATER_THAN_P(f) && true_p)) {
3188  // cmp_function = cell_is_greater_than_p;
3189  cmp_function = cell_is_less_than_or_equal_to_p;
3190  }
3191  else if((ENTITY_GREATER_OR_EQUAL_P(f) && true_p)
3192  || (ENTITY_LESS_THAN_P(f) && !true_p)) {
3193  // cmp_function = cell_is_greater_than_or_equal_to_p;
3194  cmp_function = cell_is_less_than_p;
3195  }
3196  else if((ENTITY_GREATER_OR_EQUAL_P(f) && !true_p)
3197  || (ENTITY_LESS_THAN_P(f) && true_p)) {
3198  //cmp_function = cell_is_less_than_p;
3199  cmp_function = cell_is_greater_than_or_equal_to_p;
3200  }
3201  else {
3202  pips_internal_error("Unexpected relational operator.\n");
3203  cmp_function = NULL;
3204  }
3205 
3206  expression lhs = EXPRESSION(CAR(al));
3207  type lhst = expression_to_type(lhs);
3208  expression rhs = EXPRESSION(CAR(CDR(al)));
3209  type rhst = expression_to_type(rhs);
3210  if(pointer_type_p(lhst) || pointer_type_p(rhst)) {
3212  if(gen_length(L)==1) { // FI: one fixed bound
3213  cell lc = CELL(CAR(L));
3215  set out_s = points_to_graph_set(out);
3216  SET_FOREACH(points_to, pt, out_s) {
3217  cell source = points_to_source(pt);
3218  if(cell_in_list_p(source, RR)) {
3219  cell sink = points_to_sink(pt);
3220  if(cmp_function(lc, sink)) {
3222  if(approximation_exact_p(a)) {
3223  /* The condition cannot violate an exact arc. */
3224  // clear_pt_map(out);
3225  points_to_graph_bottom(out) = true;
3226  // Would be useless/different with a union
3228  }
3229  else
3231  }
3232  }
3233  }
3234  }
3235  else {
3236  list R = expression_to_points_to_sinks(rhs, in);
3237  if(gen_length(R)==1) { // FI: one fixed bound
3238  cell rc = CELL(CAR(R));
3239  list LL = expression_to_points_to_sources(lhs, in);
3240  set out_s = points_to_graph_set(out);
3241  SET_FOREACH(points_to, pt, out_s) {
3242  cell source = points_to_source(pt);
3243  if(cell_in_list_p(source, LL)) {
3244  cell sink = points_to_sink(pt);
3245  if(cmp_function(sink, rc)) {
3246  // FI: Oops in middle of the iterator...
3248  if(approximation_exact_p(a)) {
3249  /* The condition cannot violate an exact arc. */
3250  // clear_pt_map(out);
3251  points_to_graph_bottom(out) = true;
3252  // Would be useless/different with a union
3254  }
3255  else
3257  }
3258  }
3259  }
3260  }
3261  }
3262  }
3263  free_type(lhst), free_type(rhst);
3264 
3265  return in;
3266 }
struct _newgen_struct_cell_ * cell
Definition: effects.h:90
#define RR
Definition: genspec.h:95
int bool
we cannot use an enum or stdbool because we need to be compatible with newgen, thus boolean need to h...
Definition: newgen_types.h:78
bool cell_is_greater_than_or_equal_to_p(cell c1, cell c2)
Definition: expression.c:2830
bool cell_is_greater_than_p(cell c1, cell c2)
Definition: expression.c:2835
bool cell_is_less_than_p(cell c1, cell c2)
Definition: expression.c:2825
bool cell_is_less_than_or_equal_to_p(cell c1, cell c2)
See if you can decide that the addresses linked to c1 are smaller than the addresses linked to c2.
Definition: expression.c:2820
#define ENTITY_LESS_THAN_P(e)
#define ENTITY_GREATER_THAN_P(e)
#define ENTITY_LESS_OR_EQUAL_P(e)
#define ENTITY_GREATER_OR_EQUAL_P(e)

References approximation_exact_p, CAR, CDR, CELL, cell_in_list_p(), cell_is_greater_than_or_equal_to_p(), cell_is_greater_than_p(), cell_is_less_than_or_equal_to_p(), cell_is_less_than_p(), ENTITY_GREATER_OR_EQUAL_P, ENTITY_GREATER_THAN_P, ENTITY_LESS_OR_EQUAL_P, ENTITY_LESS_THAN_P, EXPRESSION, expression_to_points_to_sinks(), expression_to_points_to_sources(), expression_to_type(), f(), free_type(), gen_length(), out, pips_internal_error, pointer_type_p(), points_to_approximation, points_to_graph_bottom, points_to_graph_set, points_to_sink, points_to_source, remove_arc_from_pt_map, RR, set_clear(), and SET_FOREACH.

Referenced by relational_intrinsic_call_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pointer_arithmetic_to_points_to()

pt_map pointer_arithmetic_to_points_to ( expression  lhs,
expression  delta,
pt_map  pt_in 
)

Update the sink locations associated to the source "lhs" under points-to information pt_map by "delta".

C standard guarantees that the sink objects is unchanged by pointer arithmetic.

Property POINTS_TO_STRICT_POINTER_TYPES is used to be more or less flexible about formal parameters and local variables such as "int * p"

Parameters
lhshs
deltaelta
pt_int_in

Definition at line 760 of file expression.c.

763 {
764  pt_map pt_out = pt_in;
765  list sources = expression_to_points_to_sources(lhs, pt_out);
766  bool to_be_freed;
767  type et = points_to_expression_to_type(lhs, &to_be_freed);
768  FOREACH(CELL, source, sources) {
769  list sinks = source_to_sinks(source, pt_out, false);
770  if(ENDP(sinks)) {
772  //pips_internal_error("Sink missing for a source based on \"%s\".\n",
773  // entity_user_name(v));
774  pips_user_warning("No defined value for pointer \"%s\".\n",
775  entity_user_name(v));
776  if(gen_length(sources)==1)
777  // The code cannot be executed
778  clear_pt_map(pt_out);
779  }
780  offset_cells(source, sinks, delta, et, pt_out);
781  // FI: we could perform some filtering out of pt_in
782  // If an arc points from source to nowehere/undefined or to the
783  // null location, this arc should be removed from pt_in as it
784  // cannot lead to an execution reaching the next statement.
785  FOREACH(CELL, sink, sinks) {
786  if(nowhere_cell_p(sink))
787  remove_points_to_arcs(source, sink, pt_out);
788  else if(null_cell_p(sink))
789  remove_points_to_arcs(source, sink, pt_out);
790  }
791  }
792  // FI: should we free the sources list? Fully free it?
793  return pt_out;
794 }
void offset_cells(cell source, list sinks, expression delta, type et, pt_map in)
Each cell in sinks is replaced by a cell located "delta" elements further up in the memory.
Definition: expression.c:869
void remove_points_to_arcs(cell, cell, pt_map)

References CELL, cell_any_reference(), clear_pt_map, ENDP, entity_user_name(), expression_to_points_to_sources(), FOREACH, gen_length(), nowhere_cell_p(), null_cell_p(), offset_cells(), pips_user_warning, points_to_expression_to_type(), reference_variable, remove_points_to_arcs(), and source_to_sinks().

Referenced by intrinsic_call_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pointer_assignment_to_points_to()

pt_map pointer_assignment_to_points_to ( expression  lhs,
expression  rhs,
pt_map  pt_in 
)

FI: this is a crazy idea to avoid problems in balancing test branches. It should only be useful when the formal context has to be expanded by this assignment. lhs = lhs;

Of course, it is a catastrophy when expression lhs has side effects...

And it does not work because the current "in" of the test is modified by side-effect no seen when the false branch is analyzed.

Parameters
lhshs
rhshs
pt_int_in

Definition at line 1437 of file expression.c.

1440 {
1441  /* FI: this is a crazy idea to avoid problems in balancing test
1442  * branches. It should only be useful when the formal context has to
1443  * be expanded by this assignment. lhs = lhs;
1444  *
1445  * Of course, it is a catastrophy when expression lhs has side effects...
1446  *
1447  * And it does not work because the current "in" of the test is
1448  * modified by side-effect no seen when the false branch is analyzed.
1449  */
1450  // pt_map pt_out = internal_pointer_assignment_to_points_to(lhs, lhs, pt_in);
1451  pt_map pt_out = internal_pointer_assignment_to_points_to(lhs, rhs, pt_in);
1452  return pt_out;
1453 }
pt_map internal_pointer_assignment_to_points_to(expression lhs, expression rhs, pt_map pt_in)
Any abstract location of the lhs in L is going to point to any sink of any abstract location of the r...
Definition: expression.c:1315

References internal_pointer_assignment_to_points_to().

Referenced by assignment_to_points_to(), and expand_points_to_domain().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pointer_formal_parameter_to_stub_points_to()

set pointer_formal_parameter_to_stub_points_to ( type  pt,
cell  c 
)

Input : a formal parameter which is a pointer and its type.

Output : a set of points-to where sinks are stub points-to. we descent recursively until reaching a basic type, then we call create_stub_points_to()to generate the adequate points-to.

FI: I do not know if I want to keep using this function because stubs are not created on demand and because some are certainly not useful for the points-to analysis. But they may be useful for client analysis... However, client analyses will have to create more such stubs...

maybe should be removed if we have already called ultimate type in formal_points_to_parameter()

The pointer may be NULL or undefined. We neglect undefined/nowhere

The pointer may points towards another object (or set of object)

Recursive descent for pointers: the new sink becomes the new source... FI: I do not think this is useful because they will be created on demand...

what about storage

Create a target of unknown type

make_type_unknown()

Parameters
ptt

Definition at line 810 of file points_to_init_analysis.c.

811 {
816  /* maybe should be removed if we have already called ultimate type
817  * in formal_points_to_parameter() */
818 
819  /* The pointer may be NULL or undefined. We neglect undefined/nowhere */
820  // AM: Get the property POINTS_TO_NULL_POINTER_INITIALIZATION
821  bool null_initialization_p = get_bool_property("POINTS_TO_NULL_POINTER_INITIALIZATION");
822  if(null_initialization_p) {
823  cell nc = copy_cell(c);
825  points_to npt = make_points_to(nc, null_c,
828  pt_in = add_arc_to_simple_pt_map(npt, pt_in);
829  }
830 
831  /* The pointer may points towards another object (or set of object) */
832  type upt = type_to_pointed_type(pt);
833  if( type_variable_p(upt) ){
834  basic fpb = variable_basic(type_variable(upt));
835  if( array_type_p(upt) ){
837  !null_initialization_p);
838  pt_in = set_add_element(pt_in, pt_in,
839  (void*) pt_to );
840  }
841  else {
842  switch(basic_tag(fpb)){
843  case is_basic_int:{
844  // type st = type_undefined; // sink type
845  // pt_to = create_advanced_stub_points_to(c, upt, !null_initialization_p);
846  pt_to = create_stub_points_to(c, upt, !null_initialization_p);
847  pt_in = set_add_element(pt_in, pt_in,
848  (void*) pt_to );
849  break;
850  }
851  case is_basic_float:{
852  //pt_to = create_advanced_stub_points_to(c, upt, !null_initialization_p);
853  pt_to = create_stub_points_to(c, upt, !null_initialization_p);
854  pt_in = set_add_element(pt_in, pt_in,
855  (void*) pt_to );
856  break;
857  }
858  case is_basic_logical:{
859  //pt_to = create_advanced_stub_points_to(c, upt, !null_initialization_p);
860  pt_to = create_stub_points_to(c, upt, !null_initialization_p);
861  pt_in = set_add_element(pt_in, pt_in,
862  (void*) pt_to );
863  break;
864  }
865  case is_basic_overloaded:{
866  // FI: Oops, what are we doing here?
867  pt_to = create_stub_points_to(c, upt, !null_initialization_p);
868  pt_in = set_add_element(pt_in, pt_in,
869  (void*) pt_to );
870  break;
871  }
872  case is_basic_complex:{
873  //pt_to = create_advanced_stub_points_to(c, upt, !null_initialization_p);
874  pt_to = create_stub_points_to(c, upt, !null_initialization_p);
875  pt_in = set_add_element(pt_in, pt_in,
876  (void*) pt_to );
877  break;
878  }
879  case is_basic_pointer:{
880  //pt_to = create_advanced_stub_points_to(c, upt, !null_initialization_p);
881  pt_to = create_stub_points_to(c, upt, !null_initialization_p);
882  pt_in = set_add_element(pt_in, pt_in,
883  (void*) pt_to );
884  cell sink = points_to_sink(pt_to);
885  if(false) {
886  /* Recursive descent for pointers: the new sink becomes the
887  new source... FI: I do not think this is useful because
888  they will be created on demand... */
890  pt_in = set_union(pt_in, pt_in,tmp);
891  set_free(tmp);
892  }
893  /* what about storage*/
894  break;
895  }
896  case is_basic_derived:{
897  //pt_to = create_advanced_stub_points_to(c, upt, !null_initialization_p);
898  pt_to = create_stub_points_to(c, upt, !null_initialization_p);
899  pt_in = set_add_element(pt_in, pt_in,
900  (void*) pt_to );
901  break;
902  }
903  case is_basic_bit:
904  pips_internal_error("Not implemented.\n");
905  break;
906  case is_basic_string:{
907  // FI: I'm not too sure about what to do for strings...
908  pt_to = create_stub_points_to(c, upt, !null_initialization_p);
909  pt_in = set_add_element(pt_in, pt_in,
910  (void*) pt_to );
911  break;
912  }
913  case is_basic_typedef:{
914  //pt_to = create_advanced_stub_points_to(c, upt, !null_initialization_p);
915  pt_to = create_stub_points_to(c, upt, !null_initialization_p);
916  pt_in = set_add_element(pt_in, pt_in,
917  (void*) pt_to );
918  break;
919  }
920  default: pips_internal_error("unexpected tag %d", basic_tag(fpb));
921  break;
922  }
923  }
924  }
925  else if(type_functional_p(upt)) {
926  pt_to = create_stub_points_to(c, upt, !null_initialization_p);
927  add_arc_to_simple_pt_map(pt_to, pt_in);
928 }
929  else if(type_void_p(upt)) {
930  /* Create a target of unknown type */
931  pt_to = create_stub_points_to(c, upt/* make_type_unknown() */,
932  !null_initialization_p);
933  pt_in = set_add_element(pt_in, pt_in, (void*) pt_to );
934  }
935  else
936  //we don't know how to handle other types
937  pips_internal_error("Unexpected type");
938 
939  return pt_in;
940 
941 
942 }
points_to create_pointer_to_array_stub_points_to(cell c, type t, bool exact_p)
To create the points-to stub associated to the formal parameter, the sink name is a concatenation of ...

References add_arc_to_simple_pt_map, array_type_p(), basic_tag, copy_cell(), create_pointer_to_array_stub_points_to(), create_stub_points_to(), get_bool_property(), is_basic_bit, is_basic_complex, is_basic_derived, is_basic_float, is_basic_int, is_basic_logical, is_basic_overloaded, is_basic_pointer, is_basic_string, is_basic_typedef, make_approximation_may(), make_descriptor_none(), make_null_pointer_value_cell(), make_points_to(), pips_internal_error, pointer_formal_parameter_to_stub_points_to(), points_to_equal_p(), points_to_rank(), points_to_sink, points_to_undefined, set_add_element(), set_free(), set_generic_make(), set_private, set_union(), type_functional_p, type_to_pointed_type(), type_variable, type_variable_p, type_void_p, and variable_basic.

Referenced by formal_points_to_parameter(), and pointer_formal_parameter_to_stub_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pointer_points_to_reference_p()

bool pointer_points_to_reference_p ( reference  )

◆ pointer_reference_dereferencing_to_points_to()

void pointer_reference_dereferencing_to_points_to ( reference  r,
pt_map  in 
)
Parameters
inn

Definition at line 318 of file dereferencing.c.

319 {
321  // FI: assume side effects are OK...
322  (void) expression_to_points_to(pae, in, true);
323  free_expression(pae);
324 }
expression pointer_reference_to_expression(reference r)
Assume p is a pointer.
Definition: expression.c:4004

References expression_to_points_to(), free_expression(), and pointer_reference_to_expression().

Referenced by reference_dereferencing_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pointer_reference_to_points_to_sinks()

list pointer_reference_to_points_to_sinks ( reference  r,
pt_map  in,
bool  eval_p 
)

What to do when a pointer "p" is dereferenced within a reference "r".

If p is a scalar pointer, p[i] is equivalent to *(p+i) and p[i][j] to *(*(p+i)+j).

If p is a 2-D array of pointers, p[i], p[i][j] do not belong here. But, p[i][j][k] is equivalent to *(p[i][j]+k) and p[i][j][k][l] to *(*(p[i][j]+k)+l).

The equivalent expression is fully allocated to be freed at the end. Which may cause problems if the points-to analysis re-use parts of the internal data structure...

The normalization could have been performed by the parser, but PIPS is source-to-source for the benefit of its human user.

Parameters
inn
eval_pval_p

Definition at line 709 of file sinks.c.

710 {
711  list sinks = NIL;
713 
714  if(eval_p)
715  sinks = expression_to_points_to_sinks(pae, in);
716  else
717  sinks = expression_to_points_to_sources(pae, in);
718 
719  free_expression(pae);
720 
721  return sinks;
722 }

References expression_to_points_to_sinks(), expression_to_points_to_sources(), free_expression(), NIL, and pointer_reference_to_expression().

Referenced by reference_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pointer_source_to_sinks()

list pointer_source_to_sinks ( cell  sc,
pt_map  in 
)

Returns the sinks for a source cell "sc" of type pointer according to the points-to relation "in".

This is an extension of extended_source_to_sinks() that also take into account partially subscribed arrays. Such references end up with a pointer type, but "in" is not involved in the dereferencing... since no dereferencing is necessary. An extra 0 subscript must be added.

FI: This issue is also dealt elsewhere, but I do not know where nor how often.

Parameters
scc
inn

Definition at line 2455 of file points_to_set.c.

2456 {
2457  list sinks = NIL;
2458  reference r = cell_any_reference(sc);
2459  entity v = reference_variable(r);
2461  if(array_type_p(t)) {
2462  // FI: pointers count for 1 in array depth
2463  // With a array of pointers, a dereferencing 0 subscript is added
2464  // int dn = (int) type_depth(t);
2466  list sl = reference_indices(r);
2467  int sn = (int) gen_length(sl);
2468  if(sn<dn) {
2469  cell sink = copy_cell(sc);
2470  reference sink_r = cell_any_reference(sink);
2471  reference_indices(sink_r) = gen_nconc(reference_indices(sink_r),
2473  sinks = CONS(CELL, sink, NIL);
2474  }
2475  }
2476  if(ENDP(sinks))
2477  sinks = extended_source_to_sinks(sc, in);
2478  return sinks;
2479 }

References array_type_p(), CELL, cell_any_reference(), CONS, copy_cell(), ENDP, entity_basic_concrete_type(), EXPRESSION, extended_source_to_sinks(), gen_length(), gen_nconc(), int, make_zero_expression(), NIL, reference_indices, reference_variable, type_variable, and variable_dimensions.

Referenced by dereferencing_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pointer_subscript_to_expression()

expression pointer_subscript_to_expression ( cell  c,
list  csl 
)

Allocate a new expression based on the reference in "c" and the subscript list "csl".

No sharing with the arguments. The pointer subscripts are transformed into pointer arithmetic and dereferencements.

Parameters
cslsl

Definition at line 1430 of file sinks.c.

1431 {
1434 
1435  FOREACH(EXPRESSION, pse, csl) {
1436  expression npse = copy_expression(pse);
1439  }
1440  return pae;
1441 }
#define PLUS_C_OPERATOR_NAME
expression reference_to_expression(reference r)
Definition: expression.c:196

References binary_intrinsic_expression, cell_any_reference(), copy_expression(), copy_reference(), DEREFERENCING_OPERATOR_NAME, EXPRESSION, FOREACH, PLUS_C_OPERATOR_NAME, reference_to_expression(), and unary_intrinsic_expression.

Referenced by subscript_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_anywhere()

set points_to_anywhere ( list  lhs_list,
set  input 
)

lhs_path matches the kill set.

input - kill

if the lhs_set or the rhs set contains more than an element, we set the approximation to MAY.

Computing the gen set

create a new points to with as source the current element of lhs_set and sink the null value .

gen + input_kill_diff

Parameters
lhs_lisths_list
inputnput

Definition at line 122 of file constant-path-utils.c.

123 {
124  /* lhs_path matches the kill set.*/
134 
135  SET_FOREACH ( points_to, p, input ) {
136  FOREACH ( cell, c, lhs_list ) {
138  set_add_element(kill, kill, p);
139  }
140  }
141 
142  /* input - kill */
143  set_difference(input_kill_diff, input, kill);
144 
145  /* if the lhs_set or the rhs set contains more than an element, we
146  set the approximation to MAY. */
147  if ( (int)gen_length(lhs_list) > 1 )// || set_size(rhs_set)>1)
149 
150  /* Computing the gen set*/
151  FOREACH ( cell, c, lhs_list ) {
152  /* create a new points to with as source the current
153  element of lhs_set and sink the null value .*/
155  reference r = make_reference(e, NIL);
156  cell sink = make_cell_reference(r);
157  points_to pt_to = make_points_to(c, sink, a, make_descriptor_none());
158  set_add_element(gen, gen, (void*)pt_to);
159  }
160  /* gen + input_kill_diff*/
161  set_union(res, gen, input_kill_diff);
162 
163  return res;
164 }
#define ANYWHERE_LOCATION
static int input(void)

References ANYWHERE_LOCATION, entity_all_xxx_locations(), FOREACH, gen(), gen_length(), input(), make_approximation_exact(), make_approximation_may(), make_cell_reference(), make_descriptor_none(), make_points_to(), make_reference(), NIL, points_to_compare_cell(), points_to_equal_p(), points_to_rank(), points_to_source, set_add_element(), set_difference(), SET_FOREACH, set_generic_make(), set_private, and set_union().

Referenced by list_assignment_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_anywhere_sinks()

list points_to_anywhere_sinks ( type  t)

Definition at line 102 of file sinks.c.

103 {
104  entity ne;
105  if(type_undefined_p(t))
106  ne = entity_all_locations();
107  else
109  return entity_to_sinks(ne);
110 }
list entity_to_sinks(entity e)
allocate a new list of sinks with one element, abstract or concrete, e.
Definition: sinks.c:72

References entity_all_locations(), entity_to_sinks(), entity_typed_anywhere_locations(), and type_undefined_p.

Referenced by call_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_anywhere_typed()

set points_to_anywhere_typed ( list  lhs_list,
set  input 
)

Already exists in points_to_general_algorithm.c, to be removed later...

iterate over the lhs_set, if it contains more than an element approximations are set to MAY, otherwise it's set to EXACT Set the sink to anywhere .

input - kill

if the lhs_set or the rhs set contains more than an element, we set the approximation to MAY.

Computing the gen set

create a new points to with as source the current element of lhs_set and sink the null value .

Parameters
lhs_lisths_list
inputnput

Definition at line 75 of file constant-path-utils.c.

76 {
86 
88  FOREACH(cell, c, lhs_list) {
90  set_add_element(kill, kill, p);
91  }
92  }
93 
94  /* input - kill */
95  set_difference(input_kill_diff, input, kill);
96 
97  /* if the lhs_set or the rhs set contains more than an element, we
98  set the approximation to MAY. */
99  if((int)gen_length(lhs_list) > 1)// || set_size(rhs_set)>1)
101 
102  /* Computing the gen set*/
103  FOREACH(cell, c, lhs_list) {
104  /* create a new points to with as source the current
105  element of lhs_set and sink the null value .*/
107  entity er = reference_variable(cr);
108  type t = entity_type(er);
110  reference r = make_reference(e, NIL);
111  cell sink = make_cell_reference(r);
112  points_to pt_to = make_points_to(c, sink, a, make_descriptor_none());
113  set_add_element(gen, gen, (void*)pt_to);
114  }
115 
116  set_union(res, gen, input_kill_diff);
117 
118  return res;
119 }

References ANYWHERE_LOCATION, cell_any_reference(), entity_all_xxx_locations_typed(), entity_type, FOREACH, gen(), gen_length(), input(), make_approximation_exact(), make_approximation_may(), make_cell_reference(), make_descriptor_none(), make_points_to(), make_reference(), NIL, points_to_compare_cell(), points_to_equal_p(), points_to_rank(), points_to_source, reference_variable, set_add_element(), set_difference(), SET_FOREACH, set_generic_make(), set_private, and set_union().

Referenced by list_assignment_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_backward_translation()

void points_to_backward_translation ( void  )

Definition at line 71 of file points_to_init_analysis.c.

72 {
73 }

◆ points_to_binding()

set points_to_binding ( list  args,
set  in,
set  pt_binded 
)

Apply points_to_binding_arguments() to each pair (, complete the process of binding each element of "in" to its corresponding memory address at the call site.

Necessary to translate the fields of structures.

"args": list of formal parameters of some callee

"in": points-to in of the callee

"pt_binded": points-to from formal to actual parameters for a specific call site

A new set is allocated.

Process each formal parameter and look for its actual values in "pt_binded"

Parameters
argsrgs
inn
pt_bindedt_binded

Definition at line 2780 of file interprocedural.c.

2781 {
2782 
2783  set bm = new_simple_pt_map();
2784  //set bm1 = new_simple_pt_map();
2785 
2786  /* Process each formal parameter and look for its actual values in
2787  "pt_binded" */
2788  SET_FOREACH(points_to, pt, pt_binded) {
2789  FOREACH(CELL, c1, args) {
2790  cell source = points_to_source(pt);
2791  if(cell_equal_p(c1, source)) {
2792  cell c2 = points_to_source_alias(pt, pt_binded);
2793  // FI: We end up with c1=c2=one formal parameter...
2794  // No need to add "p->p" in "bm"...
2795  //approximation a = make_approximation_exact();
2796  //points_to new_pt = make_points_to(c1, c2, a, make_descriptor_none());
2797  //add_arc_to_simple_pt_map(new_pt, bm);
2798  set c1c2 = points_to_binding_arguments(c1, c2, in, pt_binded);
2799  bm = set_union(bm, bm, c1c2);
2800  set_clear(c1c2), set_free(c1c2);
2801  }
2802  else if(cell_entity_equal_p(c1, source)) {
2803  pips_assert("c1 is a reference with no indices",
2805  cell c2 = copy_cell(source);
2806  // FI: We end up with c1=c2=one formal parameter...
2807  // No need to add "p->p" in "bm"...
2808  //approximation a = make_approximation_exact();
2809  //points_to new_pt = make_points_to(c1, c2, a, make_descriptor_none());
2810  //add_arc_to_simple_pt_map(new_pt, bm);
2811  set c1c2 = points_to_binding_arguments(source, c2, in, pt_binded);
2812  bm = set_union(bm, bm, c1c2);
2813  set_clear(c1c2), set_free(c1c2);
2814  }
2815  }
2816  }
2817 
2818  return bm;
2819 }
bool cell_entity_equal_p(cell, cell)
Definition: effects.c:1234
set points_to_binding_arguments(cell c1, cell c2, set in, set pt_binded)
Recursively find all the arcs, "ai", starting from the argument "c1" using "in", find all the arcs,...
cell points_to_source_alias(points_to pt, set pt_binded)
Let "pt_binded" be the results of assignments of actual arguments to formal arguments (see compute_po...

References CELL, cell_any_reference(), cell_entity_equal_p(), cell_equal_p(), copy_cell(), ENDP, FOREACH, new_simple_pt_map, pips_assert, points_to_binding_arguments(), points_to_source, points_to_source_alias(), reference_indices, set_clear(), SET_FOREACH, set_free(), and set_union().

Referenced by user_call_to_points_to_fast_interprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_binding_arguments()

set points_to_binding_arguments ( cell  c1,
cell  c2,
set  in,
set  pt_binded 
)

Recursively find all the arcs, "ai", starting from the argument "c1" using "in", find all the arcs, "aj", starting from the parameter "c2" using "pt_binded", map each node "ai" to its corresponding "aj" and store the "ai->aj" arc in a new set, "bm".

"pt_binded" contains the correspondance between formal and actual parameters, e.g. "fp->ap", with some information about the possible approximations because one formal parameter can points toward several actual memory locations of the caller.

"in" contains the formal context of the callee, as it stands at its entry point (DBR_POINTS_TO_IN).

"bm" is the binding relationship between references of the formal context of the callees towards addresses of the caller. For instance, when function "void foo(int ** fp)" is called as "ap=&q; foo(ap);", bm = {(_ap_1, q)}.

See Amira Mensi's PhD dissertation, chapter about interprocedural analysis

Recursive call down the different points_to paths

Here we have, for instance, "q[*]" in "c1" for "q[4]" in "in".

FI: I do not see how to handle incompatibility between assumptions...

(!source_in_set_p(c1, in) && !source_subset_in_set_p(c1, in))

c1 is not a pointer: it is simply mapped to c2

Parameters
c11
c22
inn
pt_bindedt_binded

Definition at line 2513 of file interprocedural.c.

2514 {
2515  set bm = new_simple_pt_map();
2516 
2517  if(source_in_set_p(c1, in) || source_subset_in_set_p(c1, in)) {
2518  // FI: impedance problem... and memory leak
2519  points_to_graph in_g = make_points_to_graph(false, in);
2520  points_to_graph pt_binded_g = make_points_to_graph(false, pt_binded);
2521  // FI: allocate a new copy for sink1 and sink2
2522  //list c1_children = cell_to_pointer_cells(c1);
2523  //list c2_children = cell_to_pointer_cells(c2);
2524  list c1_children = recursive_cell_to_pointer_cells(c1);
2525  list c2_children = recursive_cell_to_pointer_cells(c2);
2526  FOREACH(CELL,c1c, c1_children) {
2527  FOREACH(CELL,c2c, c2_children) {
2528  list sinks1 = points_to_source_to_some_sinks(c1c, in_g, true);
2529  list sinks2 = points_to_source_to_some_sinks(c2c, pt_binded_g, true);
2530  pips_assert("sinks1 is not empty", !ENDP(sinks1));
2531  pips_assert("sinks2 is not empty", !ENDP(sinks2));
2532  // FI Allocate more copies
2533  list tmp1 = gen_full_copy_list(sinks1);
2534  list tmp2 = gen_full_copy_list(sinks2);
2535 
2536  FOREACH(CELL, s1, sinks1) { // Formal cell: fp->_fp_1 or fp->NULL
2537  // FI: no need to translate constants NULL and UNDEFINED
2538  if(!null_cell_p(s1) && !nowhere_cell_p(s1)) {
2539  FOREACH(CELL, s2, sinks2) { // Actual cell: ap-> i... NOWHERE... NULL...
2540  // FI: _fp_1 may or not exist since it is neither null nor undefined
2541  if(!null_cell_p(s2) && !nowhere_cell_p(s2)) {
2543  if((size_t)gen_length(sinks2)>1) // FI->FI: atomicity should be tested too
2544  a = make_approximation_may();
2545  else
2547  cell sink1 = copy_cell(s1);
2548  cell sink2 = copy_cell(s2);
2549  // Build arc _fp_1->... NOWHERE ... NULL ...
2550  points_to pt = make_points_to(sink1, sink2, a, make_descriptor_none());
2551  add_arc_to_simple_pt_map(pt, bm);
2552  }
2553  //gen_remove(&sinks2, (void*)s2);
2554  }
2555  }
2556  //gen_remove(&sinks1, (void*)s1);
2557  }
2558 
2559  /* Recursive call down the different points_to paths*/
2560  FOREACH(CELL, sr1, tmp1) {
2561  if(!null_cell_p(sr1) && !nowhere_cell_p(sr1)) {
2562  FOREACH(CELL, sr2, tmp2) {
2563  if(!null_cell_p(sr2) && !nowhere_cell_p(sr2)) {
2564  set sr1sr2 = points_to_binding_arguments(sr1, sr2, in, pt_binded);
2565  bm = set_union(bm, sr1sr2, bm);
2566  set_clear(sr1sr2), set_free(sr1sr2);
2567  }
2568  }
2569  }
2570  }
2571  }
2572  }
2573  }
2574  else if(source_subset_in_set_p(c1, in)) { // Not reachable
2575  /* Here we have, for instance, "q[*]" in "c1" for "q[4]" in "in". */
2576  /* FI: I do not see how to handle incompatibility between assumptions... */
2577  pips_internal_error("Do not know how to handle subsets...\n");
2578  }
2579  else /* (!source_in_set_p(c1, in) && !source_subset_in_set_p(c1, in)) */ {
2580  // FI: this has already been performed
2581  /* c1 is not a pointer: it is simply mapped to c2 */
2582  // points_to pt = make_points_to(c1, c2, make_approximation_exact(), make_descriptor_none());
2583  // add_arc_to_simple_pt_map(pt, bm);
2584  ;
2585  }
2586  return bm;
2587 }
list recursive_cell_to_pointer_cells(cell)
Definition: effects.c:1680
bool source_subset_in_set_p(cell, set)
test if a cell "source" appears as a source in a set of points-to
list points_to_source_to_some_sinks(cell, pt_map, bool)
May not retrieve all sinks of the source.
bool source_in_set_p(cell, set)
test if a cell appear as a source in a set of points-to

References add_arc_to_simple_pt_map, approximation_undefined, CELL, copy_cell(), ENDP, FOREACH, gen_full_copy_list(), gen_length(), make_approximation_exact(), make_approximation_may(), make_descriptor_none(), make_points_to(), make_points_to_graph(), new_simple_pt_map, nowhere_cell_p(), null_cell_p(), pips_assert, pips_internal_error, points_to_source_to_some_sinks(), recursive_cell_to_pointer_cells(), s1, set_clear(), set_free(), set_union(), source_in_set_p(), and source_subset_in_set_p().

Referenced by points_to_binding().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_cell_list_and()

void points_to_cell_list_and ( list a,
const  list 
)

Compute A = A inter B: complexity in O(n2)

This element of a is not in list b: delete it:

Definition at line 3133 of file points_to_set.c.

3134 {
3135  if (ENDP(*a))
3136  return ;
3137  if (!points_to_cell_in_list_p(CELL(CAR(*a)),b)) {
3138  /* This element of a is not in list b: delete it: */
3139  cons *aux = *a;
3140 
3141  *a = CDR(*a);
3142  free(aux);
3144  }
3145  else
3146  points_to_cell_list_and(&CDR(*a), b);
3147 }
void free(void *)
void points_to_cell_list_and(list *a, const list b)
Compute A = A inter B: complexity in O(n2)
int aux
Definition: solpip.c:104

References aux, CAR, CDR, CELL, ENDP, free(), points_to_cell_in_list_p(), points_to_cell_list_and(), and return().

Referenced by points_to_cell_list_and().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_cell_name()

string points_to_cell_name ( cell  source)

Create a string which is the cell reference in C syntax.

A new string is allocated.

Parameters
sourceource

Definition at line 186 of file points_to_set.c.

187 {
188  reference sro = cell_to_reference(source);
189  string key = strdup(reference_to_string(sro));
190 
191  return key;
192 }

References cell_to_reference(), reference_to_string(), and strdup().

Referenced by compute_points_to_gen_set(), maximal_out_degree_of_points_to_graph(), points_to_source_name_to_sinks(), and points_to_source_name_to_source_cell().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_cell_null_initialization()

list points_to_cell_null_initialization ( cell  c,
pt_map  pts 
)

If required according to the property, create a new arc from cell "c" to "null".

Cell "c" is absorbed not by the points_to created and added to set "pts".

Parameters
ptsts

Definition at line 1318 of file points_to_set.c.

1319 {
1320  list sinks = NIL;
1321  bool null_initialization_p =
1322  get_bool_property("POINTS_TO_NULL_POINTER_INITIALIZATION");
1323  if(null_initialization_p) {
1324  sinks = null_to_sinks(c, pts);
1325  }
1326  return sinks;
1327 }

References get_bool_property(), NIL, and null_to_sinks().

Referenced by generic_stub_source_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_cell_source_projection()

points_to_graph points_to_cell_source_projection ( points_to_graph  ptg,
cell  c 
)

Remove all arcs in "ptg" starting from "c".

Parameters
ptgtg

Definition at line 330 of file points_to_set.c.

331 {
332  set pts = points_to_graph_set(ptg);
333 
334  SET_FOREACH(points_to, pt, pts) {
335  cell source = points_to_source(pt);
336 
337  if(cell_equal_p(source, c)) {
338  set_del_element(pts, pts, (void*)pt);
339  }
340  }
341 
342  return ptg;
343 }

References cell_equal_p(), points_to_graph_set, points_to_source, set_del_element(), and SET_FOREACH.

Referenced by equal_condition_to_points_to(), and null_equal_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_cell_to_number_of_unbounded_dimensions()

int points_to_cell_to_number_of_unbounded_dimensions ( cell  c)

Definition at line 2097 of file points_to_set.c.

2098 {
2101  return n;
2102 }
int points_to_reference_to_number_of_unbounded_dimensions(reference r)

References cell_any_reference(), and points_to_reference_to_number_of_unbounded_dimensions().

+ Here is the call graph for this function:

◆ points_to_cell_to_pointer_cells()

list points_to_cell_to_pointer_cells ( cell  c)

Definition at line 1900 of file expression.c.

1901 {
1903 }
static list generic_points_to_cell_to_useful_pointer_cells(cell c, set pts)
Returns a list of cells of pointer type which are included in cell "c".
Definition: expression.c:1862

References generic_points_to_cell_to_useful_pointer_cells(), and set_undefined.

Referenced by memory_leak_to_more_memory_leaks(), and points_to_cells_to_pointer_cells().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_cell_to_string()

◆ points_to_cell_to_useful_pointer_cells()

list points_to_cell_to_useful_pointer_cells ( cell  c,
set  pts 
)
Parameters
ptsts

Definition at line 1905 of file expression.c.

1906 {
1908 }

References generic_points_to_cell_to_useful_pointer_cells().

Referenced by filter_formal_context_according_to_actual_context(), and recursive_filter_formal_context_according_to_actual_context().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_cell_translation()

list points_to_cell_translation ( cell  sr1,
set  binding,
entity  f 
)

Compute the list of cells that correspond to cell "sr1" according to the translation mapping "bm" when function "f" is called.

The check with rv may be useless, for instance when a sink cell is checked, as it is impossible (in C at least) to points toward the return value.

Translate sr1 if needed

No translation is needed.

We assume here that the subscript list of sr1, the reference to translate, is longer than the subscript list of sr2, the source of its translation.

Parameters
sr1r1
bindinginding

Definition at line 2211 of file interprocedural.c.

2212 {
2213  list new_sr_l = NIL;
2215 
2216  /* Translate sr1 if needed */
2217  reference r_1 = cell_any_reference(sr1);
2218  entity v_1 = reference_variable(r_1);
2221  || heap_cell_p(sr1)
2222  || v_1 == rv
2223  || entity_to_module_entity(v_1)!=f) {
2224  /* No translation is needed. */
2225  cell new_sr = copy_cell(sr1);
2226  new_sr_l = CONS(CELL, new_sr, new_sr_l);
2227  }
2228  else {
2229  list ind1 = reference_indices(r_1);
2230  SET_FOREACH(points_to, pp, binding) {
2231  cell sr2 = points_to_source(pp);
2232  cell sk2 = points_to_sink(pp);
2234  // FI: this test should be factored out
2235  if(!source_in_set_p(sr1, binding)) {
2236  // sr1 cannot be translated directly, let's try to remove
2237  // (some) subscripts
2238  reference r_12 = cell_any_reference(sr2);
2239  entity v_12 = reference_variable( r_12 );
2241  /* We assume here that the subscript list of sr1, the
2242  reference to translate, is longer than the subscript
2243  list of sr2, the source of its translation. */
2244  list ind2 = reference_indices(r_12);
2245  pips_assert("The effective subscript list is longer than "
2246  "the translated subscript list",
2247  gen_length(ind1)>=gen_length(ind2));
2248  // Either we check the subscript compatibility or we trust it
2249  // Let's trust it: no!
2250  list cind1 = ind1, cind2 = ind2;
2251  bool compatible_p = true;
2252  while(!ENDP(cind2)) {
2253  expression s1 = EXPRESSION(CAR(cind1));
2254  expression s2 = EXPRESSION(CAR(cind2));
2256  compatible_p = false;
2257  break;
2258  }
2259  POP(cind1), POP(cind2);
2260  }
2261  if(compatible_p) {
2262  // Propagate the remaining subscripts on the translation target
2263  reference_indices(r22) = gen_nconc(reference_indices(r22),cind1);
2264  cell new_sr = make_cell_reference(r22);
2265  new_sr_l = CONS(CELL, new_sr, new_sr_l);
2266  }
2267  }
2268  }
2269  else if(points_to_compare_cell(sr1,sr2)) {
2270  // sr1 can be translated directly as sk2
2271  cell new_sr = copy_cell(points_to_sink(pp));
2272  new_sr_l = CONS(CELL, new_sr, new_sr_l);
2273  }
2274  }
2275  }
2276  return new_sr_l;
2277 }
bool entity_typed_anywhere_locations_p(entity e)
Test if an entity is the bottom of the lattice.
bool entity_anywhere_locations_p(entity e)
test if an entity is the bottom of the lattice
bool compatible_points_to_subscripts_p(expression, expression)
Two subscript are compatible if they are equal or if one of them is unbounded.
Definition: points_to.c:1041

References any_function_to_return_value(), CAR, CELL, cell_any_reference(), cell_to_reference(), compatible_points_to_subscripts_p(), CONS, copy_cell(), copy_reference(), ENDP, entity_anywhere_locations_p(), entity_local_name(), entity_to_module_entity(), entity_typed_anywhere_locations_p(), EXPRESSION, f(), gen_length(), gen_nconc(), heap_cell_p(), make_cell_reference(), NIL, pips_assert, points_to_compare_cell(), points_to_sink, points_to_source, POP, reference_indices, reference_variable, s1, same_string_p, SET_FOREACH, and source_in_set_p().

Referenced by add_implicitly_killed_arcs_to_kill_set(), compute_points_to_gen_set(), and generic_points_to_cells_translation().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_cells_exact_translation()

list points_to_cells_exact_translation ( list  cl,
set  binding,
entity  f 
)

Allocate a new list with the translations of the cells in cl, when their translation make sense and is unique (one-to-one mapping).

Effects on copied parameters are discarded.

Parameters
cll
bindinginding

Definition at line 2327 of file interprocedural.c.

2328 {
2329  return generic_points_to_cells_translation(cl, binding, f, true);
2330 }
list generic_points_to_cells_translation(list cl, set binding, entity f, bool exact_p)
Allocate a new list with the translations of the cells in cl, when their translation make sense.

References f(), and generic_points_to_cells_translation().

Referenced by user_call_to_points_to_interprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_cells_parameters()

list points_to_cells_parameters ( list  dl)

interprocedural.c

interprocedural.c

The list is not sorted. It is probably a reversed list.

Parameters
dll

Definition at line 68 of file interprocedural.c.

69 {
70  list fpcl = NIL;
71  FOREACH(ENTITY, fp, dl) {
72  if(formal_parameter_p(fp) && !location_entity_p(fp)) {
74  // FI: not all formal parameter may impact points-to
75  if(pointer_type_p(fpt) || struct_type_p(fpt) || array_type_p(fpt)) {
76  reference r = make_reference(fp, NIL);
78  fpcl = gen_nconc(CONS(CELL, c, NULL), fpcl);
79  }
80  }
81  }
82  return fpcl;
83 }
bool location_entity_p(entity)
Definition: locations.c:349

References array_type_p(), CELL, CONS, ENTITY, entity_basic_concrete_type(), FOREACH, formal_parameter_p(), gen_nconc(), location_entity_p(), make_cell_reference(), make_reference(), NIL, pointer_type_p(), and struct_type_p().

Referenced by user_call_to_points_to(), user_call_to_points_to_fast_interprocedural(), user_call_to_points_to_interprocedural(), and user_call_to_points_to_interprocedural_binding_set().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_cells_pointer_arguments()

list points_to_cells_pointer_arguments ( list  al)

Transform a list of arguments of type "expression" to a list of cells.

The list is not sorted. It is probably a reversed list.

Parameters
all

Definition at line 90 of file interprocedural.c.

91 {
92  list apcl = NIL;
93  FOREACH(EXPRESSION, ap, al) {
97  apcl = gen_nconc(CONS(CELL, c, NULL), apcl);
98  }
99  }
100  return apcl;
101 }

References CELL, CONS, EXPRESSION, expression_pointer_p(), expression_reference(), expression_reference_p(), FOREACH, gen_nconc(), make_cell_reference(), and NIL.

Referenced by user_call_to_points_to_fast_interprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_cells_to_pointer_cells()

list points_to_cells_to_pointer_cells ( list  pl)

Convert cells in l into derived pointer cells when possible.

The elements of list pl are reused in list l

Parameters
pll

Definition at line 1917 of file expression.c.

1918 {
1919  list l = NIL;
1920  FOREACH(CELL, pc, pl) {
1922  l = gen_nconc(l, nl);
1923  }
1924  return l;
1925 }
static hash_table pl
properties are stored in this hash table (string -> property) for fast accesses.
Definition: properties.c:783

References CELL, FOREACH, gen_nconc(), NIL, pl, and points_to_cell_to_pointer_cells().

Referenced by recursive_filter_formal_context_according_to_actual_context().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_cells_translation()

list points_to_cells_translation ( list  cl,
set  binding,
entity  f 
)

Allocate a new list with the translations of the cells in cl, when their translation make sense.

Effects on copied parameters are discarded.

Parameters
cll
bindinginding

Definition at line 2318 of file interprocedural.c.

2319 {
2320  return generic_points_to_cells_translation(cl, binding, f, false);
2321 }

References f(), and generic_points_to_cells_translation().

Referenced by user_call_to_points_to_interprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_compare_cell()

bool points_to_compare_cell ( cell  c1,
cell  c2 
)
Parameters
c11
c22

Definition at line 2657 of file points_to_set.c.

2658 {
2659  if(c1==c2)
2660  return true;
2661 
2662  int i = 0;
2663  reference r1 = cell_to_reference(c1);
2664  reference r2 = cell_to_reference(c2);
2665  entity v1 = reference_variable(r1);
2666  entity v2 = reference_variable(r2);
2667  list sl1 = NIL, sl2 = NIL;
2668  extern const char* entity_minimal_user_name(entity);
2669 
2671  if(i==0) {
2672  sl1 = reference_indices(r1);
2673  sl2 = reference_indices(r2);
2674  int i1 = gen_length(sl1);
2675  int i2 = gen_length(sl2);
2676 
2677  i = i2>i1? 1 : (i2<i1? -1 : 0);
2678 
2679  for(;i==0 && !ENDP(sl1); POP(sl1), POP(sl2)){
2680  expression se1 = EXPRESSION(CAR(sl1));
2681  expression se2 = EXPRESSION(CAR(sl2));
2683  int i1 = expression_to_int(se1);
2684  int i2 = expression_to_int(se2);
2685  i = i2>i1? 1 : (i2<i1? -1 : 0);
2686  }else{
2687  string s1 = expression_to_string(se1);
2688  string s2 = expression_to_string(se2);
2689  i = strcmp(s1, s2);
2690  }
2691  }
2692  }
2693 
2694  return (i== 0 ? true: false) ;
2695 }

References CAR, cell_to_reference(), ENDP, entity_minimal_user_name(), EXPRESSION, expression_constant_p(), expression_to_int(), expression_to_string(), gen_length(), NIL, POP, reference_indices, reference_variable, and s1.

Referenced by cell_in_list_p(), cell_in_points_to_set_p(), compute_points_to_kill_set(), gen_must_set(), points_to_anywhere(), points_to_anywhere_typed(), and points_to_cell_translation().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_compare_location()

int points_to_compare_location ( void *  vpt1,
void *  vpt2 
)

Order the two points-to relations according to the alphabetical order of the underlying variables.

Return -1, 0, or 1.

Parameters
vpt1pt1
vpt2pt2

Definition at line 2744 of file points_to_set.c.

2744  {
2745  int i = 0;
2746  points_to pt1 = *((points_to *) vpt1);
2747  points_to pt2 = *((points_to *) vpt2);
2748 
2749  cell c1so = points_to_source(pt1);
2750  cell c2so = points_to_source(pt2);
2751  cell c1si = points_to_sink(pt1);
2752  cell c2si = points_to_sink(pt2);
2753 
2754  // FI: bypass of GAP case
2755  reference r1so = cell_to_reference(c1so);
2756  reference r2so = cell_to_reference(c2so);
2757  reference r1si = cell_to_reference(c1si);
2758  reference r2si = cell_to_reference(c2si);
2759 
2760  entity v1so = reference_variable(r1so);
2761  entity v2so = reference_variable(r2so);
2762  entity v1si = reference_variable(r1si);
2763  entity v2si = reference_variable(r2si);
2764  list sl1 = NIL, sl2 = NIL;
2765  // FI: memory leak? generation of a new string?
2766  extern const char* entity_minimal_user_name(entity);
2767 
2768  i = strcmp(entity_minimal_user_name(v1so), entity_minimal_user_name(v2so));
2769  if(i==0) {
2771  if(i==0) {
2772  sl1 = reference_indices(r1so);
2773  sl2 = reference_indices(r2so);
2774  int i1 = gen_length(sl1);
2775  int i2 = gen_length(sl2);
2776 
2777  i = i2>i1? 1 : (i2<i1? -1 : 0);
2778 
2779  if(i==0) {
2780  list sli1 = reference_indices(r1si);
2781  list sli2 = reference_indices(r2si);
2782  int i1 = gen_length(sli1);
2783  int i2 = gen_length(sli2);
2784 
2785  i = i2>i1? 1 : (i2<i1? -1 : 0);
2786  if(i==0) {
2787  for(;i==0 && !ENDP(sl1); POP(sl1), POP(sl2)){
2788  expression se1 = EXPRESSION(CAR(sl1));
2789  expression se2 = EXPRESSION(CAR(sl2));
2791  int i1 = expression_to_int(se1);
2792  int i2 = expression_to_int(se2);
2793  i = i2>i1? 1 : (i2<i1? -1 : 0);
2794  if(i==0){
2795  for(;i==0 && !ENDP(sli1); POP(sli1), POP(sli2)){
2796  expression sei1 = EXPRESSION(CAR(sli1));
2797  expression sei2 = EXPRESSION(CAR(sli2));
2798  if(expression_constant_p(sei1) && expression_constant_p(sei2)){
2799  int i1 = expression_to_int(sei1);
2800  int i2 = expression_to_int(sei2);
2801  i = i2>i1? 1 : (i2<i1? -1 : 0);
2802  }else{
2803  string s1 = expression_to_string(se1);
2804  string s2 = expression_to_string(se2);
2805  i = strcmp(s1, s2);
2806  }
2807  }
2808  }
2809  }else{
2810  string s1 = expression_to_string(se1);
2811  string s2 = expression_to_string(se2);
2812  i = strcmp(s1, s2);
2813  }
2814  }
2815  }
2816  }
2817  }
2818  }
2819  return i;
2820 }
__m64 v2si
Definition: 3dnow.h:7

References CAR, cell_to_reference(), ENDP, entity_minimal_user_name(), EXPRESSION, expression_constant_p(), expression_to_int(), expression_to_string(), gen_length(), NIL, points_to_sink, points_to_source, POP, reference_indices, reference_variable, and s1.

+ Here is the call graph for this function:

◆ points_to_compare_ptr_cell()

bool points_to_compare_ptr_cell ( const void *  vcel1,
const void *  vcel2 
)
Parameters
vcel1cel1
vcel2cel2

Definition at line 2698 of file points_to_set.c.

2699 {
2700  int i = 0;
2701  cell c1 = *((cell *)vcel1);
2702  cell c2 = *((cell *)vcel2);
2703  reference r1 = cell_to_reference(c1);
2704  reference r2 = cell_to_reference(c2);
2705  entity v1 = reference_variable(r1);
2706  entity v2 = reference_variable(r2);
2707  list sl1 = NIL, sl2 = NIL;
2708  extern const char* entity_minimal_user_name(entity);
2709  string n1 = entity_abstract_location_p(v1)?
2711  string n2 = entity_abstract_location_p(v2)?
2713  i = strcmp(n1, n2);
2714  if(i==0) {
2715  sl1 = reference_indices(r1);
2716  sl2 = reference_indices(r2);
2717  int i1 = gen_length(sl1);
2718  int i2 = gen_length(sl2);
2719 
2720  i = i2>i1? 1 : (i2<i1? -1 : 0);
2721 
2722  for(;i==0 && !ENDP(sl1); POP(sl1), POP(sl2)){
2723  expression se1 = EXPRESSION(CAR(sl1));
2724  expression se2 = EXPRESSION(CAR(sl2));
2726  int i1 = expression_to_int(se1);
2727  int i2 = expression_to_int(se2);
2728  i = i2>i1? 1 : (i2<i1? -1 : 0);
2729  }else{
2730  string s1 = expression_to_string(se1);
2731  string s2 = expression_to_string(se2);
2732  i = strcmp(s1, s2);
2733  }
2734  }
2735  }
2736 
2737  return i;
2738 }

References CAR, cell_to_reference(), ENDP, entity_abstract_location_p(), entity_local_name(), entity_minimal_user_name(), EXPRESSION, expression_constant_p(), expression_to_int(), expression_to_string(), gen_length(), NIL, POP, reference_indices, reference_variable, and s1.

Referenced by generic_points_to_set_to_stub_cell_list().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_context_statement_in()

pt_map points_to_context_statement_in ( void  )

Definition at line 127 of file statement.c.

128 {
130  return in;
131 }
points_to_graph pt_map

References stack_head(), and statement_points_to_context.

Referenced by user_call_to_points_to_interprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_context_statement_line_number()

int points_to_context_statement_line_number ( void  )

Definition at line 120 of file statement.c.

121 {
122  //statement s = stack_head(current_statement_points_to_context);
124  return statement_number(s);
125 }
statement get_current_statement_from_statement_global_stack(void)
Definition: static.c:344
#define statement_number(x)
Definition: ri.h:2452

References get_current_statement_from_statement_global_stack(), and statement_number.

Referenced by aliased_translation_p(), binary_intrinsic_call_to_points_to_sinks(), check_type_of_points_to_cells(), declaration_statement_to_points_to(), dereferencing_subscript_to_points_to(), equal_condition_to_points_to(), expression_to_points_to_cells(), filter_formal_context_according_to_actual_context(), freed_list_to_points_to(), freed_pointer_to_points_to(), internal_pointer_assignment_to_points_to(), intrinsic_call_to_points_to(), list_assignment_to_points_to(), memory_leak_to_more_memory_leaks(), new_filter_formal_context_according_to_actual_context(), non_equal_condition_to_points_to(), offset_cell(), offset_points_to_cell(), process_casted_sinks(), process_casted_sources(), reference_dereferencing_to_points_to(), reference_to_points_to_sinks(), source_to_sinks(), subscript_to_points_to_sinks(), subscripted_reference_to_points_to(), and user_call_to_points_to_interprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_equal_p()

int points_to_equal_p ( const void *  vpt1,
const void *  vpt2 
)

returns true if two points-to arcs "vpt1" and "vpt2" are equal.

Used to build sets of points-to using the set library of Newgen

Parameters
vpt1pt1
vpt2pt2

Definition at line 98 of file points_to_set.c.

99 {
100  points_to pt1 = (points_to) vpt1;
101  points_to pt2 = (points_to) vpt2;
102 
103  //same source
104  cell c1 = points_to_source(pt1);
105  cell c2 = points_to_source(pt2);
106  bool cmp1 = locations_equal_p(c1,c2);
107 
108  // same sink
109  cell c3 = points_to_sink(pt1);
110  cell c4 = points_to_sink(pt2);
111  bool cmp2 = locations_equal_p(c3,c4);
112 
113  // same approximation
116  // FI: must is forgotten...
117  //bool cmp3 = (approximation_exact_p(a1) && approximation_exact_p(a2))
118  // || ( approximation_may_p(a1) && approximation_may_p(a2));
119  // FI: should we identify "exact" and "must"?
120  bool cmp3 = (approximation_tag(a1)==approximation_tag(a2));
121  bool cmp = cmp1 && cmp2 && cmp3;
122 
123  ifdebug(8) {
124  printf("%s for pt1=%p and pt2=%p\n", bool_to_string(cmp), pt1, pt2);
125  print_points_to(pt1);
126  print_points_to(pt2);
127  }
128 
129  return cmp;
130 }
string bool_to_string(bool)
Definition: string.c:243
struct _newgen_struct_points_to_ * points_to

References approximation_tag, bool_to_string(), ifdebug, locations_equal_p(), points_to_approximation, points_to_sink, points_to_source, print_points_to(), and printf().

Referenced by arc_in_points_to_set_p(), array_formal_parameter_to_stub_points_to(), compute_points_to_binded_set(), derived_formal_parameter_to_stub_points_to(), formal_points_to_parameter(), gen_may_constant_paths(), gen_may_set(), gen_must_constant_paths(), gen_must_set(), init_points_to_analysis(), k_limit_points_to(), kill_may_set(), merge_points_to_set(), new_points_to_unstructured(), opgen_null_location(), pointer_formal_parameter_to_stub_points_to(), points_to_anywhere(), points_to_anywhere_typed(), points_to_function_projection(), points_to_in_list_p(), points_to_independent_store(), points_to_may_filter(), points_to_must_filter(), points_to_nowhere(), typedef_formal_parameter_to_stub_points_to(), and user_call_to_points_to_fast_interprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_forward_translation()

void points_to_forward_translation ( void  )

points_to_init_analysis.c

points_to_init_analysis.c

This package computes the points-to interprocedurally.

See Chapter ? in Amira Mensi's PhD dissertation.

Definition at line 66 of file points_to_init_analysis.c.

67 {
68 
69 }

◆ points_to_function_projection()

set points_to_function_projection ( set  pts)

"pts" is the points-to relation existing at the return point of a function.

Meaningless arcs in an interprocedural context must be eliminated.

The concept of "meaningless" arc has changed. Formal parameters are no longer "projected" although some of them are copies because, when they are not written, they are aliases of the actual parameters and carry useful information.

Unfortunately, we do not compute the information about may/must be written pointers.

As a consequence, some memory leaks cannot be detected here. The problem could be spotted when handling a call site, but then the memory leak will be indicated at each call site. This is not implemented, but we have a test case, Pointers/Mensi.sub/conditional_free01.c.

FI: side-effects to be used explicitly in this function For the time being a new set is allocated

Do we have a useful return value?

Preserve the return value. And indexed formal parameters such as s.tab? No, because struct are passed by copy. But not arrays... Except that copies are perfect alias of the actual argument when they are not modified. Since we do not have information about modified formal parameter, the Written set, we should provisionally preserve all formal parameters, no matter what they points to. See EffectsWithPointsTo/modif_pointer0a4.c

Also preserve nowhere generated by free although the pointer itself is not written. Beware that a formal pointer may be written... FI: we should be able to check is the source has been written or not in the current function... See Pointers/array10.c. However, it is still transiently true and not a bug.

Detect memory leaks

Look recursively for more memory leaks: cells in "emll" are no longer reachable

Parameters
ptsts

Definition at line 477 of file points_to_set.c.

478 {
481  set_assign(res, pts);
482  /* Do we have a useful return value? */
486  if(pointer_type_p(rt) || struct_type_p(rt))
488 
489  list pmll = NIL; // Potential memory leak list
490 
491  SET_FOREACH(points_to, pt, pts) {
493  /* Preserve the return value. And indexed formal parameters
494  * such as s.tab? No, because struct are passed by copy. But not
495  * arrays... Except that copies are perfect alias of the actual
496  * argument when they are not modified. Since we do not have
497  * information about modified formal parameter, the Written set,
498  * we should provisionally preserve all formal parameters, no
499  * matter what they points to. See
500  * EffectsWithPointsTo/modif_pointer0a4.c */
501  cell source = points_to_source(pt);
502  //type source_t = points_to_cell_to_concrete_type(source);
503  reference r = cell_any_reference(source);
504  //list sl = reference_indices(r);
505  entity v = reference_variable(r);
507  if(rv!=v && !array_type_p(v_t) && !formal_parameter_p(v)) {
508  /* Also preserve nowhere generated by free although the
509  * pointer itself is not written. Beware that a formal pointer
510  * may be written... FI: we should be able to check is the
511  * source has been written or not in the current
512  * function... See Pointers/array10.c. However, it is still
513  * transiently true and not a bug.
514  */
515  cell sink = points_to_sink(pt);
516  if(!nowhere_cell_p(sink)) {
517  // FI: written by Amira
518  set_del_element(res, res, (void*)pt);
519  if((heap_cell_p(sink) || all_heap_locations_cell_p(sink))
520  // FI: we are protected by the test on v_t
521  // The atomicity should not be an issue here
522  && atomic_points_to_cell_p(source))
523  pmll = CONS(CELL, sink, pmll);
524  }
525  }
526  }
527  }
528 
529  /* Detect memory leaks */
530  list emll = potential_to_effective_memory_leaks(pmll, res);
531  gen_free_list(pmll);
532 
533  /* Look recursively for more memory leaks: cells in "emll" are no
534  longer reachable */
535  res = remove_points_to_cells(emll, res);
536  gen_free_list(emll);
537 
538  return res;
539 }
bool all_heap_locations_cell_p(cell)
Definition: effects.c:432
bool cell_out_of_scope_p(cell c)
Return true if a cell is out of scope.
list potential_to_effective_memory_leaks(list pmll, set res)
A new list, "emll", is allocated.
set remove_points_to_cells(list cl, set g)
All nodes, i.e.

References all_heap_locations_cell_p(), array_type_p(), atomic_points_to_cell_p(), CELL, cell_any_reference(), cell_out_of_scope_p(), compute_basic_concrete_type(), CONS, entity_basic_concrete_type(), entity_undefined, formal_parameter_p(), function_to_return_value(), functional_result, gen_free_list(), get_current_module_entity(), heap_cell_p(), NIL, nowhere_cell_p(), pointer_type_p(), points_to_equal_p(), points_to_rank(), points_to_sink, points_to_source, potential_to_effective_memory_leaks(), reference_variable, remove_points_to_cells(), set_assign(), set_del_element(), SET_FOREACH, set_generic_make(), set_private, struct_type_p(), and type_functional.

Referenced by generic_points_to_analysis().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_graph_assign()

pt_map points_to_graph_assign ( pt_map  out,
pt_map  in 
)
Parameters
outut
inn

Definition at line 3194 of file points_to_set.c.

3195 {
3197  points_to_graph_set(in));
3198  return out;
3199 }

References out, points_to_graph_set, and set_assign().

Referenced by control_to_points_to(), and cyclic_graph_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_in_list_p()

bool points_to_in_list_p ( points_to  pt,
const  list 
)

found!

else no found

Parameters
ptt
listx

Definition at line 2647 of file points_to_set.c.

2648 {
2649  list l = (list) lx;
2650  for (; !ENDP(l); POP(l))
2651  if (points_to_equal_p(POINTS_TO(CAR(l)), pt)) return true; /* found! */
2652 
2653  return false; /* else no found */
2654 }

References CAR, ENDP, POINTS_TO, points_to_equal_p(), and POP.

+ Here is the call graph for this function:

◆ points_to_independent_store()

set points_to_independent_store ( set  s)

Definition at line 1273 of file constant-path-utils.c.

1274 {
1276  points_to_rank);
1277  bool changed = false;
1278 
1279  SET_FOREACH(points_to, pt, s){
1280  cell source = points_to_source(pt);
1281  cell sink = points_to_sink(pt);
1282  cell new_source = simple_cell_to_store_independent_cell(source, &changed);
1283  cell new_sink = simple_cell_to_store_independent_cell(sink, &changed);
1284  points_to npt = make_points_to(new_source, new_sink, points_to_approximation(pt),points_to_descriptor(pt));
1285  set_add_element(res, res, (void*) npt);
1286  }
1287 
1288  return res;
1289 }

References make_points_to(), points_to_approximation, points_to_descriptor, points_to_equal_p(), points_to_rank(), points_to_sink, points_to_source, set_add_element(), SET_FOREACH, set_generic_make(), set_private, and simple_cell_to_store_independent_cell().

Referenced by any_loop_to_points_to(), and new_any_loop_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_indices_to_array_index_number()

int points_to_indices_to_array_index_number ( list  sl)

Count the number of array indices and ignore the field subscripts.

Parameters
sll

Definition at line 384 of file points_to_init_analysis.c.

385 {
386  int c = 0;
387  FOREACH(EXPRESSION, s, sl) {
388  if(!expression_reference_p(s))
389  c++;
390  }
391  return c;
392 }

References EXPRESSION, expression_reference_p(), and FOREACH.

Referenced by create_stub_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_indices_to_subscript_indices()

list points_to_indices_to_subscript_indices ( list  ptsl)

Generate a new subscript list.

References to fields are ignored, constant and unbounded expressions are preserved, non-constant expressions are replaced by unbounded expressions.

Parameters
ptsltsl

Definition at line 425 of file points_to_init_analysis.c.

426 {
427  list csl = NIL;
428  list sl = NIL;
429  for(csl = ptsl; !ENDP(csl); POP(csl)) {
430  expression se = EXPRESSION(CAR(csl));
431  // FI: how many different kinds of expressions do we have?
432  // This dichotomy between references and calls may be too simple
433  if(!expression_reference_p(se)) {
434  if(!unbounded_expression_p(se)) {
436  sl = CONS(EXPRESSION, copy_expression(se), sl);
437  else
438  // do not propagate store-dependent information
440  }
441  else { // copy the unbounded expression
442  sl = CONS(EXPRESSION, copy_expression(se), sl);
443  }
444  }
445  else {
447  entity v = reference_variable(r);
448  if(entity_field_p(v))
449  ; // ignore fields
450  else
451  // do not propagate store-dependent information
453  }
454  }
455  sl = gen_nreverse(sl);
456  return sl;
457 }
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
bool entity_field_p(entity e)
e is the field of a structure
Definition: entity.c:857

References CAR, CONS, copy_expression(), ENDP, entity_field_p(), EXPRESSION, expression_reference(), expression_reference_p(), extended_integer_constant_expression_p(), gen_nreverse(), make_unbounded_expression(), NIL, POP, reference_variable, and unbounded_expression_p().

Referenced by create_stub_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_indices_to_unbounded_indices()

void points_to_indices_to_unbounded_indices ( list  sl)

FI: probably a duplicate...

Parameters
sll

Definition at line 395 of file points_to_init_analysis.c.

396 {
397  list csl = NIL;
398  for (csl = sl; !ENDP(csl); POP(csl)) {
399  expression se = EXPRESSION(CAR(csl));
400  if (!expression_reference_p(se)) {
401  if (unbounded_expression_p(se))
402  ;
403  else if (expression_is_constant_p(se))
404  ;
405  else {
406  free_expression(se);
408  }
409  }
410  else {
412  entity v = reference_variable(r);
413  if(!entity_field_p(v))
414  free_expression(se);
416  }
417  }
418  return; // Useful for gdb?
419 }
bool expression_is_constant_p(expression e)
BEGIN_EOLE.
Definition: constant.c:666

References CAR, ENDP, entity_field_p(), EXPRESSION, EXPRESSION_, expression_is_constant_p(), expression_reference(), expression_reference_p(), free_expression(), make_unbounded_expression(), NIL, POP, reference_variable, and unbounded_expression_p().

+ Here is the call graph for this function:

◆ points_to_may_filter()

set points_to_may_filter ( set  in)

returns a set which contains all the MAY points to

Parameters
inn

Definition at line 716 of file constant-path-utils.c.

717 {
720 
721  SET_FOREACH(points_to, pt, in){
723  set_add_element(in_may, in_may, (void*)pt);
724  }
725  return in_may;
726 }

References approximation_may_p, points_to_approximation, points_to_equal_p(), points_to_rank(), set_add_element(), SET_FOREACH, set_generic_make(), and set_private.

Referenced by list_assignment_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_must_filter()

set points_to_must_filter ( set  in)

returns a set which contains all the EXACT points to

Parameters
inn

Definition at line 729 of file constant-path-utils.c.

730 {
733  SET_FOREACH(points_to, pt, in){
735  set_add_element(in_must, in_must, (void*)pt);
736  }
737  return in_must;
738 }

References approximation_exact_p, points_to_approximation, points_to_equal_p(), points_to_rank(), set_add_element(), SET_FOREACH, set_generic_make(), and set_private.

Referenced by list_assignment_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_name()

string points_to_name ( const points_to  pt)

create a string which is a concatenation of the source's name, the sink's name and the approximation of their relation(may or exact).

The same string is used by the function points_to_rank()

Parameters
ptt

Definition at line 163 of file points_to_set.c.

164 {
165  cell source = points_to_source(pt);
166  cell sink = points_to_sink(pt);
168  tag rel_tag = approximation_tag(rel);
169  string s = strdup(int2a(rel_tag));
170  reference sro = cell_to_reference(source);
171  reference sri = cell_to_reference(sink);
172  string s1 = strdup(reference_to_string(sro));
173  string s2 = strdup(reference_to_string(sri));
174  string key = strdup(concatenate(s1,
175  " ",
176  s2,
177  s,
178  NULL));
179  return key;
180 }

References approximation_tag, cell_to_reference(), concatenate(), int2a(), points_to_approximation, points_to_sink, points_to_source, reference_to_string(), s1, and strdup().

+ Here is the call graph for this function:

◆ points_to_nowhere()

set points_to_nowhere ( list  lhs_list,
set  input 
)

arg1: list of cells arg2: set of points-to Create a points-to set with elements of lhs_list as source and NOWHERE as sink.

Iterate over input and kill all points-to relations where sinks are elements of lhs_list.

if the lhs_set or the rhs set contains more than an element, we set the approximation to MAY.

Computing the gen set

Parameters
lhs_lisths_list
inputnput

Definition at line 1351 of file constant-path-utils.c.

1352 {
1354  points_to_rank);
1356  points_to_rank);
1358  points_to_rank);
1360  points_to_rank);
1362 
1363  SET_FOREACH(points_to, p, input) {
1364  FOREACH(cell, c, lhs_list) {
1365  if(points_to_source(p) == c)
1366  set_add_element(kill, kill, p);
1367  }
1368  }
1369  set_difference(input_kill_diff, input, kill);
1370  /* if the lhs_set or the rhs set contains more than an element, we
1371  set the approximation to MAY. */
1372  if((int)gen_length(lhs_list) > 1)// || set_size(rhs_set)>1)
1373  a = make_approximation_may();
1374 
1375  /* Computing the gen set */
1376  FOREACH(cell, c, lhs_list) {
1377  cell sink = make_nowhere_cell();
1379  set_add_element(gen, gen, (void*)pt_to);
1380  }
1381  free_approximation(a);
1382  set_union(res, gen, input_kill_diff);
1383 
1384  return res;
1385 }

References copy_approximation(), FOREACH, free_approximation(), gen(), gen_length(), input(), make_approximation_exact(), make_approximation_may(), make_descriptor_none(), make_nowhere_cell(), make_points_to(), points_to_equal_p(), points_to_rank(), points_to_source, set_add_element(), set_difference(), SET_FOREACH, set_generic_make(), set_private, and set_union().

+ Here is the call graph for this function:

◆ points_to_null_sinks()

list points_to_null_sinks ( void  )

The null location is not typed. The impact on dependence test is not clear.

Definition at line 87 of file sinks.c.

88 {
89  /* The null location is not typed. The impact on dependence test is
90  not clear. */
92  return entity_to_sinks(ne);
93 }

References entity_null_locations(), and entity_to_sinks().

Referenced by call_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_path_to_k_limited_points_to_path()

points_to points_to_path_to_k_limited_points_to_path ( list  p,
int  k,
type  t,
bool  array_p,
pt_map  in 
)

"p" is a points-to path ending with a cell that points towards a new cell ot type "t".

To avoid creating infinite/unbounded path, no more than k nodes of type "t" can be present in path "p". If k are found, a cycle is created to represent longer paths. The corresponding arc is returned. If the creation condition is not met, do not create a new arc.

The current path cannot be made any longer

Find the k-th node of type "t" if it exists

Skip sources that are already in the path "p" so as to avoid infinite path due to cycles in points-to graph "in".

Parameters
array_prray_p
inn

Definition at line 1004 of file points_to_set.c.

1009 {
1010  pips_assert("p contains at least one element", !ENDP(p));
1011 
1013  cell c = CELL(CAR(p));
1014  list sources = sink_to_sources(c, points_to_graph_set(in), false); // No duplication of cells
1015 
1016  if(ENDP(sources)) {
1017  /* The current path cannot be made any longer */
1018 
1019  /* Find the k-th node of type "t" if it exists */
1021  if(!cell_undefined_p(kc)) {
1022  // cell nkc = copy_cell(kc);
1023  // The above function should return a freshly allocated cell or
1024  // a cell_undefined
1025  cell nkc = kc;
1026  cell source = copy_cell(CELL(CAR(gen_last(p))));
1027  pt = make_points_to(source, nkc, make_approximation_may(),
1029  }
1030  }
1031  else {
1032  FOREACH(CELL, source, sources) {
1033  /* Skip sources that are already in the path "p" so as to avoid
1034  infinite path due to cycles in points-to graph "in". */
1035  if(node_in_points_to_path_p(source, p)) {
1036  ; // Could be useful for debugging
1037  }
1038  else {
1039  list np = CONS(CELL, source, p); // make the path longer
1040  // And recurse
1041  pt = points_to_path_to_k_limited_points_to_path(np, k, t, array_p, in);
1042  // And restore p
1043  CDR(np) = NIL;
1044  gen_free_list(np);
1045  if(!points_to_undefined_p(pt)) // Stop as soon as an arc has been created; FI->AM/FC: may not be correct...
1046  break;
1047  }
1048  }
1049  }
1050  return pt;
1051 }
cell find_kth_points_to_node_in_points_to_path(list p, type t, int k)
Find the "k"-th node of type "t" in list "p".
list sink_to_sources(cell sink, set pts, bool fresh_p)
Build a list of possible cell sources for cell "sink" in points-to graph "pts".
bool node_in_points_to_path_p(cell n, list p)

References CAR, CDR, CELL, cell_undefined_p, CONS, copy_cell(), ENDP, find_kth_points_to_node_in_points_to_path(), FOREACH, gen_free_list(), gen_last(), make_approximation_may(), make_descriptor_none(), make_points_to(), NIL, node_in_points_to_path_p(), pips_assert, points_to_graph_set, points_to_path_to_k_limited_points_to_path(), points_to_undefined, points_to_undefined_p, and sink_to_sources().

Referenced by create_k_limited_stub_points_to(), and points_to_path_to_k_limited_points_to_path().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_rank()

_uint points_to_rank ( const void *  vpt,
size_t  size 
)

create a key which is a concatenation of the source's name, the sink's name and the approximation of their relation(may or exact)

Parameters
vptpt
sizeize

Definition at line 135 of file points_to_set.c.

136 {
137  points_to pt= (points_to)vpt;
138  cell source = points_to_source(pt);
139  cell sink = points_to_sink(pt);
141  tag rel_tag = approximation_tag(rel);
142  string s = strdup(int2a(rel_tag));
143  reference sro = cell_to_reference(source);
144  reference sri = cell_to_reference(sink);
145  // FI: strdup must be useless
146  string s1 = strdup(reference_to_string(sro));
147  string s2 = strdup(reference_to_string(sri));
148  string key = strdup(concatenate(s1,
149  " ",
150  s2,
151  s,
152  NULL));
153  _uint rank = hash_string_rank(key,size);
154  free(key);
155  return rank;
156 }
static entity rank
uintptr_t _uint
Definition: newgen_types.h:54

References approximation_tag, cell_to_reference(), concatenate(), free(), hash_string_rank(), int2a(), points_to_approximation, points_to_sink, points_to_source, rank, reference_to_string(), s1, and strdup().

Referenced by array_formal_parameter_to_stub_points_to(), compute_points_to_binded_set(), derived_formal_parameter_to_stub_points_to(), formal_points_to_parameter(), gen_may_constant_paths(), gen_may_set(), gen_must_constant_paths(), gen_must_set(), init_points_to_analysis(), kill_may_set(), merge_points_to_set(), new_points_to_unstructured(), opgen_null_location(), pointer_formal_parameter_to_stub_points_to(), points_to_anywhere(), points_to_anywhere_typed(), points_to_function_projection(), points_to_independent_store(), points_to_may_filter(), points_to_must_filter(), points_to_nowhere(), typedef_formal_parameter_to_stub_points_to(), and user_call_to_points_to_fast_interprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_reference_to_number_of_unbounded_dimensions()

int points_to_reference_to_number_of_unbounded_dimensions ( reference  r)

Definition at line 2104 of file points_to_set.c.

2105 {
2106  list sl = reference_indices(r);
2108  return n;
2109 }
int points_to_subscripts_to_number_of_unbounded_dimensions(list sl)

References points_to_subscripts_to_number_of_unbounded_dimensions(), and reference_indices.

Referenced by points_to_cell_to_number_of_unbounded_dimensions().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_reference_to_translation()

list points_to_reference_to_translation ( reference  n_r,
list  sl,
pt_map  ptm,
bool  fresh_p 
)

FI: easier it fresh_p is true...

Try to use an extra subscript

We've got one translation at least. Now, we must update the subscripts.

We assume that c has at least as many subscripts as n_r

Update the last subscripts. E.g. _x_3[*] and _x_3[0] ->y[i][0] leads to y[i]*

Update the last subscripts. E.g. _q_2[0][one] and _q_2[0] ->s leads to sone

Parameters
n_r_r
sll
ptmtm
fresh_presh_p

Definition at line 1682 of file points_to_set.c.

1686 {
1687  pips_assert("fresh_p must be set to true", fresh_p);
1688  list translations = NIL;
1689  // cell n_c = make_cell_reference(n_r); // FI: memory leak
1690  //list atl = points_to_source_to_sinks(n_c, ptm, fresh_p); // Address Translation List?
1691  // list atl = points_to_source_to_any_sinks(n_c, ptm, fresh_p); // Address Translation List?
1692  list atl = NIL;
1693  entity v = reference_variable(n_r);
1694  // matching list of points-to arcs:
1695  //list ml = source_entity_to_points_to(v, sl, ptm);
1696  list ml = reference_to_points_to_translations(v, sl, ptm);
1697  return ml;
1698 
1699  if(ENDP(ml)) {
1700  if(ENDP(sl)) {
1701  pips_internal_error("Reference \"n_r\" cannot be translated with \"ptm\".\n");
1702  }
1703  else {
1704  /* Try to use an extra subscript */
1705  expression ns = EXPRESSION(CAR(sl));
1708  translations = points_to_reference_to_translation(n_r, CDR(sl), ptm, fresh_p);
1709  }
1710  }
1711  else {
1712  /* We've got one translation at least. Now, we must update the subscripts. */
1713  FOREACH(CELL, c, atl) {
1714  if(!null_cell_p(c) && !nowhere_cell_p(c)) {
1715  reference c_r = cell_any_reference(c);
1716  /* We assume that c has at least as many subscripts as n_r */
1717  int c_d = (int) gen_length(reference_indices(c_r));
1718  int r_d = (int) gen_length(reference_indices(n_r))+gen_length(sl);
1719  //pips_assert("The target dimension is larger than the source dimension",
1720  // c_d>=r_d);
1721  int o = c_d-r_d;
1722  if(o==0) {
1724  gen_full_copy_list(sl));
1725  }
1726  else if(o>0) {
1727  /* Update the last subscripts. E.g. _x_3[*] and _x_3[0]
1728  ->y[i][0] leads to y[i][*] (see EffectsWithPointsTo/call05.c) */
1729  list csl = reference_indices(c_r);
1730  list acsl = gen_nthcdr(o-1, csl);
1731  CDR(acsl) = gen_nconc(reference_indices(n_r),
1732  gen_full_copy_list(sl));
1733  }
1734  else {
1735  /* Update the last subscripts. E.g. _q_2[0][one] and _q_2[0]
1736  ->s leads to s[one] (see EffectsWithPointsTo/call05.c) */
1737  // FI: it should be more complex, but I'll wait for more examples...
1739  }
1740  translations = atl; // FI: we may not need to variables...
1741  }
1742  }
1743  }
1744  return translations;
1745 }
list gen_nthcdr(int n, const list lx)
caution: the first item is 0! was: return( (n<=0) ? l : gen_nthcdr( n-1, CDR( l ))) ; if n>gen_length...
Definition: list.c:700
list reference_to_points_to_translations(entity v, list sl, pt_map ptm)
This function is designed to work properly for the translation of effects at call sites.
list points_to_reference_to_translation(reference n_r, list sl, pt_map ptm, bool fresh_p)
FI: easier it fresh_p is true...

References CAR, CDR, CELL, cell_any_reference(), CONS, copy_expression(), ENDP, EXPRESSION, FOREACH, gen_full_copy_list(), gen_length(), gen_nconc(), gen_nthcdr(), int, NIL, nowhere_cell_p(), null_cell_p(), pips_assert, pips_internal_error, points_to_reference_to_translation(), reference_indices, reference_to_points_to_translations(), and reference_variable.

Referenced by points_to_reference_to_translation(), and points_to_source_to_translations().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_set_block_projection()

set points_to_set_block_projection ( set  pts,
list  l,
bool  main_p,
bool  body_p 
)

Remove from "pts" arcs based on at least one local entity in list "l" and preserve those based on static and global entities.

This function is called when exiting a statement block.

Detection of dangling pointers.

Detection of memory leaks. Could be skipped when dealing with the "main" module, but the information would have to be passed down thru an extra parameter.

Side-effects on argument "pts" which is returned.

Check for memory leaks

Both the sink and the source disappear: the arc is removed

Any memory leak?

Parameters
ptsts
main_pain_p
body_pody_p

Definition at line 206 of file points_to_set.c.

207 {
208  list pls = NIL; // Possibly lost sinks
209  list new_l = NIL; // new arcs to add
210  list old_l = NIL; // old arcs to remove
212  FOREACH(ENTITY, e, l) {
214  // The use of "sink_p" is only an optimization
215  bool sink_p = pointer_type_p(uet)
217  || struct_type_p(uet)
218  || array_of_struct_type_p(uet);
219 
220  SET_FOREACH(points_to, pt, pts){
221  cell source = points_to_source(pt);
222  cell sink = points_to_sink(pt);
225 
226  if(sink_p && e == e_sr && (!(variable_static_p(e_sr) || top_level_entity_p(e_sr) || heap_cell_p(source) || e_sr==rv))) {
227  set_del_element(pts, pts, (void*)pt);
228  if(heap_cell_p(sink)) {
229  /* Check for memory leaks */
230  pls = CONS(CELL, sink, pls);
231  }
232  // FI: memory leak? sink should be copied and pt be freed...
233  }
234  else if(e == e_sk
235  && (!(variable_static_p(e_sk)
236  || top_level_entity_p(e_sk)
237  || heap_cell_p(sink)))) {
238  if(gen_in_list_p(e_sr, l)) {
239  /* Both the sink and the source disappear: the arc is removed */
240  set_del_element(pts, pts, (void*)pt);
241  }
242  else {
244 
245  if(approximation_exact_p(a)) {
246  // FI: this may be transient if the source is a formal
247  // parameter and if the projected block is the function
248  // statement
249  if(!body_p || !formal_parameter_p(e_sr))
250  pips_user_warning("Dangling pointer \"%s\" towards \"%s\".\n",
251  entity_user_name(e_sr),
252  entity_user_name(e_sk));
253  }
254  // list lhs = CONS(CELL, source, NIL);
255  // pts = points_to_nowhere_typed(lhs, pts);
256  bool to_be_freed;
257  type sink_t = points_to_cell_to_type(sink, &to_be_freed);
258  type n_sink_t = copy_type(sink_t);
259  if(to_be_freed) free_type(sink_t);
260  points_to npt = make_points_to(copy_cell(source),
261  make_typed_nowhere_cell(n_sink_t),
264  // Since we are looping on pts... no side-effects on pts
265  new_l = CONS(POINTS_TO, npt, new_l);
266  old_l = CONS(POINTS_TO, pt, old_l);
267  }
268  }
269  }
270  }
271 
272  FOREACH(POINTS_TO, npt, new_l)
273  add_arc_to_simple_pt_map(npt, pts);
274  gen_free_list(new_l);
275  FOREACH(POINTS_TO, pt, old_l)
277  gen_free_list(old_l);
278 
279  if(!main_p) {
280  /* Any memory leak? */
281  FOREACH(CELL, c, pls) {
282  if(!sink_in_set_p(c, pts)) {
284  entity b = reference_variable(r);
285  pips_user_warning("Memory leak for bucket \"%s\".\n",
286  entity_name(b));
287  points_to_graph ptg = make_points_to_graph(false, pts);
288  ptg = memory_leak_to_more_memory_leaks(c, ptg);
291  }
292  }
293  }
294  return pts;
295 }
set add_arc_to_simple_pt_map(points_to a, set s)
bool sink_in_set_p(cell sink, set s)
test if a cell appear as a sink in a set of points-to
set remove_arc_from_simple_pt_map(points_to a, set s)

References add_arc_to_simple_pt_map(), any_function_to_return_value(), approximation_exact_p, array_of_pointers_type_p(), array_of_struct_type_p(), CELL, cell_any_reference(), cell_to_reference(), CONS, copy_approximation(), copy_cell(), copy_type(), ENTITY, entity_basic_concrete_type(), entity_name, entity_user_name(), FOREACH, formal_parameter_p(), free_points_to_graph(), free_type(), gen_free_list(), gen_in_list_p(), get_current_module_entity(), heap_cell_p(), make_descriptor_none(), make_points_to(), make_points_to_graph(), make_typed_nowhere_cell(), memory_leak_to_more_memory_leaks(), NIL, pips_user_warning, pointer_type_p(), POINTS_TO, points_to_approximation, points_to_cell_to_type(), points_to_graph_set, points_to_sink, points_to_source, reference_variable, remove_arc_from_simple_pt_map(), set_del_element(), SET_FOREACH, set_undefined, sink_in_set_p(), struct_type_p(), top_level_entity_p(), and variable_static_p().

Referenced by statement_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_set_sharing_p()

bool points_to_set_sharing_p ( set  s)

Sharing of cells

Sharing of references

Definition at line 2978 of file points_to_set.c.

2979 {
2980  bool sharing_p = false;
2981 
2982  SET_FOREACH(points_to, pt1, s) {
2983  cell source_1 = points_to_source(pt1);
2984  cell sink_1 = points_to_sink(pt1);
2985  reference source_r1 = cell_any_reference(source_1);
2986  reference sink_r1 = cell_any_reference(sink_1);
2987 
2988  bool found_p = false;
2989  SET_FOREACH(points_to, pt2, s) {
2990  if(pt1==pt2)
2991  found_p = true;
2992  if(found_p && pt1!=pt2) {
2993  cell source_2 = points_to_source(pt2);
2994  cell sink_2 = points_to_sink(pt2);
2995  reference source_r2 = cell_any_reference(source_2);
2996  reference sink_r2 = cell_any_reference(sink_2);
2997 
2998  bool new_sharing_p = false;
2999 
3000  /* Sharing of cells */
3001  if(source_1==source_2) {
3002  new_sharing_p = true;
3003  fprintf(stderr, "Sharing between source_1 and source_2.\n");
3004  }
3005  else if(source_1==sink_2) {
3006  new_sharing_p = true;
3007  fprintf(stderr, "Sharing between source_1 and sink_2.\n");
3008  }
3009  else if(sink_1==source_2) {
3010  new_sharing_p = true;
3011  fprintf(stderr, "Sharing between sink_1 and source_2.\n");
3012  }
3013  else if(sink_1==sink_2) {
3014  new_sharing_p = true;
3015  fprintf(stderr, "Sharing between sink_1 and sink_2.\n");
3016  }
3017 
3018  if(!new_sharing_p) {
3019  /* Sharing of references */
3020  if(source_r1==source_r2) {
3021  new_sharing_p = true;
3022  fprintf(stderr, "Sharing between source_r1 and source_r2.\n");
3023  }
3024  else if(source_r1==sink_r2) {
3025  new_sharing_p = true;
3026  fprintf(stderr, "Sharing between source_r1 and sink_r2.\n");
3027  }
3028  else if(sink_r1==source_r2) {
3029  new_sharing_p = true;
3030  fprintf(stderr, "Sharing between sink_r1 and source_r2.\n");
3031  }
3032  else if(sink_r1==sink_r2) {
3033  new_sharing_p = true;
3034  fprintf(stderr, "Sharing between sink_r1 and sinke_r2.\n");
3035  }
3036  }
3037  if(new_sharing_p) {
3038  fprintf(stderr, "For pt1 ");
3039  dump_points_to(pt1);
3040  fprintf(stderr, "\nand pt2 ");
3041  dump_points_to(pt2);
3042  }
3043  sharing_p = sharing_p || new_sharing_p;
3044  }
3045  }
3046  }
3047  return sharing_p;
3048 }
void dump_points_to(const points_to pt)

References cell_any_reference(), dump_points_to(), fprintf(), points_to_sink, points_to_source, and SET_FOREACH.

Referenced by consistent_points_to_set().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_set_to_module_stub_cell_list()

list points_to_set_to_module_stub_cell_list ( entity  m,
set  s,
list  osl 
)
Parameters
oslsl

Definition at line 2860 of file interprocedural.c.

2861 {
2862  return generic_points_to_set_to_stub_cell_list(m, s, osl);
2863 }
list generic_points_to_set_to_stub_cell_list(entity f, set s, list osl)
Add cells referencing a points-to stub found in parameter "s" are copied and added to list "osl".

References generic_points_to_set_to_stub_cell_list().

Referenced by user_call_to_points_to_interprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_set_to_stub_cell_list()

list points_to_set_to_stub_cell_list ( set  s,
list  osl 
)
Parameters
oslsl

Definition at line 2855 of file interprocedural.c.

2856 {
2858 }

References entity_undefined, and generic_points_to_set_to_stub_cell_list().

+ Here is the call graph for this function:

◆ points_to_sink_to_points_to()

points_to points_to_sink_to_points_to ( cell  sink,
pt_map  ptm 
)

Return the points-to "fpt" ending in cell "sink" if it exists.

Return points-to_undefined otherwise.

  1. See if cell "sink" is the destination vertex of a points-to arc.
Parameters
sinkink
ptmtm

Definition at line 1988 of file points_to_set.c.

1989 {
1991  set pts = points_to_graph_set(ptm);
1992 
1993  /* 1. See if cell "sink" is the destination vertex of a points-to arc. */
1994  SET_FOREACH( points_to, pt, pts) {
1995  if(cell_equal_p(sink, points_to_sink(pt))) {
1996  fpt = pt;
1997  break;
1998  }
1999  }
2000  return fpt;
2001 }

References cell_equal_p(), points_to_graph_set, points_to_sink, points_to_undefined, and SET_FOREACH.

Referenced by remove_impossible_arcs_to_null().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_sink_to_sources()

list points_to_sink_to_sources ( cell  sink,
pt_map  ptm,
bool  fresh_p 
)

Build the sources of sink "sink" according to the points-to graphs.

If "sink" is not found in the graph, return an empty list "sources". If "fresh_p", allocate copies. If not, return pointers to the destination vertices in "ptm".

It is not clear how much the abstract address lattice must be used to retrieve sources... If source = a[34], clearly a[*] is an OK equivalent source if a[34] is not a vertex of "ptm".

  1. See if cell "sink" is the destination vertex of a points-to arc.
  2. Much harder... See if sink is contained in one of the many abstract sinks or if its address can be obtained from the address of another sink cell thanks to pointer arithmetic or indexing. Step 1 is subsumed by Step 2... but is much faster.

FI: I am not sure that using pointer arithmetics to declare equivalence is a good idea.

Parameters
sinkink
ptmtm
fresh_presh_p

Definition at line 1947 of file points_to_set.c.

1948 {
1949  list sources = NIL;
1950  set pts = points_to_graph_set(ptm);
1951 
1952  /* 1. See if cell "sink" is the destination vertex of a points-to arc. */
1953  SET_FOREACH( points_to, pt, pts) {
1954  if(cell_equal_p(sink, points_to_sink(pt))) {
1955  cell sc = fresh_p? copy_cell(points_to_source(pt)) : points_to_source(pt);
1956  sources = CONS(CELL, sc, sources);
1957  }
1958  }
1959 
1960 
1961  /* 2. Much harder... See if sink is contained in one of the many
1962  abstract sinks or if its address can be obtained from the address
1963  of another sink cell thanks to pointer arithmetic or
1964  indexing. Step 1 is subsumed by Step 2... but is much faster. */
1965  if(ENDP(sources)) {
1966  SET_FOREACH(points_to, pt, pts) {
1967  if(cell_included_p(sink, points_to_sink(pt))
1968  /* FI: I am not sure that using pointer arithmetics to
1969  declare equivalence is a good idea. */
1970  || cell_equivalent_p(sink, points_to_sink(pt))) {
1971  // FI: memory leak forced because of refine_points_to_cell_subscripts
1972  cell sc = (true||fresh_p)? copy_cell(points_to_source(pt)) : points_to_source(pt);
1973  // FI: I do not remember what this is for...
1974  // FI: does not seem right; for instance:
1975  // sources(_ll_1_2__1[next]) may not exist while "_ll_1[next]"
1976  // with points to arc "_ll_1[next]->_ll_1_2__1" might be acceptable
1977  // refine_points_to_cell_subscripts(sc, sink, points_to_sink(pt));
1978  sources = CONS(CELL, sc, sources);
1979  }
1980  }
1981  }
1982 
1983  return sources;
1984 }
bool cell_equivalent_p(cell, cell)
Check that memory locations denoted by cell "c1" can be reached by knowing cell "c2" and by using poi...
Definition: effects.c:1311

References CELL, cell_equal_p(), cell_equivalent_p(), cell_included_p(), CONS, copy_cell(), ENDP, NIL, points_to_graph_set, points_to_sink, points_to_source, and SET_FOREACH.

Referenced by freed_list_to_points_to(), and generic_remove_unreachable_vertices_in_points_to_graph().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_source_alias()

cell points_to_source_alias ( points_to  pt,
set  pt_binded 
)

Let "pt_binded" be the results of assignments of actual arguments to formal arguments (see compute_points_to_binded_set()).

Let "pt" be a points-to arc in "pt_binded".

Find for the source of p its corresponding alias, which means finding another source that points to the same location.

Parameters
ptt
pt_bindedt_binded

Definition at line 2873 of file interprocedural.c.

2874 {
2875  cell source = cell_undefined;
2876  cell sink1 = points_to_sink(pt);
2877  SET_FOREACH(points_to, p, pt_binded) {
2878  cell sink2 = points_to_sink(p);
2879  if(cell_equal_p(sink1, sink2)) {
2880  source = points_to_source(p);
2881  break;
2882  }
2883  }
2884  if(cell_undefined_p(source))
2885  pips_internal_error("At least one alias should be found.\n");
2886 
2887  return source;
2888 }

References cell_equal_p(), cell_undefined, cell_undefined_p, pips_internal_error, points_to_sink, points_to_source, and SET_FOREACH.

Referenced by points_to_binding().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_source_name_to_sinks()

list points_to_source_name_to_sinks ( string  sn,
pt_map  ptm,
bool  fresh_p 
)

Use "sn" as a source name to derive a list of sink cells according to the points-to graph ptm.

Allocate copies of the sink cells if "fresh_p".

Parameters
snn
ptmtm
fresh_presh_p

Definition at line 2008 of file points_to_set.c.

2009 {
2010  list sinks = NIL;
2011  set pts = points_to_graph_set(ptm);
2012 
2013  SET_FOREACH( points_to, pt, pts) {
2014  cell c = points_to_source(pt);
2015  string cn = points_to_cell_name(c);
2016  if(strcmp(sn, cn)==0) {
2017  cell sc = fresh_p? copy_cell(points_to_sink(pt)) : points_to_sink(pt);
2018  sinks = CONS(CELL, sc, sinks);
2019  }
2020  free(cn);
2021  }
2022 
2023  return sinks;
2024 }

References CELL, CONS, copy_cell(), free(), NIL, points_to_cell_name(), points_to_graph_set, points_to_sink, points_to_source, and SET_FOREACH.

Referenced by normalize_points_to_graph().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_source_name_to_source_cell()

cell points_to_source_name_to_source_cell ( string  sn,
pt_map  ptm,
bool  fresh_p 
)
Parameters
snn
ptmtm
fresh_presh_p

Definition at line 2026 of file points_to_set.c.

2027 {
2028  cell rc = cell_undefined;
2029  set pts = points_to_graph_set(ptm);
2030 
2031  SET_FOREACH(points_to, pt, pts) {
2032  cell c = points_to_source(pt);
2033  string cn = points_to_cell_name(c);
2034  if(strcmp(sn, cn)==0) {
2035  rc = fresh_p? copy_cell(c) : c;
2036  break;
2037  }
2038  free(cn);
2039  }
2040 
2041  return rc;
2042 }

References cell_undefined, copy_cell(), free(), points_to_cell_name(), points_to_graph_set, points_to_source, and SET_FOREACH.

Referenced by normalize_points_to_graph().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_source_projection()

set points_to_source_projection ( set  pts,
entity  e 
)

Remove all arcs starting from e because e has been assigned a new value.

Check for memory leaks

Any memory leak?

Parameters
ptsts

Definition at line 298 of file points_to_set.c.

299 {
300  list pls = NIL; // Possibly lost sinks
301 
302  SET_FOREACH(points_to, pt, pts) {
303  cell source = points_to_source(pt);
304  cell sink = points_to_sink(pt);
306  //entity e_sk = reference_variable(cell_to_reference(sink));
307 
308  if(e == e_sr) {
309  set_del_element(pts, pts, (void*)pt);
310  if(heap_cell_p(sink)) {
311  /* Check for memory leaks */
312  pls = CONS(CELL, sink, pls);
313  }
314  }
315  }
316 
317  /* Any memory leak? */
318  FOREACH(CELL, c, pls) {
319  if(!sink_in_set_p(c, pts)) {
321  entity b = reference_variable(r);
322  pips_user_warning("Memory leak for bucket \"%s\".\n",
323  entity_name(b));
324  }
325  }
326  return pts;
327 }

References CELL, cell_any_reference(), cell_to_reference(), CONS, entity_name, FOREACH, heap_cell_p(), NIL, pips_user_warning, points_to_sink, points_to_source, reference_variable, set_del_element(), SET_FOREACH, and sink_in_set_p().

Referenced by reference_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_source_to_any_sinks()

list points_to_source_to_any_sinks ( cell  source,
pt_map  ptm,
bool  fresh_p 
)

Retrieve all possible sinks of the source.

Parameters
sourceource
ptmtm
fresh_presh_p

Definition at line 1933 of file points_to_set.c.

1934 {
1935  return generic_points_to_source_to_sinks(source, ptm, fresh_p, false, true, false);
1936 }

References generic_points_to_source_to_sinks().

Referenced by filter_formal_context_according_to_actual_context(), new_filter_formal_context_according_to_actual_context(), and upgrade_approximations_in_points_to_set().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_source_to_arcs()

list points_to_source_to_arcs ( cell  source,
pt_map  ptm,
bool  fresh_p 
)

Build the list of arcs whose source is "source" according to the points-to graphs "ptm".

If "source" is not found in the graph, return an empty list "sinks". If "fresh_p", allocate copies. If not, return pointers to the arcs in "ptm".

It is not clear how much the abstract address lattice must be used to retrieve sinks... If source = a[34], clearly a[*] is an OK equivalent source if a[34] is not a vertex of "ptm". Currently, we assume that the origin vertex must be exactly "source".

See when the cell "source" is the starting vertex of a points-to arc.

Parameters
sourceource
ptmtm
fresh_presh_p

Definition at line 2081 of file points_to_set.c.

2082 {
2083  list arcs = NIL;
2084  set pts = points_to_graph_set(ptm);
2085 
2086  /* See when the cell "source" is the starting vertex of a points-to arc. */
2087  SET_FOREACH( points_to, pt, pts) {
2088  if(cell_equal_p(source, points_to_source(pt))) {
2089  points_to pta = fresh_p? copy_points_to(pt) : pt;
2090  arcs = CONS(POINTS_TO, pta, arcs);
2091  }
2092  }
2093 
2094  return arcs;
2095 }

References cell_equal_p(), CONS, copy_points_to(), NIL, POINTS_TO, points_to_graph_set, points_to_source, and SET_FOREACH.

Referenced by fuse_points_to_sink_cells(), and struct_assignment_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_source_to_effective_sinks()

list points_to_source_to_effective_sinks ( cell  source,
pt_map  ptm,
bool  fresh_p 
)
Parameters
sourceource
ptmtm
fresh_presh_p

Definition at line 1915 of file points_to_set.c.

1916 {
1917  return generic_points_to_source_to_sinks(source, ptm, fresh_p, true, false, true);
1918 }

References generic_points_to_source_to_sinks().

+ Here is the call graph for this function:

◆ points_to_source_to_sinks()

list points_to_source_to_sinks ( cell  source,
pt_map  ptm,
bool  fresh_p 
)

Build the sinks of source "source" according to the points-to graphs.

If "source" is not found in the graph, return an empty list "sinks". If "fresh_p", allocate copies. If not, return pointers to the destination vertices in "ptm".

It is not clear how much the abstract address lattice must be used to retrieve sinks... If source = a[34], clearly a[*] is an OK equivalent source if a[34] is not a vertex of "ptm".

Parameters
sourceource
ptmtm
fresh_presh_p

Definition at line 1909 of file points_to_set.c.

1910 {
1911  //return generic_points_to_source_to_sinks(source, ptm, fresh_p, true, false, false);
1912  return generic_points_to_source_to_sinks(source, ptm, fresh_p, false, true, false);
1913 }

References generic_points_to_source_to_sinks().

Referenced by malloc_to_points_to_sinks(), recursive_filter_formal_context_according_to_actual_context(), and source_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_source_to_some_sinks()

list points_to_source_to_some_sinks ( cell  source,
pt_map  ptm,
bool  fresh_p 
)

May not retrieve all sinks of the source.

This happens with arrays of pointers. See EffectsWithPointers/call22.c

Parameters
sourceource
ptmtm
fresh_presh_p

Definition at line 1924 of file points_to_set.c.

1925 {
1926  return generic_points_to_source_to_sinks(source, ptm, fresh_p, false, false, false);
1927 }

References generic_points_to_source_to_sinks().

Referenced by new_recursive_filter_formal_context_according_to_actual_context_for_pointer_pair(), points_to_binding_arguments(), and recursive_filter_formal_context_according_to_actual_context().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_source_to_translations()

list points_to_source_to_translations ( cell  source,
pt_map  ptm,
bool  fresh_p 
)

Use "ptm" as a translation map.

Must be similar to a function written by Beatrice to evaluate a complex reference according to points-to information. In her case, it is not a translation, but an evaluation of the possibly many dereferencements contained in the reference.

Try to translate a prefix of the source reference and substitue it when a translation is found. No need to translate further down, unlike Beatrice's function.

fresh_p might be useless because new cells always must be generated.

Outdated comment: The cell source is not a source in ptm, but a related cell may be the source

Beware of constant strings...

Parameters
sourceource
ptmtm
fresh_presh_p

Definition at line 1760 of file points_to_set.c.

1761 {
1762  //list translations = points_to_source_to_sinks(source, ptm, fresh_p);
1763  reference r = cell_any_reference(source);
1764  entity v = reference_variable(r);
1765  list translations = NIL;
1766 
1767  if(ENDP(translations)) {
1768  /* Outdated comment: The cell source is not a source in ptm, but a
1769  related cell may be the source */
1770  list sl = reference_indices(r);
1771  reference n_r = make_reference(v, NIL);
1772  translations = points_to_reference_to_translation(n_r, sl, ptm, fresh_p);
1773  }
1774 
1775  ifdebug(8) {
1776  bool to_be_freed;
1777  type source_t = points_to_cell_to_type(source, &to_be_freed);
1778  type source_et = compute_basic_concrete_type(source_t);
1779  FOREACH(CELL, c, translations) {
1780  if(!null_cell_p(c) && !nowhere_cell_p(c) && !anywhere_cell_p(c)) {
1781  bool c_to_be_freed;
1782  type c_t = points_to_cell_to_type(c, &c_to_be_freed);
1783  type c_et = compute_basic_concrete_type(c_t);
1784  if(!overloaded_type_p(c_et) && !type_equal_p(source_et, c_et)
1785  /* Beware of constant strings... */
1786  && !type_functional_p(c_et))
1787  pips_internal_error("Type mismatch after translation.\n");
1788  if(c_to_be_freed) free_type(c_t);
1789  }
1790  }
1791  if(to_be_freed) free_type(source_t);
1792  }
1793 
1794  return translations;
1795 }

References anywhere_cell_p(), CELL, cell_any_reference(), compute_basic_concrete_type(), ENDP, FOREACH, free_type(), ifdebug, make_reference(), NIL, nowhere_cell_p(), null_cell_p(), overloaded_type_p(), pips_internal_error, points_to_cell_to_type(), points_to_reference_to_translation(), reference_indices, reference_variable, type_equal_p(), and type_functional_p.

+ Here is the call graph for this function:

◆ points_to_sources_to_effective_sinks()

list points_to_sources_to_effective_sinks ( list  sources,
pt_map  ptm,
bool  fresh_p 
)
Parameters
sourcesources
ptmtm
fresh_presh_p

Definition at line 2066 of file points_to_set.c.

2067 {
2068  return generic_points_to_sources_to_sinks(sources, ptm, fresh_p, true);
2069 }
list generic_points_to_sources_to_sinks(list sources, pt_map ptm, bool fresh_p, bool effective_p)
Build the union of the sinks of cells in "sources" according to the points-to graphs "ptm".

References generic_points_to_sources_to_sinks().

Referenced by translation_transitive_closure().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_sources_to_sinks()

list points_to_sources_to_sinks ( list  sources,
pt_map  ptm,
bool  fresh_p 
)
Parameters
sourcesources
ptmtm
fresh_presh_p

Definition at line 2061 of file points_to_set.c.

2062 {
2063  return generic_points_to_sources_to_sinks(sources, ptm, fresh_p, false);
2064 }

References generic_points_to_sources_to_sinks().

Referenced by fuse_points_to_sink_cells().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_storage()

void points_to_storage ( set  pts_to_set,
statement  s,
bool  store 
)

passes.c

passes.c

In case s is a loop, do, while or for, the parameter "store" is set to false to prevent key redefinitions in the underlying points-to hash-table. This entry condition is not checked.

In case s is a sequence, the sorted copy pts_to_set is associated to each substatement and shared by s and all its substatement.

Note: the function is called with store==true from points_to_whileloop(). And the hash-table can be updated (hash_update()).

Parameters
pts_to_setts_to_set
storetore

Definition at line 67 of file passes.c.

67  {
68  list pt_list = NIL, tmp_l;
70 
71  if ( !set_empty_p(pts_to_set) && store == true ) {
72 
73  pt_list = set_to_sorted_list(pts_to_set,
74  (int(*)(const void*, const void*))
76  tmp_l = gen_full_copy_list(pt_list);
77  new_pt_list = make_points_to_list(true, tmp_l);
78  points_to_list_consistent_p(new_pt_list);
79  store_or_update_pt_to_list(s, new_pt_list);
80 
82  if(instruction_sequence_p(i)) {
85  store_or_update_pt_to_list(stm, new_pt_list);
86  }
87  }
88  }
89  else if(set_empty_p(pts_to_set)){
90  tmp_l = gen_full_copy_list(pt_list);
91  new_pt_list = make_points_to_list(true, tmp_l);
92  store_or_update_pt_to_list(s, new_pt_list);
93  }
94  gen_free_list(pt_list);
95 }
#define instruction_sequence_p(x)
Definition: ri.h:1512
#define sequence_statements(x)
Definition: ri.h:2360
#define statement_instruction(x)
Definition: ri.h:2458

References FOREACH, gen_free_list(), gen_full_copy_list(), instruction_sequence, instruction_sequence_p, make_points_to_list(), NIL, points_to_compare_cells(), points_to_list_consistent_p(), points_to_list_undefined, sequence_statements, set_empty_p(), set_to_sorted_list(), statement_instruction, and store_or_update_pt_to_list().

+ Here is the call graph for this function:

◆ points_to_subscripts_to_number_of_unbounded_dimensions()

int points_to_subscripts_to_number_of_unbounded_dimensions ( list  sl)
Parameters
sll

Definition at line 2111 of file points_to_set.c.

2112 {
2113  int count = 0;
2114  FOREACH(EXPRESSION, s, sl) {
2115  if(unbounded_expression_p(s))
2116  count++;
2117  }
2118  return count;
2119 }

References count, EXPRESSION, FOREACH, and unbounded_expression_p().

Referenced by points_to_reference_to_number_of_unbounded_dimensions(), and sinks_fully_matches_source_p().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_to_context_points_to()

pt_map points_to_to_context_points_to ( pt_map  in)

Return the subset of "in" that is related to formal parameters and stubs.

More care should be taken about formal parameter modifications. Dummy initial variables should be allocated to preserve the values of formal parameters on entry.

Parameters
inn

Definition at line 127 of file passes.c.

128 {
129  pt_map out = new_pt_map();
130  set in_s = points_to_graph_set(in);
131  set out_s = points_to_graph_set(out);
132 
133  SET_FOREACH(points_to, pt, in_s) {
134  cell source = points_to_source(pt);
136  || stub_points_to_cell_p(source)) {
137  cell sink = points_to_sink(pt);
138  if(stub_points_to_cell_p(sink)) {
139  points_to npt = copy_points_to(pt);
140  add_arc_to_simple_pt_map(npt, out_s);
141  }
142  }
143  }
144 
145  return out;
146 }
bool formal_parameter_points_to_cell_p(cell)
Definition: points_to.c:99

References add_arc_to_simple_pt_map, copy_points_to(), formal_parameter_points_to_cell_p(), new_pt_map, out, points_to_graph_set, points_to_sink, points_to_source, SET_FOREACH, and stub_points_to_cell_p().

+ Here is the call graph for this function:

◆ points_to_translation_mapping_is_typed_p()

bool points_to_translation_mapping_is_typed_p ( set  translation)

FI: for some reason, the translation was built wrongly to express the fact that the source points to any element of the sink as in Semantics-New/Ancourt3009/memcpy09c where pointer arithmetic is used in the actual argument expression.

out -> buffer_out[*]

out cannot be replaced by buffer_out, because out[i] would result in buffer_out[i] instead of buffer_out[*].

Parameters
translationranslation

Definition at line 1433 of file interprocedural.c.

1434 {
1435  bool typed_p = true;
1436  SET_FOREACH(points_to, pt, translation) {
1437  cell source = points_to_source(pt);
1438  cell sink = points_to_sink(pt);
1439  type source_t = points_to_cell_to_concrete_type(source);
1440  type isink_t = points_to_cell_to_concrete_type(sink);
1441  type sink_t = constant_string_type_to_string_type(isink_t);
1442 #if 0
1443  if(type_functional_p(isink_t)) {
1444  reference ar = cell_any_reference(ac);
1445  entity a = reference_variable(ar);
1446  if(constant_string_entity_p(a)) {
1447  sink_t = ...;
1448  }
1449  }
1450 #endif
1451  if(char_type_p(source_t) && char_star_constant_function_type_p(isink_t)) {
1452  // an array of char points to a constant string, e.g. "YES"
1453  typed_p = true;
1454  }
1455  else if(!array_pointer_string_type_equal_p(source_t, sink_t)
1456  && !overloaded_type_p(sink_t)) {
1457  /* FI: for some reason, the translation was built wrongly to
1458  * express the fact that the source points to any element of the
1459  * sink as in Semantics-New/Ancourt3009/memcpy09c where pointer
1460  * arithmetic is used in the actual argument expression.
1461  *
1462  * out -> buffer_out[*]
1463  *
1464  * out cannot be replaced by buffer_out, because out[i] would
1465  * result in buffer_out[i] instead of buffer_out[*].
1466  */
1467  type st = type_to_pointed_type(source_t);
1468  // FI: if(type_structurally_equal_p(source_t, sink_t)? slower?
1469  if(array_pointer_string_type_equal_p(st, sink_t))
1470  typed_p = true;
1471  else {
1472  typed_p = false;
1473  pips_internal_error("Badly typed points-to translation mapping.\n");
1474  }
1475  break;
1476  }
1477  }
1478  return typed_p;
1479 }

References array_pointer_string_type_equal_p(), cell_any_reference(), char_star_constant_function_type_p(), char_type_p(), constant_string_entity_p(), constant_string_type_to_string_type(), overloaded_type_p(), pips_internal_error, points_to_cell_to_concrete_type(), points_to_sink, points_to_source, reference_variable, SET_FOREACH, type_functional_p, and type_to_pointed_type().

Referenced by filter_formal_context_according_to_actual_context(), new_filter_formal_context_according_to_actual_context(), points_to_translation_of_formal_parameters(), and recursive_filter_formal_context_according_to_actual_context().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_translation_of_formal_parameters()

void points_to_translation_of_formal_parameters ( list  fpcl,
list  al,
pt_map  pt_in,
set  translation 
)

List al and fpcl are assumed consistent, and consistent with the formal parameter ranks.

assumption about fpcl

This function does not return constant memory paths... This could fixed below with calls to points_to_indices_to_unbounded_indices(), but it could/should also be fixed later in the processing, at callees level. See EffectsWithPointsTo.sub/call05.c

See also EffectsWithPointsTo.sub/call08.c: &y[i][1] You need expression_to_points_to_sinks() on such a lhs expression...

This occurs with actual argument "&e": when the address-of operator is used, the relation between the formal parameter, let say "p", and "e" cannot be expressed unless we build a location entity with name "&e".

Beware of constant character strings

Likely to be wrong whe the formal parameter is a pointer and the actual parameter is a simple pointer, or a pointer to an array with fewer dimensions.

Parameters
fpclpcl
all
pt_int_in
translationranslation

Definition at line 1483 of file interprocedural.c.

1487 {
1488  FOREACH(CELL, fc, fpcl) {
1489  /* assumption about fpcl */
1492  expression a = EXPRESSION(gen_nth(n-1, al));
1493  /* This function does not return constant memory paths... This
1494  * could fixed below with calls to
1495  * points_to_indices_to_unbounded_indices(), but it could/should also be
1496  * fixed later in the processing, at callees level. See
1497  * EffectsWithPointsTo.sub/call05.c
1498  *
1499  * See also EffectsWithPointsTo.sub/call08.c: &y[i][1]
1500  * You need expression_to_points_to_sinks() on such a lhs expression...
1501  */
1502  list acl = expression_to_points_to_sources(a, pt_in);
1503  if(false && ENDP(acl)) {
1504  /* This occurs with actual argument "&e": when the address-of
1505  operator is used, the relation between the formal parameter,
1506  let say "p", and "e" cannot be expressed unless we build a
1507  location entity with name "&e". */
1508  acl = expression_to_points_to_sinks(a, pt_in);
1509  }
1510  int nacl = (int) gen_length(acl);
1511  // FI->FI: you should check nacl==0... OK, but to do what ?
1512  approximation ap = nacl==1? make_approximation_exact() :
1514  FOREACH(CELL, ac, acl) {
1515  cell source = copy_cell(fc);
1516  //bool to_be_freed;
1517  //type a_source_t = points_to_cell_to_type(ac, &to_be_freed);
1518  //type source_t = compute_basic_concrete_type(a_source_t);
1519  type source_t = points_to_cell_to_concrete_type(source);
1520  if(pointer_type_p(source_t)) {
1521  cell n_source = copy_cell(fc);
1522  cell n_sink = copy_cell(ac);
1523  type e_sink_t = points_to_cell_to_concrete_type(n_sink);
1524  type sink_t = e_sink_t;
1525  /* Beware of constant character strings */
1526  if(type_functional_p(e_sink_t)) {
1527  functional f = type_functional(sink_t);
1529  sink_t = functional_result(f);
1530  }
1531  //reference n_sink_r = cell_any_reference(n_sink);
1532  // points_to_indices_to_unbounded_indices(reference_indices(n_sink_r));
1533  if(type_equal_p(source_t, sink_t)) {
1534  if(array_pointer_string_type_equal_p(source_t, sink_t))
1535  ; // do nothing: a 1D array is equivalent to a pointer
1536  else if(array_type_p(sink_t)) {
1537  // FI: I do not remember in which case I needed this
1539  }
1540  else if(scalar_type_p(sink_t)) {
1541  // Pointers/dereferencing11.c:
1542  // "i", double *, and "fifi[3][0]", double [2][3]
1543  reference n_sink_r = cell_any_reference(n_sink);
1544  list n_sink_sl = reference_indices(n_sink_r);
1545  bool succeed_p = false;
1546  if(!ENDP(n_sink_sl)) {
1547  expression ls = EXPRESSION(CAR(gen_last(n_sink_sl)));
1548  if(zero_expression_p(ls)) {
1549  // points_to_cell_remove_last_zero_subscript(n_sink);
1550  gen_remove_once(&reference_indices(n_sink_r), ls);
1551  succeed_p = true;
1552  }
1553  }
1554  if(!succeed_p)
1555  pips_internal_error("Not implemented yet.\n");
1556  }
1557  else
1558  pips_internal_error("Not implemented yet.\n");
1559  }
1560  points_to pt = make_points_to(n_source, n_sink, copy_approximation(ap),
1563  }
1564  else if(array_type_p(source_t)) {
1565  if(array_of_pointers_type_p(source_t)) {
1566  /* Likely to be wrong whe the formal parameter is a pointer
1567  and the actual parameter is a simple pointer, or a
1568  pointer to an array with fewer dimensions. */
1569  cell n_source = copy_cell(fc);
1570  cell n_sink = copy_cell(ac);
1571  //reference n_sink_r = cell_any_reference(n_sink);
1572  // points_to_indices_to_unbounded_indices(reference_indices(n_sink_r));
1573  points_to pt = make_points_to(n_source, n_sink, copy_approximation(ap),
1575  add_arc_to_simple_pt_map(pt, translation);
1576  //pips_internal_error("Not implemented yet.\n");
1577  }
1578  else if(array_of_struct_type_p(source_t)) {
1579  list fl = struct_type_to_fields(source_t);
1580  FOREACH(ENTITY, f, fl) {
1582  if(pointer_type_p(ft))
1583  pips_internal_error("Not implemented yet.\n");
1584  if(struct_type_p(ft))
1585  pips_internal_error("Not implemented yet.\n");
1586  else {
1587  ; // ignore
1588  }
1589  }
1590  }
1591  else {
1592  ; // Do no worry about these arrays
1593  }
1594  }
1595  else if(struct_type_p(source_t)) {
1596  // Can we make an artificial lhs and rhs and call
1597  // assign_to_points_to() in that specific case?
1598  // Or do we have to program yet another recursive descent in structs?
1599  // How do we keep track of the approximation?
1601  ac,
1602  ap,
1603  source_t,
1604  translation);
1605  }
1606  else {
1607  ; // No need
1608  }
1609  //if(to_be_freed) free_type(a_source_t);
1610  }
1611  free_approximation(ap);
1612  }
1613  pips_assert("The points-to translation mapping is well typed",
1615 }
void gen_remove_once(list *pl, const void *o)
Remove the first occurence of o in list pl:
Definition: list.c:691
gen_chunk gen_nth(int n, const list l)
to be used as ENTITY(gen_nth(3, l))...
Definition: list.c:710
void points_to_translation_of_struct_formal_parameter(cell fc, cell ac, approximation a, type st, set translation)
list struct_type_to_fields(type)
Definition: type.c:5798

References add_arc_to_simple_pt_map, add_subscript_dependent_arc_to_simple_pt_map(), array_of_pointers_type_p(), array_of_struct_type_p(), array_pointer_string_type_equal_p(), array_type_p(), CAR, CELL, cell_any_reference(), copy_approximation(), copy_cell(), ENDP, ENTITY, entity_basic_concrete_type(), entity_storage, EXPRESSION, expression_to_points_to_sinks(), expression_to_points_to_sources(), f(), FOREACH, formal_offset, free_approximation(), functional_parameters, functional_result, gen_last(), gen_length(), gen_nth(), gen_remove_once(), int, make_approximation_exact(), make_approximation_may(), make_descriptor_none(), make_points_to(), pips_assert, pips_internal_error, pointer_type_p(), points_to_cell_add_zero_subscript(), points_to_cell_to_concrete_type(), points_to_translation_mapping_is_typed_p(), points_to_translation_of_struct_formal_parameter(), reference_indices, reference_variable, scalar_type_p(), storage_formal, struct_type_p(), struct_type_to_fields(), type_equal_p(), type_functional, type_functional_p, and zero_expression_p().

Referenced by user_call_to_points_to_interprocedural(), and user_call_to_points_to_interprocedural_binding_set().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ points_to_translation_of_struct_formal_parameter()

void points_to_translation_of_struct_formal_parameter ( cell  fc,
cell  ac,
approximation  a,
type  st,
set  translation 
)

We assume that cell fc and cell ac are of type st and that st is a struct type.

Parameters
fcc
acc
stt
translationranslation

Definition at line 1365 of file interprocedural.c.

1370 {
1371  /* We assume that cell fc and cell ac are of type st and that st is
1372  a struct type. */
1373  // pips_internal_error("Not implemented yet.\n");
1374  list fl = struct_type_to_fields(st);
1375 
1376  FOREACH(ENTITY, f, fl) {
1378  if(pointer_type_p(ft)) {
1379  cell nfc = copy_cell(fc);
1380  cell nac = copy_cell(ac);
1383  points_to pt = make_points_to(nfc, nac, copy_approximation(a),
1385  add_arc_to_simple_pt_map(pt, translation);
1386  }
1387  else if(struct_type_p(ft)) {
1388  cell nfc = copy_cell(fc);
1389  cell nac = copy_cell(ac);
1393  ac,
1394  a,
1395  ft,
1396  translation);
1397  free_cell(nfc), free_cell(nac);
1398  }
1399  else if(array_of_pointers_type_p(ft)) {
1400  cell nfc = copy_cell(fc);
1401  cell nac = copy_cell(ac);
1406  points_to pt = make_points_to(nfc, nac, copy_approximation(a),
1408  add_arc_to_simple_pt_map(pt, translation);
1409  }
1410  else if(array_of_struct_type_p(ft)) {
1411  cell nfc = copy_cell(fc);
1412  cell nac = copy_cell(ac);
1420  ac,
1421  a,
1422  cet,
1423  translation);
1424  free_cell(nfc), free_cell(nac);
1425  }
1426  else {
1427  ; // do nothing
1428  }
1429  }
1430 
1431 }

References add_arc_to_simple_pt_map, array_of_pointers_type_p(), array_of_struct_type_p(), array_type_to_element_type(), compute_basic_concrete_type(), copy_approximation(), copy_cell(), ENTITY, entity_basic_concrete_type(), f(), FOREACH, free_cell(), make_descriptor_none(), make_points_to(), pointer_type_p(), points_to_cell_add_field_dimension(), points_to_cell_add_unbounded_subscripts(), struct_type_p(), and struct_type_to_fields().

Referenced by points_to_translation_of_formal_parameters().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pop_statement_points_to_context()

pt_map pop_statement_points_to_context ( void  )

Definition at line 133 of file statement.c.

134 {
137 }
void * stack_pop(stack)
POPs one item from stack s.
Definition: stack.c:399

References current_statement_points_to_context, stack_pop(), and statement_points_to_context.

Referenced by statement_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ potential_to_effective_memory_leaks()

list potential_to_effective_memory_leaks ( list  pmll,
set  res 
)

A new list, "emll", is allocated.

It contains the cells in the potential memory leak list that are unreachable in set/relation "res". Relation "res" is unchanged. List "pmll" is unchanged.

FI: This is not a sufficient implementation. It fails with strongly connected components (SCC) in "res". The fixed point algorithms are likely to generate SCCs.

Parameters
pmllmll
reses

Definition at line 431 of file points_to_set.c.

432 {
433  list emll = NIL; // Effective memory leak list
434  FOREACH(CELL, h, pmll) {
435  bool found_p = false;
436  SET_FOREACH(points_to, pt, res) {
437  cell sink = points_to_sink(pt);
438  if(points_to_cell_equal_p(h, sink)) {
439  found_p = true;
440  break;
441  }
442  }
443  if(!found_p) {
444  // FI: because of the current heap model, all arcs to a memory
445  // bucket are may arcs. We probably cannot get more than
446  // "possible" memory leak. More thinking needed.
447  // FI: Especially for sources that are not atomic...
448  pips_user_warning("Memory cell %s leaked.\n",
450  emll = CONS(CELL, h, emll);
451  }
452  }
453  return emll;
454 }

References CELL, cell_any_reference(), CONS, FOREACH, NIL, pips_user_warning, points_to_cell_equal_p(), points_to_sink, reference_to_string(), and SET_FOREACH.

Referenced by points_to_function_projection(), and remove_points_to_cell().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_code_points_to()

bool print_code_points_to ( const char *  ,
string  ,
string   
)

◆ print_code_points_to_list()

bool print_code_points_to_list ( const char *  module_name)
Parameters
module_nameodule_name

Definition at line 202 of file points_to_prettyprint.c.

203 {
205  DBR_POINTS_TO,
206  PT_TO_SUFFIX);
207 }
bool print_code_points_to(const char *module_name, string resource_name __attribute__((__unused__)), string file_suffix)
bool print_code_points_to(const char* module_name,
#define PT_TO_SUFFIX

References module_name(), print_code_points_to(), and PT_TO_SUFFIX.

+ Here is the call graph for this function:

◆ print_or_dump_points_to()

void print_or_dump_points_to ( const  points_to,
bool  print_p 
)

print a points-to arc for debug

Parameters
points_tot
print_print_p

Definition at line 568 of file points_to_set.c.

569 {
570  if(points_to_undefined_p(pt))
571  (void) fprintf(stderr,"POINTS_TO UNDEFINED\n");
572  // For debugging with gdb, dynamic type checking
574  (void) fprintf(stderr,"Arg. \"pt\"is not a points_to.\n");
575  else {
576  cell source = points_to_source(pt);
577  cell sink = points_to_sink(pt);
579  reference r1 = cell_to_reference(source);
580  reference r2 = cell_to_reference(sink);
581  entity v1 = reference_variable(r1);
582  entity v2 = reference_variable(r2);
586 
587  fprintf(stderr,"%p ", pt);
588  if(m!=m1)
589  fprintf(stderr,"%s" MODULE_SEP_STRING, entity_local_name(m1));
590  print_reference(r1);
591  fprintf(stderr,"->");
592  if(m!=m2 && !null_cell_p(sink) && !nowhere_cell_p(sink)
594  fprintf(stderr,"%s" MODULE_SEP_STRING, entity_local_name(m2));
595  print_reference(r2);
596  fprintf(stderr," (%s)", approximation_to_string(app));
597  if(!print_p) {
598  fprintf(stderr," [%p, %p]", points_to_source(pt), points_to_sink(pt));
599  }
600  fprintf(stderr,"\n");
601  }
602 }
string approximation_to_string(approximation)
Definition: prettyprint.c:458
#define points_to_domain_number(x)
void print_reference(reference r)
Definition: expression.c:142
#define points_to_domain
Definition: print.c:367

References anywhere_cell_p(), approximation_to_string(), cell_to_reference(), cell_typed_anywhere_locations_p(), entity_local_name(), entity_module_name(), fprintf(), get_current_module_entity(), module_name_to_entity(), MODULE_SEP_STRING, nowhere_cell_p(), null_cell_p(), points_to_approximation, points_to_domain, points_to_domain_number, points_to_sink, points_to_source, points_to_undefined_p, print_reference(), and reference_variable.

Referenced by dump_points_to(), and print_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_or_dump_points_to_set()

void print_or_dump_points_to_set ( string  what,
set  s,
bool  print_p 
)

Print a set of points-to for debug.

Parameters
whathat
print_print_p

Definition at line 615 of file points_to_set.c.

616 {
617  fprintf(stderr,"points-to set %s:\n", what);
618  if(set_undefined_p(s))
619  fprintf(stderr, "undefined set\n");
620  else if(s==NULL)
621  fprintf(stderr, "uninitialized set\n");
622  else if(set_size(s)==0)
623  fprintf(stderr, "empty set\n");
624  else {
625  if(print_p) {
626  SET_MAP(elt, print_points_to((points_to) elt), s);
627  }
628  else {
629  SET_MAP(elt, dump_points_to((points_to) elt), s);
630  }
631  }
632  fprintf(stderr, "\n");
633 }
#define SET_MAP(element, code, the_set)
Definition: newgen_set.h:54

References dump_points_to(), fprintf(), print_points_to(), SET_MAP, set_size(), and set_undefined_p.

Referenced by dump_points_to_set(), and print_points_to_set().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_points_to()

void print_points_to ( const  points_to)
Parameters
points_tot

Definition at line 604 of file points_to_set.c.

605 {
606  print_or_dump_points_to(pt, true);
607 }

References print_or_dump_points_to().

Referenced by consistent_points_to_set(), points_to_equal_p(), and print_or_dump_points_to_set().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_points_to_graph()

void print_points_to_graph ( points_to_graph  ptg)
Parameters
ptgtg

Definition at line 190 of file points_to_prettyprint.c.

191 {
192  bool ok = !points_to_graph_bottom(ptg);
193  if(!ok)
194  fprintf(stderr, "Points-to graph does not exist, dead code\n");
195  else {
196  set s = points_to_graph_set(ptg);
197  print_points_to_set("", s);
198  }
199 }
static bool ok

References fprintf(), ok, points_to_graph_bottom, points_to_graph_set, and print_points_to_set().

+ Here is the call graph for this function:

◆ print_points_to_list()

void print_points_to_list ( points_to_list  ptl)
Parameters
ptltl

Definition at line 183 of file points_to_prettyprint.c.

184 {
185  text t = text_points_to_relations(ptl, "");
186  print_text(stderr, t);
187  free_text(t);
188 }
void free_text(text p)
Definition: text.c:74
text text_points_to_relations(points_to_list ptl, string header)
void print_text(FILE *fd, text t)
Definition: print.c:195

References free_text(), print_text(), and text_points_to_relations().

+ Here is the call graph for this function:

◆ print_points_to_path()

void print_points_to_path ( list  p)

For debugging.

Definition at line 837 of file points_to_set.c.

838 {
839  if(ENDP(p))
840  fprintf(stderr, "p is empty.\n");
841  else {
842  FOREACH(CELL, c, p) {
843  if(c!=CELL(CAR(p)))
844  fprintf(stderr, "->");
846  }
847  fprintf(stderr, "\n");
848  }
849 }

References CAR, CELL, ENDP, FOREACH, fprintf(), and print_points_to_cell.

Referenced by find_kth_points_to_node_in_points_to_path().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_points_to_relation()

void print_points_to_relation ( points_to  pt_to)

print a points-to arc, print_points_to() or print_points_to_arc()

Parameters
pt_tot_to

Definition at line 399 of file points_to_prettyprint.c.

400 {
401  text t = text_points_to_relation(pt_to);
402  print_text(stderr, t);
403  free_text(t);
404 }
text text_points_to_relation(points_to pt_to)
text text_region(effect reg) input : a region output : a text consisting of several lines of commenta...

References free_text(), print_text(), and text_points_to_relation().

Referenced by print_points_to_relations().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_points_to_relations()

void print_points_to_relations ( list  l_pt_to)

print a list of points-to arcs

Parameters
l_pt_to_pt_to

Definition at line 407 of file points_to_prettyprint.c.

408 {
409  fprintf(stderr,"\n");
410  if (ENDP(l_pt_to))
411  fprintf(stderr,"<none>");
412  else
413  {
414  FOREACH(POINTS_TO, pt, l_pt_to)
415  {
417  }
418  }
419  fprintf(stderr,"\n");
420 }
void print_points_to_relation(points_to pt_to)
print a points-to arc, print_points_to() or print_points_to_arc()

References ENDP, FOREACH, fprintf(), POINTS_TO, and print_points_to_relation().

+ Here is the call graph for this function:

◆ print_points_to_set()

◆ printed_points_to_list_undefined_p()

bool printed_points_to_list_undefined_p ( void  )

◆ program_points_to()

bool program_points_to ( char *  name)
Parameters
nameame

Definition at line 613 of file passes.c.

614 {
615  //transformer t = transformer_identity();
617  int i, nmodules;
618  gen_array_t modules;
619  // list e_inter = NIL;
620  list pptl = NIL; // Program points-to list
621 
622  pips_assert("main was found", the_main!=entity_undefined);
623 
624  debug_on("POINTS_TO_DEBUG_LEVEL");
625  pips_debug(1, "considering program \"%s\" with main \"%s\"\n", name,
626  module_local_name(the_main));
627 
628  set_current_module_entity(the_main);
630  db_get_memory_resource(DBR_CODE,
631  module_local_name(the_main),
632  true));
633  modules = db_get_module_list();
634  nmodules = gen_array_nitems(modules);
635  pips_assert("some modules in the program", nmodules>0);
636 
637  for(i=0; i<nmodules; i++) {
638  string mname = gen_array_item(modules, i);
639  pips_debug(1, "considering module %s\n", mname);
640 
641  // Module initial points-to list
642  points_to_list mptl =
644  db_get_memory_resource(DBR_INITIAL_POINTS_TO, mname, true));
645  if(!points_to_list_bottom(mptl)) {
646  // FI: a bit simplistic if C standard allows double definitions...
647  pptl = gen_nconc(pptl, points_to_list_list(mptl));
648  }
649  }
650 
651  points_to_list program_ptl = make_points_to_list(false, pptl);
652  DB_PUT_MEMORY_RESOURCE(DBR_PROGRAM_POINTS_TO, "", (void *) program_ptl);
653 
656 
657  gen_array_full_free(modules);
658 
659  debug_off();
660  return true;
661 }
size_t gen_array_nitems(const gen_array_t a)
Definition: array.c:131
void gen_array_full_free(gen_array_t a)
Definition: array.c:77
void * gen_array_item(const gen_array_t a, size_t i)
Definition: array.c:143
void reset_current_module_statement(void)
Reset the current module statement.
Definition: static.c:221
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
gen_array_t db_get_module_list(void)
Get an array of all the modules (functions, procedures and compilation units) of a workspace.
Definition: database.c:1266
string get_main_entity_name(void)
Return the local name of the main module if it is available, or the local name of any module by defau...
Definition: util.c:63
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582

References copy_points_to_list(), db_get_memory_resource(), db_get_module_list(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, entity_undefined, gen_array_full_free(), gen_array_item(), gen_array_nitems(), gen_nconc(), get_main_entity_name(), make_points_to_list(), module_local_name(), module_name_to_entity(), NIL, pips_assert, pips_debug, points_to_list_bottom, points_to_list_list, reset_current_module_entity(), reset_current_module_statement(), set_current_module_entity(), and set_current_module_statement().

+ Here is the call graph for this function:

◆ push_statement_points_to_context()

void push_statement_points_to_context ( statement  s,
pt_map  in 
)
Parameters
inn

Definition at line 98 of file statement.c.

99 {
102 }
void stack_push(void *, stack)
stack use
Definition: stack.c:373

References current_statement_points_to_context, stack_push(), and statement_points_to_context.

Referenced by statement_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ range_to_points_to()

pt_map range_to_points_to ( range  r,
pt_map  pt_in,
bool  side_effect_p 
)
Parameters
pt_int_in
side_effect_pide_effect_p

Definition at line 284 of file expression.c.

285 {
286  pt_map pt_out = pt_in;
287  expression l = range_lower(r);
288  expression u = range_upper(r);
290  pt_out = expression_to_points_to(l, pt_in, side_effect_p);
291  pt_out = expression_to_points_to(u, pt_out, side_effect_p);
292  pt_out = expression_to_points_to(i, pt_out, side_effect_p);
293  return pt_out;
294 }

References expression_to_points_to(), range_increment, range_lower, and range_upper.

Referenced by expression_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ range_to_points_to_sinks()

list range_to_points_to_sinks ( range  r,
pt_map  in 
)
Parameters
inn

Definition at line 1626 of file sinks.c.

1627 {
1628  list sinks = NIL;
1629  pips_user_warning("Not implemented yet for %p and %p\n", r, in);
1630  return sinks;
1631 }

References NIL, and pips_user_warning.

Referenced by expression_to_points_to_cells().

+ Here is the caller graph for this function:

◆ Ready_p()

bool Ready_p ( control  c,
set  Processed,
set  Reachable 
)

A node is ready to be processed if its predecessors are not reachable or processed.

Pred = set_assign_list(Pred,gen_full_copy_list( Pred_l));

Parameters
Processedrocessed
Reachableeachable

Definition at line 97 of file unstructured.c.

98 {
99  set Pred = set_make(set_pointer);
100  list Pred_l = control_predecessors(c);
101  FOREACH(control, ctr, Pred_l) {
102  Pred = set_add_element(Pred, Pred, (void*)ctr);
103  }
104  /* Pred = set_assign_list(Pred,gen_full_copy_list( Pred_l)); */
105  bool ready_p = false;
106  SET_FOREACH(control, p , Pred) {
107  ready_p = set_belong_p(Processed,(void*) p) || !set_belong_p(Reachable,(void*) p);
108  }
109  return ready_p;
110 }
@ set_pointer
Definition: newgen_set.h:44
set set_make(set_type)
Create an empty set of any type but hash_private.
Definition: set.c:102
#define control_predecessors(x)
Definition: ri.h:943

References control_predecessors, FOREACH, set_add_element(), set_belong_p(), SET_FOREACH, set_make(), and set_pointer.

Referenced by ready_to_be_processed_set().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ready_to_be_processed_set()

set ready_to_be_processed_set ( control  n,
set  Processed,
set  Reachable 
)

A set containing all the successors of n that are ready to be processed.

Succ = set_assign_list(Succ, gen_full_copy_list(Succ_l));

Parameters
Processedrocessed
Reachableeachable

Definition at line 114 of file unstructured.c.

115 {
116  set Succ = set_make(set_pointer);
117  set rtbp = set_make(set_pointer);
118  list Succ_l = control_successors(n);
119  FOREACH(control, ctr, Succ_l) {
120  Succ = set_add_element(Succ, Succ, (void*)ctr);
121  }
122  /* Succ = set_assign_list(Succ, gen_full_copy_list(Succ_l)); */
123  SET_FOREACH(control, p , Succ){
124  if(Ready_p(p, Processed, Reachable))
125  set_add_element(rtbp, rtbp, (void*)p);
126  }
127  return rtbp;
128 }
bool Ready_p(control c, set Processed, set Reachable)
A node is ready to be processed if its predecessors are not reachable or processed.
Definition: unstructured.c:97
#define control_successors(x)
Definition: ri.h:945

References control_successors, FOREACH, Ready_p(), set_add_element(), SET_FOREACH, set_make(), and set_pointer.

Referenced by new_points_to_unstructured().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ recursive_filter_formal_context_according_to_actual_context()

bool recursive_filter_formal_context_according_to_actual_context ( list  fcl,
set  pt_in,
set  pt_binded,
set  binding,
set  filtered 
)

This function looks for successors of elements of list "fcl" both in points-to relations "pt_in" and "pt_binded".

Update the formal context defined by "pt_binded" on demand as necessary according to "pt_in", update the translation mapping "binding" according to the new pairs found, and go down recursively with a new list of constant paths, "nfcl", the possible successors in the formal context of the callee of elements in "fcl" when possible. In fact, the elements in "nfcl" must be pointers and are not necessarily the successors of elements of "fcl", but pointers contained in them.

This function is very similar to filter_formal_context_according_to_actual_context(), but a little bit more tricky. Amira Mensi unified both in her own version, but the unification makes the maintenance more difficult.

Copy only possible arcs "pt" from "pt_in" into the "filtered" set

FI: this assert may be too strong FI: This assert is too strong for Pointers/formal_parameter01 and its message is misleading because "source" is not an element of "fcl". Elements of "fcl" must be translated, but related elements may not be translatable because the effective context is not as rich as the formal context. For instance, the formal context may expect an array for each formal scalar pointer, but the effective target may be a scalar. And an error must be raised if pointer arithmetic is used in the callee.

Make sure pt_binded is large enough: the pointer may be initialized before the call to the caller and used only in the callee. Because of the on-demand approach, pt_binded does not contain enough elements.

Do we have a similar arc in pt_binded?

Compute the binding relation for sinks of the formal context list "fcl"

If "fc" is not a pointer, look for pointers in "fc"

Now, we have to call about the same function recursively on the list of formal sinks

Parameters
fclcl
pt_int_in
pt_bindedt_binded
bindinginding
filterediltered

Definition at line 362 of file interprocedural.c.

367 {
368  bool ok_p = true;
369  points_to_graph binding_g = make_points_to_graph(false, binding);
370 
371  /* Copy only possible arcs "pt" from "pt_in" into the "filtered" set */
372  SET_FOREACH(points_to, pt, pt_in) {
373  cell source = points_to_source(pt);
374  if(related_points_to_cell_in_list_p(source, fcl)) {
375  cell sink = points_to_sink(pt);
376  list ptsl = points_to_source_to_sinks(source, binding_g, false);
377 
378  /* FI: this assert may be too strong FI: This assert is too
379  * strong for Pointers/formal_parameter01 and its message is
380  * misleading because "source" is not an element of
381  * "fcl". Elements of "fcl" must be translated, but related
382  * elements may not be translatable because the effective
383  * context is not as rich as the formal context. For instance,
384  * the formal context may expect an array for each formal scalar
385  * pointer, but the effective target may be a scalar. And an
386  * error must be raised if pointer arithmetic is used in the
387  * callee.
388  */
389  if(points_to_cell_in_list_p(source, fcl ))
390  pips_assert("Elements of \"fcl\" can be translated", !ENDP(ptsl));
391 
393  gen_free_list(ptsl);
394 
395  if(!ENDP(tsl)) {
396  /* Make sure pt_binded is large enough: the pointer may be
397  initialized before the call to the caller and used only in
398  the callee. Because of the on-demand approach, pt_binded
399  does not contain enough elements. */
400  pt_map pt_binded_g = make_points_to_graph(false, pt_binded);
401  FOREACH(CELL, c, tsl) {
402  list sinks = any_source_to_sinks(c, pt_binded_g, false);
403  gen_free_list(sinks);
404  }
405 
406  if(null_cell_p(sink)) {
407  /* Do we have a similar arc in pt_binded? */
408  FOREACH(CELL, tc, tsl) {
409  if(cell_points_to_null_sink_in_set_p(tc, pt_binded)) {
410  points_to npt = copy_points_to(pt);
411  add_arc_to_simple_pt_map(npt, filtered);
412  break;
413  }
414  else {
415  ; // do not copy this arc in filtered set
416  }
417  }
418  }
419  else {
420  FOREACH(CELL, tc, tsl) {
422  /* */
423  semantics_user_warning("An uninitialized pointer, \"%s\", may be reached.\n ", points_to_cell_to_string(tc));
424  //ok_p = false;
425  }
426  else if(cell_points_to_non_null_sink_in_set_p(tc, pt_binded)) {
427  if(cell_points_to_nowhere_sink_in_set_p(tc, pt_binded)) {
428  /* */
429  semantics_user_warning("An uninitialized pointer, \"%s\", might be reached.\n ", points_to_cell_to_string(tc));
430  }
431  points_to npt = copy_points_to(pt);
432  add_arc_to_simple_pt_map(npt, filtered);
433  break;
434  }
435  else {
436  ; // do not copy this arc in filtered set
437  }
438  }
439  }
440  gen_free_list(tsl);
441  }
442  else {
443  ; // do not copy this arc in filtered set
444  }
445  }
446  }
447 
448  /* Compute the binding relation for sinks of the formal context list "fcl" */
449  list nfcl = NIL;
450  FOREACH(CELL, c, fcl) {
451  points_to_graph filtered_g = make_points_to_graph(false, filtered);
452  list fl = points_to_source_to_some_sinks(c, filtered_g, false); // formal list
453  if(!ENDP(fl)) {
454  // FI: I am in trouble with _nl_1 and _nl_1[next]; the first one
455  // is not recognized in the second one.
456  //list tsl = points_to_source_to_sinks(c, binding_g, false);
457  list tsl = points_to_source_to_some_sinks(c, binding_g, false);
458  //list tsl = source_to_sinks(c, binding_g, false);
459  FOREACH(CELL, tc, tsl) {
460  points_to_graph pt_binded_g = make_points_to_graph(false, pt_binded);
461  list al = points_to_source_to_some_sinks(tc, pt_binded_g, false); // formal list
462  int nfl = (int) gen_length(fl);
463  int nal = (int) gen_length(al);
465  if(nfl==1 && nal==1)
467  else
469  FOREACH(CELL, fc, fl) {
470  if(!null_cell_p(fc)) {
471  FOREACH(CELL, ac, al) {
472  if(!null_cell_p(ac) && !nowhere_cell_p(ac)) {
475  // FI: why not use array_pointer_string_type_equal_p()?
476  if(!type_equal_p(fc_t, ac_t) && !overloaded_type_p(ac_t)) {
479  if(!type_equal_p(fc_t, ac_nt))
480  pips_internal_error("translation failure.\n");
481  }
485  add_arc_to_simple_pt_map(tr, binding);
486  }
487  }
488  /* If "fc" is not a pointer, look for pointers in "fc" */
490  nfcl = gen_nconc(nfcl, pcl);
491  //nfcl = CONS(CELL, fc, nfcl);
492  }
493  }
495  }
496  }
497  else {
498  ; // No need to go down... if we stop with a good reason, not
499  // because of a bug
500  // pips_internal_error("Translation error.\n");
501  }
502  }
503 
504  pips_assert("The points-to translation mapping is well typed",
506 
507  /* Now, we have to call about the same function recursively on the
508  list of formal sinks */
509  if(ok_p && !ENDP(nfcl)) {
511  (nfcl, pt_in, pt_binded, binding, filtered);
512  gen_free_list(nfcl);
513  }
514 
515  // FI binding_g should be freed, but not the set in it...
516 
517  return ok_p;
518 }
bool cell_points_to_null_sink_in_set_p(cell, set)
Definition: points_to.c:898
bool cell_points_to_nowhere_sink_in_set_p(cell, set)
Definition: points_to.c:845
bool cell_must_point_to_nowhere_sink_in_set_p(cell, set)
How are array handled in pts? do we have arcs "a->a"?
Definition: points_to.c:870
list points_to_cells_to_pointer_cells(list pl)
Convert cells in l into derived pointer cells when possible.
Definition: expression.c:1917
list any_source_to_sinks(cell, pt_map, bool)
Generalization of source_to_sinks().
static int tc
Internal variables
Definition: reindexing.c:107

References add_arc_to_simple_pt_map, any_source_to_sinks(), approximation_undefined, CELL, cell_must_point_to_nowhere_sink_in_set_p(), cell_points_to_non_null_sink_in_set_p(), cell_points_to_nowhere_sink_in_set_p(), cell_points_to_null_sink_in_set_p(), copy_approximation(), copy_cell(), copy_points_to(), ENDP, FOREACH, free_approximation(), gen_free_list(), gen_length(), gen_nconc(), int, make_approximation_exact(), make_approximation_may(), make_descriptor_none(), make_points_to(), make_points_to_graph(), NIL, nowhere_cell_p(), null_cell_p(), overloaded_type_p(), pips_assert, pips_internal_error, points_to_cell_add_zero_subscript(), points_to_cell_in_list_p(), points_to_cell_to_concrete_type(), points_to_cell_to_string(), points_to_cell_to_useful_pointer_cells(), points_to_cells_to_pointer_cells(), points_to_sink, points_to_source, points_to_source_to_sinks(), points_to_source_to_some_sinks(), points_to_translation_mapping_is_typed_p(), related_points_to_cell_in_list_p(), semantics_user_warning, SET_FOREACH, tc, and type_equal_p().

Referenced by filter_formal_context_according_to_actual_context().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reduce_cell_to_pointer_type()

cell reduce_cell_to_pointer_type ( cell  c)

Remove last subscripts of cell c till its type becomes a scalar pointer.

This of course may fail.

Remove the last subscript, hopefully 0

Definition at line 1809 of file expression.c.

1810 {
1811  bool to_be_freed;
1812  type t = points_to_cell_to_type(c, &to_be_freed);
1814  list sl = reference_indices(r);
1815  bool remove_p = !pointer_type_p(t);
1816  if(to_be_freed) free_type(t);
1817  while(remove_p) {
1818  if(!ENDP(sl)) {
1819  /* Remove the last subscript, hopefully 0 */
1820  list ls = gen_last(sl); // last subscript
1821  expression lse = EXPRESSION(CAR(ls));
1823  break; // This subscript cannot be removed
1824  gen_list_and_not(&sl, ls);
1825  reference_indices(r) = sl;
1826  // because sl is a sublist of ls, the chunk has already been freed
1827  // gen_full_free_list(ls);
1828  // gen_free_list(ls);
1829  t = points_to_cell_to_type(c, &to_be_freed);
1830  // remove_p = !pointer_type_p(t); we may end up with char[] instead of char*
1831  remove_p = !C_pointer_type_p(t);
1832  if(to_be_freed) free_type(t);
1833  }
1834  else
1835  break; // FI: in fact, an internal error
1836  }
1837  return c;
1838 }
bool field_reference_expression_p(expression)
Check if expression "e" is a reference to a struct field.
Definition: points_to.c:224

References C_pointer_type_p(), CAR, cell_any_reference(), ENDP, EXPRESSION, field_reference_expression_p(), free_type(), gen_last(), gen_list_and_not(), pointer_type_p(), points_to_cell_to_type(), and reference_indices.

Referenced by list_assignment_to_points_to(), and reduce_cells_to_pointer_type().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reduce_cells_to_pointer_type()

list reduce_cells_to_pointer_type ( list  cl)

Undo the extra eval performed when stubs are generated: 0 subscripts are added when arrays are involved.

Parameters
cll

Definition at line 1844 of file expression.c.

1845 {
1846  FOREACH(CELL, c, cl) {
1847  if(null_cell_p(c)) // There may be other exceptions...
1848  ;
1849  else
1850  (void) reduce_cell_to_pointer_type(c);
1851  }
1852  return cl;
1853 }

References CELL, FOREACH, null_cell_p(), and reduce_cell_to_pointer_type().

+ Here is the call graph for this function:

◆ reference_condition_to_points_to()

pt_map reference_condition_to_points_to ( reference  r,
pt_map  in,
bool  true_p 
)

Handle conditions such as "if(p)".

Do not take care of side effects in references...

are we dealing with a pointer?

if p points to NULL, the condition is not feasible. If not, remove any arc from p to NULL

Make a points-to NULL and remove the arc from the current out

remove any arc from v to anything and add an arc from p to NULL

Make a points-to NULL and remove the arc from the current out

This condition is always false

Parameters
inn
true_prue_p

Definition at line 2538 of file expression.c.

2539 {
2540  pt_map out = in;
2541  entity v = reference_variable(r);
2543  list sl = reference_indices(r);
2544 
2545  /* Do not take care of side effects in references... */
2546  out = expressions_to_points_to(sl, out, false);
2547 
2548  /* are we dealing with a pointer? */
2549  if(pointer_type_p(vt)) {
2550  if(true_p) {
2551  /* if p points to NULL, the condition is not feasible. If not,
2552  remove any arc from p to NULL */
2553  if(reference_must_points_to_null_p(r, in)) {
2554  // FI: memory leak with clear_pt?
2555  pips_user_warning("Dead code detected.\n");
2556  clear_pt_map(out);
2557  points_to_graph_bottom(out) = true;
2558  }
2559  else {
2560  /* Make a points-to NULL and remove the arc from the current out */
2563  points_to a = make_points_to(source, sink, make_approximation_may(),
2565  remove_arc_from_pt_map(a, in);
2566  free_points_to(a);
2567  }
2568  }
2569  else {
2570  if(reference_may_points_to_null_p(r, in)) {
2571  /* remove any arc from v to anything and add an arc from p to NULL */
2572  set in_s = points_to_graph_set(in);
2573  points_to_source_projection(in_s, v);
2574  /* Make a points-to NULL and remove the arc from the current out */
2579  add_arc_to_pt_map(a, in);
2580  }
2581  else {
2582  /* This condition is always false */
2583  pips_user_warning("Dead code detected.\n");
2584  clear_pt_map(out);
2585  points_to_graph_bottom(out) = true;
2586  }
2587  }
2588  }
2589 
2590  return out;
2591 }
void free_points_to(points_to p)
bool reference_must_points_to_null_p(reference, pt_map)
Definition: sinks.c:1859
bool reference_may_points_to_null_p(reference, pt_map)
Definition: sinks.c:1873
set points_to_source_projection(set, entity)
Remove all arcs starting from e because e has been assigned a new value.

References add_arc_to_pt_map, clear_pt_map, copy_reference(), entity_basic_concrete_type(), expressions_to_points_to(), free_points_to(), make_approximation_exact(), make_approximation_may(), make_cell_reference(), make_descriptor_none(), make_null_pointer_value_cell(), make_points_to(), out, pips_user_warning, pointer_type_p(), points_to_graph_bottom, points_to_graph_set, points_to_source_projection(), reference_indices, reference_may_points_to_null_p(), reference_must_points_to_null_p(), reference_variable, and remove_arc_from_pt_map.

Referenced by condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reference_dereferencing_to_points_to()

pt_map reference_dereferencing_to_points_to ( reference  r,
pt_map  in,
bool  nowhere_dereferencing_p,
bool  null_dereferencing_p 
)

Can we execute the reference r in points-to context "in" without segfaulting?

Do not go down in subscript expressions.

See also reference_to_points_to_sinks(). Unfortunate cut-and-paste.

Does the reference implies some dereferencing itself?

C syntactic sugar: *a is equivalent to a[0] when a is an array. No real dereferencing needed.

Remove store-dependent indices

Parameters
inn
nowhere_dereferencing_powhere_dereferencing_p
null_dereferencing_pull_dereferencing_p

Definition at line 333 of file dereferencing.c.

337 {
338  entity e = reference_variable(r);
340  list sl = reference_indices(r);
341 
342  /* Does the reference implies some dereferencing itself? */
343  // FI: I do not remember what this means; examples are nice
346  }
347  else if(pointer_type_p(t) && !ENDP(sl)) {
349  }
350  else if(array_of_pointers_type_p(t)
353  }
354  else if(array_type_p(t) && !array_of_pointers_type_p(t)) {
355  /* C syntactic sugar: *a is equivalent to a[0] when a is an
356  array. No real dereferencing needed. */
357  ;
358  }
359  else {
360  // FI: I am confused here
361  // FI: we might have to do more when a struct or an array is referenced
362  if(pointer_type_p(t) || array_of_pointers_type_p(t)) { // FI: implies ENDP(sl)
363  reference nr = copy_reference(r);
364  cell source = make_cell_reference(nr);
365  /* Remove store-dependent indices */
366  reference_indices(nr) =
368  list sinks = source_to_sinks(source, in, false);
369  int n = (int) gen_length(sinks);
370  FOREACH(CELL, sink, sinks) {
371  if(!nowhere_dereferencing_p && nowhere_cell_p(sink)) {
372  remove_points_to_arcs(source, sink, in);
373  n--;
374  }
375  if(!null_dereferencing_p && null_cell_p(sink)) {
376  remove_points_to_arcs(source, sink, in);
377  n--;
378  }
379  }
380  if(n==0) {
381  clear_pt_map(in);
382  points_to_graph_bottom(in) = true;
384  semantics_user_warning("Null or undefined pointer may be dereferenced because of \"%s\" at line %d.\n",
387  else
388  semantics_user_warning("Null or undefined pointer may be dereferenced because of \"%s\".\n",
390  }
391 
392  gen_free_list(sinks);
393  }
394  }
395  return in;
396 }
bool pointer_points_to_reference_p(reference r __attribute__((unused)))
see if a points_to_reference includes a pointer dereferencing: this is impossible if the points-to re...
void pointer_reference_dereferencing_to_points_to(reference r, pt_map in)
list subscript_expressions_to_constant_subscript_expressions(list sl)
make a full copy of the subscript expression list, preserve constant subscripts, replace non-constant...
Definition: expression.c:3981

References array_of_pointers_type_p(), array_type_p(), CELL, clear_pt_map, copy_reference(), effect_reference_to_string(), ENDP, entity_basic_concrete_type(), FOREACH, gen_free_list(), gen_length(), int, make_cell_reference(), nowhere_cell_p(), null_cell_p(), pointer_points_to_reference_p(), pointer_reference_dereferencing_to_points_to(), pointer_type_p(), points_to_context_statement_line_number(), points_to_graph_bottom, reference_indices, reference_variable, remove_points_to_arcs(), semantics_user_warning, source_to_sinks(), statement_points_to_context_defined_p(), subscript_expressions_to_constant_subscript_expressions(), type_variable, and variable_dimension_number().

Referenced by dereferencing_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reference_may_points_to_null_p()

bool reference_may_points_to_null_p ( reference  r,
pt_map  in 
)
Parameters
inn

Definition at line 1873 of file sinks.c.

1874 {
1875  list sinks = reference_to_sinks(r, in, false);
1876  bool may_p = false;
1877 
1878  FOREACH(CELL, c, sinks) {
1879  if(null_cell_p(c)) {
1880  may_p = true;
1881  break;
1882  }
1883  }
1884 
1885  gen_free_list(sinks);
1886  return may_p;
1887 }
list reference_to_sinks(reference, pt_map, bool)

References CELL, FOREACH, gen_free_list(), null_cell_p(), and reference_to_sinks().

Referenced by reference_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reference_must_points_to_null_p()

bool reference_must_points_to_null_p ( reference  r,
pt_map  in 
)
Parameters
inn

Definition at line 1859 of file sinks.c.

1860 {
1861  list sinks = reference_to_sinks(r, in, false);
1862  bool must_p = false;
1863 
1864  if(gen_length(sinks)==1) {
1865  // It is a must arc
1866  cell c = CELL(CAR(sinks));
1867  must_p = null_cell_p(c);
1868  }
1869  gen_free_list(sinks);
1870  return must_p;
1871 }

References CAR, CELL, gen_free_list(), gen_length(), null_cell_p(), and reference_to_sinks().

Referenced by reference_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reference_to_field_disambiguator()

string reference_to_field_disambiguator ( reference  r)

Build an ASCII string to disambiguate the different field paths that may exist in similar references.

If the variable referenced by "r" is not a struct, returns the empty string.

If it is a struct, derive a string that is unique to a particular combination of fields and subfields.

Definition at line 468 of file points_to_init_analysis.c.

469 {
470  string fs = string_undefined;
471  string ofs = string_undefined;
472  list sl = reference_indices(r);
473  FOREACH(EXPRESSION, s, sl) {
474  if(expression_reference_p(s)) {
476  if(entity_field_p(f)) {
477  int n = entity_field_rank(f);
478  if(string_undefined_p(fs))
479  asprintf(&fs, "_%d_", n);
480  else {
481  ofs = fs;
482  asprintf(&fs, "%s%d_", ofs, n);
483  free(ofs);
484  }
485  }
486  }
487  }
488  if(string_undefined_p(fs))
489  fs = strdup("");
490  return fs;
491 }
#define asprintf
Definition: misc-local.h:225
#define string_undefined_p(s)
Definition: newgen_types.h:41
int entity_field_rank(entity f)
f is a field of a structure or of an union: what is its rank?
Definition: entity.c:940

References asprintf, entity_field_p(), entity_field_rank(), EXPRESSION, expression_reference(), expression_reference_p(), f(), FOREACH, free(), reference_indices, reference_variable, strdup(), string_undefined, and string_undefined_p.

Referenced by create_stub_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reference_to_points_to()

pt_map reference_to_points_to ( reference  r,
pt_map  pt_in,
bool  side_effect_p 
)

The subscript expressions may impact the points-to information.

E.g. a[*(p++)]

FI: I'm surprised that pointers can be indexed instead of being subscripted... This is linked to the parser in expression_to_points_to().

Parameters
pt_int_in
side_effect_pide_effect_p

Definition at line 262 of file expression.c.

263 {
264  pt_map pt_out = pt_in;
265  if(!points_to_graph_bottom(pt_in)) {
266  list sel = reference_indices(r);
267  entity v = reference_variable(r);
269  // FI: some or all of these tests could be placed in
270  // dereferencing_to_points_to()
271  if(!entity_stub_sink_p(v)
272  && !formal_parameter_p(v)
273  && !ENDP(sel)
274  && pointer_type_p(t)) {
276  pt_out = dereferencing_to_points_to(e, pt_in);
277  free_expression(e);
278  }
279  pt_out = expressions_to_points_to(sel, pt_in, side_effect_p);
280  }
281  return pt_out;
282 }

References dereferencing_to_points_to(), ENDP, entity_basic_concrete_type(), entity_stub_sink_p(), entity_to_expression(), expressions_to_points_to(), formal_parameter_p(), free_expression(), pointer_type_p(), points_to_graph_bottom, reference_indices, and reference_variable.

Referenced by expression_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reference_to_points_to_sinks()

list reference_to_points_to_sinks ( reference  r,
type  et,
pt_map  in,
bool  eval_p,
bool  constant_p 
)

Returns a list of memory cells "sinks" possibly accessed by the evaluation of reference "r".

No sharing between the returned list "sinks" and the reference "r" or the points-to set "in".

Examples if eval_p==false: x->x, t[1]->t[1], t[1][2]->t[1][2], p->p...

Examples if eval_p==true: x->error, t[1]->t[1][0], t[1][2]->t[1][2][0], p->p[0]...

If constant_p, stored-dependent subscript expressions are replaced by "*" and store-independent expressions are replaced by their values, e.g. x[3+4]->x[7]. Else, subscript expressions are left unchanged. Motivation: constant_p==true for points-to computation, and false for the translation of effects. In the latter case, the transformation into a constant reference is postponed.

Issue: let's assume "t" to be an array "int t[10][10[10];". The C language is (too) flexible. If "p" is an "int ***p;", the impact of assignment "p=t;" leads to "p points-to t" or "p points-to t[0]" or "p points-to t[0][0][0]". Two different criteria can be used: the compatibiliy of the pointer type and the pointed cell type, or the equality of the pointer value and of the pointed cell address.

In the first case, t->t[0]->t[0][0]->t[0][0][0].

In the second case, t->t[0][0][0], t[0]->t[0][0][0], t[0][0]->t[0][0][0].

FI: I do not trust this function. It is already too long. And I am not confident the case disjunction is correct/well chosen.

Two proper possibilities: an array of pointers fully subscribed or any other kind of array partially subscribed. And an unsuitable one: an integer value...

No matter what, the target is obtained by adding a 0 subscript

FI: I do not know if the subscript removal impact the handling of loops by the points-to analysis; see Points-to/array07.c

What is the value of the subscript expression?

scalar case, rhs is already a lvalue

An array name can be used as pointer constant

We should add null indices according to its number of dimensions

This function may be called from the effect library via backward_translation_of_points_to_formal_context()

ips_assert("The expected type and the reference type are equal", array_pointer_type_equal_p(et, rt));

ips_assert("The expected type and the reference type are compatible", concrete_type_equal_p(et, rt));

Parameters
ett
inn
eval_pval_p
constant_ponstant_p

Definition at line 755 of file sinks.c.

758 {
759  list sinks = NIL;
760  entity e = reference_variable(r);
762  list sl = reference_indices(r);
763 
764  ifdebug(8) {
765  pips_debug(8, "Reference r = ");
766  print_reference(r);
767  fprintf(stderr, "\n");
768  }
769 
770  //bool to_be_freed;
772  //type rt = compute_basic_concrete_type(srt);
773  if(false && eval_p && !pointer_type_p(rt)) {
774  // There must be a type mismatch
775  pips_user_error("Type mmismatch for reference \"%s\" at line %d.",
778  }
779  else {
780 
781  // FI: conditional01.c shows that the C parser may not generate the
782  // right construct when a scalar or an pointer is indexed.
783  // FI: maybe more difficult to guess of array of pointers...
784  if(pointer_type_p(t) && !ENDP(sl)) {
785  sinks = pointer_reference_to_points_to_sinks(r, in, eval_p);
786  }
787  else if(array_of_pointers_type_p(t)
789  sinks = pointer_reference_to_points_to_sinks(r, in, eval_p);
790  }
791  else {
792  // FI: to be checked otherwise?
793  //expression rhs = expression_undefined;
794  if (!ENDP(sl)) { // FI: I'm not sure this is a useful disjunction
795  /* Two proper possibilities: an array of pointers fully subscribed
796  or any other kind of array partially subscribed. And an
797  unsuitable one: an integer value... */
798  int nd = NumberOfDimension(e);
799  int rd = (int) gen_length(sl);
800  if (nd > rd) {
801  /* No matter what, the target is obtained by adding a 0 subscript */
802  /* FI: I do not know if the subscript removal impact the
803  handling of loops by the points-to analysis; see
804  Points-to/array07.c */
805  reference nr =
807  cell nc = make_cell_reference(nr);
808  // was:
809  // for(int i=rd; eval_p && i<nd; i++) { // FI: not efficient
810  if (eval_p)
811  {
814  CONS(EXPRESSION, ze, NIL));
815  // FC: this makes the loop to exit on the first iteration?
816  // replaced by an equivalent if, but probably a bug.
817  // i = nd
818  }
819  sinks = CONS(CELL, nc, NIL);
820  }
821  else if (nd == rd) {
822  // FI: eval_p is not used here...
824  cell nc = make_cell_reference(nr);
825  if(eval_p) {
826  sinks = source_to_sinks(nc, in, true); // FI: allocate a new copy
827  }
828  else
829  sinks = CONS(CELL, nc, NIL);
830  }
831  else { // rd is too big
832  // Could be a structure with field accesses expressed as indices
833  // Can be a dereferenced pointer, "p[0]" instead of "*p"
834  type et = ultimate_type(entity_type(e));
835  if(struct_type_p(et)) {
836  reference nr = copy_reference(r);
837  cell nc = make_cell_reference(nr);
838  if(eval_p) {
839  sinks = source_to_sinks(nc, in, true);
840  /*
841  expression ze = int_to_expression(0);
842  reference_indices(nr) = gen_nconc(reference_indices(nr),
843  CONS(EXPRESSION, ze, NIL));
844  */
845  }
846  else
847  sinks = CONS(CELL, nc, NIL);
848  }
849  else if(pointer_type_p(et)) {
850  pips_assert("One subscript", rd==1 && nd==0);
851  /* What is the value of the subscript expression? */
852  //expression sub = EXPRESSION(CAR(reference_indices(r)));
853  // FI: should we try to evaluate the subscript statically?
854  // If the expression is not zero, the target is unchanged but
855  // * must be used as subscript in sinks
856 
857  entity v = reference_variable(r);
858  reference nr = make_reference(v, NIL);
859  cell nc = make_cell_reference(nr);
860  if(eval_p) {
861  // FI: two rounds of source_to_sinks() I guess
862  list sinks_1 = source_to_sinks(nc, in, true);
863  FOREACH(CELL, c, sinks_1) {
864  list sinks_2 = source_to_sinks(c, in, true);
865  sinks = gen_nconc(sinks, sinks_2);
866  }
867  }
868  else {
869  // FI: what's going to happen with subscript expressions?
870  // FI: strict typing?
871  sinks = source_to_sinks(nc, in, true);
872  }
873  // FI FI FI
874  ;
875  }
876  else {
877  // FI: you may have an array of struct to begin with, and of
878  // structs including other structs
879  // Handle it just like a struct
880  //pips_user_error("Too many subscript expressions for array \"%s\".\n",
881  // entity_user_name(e));
882  reference nr = copy_reference(r);
883  cell nc = make_cell_reference(nr);
884  if(eval_p) {
885  sinks = source_to_sinks(nc, in, true);
886  }
887  else
888  sinks = CONS(CELL, nc, NIL);
889  }
890  }
891  }
892  else {
893  /* scalar case, rhs is already a lvalue */
894  if(scalar_type_p(t)) {
896  if(eval_p) {
897  // FI: we have a pointer. It denotes another location.
898  sinks = source_to_sinks(nc, in, true);
899  // FI: in some cases, nc is reused in sinks
900  if(!gen_in_list_p(nc, sinks))
901  free_cell(nc);
902  }
903  else {
904  // FI: without dereferencing
905  sinks = CONS(CELL, nc, NIL);
906  }
907  }
908  else if(array_type_p(t)) { // FI: not OK with typedef
909  /* An array name can be used as pointer constant */
910  /* We should add null indices according to its number of dimensions */
911  reference nr = copy_reference(r);
912  cell nc = make_cell_reference(nr);
913  if (true) {
914  // int n = NumberOfDimension(e);
915  // int rd = (int) gen_length(reference_indices(r));
916  // FI: not efficient and quite convoluted!
917  // FC: brain damaged, this is not a loop, compiler complains
918  // for(int i=rd; eval_p && i<n; i++) {
919  if (eval_p)
920  {
921  reference_indices(nr) =
924  // FC: this assignment make the loop exit on the first iteration?
925  // i = n; // to be type compatible: add at most one subscript
926  }
927  }
928  else {
929  // DEAD CODE
930  // FI: this is not always a good thing. See arithmetic11.c.
931  // The type of the source is needed to determine the number
932  // of zero subscripts...
934  }
935  sinks = CONS(CELL, nc, NIL);
936  }
937  else {
938  pips_internal_error("Pointer assignment from something "
939  "that is not a pointer.\n Could be a "
940  "function assigned to a functional pointer.\n");
941  }
942  }
943  }
944 
945  if(ENDP(sinks)) {
946  /* This function may be called from the effect library via
947  backward_translation_of_points_to_formal_context() */
949  pips_user_warning("Some kind of execution error has been encountered at line %d.\n",
951  }
952  else {
953  pips_user_warning("Some kind of execution error has been encountered.\n");
954  }
955  clear_pt_map(in);
956  points_to_graph_bottom(in) = true;
957  }
958  }
959 
960  /*pips_assert("The expected type and the reference type are equal",
961  array_pointer_type_equal_p(et, rt)); */
962  /*pips_assert("The expected type and the reference type are compatible",
963  concrete_type_equal_p(et, rt)); */
964  pips_assert("The expected type and the reference type are compatible",
965  type_structurally_equal_p(et, rt));
966  check_type_of_points_to_cells(sinks, rt, eval_p);
967 
968  //if(to_be_freed) free_type(srt);
969 
970  ifdebug(8) {
971  pips_debug(8, "Resulting cells: ");
972  print_points_to_cells(sinks);
973  fprintf(stderr, "\n");
974  }
975 
976  return sinks;
977 }
void check_type_of_points_to_cells(list sinks, type ct, bool eval_p)
Check that all cells in list "sinks" are compatible with type "ct" if "eval_p" is false,...
Definition: expression.c:1214
reference reference_with_store_independent_indices(reference r)
Return by side effect a reference whose memory locations includes the memory locations of r in case t...
Definition: expression.c:3045
int NumberOfDimension(entity)
Definition: size.c:588
list pointer_reference_to_points_to_sinks(reference r, pt_map in, bool eval_p)
What to do when a pointer "p" is dereferenced within a reference "r".
Definition: sinks.c:709
reference simplified_reference(reference r)
Return NULL as sink.
Definition: sinks.c:670

References array_of_pointers_type_p(), array_type_p(), CELL, check_type_of_points_to_cells(), clear_pt_map, CONS, constant_p(), copy_reference(), effect_reference_to_string(), ENDP, entity_basic_concrete_type(), entity_type, EXPRESSION, FOREACH, fprintf(), free_cell(), gen_in_list_p(), gen_length(), gen_nconc(), ifdebug, int, int_to_expression(), make_cell_reference(), make_reference(), NIL, NumberOfDimension(), pips_assert, pips_debug, pips_internal_error, pips_user_error, pips_user_warning, pointer_reference_to_points_to_sinks(), pointer_type_p(), points_to_cell_add_zero_subscripts(), points_to_context_statement_line_number(), points_to_graph_bottom, points_to_reference_to_concrete_type(), print_points_to_cells, print_reference(), reference_indices, reference_variable, reference_with_store_independent_indices(), scalar_type_p(), simplified_reference(), source_to_sinks(), statement_points_to_context_defined_p(), struct_type_p(), type_structurally_equal_p(), type_variable, ultimate_type(), and variable_dimension_number().

Referenced by expression_to_points_to_cells(), and subscripted_reference_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reference_to_points_to_translations()

list reference_to_points_to_translations ( entity  v,
list  sl,
pt_map  ptm 
)

This function is designed to work properly for the translation of effects at call sites.

ptm is assumed to be a translation mapping.

Knowing that v(o_sl) is translated into w(d_sl), what is the translation of v(sl), w[tsl], assuming that o_sl, d_sl and sl are all subscript lists?

We assume that |o_sl|<|sl| because otherwise v[o_sl] would not be a constant memory location (?). We assume that |o_sl|<|d_sl| because we do not modelize sharing.

tsl is the result of the concatenation of three subscripts lists: a prefix made of the first subscripts of d_sl that are not covered by sl, the other subscripts of d_sl, updated according to the subscript values in sl, and a suffix, the subscripts in sl that have not equivalent in o_sl.

Update the last subscripts. E.g. _x_3[*] and _x_3[0] -> y[i][0] leads to y[i]*.

Update the last subscripts. E.g. _q_2[0][one] and _q_2[0] -> s leads to sone.

Update the last subscripts. E.g. x_3[4] and _x_3[0] -> y[*][1] leads to y[*][5]... A proof is needed to justify the subscript addition... if only to show that _x_3[0] is acceptable to claim something about _x[4]... (see EffectsWithPointsTo.sub/call08,c).

Same thing with _x_3[i] and _x_3[0] -> y[*][j]?

This functions is similar to what must be done to compute the sink or the source of an expression, but here both the subscript list sl and the sinks of the points-to arcs in ptm do not have to be constant paths.

null and undefined targets are not possible

Are the subscript lists compatible?

Offset to be applied...

We have an equality between the effect and the origin

The subscripts left in csl must be appended to the new sink

Build the prefix

Build the body: depending on the subscripts in sl and o_sl, update or not the susbcripts in cd_sl

Skip subscripts not reproduced in the destination

Build the suffix

Check the resulting length

Do no index constant character strings

Parameters
sll
ptmtm

Definition at line 1540 of file points_to_set.c.

1541 {
1542  // list of translated cells corresponding to the reference v[sl]
1543  list tl = NIL;
1544  set ptm_s = points_to_graph_set(ptm);
1545  SET_FOREACH(points_to, pt, ptm_s) {
1546  cell d = points_to_sink(pt);
1547  /* null and undefined targets are not possible */
1548  if(!null_cell_p(d) && !nowhere_cell_p(d)) {
1549  cell o = points_to_source(pt);
1550  reference o_r = cell_any_reference(o);
1551  entity o_v = reference_variable(o_r);
1552  if(o_v == v) {
1553  /* Are the subscript lists compatible? */
1554  list o_sl = reference_indices(o_r);
1555  list csl = sl, co_sl = o_sl;
1556  bool compatible_p = true;
1557  while(!ENDP(csl) && !ENDP(co_sl)) {
1558  expression sl_e = EXPRESSION(CAR(csl));
1559  expression o_sl_e = EXPRESSION(CAR(co_sl));
1560  if(unbounded_expression_p(sl_e)
1561  || unbounded_expression_p(o_sl_e)
1562  || expression_equal_p(sl_e, o_sl_e))
1563  ;
1566  /* Offset to be applied... */
1567  ;
1568  else {
1569  compatible_p = false;
1570  break;
1571  }
1572  POP(csl), POP(co_sl);
1573  }
1574  if(compatible_p && ENDP(csl) && ENDP(co_sl)
1575  && expression_lists_equal_p(sl, o_sl)) {
1576  /* We have an equality between the effect and the origin */
1578  if(!points_to_cell_in_list_p(tc, tl))
1579  tl = CONS(CELL, tc, tl);
1580  else
1581  free_cell(tc);
1582  }
1583  else if(compatible_p) {
1584  reference d_r = cell_any_reference(d);
1585  list d_sl = reference_indices(d_r);
1586  /* The subscripts left in csl must be appended to the new sink */
1587  int nsl = (int) gen_length(sl);
1588  int no_sl = (int) gen_length(o_sl);
1589  int nd_sl = (int) gen_length(d_sl);
1590  int np = nd_sl-no_sl; // #subscripts linked to the destination only
1591  // np may b negative because the source has a [0] subscript
1592  // that is non-significant
1593  int ns = nsl-no_sl; // #subscripts linked to the new source only
1594  int nb = no_sl; // #subscripts to update for body, unless np is <0
1595  pips_assert("the suffix and the body have positive length",
1596  ns>=0 && nb>=0);
1597  int i = 0;
1598  // The new subscript list is built backwards
1599  list tsl = NIL;
1600  list cd_sl = d_sl;
1601  /* Build the prefix */
1602  for(i=0; i<np; i++) {
1603  expression se = EXPRESSION(CAR(cd_sl));
1604  tsl = CONS(EXPRESSION,copy_expression(se), tsl);
1605  POP(cd_sl);
1606  }
1607  /* Build the body: depending on the subscripts in sl and o_sl,
1608  update or not the susbcripts in cd_sl */
1609  co_sl = o_sl;
1610  csl = sl;
1611  /* Skip subscripts not reproduced in the destination */
1612  while(np<0) {
1613  POP(csl), np++, nb--;
1614  }
1615  for(i=0;i<nb; i++) {
1616  expression sl_e = EXPRESSION(CAR(csl));
1617  expression d_sl_e = EXPRESSION(CAR(cd_sl));
1618  if(unbounded_expression_p(sl_e))
1619  tsl = CONS(EXPRESSION,copy_expression(sl_e), tsl);
1620  else if(unbounded_expression_p(d_sl_e))
1621  tsl = CONS(EXPRESSION,copy_expression(d_sl_e), tsl);
1622  else if(zero_expression_p(sl_e))
1623  tsl = CONS(EXPRESSION,copy_expression(d_sl_e), tsl);
1624  else if(zero_expression_p(d_sl_e))
1625  tsl = CONS(EXPRESSION,copy_expression(sl_e), tsl);
1626  else {
1627  value sl_v = EvalExpression(sl_e);
1628  value d_sl_v = EvalExpression(d_sl_e);
1630  if(value_constant_p(sl_v) && value_constant_p(d_sl_v)) {
1631  constant sl_c = value_constant(sl_v);
1632  constant d_sl_c = value_constant(d_sl_v);
1633  if(constant_int_p(sl_c) && constant_int_p(d_sl_c)) {
1634  // Possible overflow
1635  int nic = constant_int(sl_c)+constant_int(d_sl_c);
1636  ne = int_to_expression(nic);
1637  }
1638  }
1639  if(expression_undefined_p(ne))
1641  copy_expression(d_sl_e),
1642  copy_expression(sl_e));
1643  tsl = CONS(EXPRESSION, ne, tsl);
1644  }
1645  POP(csl);
1646  POP(co_sl);
1647  POP(cd_sl);
1648  }
1649  /* Build the suffix */
1650  while(!ENDP(csl)) {
1651  expression sl_e = EXPRESSION(CAR(csl));
1652  tsl = CONS(EXPRESSION,copy_expression(sl_e), tsl);
1653  POP(csl);
1654  }
1655  tsl = gen_nreverse(tsl);
1656  /* Check the resulting length */
1657  int ntsl = (int) gen_length(tsl);
1658  pips_assert("The resulting", ntsl==np+nb+ns);
1659  entity d_v = reference_variable(d_r);
1660  type d_v_t = entity_basic_concrete_type(d_v);
1662  if(type_functional_p(d_v_t)) {
1663  /* Do no index constant character strings */
1664  tr = make_reference(d_v, NIL);
1665  gen_free_list(tsl);
1666  }
1667  else
1668  tr = make_reference(d_v, tsl);
1669  cell tc = make_cell_reference(tr);
1670  if(!points_to_cell_in_list_p(tc, tl))
1671  tl = CONS(CELL, tc, tl);
1672  else
1673  free_cell(tc);
1674  }
1675  }
1676  }
1677  }
1678  return tl;
1679 }
#define PLUS_OPERATOR_NAME
bool expression_lists_equal_p(list l1, list l2)
Definition: expression.c:1405

References binary_intrinsic_expression, CAR, CELL, cell_any_reference(), CONS, constant_int, constant_int_p, copy_cell(), copy_expression(), ENDP, entity_basic_concrete_type(), EvalExpression(), EXPRESSION, expression_equal_p(), expression_lists_equal_p(), expression_undefined, expression_undefined_p, extended_integer_constant_expression_p(), free_cell(), gen_free_list(), gen_length(), gen_nreverse(), int, int_to_expression(), make_cell_reference(), make_reference(), NIL, nowhere_cell_p(), null_cell_p(), pips_assert, PLUS_OPERATOR_NAME, points_to_cell_in_list_p(), points_to_graph_set, points_to_sink, points_to_source, POP, reference_indices, reference_undefined, reference_variable, SET_FOREACH, tc, type_functional_p, unbounded_expression_p(), value_constant, value_constant_p, and zero_expression_p().

Referenced by points_to_reference_to_translation(), and substitute_stubs_in_transformer_with_translation_binding().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reference_to_sinks()

list reference_to_sinks ( reference  r,
pt_map  in,
bool  fresh_p 
)
Parameters
inn
fresh_presh_p

Definition at line 2529 of file points_to_set.c.

2530 {
2532  list sinks = source_to_sinks(source, in, fresh_p);
2533  free_cell(source);
2534  return sinks;
2535 }

References copy_reference(), free_cell(), make_cell_reference(), and source_to_sinks().

Referenced by reference_may_points_to_null_p(), and reference_must_points_to_null_p().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ relational_intrinsic_call_condition_to_points_to()

pt_map relational_intrinsic_call_condition_to_points_to ( call  c,
pt_map  in,
bool  true_p 
)

Update the points-to information "in" according to the validity of the condition.

We can remove the arcs that violate the condition or decide that the condition cannot be true.

Parameters
inn
true_prue_p

Definition at line 3274 of file expression.c.

3275 {
3276  pt_map out = in;
3277  entity f = call_function(c);
3278  list al = call_arguments(c);
3279 
3280  if((ENTITY_EQUAL_P(f) && true_p)
3281  || (ENTITY_NON_EQUAL_P(f) && !true_p)) {
3283  }
3284  else if((ENTITY_EQUAL_P(f) && !true_p)
3285  || (ENTITY_NON_EQUAL_P(f) && true_p)) {
3287  }
3288  else if(ENTITY_LESS_OR_EQUAL_P(f)
3291  || ENTITY_LESS_THAN_P(f)) {
3292  out = order_condition_to_points_to(f, al, true_p, in);
3293  }
3294  else {
3295  pips_internal_error("Not implemented yet.\n");
3296  }
3297  pips_assert("out is consistent", points_to_graph_consistent_p(out));
3298  return out;
3299 }
pt_map equal_condition_to_points_to(list al, pt_map in)
The expression list "al" contains exactly two arguments, "lhs" and "rhs".
Definition: expression.c:2986
pt_map order_condition_to_points_to(entity f, list al, bool true_p, pt_map in)
The expression list "al" contains exactly two arguments.
Definition: expression.c:3176
pt_map non_equal_condition_to_points_to(list al, pt_map in)
The expression list "al" contains exactly two arguments.
Definition: expression.c:3086
#define ENTITY_NON_EQUAL_P(e)
#define ENTITY_EQUAL_P(e)

References call_arguments, call_function, ENTITY_EQUAL_P, ENTITY_GREATER_OR_EQUAL_P, ENTITY_GREATER_THAN_P, ENTITY_LESS_OR_EQUAL_P, ENTITY_LESS_THAN_P, ENTITY_NON_EQUAL_P, equal_condition_to_points_to(), f(), non_equal_condition_to_points_to(), order_condition_to_points_to(), out, pips_assert, pips_internal_error, and points_to_graph_consistent_p().

Referenced by intrinsic_call_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remove_arc_from_simple_pt_map()

set remove_arc_from_simple_pt_map ( points_to  a,
set  s 
)

Definition at line 3585 of file points_to_set.c.

3586 {
3587  s = set_del_element(s, s, (void *) a);
3588  return s;
3589 }

References set_del_element().

Referenced by points_to_set_block_projection(), and remove_points_to_cell().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remove_arcs_from_pt_map()

void remove_arcs_from_pt_map ( points_to  pts,
set  pt_out 
)
Parameters
ptsts
pt_outt_out

Definition at line 231 of file interprocedural.c.

232 {
233  cell sink = points_to_sink(pts);
234  cell source = points_to_source(pts);
235 
236 
237  SET_FOREACH(points_to, pt, pt_out) {
238  if(cell_equal_p(points_to_source(pt), sink) ||cell_equal_p(points_to_source(pt), source) ) {
239  remove_arc_from_simple_pt_map(pts, pt_out);
241  reference r = make_reference(e, NIL);
242  cell source = make_cell_reference(r);
243  cell sink = copy_cell(source);
245  points_to npt = make_points_to(source, sink, a, make_descriptor_none());
246  add_arc_to_simple_pt_map(npt, pt_out);
247  remove_arcs_from_pt_map(pt, pt_out);
248  }
249  }
250 }
void remove_arcs_from_pt_map(points_to pts, set pt_out)

References add_arc_to_simple_pt_map, cell_equal_p(), copy_cell(), entity_anywhere_locations(), make_approximation_exact(), make_cell_reference(), make_descriptor_none(), make_points_to(), make_reference(), NIL, points_to_sink, points_to_source, remove_arc_from_simple_pt_map, and SET_FOREACH.

Referenced by user_call_to_points_to_intraprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remove_impossible_arcs_to_null()

void remove_impossible_arcs_to_null ( list pL,
pt_map  in 
)

You know that null and undefined cells in "*pL" are impossible because of the operation that is going to be performed on it.

Remove the corresponding arcs in points-to graph "in". Remove the corresponding cells from "*pL".

The search uses pointers. So "*pL" must contain sink cells of arcs of "in".

Parameters
pLL
inn

Definition at line 3498 of file points_to_set.c.

3499 {
3500  list fl = NIL;
3501  bool nowhere_ok_p =
3502  get_bool_property("POINTS_TO_UNINITIALIZED_POINTER_DEREFERENCING");
3503  FOREACH(CELL, pc, *pL) {
3504  if(null_cell_p(pc) || (nowhere_cell_p(pc) && !nowhere_ok_p)) {
3506  if(points_to_undefined_p(pt))
3507  pips_internal_error("NULL, returned as a source for an expression, "
3508  "does not appear in the points-to graph.\n");
3509  remove_arc_from_pt_map(pt, in);
3510  fl = CONS(CELL, pc, fl);
3511  }
3512  }
3513  gen_list_and_not(pL, fl);
3514  gen_free_list(fl);
3515 }
points_to points_to_sink_to_points_to(cell sink, pt_map ptm)
Return the points-to "fpt" ending in cell "sink" if it exists.

References CELL, CONS, FOREACH, gen_free_list(), gen_list_and_not(), get_bool_property(), NIL, nowhere_cell_p(), null_cell_p(), pips_internal_error, points_to_sink_to_points_to(), points_to_undefined_p, and remove_arc_from_pt_map.

Referenced by binary_intrinsic_call_to_points_to_sinks(), dereferencing_to_sinks(), and subscripted_reference_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remove_points_to_arcs()

void remove_points_to_arcs ( cell  source,
cell  sink,
pt_map  pt 
)
Parameters
sourceource
sinkink
ptt

Definition at line 3114 of file points_to_set.c.

3115 {
3116  points_to a = make_points_to(copy_cell(source), copy_cell(sink),
3119  remove_arc_from_pt_map(a, pt);
3120  free_points_to(a);
3121 
3122  a = make_points_to(copy_cell(source), copy_cell(sink),
3125  remove_arc_from_pt_map(a, pt);
3126  free_points_to(a);
3127 }

References copy_cell(), free_points_to(), make_approximation_exact(), make_approximation_may(), make_descriptor_none(), make_points_to(), and remove_arc_from_pt_map.

Referenced by pointer_arithmetic_to_points_to(), and reference_dereferencing_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remove_points_to_cell()

set remove_points_to_cell ( cell  c,
set  g 
)

All arcs in relation "g" must be removed or updated if they use the node "c".

If "c" is the source of an arc, the arc must be removed and the sink is a new potential leak.

If "c" is the sink of an arc, NOWHERE, i.e. UNDEFINED is the new sink. The approximation is unchanged.

Since the heap model does not support a precise analysis, this is not sure. For the time being, all buckets allocated by the same statement have a unique name. So arcs pointing to one cannot be removed when another one is freed. However, since we check that no arc points to an abstract bucket before we declare a sure memory leak, this should be OK in the context of memory leaks...

&& atomic_points_to_cell_p(c)

Apply the arc removals

Apply the arc additions

Look for effective memory leaks induced by the removal

Go down recursively...

Definition at line 361 of file points_to_set.c.

362 {
363  // FI: do we have to check the atomicity of the source? If it is
364  // removed, it is removed, isn'it? So it's up to the caller?
365 
366  list pmll = NIL; // potential memory leak list
367  list ral = NIL; // removed arc list
368  list nal = NIL; // new arc list
369  SET_FOREACH(points_to, a, g) {
370  cell source = points_to_source(a);
371  cell sink = points_to_sink(a);
372  if(points_to_cell_equal_p(c, source)) {
373  ral = CONS(POINTS_TO, a, ral);
374  if(heap_cell_p(sink) /* && atomic_points_to_cell_p(c)*/ ) {
375  pmll = CONS(CELL, sink, pmll);
376  }
377  }
378  else if(points_to_cell_equal_p(c, sink)) {
379  type sink_t = points_to_cell_to_concrete_type(sink);
380  cell nsink =
381  get_bool_property("ALIASING_ACROSS_TYPES")?
383  : make_typed_nowhere_cell(sink_t);
385  points_to na = make_points_to(copy_cell(source),
386  nsink,
387  nap,
389  ral = CONS(POINTS_TO, a, ral);
390  nal = CONS(POINTS_TO, na, nal);
391  }
392  }
393 
394  /* Apply the arc removals */
395  FOREACH(POINTS_TO, ra, ral)
397 
398  /* Apply the arc additions */
399  FOREACH(POINTS_TO, na, nal)
401 
402  /* Look for effective memory leaks induced by the removal */
404  if(!ENDP(emll)) {
405  /* Go down recursively... */
406  remove_points_to_cells(emll, g);
407  }
408 
409  return g;
410 }

References add_arc_to_simple_pt_map(), CELL, CONS, copy_approximation(), copy_cell(), ENDP, FOREACH, get_bool_property(), heap_cell_p(), make_descriptor_none(), make_nowhere_cell(), make_points_to(), make_typed_nowhere_cell(), NIL, POINTS_TO, points_to_approximation, points_to_cell_equal_p(), points_to_cell_to_concrete_type(), points_to_sink, points_to_source, potential_to_effective_memory_leaks(), remove_arc_from_simple_pt_map(), remove_points_to_cells(), and SET_FOREACH.

Referenced by remove_points_to_cells().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remove_points_to_cells()

set remove_points_to_cells ( list  cl,
set  g 
)

All nodes, i.e.

cells, in "cl" must be removed from graph "g".

graph "g" is updated by side-effects and returned.

Parameters
cll

Definition at line 416 of file points_to_set.c.

417 {
418  FOREACH(CELL, c, cl)
419  (void) remove_points_to_cell(c, g);
420  return g;
421 }
set remove_points_to_cell(cell c, set g)
All arcs in relation "g" must be removed or updated if they use the node "c".

References CELL, FOREACH, and remove_points_to_cell().

Referenced by points_to_function_projection(), and remove_points_to_cell().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remove_unreachable_heap_vertices_in_points_to_graph()

pt_map remove_unreachable_heap_vertices_in_points_to_graph ( pt_map  in,
bool  verbose_p 
)
Parameters
inn
verbose_perbose_p

Definition at line 3461 of file points_to_set.c.

3462 {
3464  return out;
3465 }
pt_map generic_remove_unreachable_vertices_in_points_to_graph(pt_map ptg, int code, bool verbose_p)
Remove arcs in points-to graph "ptg" when they start from a stub cell that is not reachable.

References generic_remove_unreachable_vertices_in_points_to_graph(), and out.

+ Here is the call graph for this function:

◆ remove_unreachable_stub_vertices_in_points_to_graph()

pt_map remove_unreachable_stub_vertices_in_points_to_graph ( pt_map  in)
Parameters
inn

Definition at line 3455 of file points_to_set.c.

3456 {
3458  return out;
3459 }

References generic_remove_unreachable_vertices_in_points_to_graph(), and out.

Referenced by any_loop_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remove_unreachable_vertices_in_points_to_graph()

pt_map remove_unreachable_vertices_in_points_to_graph ( pt_map  in)

This function looks pretty dangerous as variables can be reached by their names.

Parameters
inn

Definition at line 3469 of file points_to_set.c.

3470 {
3472  return out;
3473 }

References generic_remove_unreachable_vertices_in_points_to_graph(), and out.

+ Here is the call graph for this function:

◆ reset_heap_model()

void reset_heap_model ( void  )

Definition at line 1185 of file sinks.c.

1186 {
1188  malloc_counter = 0;
1189 }
#define statement_undefined
Definition: ri.h:2419

References malloc_counter, malloc_statement, and statement_undefined.

Referenced by statement_to_points_to().

+ Here is the caller graph for this function:

◆ reset_points_to_context()

void reset_points_to_context ( void  )

Definition at line 158 of file passes.c.

159 {
160  pips_assert("points_to_context is defined",
162  // Deep when pt_map is a Newgen object
163  // free_pt_map(points_to_context); // Shallow if pt_map==set
165 }

References pips_assert, points_to_context, pt_map_undefined, and pt_map_undefined_p.

Referenced by generic_points_to_analysis().

+ Here is the caller graph for this function:

◆ reset_printed_points_to_list()

void reset_printed_points_to_list ( void  )

Referenced by print_code_points_to().

+ Here is the caller graph for this function:

◆ reset_statement_points_to_context()

void reset_statement_points_to_context ( void  )

Definition at line 139 of file statement.c.

140 {
143 }
#define stack_undefined
Definition: newgen_stack.h:55
void stack_free(stack *)
type, bucket_size, policy
Definition: stack.c:292

References stack_free(), stack_undefined, and statement_points_to_context.

Referenced by generic_points_to_analysis().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ scalar_stub_source_to_sinks()

list scalar_stub_source_to_sinks ( cell  source,
pt_map  pts,
bool  fresh_p 
)
Parameters
sourceource
ptsts
fresh_presh_p

Definition at line 1165 of file points_to_set.c.

1166 {
1167  list sinks = generic_stub_source_to_sinks(source, pts, false, fresh_p);
1168  return sinks;
1169 }

References generic_stub_source_to_sinks().

Referenced by stub_source_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sequence_to_points_to()

pt_map sequence_to_points_to ( sequence  seq,
pt_map  pt_in 
)
Parameters
seqeq
pt_int_in

Definition at line 436 of file statement.c.

437 {
438  pt_map pt_out = pt_in;
439  //bool store = true; // FI: management and use of store_p? Could be useful? How is it used?
440  // pt_out = points_to_sequence(seq, pt_in, store);
442  pt_out = statement_to_points_to(st, pt_out);
443  }
444 
445  return pt_out;
446 }

References FOREACH, sequence_statements, and statement_to_points_to().

Referenced by instruction_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_printed_points_to_list()

void set_printed_points_to_list ( statement_points_to  )

Referenced by print_code_points_to().

+ Here is the caller graph for this function:

◆ simplified_reference()

reference simplified_reference ( reference  r)

Return NULL as sink.

Double definition... list points_to_null_sinks() { entity ne = entity_null_locations(); reference nr = make_reference(ne, NIL); cell nc = make_cell_reference(nr); list sinks = CONS(CELL, nc, NIL); return sinks; } Points-to cannot used any kind of reference, just constant references.

For instance, "x[i]" is transformed into "x[*]" because the value of "i" is unknown. x[3+4] may be transformed into x[7].

A new referencec is allocated. Reference "r" is unchanged.

Definition at line 670 of file sinks.c.

671 {
672  list sl = reference_indices(r);
673  list nsl = NIL;
674 
675  FOREACH(EXPRESSION, s, sl) {
676  value v = EvalExpression(s);
679  int cs = constant_int(value_constant(v));
680  ns = int_to_expression(cs);
681  }
682  else {
684  }
685  nsl = gen_nconc(nsl, CONS(EXPRESSION, ns, NIL));
686  }
687 
688  entity var = reference_variable(r);
689  reference nr = make_reference(var, nsl);
690  return nr;
691 }

References CONS, constant_int, constant_int_p, EvalExpression(), EXPRESSION, expression_undefined, FOREACH, gen_nconc(), int_to_expression(), make_reference(), make_unbounded_expression(), NIL, reference_indices, reference_variable, value_constant, and value_constant_p.

Referenced by reference_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sink_in_set_p()

bool sink_in_set_p ( cell  sink,
set  s 
)

test if a cell appear as a sink in a set of points-to

Parameters
sinkink

Definition at line 680 of file points_to_set.c.

681 {
682  bool in_p = false;
683  SET_FOREACH ( points_to, pt, s ) {
684  if( cell_equal_p(points_to_sink(pt),sink) )
685  in_p = true;
686  }
687  return in_p;
688 }

References cell_equal_p(), points_to_sink, and SET_FOREACH.

Referenced by points_to_set_block_projection(), and points_to_source_projection().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sink_to_sources()

list sink_to_sources ( cell  sink,
set  pts,
bool  fresh_p 
)

Build a list of possible cell sources for cell "sink" in points-to graph "pts".

If fresh_p is set, allocate new cells, if not just build the spine of the list.

Get rid of the constant subscripts since they are not direclty part of the points-to scheme on the sink side

  1. Try to find the source in the points-to information
Parameters
sinkink
ptsts
fresh_presh_p

Definition at line 1123 of file points_to_set.c.

1124 {
1125  list sources = NIL;
1126 
1127  // FI: This is a short-term short cut
1128  // The & operator can be applied to anything
1129  // We should start with all subscripts and then get rid of subscript
1130  // one by one and each time add a new source
1131 
1132  /* Get rid of the constant subscripts since they are not direclty
1133  part of the points-to scheme on the sink side */
1134  //entity v = reference_variable(cell_any_reference(sink));
1135  //reference nr = make_reference(v, NIL);
1136  //cell nsink = make_cell_reference(nr);
1137 
1138  /* 1. Try to find the source in the points-to information */
1139  SET_FOREACH(points_to, pt, pts) {
1140  // FI: a more flexible test is needed as the sink cell may be
1141  // either a, or a[0] or a[*] or a[*][*] or...
1142  //if(cell_equal_p(nsink, points_to_sink(pt))) {
1143  if(related_points_to_cells_p(sink, points_to_sink(pt))) {
1144  cell sc = fresh_p? copy_cell(points_to_source(pt))
1145  : points_to_source(pt);
1146  sources = CONS(CELL, sc, sources);
1147  }
1148  }
1149  //free_cell(nsink);
1150  return sources;
1151 }
bool related_points_to_cells_p(cell, cell)
Definition: points_to.c:165

References CELL, CONS, copy_cell(), NIL, points_to_sink, points_to_source, related_points_to_cells_p(), and SET_FOREACH.

Referenced by points_to_path_to_k_limited_points_to_path().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sinks_fully_matches_source_p()

bool sinks_fully_matches_source_p ( cell  source,
list  sinks 
)

Is there at least one cell "sink" in list "sinks" whose subscripts fully match the subscripts in cell "source"?

It is easy in a one-D setting. If "p" is an array or a presumed array and if the source is "p[*]" then sinks "{a[1], a[2]}" are not sufficient. Something else is needed such as "a[*]" or "b[*]" or "undefined".

FI: As a first cut, the numbers of unbounded subscripts in references are counted and compared.

Parameters
sourceource
sinksinks

Definition at line 2132 of file points_to_set.c.

2133 {
2134  bool match_p = false;
2135  reference source_r = cell_any_reference(source);
2136  list source_sl = reference_indices(source_r);
2137 
2138  if(ENDP(sinks)) {
2139  match_p = false;
2140  }
2141  else if(ENDP(source_sl)) {
2142  match_p = true; // no issue
2143  }
2144  else {
2145  int n_us_in_source =
2147  FOREACH(CELL, sink, sinks) {
2148  reference sink_r = cell_any_reference(sink);
2149  list sink_sl = reference_indices(sink_r);
2150  int n_us_in_sink =
2152  if(n_us_in_sink >= n_us_in_source) {
2153  match_p = true;
2154  break;
2155  }
2156  }
2157  }
2158 
2159  return match_p;
2160 }

References CELL, cell_any_reference(), ENDP, FOREACH, points_to_subscripts_to_number_of_unbounded_dimensions(), and reference_indices.

Referenced by source_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sizeofexpression_to_points_to_sinks()

list sizeofexpression_to_points_to_sinks ( sizeofexpression  ,
type  ,
pt_map   
)

◆ source_in_graph_p()

bool source_in_graph_p ( cell  source,
points_to_graph  s 
)
Parameters
sourceource

Definition at line 674 of file points_to_set.c.

675 {
676  return source_in_set_p(source, points_to_graph_set(s));
677 }
bool source_in_set_p(cell source, set s)
test if a cell appear as a source in a set of points-to

References points_to_graph_set, and source_in_set_p().

Referenced by user_call_to_points_to_intraprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ source_in_set_p()

bool source_in_set_p ( cell  source,
set  s 
)

test if a cell appear as a source in a set of points-to

if( opkill_may_vreference(source, points_to_source(pt) ))

Parameters
sourceource

Definition at line 646 of file points_to_set.c.

647 {
648  bool in_p = false;
649  SET_FOREACH ( points_to, pt, s ) {
650  /* if( opkill_may_vreference(source, points_to_source(pt) )) */
651  if(cell_equal_p(source, points_to_source(pt)))
652  return true;
653  }
654  return in_p;
655 }

References cell_equal_p(), points_to_source, and SET_FOREACH.

Referenced by compute_points_to_kill_set(), points_to_binding_arguments(), points_to_cell_translation(), and source_in_graph_p().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ source_subset_in_set_p()

bool source_subset_in_set_p ( cell  source,
set  s 
)

test if a cell "source" appears as a source in a set of points-to

if( opkill_may_vreference(source, points_to_source(pt) ))

Parameters
sourceource

Definition at line 657 of file points_to_set.c.

658 {
659  bool in_p = false;
660  SET_FOREACH ( points_to, pt, s ) {
661  /* if( opkill_may_vreference(source, points_to_source(pt) )) */
662  if(cell_equal_p(source, points_to_source(pt))) {
663  in_p = true;
664  break;
665  }
666  else if(cell_included_p(points_to_source(pt), source)) {
667  in_p = true;
668  break;
669  }
670  }
671  return in_p;
672 }

References cell_equal_p(), cell_included_p(), points_to_source, and SET_FOREACH.

Referenced by points_to_binding_arguments().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ source_to_sinks()

list source_to_sinks ( cell  source,
pt_map  pts,
bool  fresh_p 
)

Return a list of cells, "sinks", that are sink for some arc whose source is "source" or related to "source" in set "pts".

If no such arc is found, add new points-to stubs and new arcs in "pts" when global, formal or virtual variables are used in "source". Manage fix point detection to avoid creating an infinite number of such points-to stubs when recursive data structures are accessed in loops.

If "fresh_p" is set to true, no sharing is created between list "sinks" and reference "source" or points-to set "pts". Else, the cells in list "sinks" are the cells in arcs of the points-to set.

FI: I am not sure the above paragraph is properly implemented.

This function is based on several other simpler functions:

This function should never return an empty list. The caller should handle it as a bug in the analyzed code.

Function added by FI. It is recursive via...

Can we expect a sink?

0. Is the source a pointer? You would expect a yes, but C pointer arithmetics requires some strange typing. We assume it is an array of pointers.

  1. Try to find the source in the points-to information
  2. If the previous step has failed, build a new sink if the source is a formal parameter, a global variable, a C file local global variable (static) or a stub.

We may need a stub even if sinks is not empty when the source contains "*" subscript(s) and when none of the sinks contains such a subscript, or, more precisely when star subscripts do not match, matching being not yet clearly defined.

Must be checked before globals because stubs for global variables are themselves global.

  1. Still no sinks? Check the lattice structure...

FI: it seems easier to maintain the consistency between the sinks and the arcs for the global consistency of the points-to processing. Otherwise, we may have to check for special cases like undefined or anywhere.

A bug somewhere up...

Parameters
sourceource
ptsts
fresh_presh_p

Definition at line 2214 of file points_to_set.c.

2215 {
2216  list sinks = NIL;
2217  if(pt_map_undefined_p(pts)) {
2218  if(false && get_bool_property("ALIASING_ACROSS_TYPES")) {
2219  // make_untyped_anywhere_cell()
2221  reference r = make_reference(a, NIL);
2222  cell c = make_cell_reference(r);
2223  sinks = CONS(CELL, c, NIL);
2224  }
2225  else {
2227  type ct = type_to_pointed_type(t); // FI: assumed concrete...
2228  sinks = CONS(CELL, make_anywhere_cell(ct), NIL);
2229  }
2230  }
2231  else if(!points_to_graph_bottom(pts)) {
2232  //bool to_be_freed;
2233  type source_t = points_to_cell_to_concrete_type(source);
2234  //type source_t = points_to_cell_to_type(source, & to_be_freed);
2235  //type c_source_t = compute_basic_concrete_type(source_t);
2236  bool ok_p = C_pointer_type_p(source_t)
2237  || overloaded_type_p(source_t) // might be a pointer
2238  || null_cell_p(source);
2239  //if(to_be_freed) free_type(source_t);
2240 
2241  /* Can we expect a sink? */
2242  if(!ok_p) {
2243  // Likely typing error in source code
2245  pips_user_warning("Typing error in a pointer assignment or a dereferencing with \"%s\" at line %d.\n",
2246  entity_user_name(v),
2248  // Return an empty list
2249  }
2250  else if(nowhere_cell_p(source)) {
2251  sinks = nowhere_source_to_sinks(source, pts);
2252  }
2253  else if(anywhere_cell_p(source) || cell_typed_anywhere_locations_p(source)) {
2254  sinks = anywhere_source_to_sinks(source, pts);
2255  }
2256  else if(null_pointer_value_cell_p(source)) {
2257  sinks = null_source_to_sinks(source, pts);
2258  }
2259  else {
2260  /* 0. Is the source a pointer? You would expect a yes, but C
2261  pointer arithmetics requires some strange typing. We assume it
2262  is an array of pointers. */
2263  //bool to_be_freed;
2264  //type ct = points_to_cell_to_type(source, &to_be_freed);
2265  //if(array_type_p(ct)) {
2266  if(array_type_p(source_t)) {
2267  basic ctb = variable_basic(type_variable(source_t));
2268  // FI->AM: I am not happy at all with his
2269  if(basic_pointer_p(ctb)) {
2270  ;
2271  }
2272  else {
2273  cell sc = copy_cell(source);
2274  sinks = CONS(CELL, sc, sinks);
2275  }
2276  }
2277  //if(to_be_freed) free_type(ct);
2278 
2279  /* 1. Try to find the source in the points-to information */
2280  if(ENDP(sinks))
2281  sinks = points_to_source_to_sinks(source, pts, fresh_p);
2282 
2283  /* 2. If the previous step has failed, build a new sink if the
2284  * source is a formal parameter, a global variable, a C file local
2285  * global variable (static) or a stub.
2286  *
2287  * We may need a stub even if sinks is not empty when the source
2288  * contains "*" subscript(s) and when none of the sinks contains
2289  * such a subscript, or, more precisely when star subscripts do
2290  * not match, matching being not yet clearly defined.
2291  */
2292  if(ENDP(sinks) || !sinks_fully_matches_source_p(source, sinks)) {
2293  reference r = cell_any_reference(source);
2294  entity v = reference_variable(r);
2295  list n_sinks = NIL;
2296  if(formal_parameter_p(v)) {
2297  n_sinks = formal_source_to_sinks(source, pts, fresh_p);
2298  }
2299  /* Must be checked before globals because stubs for global
2300  variables are themselves global. */
2301  else if(entity_stub_sink_p(v)) {
2302  n_sinks = stub_source_to_sinks(source, pts, fresh_p);
2303  }
2304  else if(top_level_entity_p(v) || static_global_variable_p(v)) {
2305  n_sinks = global_source_to_sinks(source, pts, fresh_p);
2306  }
2307  else if(entity_typed_anywhere_locations_p(v)) {
2308  pips_internal_error("This case should have been handled above.\n");
2309  }
2310  sinks = gen_nconc(sinks, n_sinks);
2311 
2312  /* 3. Still no sinks? Check the lattice structure... */
2313  if(ENDP(sinks)) {
2314  type source_t = entity_basic_concrete_type(v);
2315  cell tac = make_anywhere_points_to_cell(source_t);// typed anywhere cell
2316  sinks = points_to_source_to_sinks(tac, pts, fresh_p);
2317  if(ENDP(sinks)) {
2319  reference ar = make_reference(a, NIL);
2320  cell ac = make_cell_reference(ar);// untyped anywhere cell
2321  sinks = points_to_source_to_sinks(ac, pts, fresh_p);
2322  free_cell(ac);
2323  }
2324  /* FI: it seems easier to maintain the consistency between the
2325  sinks and the arcs for the global consistency of the
2326  points-to processing. Otherwise, we may have to check for
2327  special cases like undefined or anywhere. */
2328  FOREACH(CELL, c, sinks) {
2329  points_to npt = make_points_to(copy_cell(source),
2330  copy_cell(c),
2333  add_arc_to_pt_map(npt, pts);
2334  }
2335  free_cell(tac);
2336  }
2337 
2338  if(ENDP(sinks)) {
2339  /* A bug somewhere up... */
2340  reference r = cell_any_reference(source);
2341  print_reference(r);
2342  pips_user_warning("\nUninitialized or null pointer dereferenced: "
2343  "Sink missing for a source based on \"%s\".\n"
2344  "Update points-to property POINTS_TO_UNINITIALIZED_POINTER_DEREFERENCING and/or POINTS_TO_UNINITIALIZED_NULL_DEREFERENCING according to needs.\n",
2345  entity_user_name(v));
2346  clear_pt_map(pts);
2347  points_to_graph_bottom(pts) = true;
2348  // FI: it is not a pips error but a user error (in theory)
2349  // pips_internal_error("Dereferencing of an unitialized pointer.\n");
2350  }
2351  }
2352  }
2353  }
2354  // FI: use gen_nreverse() to simplify debbugging? Not meaningful
2355  // with SET_FOREACH
2356  return sinks;
2357 }
bool null_pointer_value_cell_p(cell)
list stub_source_to_sinks(cell source, pt_map pts, bool fresh_p)
list nowhere_source_to_sinks(cell source, pt_map pts)
list null_source_to_sinks(cell source, pt_map pts)
bool sinks_fully_matches_source_p(cell source, list sinks)
Is there at least one cell "sink" in list "sinks" whose subscripts fully match the subscripts in cell...
list points_to_source_to_sinks(cell source, pt_map ptm, bool fresh_p)
Build the sinks of source "source" according to the points-to graphs.
list formal_source_to_sinks(cell source, pt_map pts, bool fresh_p)
Creation of a stub for a formal parameter or for a reference based on a formal parameter.
list global_source_to_sinks(cell source, pt_map pts, bool fresh_p)

References add_arc_to_pt_map(), anywhere_cell_p(), anywhere_source_to_sinks(), array_type_p(), basic_pointer_p, C_pointer_type_p(), CELL, cell_any_reference(), cell_typed_anywhere_locations_p(), clear_pt_map, CONS, copy_cell(), ENDP, entity_anywhere_locations(), entity_basic_concrete_type(), entity_stub_sink_p(), entity_typed_anywhere_locations_p(), entity_user_name(), FOREACH, formal_parameter_p(), formal_source_to_sinks(), free_cell(), gen_nconc(), get_bool_property(), global_source_to_sinks(), make_anywhere_cell(), make_anywhere_points_to_cell(), make_approximation_may(), make_cell_reference(), make_descriptor_none(), make_points_to(), make_reference(), NIL, nowhere_cell_p(), nowhere_source_to_sinks(), null_cell_p(), null_pointer_value_cell_p(), null_source_to_sinks(), overloaded_type_p(), pips_internal_error, pips_user_warning, points_to_cell_to_concrete_type(), points_to_context_statement_line_number(), points_to_graph_bottom, points_to_source_to_sinks(), print_reference(), pt_map_undefined_p, reference_variable, sinks_fully_matches_source_p(), static_global_variable_p(), stub_source_to_sinks(), top_level_entity_p(), type_to_pointed_type(), type_variable, and variable_basic.

Referenced by any_source_to_sinks(), binary_intrinsic_call_to_points_to_sinks(), dereferencing_to_sinks(), extended_source_to_sinks(), formal_source_to_sinks(), generic_stub_source_to_sinks(), global_source_to_sinks(), internal_pointer_assignment_to_points_to(), pointer_arithmetic_to_points_to(), reference_dereferencing_to_points_to(), reference_to_points_to_sinks(), reference_to_sinks(), sources_to_sinks(), and subscript_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sources_to_sinks()

list sources_to_sinks ( list  sources,
pt_map  ptm,
bool  fresh_p 
)

Same as source_to_sinks, but for a list of cells.

Parameters
sourcesources
ptmtm
fresh_presh_p

Definition at line 2519 of file points_to_set.c.

2520 {
2521  list sinks = NIL;
2522  FOREACH(CELL, c, sources) {
2523  list cl = source_to_sinks(c, ptm, fresh_p);
2524  sinks = gen_nconc(sinks, cl);
2525  }
2526  return sinks;
2527 }

References CELL, FOREACH, gen_nconc(), NIL, and source_to_sinks().

+ Here is the call graph for this function:

◆ statement_points_to_context_defined_p()

◆ statement_to_points_to()

pt_map statement_to_points_to ( statement  s,
pt_map  pt_in 
)

See points_to_statement()

Process the declarations

Go down recursively, although it is currently useless since a declaration statement is a call to CONTINUE

Get the current version of pt_in, updated by the analysis of s.

Either pt_in or pt_out should be stored in the hash_table

But it might be smarter (or not) to require or not the storage.

Eliminate local information if you exit a block

The statement context is know unknown: it has been popped above. No precise error message in points_to_set_block_projection()

Because arc removals do not update the approximations of the remaining arcs, let's upgrade approximations before the information is passed. Useful for arithmetic02.

Really dangerous here: if pt_map "in" is empty, then pt_map "out" must be empty to...

FI: we have a problem to denote unreachable statement. To associate an empty set to them woud be a way to avoid problems when merging points-to along different control paths. But you might also wish to start with an empty set... And anyway, you can find declarations in dead code...

Parameters
pt_int_in

Definition at line 154 of file statement.c.

155 {
156  pips_assert("pt_in is consistent", consistent_pt_map_p(pt_in));
159  pt_map pt_out = new_pt_map();
160  pt_out = full_copy_pt_map(pt_in);
162 
163  if(points_to_graph_bottom(pt_in)) {
164  // The information about dead code must be propagated downwards
165  pt_out = instruction_to_points_to(i, pt_out);
166  pips_assert("The resulting points-to graph is bottom",
167  points_to_graph_bottom(pt_out));
168  }
169  else {
170 
171  init_heap_model(s);
172  // FI: it would be nice to stack the current statement in order to
173  // provide more helpful error messages
175 
176  if(declaration_statement_p(s)) {
177  /* Process the declarations */
178  pt_out = declaration_statement_to_points_to(s, pt_out);
179  pips_assert("pt_out is consistent", consistent_pt_map_p(pt_out));
180  /* Go down recursively, although it is currently useless since a
181  declaration statement is a call to CONTINUE */
182  pt_out = instruction_to_points_to(i, pt_out);
183  }
184  else {
185  pt_out = instruction_to_points_to(i, pt_out);
186  }
187 
188  pips_assert("pt_out is consistent", consistent_pt_map_p(pt_out));
189 
190  /* Get the current version of pt_in, updated by the analysis of s. */
192 
193  pips_assert("pt_in is consistent", consistent_pt_map_p(pt_in));
194 
196  }
197 
198  /* Either pt_in or pt_out should be stored in the hash_table
199  *
200  * But it might be smarter (or not) to require or not the storage.
201  */
202  // FI: currently, this is going to be redundant most of the time
203  pt_map pt_merged;
204  if(bound_pt_to_list_p(s)) {
205  points_to_list ptl_prev = load_pt_to_list(s);
206  list ptl_prev_l = gen_full_copy_list(points_to_list_list(ptl_prev));
207  pt_map pt_prev = new_pt_map();
208  pt_prev = graph_assign_list(pt_prev, ptl_prev_l);
209  gen_free_list(ptl_prev_l);
210  pt_merged = merge_points_to_graphs(pt_in, pt_prev);
211  }
212  else
213  pt_merged = pt_in;
214  fi_points_to_storage(pt_merged, s, true);
215 
216  /* Eliminate local information if you exit a block */
217  if(statement_sequence_p(s)) {
220  bool main_p = ms==s && entity_main_module_p(m);
221  bool body_p = ms==s;
223  /* The statement context is know unknown: it has been popped
224  above. No precise error message in
225  points_to_set_block_projection() */
227  points_to_graph_set(pt_out) =
228  points_to_set_block_projection(points_to_graph_set(pt_out), dl, main_p, body_p);
230  }
231 
232  /* Because arc removals do not update the approximations of the
233  remaining arcs, let's upgrade approximations before the
234  information is passed. Useful for arithmetic02. */
236 
237  /* Really dangerous here: if pt_map "in" is empty, then pt_map "out"
238  * must be empty to...
239  *
240  * FI: we have a problem to denote unreachable statement. To
241  * associate an empty set to them woud be a way to avoid problems
242  * when merging points-to along different control paths. But you
243  * might also wish to start with an empty set... And anyway, you can
244  * find declarations in dead code...
245  */
246  // FI: a temporary fix to the problem, to run experiments...
247  //if(empty_pt_map_p(pt_in) && !declaration_statement_p(s)
248  // && s!=get_current_module_statement())
249  // clear_pt_map(pt_out); // FI: memory leak?
250 
251  pips_assert("pt_out is consistent on exit", consistent_pt_map_p(pt_out));
252 
254 
255  return pt_out;
256 }
bool bound_pt_to_list_p(statement)
statement get_current_module_statement(void)
Get the current module statement.
Definition: static.c:208
bool statement_sequence_p(statement s)
Statement classes induced from instruction type.
Definition: statement.c:335
bool declaration_statement_p(statement s)
Had to be optimized according to Beatrice Creusillet.
Definition: statement.c:224
void fi_points_to_storage(pt_map ptm, statement s, bool store)
Definition: passes.c:97
pt_map declaration_statement_to_points_to(statement s, pt_map pt_in)
See points_to_init()
Definition: statement.c:262
void push_statement_points_to_context(statement s, pt_map in)
Definition: statement.c:98
pt_map pop_statement_points_to_context(void)
Definition: statement.c:133
pt_map instruction_to_points_to(instruction i, pt_map pt_in)
See points_to_statement()
Definition: statement.c:370
void reset_heap_model(void)
Definition: sinks.c:1185
pt_map graph_assign_list(pt_map, list)
FI: I add functions dealing with points_to_graph variable, i.e.
set points_to_set_block_projection(set, list, bool, bool)
Remove from "pts" arcs based on at least one local entity in list "l" and preserve those based on sta...
void init_heap_model(statement)
Definition: sinks.c:1179
bool entity_main_module_p(entity e)
Definition: entity.c:700
statement pop_statement_global_stack(void)
Definition: static.c:352
void push_statement_on_statement_global_stack(statement)
Definition: static.c:333

References bound_pt_to_list_p(), consistent_pt_map_p, declaration_statement_p(), declaration_statement_to_points_to(), entity_main_module_p(), fi_points_to_storage(), full_copy_pt_map(), gen_free_list(), gen_full_copy_list(), get_current_module_entity(), get_current_module_statement(), graph_assign_list(), init_heap_model(), instruction_to_points_to(), load_pt_to_list(), merge_points_to_graphs(), new_pt_map, pips_assert, points_to_graph_bottom, points_to_graph_set, points_to_list_list, points_to_set_block_projection(), pop_statement_global_stack(), pop_statement_points_to_context(), push_statement_on_statement_global_stack(), push_statement_points_to_context(), reset_heap_model(), statement_declarations, statement_instruction, statement_sequence_p(), and upgrade_approximations_in_points_to_set().

Referenced by any_loop_to_points_to(), control_to_points_to(), cyclic_graph_to_points_to(), generic_points_to_analysis(), new_any_loop_to_points_to(), new_points_to_unstructured(), sequence_to_points_to(), test_to_points_to(), and whileloop_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ store_independent_points_to_arc_p()

bool store_independent_points_to_arc_p ( points_to  a)

Definition at line 2888 of file points_to_set.c.

2889 {
2890  return consistent_points_to_arc_p(a, true);
2891 }

References consistent_points_to_arc_p().

Referenced by add_arc_to_pt_map(), add_arc_to_pt_map_(), add_arc_to_simple_pt_map(), and consistent_points_to_set().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ store_or_update_printed_points_to_list()

void store_or_update_printed_points_to_list ( statement  ,
points_to_list   
)

◆ store_printed_points_to_list()

void store_printed_points_to_list ( statement  ,
points_to_list   
)

◆ struct_assignment_to_points_to()

pt_map struct_assignment_to_points_to ( expression  lhs,
expression  rhs,
pt_map  pt_in 
)

pt_in is modified by side-effects and returned as pt_out

This function is also used for declarations, although the syntax for declarations is reacher than the syntax for assignments which can use BRACE_INTRINSIC.

Current arc list (cal): the new arc may be conflicting with an existing must arc

We may have an implicit array of struct in the right or left hand side

rray_type_p(ft) ||

FI: conditionally add zero subscripts necessary to move from an array "a" to its first element, e.g. a[0][0][0]

Parameters
lhshs
rhshs
pt_int_in

Definition at line 2319 of file expression.c.

2322 {
2323  pt_map pt_out = pt_in;
2325  pt_out = struct_initialization_to_points_to(lhs, rhs, pt_in);
2326  else {
2327  list L = expression_to_points_to_sources(lhs, pt_out);
2328  list R = expression_to_points_to_sources(rhs, pt_out);
2329  FOREACH(CELL, lc, L) {
2330  bool l_to_be_freed;
2331  type lt = cell_to_type(lc, &l_to_be_freed);
2333  if(!entity_abstract_location_p(le)) {
2334  FOREACH(CELL, rc, R) {
2335  bool r_to_be_freed;
2336  type rt = cell_to_type(rc, &r_to_be_freed);
2338  if(entity_abstract_location_p(le)) {
2339  if(entity_abstract_location_p(re)) {
2340  pips_internal_error("Not implemented yet.");
2341  }
2342  else {
2343  pips_internal_error("Not implemented yet.");
2344  }
2345  }
2346  else {
2347  if(entity_abstract_location_p(re)) {
2348  // FI: when re==NULL, we could generate a user warning or
2349  // ignore the dereferencement of NULL...
2350 
2351  // All fields are going to point to this abstract
2352  // location... or to the elements pointed by this abstract
2353  // location
2354  pips_assert("Left type is struct",
2355  struct_type_p(lt));
2357  type st = entity_type(ste); // structure type
2358  list fl = type_struct(st); // field list
2359  FOREACH(ENTITY, f, fl) {
2360  type ft = entity_type(f); // field type
2361  if(pointer_type_p(ft)) {
2363  // reference rr = copy_reference(cell_any_reference(rc));
2365  cell lc = make_cell_reference(lr);
2366  type p_t = type_to_pointed_type(ft);
2367  cell rc = make_anywhere_cell(p_t);
2368  // reference_add_field_dimension(rr, f);
2369  // expression nlhs = reference_to_expression(lr);
2370  // expression nrhs = reference_to_expression(rr);
2371 
2372  // FI: too bad this cannot be reused because of an assert in normalize_reference()....
2373  // pt_out = assignment_to_points_to(nlhs, nrhs, pt_out);
2375  // FI: pt is allocated but not used...
2376  // FI: see update_points_to_graph_with_arc()?
2377  /* Current arc list (cal): the new arc may be
2378  conflicting with an existing must arc */
2379  list cal = points_to_source_to_arcs(lc, pt_out, false);
2380  list oal = NIL;
2381  list nal = NIL;
2382  FOREACH(POINTS_TO, a, cal) {
2384  if(approximation_exact_p(ap)) {
2385  oal = CONS(POINTS_TO, a, oal);
2386  points_to na =
2391  nal = CONS(POINTS_TO, na, nal);
2392  }
2393  }
2394  FOREACH(POINTS_TO, oa, oal)
2395  remove_arc_from_pt_map(oa, pt_out);
2396  FOREACH(POINTS_TO, na, nal)
2397  add_arc_to_pt_map(na, pt_out);
2398  gen_free_list(oal), gen_free_list(nal);
2399  add_arc_to_pt_map(pt, pt_out); // FI: I guess...
2400  // FI->FC: it would be nice to have a Newgen free_xxxxs() to
2401  // free a list of objects of type xxx with one call
2402  // FI: why would we free these expressions?
2403  // free_expression(lhs), free_expression(rhs);
2404  }
2405  else if(struct_type_p(ft)) {
2406  pips_internal_error("Not implemented yet.\n");
2407  }
2408  else {
2409  ; // Do nothing
2410  }
2411  }
2412  }
2413  else {
2414  pips_assert("Both types are struct or array of struct",
2416  && (struct_type_p(rt) || array_of_struct_type_p(rt)));
2417  /* We may have an implicit array of struct in the right or
2418  * left hand side
2419  */
2420  // pips_assert("Both type are equal", type_equal_p(lt, rt));
2421  basic ltb = variable_basic(type_variable(lt));
2422  basic rtb = variable_basic(type_variable(rt));
2423  pips_assert("Both type are somehow equal",
2424  basic_equal_p(ltb, rtb));
2426  type st = entity_type(ste); // structure type
2427  list fl = type_struct(st); // field list
2428  FOREACH(ENTITY, f, fl) {
2429  type uft = entity_basic_concrete_type(f); // field type
2430  // type uft = ultimate_type(ft);
2431  bool array_p = /*array_type_p(ft) ||*/ array_type_p(uft);
2432  if(!array_p && (pointer_type_p(uft) || struct_type_p(uft))) {
2435  /* FI: conditionally add zero subscripts necessary to
2436  move from an array "a" to its first element,
2437  e.g. a[0][0][0] */
2444  pt_out = assignment_to_points_to(nlhs, nrhs, pt_out);
2445  // FI->FC: it would be nice to have a Newgen free_xxxxs() to
2446  // free a list of objects of type xxx with one call
2447  // The references within the expressions are now part of pt_out
2448  // free_expression(lhs), free_expression(rhs);
2449  }
2450  else if(array_p && (array_of_pointers_type_p(uft)
2451  || pointer_type_p(uft)
2452  || array_of_struct_type_p(uft)
2453  || struct_type_p(uft))) {
2454  // Same as above, but an unbounded subscript is added...
2455  // Quite a special assign in C...
2463  CONS(EXPRESSION, li, NIL));
2465  CONS(EXPRESSION, ri, NIL));
2468  pt_out = assignment_to_points_to(nlhs, nrhs, pt_out);
2469  }
2470  else {
2471  ; // Do nothing
2472  }
2473  }
2474  }
2475  }
2476  }
2477  }
2478  else {
2479  // FI: the lhs is an unknown struct allocated anywhere
2480  // FI: we might have to generate new arcs. e.g. from HEAP to STACK...
2481  pips_internal_error("Not implemented yet.\n");
2482  }
2483  }
2484  }
2485  // pips_internal_error("Not implemented yet for lhs %p and rhs %p\n", lhs, rhs);
2486 
2487  return pt_out;
2488 }
reference reference_add_field_dimension(reference, entity)
add a field f as a subscript to a reference r if it is meaningful.
Definition: effects.c:1475
reference simple_reference_add_field_dimension(reference, entity)
Do not check anything, just add f as a last subscript.
Definition: effects.c:1581
pt_map struct_initialization_to_points_to(expression lhs, expression rhs, pt_map in)
Definition: expression.c:2262
list points_to_source_to_arcs(cell, pt_map, bool)
Build the list of arcs whose source is "source" according to the points-to graphs "ptm".
bool C_initialization_expression_p(expression e)
Definition: expression.c:4056

References add_arc_to_pt_map, approximation_exact_p, array_of_pointers_type_p(), array_of_struct_type_p(), array_type_p(), assignment_to_points_to(), basic_derived, basic_equal_p(), C_initialization_expression_p(), CELL, cell_any_reference(), cell_to_type(), CONS, copy_cell(), copy_reference(), ENTITY, entity_abstract_location_p(), entity_basic_concrete_type(), entity_type, EXPRESSION, expression_to_points_to_sources(), f(), FOREACH, gen_free_list(), gen_nconc(), make_anywhere_cell(), make_approximation_may(), make_cell_reference(), make_descriptor_none(), make_points_to(), make_unbounded_expression(), NIL, pips_assert, pips_internal_error, pointer_type_p(), POINTS_TO, points_to_approximation, points_to_sink, points_to_source, points_to_source_to_arcs(), reference_add_field_dimension(), reference_add_zero_subscripts(), reference_indices, reference_to_expression(), reference_variable, remove_arc_from_pt_map, simple_reference_add_field_dimension(), struct_initialization_to_points_to(), struct_type_p(), type_struct, type_to_pointed_type(), type_variable, and variable_basic.

Referenced by assignment_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ struct_initialization_to_points_to()

pt_map struct_initialization_to_points_to ( expression  lhs,
expression  rhs,
pt_map  in 
)

Temporary implementation: use anywhere as default initialization

We must assign to each relevant field its initial value

Parameters
lhshs
rhshs
inn

Definition at line 2262 of file expression.c.

2265 {
2266  pt_map out = in;
2267  // Implementation 0:
2268  // pips_internal_error("Not implemented yet.\n");
2269  // pips_assert("to please gcc, waiting for implementation", lhs==rhs && in==in);
2271 
2272  // L must contain a unique cell, containing a non-index reference
2273  pips_assert("One struct to initialize", (int) gen_length(L)==1);
2274  cell c = CELL(CAR(L));
2276  entity e = reference_variable(r);
2277  pips_assert("c is not indexed", ENDP(reference_indices(r)));
2278  if(0) {
2279  /* Temporary implementation: use anywhere as default initialization */
2280  // ignore rhs
2282  FOREACH(CELL, source, l) {
2283  bool to_be_freed;
2284  type t = points_to_cell_to_type(source, &to_be_freed);
2286  cell sink = make_anywhere_cell(c_t);
2287  if(to_be_freed) free_type(t);
2288  points_to pt = make_points_to(source, sink,
2291  add_arc_to_pt_map(pt, out);
2292  }
2293  }
2294  else {
2295  /* We must assign to each relevant field its initial value */
2296  list fl = struct_variable_to_fields(e); // list of entities
2298  pips_assert("The field and initial value lists have the same length",
2299  gen_length(fl)==gen_length(vl));
2300  list cvl = vl;
2301  FOREACH(ENTITY, f, fl) {
2302  reference nr =
2305  out = assignment_to_points_to(nlhs, EXPRESSION(CAR(cvl)), out);
2306  POP(cvl);
2307  }
2308  }
2309 
2310  return out;
2311 }
list struct_initialization_expression_to_expressions(expression e)
Returns a list of expressions hidden by the brace function.
Definition: expression.c:4073
list struct_variable_to_fields(entity)
Assume that v is declared as a struct.
Definition: variable.c:2045

References add_arc_to_pt_map, assignment_to_points_to(), CAR, CELL, cell_any_reference(), compute_basic_concrete_type(), CONS, ENDP, ENTITY, entity_to_expression(), EXPRESSION, expression_to_points_to_sources(), f(), FOREACH, free_type(), gen_length(), make_anywhere_cell(), make_approximation_exact(), make_descriptor_none(), make_points_to(), make_reference(), NIL, out, pips_assert, points_to_cell_to_type(), POP, reference_indices, reference_to_expression(), reference_variable, struct_initialization_expression_to_expressions(), struct_variable_to_fields(), type_to_pointed_type(), and variable_to_pointer_locations().

Referenced by struct_assignment_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ struct_variable_to_pointer_locations()

list struct_variable_to_pointer_locations ( entity  e,
entity  ee 
)

return list of cells for pointers declared directly or indirecltly in variable "e" of type struct defined by entity "ee" and its type.

Typedefs have already been taken care of by the caller (?).

Signature with e and ee inherited from Amira Mensi.

Find pointers downwards and build a list of cells.

Parameters
eee

Definition at line 115 of file variable.c.

116 {
117  list l = NIL;
118  // bool eval = true;
119  type tt = entity_type(ee);
120  pips_assert("entity ee has type struct", type_struct_p(tt));
121  list fl = type_struct(tt); // list of fields, or field list
122 
123  list sl = NIL;
124  if(array_entity_p(e)) {
125  int i;
126  for(i=0; i< variable_entity_dimension(e); i++) {
128  sl = CONS(EXPRESSION, se, sl);
129  }
130  }
131 
132  FOREACH(ENTITY, f, fl) {
135  // FI: I wonder if we should not build the points-to right away
136  // when we know the type of the nowehere/undefined cell;
137  // reminder: this type is useful to switch to a anywhere
138  // abstract location
139  list l2 = NIL;
140  if(array_type_p(entity_type(f))) {
142  l2 = CONS(EXPRESSION, s2, NIL);
143  }
145  list fsl = CONS(EXPRESSION, s, l2); // field list
146  list nsl = gen_full_copy_list(sl); // subscript list
147  list fl = gen_nconc(nsl,fsl); // full list
148  reference r = make_reference(e, fl);
149  cell c = make_cell_reference(r);
150  l = gen_nconc(l, CONS(CELL, c, NIL));
151  }
152  else if(struct_type_p(ft) || array_of_struct_type_p(ft)) {
153  // The main data structure contains a secondary data structure
154  // FI: build the prefix and go down
155  list l2 = NIL;
156  if(array_type_p(entity_type(f))) {
158  l2 = CONS(EXPRESSION, s2, gen_full_copy_list(l2));
159  }
161  list fsl = CONS(EXPRESSION, s, l2); // field list
162  list nsl = gen_full_copy_list(sl); // subscript list
163  list fl = gen_nconc(nsl,fsl); // full list
164  reference r = make_reference(e, fl);
165  cell c = make_cell_reference(r);
166 
167  /* Find pointers downwards and build a list of cells. */
169 
170  free_cell(c);
171  l = gen_nconc(l, ll);
172  //pips_internal_error("Not implemented yet.\n");
173  //l = array_of_struct_to_pointer_location(e, ee);
174  }
175  }
176  gen_full_free_list(sl);
177  return l;
178 }
list struct_variable_to_pointer_subscripts(cell c, entity f)
returns a list of cells to reach pointers depending on field f.
Definition: variable.c:183
int variable_entity_dimension(entity v)
variable_entity_dimension(entity v): returns the dimension of variable v; scalar have dimension 0.
Definition: variable.c:1293

References array_entity_p(), array_of_pointers_type_p(), array_of_struct_type_p(), array_type_p(), CELL, CONS, ENTITY, entity_to_expression(), entity_type, EXPRESSION, f(), FOREACH, free_cell(), gen_full_copy_list(), gen_full_free_list(), gen_nconc(), make_cell_reference(), make_reference(), make_unbounded_expression(), NIL, pips_assert, pointer_type_p(), struct_type_p(), struct_variable_to_pointer_subscripts(), type_struct, type_struct_p, ultimate_type(), and variable_entity_dimension().

Referenced by variable_to_pointer_locations().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ struct_variable_to_pointer_subscripts()

list struct_variable_to_pointer_subscripts ( cell  c,
entity  f 
)

returns a list of cells to reach pointers depending on field f.

Cell c is the current prefix.

In case we are dealing with an array of structs, add subscript expressions in mc, a modified copy of parameter c

Take care of each field in the structure.

copy cell c and add a subscript for f

copy cell c and add a subscript for f

Definition at line 183 of file variable.c.

184 {
185  list sl = NIL;
187  pips_assert("We are dealing with a struct", struct_type_p(ft)
188  || array_of_struct_type_p(ft));
190  type st = entity_type(basic_derived(fb));
191  list sfl = type_struct(st);
192 
193  /* In case we are dealing with an array of structs, add subscript
194  expressions in mc, a modified copy of parameter c */
195  cell mc = copy_cell(c); // modified cell c
196  /*
197  if(array_type_p(ft)) {
198  list ssl = NIL;
199  int i;
200  for(i=0; i< variable_dimension_number(type_variable(ft)); i++) {
201  expression se = make_unbounded_expression();
202  ssl = CONS(EXPRESSION, se, ssl);
203  }
204  reference r = cell_any_reference(mc);
205  reference_indices(r) = gen_nconc(reference_indices(r), ssl);
206  }
207  */
208 
209  /* Take care of each field in the structure. */
210  FOREACH(ENTITY, sf, sfl) {
211  type sft = ultimate_type(entity_type(sf));
212  if(pointer_type_p(sft) || array_of_pointers_type_p(sft)) {
213  /* copy cell c and add a subscript for f */
214  cell nc = copy_cell(mc);
218  CONS(EXPRESSION, se, NIL));
219  if(array_entity_p(sf)) {
222  CONS(EXPRESSION, ue, NIL));
223  }
224  sl = gen_nconc(sl, CONS(CELL, nc, NIL));
225  }
226  else if(struct_type_p(sft) || array_of_struct_type_p(sft)) {
227  /* copy cell c and add a subscript for f */
228  cell nc = copy_cell(c);
232  CONS(EXPRESSION, se, NIL));
233  if(array_entity_p(sf)) {
236  CONS(EXPRESSION, ue, NIL));
237  }
239  sl = gen_nconc(sl, nsl);
240  free_cell(nc);
241  }
242  }
243 
244  free_cell(mc);
245 
246  return sl;
247 }

References array_entity_p(), array_of_pointers_type_p(), array_of_struct_type_p(), basic_derived, CELL, cell_any_reference(), CONS, copy_cell(), ENTITY, entity_to_expression(), entity_type, EXPRESSION, f(), FOREACH, free_cell(), gen_nconc(), make_unbounded_expression(), NIL, pips_assert, pointer_type_p(), reference_indices, struct_type_p(), struct_variable_to_pointer_subscripts(), type_struct, type_variable, ultimate_type(), and variable_basic.

Referenced by struct_variable_to_pointer_locations(), and struct_variable_to_pointer_subscripts().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ stub_source_to_sinks()

list stub_source_to_sinks ( cell  source,
pt_map  pts,
bool  fresh_p 
)
Parameters
sourceource
ptsts
fresh_presh_p

Definition at line 1153 of file points_to_set.c.

1154 {
1155  list sinks = NIL;
1156  reference r = cell_any_reference(source);
1157  list sl = reference_indices(r);
1158  if(ENDP(sl))
1159  sinks = scalar_stub_source_to_sinks(source, pts, fresh_p);
1160  else
1161  sinks = array_stub_source_to_sinks(source, pts, fresh_p);
1162  return sinks;
1163 }
list scalar_stub_source_to_sinks(cell source, pt_map pts, bool fresh_p)
list array_stub_source_to_sinks(cell source, pt_map pts, bool fresh_p)

References array_stub_source_to_sinks(), cell_any_reference(), ENDP, NIL, reference_indices, and scalar_stub_source_to_sinks().

Referenced by source_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ subscript_expression_p()

bool subscript_expression_p ( expression  e)

Definition at line 752 of file constant-path-utils.c.

753 {
755 }
#define syntax_subscript_p(x)
Definition: ri.h:2743

References expression_syntax, and syntax_subscript_p.

◆ subscript_to_points_to_sinks()

list subscript_to_points_to_sinks ( subscript  s,
type  et,
pt_map  in,
bool  eval_p 
)

Generate the corresponding points-to reference(s).

All access operators such as ., ->, * are replaced by subscripts.

See Strict_typing.sub/assigment11.c: the index is not put back at the right place. It would be easy (?) to fix it in this specific case, not forgetting the field subscripts..., but I do not see how to handle general stubs with artificial dimensions...

FI: In many cases, you do need the source. However, you have different kind of sources because "x" and "&x[0]" are synonyms and because you sometimes need "x" and some other times "&x[0]".

If the first dimension is unbounded, it has (probably) be added because of a pointer. A zero subscript is also added.

Add a zero subscript

Add subscript when possible. For typing reason, typed anywhere cell should be subscripted.

Add the subscripts

The reference "p[i][j]" is transformed into an expression "*(*(p+i)+j)" if "p" is really a pointer expression, not a partial array reference.

Parameters
ett
inn
eval_pval_p

Definition at line 1451 of file sinks.c.

1455 {
1456  expression a = subscript_array(s);
1457  bool to_be_freed;
1458  // If ever a pointer is deferenced somewhere, at is not going to
1459  // take into account the extra dimensions needed for pointer arithmetics
1460  type at = points_to_expression_to_type(a, &to_be_freed);
1461 
1462  /* FI: In many cases, you do need the source. However, you have
1463  * different kind of sources because "x" and "&x[0]" are synonyms
1464  * and because you sometimes need "x" and some other times "&x[0]".
1465  */
1466  list sources = expression_to_points_to_sources(a, in);
1467 
1468  list sl = subscript_indices(s);
1470  list sinks = NIL;
1471  list i_sources = NIL;
1472  bool eval_performed_p = false;
1473 
1474  /* If the first dimension is unbounded, it has (probably) be added
1475  because of a pointer. A zero subscript is also added. */
1476  bool strict_p = get_bool_property("POINTS_TO_STRICT_POINTER_TYPES");
1477  if(array_type_p(at) && !strict_p) {
1478  variable v = type_variable(at);
1480  if(unbounded_dimension_p(d1)) {
1481  /* Add a zero subscript */
1483  csl = CONS(EXPRESSION, z, csl);
1484  }
1485  }
1486 
1487  /* Add subscript when possible. For typing reason, typed anywhere
1488  cell should be subscripted. */
1489  FOREACH(CELL, c, sources) {
1490  // FI: some other lattice abstract elements should be removed like
1491  // STACK, DYNAMIC
1492  if(!nowhere_cell_p(c) && !null_cell_p(c) && !anywhere_cell_p(c)
1493  && !all_heap_locations_cell_p(c)) {
1494  bool to_be_freed2;
1495  type t = points_to_cell_to_type(c, &to_be_freed2);
1497  entity v = reference_variable(r);
1498 
1499  if(array_type_p(at)) {
1500  list ncsl = gen_full_copy_list(csl);
1501  if(entity_stub_sink_p(v)) {
1502  // argv03
1504 
1505  // FI: an horror... fixing a design mistake by a kludge...
1506  // useful for argv03, disastrous for dereferencing08
1507  if(!points_to_array_reference_p(r)) {
1509  ;
1510  else
1511  pips_internal_error("Subscript handling failure 1.\n");
1512  }
1513  // FI: the update depends on the sink model
1514  // points_to_reference_update_final_subscripts(r, ncsl);
1516 
1517  // FI: let's add the zero subscripts again...
1518  // points_to_cell_add_zero_subscripts(c);
1520  }
1521  else {
1522  // Expression "a" does not require any dereferencing, add
1523  // the new indices (Strict_typing.sub/assignment11.c
1524 
1525  // FI: an horror... fixing a design mistake by a kludge...
1527  ;
1528  else
1529  pips_internal_error("Subscript handling failure 1.\n");
1530 
1532  }
1533 
1534  i_sources = CONS(CELL, c, i_sources);
1535  }
1536  else if(struct_type_p(at)) { // Just add the subscript, old version
1537  list ncsl = gen_full_copy_list(csl);
1538  if(entity_stub_sink_p(v)) {
1540  // FI: the update depends on the sink model
1542  }
1543  else {
1544  // Expression "a" does not require any dereferencing, add
1545  // the new indices (Strict_typing.sub/assignment11.c
1547  }
1548  i_sources = CONS(CELL, c, i_sources);
1549  }
1550  else if(pointer_type_p(at)) {
1553  /* Add the subscripts */
1554  list ncsl = gen_full_copy_list(csl);
1556  eval_performed_p = true;
1557  i_sources = CONS(CELL, c, i_sources);
1558  }
1559  else {
1560  /* The reference "p[i][j]" is transformed into an expression
1561  "*(*(p+i)+j)" if "p" is really a pointer expression, not a
1562  partial array reference. */
1563  //expression pae = pointer_subscript_to_expression(c, csl);
1564  // FI: I guess csl might have to be freed...
1565  list nsl = gen_full_copy_list(sl);
1567  i_sources = expression_to_points_to_sources(pae, in);
1568  free_expression(pae);
1569  }
1570  }
1571  else {
1572  pips_internal_error("Unexpected case.\n");
1573  }
1574  if(to_be_freed2) free_type(t);
1575  }
1576  else if(anywhere_cell_p(c)
1577  || all_heap_locations_cell_p(c)) {
1578  i_sources = CONS(CELL, c, i_sources);
1579  }
1580  }
1581 
1582  gen_full_free_list(csl);
1583  gen_free_list(sources);
1584 
1585  if(eval_p && !eval_performed_p) {
1586  FOREACH(CELL, source, i_sources) {
1587  bool to_be_freed;
1588  type t = points_to_cell_to_type(source, &to_be_freed);
1589  reference r = cell_any_reference(source);
1591  //points_to_cell_add_zero_subscripts(source);
1592  //adapt_reference_to_type(r, at, points_to_context_statement_line_number);
1595  CONS(EXPRESSION, z, NIL));
1596  sinks = gen_nconc(sinks, CONS(CELL, source, NIL));
1597  }
1598  else if(pointer_type_p(t)) {
1599  // A real pointer, not an under-subscripted array
1600  list pointed = source_to_sinks(source, in, true);
1601  sinks = gen_nconc(sinks, pointed);
1602  }
1603  else {
1604  // FI: Pretty bad wrt sharing and memory leaks
1605  sinks = gen_nconc(sinks, CONS(CELL, source, NIL));
1606  }
1607  if(to_be_freed) free_type(t);
1608  }
1609  }
1610  else
1611  sinks = i_sources;
1612 
1613  if(to_be_freed) free_type(at);
1614 
1615  if(ENDP(sinks)) {
1616  pips_user_warning("Some kind of execution error has been encountered.\n");
1617  clear_pt_map(in);
1618  points_to_graph_bottom(in) = true;
1619  }
1620 
1621  check_type_of_points_to_cells(sinks, et, eval_p);
1622 
1623  return sinks;
1624 }
bool points_to_array_reference_p(reference)
Is this a reference to an array or a reference to a pointer? This is not linked to the type of the re...
Definition: points_to.c:599
void points_to_reference_update_final_subscripts(reference, list)
Substitute the subscripts "sl" in points-to reference "r" just after the last field subscript by "nsl...
Definition: points_to.c:278
bool unbounded_dimension_p(dimension dim)
bool unbounded_dimension_p(dim) input : a dimension of an array entity.
Definition: expression.c:1130
expression pointer_subscript_to_expression(cell c, list csl)
Allocate a new expression based on the reference in "c" and the subscript list "csl".
Definition: sinks.c:1430

References adapt_reference_to_type(), all_heap_locations_cell_p(), anywhere_cell_p(), array_type_p(), CAR, CELL, cell_any_reference(), check_type_of_points_to_cells(), clear_pt_map, complete_points_to_reference_with_zero_subscripts(), CONS, DIMENSION, ENDP, entity_stub_sink_p(), EXPRESSION, expression_to_points_to_sources(), FOREACH, free_expression(), free_type(), gen_free_list(), gen_full_copy_list(), gen_full_free_list(), gen_nconc(), get_bool_property(), make_zero_expression(), NIL, nowhere_cell_p(), null_cell_p(), pips_internal_error, pips_user_warning, pointer_subscript_to_expression(), pointer_type_p(), points_to_array_reference_p(), points_to_cell_to_type(), points_to_context_statement_line_number(), points_to_expression_to_type(), points_to_graph_bottom, points_to_reference_update_final_subscripts(), reference_indices, reference_variable, source_to_sinks(), struct_type_p(), subscript_array, subscript_expressions_to_constant_subscript_expressions(), subscript_indices, type_variable, unbounded_dimension_p(), and variable_dimensions.

Referenced by expression_to_points_to_cells().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ subscripted_reference_to_points_to()

void subscripted_reference_to_points_to ( reference  r,
list  sl,
pt_map  pt_in 
)

expression.c

expression.c

FI: we have to find the right location for the subscript to update. Some dimensions are due to the dimension of the source in pt_in, one dimension is due to the fact that we are dealing with a pointer, some dimensions are due to the fact that an array is pointed. The dimension to update may be the first one, the last one, or one in the middle.

This also depends on strict typing...

See for instance, Pointers/pointer20.c

Parameters
sll
pt_int_in

Definition at line 57 of file expression.c.

58 {
59  if(!ENDP(sl)) {
61  if(pointer_type_p(rt)) {
62  //type pt = type_to_pointed_type(rt);
63  //list cl = reference_to_points_to_sinks(r, pt, pt_in, false, true);
64  list cl = reference_to_points_to_sinks(r, rt, pt_in, true, true);
65  // FI: the arc between "r" and NULL should be removed...
67  FOREACH(CELL, c, cl) {
68  if(!ENDP(CDR(sl))) {
69  expression fs = EXPRESSION(CAR(sl));
70  /* FI: we have to find the right location for the subscript
71  * to update. Some dimensions are due to the dimension of
72  * the source in pt_in, one dimension is due to the fact
73  * that we are dealing with a pointer, some dimensions are
74  * due to the fact that an array is pointed. The dimension
75  * to update may be the first one, the last one, or one in
76  * the middle.
77  *
78  * This also depends on strict typing...
79  *
80  * See for instance, Pointers/pointer20.c
81  */
84  list osl = reference_indices(or);
85  if(ENDP(osl)) {
88  NIL);
89  }
90  else {
92  }
95  }
96  else
97  pips_internal_error("reference could not be updated.\n");
98  }
99  }
100  }
101  else if(array_of_pointers_type_p(rt)) {
102  pips_internal_error("Not implemented yet.\n");
103  }
104  else
105  pips_internal_error("Meaningless call.\n");
106  }
107 }
void points_to_cell_update_last_subscript(cell, expression)
Transform reference a[i]...[j] and expression s into reference a[i]..[j+s] if j and s are constant in...
Definition: effects.c:1643
list reference_to_points_to_sinks(reference, type, pt_map, bool, bool)
Returns a list of memory cells "sinks" possibly accessed by the evaluation of reference "r".
Definition: sinks.c:755

References adapt_reference_to_type(), array_of_pointers_type_p(), CAR, CDR, CELL, cell_any_reference(), CONS, copy_expression(), ENDP, EXPRESSION, FOREACH, NIL, pips_internal_error, pointer_type_p(), points_to_cell_update_last_subscript(), points_to_context_statement_line_number(), points_to_reference_to_concrete_type(), reference_indices, reference_to_points_to_sinks(), and remove_impossible_arcs_to_null().

Referenced by expression_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ternary_intrinsic_call_to_points_to_sinks()

list ternary_intrinsic_call_to_points_to_sinks ( call  c,
pt_map  in,
bool  eval_p,
bool  constant_p 
)
Parameters
inn
eval_pval_p
constant_ponstant_p

Definition at line 594 of file sinks.c.

598 {
599  entity f = call_function(c);
600  list al = call_arguments(c);
601  list sinks = NIL;
602 
603  pips_assert("in is consistent", consistent_pt_map_p(in));
604 
605  if(ENTITY_CONDITIONAL_P(f)) {
606  //bool eval_p = true;
607  expression c = EXPRESSION(CAR(al));
608  pt_map in_t = full_copy_pt_map(in);
609  pt_map in_f = full_copy_pt_map(in);
610  in_t = condition_to_points_to(c, in_t, true);
611  in_f = condition_to_points_to(c, in_f, false);
612  expression e1 = EXPRESSION(CAR(CDR(al)));
613  expression e2 = EXPRESSION(CAR(CDR(CDR(al))));
614  list sinks1 = NIL;
615  if(!points_to_graph_bottom(in_t))
616  sinks1 = expression_to_points_to_cells(e1, in_t, eval_p, constant_p);
617  list sinks2 = NIL;
618  if(!points_to_graph_bottom(in_f))
619  sinks2 = expression_to_points_to_cells(e2, in_f, eval_p, constant_p);
620  sinks = gen_nconc(sinks1, sinks2);
621  // The "in" points-to graph may be enriched by both sub-graphs
622  //
623  // side-effects on in? memory leak...
625  points_to_graph_set(in_f));
627  points_to_graph_bottom(in) = true;
628  // The free is too deep. References from points-to arcs in in_t
629  // and in_f may have been integrated in sinks1 and/or sinks2
630  // See conditional05
631  clear_pt_map(in_t), clear_pt_map(in_f);
632  free_pt_map(in_t), free_pt_map(in_f);
633  }
634  // FI: any other ternary intrinsics?
635 
636  return sinks;
637 }
set merge_points_to_set(set, set)
Merge two points-to sets.

References call_arguments, call_function, CAR, CDR, clear_pt_map, condition_to_points_to(), consistent_pt_map_p, constant_p(), ENTITY_CONDITIONAL_P, EXPRESSION, expression_to_points_to_cells(), f(), free_pt_map, full_copy_pt_map(), gen_nconc(), merge_points_to_set(), NIL, pips_assert, points_to_graph_bottom, and points_to_graph_set.

Referenced by intrinsic_call_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ test_to_points_to()

pt_map test_to_points_to ( test  t,
pt_map  pt_in 
)

Computing the points-to information after a test.

All the relationships are of type MAY, even if the same arc is defined, e.g. "if(c) p = &i; else p=&i;".

Might be refined later by using preconditions.

Make sure the condition is exploited, either because of side effects or simply because of dereferencements.

This cannot be done here because of side-effects.

FI: because the conditions must be evaluated for true and false?

condition's side effect and information are taked into account, e.g.:

"if(p=q)" or "if(*p++)" or "if(p)" which implies p->NULL in the else branch. FI: to be checked with test cases

We must use a common definition domain for both relations in order to obatin a really consistent points-to relation after the merge. This is similar to what is done in semantics for scalar preconditions.

Parameters
pt_int_in

Definition at line 496 of file statement.c.

497 {
498  pt_map pt_out = pt_map_undefined;
499 
500  //bool store = true;
501  // pt_out = points_to_test(t, pt_in, store);
502  // Translation of points_to_test
503  statement ts = test_true(t);
504  statement fs = test_false(t);
505  expression c = test_condition(t);
506  pt_map pt_t = pt_map_undefined;
507  pt_map pt_f = pt_map_undefined;
508 
509  /* Make sure the condition is exploited, either because of side
510  * effects or simply because of dereferencements.
511  *
512  * This cannot be done here because of side-effects.
513  *
514  * FI: because the conditions must be evaluated for true and false?
515  */
516  //pt_in = expression_to_points_to(c, pt_in);
517  //list el = expression_to_proper_constant_path_effects(c);
518  //if(!effects_write_p(el))
519  // pt_in = expression_to_points_to(c, pt_in, true);
520  //gen_free_list(el);
521 
522  // The side effects won't be taken into account when the condition
523  // is evaluated
524  pt_in = expression_to_points_to(c, pt_in, true);
525 
526  pt_map pt_in_t = full_copy_pt_map(pt_in);
527  pt_map pt_in_f = full_copy_pt_map(pt_in);
528 
529  /* condition's side effect and information are taked into account, e.g.:
530  *
531  * "if(p=q)" or "if(*p++)" or "if(p)" which implies p->NULL in the
532  * else branch. FI: to be checked with test cases */
533  if(!points_to_graph_bottom(pt_in_t)) // FI: we are in dead code
534  pt_in_t = condition_to_points_to(c, pt_in_t, true);
535  pt_t = statement_to_points_to(ts, pt_in_t);
536 
537  if(!points_to_graph_bottom(pt_in_f)) // FI: we are in dead code
538  pt_in_f = condition_to_points_to(c, pt_in_f, false);
539  pt_f = statement_to_points_to(fs, pt_in_f);
540 
541  pips_assert("pt_t is consistent", points_to_graph_consistent_p(pt_t));
542  pips_assert("pt_f is consistent", points_to_graph_consistent_p(pt_f));
543 
544  /* We must use a common definition domain for both relations in
545  order to obatin a really consistent points-to relation after the
546  merge. This is similar to what is done in semantics for scalar
547  preconditions. */
548  equalize_points_to_domains(pt_t, pt_f);
549 
550  pt_out = merge_points_to_graphs(pt_t, pt_f);
551 
552  pips_assert("pt_out is consistent", points_to_graph_consistent_p(pt_out));
553 
554  // FI: we should take care of pt_t and pt_f to avoid memory leaks
555  // In that specific case, clear_pt_map() and free_pt_map() should be ok
556 
557  pips_assert("pt_out is consistent", points_to_graph_consistent_p(pt_out));
558 
561  free_pt_map(pt_t), free_pt_map(pt_f);
562 
563  pips_assert("pt_out is consistent", points_to_graph_consistent_p(pt_out));
564 
565  return pt_out;
566 }
void equalize_points_to_domains(points_to_graph pt_t, points_to_graph pt_f)
Make sure that pt_t and pt_f have the same definition domain except if one of them is bottom.
Definition: statement.c:479
#define test_false(x)
Definition: ri.h:2837
#define test_true(x)
Definition: ri.h:2835
#define test_condition(x)
Definition: ri.h:2833

References condition_to_points_to(), equalize_points_to_domains(), expression_to_points_to(), free_pt_map, full_copy_pt_map(), merge_points_to_graphs(), pips_assert, points_to_graph_bottom, points_to_graph_consistent_p(), points_to_graph_set, pt_map_undefined, set_clear(), statement_to_points_to(), test_condition, test_false, and test_true.

Referenced by instruction_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ text_code_points_to()

text text_code_points_to ( statement  s)

Definition at line 84 of file points_to_prettyprint.c.

85 {
86  text t;
87  debug_on("PRETTYPRINT_DEBUG_LEVEL");
91  debug_off();
92  return t;
93 }
text text_points_to(entity module __attribute__((__unused__)), int margin __attribute__((__unused__)), statement s)
void close_prettyprint()
because some prettyprint functions may be used for debug, so the last hook set by somebody may have s...
Definition: misc.c:242
void init_prettyprint(text(*hook)(entity, int, statement))
checks that the prettyprint hook was actually reset...
Definition: misc.c:231
text text_module(entity, statement)

References close_prettyprint(), debug_off, debug_on, get_current_module_entity(), init_prettyprint(), text_module(), and text_points_to().

+ Here is the call graph for this function:

◆ text_points_to()

text text_points_to ( entity  ,
int  ,
statement   
)

◆ text_points_to_relation()

text text_points_to_relation ( points_to  pt_to)

text text_region(effect reg) input : a region output : a text consisting of several lines of commentaries, representing the region modifies : nothing

of string

PREFIX

REFERENCES

Change nowhere cells into undefined to comply with the C standard

if (points_to_second_address_of_p(pt_to))

append("&");

DESCRIPTOR

sorts in such a way that constraints with phi variables come first.

APPROXIMATION

CLOSE

Parameters
pt_tot_to

Definition at line 253 of file points_to_prettyprint.c.

254 {
255  text tpt_to = text_undefined;
256 
257  bool foresys = false;
258  string str_prefix = get_comment_continuation();
260  Psysteme sc;
261  list /* of string */ ls;
262 
263  if (points_to_undefined_p(pt_to))
264  {
265  ifdebug(1)
266  {
267  return make_text(CONS(SENTENCE,
269  strdup(concatenate(str_prefix,
270  "undefined points to relation\n",
271  NULL))),
272  NIL));
273  }
274  else
275  pips_user_warning("unexpected points-to relation undefined\n");
276  }
277  else
278  tpt_to = make_text(NIL);
279 
280  cell source = points_to_source(pt_to);
281  cell sink = points_to_sink(pt_to);
282 
283  pips_assert("there should not be preference cells in points to relation (source) \n",
284  !cell_preference_p(source));
285  pips_assert("there should not be preference cells in points to relation (sink) \n",
286  !cell_preference_p(sink));
287 
288  pips_assert("gaps not handled yet (source)", !cell_gap_p(source));
289  pips_assert("gaps not handled yet (sink)", !cell_gap_p(sink));
290 
291 
292  reference source_r = cell_reference(source);
293  reference sink_r = cell_reference(sink);
295  descriptor d = points_to_descriptor(pt_to);
296 
297  /* PREFIX
298  */
300  append(" ");
301 
302  /* REFERENCES */
303  ls = effect_words_reference(source_r);
304 
305  FOREACH(STRING, s, ls) {append(s);}
306  gen_free_string_list(ls); ls = NIL;
307 
308  append(" -> ");
309 
310  /* Change nowhere cells into undefined to comply with the C standard */
311  entity e = reference_variable(sink_r);
313  ls = effect_words_reference(sink_r);
314  }
315  else {
316  string undef = "undefined" ;
317  ls = CONS(STRING,strdup(undef),NIL);
318  }
319  // ls = effect_words_reference(sink_r);
320  /* if (points_to_second_address_of_p(pt_to)) */
321  /* append("&"); */
322 
323  FOREACH(STRING, s, ls) {append(s);}
324  gen_free_string_list(ls); ls = NIL;
325 
326  /* DESCRIPTOR */
327  /* sorts in such a way that constraints with phi variables come first.
328  */
329  if(!descriptor_none_p(d))
330  {
331  sc = sc_copy(descriptor_convex(d));
333  system_sorted_text_format(line_buffer, str_prefix, tpt_to, sc,
335  vect_contains_phi_p, foresys);
336  sc_rm(sc);
337  }
338 
339  /* APPROXIMATION */
340  append(approximation_may_p(ap) ? " , MAY" : " , EXACT");
341 
342  /* CLOSE */
343  close_current_line(line_buffer, tpt_to, str_prefix);
344 
345  return tpt_to;
346 }
sentence make_sentence(enum sentence_utype tag, void *val)
Definition: text.c:59
text make_text(list a)
Definition: text.c:107
int is_inferior_cell_descriptor_pvarval(Pvecteur *pvarval1, Pvecteur *pvarval2)
weight function for Pvecteur passed as argument to sc_lexicographic_sort in prettyprint functions inv...
Definition: compare.c:305
void system_sorted_text_format(string line, string prefix, text txt, Psysteme ps, string(*variable_name)(Variable), bool(*put_first)(Pvecteur), bool a_la_fortran)
lower level hook for regions.
list effect_words_reference(reference)
prettyprint.c
Definition: prettyprint.c:68
const char * pips_region_user_name(entity)
char * pips_region_user_name(entity ent) output : the name of entity.
Definition: prettyprint.c:169
bool vect_contains_phi_p(Pvecteur)
bool vect_contains_phi_p(Pvecteur v) input : a vector output : true if v contains a PHI variable,...
Definition: effects.c:1427
#define descriptor_convex(x)
Definition: effects.h:601
#define descriptor_none_p(x)
Definition: effects.h:602
#define STRING(x)
Definition: genC.h:87
void gen_free_string_list(list ls)
Definition: list.c:564
#define append(s)
string get_comment_sentinel()
Start a single line comment.
Definition: misc.c:154
string get_comment_continuation()
Start a single line comment with continuation (blank spaces)
Definition: misc.c:167
static int * line_buffer
le buffer contenant la ligne que l'on doit lire en avance pour se rendre compte qu'on a finit de lire...
Definition: reader.c:251
void sc_rm(Psysteme ps)
void sc_rm(Psysteme ps): liberation de l'espace memoire occupe par le systeme de contraintes ps;
Definition: sc_alloc.c:277
Psysteme sc_copy(Psysteme ps)
Psysteme sc_copy(Psysteme ps): duplication d'un systeme (allocation et copie complete des champs sans...
Definition: sc_alloc.c:230
void sc_lexicographic_sort(Psysteme sc, int(*compare)(Pvecteur *, Pvecteur *))
Minimize first the lexico-graphic weight of each constraint according to the comparison function "com...
Definition: sc_unaires.c:206
#define MAX_LINE_LENGTH
maximum length of a line when prettyprinting...
void close_current_line(string, text, string)
Definition: util.c:235
#define SENTENCE(x)
newgen_unformatted_domain_defined
Definition: text.h:36
#define text_undefined
Definition: text.h:91
@ is_sentence_formatted
Definition: text.h:57
char *(* get_variable_name_t)(Variable)
Definition: vecteur-local.h:62

References append, approximation_may_p, cell_gap_p, cell_preference_p, cell_reference, close_current_line(), concatenate(), CONS, descriptor_convex, descriptor_none_p, effect_words_reference(), entity_typed_nowhere_locations_p(), FOREACH, gen_free_string_list(), get_comment_continuation(), get_comment_sentinel(), ifdebug, is_inferior_cell_descriptor_pvarval(), is_sentence_formatted, line_buffer, make_sentence(), make_text(), MAX_LINE_LENGTH, NIL, pips_assert, pips_region_user_name(), pips_user_warning, points_to_approximation, points_to_descriptor, points_to_sink, points_to_source, points_to_undefined_p, reference_variable, sc_copy(), sc_lexicographic_sort(), sc_rm(), SENTENCE, strdup(), STRING, system_sorted_text_format(), text_undefined, and vect_contains_phi_p().

Referenced by print_points_to_relation(), and text_points_to_relations().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ text_points_to_relations()

text text_points_to_relations ( points_to_list  ptl,
string  header 
)

in case of loose_prettyprint, at least one region to print?

GO: No redundant test anymore, see text_statement_array_regions

header first

Parameters
ptltl
headereader

Definition at line 349 of file points_to_prettyprint.c.

350 {
351  list l_pt_to = points_to_list_list(ptl);
352  bool bottom_p = points_to_list_bottom(ptl);
353 
354  text tpt_to = make_text(NIL);
355  /* in case of loose_prettyprint, at least one region to print? */
356  bool loose_p = get_bool_property("PRETTYPRINT_LOOSE");
357 
358  /* GO: No redundant test anymore, see text_statement_array_regions */
359  if (l_pt_to != (list) HASH_UNDEFINED_VALUE && l_pt_to != list_undefined)
360  {
361  /* header first */
363  string str_prefix = get_comment_continuation();
364  if (loose_p)
365  {
366  strcpy(line_buffer,"\n");
368  }
369  else
370  {
372  }
373  append(" ");
374  append(header);
375  if(bottom_p)
376  append(" unreachable\n");
377  else if(ENDP(l_pt_to))
378  append(" none\n");
379  else
380  append("\n");
381  ADD_SENTENCE_TO_TEXT(tpt_to,
383  strdup(line_buffer)));
384  l_pt_to = points_to_list_sort(l_pt_to);
385  FOREACH(points_to, pt_to, l_pt_to)
386  {
387  MERGE_TEXTS(tpt_to, text_points_to_relation(pt_to));
388  }
389 
390  if (loose_p)
391  ADD_SENTENCE_TO_TEXT(tpt_to,
393  strdup("\n")));
394  }
395  return tpt_to;
396 }
list points_to_list_sort(list)
Allocate a copy of ptl and sort it.
Definition: prettyprint.c:389
#define MERGE_TEXTS(r, t)
#define ADD_SENTENCE_TO_TEXT(t, p)

References ADD_SENTENCE_TO_TEXT, append, ENDP, FOREACH, get_bool_property(), get_comment_continuation(), get_comment_sentinel(), HASH_UNDEFINED_VALUE, is_sentence_formatted, line_buffer, list_undefined, make_sentence(), make_text(), MAX_LINE_LENGTH, MERGE_TEXTS, NIL, points_to_list_bottom, points_to_list_list, points_to_list_sort(), strdup(), and text_points_to_relation().

Referenced by print_code_points_to(), print_points_to_list(), and text_pt_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ text_pt_to()

text text_pt_to ( entity  ,
int  ,
statement   
)

◆ translation_transitive_closure()

list translation_transitive_closure ( cell  c,
set  translation 
)

We are done

Parameters
translationranslation

Definition at line 1702 of file interprocedural.c.

1703 {
1704  list succ = CONS(CELL, c, NIL);
1705  list n_succ = gen_copy_seq(succ);
1706  bool finished_p = false;
1707  while(!finished_p) {
1708  points_to_graph translation_g = make_points_to_graph(false, translation);
1709  // Do not worry about sharing due to NULL or UNDEFINED/NOWHERE
1710  // Potentially new successors
1711  list pn_succ = points_to_sources_to_effective_sinks(n_succ, translation_g, false);
1712  list n_succ = NIL; // Reealy new successors
1713  // FI: does not work in general because the content is not used, shallow
1714  // gen_list_and_not(&n_succ, succ);
1715  FOREACH(CELL, c, pn_succ) {
1716  if(!points_to_cell_in_list_p(c, succ))
1717  n_succ = CONS(CELL, c, n_succ);
1718  }
1719  gen_free_list(pn_succ);
1720  if(ENDP(n_succ)) {
1721  /* We are done */
1722  finished_p = true;
1723  break;
1724  }
1725  else {
1726  succ = gen_nconc(succ, n_succ);
1727  n_succ = gen_copy_seq(n_succ);
1728  }
1729  }
1730  return succ;
1731 }
list points_to_sources_to_effective_sinks(list, pt_map, bool)

References CELL, CONS, ENDP, FOREACH, gen_copy_seq(), gen_free_list(), gen_nconc(), make_points_to_graph(), NIL, points_to_cell_in_list_p(), and points_to_sources_to_effective_sinks().

Referenced by aliased_translation_p().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ type_compatible_super_cell()

cell type_compatible_super_cell ( type  t,
cell  c 
)

See if a super-cell of "c" exists witf type "t".

A supercell is a cell "nc" equals to cell "c" but with a shorter subscript list.

This function is almost identical to the previous one.

A new cell is allocated and returned.

Remove the last subscript

Definition at line 906 of file points_to_set.c.

907 {
908  cell nc = copy_cell(c);
909  reference nr = cell_any_reference(nc);
910  //list sl = reference_indices(nr);
911  bool compatible_p = false;
912 
913  do {
914  bool to_be_freed;
915  type nct = cell_to_type(nc, &to_be_freed);
916  if(type_equal_p(t, nct)) {
917  compatible_p = true;
918  if(to_be_freed) free_type(nct);
919  break;
920  }
921  else if(ENDP(reference_indices(nr))) {
922  if(to_be_freed) free_type(nct);
923  break;
924  }
925  else {
926  if(to_be_freed) free_type(nct);
927  /* Remove the last subscript */
929  gen_remove(&reference_indices(nr), l);
930  }
931  } while(true);
932 
933  ifdebug(8) {
934  bool to_be_freed;
935  type ct = cell_to_type(nc, &to_be_freed);
936  pips_debug(8, "Cell of type \"%s\" is %s included in cell of type \"%s\"\n",
939  compatible_p? "":"not");
940  if(to_be_freed) free_type(ct);
941  if(compatible_p) {
942  pips_debug(8, "Type compatible cell \"");
944  fprintf(stderr, "\"\n.");
945  }
946  }
947 
948  return nc;
949 }
void gen_remove(list *cpp, const void *o)
remove all occurences of item o from list *cpp, which is thus modified.
Definition: list.c:685

References CAR, cell_any_reference(), cell_to_type(), copy_cell(), ENDP, EXPRESSION, fprintf(), free_type(), gen_last(), gen_remove(), ifdebug, pips_debug, print_points_to_cell, reference_indices, type_equal_p(), and type_to_full_string_definition().

Referenced by find_kth_points_to_node_in_points_to_path().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ type_compatible_with_points_to_cell_p()

bool type_compatible_with_points_to_cell_p ( type  t,
cell  c 
)

A type "t" is compatible with a cell "c" if any of the enclosing cell "c'" of "c", including "c", is of type "t".

For instance, "a.next" is included in "a". It is compatible with both the type of "a" and the type of "a.next".

Remove the last subscript

Definition at line 857 of file points_to_set.c.

858 {
859  cell nc = copy_cell(c);
860  reference nr = cell_any_reference(nc);
861  //list sl = reference_indices(nr);
862  bool compatible_p = false;
863 
864  do {
865  bool to_be_freed;
866  type nct = cell_to_type(nc, &to_be_freed);
868  compatible_p = true;
869  if(to_be_freed) free_type(nct);
870  break;
871  }
872  else if(ENDP(reference_indices(nr))) {
873  if(to_be_freed) free_type(nct);
874  break;
875  }
876  else {
877  if(to_be_freed) free_type(nct);
878  /* Remove the last subscript */
880  gen_remove(&reference_indices(nr), l);
881  }
882  } while(true);
883 
884  ifdebug(8) {
885  bool to_be_freed;
886  type ct = cell_to_type(nc, &to_be_freed);
887  pips_debug(8, "Cell of type \"%s\" is %s included in cell of type \"%s\"\n",
889  compatible_p? "":"not",
891  if(to_be_freed) free_type(ct);
892  }
893 
894  free_cell(nc);
895 
896  return compatible_p;
897 }
bool concrete_array_pointer_type_equal_p(type, type)
Same as above, but resolve typedefs first.
Definition: type.c:700

References CAR, cell_any_reference(), cell_to_type(), concrete_array_pointer_type_equal_p(), copy_cell(), ENDP, EXPRESSION, free_cell(), free_type(), gen_last(), gen_remove(), ifdebug, pips_debug, reference_indices, and type_to_full_string_definition().

Referenced by find_kth_points_to_node_in_points_to_path().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ typedef_formal_parameter_to_stub_points_to()

set typedef_formal_parameter_to_stub_points_to ( type  pt,
cell  c 
)

Input : a formal parameter which is a typedef.

FI: a formal parameter cannot be a typedef, but it can be typed with a typedefined type.

maybe should be removed if we have already called ultimate type in formal_points_to_parameter()

We ignor dimensions for the being, descriptors are not implemented yet...Amira Mensi

ultimate_type() returns a wrong type for arrays. For example for type int*[10] it returns int*[10] instead of int[10].

l = points_to_init_derived(e, e2);

In fact, there should be a FOREACH to scan all elements of l_ef

free the spine

Parameters
ptt

Definition at line 1033 of file points_to_init_analysis.c.

1034 {
1040  points_to_rank);
1041  bool exact_p = !get_bool_property("POINTS_TO_NULL_POINTER_INITIALIZATION");
1042 
1043  /* maybe should be removed if we have already called ultimate type
1044  * in formal_points_to_parameter() */
1045 
1046  type upt = type_to_pointed_type(pt);
1047  r = cell_any_reference(c);
1048  e = reference_variable(r);
1049 
1050  if(type_variable_p(upt)){
1051  if(array_entity_p(e)){
1052  /* We ignor dimensions for the being, descriptors are not
1053  * implemented yet...Amira Mensi*/
1054  ;
1055  /* ultimate_type() returns a wrong type for arrays. For
1056  * example for type int*[10] it returns int*[10] instead of int[10]. */
1057  }
1058  else {
1059  basic fpb = variable_basic(type_variable(upt));
1060  if(basic_typedef_p(fpb)){
1061  entity e1 = basic_typedef(fpb);
1062  type t1 = entity_type(e1);
1063  if(entity_variable_p(e1)){
1065  if(basic_derived_p(b2)){
1066  entity e2 = basic_derived(b2);
1067  /* l = points_to_init_derived(e, e2); */
1068  type t = entity_type(e2);
1070  if(type_struct_p(t)){
1071  list l1 = type_struct(t);
1072  FOREACH(ENTITY, i, l1){
1074  if(expression_pointer_p(ef)){
1075  type ent_type = entity_type(i);
1077  ex,
1078  ef);
1080  effect ef = effect_undefined;
1081  list l_ef = NIL;
1083  true);
1084  ef = EFFECT(CAR(l_ef)); /* In fact, there should be a FOREACH to scan all elements of l_ef */
1085  gen_free_list(l_ef); /* free the spine */
1086 
1087  reference source_ref = effect_any_reference(ef);
1088  effects_free(l1);
1090  cell source_cell = make_cell_reference(source_ref);
1091  pt_to = create_stub_points_to(source_cell, ent_type, exact_p);
1092  pt_in = set_add_element(pt_in, pt_in,
1093  (void*) pt_to );
1094  }
1095  }
1096  }
1097  }
1098  }
1099  }
1100  }
1101  }
1102 
1103  return pt_in;
1104 }
#define entity_variable_p(e)
An entity_variable_p(e) may hide a typedef and hence a functional type.
#define basic_typedef_p(x)
Definition: ri.h:641
#define basic_typedef(x)
Definition: ri.h:643
Value b2
Definition: sc_gram.c:105

References array_entity_p(), b2, basic_derived, basic_derived_p, basic_typedef, basic_typedef_p, CAR, cell_any_reference(), create_stub_points_to(), EFFECT, effect_any_reference, effect_undefined, effects_free(), ENTITY, entity_intrinsic(), entity_to_expression(), entity_type, entity_undefined, entity_variable_p, expression_pointer_p(), FIELD_OPERATOR_NAME, FOREACH, gen_free_list(), generic_effects_reset_all_methods(), generic_proper_effects_of_complex_address_expression(), get_bool_property(), make_cell_reference(), MakeBinaryCall(), NIL, points_to_equal_p(), points_to_rank(), points_to_undefined, reference_undefined, reference_variable, set_add_element(), set_generic_make(), set_methods_for_proper_simple_effects(), set_private, type_struct, type_struct_p, type_to_pointed_type(), type_variable, type_variable_p, and variable_basic.

Referenced by formal_points_to_parameter().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unary_intrinsic_call_to_points_to_sinks()

list unary_intrinsic_call_to_points_to_sinks ( call  c,
pt_map  in,
bool  eval_p,
bool  constant_p 
)

We have to undo the impact of side effects performed when the arguments were analyzed for points-to information

Needed for dereferencing17.c, but not for properties03 because in the second case the dereferencing is delayed...

There is an issue with eval_p: since we are looking for sinks, we always have to dereference "a" at least once.

We have to undo the impact of side effects performed when the arguments were analyzed for points-to information

Parameters
inn
eval_pval_p
constant_ponstant_p

Definition at line 216 of file sinks.c.

217 {
218  entity f = call_function(c);
219  list al = call_arguments(c);
220  expression a = EXPRESSION(CAR(al));
221  list sinks = NIL;
222  pips_assert("One argument", gen_length(al)==1);
223  // pips_internal_error("Not implemented for %p and %p\n", c, in);
224  if (ENTITY_MALLOC_SYSTEM_P(f)) {
225  sinks = malloc_to_points_to_sinks(a, in);
226  }
227  else if (ENTITY_FREE_SYSTEM_P(f)) {
228  // FI: should be useless because free() returns void
229  sinks = CONS(CELL, make_nowhere_cell(), NIL);
230  }
231  else if(ENTITY_ADDRESS_OF_P(f)) {
232  // sinks = expression_to_constant_paths(statement_undefined, a, in);
233  if(eval_p) {
234  // sinks = expression_to_points_to_sources(a, in);
235  sinks = expression_to_points_to_cells(a, in, false, constant_p);
236  }
237  else {
238  // It is not possible in general to associate a reference to &e
239  // However, we might think of transforming &a[i][j] into a[i]
240  // and &a[0] into a...
241  sinks=NIL;
242  }
243  }
244  else if(ENTITY_DEREFERENCING_P(f)) {
245  if(pt_map_undefined_p(in)) {
247  cell c = make_anywhere_cell(t);
248  sinks = CONS(CELL, c, NIL);
249  }
250  else {
251  // FI: I do not understand why eval_p is only used for dereferencing...
252  // struct18.c sensitive to the test below
253  if(eval_p)
254  sinks = dereferencing_to_sinks(a, in, eval_p);
255  else {
256  sinks = dereferencing_to_sinks(a, in, eval_p);
257  // sinks = expression_to_points_to_sources(a, in);
258  }
259  }
260  }
261  else if(ENTITY_PRE_INCREMENT_P(f)) {
262  if(eval_p) {
263  sinks = expression_to_points_to_sinks(a, in);
264  // FI: this has already been done when the side effects are exploited
265  //expression one = int_to_expression(1);
266  //offset_cells(sinks, one);
267  //free_expression(one);
268  }
269  }
270  else if(ENTITY_PRE_DECREMENT_P(f)) {
271  if(eval_p)
272 {
273  sinks = expression_to_points_to_sinks(a, in);
274  //expression m_one = int_to_expression(-1);
275  //offset_cells(sinks, m_one);
276  //free_expression(m_one);
277  }
278  }
280  //sinks = expression_to_constant_paths(statement_undefined, a, in);
281  // arithmetic05: "q=p++;" p++ must be evaluated
282  //list sources = expression_to_points_to_sinks(a, in);
283  //if(gen_length(sources)==1) {
284  //cell source = CELL(CAR(sources));
285  if(eval_p) {
287  sinks = expression_to_points_to_sinks(a, in);
288  /* We have to undo the impact of side effects performed when the arguments were analyzed for points-to information */
291  delta = int_to_expression(-1);
292  else
293  delta = int_to_expression(1);
294  offset_points_to_cells(sinks, delta, dt);
295  free_expression(delta);
296  }
297  else {
298  if(false) {
299  /* Needed for dereferencing17.c, but not for properties03
300  because in the second case the dereferencing is
301  delayed... */
302  /* There is an issue with eval_p: since we are looking for
303  sinks, we always have to dereference "a" at least once. */
305  sinks = expression_to_points_to_sinks(a, in);
306  /* We have to undo the impact of side effects performed when the arguments were analyzed for points-to information */
309  delta = int_to_expression(-1);
310  else
311  delta = int_to_expression(1);
312  offset_points_to_cells(sinks, delta, dt);
313  free_expression(delta);
314  }
315  }
316  }
317  else {
318  // FI: to be continued
319  pips_internal_error("Unexpected unary pointer operator\n");
320  }
321 
322  return sinks;
323 }
list dereferencing_to_sinks(expression a, pt_map in, bool eval_p)
Returns "sinks", the list of cells pointed to by expression "a" according to points-to graph "in".
#define ENTITY_MALLOC_SYSTEM_P(e)
#define ENTITY_ADDRESS_OF_P(e)

References call_arguments, call_function, CAR, CELL, CONS, constant_p(), dereferencing_to_sinks(), ENTITY_ADDRESS_OF_P, ENTITY_DEREFERENCING_P, ENTITY_FREE_SYSTEM_P, ENTITY_MALLOC_SYSTEM_P, ENTITY_POST_DECREMENT_P, ENTITY_POST_INCREMENT_P, ENTITY_PRE_DECREMENT_P, ENTITY_PRE_INCREMENT_P, EXPRESSION, expression_to_points_to_cells(), expression_to_points_to_sinks(), expression_undefined, f(), free_expression(), gen_length(), int_to_expression(), make_anywhere_cell(), make_nowhere_cell(), malloc_to_points_to_sinks(), NIL, offset_points_to_cells(), pips_assert, pips_internal_error, points_to_expression_to_concrete_type(), points_to_expression_to_pointed_type(), and pt_map_undefined_p.

Referenced by intrinsic_call_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unique_location_cell_p()

bool unique_location_cell_p ( cell  c)

Does cell "c" represent a unique memory location or a set of memory locations?

This is key to decide if a points-to arc is a must or a may arc.

Is it always possible to decide when heap abstract locations are concerned?

See also cell_abstract_location_p()

Definition at line 980 of file constant-path-utils.c.

981 {
982  bool unique_p = !anywhere_cell_p(c)
984  // FI: typed or not?
985  // FI: how do you know when heap cells are unique and when they
986  // represent a set of cells?
987  && !heap_cell_p(c);
988 
989  // FI: how do you deal with arrays of pointers?
990  if(unique_p) {
992  list sl = reference_indices(r);
993  FOREACH(EXPRESSION, s, sl) {
994  if(unbounded_expression_p(s)) {
995  unique_p = false;
996  break;
997  }
998  }
999  }
1000  return unique_p;
1001 }

References anywhere_cell_p(), cell_any_reference(), cell_typed_anywhere_locations_p(), EXPRESSION, FOREACH, heap_cell_p(), reference_indices, and unbounded_expression_p().

Referenced by gen_may_constant_paths(), and gen_must_constant_paths().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unique_malloc_to_points_to_sinks()

list unique_malloc_to_points_to_sinks ( expression  e)

FI->AM: is "unique" multiple when ALIASING_ACROSS_TYPE is set to false?

FI->AM: the comments in pipsmake-rc.tex are not sufficient to understand what the choices are.

If ALIASING_ACROSS_TYPES, return an overloaded unique heap entity

We need only one HEAP abstract location: Pointers/assign03

We need one HEAP abstract location per type: Pointers/assign02

Note: we must be careful about dereferencing and fields...

Definition at line 1292 of file sinks.c.

1293 {
1294  list m = NIL;
1295  if(get_bool_property("ALIASING_ACROSS_TYPES")) {
1296  /* We need only one HEAP abstract location: Pointers/assign03 */
1298  }
1299  else {
1300  /* We need one HEAP abstract location per type: Pointers/assign02
1301  *
1302  * Note: we must be careful about dereferencing and fields...
1303  */
1305  }
1306  return m;
1307 }

References flow_sensitive_malloc_to_points_to_sinks(), get_bool_property(), and NIL.

Referenced by malloc_to_points_to_sinks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unreachable_points_to_cell_p()

bool unreachable_points_to_cell_p ( cell  c,
pt_map  ptg 
)

Can cell c be accessed via another cell?

FI: the CP lattice should be used instead

If "c" is somehow included into "sink", "c" is reachable. For instance, if c[*] is reachable than c[1] is reachable too.

But the opposite may be true: if c[1] is reachable, then c[*] is reachable.

However, if "struct s" is reachable, then so "s[next]" . But if "s[next]" is reachable does not imply that "s" is reachable.

Parameters
ptgtg

Definition at line 3373 of file points_to_set.c.

3374 {
3375  set ptg_s = points_to_graph_set(ptg);
3376  bool unreachable_p = true;
3377 
3378  SET_FOREACH(points_to, pt, ptg_s) {
3379  cell sink = points_to_sink(pt);
3380  /* FI: the CP lattice should be used instead
3381  *
3382  * If "c" is somehow included into "sink", "c" is reachable. For
3383  * instance, if c[*] is reachable than c[1] is reachable too.
3384  *
3385  * But the opposite may be true: if c[1] is reachable, then c[*]
3386  * is reachable.
3387  *
3388  * However, if "struct s" is reachable, then so "s[next]" . But if
3389  * "s[next]" is reachable does not imply that "s" is reachable.
3390  */
3391  //if(points_to_cell_equal_p(c,sink)) {
3392  if(related_points_to_cells_p(c,sink)) {
3393  unreachable_p = false;
3394  break;
3395  }
3396  }
3397 
3398  return unreachable_p;
3399 }

References points_to_graph_set, points_to_sink, related_points_to_cells_p(), and SET_FOREACH.

Referenced by freed_list_to_points_to(), list_assignment_to_points_to(), and memory_leak_to_more_memory_leaks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unstructured_to_points_to()

pt_map unstructured_to_points_to ( unstructured  u,
pt_map  pt_in 
)
Parameters
pt_int_in

Definition at line 958 of file statement.c.

959 {
960  pt_map pt_out = pt_in;
961 
962  pt_out = new_points_to_unstructured(u, pt_in, true);
963 
964  return pt_out;
965 }
pt_map new_points_to_unstructured(unstructured, pt_map, bool)

References new_points_to_unstructured().

Referenced by instruction_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ update_points_to_context_with_arc()

void update_points_to_context_with_arc ( points_to  pt)

Same as , but be careful about the arc before adding it to the points-to context.

This function is used to update the contexts when dealing with global variables at a call site.

Parameters
ptt

Definition at line 285 of file passes.c.

286 {
287  pips_assert("points_to_context is defined",
289  // Copy "pt" before it may be freed by update_points_to_graph_with_arc()
290  points_to npt = copy_points_to(pt);
292  //add_arc_to_pt_map(pt, points_to_context);
293  pips_assert("in is consistent", consistent_pt_map_p(points_to_context));
294  //add_arc_to_statement_points_to_context(npt);
296 }
pt_map update_points_to_graph_with_arc(points_to a, pt_map pt)
Instead of simply adding the new arc, make sure the consistency is not broken.
Definition: passes.c:183
void update_statement_points_to_context_with_arc(points_to)
Definition: statement.c:112

References consistent_pt_map_p, copy_points_to(), pips_assert, points_to_context, pt_map_undefined_p, update_points_to_graph_with_arc(), and update_statement_points_to_context_with_arc().

Referenced by filter_formal_context_according_to_actual_context(), new_filter_formal_context_according_to_actual_context(), and new_recursive_filter_formal_context_according_to_actual_context_for_pointer_pair().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ update_points_to_graph_with_arc()

pt_map update_points_to_graph_with_arc ( points_to  a,
pt_map  pt 
)

Instead of simply adding the new arc, make sure the consistency is not broken.

If "a" is an exact arc starting from source "s_a" and pointing to destination "d_a" and if "pt" contains may arcs or an exact arc s->d, these arcs must be removed. Vice-versa, if "a=(s_a,d_a)" is a may arc and if "pt" contain an exact arc (s,d)...

FI: I am cheating and doing exactly what I need to deal with global variables at call sites...

FI: issue with the commented out free() below: the caller doesn't know that the object may be freed and may reuse it later, for instance to make a copy of it...

Argument a is either included in pt or freed. it cannot be used after the call.

Arc a is already in relation pt

ap_b must be exact

Same source, different destinations

We are in trouble if both arcs carry approximation exact...

Arc b is less precise and mut be removed to avoid a conflict

Two may arcs: they are compatible but this may be invalidated later by another arc in pt, for isntance making a redundant.

The sources are different

Parameters
ptt

Definition at line 183 of file passes.c.

184 {
185  // Default functionality
186  // add_arc_to_pt_map(a, pt);
187 
188  cell s_a = points_to_source(a);
190  list dl = NIL; // delete list
191  list nl = NIL; // new list
192  bool found_p = false;
193  bool freed_p = false; // nl could be cleaned up instead at each free
194  set pt_s = points_to_graph_set(pt);
195 
196  SET_FOREACH(points_to, b, pt_s) {
197  cell s_b = points_to_source(b);
198  if(points_to_cell_equal_p(s_a, s_b)) {
199  cell d_a = points_to_sink(a);
200  cell d_b = points_to_sink(b);
202  found_p = true;
203  if(points_to_cell_equal_p(d_a, d_b)) {
204  if(approximation_tag(ap_a)==approximation_tag(ap_b)) {
205  /* Arc a is already in relation pt*/
206  //free_points_to(a);
207  freed_p = true;
208  }
209  else if(approximation_may_p(ap_a)) {
210  /* ap_b must be exact */
211  //free_points_to(a); // a is of no use because the context is stricter
212  freed_p = true;
213  }
214  }
215  else { /* Same source, different destinations */
216  /* We are in trouble if both arcs carry approximation exact... */
217  if(approximation_exact_p(ap_a)) {
218  if(approximation_exact_p(ap_b)) {
219  pips_internal_error("Conflicting arcs.\n"); // we are in trouble
220  }
221  else {
222  /* Arc b is less precise and mut be removed to avoid a conflict */
223  dl = CONS(POINTS_TO, b, dl);
224  }
225  }
226  else {
227  if(approximation_exact_p(ap_b)) {
228  // pips_internal_error("Conflicting arcs.\n"); // we are in trouble
229  // But the may arc is included in the exact arc already in pt
230  //free_points_to(a);
231  freed_p = true;
232  }
233  else {
234  /* Two may arcs: they are compatible but this may be
235  invalidated later by another arc in pt, for isntance
236  making a redundant. */
237  nl = CONS(POINTS_TO, a, nl);
238  }
239  }
240  }
241  }
242  else {
243  /* The sources are different */
244  ; // ignore this arc from pt
245  }
246  }
247 
248  if(found_p) {
249  FOREACH(POINTS_TO, d, dl)
250  remove_arc_from_pt_map(d, pt);
251 
252  // 0 or 1 element, which must be "a", which may have been freed
253  // after insertion in nl
254  FOREACH(POINTS_TO, n, nl)
255  if(!freed_p)
256  add_arc_to_pt_map(n, pt);
257  }
258  else
259  add_arc_to_pt_map(a, pt);
260 
261  return pt;
262 }

References add_arc_to_pt_map, approximation_exact_p, approximation_may_p, approximation_tag, CONS, FOREACH, NIL, pips_internal_error, POINTS_TO, points_to_approximation, points_to_cell_equal_p(), points_to_graph_set, points_to_sink, points_to_source, remove_arc_from_pt_map, and SET_FOREACH.

Referenced by update_points_to_context_with_arc(), and update_statement_points_to_context_with_arc().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ update_printed_points_to_list()

void update_printed_points_to_list ( statement  ,
points_to_list   
)

◆ update_statement_points_to_context_with_arc()

void update_statement_points_to_context_with_arc ( points_to  pt)
Parameters
ptt

Definition at line 112 of file statement.c.

113 {
115  //add_arc_to_pt_map(pt, in);
117  pips_assert("in is consistent", consistent_pt_map_p(in));
118 }

References consistent_pt_map_p, pips_assert, stack_head(), statement_points_to_context, and update_points_to_graph_with_arc().

Referenced by update_points_to_context_with_arc().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ upgrade_approximations_in_points_to_set()

void upgrade_approximations_in_points_to_set ( pt_map  ptm)

When arcs have been removed from a points-to relation, the approximations of remaining arcs may not correspond to the new points-to relation.

A may approximation may have become an exact approximation.

The semantics of the approximation and its many constraints must be taken into account. But they are not (yet) well formaly defined... The conditions here are:

  1. One out-going arc
  2. The source cannot be an abstract location because the concrete is not well known. Same thing for the sink.
  3. The source must be atomic, i.e. t[*] does not qualify because many concrete locations exist. Same thing for the source.
  4. What do we want to do with stubs? In an intraprocedural analysis, the concrete location is well defined. In an interprocedural analysis, depending on the call site, the stub may exist or not, or the concrete locations can be many. Also, the implementation is no symetrical: sinks are not tested. However, at run-time, the atomic stubs correspond to one concrete location, and if they are part of a exact/must arc, the call site must provide a corresponding concrete location. The arc will later be converted to a may arc if the translation is not exact.

Another question: is it OK to fix a lack of precision later or wouldn't it ne better to maintain the proper approximation on the fly, when more information is available?

Note about the implementation: Because of points-to set implementation, you cannot change approximations by side effects.

&& !stub_points_to_cell_p(source)

Parameters
ptmtm

Definition at line 3085 of file points_to_set.c.

3086 {
3087  set pts = points_to_graph_set(ptm);
3088  SET_FOREACH(points_to, pt, pts) {
3090  if(!approximation_exact_p(a)) {
3091  cell source = points_to_source(pt);
3092  if(!cell_abstract_location_p(source) // Represents may locations
3093  /* && !stub_points_to_cell_p(source)*/ // May not exist... See above
3094  && generic_atomic_points_to_cell_p(source, false)) {
3095  list sinks = points_to_source_to_any_sinks(source, ptm, false);
3096  if(gen_length(sinks)==1) {
3097  cell sink = points_to_sink(pt);
3098  if(!cell_abstract_location_p(sink)
3099  && generic_atomic_points_to_cell_p(sink, false)) {
3100  points_to npt = make_points_to(copy_cell(source),
3101  copy_cell(sink),
3104  remove_arc_from_pt_map(pt, ptm);
3105  (void) add_arc_to_pt_map(npt, ptm);
3106  }
3107  }
3108  gen_free_list(sinks);
3109  }
3110  }
3111  }
3112 }
bool cell_abstract_location_p(cell)
Definition: effects.c:273
list points_to_source_to_any_sinks(cell source, pt_map ptm, bool fresh_p)
Retrieve all possible sinks of the source.

References add_arc_to_pt_map(), approximation_exact_p, cell_abstract_location_p(), copy_cell(), gen_free_list(), gen_length(), generic_atomic_points_to_cell_p(), make_approximation_exact(), make_descriptor_none(), make_points_to(), points_to_approximation, points_to_graph_set, points_to_sink, points_to_source, points_to_source_to_any_sinks(), remove_arc_from_pt_map, and SET_FOREACH.

Referenced by any_loop_to_points_to(), filter_formal_context_according_to_actual_context(), new_filter_formal_context_according_to_actual_context(), and statement_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ user_call_condition_to_points_to()

pt_map user_call_condition_to_points_to ( call  c,
pt_map  in,
list  el,
bool  true_p 
)
Parameters
inn
ell
true_prue_p

Definition at line 2679 of file expression.c.

2680 {
2681  pt_map out = in;
2682  // FI: a call site to handle like any other user call site...
2683  // Althgouh you'd like to know if true or false is returned...
2684  //pips_user_warning("Interprocedural points-to not implemented yet. "
2685  // "Call site fully ignored.\n");
2686  //
2687  if(true_p) // Analyze the call only once?
2688  out = user_call_to_points_to(c, in, el);
2689  else // No, because side-effects must be taken into account for both branches
2690  out = user_call_to_points_to(c, in, el);
2691  return out;
2692 }

References out, and user_call_to_points_to().

Referenced by call_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ user_call_to_points_to()

points_to_graph user_call_to_points_to ( call  c,
points_to_graph  pt_in,
list  el 
)

FI: limited to the interprocedural option.

pcl =

Using memory effects does not simplify the points-to analysis, which is a preliminary analusis wrt memory effects

Parameters
pt_int_in
ell

Definition at line 106 of file interprocedural.c.

109 {
110  points_to_graph pt_out = pt_in;
111  if(!points_to_graph_bottom(pt_in)) {
112  entity f = call_function(c);
113  //list al = call_arguments(c);
114 
115  // FI: intraprocedural, use effects
116  // FI: interprocedural, check alias compatibility, generate gen and kill sets,...
117  pt_out = pt_in;
118 
119  // Code by Amira
120  //list fpcl = NIL; // Formal parameter cell list
122  if(type_functional_p(t)) {
124  /*fpcl = */points_to_cells_parameters(dl);
125  }
126  else {
127  pips_internal_error("Function has not a functional type.\n");
128  }
129 
130  /* Using memory effects does not simplify the points-to analysis,
131  which is a preliminary analusis wrt memory effects */
133  pt_out = user_call_to_points_to_interprocedural(c, pt_in);
134  }
136  pt_out = user_call_to_points_to_fast_interprocedural(c, pt_in, el);
137  }
138  else {
139  pt_out = user_call_to_points_to_intraprocedural(c, pt_in, el);
140  }
141  }
142 
143  return pt_out;
144 }
bool interprocedural_points_to_analysis_p()
Definition: passes.c:550
bool fast_interprocedural_points_to_analysis_p()
Definition: passes.c:555
pt_map user_call_to_points_to_fast_interprocedural(call c, pt_map pt_in, list csel __attribute__((unused)))
ompute the points to relations in a fast interprocedural way
list points_to_cells_parameters(list dl)
Transform a list of parameters of type "entity" to a list of cells.
pt_map user_call_to_points_to_interprocedural(call c, pt_map pt_caller)
Compute the points-to relations in a complete interprocedural way: be as accurate as possible.
pt_map user_call_to_points_to_intraprocedural(call c, pt_map pt_in, list el __attribute__((unused)))

References call_function, code_declarations, entity_basic_concrete_type(), entity_initial, f(), fast_interprocedural_points_to_analysis_p(), interprocedural_points_to_analysis_p(), pips_internal_error, points_to_cells_parameters(), points_to_graph_bottom, type_functional_p, user_call_to_points_to_fast_interprocedural(), user_call_to_points_to_interprocedural(), user_call_to_points_to_intraprocedural(), and value_code.

Referenced by call_to_points_to(), and user_call_condition_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ user_call_to_points_to_fast_interprocedural()

pt_map user_call_to_points_to_fast_interprocedural ( call  ,
pt_map  ,
list   
)

◆ user_call_to_points_to_interprocedural()

pt_map user_call_to_points_to_interprocedural ( call  c,
pt_map  pt_caller 
)

Compute the points-to relations in a complete interprocedural way: be as accurate as possible.

Not much to do if both IN and OUT are empty, except if OUT is bottom (see below)

This used to be only useful when a free occurs with the callee, since information about formal parameters used to be normally projected out.

Global variables do not require any translation in C, but it might more convenient to apply translation uniformly, without checking for global variables... Or the other way round?

Filter "pt_in" according to "pt_binded". For instance, a formal parameter can point to NULL in "pt_in" only if it also points to NULL in pt_binded. In the same way, a formal parameter can point to a points-to stub in "pt_in" only if it points to a non-NULL target in pt_binded. Also, a formal parameter cannot points exactly to UNDEFINED in "pt_binded" as it would be useless (not clear if we can remove such an arc when it is a may arc...). Finally, each formal parameter must still point to something. The mapping "binding" is augmented as needed. as well as "pt_caller" because of the on-demand approach. But "pt_binded" is not updated accordingly (?).

set pt_in_filtered =

filter_formal_context_according_to_actual_context(fpcl,

pt_in,

pt_binded,

binding);

We have to test if pt_binded is compatible with pt_in_callee

We have to start by computing all the elements of E (stubs)

See if two formal parameters can reach the same memory cell, i.e. transitive closure of binding map. We should take care of global variables too...

If no pointer is written, aliasing is not an issue

Explicitly written pointers imply some arc removals; pointer assignments directly or indirectly in the callee.

FI: pt_caller_s may have been modified implictly because the formal context has been increased according to the needs of the callee. But pt_caller_s may also have been updated by what has happened prevously when analyzing the current statement. See for instance Pointers/sort01.c.

Compute pt_kill_2

Implicitly written pointers imply some arc removals: free(), tests and exits. These are the elements of pt_kill_1, although the equations do not seem to fit at all since pt_in_filtered is not an argument...

Translation failure, incompatibility between the call site and the callee.

Some check

Use written/wpl to reduce the precision of exact arcs in pt_end. This is equivalent to pt_kill_3 and pt_gen_3.

FI: I do not understand why the precision of the write is not exploited. We may need to use mwpl instead of wpl

Some check

This cannot be performed earlier because the points-to precondition of the caller may have to be enriched according to the formal context of the callee, or the effect computation is going to fail.

Parameters
pt_callert_caller

Definition at line 1892 of file interprocedural.c.

1894 {
1895  pt_map pt_end_f = pt_caller;
1896  pips_assert("pt_caller is valid", !points_to_graph_bottom(pt_caller));
1897  pips_assert("pt_caller is consistent", consistent_pt_map_p(pt_caller));
1898  entity f = call_function(c);
1899  list al = call_arguments(c);
1901  list fpcl = points_to_cells_parameters(dl);
1902  points_to_list pts_to_in = (points_to_list)
1903  db_get_memory_resource(DBR_POINTS_TO_IN, module_local_name(f), true);
1904  list l_pt_to_in = gen_full_copy_list(points_to_list_list(pts_to_in));
1905  points_to_list pts_to_out = (points_to_list)
1906  db_get_memory_resource(DBR_POINTS_TO_OUT, module_local_name(f), true);
1907  bool out_bottom_p = points_to_list_bottom(pts_to_out);
1908 
1909  list l_pt_to_out = gen_full_copy_list(points_to_list_list(pts_to_out));
1910 
1911  /* Not much to do if both IN and OUT are empty, except if OUT is
1912  bottom (see below) */
1913  if(!(ENDP(l_pt_to_out) && ENDP(l_pt_to_in))) {
1914  // FI: this function should be moved from semantics into effects-util
1915  extern list load_body_effects(entity e);
1916  list el = load_body_effects(f);
1917  list wpl = written_pointers_set(el);
1919  set pt_caller_s = points_to_graph_set(pt_caller);
1920  set pt_in = set_assign_list(new_simple_pt_map(), l_pt_to_in);
1921  set pt_out = set_assign_list(new_simple_pt_map(), l_pt_to_out);
1922 
1923  // FI: function name... set or list?
1924  bool success_p = false;
1925  set pt_binded = compute_points_to_binded_set(f, al, pt_caller_s, &success_p);
1926  ifdebug(8) print_points_to_set("pt_binded", pt_binded);
1927 
1928  if(success_p) {
1929  set binding = new_simple_pt_map();
1930  /* This used to be only useful when a free occurs with the
1931  callee, since information about formal parameters used to be
1932  normally projected out. */
1933  points_to_translation_of_formal_parameters(fpcl, al, pt_caller, binding);
1934 
1935  /* Global variables do not require any translation in C, but it
1936  might more convenient to apply translation uniformly, without
1937  checking for global variables... Or the other way round? */
1938  //points_to_translation_of_global_variables(pt_out, pt_caller, binding);
1939 
1940  /* Filter "pt_in" according to "pt_binded". For instance, a
1941  formal parameter can point to NULL in "pt_in" only if it
1942  also points to NULL in pt_binded. In the same way, a formal
1943  parameter can point to a points-to stub in "pt_in" only
1944  if it points to a non-NULL target in pt_binded. Also, a
1945  formal parameter cannot points exactly to UNDEFINED in
1946  "pt_binded" as it would be useless (not clear if we can remove
1947  such an arc when it is a may arc...). Finally, each formal
1948  parameter must still point to something. The mapping
1949  "binding" is augmented as needed. as well as "pt_caller"
1950  because of the on-demand approach. But "pt_binded" is not
1951  updated accordingly (?). */
1952  /* set pt_in_filtered = */
1953  /* filter_formal_context_according_to_actual_context(fpcl, */
1954  /* pt_in, */
1955  /* pt_binded, */
1956  /* binding); */
1957  set pt_in_filtered =
1959  pt_in,
1960  pt_binded,
1961  binding);
1962 
1963  /* We have to test if pt_binded is compatible with pt_in_callee */
1964  /* We have to start by computing all the elements of E (stubs) */
1965  //list stubs = stubs_list(pt_in_callee, pt_out_callee);
1966  // bool compatible_p = true;
1967  // FI: I do not understand Amira's test
1968  // = sets_binded_and_in_compatible_p(stubs, fpcl, pt_binded,
1969  // pt_in_callee_filtered, pt_out_callee,
1970  // binding);
1971  /* See if two formal parameters can reach the same memory cell,
1972  * i.e. transitive closure of binding map. We should take care
1973  * of global variables too... */
1974  // compatible_p = compatible_p && !aliased_translation_p(fpcl, pt_binded);
1975 
1976  // pt_binded and pt_in are incompatible for instance because the
1977  // caller not initialized a pointer
1978  if(set_undefined_p(pt_in_filtered)) {
1979  out_bottom_p = true;
1980  }
1981  /* If no pointer is written, aliasing is not an issue */
1982  else if(ENDP(wpl) || !aliased_translation_p(fpcl, pt_binded)) {
1983 
1984  set pt_out_filtered =
1986  (pt_out, pt_in_filtered, wpl, f);
1987 
1988  /* Explicitly written pointers imply some arc removals; pointer
1989  assignments directly or indirectly in the callee. */
1990  // pt_end = set_difference(pt_end, pt_caller_s, pts_kill);
1991 
1992  /* FI: pt_caller_s may have been modified implictly because the
1993  * formal context has been increased according to the needs of
1994  * the callee. But pt_caller_s may also have been updated by what
1995  * has happened prevously when analyzing the current
1996  * statement. See for instance Pointers/sort01.c.
1997  */
1999  c_pt_caller_s = set_union(c_pt_caller_s, c_pt_caller_s, pt_caller_s);
2000 
2001  list tcwpl = points_to_cells_exact_translation(cwpl, binding, f);
2002  /* Compute pt_kill_2 */
2003  set pt_kill = compute_points_to_kill_set(tcwpl, c_pt_caller_s, binding);
2004  /* Implicitly written pointers imply some arc removals:
2005  * free(), tests and exits. These are the elements of
2006  * pt_kill_1, although the equations do not seem to fit at
2007  * all since pt_in_filtered is not an argument...
2008  */
2010  wpl,
2011  c_pt_caller_s,
2012  pt_out_filtered,
2013  binding,
2014  f);
2015  ifdebug(8) print_points_to_set("pt_kill", pt_kill);
2016 
2017  set pt_end = new_simple_pt_map();
2018  // FI: c_pr_in_s is probably pt_{caller} in the dissertation
2019  pt_end = set_difference(pt_end, c_pt_caller_s, pt_kill);
2020 
2021  set pt_gen_1 = compute_points_to_gen_set(pt_out_filtered,
2022  wpl,
2023  binding, f);
2024 
2025  if(set_undefined_p(pt_gen_1)) {
2026  /* Translation failure, incompatibility between the call site
2027  and the callee. */
2028  pips_user_warning("Incompatibility between call site and "
2029  "callee's output.\n");
2030  out_bottom_p = true;
2031  }
2032  else {
2033  pips_assert("pt_gen_1 is consistent", consistent_points_to_set(pt_gen_1));
2034 
2035  // FI->FI: Not satisfying; kludge to solve issue with Pointers/inter04
2036  // FI->FI: this causes a core dump for Pointers/formal_parameter01.c
2037  // A lot should be said about this test case, which is revealing
2038  // because of the test it contains, and because of the
2039  // pointer arithmetic, and because the useless primature
2040  // expansion of_pi_1[1] in _pi_1[*] which is semantically
2041  // correct but fuzzy as it implies possible unexisting arcs
2042  // for _pi_1[0], _pi_1[2], etc...
2043  // FI->FI: the upgrade must be postponed
2044  /*
2045  pt_map pt_gen_1_g = make_points_to_graph(false, pt_gen_1);
2046  upgrade_approximations_in_points_to_set(pt_gen_1_g);
2047 
2048  pips_assert("pt_gen_1 is consistent after upgrade",
2049  consistent_points_to_set(pt_gen_1));
2050  */
2051 
2052  /* Some check */
2053  list stubs = points_to_set_to_module_stub_cell_list(f, pt_gen_1, NIL);
2054  if(!ENDP(stubs)) {
2055  pips_internal_error("Translation failure in pt_gen_1.\n");
2056  }
2057 
2058  /* Use written/wpl to reduce the precision of exact arcs in
2059  * pt_end. This is equivalent to pt_kill_3 and pt_gen_3.
2060  *
2061  *
2062  * FI: I do not understand why the precision of the write is not
2063  * exploited. We may need to use mwpl instead of wpl
2064  *
2065  */
2066  list twpl = points_to_cells_translation(wpl, binding, f);
2067  pt_end =
2069  // FI: I keep it temporarily for debugging purposes
2070  // gen_free_list(twpl);
2071 
2072  // FI: set_union is unsafe; the union of two consistent
2073  // points-to graph is not a consistent points-to graph
2074  pt_end = set_union(pt_end, pt_end, pt_gen_1);
2075  pips_assert("pt_end is consistent", consistent_points_to_set(pt_end));
2076  ifdebug(8) print_points_to_set("pt_end =",pt_end);
2077  /* Some check */
2078  stubs = points_to_set_to_module_stub_cell_list(f, pt_end, NIL);
2079  if(!ENDP(stubs)) {
2080  pips_internal_error("Translation failure in pt_end.\n");
2081  }
2082  points_to_graph_set(pt_end_f) = pt_end;
2083  }
2084  }
2085  else {
2086  pips_user_warning("Aliasing between arguments at line %d.\n"
2087  "We would have to create a new formal context "
2088  "and to restart the points-to analysis "
2089  "and to modify the IN and OUT data structures...\n"
2090  "Or use a simpler analysis, here an intraprocedural one.\n",
2092 
2093  pt_end_f = user_call_to_points_to_intraprocedural(c, pt_caller, el);
2094  }
2095  }
2096  else
2097  out_bottom_p = true;
2098  }
2099  else {
2100  // FI: I do not think we want this warning in general!
2101  pips_user_warning("Function \"%s\" has no side effect on its formal context "
2102  "via pointer variables.\n", entity_user_name(f));
2103  }
2104 
2105  /* This cannot be performed earlier because the points-to
2106  precondition of the caller may have to be enriched according to
2107  the formal context of the callee, or the effect computation is
2108  going to fail. */
2109  if(out_bottom_p) {
2110  clear_pt_map(pt_end_f);
2111  points_to_graph_bottom(pt_end_f) = true;
2112  }
2113 
2114  return pt_end_f;
2115 }
list load_body_effects(entity e)
if(!(yy_init))
Definition: genread_lex.c:1029
list points_to_set_to_module_stub_cell_list(entity m, set s, list osl)
void add_implicitly_killed_arcs_to_kill_set(set pt_kill, list wpl, set pt_caller, set pt_out_callee_filtered, set binding, entity f)
Initial comments: add arcs of set "pt_caller" to set "pt_kill" if their origin cells are not in the l...
set filter_formal_out_context_according_to_formal_in_context(set out, set in, list wpl, entity f)
If an address has not been written, i.e.
set compute_points_to_kill_set(list written_must_translated, set pt_caller, set binding __attribute__((unused)))
Translate the "out" set into the scope of the caller.
bool aliased_translation_p(list fpcl, set translation)
See if two cells in "fpcl" point toward the same location via the transitive closure of "translation"...
set compute_points_to_gen_set(set pt_out, list Written, set binding, entity f)
Translate the out set in the scope of the caller using the binding information, but eliminate irrelev...
set compute_points_to_binded_set(entity called_func, list real_args, set pt_caller, bool *success_p)
For each actual argument "r" and its corresponding formal one "f", create the assignment "f = r;" and...
static set lower_points_to_approximations_according_to_write_effects(set pt_end, list wpl)
It is partly a kill and partly a gen operation.
list written_pointers_set(list eff)
Filter out written effects on pointers.
list points_to_cells_translation(list cl, set binding, entity f)
Allocate a new list with the translations of the cells in cl, when their translation make sense.
set new_filter_formal_context_according_to_actual_context(list fpcl, set pt_in, set pt_binded, set binding)
void points_to_translation_of_formal_parameters(list fpcl, list al, pt_map pt_in, set translation)
List al and fpcl are assumed consistent, and consistent with the formal parameter ranks.
list points_to_cells_exact_translation(list cl, set binding, entity f)
Allocate a new list with the translations of the cells in cl, when their translation make sense and i...
list certainly_written_pointers_set(list eff)
Filter out certainly written effects on pointers.
pt_map points_to_context_statement_in(void)
Definition: statement.c:127

References add_implicitly_killed_arcs_to_kill_set(), aliased_translation_p(), call_arguments, call_function, certainly_written_pointers_set(), clear_pt_map, code_declarations, compute_points_to_binded_set(), compute_points_to_gen_set(), compute_points_to_kill_set(), consistent_points_to_set(), consistent_pt_map_p, db_get_memory_resource(), ENDP, entity_initial, entity_user_name(), f(), filter_formal_out_context_according_to_formal_in_context(), gen_full_copy_list(), ifdebug, load_body_effects(), lower_points_to_approximations_according_to_write_effects(), module_local_name(), new_filter_formal_context_according_to_actual_context(), new_simple_pt_map, NIL, pips_assert, pips_internal_error, pips_user_warning, points_to_cells_exact_translation(), points_to_cells_parameters(), points_to_cells_translation(), points_to_context_statement_in(), points_to_context_statement_line_number(), points_to_graph_bottom, points_to_graph_set, points_to_list_bottom, points_to_list_list, points_to_set_to_module_stub_cell_list(), points_to_translation_of_formal_parameters(), print_points_to_set(), set_assign_list(), set_difference(), set_undefined_p, set_union(), user_call_to_points_to_intraprocedural(), value_code, and written_pointers_set().

Referenced by user_call_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ user_call_to_points_to_interprocedural_binding_set()

set user_call_to_points_to_interprocedural_binding_set ( call  c,
pt_map  pt_caller 
)

Compute the binding relations in a complete interprocedural way: be as accurate as possible.

This piece of code has been copied from user_call_to_points_to_interprocedural(), which should be modularized...

Not much to do if both IN and OUT are empty, except if OUT is bottom (see below)

For the side effect on binding

set pt_in_filtered =

filter_formal_context_according_to_actual_context(fpcl,

pt_in,

pt_binded,

binding);

Parameters
pt_callert_caller

Definition at line 1835 of file interprocedural.c.

1837 {
1838  set binding = new_simple_pt_map();
1839  pips_assert("pt_caller is valid", !points_to_graph_bottom(pt_caller));
1840  pips_assert("pt_caller is consistent", consistent_pt_map_p(pt_caller));
1841  entity f = call_function(c);
1842  list al = call_arguments(c);
1844  list fpcl = points_to_cells_parameters(dl);
1845  points_to_list pts_to_in = (points_to_list)
1846  db_get_memory_resource(DBR_POINTS_TO_IN, module_local_name(f), true);
1847  list l_pt_to_in = gen_full_copy_list(points_to_list_list(pts_to_in));
1848  points_to_list pts_to_out = (points_to_list)
1849  db_get_memory_resource(DBR_POINTS_TO_OUT, module_local_name(f), true);
1850 
1851  list l_pt_to_out = gen_full_copy_list(points_to_list_list(pts_to_out));
1852 
1853  /* Not much to do if both IN and OUT are empty, except if OUT is
1854  bottom (see below) */
1855  if(!(ENDP(l_pt_to_out) && ENDP(l_pt_to_in))) {
1856  set pt_caller_s = points_to_graph_set(pt_caller);
1857  set pt_in = set_assign_list(new_simple_pt_map(), l_pt_to_in);
1858 
1859  bool success_p = false;
1860  set pt_binded = compute_points_to_binded_set(f, al, pt_caller_s, &success_p);
1861  ifdebug(8) print_points_to_set("pt_binded", pt_binded);
1862 
1863  if(success_p) {
1864  points_to_translation_of_formal_parameters(fpcl, al, pt_caller, binding);
1865  /* For the side effect on binding */
1866  /* set pt_in_filtered = */
1867  /* filter_formal_context_according_to_actual_context(fpcl, */
1868  /* pt_in, */
1869  /* pt_binded, */
1870  /* binding); */
1871  set pt_in_filtered =
1873  pt_in,
1874  pt_binded,
1875  binding);
1876  if(!set_undefined_p(pt_in_filtered))
1877  set_free(pt_in_filtered);
1878  else {
1879  // Part of the effects can/could be translated...
1881  semantics_user_warning("Call site in \"%s\" incompatible with callee \"%s\".", entity_user_name(m), entity_user_name(f));
1882  }
1883  }
1884  }
1885  return binding;
1886 }

References call_arguments, call_function, code_declarations, compute_points_to_binded_set(), consistent_pt_map_p, db_get_memory_resource(), ENDP, entity_initial, entity_user_name(), f(), gen_full_copy_list(), get_current_module_entity(), ifdebug, module_local_name(), new_filter_formal_context_according_to_actual_context(), new_simple_pt_map, NIL, pips_assert, pips_internal_error, points_to_cells_parameters(), points_to_graph_bottom, points_to_graph_set, points_to_list_list, points_to_translation_of_formal_parameters(), print_points_to_set(), semantics_user_warning, set_assign_list(), set_free(), set_undefined_p, and value_code.

Referenced by new_substitute_stubs_in_transformer(), and substitute_stubs_in_transformer().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ user_call_to_points_to_intraprocedural()

pt_map user_call_to_points_to_intraprocedural ( call  ,
pt_map  ,
list   
)

◆ user_call_to_points_to_sinks()

list user_call_to_points_to_sinks ( call  ,
type  ,
pt_map  ,
bool   
)

◆ variable_to_pointer_locations()

list variable_to_pointer_locations ( entity  e)

variable.c

variable.c

We distinguish between scalar pointers, array of pointers and struct containing pointers and struct. Return a list of cells each containing a reference to aa pointer. These cells are used later as sources to build a points-to data structure pointing to nowhere/undefined.

M: missing recursive descent on variable_dimensions. int a[*(q=p)]

variable v = type_variable(t);

int d = (int) gen_length(variable_dimensions(v));

list sl = NIL;

int i;

for(i=0;i<d;i++) {

expression ind = make_unbounded_expression();

sl = CONS(EXPRESSION, ind, sl);

}

reference r = make_reference(e, sl);

Definition at line 66 of file variable.c.

67 {
68  list l = NIL;
69 
70  if (entity_variable_p(e)) {
71  /*AM: missing recursive descent on variable_dimensions. int a[*(q=p)]*/
72 
75  if (entity_array_p(e)) {
76  /* variable v = type_variable(t); */
77  /* int d = (int) gen_length(variable_dimensions(v)); */
78  /* list sl = NIL; */
79  /* int i; */
80  /* for(i=0;i<d;i++) { */
81  /* expression ind = make_unbounded_expression(); */
82  /* sl = CONS(EXPRESSION, ind, sl); */
83  /* } */
84  /* reference r = make_reference(e, sl); */
88  l = CONS(CELL, c, NIL);
89  }
90  else {
91  // FI: could be unified with previous case using d==0
94  l = CONS(CELL, c, NIL);
95  }
96  }
97  else if(struct_type_p(t) || array_of_struct_type_p(t)) {
99  entity ee = basic_derived(b);
101  }
102  //free_type(t); ee is used above
103  }
104 
105  return l;
106 }
list struct_variable_to_pointer_locations(entity e, entity ee)
return list of cells for pointers declared directly or indirecltly in variable "e" of type struct def...
Definition: variable.c:115

References array_of_pointers_type_p(), array_of_struct_type_p(), basic_derived, CELL, CONS, entity_array_p(), entity_basic_concrete_type(), entity_variable_p, make_cell_reference(), make_reference(), NIL, pointer_type_p(), points_to_cell_add_unbounded_subscripts(), struct_type_p(), struct_variable_to_pointer_locations(), type_variable, and variable_basic.

Referenced by declaration_statement_to_points_to(), malloc_to_points_to_sinks(), and struct_initialization_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ variable_to_sinks()

list variable_to_sinks ( entity  e,
pt_map  ptm,
bool  fresh_p 
)

Return all cells in points-to set "pts" who source is based on entity "e".

Similar to points_to_source_to_sinks, but much easier and shorter.

Parameters
ptmtm
fresh_presh_p

Definition at line 2485 of file points_to_set.c.

2486 {
2487  list sinks = NIL;
2488  set pts = points_to_graph_set(ptm);
2489  SET_FOREACH( points_to, pt, pts) {
2490  cell source = points_to_source(pt);
2491  reference sr = cell_any_reference(source);
2492  entity v = reference_variable(sr);
2493  if(e==v) {
2494  cell sc = fresh_p? copy_cell(points_to_sink(pt)) : points_to_sink(pt);
2495  sinks = CONS(CELL, sc, sinks);
2496  }
2497  }
2498  return sinks;
2499 
2500 }

References CELL, cell_any_reference(), CONS, copy_cell(), NIL, points_to_graph_set, points_to_sink, points_to_source, reference_variable, and SET_FOREACH.

Referenced by freed_list_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ whileloop_to_points_to()

pt_map whileloop_to_points_to ( whileloop  wl,
pt_map  pt_in 
)

Execute the first iteration

Parameters
wll
pt_int_in

Definition at line 604 of file statement.c.

605 {
606  pt_map pt_out = pt_in;
607  statement b = whileloop_body(wl);
609 
610  //bool store = false;
612  //pt_out = points_to_whileloop(wl, pt_in, store);
613  //pt_out = expression_to_points_to(c, pt_out, false);
614  pt_out = expression_to_points_to(c, pt_out, true);
615  pt_out = any_loop_to_points_to(b,
617  c,
619  pt_in);
620  }
621  else {
622  // pt_out = points_to_do_whileloop(wl, pt_in, store);
623  /* Execute the first iteration */
624  pt_out = statement_to_points_to(b, pt_out);
625  pt_out = any_loop_to_points_to(b,
627  c,
629  pt_out);
630  }
631 
632  //statement ws = whileloop_body(wl);
633  //list dl = statement_declarations(ws);
634  // FI: to be improved
635  //if(declaration_statement_p(ws) && !ENDP(dl))
636  // pt_out = points_to_set_block_projection(pt_out, dl);
637 
639 
640  return pt_out;
641 }
#define whileloop_evaluation(x)
Definition: ri.h:3166
#define whileloop_body(x)
Definition: ri.h:3162
#define whileloop_condition(x)
Definition: ri.h:3160
#define evaluation_before_p(x)
Definition: ri.h:1159

References any_loop_to_points_to(), consistent_points_to_graph_p(), evaluation_before_p, expression_to_points_to(), expression_undefined, pips_assert, statement_to_points_to(), whileloop_body, whileloop_condition, and whileloop_evaluation.

Referenced by instruction_to_points_to().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ words_points_to()

list words_points_to ( points_to  pt)
Parameters
ptt

Definition at line 210 of file points_to_prettyprint.c.

211 {
212  cell source = points_to_source(pt);
213  cell sink = points_to_sink(pt);
214 
215  pips_assert("there should not be preference cells in points to (source) \n",
216  !cell_preference_p(source));
217  pips_assert("there should not be preference cells in points to (sink) \n",
218  !cell_preference_p(sink));
219 
220  pips_assert("gaps not handled yet (source)", !cell_gap_p(source));
221  pips_assert("gaps not handled yet (sink)", !cell_gap_p(sink));
222 
223 
224  list w = NIL;
225 
226  reference source_ref = cell_reference(source);
227  reference sink_ref = cell_reference(sink);
229  pips_assert("approximation is not must\n", !approximation_exact_p(ap));
230 
231  w = gen_nconc(w, effect_words_reference(source_ref));
232  w = CHAIN_SWORD(w," -> ");
233  if(!nowhere_cell_p(sink)) {
234  w = gen_nconc(w, effect_words_reference(sink_ref));
235  }
236  else {
237  string undef = "undefined" ;
238  w = gen_nconc(w, CONS(STRING,undef,NIL));
239  }
240 
241  w = CHAIN_SWORD(w, approximation_may_p(ap) ? " (may)" : " (exact)" );
242  return (w);
243 }
#define CHAIN_SWORD(l, s)

References approximation_exact_p, approximation_may_p, cell_gap_p, cell_preference_p, cell_reference, CHAIN_SWORD, CONS, effect_words_reference(), gen_nconc(), NIL, nowhere_cell_p(), pips_assert, points_to_approximation, points_to_sink, points_to_source, and STRING.

+ Here is the call graph for this function:

◆ written_pointers_set()

list written_pointers_set ( list  eff)

Filter out written effects on pointers.

Parameters
effff

Definition at line 2609 of file interprocedural.c.

2609  {
2610  return generic_written_pointers_set(eff, false);
2611 }

References generic_written_pointers_set().

Referenced by user_call_to_points_to_fast_interprocedural(), and user_call_to_points_to_interprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: