PIPS
points_to_set.c File Reference
#include <stdlib.h>
#include <stdio.h>
#include "genC.h"
#include "linear.h"
#include "ri.h"
#include "effects.h"
#include "ri-util.h"
#include "effects-util.h"
#include "misc.h"
#include "text-util.h"
#include "prettyprint.h"
#include "properties.h"
#include "points_to_private.h"
#include "points-to.h"
+ Include dependency graph for points_to_set.c:

Go to the source code of this file.

Macros

#define INITIAL_SET_SIZE   10
 private implementation of points_to set. More...
 

Functions

int compare_entities_without_scope (const entity *pe1, const entity *pe2)
 cproto-generated files More...
 
entity location_entity (cell c)
 
bool locations_equal_p (cell acc1, cell acc2)
 eturn true if two acces_path are equals More...
 
int points_to_equal_p (const void *vpt1, const void *vpt2)
 returns true if two points-to arcs "vpt1" and "vpt2" are equal. More...
 
_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) More...
 
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). More...
 
string points_to_cell_name (cell source)
 Create a string which is the cell reference in C syntax. More...
 
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. More...
 
set points_to_source_projection (set pts, entity e)
 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 ptg, cell c)
 Remove all arcs in "ptg" starting from "c". More...
 
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". More...
 
set remove_points_to_cells (list cl, set g)
 All nodes, i.e. More...
 
list potential_to_effective_memory_leaks (list pmll, set res)
 A new list, "emll", is allocated. More...
 
set points_to_function_projection (set pts)
 "pts" is the points-to relation existing at the return point of a function. More...
 
bool cell_out_of_scope_p (cell c)
 Return true if a cell is out of scope. More...
 
void print_or_dump_points_to (const points_to pt, bool print_p)
 print a points-to arc for debug More...
 
void print_points_to (const points_to pt)
 
void dump_points_to (const points_to pt)
 
void print_or_dump_points_to_set (string what, set s, bool print_p)
 Print a set of points-to for debug. More...
 
void print_points_to_set (string what, set s)
 
void dump_points_to_set (string what, set s)
 
bool source_in_set_p (cell source, set s)
 test if a cell appear as a source in a set of points-to More...
 
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 More...
 
bool source_in_graph_p (cell source, points_to_graph s)
 
bool sink_in_set_p (cell sink, set s)
 test if a cell appear as a sink in a set of points-to More...
 
points_to find_arc_in_points_to_set (cell source, cell sink, pt_map ptm)
 The approximation is not taken into account. More...
 
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. More...
 
void print_points_to_path (list p)
 For debugging. More...
 
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". More...
 
cell type_compatible_super_cell (type t, cell c)
 See if a super-cell of "c" exists witf type "t". More...
 
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". More...
 
bool node_in_points_to_path_p (cell n, list p)
 
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". More...
 
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). More...
 
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". More...
 
list stub_source_to_sinks (cell source, pt_map pts, bool fresh_p)
 
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)
 
list generic_stub_source_to_sinks (cell source, pt_map pts, bool array_p, bool fresh_p)
 
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 "fc" found in the points-to set, update the subscript of the sink cell "sc" accordingly. More...
 
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". More...
 
list nowhere_source_to_sinks (cell source, pt_map pts)
 
list null_source_to_sinks (cell source, pt_map pts)
 
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. More...
 
list global_source_to_sinks (cell source, pt_map pts, bool fresh_p)
 
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. More...
 
list points_to_reference_to_translation (reference n_r, list sl, pt_map ptm, bool fresh_p)
 FI: easier it fresh_p is true... More...
 
list points_to_source_to_translations (cell source, pt_map ptm, bool fresh_p)
 Use "ptm" as a translation map. More...
 
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. More...
 
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. More...
 
list points_to_source_to_effective_sinks (cell source, pt_map ptm, bool fresh_p)
 
list points_to_source_to_some_sinks (cell source, pt_map ptm, bool fresh_p)
 May not retrieve all sinks of the source. More...
 
list points_to_source_to_any_sinks (cell source, pt_map ptm, bool fresh_p)
 Retrieve all possible sinks of the source. More...
 
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. More...
 
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. More...
 
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. More...
 
cell points_to_source_name_to_source_cell (string sn, pt_map ptm, bool fresh_p)
 
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". More...
 
list points_to_sources_to_sinks (list sources, pt_map ptm, bool fresh_p)
 
list points_to_sources_to_effective_sinks (list sources, pt_map ptm, bool fresh_p)
 
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". More...
 
int points_to_cell_to_number_of_unbounded_dimensions (cell c)
 
int points_to_reference_to_number_of_unbounded_dimensions (reference r)
 
int points_to_subscripts_to_number_of_unbounded_dimensions (list sl)
 
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"? More...
 
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". More...
 
list extended_source_to_sinks (cell sc, pt_map in)
 
list extended_sources_to_sinks (list pointed, pt_map in)
 Same as extended_source_to_sinks, but for a set of cells, "pointed". More...
 
list any_source_to_sinks (cell source, pt_map pts, bool fresh_p)
 Generalization of source_to_sinks(). More...
 
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". More...
 
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". More...
 
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. More...
 
list sources_to_sinks (list sources, pt_map ptm, bool fresh_p)
 Same as source_to_sinks, but for a list of cells. More...
 
list reference_to_sinks (reference r, pt_map in, bool fresh_p)
 
set merge_points_to_set (set s1, set s2)
 Merge two points-to sets. More...
 
set exact_to_may_points_to_set (set s)
 Change the all the exact points-to relations to may relations. More...
 
bool cell_in_list_p (cell c, const list lx)
 
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. More...
 
bool points_to_in_list_p (points_to pt, const list lx)
 
bool points_to_compare_cell (cell c1, cell c2)
 
bool points_to_compare_ptr_cell (const void *vcel1, const void *vcel2)
 
int points_to_compare_location (void *vpt1, void *vpt2)
 Order the two points-to relations according to the alphabetical order of the underlying variables. More...
 
bool consistent_points_to_arc_p (points_to a, bool constant_subscript_p)
 
bool store_independent_points_to_arc_p (points_to a)
 
bool dereferencing_free_points_to_arc_p (points_to a)
 
bool consistent_points_to_set (set s)
 make sure that set "s" does not contain redundant or contradictory elements More...
 
bool points_to_set_sharing_p (set s)
 
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. More...
 
void remove_points_to_arcs (cell source, cell sink, pt_map pt)
 
void points_to_cell_list_and (list *a, const list b)
 Compute A = A inter B: complexity in O(n2) More...
 
void free_points_to_graph_sets (points_to_graph s,...)
 Free several sets in one call. More...
 
pt_map graph_assign_list (pt_map ptm, list l)
 FI: I add functions dealing with points_to_graph variable, i.e. More...
 
pt_map merge_points_to_graphs (pt_map s1, pt_map s2)
 
pt_map points_to_graph_assign (pt_map out, pt_map in)
 
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". More...
 
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. More...
 
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. More...
 
string points_to_cell_to_string (cell c)
 
bool unreachable_points_to_cell_p (cell c, pt_map ptg)
 Can cell c be accessed via another cell? More...
 
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. More...
 
pt_map remove_unreachable_stub_vertices_in_points_to_graph (pt_map in)
 
pt_map remove_unreachable_heap_vertices_in_points_to_graph (pt_map in, bool verbose_p)
 
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. More...
 
bool consistent_points_to_graph_p (points_to_graph ptg)
 
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. More...
 
bool arc_in_points_to_set_p (points_to spt, set pts)
 Check if points-to arc "spt" belongs to points-to set "pts". More...
 
pt_map get_points_to_graph_from_statement (statement st)
 
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]. More...
 
pt_map add_arc_to_pt_map_ (points_to a, pt_map s)
 
set add_arc_to_simple_pt_map (points_to a, set s)
 
set remove_arc_from_simple_pt_map (points_to a, set s)
 
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]. More...
 

Macro Definition Documentation

◆ INITIAL_SET_SIZE

#define INITIAL_SET_SIZE   10

private implementation of points_to set.

points_to_equal_p to determine if two points_to relations are equal (same source, same sink, same relation)

points_to_rank how to compute rank for a points_to element

Definition at line 58 of file points_to_set.c.

Function Documentation

◆ 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
#define points_to_graph_set(x)
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_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:

◆ 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
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
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
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

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
reference cell_any_reference(cell)
API for reference.
Definition: effects.c:77
#define CELL(x)
CELL.
Definition: effects.h:424
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
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:

◆ 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 }
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
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_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:

◆ cell_in_list_p()

bool cell_in_list_p ( cell  c,
const list  lx 
)

found!

else no found

Parameters
lxx

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 }
#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
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
struct cons * list
Definition: newgen_types.h:106
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)
#define points_to_source(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_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
#define reference_variable(x)
Definition: ri.h:2326

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:

◆ 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
#define entity_name(x)
Definition: ri.h:2790
s1
Definition: set.c:247

References entity_name, and s1.

◆ 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)
void const char const char const int
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 gen_length(const list l)
Definition: list.c:150
size_t type_depth(type)
Number of steps to access the lowest leave of type t without dereferencing.
Definition: type.c:4880
#define reference_indices(x)
Definition: ri.h:2328

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
#define points_to_graph_bottom(x)
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
#define approximation_exact_p(x)
Definition: effects.h:369
bool set_belong_p(const set, const void *)
Definition: set.c:194
#define points_to_approximation(x)
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)
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...

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:

◆ 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 }
int get_int_property(const string)
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
points_to create_stub_points_to(cell, type, bool)
#define points_to_undefined_p(x)
#define points_to_undefined
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:

◆ 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:

◆ dump_points_to()

void dump_points_to ( const points_to  pt)
Parameters
ptt

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:

◆ 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:

◆ 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 }
bool nowhere_cell_p(cell)
Target of an undefined pointer.
Definition: effects.c:455
bool null_cell_p(cell)
Definition: effects.c:466
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
string reference_to_string(reference r)
Definition: expression.c:87
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
string words_to_string(cons *lw)
Definition: print.c:211

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:

◆ 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
#define cell_undefined
Definition: effects.h:430
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
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",...
string type_to_full_string_definition(type)
type.c
Definition: type.c:45
#define ifdebug(n)
Definition: sg.c:47

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:

◆ 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 }
void free_approximation(approximation p)
Definition: effects.c:135
points_to copy_points_to(points_to p)
POINTS_TO.
type points_to_cell_to_concrete_type(cell)
Definition: type.c:676
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
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:

◆ 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 }
#define remove_arc_from_pt_map(a, s)
#define consistent_pt_map_p(s)
static FILE * out
Definition: alias_check.c:128
cell points_to_cells_minimal_upper_bound(list)
bool points_to_cell_equal_p(cell, cell)
Definition: points_to.c:916
#define false
Definition: newgen_types.h:80
#define POINTS_TO(x)
POINTS_TO.
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:

◆ 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
bool points_to_cell_in_list_p(cell, list)
Definition: points_to.c:117
#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 }
#define pips_user_warning
Definition: misc-local.h:146
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.
Base of the parameters.
Definition: pip_interface.c:89

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 }
type make_type_variable(variable _field_)
Definition: ri.c:2715
basic copy_basic(basic p)
BASIC.
Definition: ri.c:104
variable make_variable(basic a1, list a2, list a3)
Definition: ri.c:2895
type cell_to_type(cell, bool *)
Definition: type.c:513
void points_to_cell_add_zero_subscripts(cell)
Definition: effects.c:1615
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".
void print_type(type)
For debugging.
Definition: type.c:111
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
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_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 }
#define new_pt_map()
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
return(s1)

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:

◆ 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 }
approximation make_approximation_exact(void)
Definition: effects.c:185
void free_expression(expression p)
Definition: ri.c:853
list expression_to_points_to_sinks(expression, pt_map)
The returned list contains cells used in "in".
Definition: sinks.c:1795
static int init
Maximal value set for Fortran 77.
Definition: entity.c:320
bool const_variable_p(entity)
Definition: variable.c:1687
bool scalar_type_p(type)
Definition: type.c:2955
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
expression variable_initial_expression(entity)
Returns a copy of the initial (i.e.
Definition: variable.c:1899
#define value_unknown_p(x)
Definition: ri.h:3077
#define type_undefined
Definition: ri.h:2883
#define entity_initial(x)
Definition: ri.h:2796

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:

◆ 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:

◆ 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 }
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_update(hash_table htp, const void *key, const void *val)
update key->val in htp, that MUST be pre-existent.
Definition: hash.c:491
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
#define HASH_MAP(k, v, code, ht)
Definition: newgen_hash.h:60
@ 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.
char * strdup()

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:

◆ 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_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 set_intersection(set, const set, const set)
Definition: set.c:229
set set_assign(set, const set)
Assign a set with the content of another set.
Definition: set.c:129
void set_free(set)
Definition: set.c:332
set set_clear(set)
Assign the empty set to s s := {}.
Definition: set.c:326
set set_union(set, const set, const set)
Definition: set.c:211
@ set_private
Definition: newgen_set.h:45
_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:

◆ 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:

◆ 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 }
#define cell_undefined_p(x)
Definition: effects.h:431
#define string_undefined
Definition: newgen_types.h:40
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_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:

◆ 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 }
expression make_zero_expression(void)
Make a zero expression.
Definition: expression.c:1212
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define variable_dimensions(x)
Definition: ri.h:3122

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:

◆ points_to_cell_list_and()

void points_to_cell_list_and ( list a,
const list  b 
)

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 *)
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
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 }
set set_del_element(set, const set, const void *)
Definition: set.c:265

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_string()

string points_to_cell_to_string ( cell  c)

◆ 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 }
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
string expression_to_string(expression e)
Definition: expression.c:77
int expression_to_int(expression exp)
================================================================
Definition: expression.c:2205

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 }
bool entity_abstract_location_p(entity al)
char * string
STRING.
Definition: newgen_types.h:39

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_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_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 atomic_points_to_cell_p(cell)
Is it a unique concrete memory location?
Definition: points_to.c:423
bool heap_cell_p(cell)
Any heap cell, more or less abstract or typed.
Definition: effects.c:420
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
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.
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
bool formal_parameter_p(entity)
Definition: variable.c:1489
#define functional_result(x)
Definition: ri.h:1444
#define type_functional(x)
Definition: ri.h:2952
#define entity_undefined
Definition: ri.h:2761

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  lx 
)

found!

else no found

Parameters
ptt
lxx

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_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 }
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
int tag
TAG.
Definition: newgen_types.h:92
char * int2a(int)
util.c
Definition: util.c:42

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_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 }
list gen_last(list l)
Return the last element of a list.
Definition: list.c:578
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 }
_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
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 }
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
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 gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
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 }
approximation copy_approximation(approximation p)
APPROXIMATION.
Definition: effects.c:132
points_to_graph make_points_to_graph(bool a1, set a2)
cell make_typed_nowhere_cell(type t)
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734
#define set_undefined
Definition: newgen_set.h:48
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
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)
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, 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_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_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 }
bool anywhere_cell_p(cell)
Is it an anywhere cell?
Definition: effects.c:367
bool type_equal_p(type, type)
Definition: type.c:547
#define type_functional_p(x)
Definition: ri.h:2950

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_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 }
bool unbounded_expression_p(expression e)
Definition: expression.c:4329

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:

◆ 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_or_dump_points_to()

void print_or_dump_points_to ( const points_to  pt,
bool  print_p 
)

print a points-to arc for debug

Parameters
ptt
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 }
bool cell_typed_anywhere_locations_p(cell c)
test if a cell is the bottom of the lattice
string approximation_to_string(approximation)
Definition: prettyprint.c:458
#define MODULE_SEP_STRING
Definition: naming-local.h:30
#define points_to_domain_number(x)
void print_reference(reference r)
Definition: expression.c:142
#define points_to_domain
Definition: print.c:367
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

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
int set_size(const set)
returns the number of items in s.
Definition: set.c:359

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  pt)
Parameters
ptt

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_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 }
#define print_points_to_cell(x)
Definition: print.c:377

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_set()

◆ 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 }
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
static int tc
Internal variables
Definition: reindexing.c:107
#define PLUS_OPERATOR_NAME
#define binary_intrinsic_expression(name, e1, e2)
value EvalExpression(expression e)
Evaluate statically an expression.
Definition: eval.c:108
bool extended_integer_constant_expression_p(expression e)
More extensive than next function.
Definition: expression.c:858
bool zero_expression_p(expression e)
Definition: expression.c:1217
bool expression_equal_p(expression e1, expression e2)
Syntactic equality e1==e2.
Definition: expression.c:1347
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
bool expression_lists_equal_p(list l1, list l2)
Definition: expression.c:1405
#define value_constant(x)
Definition: ri.h:3073
#define reference_undefined
Definition: ri.h:2302
#define constant_int(x)
Definition: ri.h:850
#define value_constant_p(x)
Definition: ri.h:3071
#define constant_int_p(x)
Definition: ri.h:848
#define expression_undefined
Definition: ri.h:1223
#define expression_undefined_p(x)
Definition: ri.h:1224

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 }
reference copy_reference(reference p)
REFERENCE.
Definition: ri.c:2047

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:

◆ refine_points_to_cell_subscripts()

static void refine_points_to_cell_subscripts ( cell  sc,
cell  ec,
cell  fc 
)
static

If the subscripts of the effective cell source "ec" are more precise than the subscripts of the cell "fc" found in the points-to set, update the subscript of the sink cell "sc" accordingly.

For instance, if "ec==q[0]" and "fc=q[*]" and "sc=_q_1[*]", transform "sc" into "_q_1[0]".

Also, if "ec==_nl_1[next]" and "fc=_nl_1" and "sc=_nl_1", transform "sc" into "_nl_1[next]"

This function has not been designed properly. It is extended as needed...

Take care of subscripts

Take care of fields

We are in trouble for the time being. Here is an example:

Arc is: "p[*]->*HEAP*_l_72". Where does p[0] point tp?

Definition at line 1270 of file points_to_set.c.

1271 {
1272  reference rsc = cell_any_reference(sc);
1273  reference rec = cell_any_reference(ec);
1274  reference rfc = cell_any_reference(fc);
1275  list slrsc = reference_indices(rsc);
1276 
1277  if(true || !ENDP(slrsc)) { // The first loop will be skipped
1278  list slrec = reference_indices(rec);
1279  list slrfc = reference_indices(rfc);
1280  list cslrsc = slrsc;
1281  list cslrec = slrec;
1282  list cslrfc = slrfc;
1283  /* Take care of subscripts */
1284  for( ; !ENDP(cslrsc) && !ENDP(cslrec) && !ENDP(cslrfc);
1285  POP(cslrsc), POP(cslrec), POP(cslrfc)) {
1286  expression ecs = EXPRESSION(CAR(cslrec));
1287  expression fcs = EXPRESSION(CAR(cslrfc));
1288  // FI: a less crude test would save some work, but this is not
1289  // the point right now...
1290  if(unbounded_expression_p(fcs)) {
1291  free_expression(EXPRESSION(CAR(cslrsc)));
1292  EXPRESSION_(CAR(cslrsc)) = copy_expression(ecs);
1293  }
1294  }
1295  if(!ENDP(cslrec)) {
1296  //pips_assert("cslrsc and cslrfc are empty",
1297  // ENDP(cslrsc) && ENDP(cslrfc));
1298  if(ENDP(cslrsc) && ENDP(cslrfc)) {
1299  /* Take care of fields */
1300  list nsl = gen_full_copy_list(cslrec);
1301  reference_indices(rsc) = gen_nconc(reference_indices(rsc), nsl);
1302  }
1303  else {
1304  /* We are in trouble for the time being. Here is an example:
1305  *
1306  * Arc is: "p[*]->*HEAP*_l_72". Where does p[0] point tp?
1307  */
1308  ; // Keep the current target unchanged
1309  }
1310  }
1311  }
1312 }
#define EXPRESSION_(x)
Definition: ri.h:1220

References CAR, cell_any_reference(), copy_expression(), ENDP, EXPRESSION, EXPRESSION_, free_expression(), gen_full_copy_list(), gen_nconc(), POP, reference_indices, and unbounded_expression_p().

Referenced by generic_points_to_source_to_sinks().

+ 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_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 }
void gen_list_and_not(list *a, const list b)
Compute A = A inter non B:
Definition: list.c:963
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 }
void free_points_to(points_to p)

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 }
cell make_nowhere_cell()
This file contains all the operators defining constant paths :

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:

◆ 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:

◆ 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:

◆ 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 }
#define pt_map_undefined_p(pt)
#define clear_pt_map(pt)
bool entity_typed_anywhere_locations_p(entity e)
Test if an entity is the bottom of the lattice.
cell make_anywhere_cell(type t)
bool null_pointer_value_cell_p(cell)
int points_to_context_statement_line_number(void)
Definition: statement.c:120
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)
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

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:

◆ 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:

◆ 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:

◆ 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:

◆ 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:

◆ 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 generic_atomic_points_to_cell_p(cell, bool)
Is it a unique concrete memory location?
Definition: points_to.c:452
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:

◆ 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: