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

Go to the source code of this file.

Functions

cell make_anywhere_points_to_cell (type t)
 Function storing points to information attached to a statement. More...
 
bool formal_parameter_points_to_cell_p (cell c)
 
bool stub_points_to_cell_p (cell c)
 
bool points_to_cell_in_list_p (cell c, list L)
 
list merge_points_to_cell_lists (list l1, list l2)
 Add in "l1" elements of "l2" that are not yet in "l1". More...
 
bool related_points_to_cell_in_list_p (cell c, list L)
 Two cells are related if they are based on the same entity. More...
 
bool related_points_to_cells_p (cell c1, cell c2)
 
void fprint_points_to_cell (FILE *f __attribute__((unused)), cell c)
 Debug: print a cell list for points-to. More...
 
void print_points_to_cell (cell c)
 Debug: use stderr. More...
 
void print_points_to_cells (list cl)
 Debug. More...
 
bool field_reference_expression_p (expression e)
 Check if expression "e" is a reference to a struct field. More...
 
int points_to_reference_to_final_dimension (reference r)
 Compute the number of array subscript at the end of a points_to_reference. More...
 
void points_to_reference_update_final_subscripts (reference r, list nsl)
 Substitute the subscripts "sl" in points-to reference "r" just after the last field subscript by "nsl". More...
 
list points_to_reference_to_typed_index (reference r, type t)
 Look for the index in "r" that corresponds to a pointer of type "t" and return the corresponding element list. More...
 
bool atomic_points_to_cell_p (cell c)
 Is it a unique concrete memory location? More...
 
bool generic_atomic_points_to_cell_p (cell c, bool strict_p)
 Is it a unique concrete memory location? More...
 
bool generic_atomic_points_to_reference_p (reference r, bool strict_p)
 Is it a unique concrete memory location? More...
 
bool atomic_points_to_reference_p (reference r)
 
bool points_to_cells_intersect_p (cell lc, cell rc)
 points-to cells use abstract addresses, hence the proper comparison is an intersection. More...
 
cell points_to_cells_minimal_upper_bound (list cl __attribute__((unused)))
 Allocate a cell that is the minimal upper bound of the cells in list "cl" according to the points-to cell lattice... More...
 
entity points_to_cells_minimal_module_upper_bound (list cl __attribute__((unused)))
 
type points_to_cells_minimal_type_upper_bound (list cl __attribute__((unused)))
 
reference points_to_cells_minimal_reference_upper_bound (entity m __attribute__((unused)), type t __attribute__((unused)), list cl __attribute__((unused)))
 
bool points_to_array_reference_p (reference r)
 Is this a reference to an array or a reference to a pointer? This is not linked to the type of the reference, as a reference may be a pointer, such as "a[10]" when "a" is declared int "a[10][20]". More...
 
type points_to_array_reference_to_type (reference r)
 If this is an array reference, what is the type of the underlying array type? More...
 
void complete_points_to_reference_with_fixed_subscripts (reference r, bool zero_p)
 Add a set of zero subscripts to a constant memory path reference "r" by side effect. More...
 
void complete_points_to_reference_with_zero_subscripts (reference r)
 
bool cells_must_point_to_null_p (list cl)
 
bool cells_may_not_point_to_null_p (list cl)
 
bool cell_points_to_non_null_sink_in_set_p (cell source, set pts)
 A set of functions called cell_points_to_xxxx(cell s, set pts) where set pts is a points-to relation set. More...
 
bool cell_points_to_nowhere_sink_in_set_p (cell source, set pts)
 
bool cell_must_point_to_nowhere_sink_in_set_p (cell source, set pts)
 How are array handled in pts? do we have arcs "a->a"? More...
 
bool cell_points_to_null_sink_in_set_p (cell source, set pts)
 
bool points_to_cell_equal_p (cell c1, cell c2)
 
bool similar_arc_in_points_to_set_p (points_to spt, set in, approximation *pa)
 See if an arc like "spt" exists in set "in", regardless of its approximation. More...
 
list points_to_cell_to_upper_bound_points_to_cells (cell c)
 Return a list of cells that are larger than cell "c" in the points-to cell lattice. More...
 
list points_to_cells_to_upper_bound_points_to_cells (list cl)
 Add to list "l" cells that are upper bound cells of the cells already in list "l" and return list "l". More...
 
bool exact_points_to_subscript_list_p (list sl)
 See if the subscript list sl is precise, i.e. More...
 
bool compatible_points_to_subscripts_p (expression s1, expression s2)
 Two subscript are compatible if they are equal or if one of them is unbounded. More...
 
points_to points_to_with_stripped_sink (points_to pt, int(*line_number_func)(void))
 The value of the source can often be expressed with different subscript lists. More...
 
bool recursive_store_independent_points_to_reference_p (type t, list sl)
 
bool store_independent_points_to_reference_p (reference r)
 Functions for points-to references, the kind of references used in points-to cells. More...
 
bool constant_points_to_indices_p (list sl)
 check that the subscript list il is either empty or made of integers or fields. More...
 
bool store_independent_points_to_indices_p (list sl)
 check that the subscript list il is either empty or made of integers or fields or unbounded entity "*". More...
 

Function Documentation

◆ atomic_points_to_cell_p()

bool atomic_points_to_cell_p ( cell  c)

Is it a unique concrete memory location?

Plus NULL? No doubt about the value of the pointer...

Plus undefined? No doubt about the indeterminate value of the pointer according to C standard...

Definition at line 423 of file points_to.c.

424 {
426  bool atomic_p = null_cell_p(c)
427  || nowhere_cell_p(c) // FI: added for EffectsWithPointsTo/call30.c
429 
430  // FI: atomic_p should be false for all abstract locations
431  // This is dealt with by atomic_points_to_reference_p()
432  /*
433  if(atomic_p && (heap_cell_p(c) || all_heap_locations_cell_p(c)))
434  atomic_p = false;
435 
436  if(atomic_p) {
437  atomic_p = !cell_abstract_location_p(c);
438  }
439  */
440 
441  return atomic_p;
442 }
bool atomic_points_to_reference_p(reference r)
Definition: points_to.c:519
reference cell_any_reference(cell)
API for reference.
Definition: effects.c:77
bool nowhere_cell_p(cell)
Target of an undefined pointer.
Definition: effects.c:455
bool null_cell_p(cell)
Definition: effects.c:466

References atomic_points_to_reference_p(), cell_any_reference(), nowhere_cell_p(), and null_cell_p().

Referenced by atomic_effect_p(), compute_points_to_gen_set(), compute_points_to_kill_set(), equal_condition_to_points_to(), freed_list_to_points_to(), non_equal_condition_to_points_to(), null_equal_condition_to_points_to(), and points_to_function_projection().

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

◆ atomic_points_to_reference_p()

bool atomic_points_to_reference_p ( reference  r)

Definition at line 519 of file points_to.c.

520 {
521  return generic_atomic_points_to_reference_p(r, true);
522 }
bool generic_atomic_points_to_reference_p(reference r, bool strict_p)
Is it a unique concrete memory location?
Definition: points_to.c:489

References generic_atomic_points_to_reference_p().

Referenced by atomic_points_to_cell_p(), and substitute_stubs_in_transformer().

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

◆ cell_must_point_to_nowhere_sink_in_set_p()

bool cell_must_point_to_nowhere_sink_in_set_p ( cell  source,
set  pts 
)

How are array handled in pts? do we have arcs "a->a"?

Parameters
sourceource
ptsts

Definition at line 870 of file points_to.c.

871 {
872  bool nowhere_p = false;
874  pips_assert("The cell is a pointer", !array_type_p(st) && pointer_type_p(st));
875  //type st = points_to_cell_to_concrete_type(source);
876  //if(!array_type_p(st) && pointer_type_p(st)) {
877  SET_FOREACH(points_to, pt, pts) {
878  cell pt_source = points_to_source(pt);
879  if(cell_equal_p(pt_source, source)) {
880  //if(cell_equivalent_p(pt_source, source)) {
881  cell pt_sink = points_to_sink(pt);
882  if(null_cell_p(pt_sink))
883  ;
884  else if(nowhere_cell_p(pt_sink)) {
886  nowhere_p = approximation_must_p(ap) || approximation_exact_p(ap);
887  break;
888  }
889  else {
890  ;
891  }
892  }
893  }
894  //}
895  return nowhere_p;
896 }
bool cell_equal_p(cell, cell)
CELLS.
Definition: effects.c:1226
type points_to_cell_to_concrete_type(cell)
Definition: type.c:676
#define approximation_exact_p(x)
Definition: effects.h:369
#define approximation_must_p(x)
Definition: effects.h:366
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
#define points_to_approximation(x)
#define points_to_sink(x)
#define points_to_source(x)
bool array_type_p(type)
Definition: type.c:2942
bool pointer_type_p(type)
Check for scalar pointers.
Definition: type.c:2993

References approximation_exact_p, approximation_must_p, array_type_p(), cell_equal_p(), nowhere_cell_p(), null_cell_p(), pips_assert, pointer_type_p(), points_to_approximation, points_to_cell_to_concrete_type(), points_to_sink, points_to_source, and SET_FOREACH.

Referenced by recursive_filter_formal_context_according_to_actual_context().

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

◆ cell_points_to_non_null_sink_in_set_p()

bool cell_points_to_non_null_sink_in_set_p ( cell  source,
set  pts 
)

A set of functions called cell_points_to_xxxx(cell s, set pts) where set pts is a points-to relation set.

The definition domain of these functions is key to their use:

  1. if the type of the source s is not a pointer type, should we return false or abort because s is not in the definition domain?
  2. if source s does not appear at all in pts, should we return false or abort because s is not in the definition domain?

If both conditions are selected, the resulting definition domain is the definition domain of the mapping pts.

If a more relaxed definition domain is sometimes useful, then strict and non-strict versions of these functions should be provided, with a clear semantics for their true and false results.

Because cell s may point to one or many cells in pts, which is a relation and not a mapping, the caller may be interested in a may or must point. The information may be convened directly by using distinct function names, cell_must_points_to_xxxx or cell_may_points_to_xxxx, or by adding a pointer to a boolean, exact_p, in the function profiles, which may save time by not looping twice on pts arcs.

This can be implemented using the approximation information of the arcs in pts... if it is trusted. Or recomputed from the arcs in pts.

Flexibility is also introduced by the use of cell_equivalent_p() instead of cell_equal_p(). If the former is used, cells derived from cell s are considered when s if not a pointer. This leads to weird behaviors. For instance, if the source s is a struct, s.f1 and s.f2 will be considered. If s.f1 points to some concrete location and s.f2 points to nowhere (undefined pointer), what result should be returned? The advantage is that the caller does not have to generate s.f1 and s.f2 which are simply found in set pts. Does cell "source" points toward a non null fully defined cell in points-to set pts?

The function name is not well chosen. Something like cell_points_to_defined_cell_p()/

Parameters
sourceource
ptsts

Definition at line 822 of file points_to.c.

823 {
824  bool non_null_p = false;
826  pips_assert("The cell is a pointer", !array_type_p(st) && pointer_type_p(st));
827  SET_FOREACH(points_to, pt, pts) {
828  cell pt_source = points_to_source(pt);
829  if(cell_equal_p(pt_source, source)) {
830  //if(cell_equivalent_p(pt_source, source)) {
831  cell pt_sink = points_to_sink(pt);
832  if(null_cell_p(pt_sink))
833  ;
834  else if(nowhere_cell_p(pt_sink))
835  ;
836  else {
837  non_null_p = true;
838  break;
839  }
840  }
841  }
842  return non_null_p;
843 }

References array_type_p(), cell_equal_p(), nowhere_cell_p(), null_cell_p(), pips_assert, pointer_type_p(), points_to_cell_to_concrete_type(), points_to_sink, points_to_source, and SET_FOREACH.

Referenced by filter_formal_context_according_to_actual_context(), new_filter_formal_context_according_to_actual_context(), and recursive_filter_formal_context_according_to_actual_context().

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

◆ cell_points_to_nowhere_sink_in_set_p()

bool cell_points_to_nowhere_sink_in_set_p ( cell  source,
set  pts 
)
Parameters
sourceource
ptsts

Definition at line 845 of file points_to.c.

846 {
847  bool nowhere_p = false;
849  pips_assert("The cell is a pointer", !array_type_p(st) && pointer_type_p(st));
850  SET_FOREACH(points_to, pt, pts) {
851  cell pt_source = points_to_source(pt);
852  if(cell_equal_p(pt_source, source)) {
853  //if(cell_equivalent_p(pt_source, source)) {
854  cell pt_sink = points_to_sink(pt);
855  if(null_cell_p(pt_sink))
856  ;
857  else if(nowhere_cell_p(pt_sink)) {
858  nowhere_p = true;
859  break;
860  }
861  else {
862  ;
863  }
864  }
865  }
866  return nowhere_p;
867 }

References array_type_p(), cell_equal_p(), nowhere_cell_p(), null_cell_p(), pips_assert, pointer_type_p(), points_to_cell_to_concrete_type(), points_to_sink, points_to_source, and SET_FOREACH.

Referenced by recursive_filter_formal_context_according_to_actual_context().

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

◆ cell_points_to_null_sink_in_set_p()

bool cell_points_to_null_sink_in_set_p ( cell  source,
set  pts 
)
Parameters
sourceource
ptsts

Definition at line 898 of file points_to.c.

899 {
900  bool null_p = false;
902  pips_assert("The cell is a pointer", !array_type_p(st) && pointer_type_p(st));
903  SET_FOREACH(points_to, pt, pts) {
904  cell pt_source = points_to_source(pt);
905  if(cell_equal_p(pt_source, source)) {
906  cell pt_sink = points_to_sink(pt);
907  if(null_cell_p(pt_sink)) {
908  null_p = true;
909  break;
910  }
911  }
912  }
913  return null_p;
914 }

References array_type_p(), cell_equal_p(), null_cell_p(), pips_assert, pointer_type_p(), points_to_cell_to_concrete_type(), points_to_sink, points_to_source, and SET_FOREACH.

Referenced by recursive_filter_formal_context_according_to_actual_context().

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

◆ cells_may_not_point_to_null_p()

bool cells_may_not_point_to_null_p ( list  cl)
Parameters
cll

Definition at line 763 of file points_to.c.

764 {
765  bool may_not_p = true;
766  pips_assert("The input list is not empty", !ENDP(cl));
767  FOREACH(CELL, c, cl) {
768  if(null_cell_p(c) || nowhere_cell_p(c)) {
769  may_not_p = false;
770  break;
771  }
772  }
773  return may_not_p;
774 }
#define CELL(x)
CELL.
Definition: effects.h:424
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#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

References CELL, ENDP, FOREACH, nowhere_cell_p(), null_cell_p(), and pips_assert.

Referenced by intrinsic_call_condition_to_points_to().

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

◆ cells_must_point_to_null_p()

bool cells_must_point_to_null_p ( list  cl)
Parameters
cll

Definition at line 750 of file points_to.c.

751 {
752  bool must_p = true;
753  pips_assert("The input list is not empty", !ENDP(cl));
754  FOREACH(CELL, c, cl) {
755  if(!null_cell_p(c)) {
756  must_p = false;
757  break;
758  }
759  }
760  return must_p;
761 }

References CELL, ENDP, FOREACH, null_cell_p(), and pips_assert.

Referenced by intrinsic_call_condition_to_points_to().

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

◆ compatible_points_to_subscripts_p()

bool compatible_points_to_subscripts_p ( expression  s1,
expression  s2 
)

Two subscript are compatible if they are equal or if one of them is unbounded.

In the ponts-to context s1 and s2 should be either integer constants or field references.

Parameters
s11
s22

Definition at line 1041 of file points_to.c.

1042 {
1043  bool compatible_p = true;
1044  bool u1 = unbounded_expression_p(s1);
1045  if(!u1) {
1046  bool u2 = unbounded_expression_p(s2);
1047  if(!u2) {
1048  /* In the ponts-to context s1 and s2 should be either integer
1049  constants or field references. */
1050  compatible_p = expression_equal_p(s1, s2);
1051  }
1052  }
1053  return compatible_p;
1054 }
bool expression_equal_p(expression e1, expression e2)
Syntactic equality e1==e2.
Definition: expression.c:1347
bool unbounded_expression_p(expression e)
Definition: expression.c:4329
s1
Definition: set.c:247

References expression_equal_p(), s1, and unbounded_expression_p().

Referenced by points_to_cell_translation().

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

◆ complete_points_to_reference_with_fixed_subscripts()

void complete_points_to_reference_with_fixed_subscripts ( reference  r,
bool  zero_p 
)

Add a set of zero subscripts to a constant memory path reference "r" by side effect.

Used when a partial array reference must be converted into a reference to the first array element (zero_p==true) or to any element (zero_p==false).

The difficulty lies with field subscripts...

Find the current number of effective subscripts: is there a field subscript somewhere?

FI: this may happen when reference "r" is not a constant memory path

Parameters
zero_pero_p

Definition at line 696 of file points_to.c.

697 {
698  type t = type_undefined;
699 
700  // FI: this assert makes sense within the ri-util framework but is
701  // too strong for the kind of references used in effects-util
702  // pips_assert("scalar type", ENDP(reference_indices(r)));
703 
704  /* Find the current number of effective subscripts: is there a field
705  subscript somewhere? */
706  list sl = reference_indices(r);
707  entity v = reference_variable(r);
708  list rsl = gen_nreverse(sl); // sl is no longer available
709  int i = 0;
710  bool field_found_p = false;
711 
712  FOREACH(EXPRESSION, se, rsl) {
713  if(field_expression_p(se)) {
717  field_found_p = true;
718  break;
719  }
720  i++;
721  }
722 
723  if(!field_found_p)
725 
726  variable vt = type_variable(t);
727  list dl = variable_dimensions(vt);
728  int d = (int) gen_length(dl);
729 
730  /* FI: this may happen when reference "r" is not a constant memory path */
731  pips_assert("Not too many subscripts wrt the type.\n", i<=d);
732 
733  list nsl = NIL; // subscript list
734  int j;
735  for(j=i+1;j<=d;j++) {
737  // reference_indices(r) = CONS(EXPRESSION, s, reference_indices(r));
738  nsl = CONS(EXPRESSION, s, nsl);
739  }
740 
743 }
void const char const char const int
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
expression make_unbounded_expression()
Definition: expression.c:4339
bool field_expression_p(expression e)
The expression is of kind "a", where "a" is a field of some struct "s".
Definition: expression.c:498
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
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
type entity_basic_concrete_type(entity)
retrieves or computes and then returns the basic concrete type of an entity
Definition: type.c:3677
#define reference_variable(x)
Definition: ri.h:2326
#define type_variable(x)
Definition: ri.h:2949
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define reference_indices(x)
Definition: ri.h:2328
#define variable_dimensions(x)
Definition: ri.h:3122
#define type_undefined
Definition: ri.h:2883
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

References CONS, entity_basic_concrete_type(), EXPRESSION, expression_reference(), f(), field_expression_p(), FOREACH, gen_length(), gen_nconc(), gen_nreverse(), int, int_to_expression(), make_unbounded_expression(), NIL, pips_assert, reference_indices, reference_variable, type_undefined, type_variable, and variable_dimensions.

Referenced by complete_points_to_reference_with_zero_subscripts().

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

◆ complete_points_to_reference_with_zero_subscripts()

void complete_points_to_reference_with_zero_subscripts ( reference  r)

Definition at line 745 of file points_to.c.

746 {
748 }
void complete_points_to_reference_with_fixed_subscripts(reference r, bool zero_p)
Add a set of zero subscripts to a constant memory path reference "r" by side effect.
Definition: points_to.c:696

References complete_points_to_reference_with_fixed_subscripts().

Referenced by dereferencing_subscript_to_points_to(), process_casted_sinks(), process_casted_sources(), and subscript_to_points_to_sinks().

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

◆ constant_points_to_indices_p()

bool constant_points_to_indices_p ( list  sl)

check that the subscript list il is either empty or made of integers or fields.

Parameters
sll

Definition at line 1272 of file points_to.c.

1273 {
1274  bool constant_p = true;
1275 
1276  FOREACH(EXPRESSION, se, sl) {
1278  syntax s = expression_syntax(se);
1279  if(syntax_reference_p(s)) {
1280  reference r = syntax_reference(s);
1282  if(!entity_field_p(f)) {
1283  constant_p = false;
1284  break;
1285  }
1286  }
1287  else {
1288  constant_p = false;
1289  break;
1290  }
1291  }
1292  }
1293  return constant_p;
1294 }
static bool constant_p(entity e)
This function return a bool indicating if related entity e represents a constant.
bool entity_field_p(entity e)
e is the field of a structure
Definition: entity.c:857
bool extended_integer_constant_expression_p(expression e)
More extensive than next function.
Definition: expression.c:858
#define syntax_reference_p(x)
Definition: ri.h:2728
#define syntax_reference(x)
Definition: ri.h:2730
#define expression_syntax(x)
Definition: ri.h:1247

References constant_p(), entity_field_p(), EXPRESSION, expression_syntax, extended_integer_constant_expression_p(), f(), FOREACH, reference_variable, syntax_reference, and syntax_reference_p.

+ Here is the call graph for this function:

◆ exact_points_to_subscript_list_p()

bool exact_points_to_subscript_list_p ( list  sl)

See if the subscript list sl is precise, i.e.

if is does not contain any unbounded expression.

It is assumed that it is a points-to subscript list. Each subscript is either an integer constant, or a field reference or an unbounded expression.

This function may have been defined several times...

Parameters
sll

Definition at line 1027 of file points_to.c.

1028 {
1029  bool exact_p = true;
1030  FOREACH(EXPRESSION, s, sl) {
1031  if(unbounded_expression_p(s)) {
1032  exact_p = false;
1033  break;
1034  }
1035  }
1036  return exact_p;
1037 }

References EXPRESSION, FOREACH, and unbounded_expression_p().

+ Here is the call graph for this function:

◆ field_reference_expression_p()

bool field_reference_expression_p ( expression  e)

Check if expression "e" is a reference to a struct field.

Definition at line 224 of file points_to.c.

225 {
226  bool field_p = false;
227  syntax s = expression_syntax(e);
228  if(syntax_reference_p(s)) {
231  field_p = entity_field_p(f);
232  }
233  return field_p;
234 }

References entity_field_p(), expression_syntax, f(), reference_variable, syntax_reference, and syntax_reference_p.

Referenced by points_to_array_reference_p(), points_to_array_reference_to_type(), points_to_reference_to_final_dimension(), points_to_reference_update_final_subscripts(), and reduce_cell_to_pointer_type().

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

◆ formal_parameter_points_to_cell_p()

bool formal_parameter_points_to_cell_p ( cell  c)

Definition at line 99 of file points_to.c.

100 {
101  bool formal_p = true;
103  entity v = reference_variable(r);
104  formal_p = formal_parameter_p(v);
105  return formal_p;
106 }
bool formal_parameter_p(entity)
Definition: variable.c:1489

References cell_any_reference(), formal_parameter_p(), and reference_variable.

Referenced by points_to_to_context_points_to().

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

◆ fprint_points_to_cell()

void fprint_points_to_cell ( FILE *f   __attribute__(unused),
cell  c 
)

Debug: print a cell list for points-to.

Parameter f is not useful in a debugging context.

Definition at line 178 of file points_to.c.

179 {
180  int dn = cell_domain_number(c);
181 
182  // For debugging with gdb, dynamic type checking
183  if(dn==cell_domain) {
184  if(cell_undefined_p(c))
185  fprintf(stderr, "cell undefined\n");
186  else {
188  print_reference(r);
189  }
190  }
191  else
192  fprintf(stderr, "Not a Newgen cell object\n");
193 }
#define cell_undefined_p(x)
Definition: effects.h:431
#define cell_domain_number(x)
Definition: effects.h:465
#define cell_domain
newgen_cell_interpretation_domain_defined
Definition: effects.h:85
void print_reference(reference r)
Definition: expression.c:142
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...

References cell_any_reference(), cell_domain, cell_domain_number, cell_undefined_p, fprintf(), and print_reference().

Referenced by print_points_to_cell().

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

◆ generic_atomic_points_to_cell_p()

bool generic_atomic_points_to_cell_p ( cell  c,
bool  strict_p 
)

Is it a unique concrete memory location?

If strict_p, stubs are not considered atomic, as is the case in an interprocedural setting since they can be associated to several cells in the caller frame.

Else, stubs are not considered non atomic per se.

Parameters
strict_ptrict_p

Definition at line 452 of file points_to.c.

453 {
455  bool atomic_p = null_cell_p(c)
456  || generic_atomic_points_to_reference_p(r, strict_p);
457 
458  return atomic_p;
459 }

References cell_any_reference(), generic_atomic_points_to_reference_p(), and null_cell_p().

Referenced by add_implicitly_killed_arcs_to_kill_set(), freed_list_to_points_to(), list_assignment_to_points_to(), and upgrade_approximations_in_points_to_set().

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

◆ generic_atomic_points_to_reference_p()

bool generic_atomic_points_to_reference_p ( reference  r,
bool  strict_p 
)

Is it a unique concrete memory location?

No, if it is a reference to an abstract location.

No, if the subscripts include an unbounded expression.

Very preliminary version. One of the keys to Amira Mensi's work.

More about stubs: a stub is not NULL but there is no information to know if they represent one address or a set of addresses. Unless the intraprocedural points-to analysis is performed for each combination of atomic/non-atomic stub, safety implies that stub-based references are not atomic (strict_p=true). In some other cases, you know that a stub does represent a unique location (strict_p=false).

Note: it is assumed that the reference is a points-to reference. All subscripts are constants, field references or unbounded expressions.

Note: FI, I have a probleme when calling this function from a proper effects environment. In that case, stubs might be assumed to be unique memory locations. The exactness information can be derived from the numer of targets in the matching list.

Note 2: FI, I do not understand why the type of the reference is not taken into account.

Parameters
strict_ptrict_p

Definition at line 489 of file points_to.c.

490 {
491  bool atomic_p = false;
492  entity v = reference_variable(r);
493 
494  if(!entity_null_locations_p(v) // FI: NULL is considered atomic
498  && !entity_heap_location_p(v)) {
499  list sl = reference_indices(r);
500  //entity v = reference_variable(r);
501  if(!entity_stub_sink_p(v) || !strict_p) {
502  atomic_p = true;
503  FOREACH(EXPRESSION, se, sl) {
504  if(unbounded_expression_p(se)) {
505  atomic_p = false;
506  break;
507  }
508  else if(expression_range_p(se)) {
509  atomic_p = false;
510  break;
511  }
512  }
513  }
514  }
515 
516  return atomic_p;
517 }
bool entity_heap_location_p(entity b)
package abstract location.
bool entity_null_locations_p(entity e)
test if an entity is the NULL POINTER
bool entity_stub_sink_p(entity e)
test if an entity is a stub sink for a formal parameter e.g.
bool entity_typed_anywhere_locations_p(entity e)
Test if an entity is the bottom of the lattice.
bool entity_anywhere_locations_p(entity e)
test if an entity is the bottom of the lattice
bool entity_typed_nowhere_locations_p(entity e)
test if an entity is the bottom of the lattice
bool expression_range_p(expression e)
Definition: expression.c:1848

References entity_anywhere_locations_p(), entity_heap_location_p(), entity_null_locations_p(), entity_stub_sink_p(), entity_typed_anywhere_locations_p(), entity_typed_nowhere_locations_p(), EXPRESSION, expression_range_p(), FOREACH, reference_indices, reference_variable, and unbounded_expression_p().

Referenced by analyzed_reference_p(), atomic_points_to_reference_p(), create_values_for_simple_effect(), generic_atomic_points_to_cell_p(), generic_transform_sink_cells_from_matching_list(), and substitute_stubs_in_transformer_with_translation_binding().

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

◆ make_anywhere_points_to_cell()

cell make_anywhere_points_to_cell ( type  t)

Function storing points to information attached to a statement.

Generate a global variable holding a statement_points_to, a mapping from statements to lists of points-to arcs. The variable is called "pt_to_list_object".

The macro also generates a set of functions used to deal with this global variables.

The functions are defined in newgen_generic_function.h:

pt_to_list_undefined_p()

reset_pt_to_list()

error_reset_pt_to_list()

set_pt_to_list(o)

get_pt_to_list()

store_pt_to_list(k, v)

update_pt_to_list(k, v)

load_pt_to_list(k)

delete_pt_to_list(k)

bound_pt_to_list_p(k)

store_or_update_pt_to_list(k, v) Functions specific to points-to analysis

Definition at line 87 of file points_to.c.

88 {
90  if(get_bool_property("ALIASING_ACROSS_TYPES"))
92  else
96  return c;
97 }
cell make_cell_reference(reference _field_)
Definition: effects.c:293
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
entity entity_all_xxx_locations_typed(string xxx, type t)
FI->AM: the predicate entity_all_xxx_locations_typed_p() is missing...
entity entity_all_locations()
eturn ANY_MODULE:ANYWHERE (the top of the lattice)
#define ANYWHERE_LOCATION
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#define entity_undefined
Definition: ri.h:2761

References ANYWHERE_LOCATION, entity_all_locations(), entity_all_xxx_locations_typed(), entity_undefined, get_bool_property(), make_cell_reference(), make_reference(), and NIL.

Referenced by anywhere_source_to_sinks(), assignment_to_points_to(), gen_may_set(), gen_must_set(), list_assignment_to_points_to(), points_to_cells_minimal_upper_bound(), process_casted_sinks(), process_casted_sources(), semantics_expression_to_points_to_sinks(), and source_to_sinks().

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

◆ merge_points_to_cell_lists()

list merge_points_to_cell_lists ( list  l1,
list  l2 
)

Add in "l1" elements of "l2" that are not yet in "l1".

List "l2" is then destroyed.

This is a set union.

Parameters
l11
l22

Definition at line 134 of file points_to.c.

135 {
136  list lt = NIL;
137  FOREACH(CELL, c2, l2) {
138  if(!points_to_cell_in_list_p(c2, l1)) {
139  lt = CONS(CELL,c2, lt);
140  }
141  }
142  lt = gen_nreverse(lt);
143  l1 = gen_nconc(l1, lt);
144  gen_free_list(l2);
145  return l1;
146 }
bool points_to_cell_in_list_p(cell c, list L)
Definition: points_to.c:117
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327

References CELL, CONS, FOREACH, gen_free_list(), gen_nconc(), gen_nreverse(), NIL, and points_to_cell_in_list_p().

Referenced by dereferencing_to_sinks().

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

◆ points_to_array_reference_p()

bool points_to_array_reference_p ( reference  r)

Is this a reference to an array or a reference to a pointer? This is not linked to the type of the reference, as a reference may be a pointer, such as "a[10]" when "a" is declared int "a[10][20]".

Look for the last field among the subscript

Definition at line 599 of file points_to.c.

600 {
601  bool array_p = false;
602  list sl = reference_indices(r);
603  entity v = reference_variable(r);
604 
605  if(ENDP(sl)) {
607  array_p = array_type_p(t);
608  }
609  else {
610  /* Look for the last field among the subscript */
611  list rsl = gen_nreverse(sl);
612  type t = type_undefined;
613  int i = 0;
614  FOREACH(EXPRESSION, se, rsl) {
618  break;
619  }
620  i++;
621  }
622  if(type_undefined_p(t)) {
624  variable vt = type_variable(t);
625  list dl = variable_dimensions(vt);
626  int d = (int) gen_length(dl);
627  int i = (int) gen_length(rsl);
628  if(i<d)
629  array_p = true;
630  }
631  else {
632  if(i==0) { // FI: could be merged with the "else if" clause
633  array_p = array_type_p(t);
634  }
635  else if(array_type_p(t)) {
636  variable vt = type_variable(t);
637  list dl = variable_dimensions(vt);
638  int d = (int) gen_length(dl);
639  if(i<d)
640  array_p = true;
641  }
642  }
644  }
645  return array_p;
646 }
bool field_reference_expression_p(expression e)
Check if expression "e" is a reference to a struct field.
Definition: points_to.c:224
#define type_undefined_p(x)
Definition: ri.h:2884

References array_type_p(), ENDP, entity_basic_concrete_type(), EXPRESSION, expression_reference(), f(), field_reference_expression_p(), FOREACH, gen_length(), gen_nreverse(), int, reference_indices, reference_variable, type_undefined, type_undefined_p, type_variable, and variable_dimensions.

Referenced by points_to_cell_add_fixed_subscripts(), and subscript_to_points_to_sinks().

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

◆ points_to_array_reference_to_type()

type points_to_array_reference_to_type ( reference  r)

If this is an array reference, what is the type of the underlying array type?

This information cannot be obtained by direct type information because subarrays are typed as pointers to even smaller arrays.

If it is not an array reference, the returned type is undefined.

No new type is allocated.

Look for the last field among the subscript

Definition at line 657 of file points_to.c.

658 {
659  list sl = reference_indices(r);
660  entity v = reference_variable(r);
661  type t = type_undefined;
662 
663  if(ENDP(sl)) {
665  }
666  else {
667  /* Look for the last field among the subscript */
668  list rsl = gen_nreverse(sl);
669  FOREACH(EXPRESSION, se, rsl) {
673  break;
674  }
675  }
676  if(type_undefined_p(t)) {
678  }
679  else {
680  ;
681  }
683  }
684  return t;
685 }

References ENDP, entity_basic_concrete_type(), EXPRESSION, expression_reference(), f(), field_reference_expression_p(), FOREACH, gen_nreverse(), reference_indices, reference_variable, type_undefined, and type_undefined_p.

Referenced by points_to_cell_add_fixed_subscripts().

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

◆ points_to_cell_equal_p()

◆ points_to_cell_in_list_p()

bool points_to_cell_in_list_p ( cell  c,
list  L 
)

◆ points_to_cell_to_upper_bound_points_to_cells()

list points_to_cell_to_upper_bound_points_to_cells ( cell  c)

Return a list of cells that are larger than cell "c" in the points-to cell lattice.

This goal is quite open because a[1][2] is dominated by both a[*][2] and a[1][*], then by a[*][*]. Assuming "a" is variable of function "foo", then we have "foo:*STACK*_b0", "*ANYMODULE*:*STACK*_b0", "foo:*ANYWHERE*_b0", "*ANYMODULE*:*ANYWHERE*_b0", "*ANYMODULE*:*ANYWHERE*".

They would all be useful to guarantee the consistency of the points-to information wrt the points-to cell lattice, but we'd rather maintain a partially consistent points-to graph and rely on functions using it to add the necessary points-to arcs.

A lattice-consistent points-to graph would contain too many arcs as x->y implies x'->y' for all x' bigger than x and y' bigger then y...

For the time being, we only need to convert a[i][j][k] into a[*][*][*] when i, j and k are real subscript expressions, not fields.

We return an empty list when cell "c" does not need any upper bound, as is the case with a, a[f] where f is a field, a[*] and all the abstract locations.

So, for the time being, this function returns a list with one or zero elements.

Definition at line 973 of file points_to.c.

974 {
975  list ubl = NIL; // upper bound list
977  entity v = reference_variable(r);
979  list sel = reference_indices(r); // subscript expression list
980  list nsel = NIL; // new subscript expression list
981  bool new_cell_p = false;
982  FOREACH(EXPRESSION, se, sel) {
984  if(integer_expression_p(se)) {
986  new_cell_p = true;
987  }
988  else
989  nse = copy_expression(se);
990  nsel = CONS(EXPRESSION, nse, nsel);
991  }
992  if(new_cell_p) {
993  nsel = gen_nreverse(nsel);
994  reference nr = make_reference(v, nsel);
995  cell nc = make_cell_reference(nr);
996  ubl = CONS(CELL, nc, ubl);
997  }
998  else
999  gen_full_free_list(nsel);
1000  }
1001  return ubl;
1002 }
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
bool entity_abstract_location_p(entity al)
void gen_full_free_list(list l)
Definition: genClib.c:1023
bool integer_expression_p(expression e)
Definition: expression.c:601
#define expression_undefined
Definition: ri.h:1223

References CELL, cell_any_reference(), CONS, copy_expression(), entity_abstract_location_p(), EXPRESSION, expression_undefined, FOREACH, gen_full_free_list(), gen_nreverse(), integer_expression_p(), make_cell_reference(), make_reference(), make_unbounded_expression(), NIL, reference_indices, and reference_variable.

Referenced by points_to_cells_to_upper_bound_points_to_cells().

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

◆ points_to_cells_intersect_p()

bool points_to_cells_intersect_p ( cell  lc,
cell  rc 
)

points-to cells use abstract addresses, hence the proper comparison is an intersection.

simple references are considered to be singleton.

Assume no aliasing between variables and within data structures.

It is safe to assume intersection...

Parameters
lcc
rcc

Definition at line 532 of file points_to.c.

533 {
534  bool intersect_p = false;
535  if(cell_equal_p(lc, rc)) {
536  // FI: too simple... All the subscript should be checked.
537  // unbounded expressions should be used to decide about a possible
538  // intersection... Unless this is guarded by
539  // atomic_points_to_reference_p(). To be investigated.
540  intersect_p = true;
541  }
542  else {
543  // Look for abstract domains
544  // Probably pretty complex...
545  // Simple first version...
546  reference lr = cell_any_reference(lc);
547  entity le = reference_variable(lr);
548  reference rr = cell_any_reference(rc);
549  entity re = reference_variable(rr);
550  intersect_p = entities_may_conflict_p(le, re);
551  }
552  return intersect_p;
553 }
bool entities_may_conflict_p(entity e1, entity e2)
Check if two entities may conflict.
Definition: conflicts.c:984

References cell_any_reference(), cell_equal_p(), entities_may_conflict_p(), and reference_variable.

Referenced by equal_condition_to_points_to().

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

◆ points_to_cells_minimal_module_upper_bound()

entity points_to_cells_minimal_module_upper_bound ( list cl   __attribute__(unused))

Definition at line 578 of file points_to.c.

579 {
581  return m;
582 }

References entity_undefined.

Referenced by points_to_cells_minimal_upper_bound().

+ Here is the caller graph for this function:

◆ points_to_cells_minimal_reference_upper_bound()

reference points_to_cells_minimal_reference_upper_bound ( entity m   __attribute__(unused),
type t   __attribute__(unused),
list cl   __attribute__(unused) 
)

Definition at line 590 of file points_to.c.

591 {
593  return r;
594 }
#define reference_undefined
Definition: ri.h:2302

References reference_undefined.

Referenced by points_to_cells_minimal_upper_bound().

+ Here is the caller graph for this function:

◆ points_to_cells_minimal_type_upper_bound()

type points_to_cells_minimal_type_upper_bound ( list cl   __attribute__(unused))

Definition at line 584 of file points_to.c.

585 {
586  type t = type_undefined;
587  return t;
588 }

References type_undefined.

Referenced by points_to_cells_minimal_upper_bound().

+ Here is the caller graph for this function:

◆ points_to_cells_minimal_upper_bound()

cell points_to_cells_minimal_upper_bound ( list cl   __attribute__(unused))

Allocate a cell that is the minimal upper bound of the cells in list "cl" according to the points-to cell lattice...

An over-approximation is always safe. So, an anywhere cell, typed or not, can be returned in a first drat implementation.

The points-to cell lattice is the product of three lattices, the module lattice, the type lattice and the abstracct reference lattice...

Definition at line 565 of file points_to.c.

566 {
567 #if 0
571  cell c = make_cell_reference(r);
572 #endif
575  return c;
576 }
type points_to_cells_minimal_type_upper_bound(list cl __attribute__((unused)))
Definition: points_to.c:584
reference points_to_cells_minimal_reference_upper_bound(entity m __attribute__((unused)), type t __attribute__((unused)), list cl __attribute__((unused)))
Definition: points_to.c:590
cell make_anywhere_points_to_cell(type t)
Function storing points to information attached to a statement.
Definition: points_to.c:87
entity points_to_cells_minimal_module_upper_bound(list cl __attribute__((unused)))
Definition: points_to.c:578
type make_scalar_overloaded_type(void)
Definition: type.c:726

References make_anywhere_points_to_cell(), make_cell_reference(), make_scalar_overloaded_type(), points_to_cells_minimal_module_upper_bound(), points_to_cells_minimal_reference_upper_bound(), and points_to_cells_minimal_type_upper_bound().

+ Here is the call graph for this function:

◆ points_to_cells_to_upper_bound_points_to_cells()

list points_to_cells_to_upper_bound_points_to_cells ( list  cl)

Add to list "l" cells that are upper bound cells of the cells already in list "l" and return list "l".

Parameters
cll

Definition at line 1007 of file points_to.c.

1008 {
1009  list ubl = NIL;
1010  FOREACH(CELL, c, cl) {
1012  ubl = gen_nconc(ubl, cubl);
1013  }
1014  ubl = gen_nconc(cl, ubl);
1015  return ubl;
1016 }
list points_to_cell_to_upper_bound_points_to_cells(cell c)
Return a list of cells that are larger than cell "c" in the points-to cell lattice.
Definition: points_to.c:973

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

+ Here is the call graph for this function:

◆ points_to_reference_to_final_dimension()

int points_to_reference_to_final_dimension ( reference  r)

Compute the number of array subscript at the end of a points_to_reference.

Look for the last field subscript and count the number of subscripts after it. If no field susbcript is found, then all subscripts are final array subscripts.

To make thinks easier, the subscript list is reversed.

Definition at line 244 of file points_to.c.

245 {
246  list sl = reference_indices(r);
247  sl = gen_nreverse(sl);
248  int d = 0;
249  FOREACH(EXPRESSION, e, sl) {
251  break;
252  else
253  d++;
254  }
255  sl = gen_nreverse(sl);
256  reference_indices(r) = sl;
257  return d;
258 }

References EXPRESSION, field_reference_expression_p(), FOREACH, gen_nreverse(), and reference_indices.

+ Here is the call graph for this function:

◆ points_to_reference_to_typed_index()

list points_to_reference_to_typed_index ( reference  r,
type  t 
)

Look for the index in "r" that corresponds to a pointer of type "t" and return the corresponding element list.

In other words, the type of "&r" is "t".

It is done in a very inefficient way

Definition at line 361 of file points_to.c.

362 {
363  bool to_be_freed;
364  type rt = points_to_reference_to_type(r, &to_be_freed);
365  list rsl = reference_indices(r); // reference subscript list
366  pips_assert("t is a pointer type", C_pointer_type_p(t));
368  list psl = list_undefined; // pointed subscript list
369 
370  if(array_pointer_type_equal_p(rt, pt))
371  psl = gen_last(rsl);
372  else {
373  if(to_be_freed) free_type(rt);
374  entity v = reference_variable(r);
375  list nl = NIL;
376  int i;
377  int n = (int) gen_length(rsl);
378  reference nr = make_reference(v, nl);
379  bool found_p = false;
380 
381  for(i=0;i<n;i++) {
382  nl = gen_nconc(nl, CONS(EXPRESSION,
384  NIL));
385  reference_indices(nr) = nl;
386  rt = points_to_reference_to_type(nr, &to_be_freed);
387  if(array_pointer_type_equal_p(rt, pt)) {
388  found_p = true;
389  break;
390  }
391  }
392 
393  free_reference(nr);
394 
395  if(found_p)
396  psl = gen_nthcdr(i, rsl);
397  else {
398  // The issue may be due to a user bug, as was the case in
399  // Strict_typing.sub/malloc03.c
400  if(entity_heap_location_p(v)) {
401  // It would be nice to have a current statement stack...
402  pips_user_error("The dynamic allocation of \"%s\" is likely "
403  "to be inadequate with its use in the current "
404  "statement.\n", entity_local_name(v));
405  }
406  else
407  pips_internal_error("Type not found.\n");
408  }
409  }
410 
411  free_type(pt);
412 
413  return psl;
414 }
void free_reference(reference p)
Definition: ri.c:2050
void free_type(type p)
Definition: ri.c:2658
type points_to_reference_to_type(reference, bool *)
FI: I need more generality than is offered by cell_to_type()
Definition: type.c:527
list gen_last(list l)
Return the last element of a list.
Definition: list.c:578
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
gen_chunk gen_nth(int n, const list l)
to be used as ENTITY(gen_nth(3, l))...
Definition: list.c:710
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
#define pips_internal_error
Definition: misc-local.h:149
#define pips_user_error
Definition: misc-local.h:147
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
type C_type_to_pointed_type(type)
returns a copy of t if t is not a pointer type, and the pointed type if t is a pointer type or.
Definition: type.c:5288
bool array_pointer_type_equal_p(type, type)
assume that a pointer to type x is equal to a 1-D array of x
Definition: type.c:609
bool C_pointer_type_p(type)
Returns OK for "char[]" as well as for "char *".
Definition: type.c:3011

References array_pointer_type_equal_p(), C_pointer_type_p(), C_type_to_pointed_type(), CONS, copy_expression(), entity_heap_location_p(), entity_local_name(), EXPRESSION, free_reference(), free_type(), gen_last(), gen_length(), gen_nconc(), gen_nth(), gen_nthcdr(), int, list_undefined, make_reference(), NIL, pips_assert, pips_internal_error, pips_user_error, points_to_reference_to_type(), reference_indices, and reference_variable.

Referenced by offset_array_reference().

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

◆ points_to_reference_update_final_subscripts()

void points_to_reference_update_final_subscripts ( reference  r,
list  nsl 
)

Substitute the subscripts "sl" in points-to reference "r" just after the last field subscript by "nsl".

"sl" must be broken into three parts, possibly empty:

  1. The first part that ends up at the last field reference. It may be empty when no field is referenced.
  2. The second part that starts just after the last field reference and that counts at most as many elements as the new subscript list, "nsl". This part must be substituted.
  3. The third part that is left unchanged after substitution.

Issue: how do you know that the initial array subscript must be preserved because it is an implicit dimension added for pointer arithmetics?

build sl1

Parameters
nslsl

Definition at line 278 of file points_to.c.

279 {
280  list sl = reference_indices(r);
281  list sl1 = NIL, sl3 = NIL, sl23 = NIL;
282 
283  sl = gen_nreverse(sl); // sl1 and sl23 are built in the right order
284  bool found_p = false;
285  bool skip_one_p = false; // to skip indices added for pointer arithmetic
286  FOREACH(EXPRESSION, e, sl) {
288  type et = expression_to_type(e);
289  if(pointer_type_p(et))
290  skip_one_p = true;
291  found_p = true;
292  free_type(et);
293  }
294  if(found_p) {
295  /* build sl1 */
296  sl1 = CONS(EXPRESSION, e , sl1);
297  }
298  else
299  sl23 = CONS(EXPRESSION, e , sl23);
300  }
301 
302  if(skip_one_p && ENDP(sl23) && !ENDP(nsl)) {
303  pips_internal_error("We are not generating a memory access constant path.\n");
304  }
305 
306  // FI: place the new indices as early as possible
307 #if 0
308  int n = (int) gen_length(nsl);
309  int i = 0;
310  FOREACH(EXPRESSION, e, sl23) {
311  if(skip_one_p) {
312  sl1 = gen_nconc(sl1, CONS(EXPRESSION, e , NIL));
313  skip_one_p = false;
314  }
315  else {
316  if(i<n)
317  free_expression(e);
318  else
319  sl3 = gen_nconc(sl3, CONS(EXPRESSION, e, NIL));
320  i++;
321  }
322  }
323 
324  sl = gen_nconc(sl1, nsl);
325  sl = gen_nconc(sl, sl3);
326 #endif
327 
328  // FI: place the new indices as late as possible
329  int n = (int) gen_length(nsl);
330  int n23 = (int) gen_length(sl23);
331  int i = 0;
332  FOREACH(EXPRESSION, e, sl23) {
333  if(i>=n23-n)
334  free_expression(e);
335  else
336  sl3 = gen_nconc(sl3, CONS(EXPRESSION, e, NIL));
337  i++;
338  }
339 
340  sl = gen_nconc(sl1, sl3);
341  sl = gen_nconc(sl, nsl);
342 
343  gen_free_list(sl23);
344  reference_indices(r) = sl;
345 
346  // We do not want to generate indirection in the reference
347  // The exactitude information is not relevant here
348  // bool exact_p;
349  // pips_assert("The reference is a constant memory access path",
350  // !effect_reference_dereferencing_p( r, &exact_p));
351  // Might only work for standard references and not for points-to
352  // references: core dumps with points-to references.
353 }
void free_expression(expression p)
Definition: ri.c:853
type expression_to_type(expression)
For an array declared as int a[10][20], the type returned for a[i] is int [20].
Definition: type.c:2486

References CONS, ENDP, EXPRESSION, expression_to_type(), field_reference_expression_p(), FOREACH, free_expression(), free_type(), gen_free_list(), gen_length(), gen_nconc(), gen_nreverse(), int, NIL, pips_internal_error, pointer_type_p(), and reference_indices.

Referenced by subscript_to_points_to_sinks().

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

◆ points_to_with_stripped_sink()

points_to points_to_with_stripped_sink ( points_to  pt,
int(*)(void)  line_number_func 
)

The value of the source can often be expressed with different subscript lists.

For instance, a, a[0], a[0][0] have different types but the same value if a is a 2-D array.

This function allocated a new points-to object whose sink has a minimal number of indices.

FI: I have added this function to deal with pointers to arrays. It is called from generic_reference_to_points_to_matching_list() to try to adapt the points-to information to the undefined requirements of Beatrice's functions for regions_with_points_to. I do not think the function below is correct when structs are involved... The stripping may be useful, but it should be much more careful.

adapt_reference_to_type() might be better here to adjust the subscripts in sink.

Add the implicit dimension

Dealing with the special case of a constant p -> "foo"

The other option would be to accept "foo"[0] as a valid reference... Extending references to constant functions is a first step...

Parameters
ptt

Definition at line 1074 of file points_to.c.

1076 {
1077  cell source = points_to_source(pt);
1078  cell sink = points_to_sink(pt);
1079  cell new_sink_cell = cell_undefined;
1080 
1081  // FI: first implementation
1082  if(false) {
1083  reference source_r = cell_any_reference(source);
1084  list source_sl = reference_indices(source_r);
1085  list c_source_sl = list_undefined;
1086 
1087  reference sink_r = cell_any_reference(sink);
1088  // FI: sink_sl is longer than source_sl if pt is semantically correct
1089  list sink_sl = reference_indices(sink_r);
1090  list c_sink_sl = list_undefined;
1091  entity sink_e = reference_variable(sink_r);
1092 
1093  list new_sink_sl = NIL;
1094  for(c_source_sl = source_sl, c_sink_sl = sink_sl;
1095  !ENDP(c_source_sl);
1096  POP(c_source_sl), POP(c_sink_sl)) {
1097  expression s = copy_expression(EXPRESSION(CAR(c_sink_sl)));
1098  new_sink_sl = CONS(EXPRESSION, s, new_sink_sl);
1099  }
1100  if(!get_bool_property("POINTS_TO_STRICT_POINTER_TYPES")
1101  && !anywhere_cell_p(sink)
1103  && !ENDP(c_sink_sl)) {
1104  /* Add the implicit dimension */
1105  expression s = copy_expression(EXPRESSION(CAR(c_sink_sl)));
1106  new_sink_sl = CONS(EXPRESSION, s, new_sink_sl);
1107  }
1108  new_sink_sl = gen_nreverse(new_sink_sl);
1109 
1110  new_sink_cell = make_cell_reference(make_reference(sink_e, new_sink_sl));
1111  }
1112  else {
1113  // Second implementation
1115  || null_cell_p(sink) || nowhere_cell_p(sink)
1116  // FI: why is the typed heap cell not handled too?
1117  || heap_cell_p(sink)) {
1118  new_sink_cell = copy_cell(sink);
1119  }
1120  else {
1121  new_sink_cell = copy_cell(sink);
1122  reference n_sink_r = cell_any_reference(new_sink_cell);
1123  type source_t = points_to_cell_to_concrete_type(source);
1124  if(pointer_type_p(source_t)) {
1125  type source_pt = type_to_pointed_type(source_t);
1126  if(adapt_reference_to_type(n_sink_r, source_pt, line_number_func))
1127  ;
1128  else {
1129  /* Dealing with the special case of a constant p -> "foo"
1130  *
1131  * The other option would be to accept "foo"[0] as a valid
1132  * reference... Extending references to constant functions
1133  * is a first step...
1134  */
1135  bool ok_p = false;
1136  type sink_t = points_to_reference_to_concrete_type(n_sink_r);
1137  if(char_type_p(source_pt)) {
1139  ok_p = true;
1140  }
1141  if(!ok_p)
1142  pips_internal_error("The type of a sink cell, \"%s\", is not compatible with the source cell, \"%s\".\n",
1143  safe_type_to_string(sink_t),
1144  safe_type_to_string(source_t));
1145  }
1146  }
1147 
1148  else
1149  pips_internal_error("The type of a source cell is not a pointer.\n");
1150  }
1151  }
1152 
1153  points_to npt = make_points_to(copy_cell(source),
1154  new_sink_cell,
1157  return npt;
1158 }
approximation copy_approximation(approximation p)
APPROXIMATION.
Definition: effects.c:132
descriptor make_descriptor_none(void)
Definition: effects.c:442
cell copy_cell(cell p)
CELL.
Definition: effects.c:246
points_to make_points_to(cell a1, cell a2, approximation a3, descriptor a4)
bool cell_typed_anywhere_locations_p(cell c)
test if a cell is the bottom of the lattice
type points_to_reference_to_concrete_type(reference)
Definition: type.c:685
bool anywhere_cell_p(cell)
Is it an anywhere cell?
Definition: effects.c:367
bool adapt_reference_to_type(reference, type, int(*)(void))
FI: a really stupid function...
Definition: type.c:1327
bool heap_cell_p(cell)
Any heap cell, more or less abstract or typed.
Definition: effects.c:420
#define cell_undefined
Definition: effects.h:430
#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
bool char_star_constant_function_type_p(type)
Beware of typedefs.
Definition: type.c:5787
string safe_type_to_string(const type)
Definition: type.c:59
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 char_type_p(type)
return true whether ‘t’ is a char or an unsigned char
Definition: type.c:2877

References adapt_reference_to_type(), anywhere_cell_p(), CAR, cell_any_reference(), cell_typed_anywhere_locations_p(), cell_undefined, char_star_constant_function_type_p(), char_type_p(), CONS, copy_approximation(), copy_cell(), copy_expression(), ENDP, EXPRESSION, gen_nreverse(), get_bool_property(), heap_cell_p(), list_undefined, make_cell_reference(), make_descriptor_none(), make_points_to(), make_reference(), NIL, nowhere_cell_p(), null_cell_p(), pips_internal_error, pointer_type_p(), points_to_approximation, points_to_cell_to_concrete_type(), points_to_reference_to_concrete_type(), points_to_sink, points_to_source, POP, reference_indices, reference_variable, safe_type_to_string(), and type_to_pointed_type().

Referenced by generic_reference_to_points_to_matching_list().

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

◆ print_points_to_cell()

void print_points_to_cell ( cell  c)

Debug: use stderr.

Definition at line 196 of file points_to.c.

197 {
198  fprint_points_to_cell(stderr, c);
199 }
void fprint_points_to_cell(FILE *f __attribute__((unused)), cell c)
Debug: print a cell list for points-to.
Definition: points_to.c:178

References fprint_points_to_cell().

Referenced by print_points_to_cells().

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

◆ print_points_to_cells()

void print_points_to_cells ( list  cl)

Debug.

Parameters
cll

Definition at line 202 of file points_to.c.

203 {
204  if(ENDP(cl))
205  fprintf(stderr, "Empty cell list");
206  else {
208  FOREACH(CELL, c, cl) {
210  entity v = reference_variable(r);
211  /* *ANY_MODULE* is unfortunately not an entity... */
213  if(!entity_undefined_p(mv) && m!=mv)
214  fprintf(stderr,"%s" MODULE_SEP_STRING, entity_local_name(mv));
216  if(!ENDP(CDR(cl)))
217  fprintf(stderr, ", ");
218  }
219  }
220  fprintf(stderr, "\n");
221 }
void print_points_to_cell(cell c)
Debug: use stderr.
Definition: points_to.c:196
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#define MODULE_SEP_STRING
Definition: naming-local.h:30
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
#define entity_undefined_p(x)
Definition: ri.h:2762

References CDR, CELL, cell_any_reference(), ENDP, entity_local_name(), entity_module_name(), entity_undefined_p, FOREACH, fprintf(), get_current_module_entity(), module_name_to_entity(), MODULE_SEP_STRING, print_points_to_cell(), and reference_variable.

+ Here is the call graph for this function:

◆ recursive_store_independent_points_to_reference_p()

bool recursive_store_independent_points_to_reference_p ( type  t,
list  sl 
)
Parameters
tany type, but here initial reference type
slremaining subscript list, all subscripts are supposed to be store independent
Returns
true none of the subsequence subscript implies a dereferencing

Reduce the length of the subscript list

There are indices because of the first test on the number of subscripts

Parameters
sll

Definition at line 1169 of file points_to.c.

1169  {
1170  bool independent_p = false;
1171 
1172  if(ENDP(sl))
1173  independent_p = true;
1174  else if(struct_type_p(t)) {
1175  expression se = EXPRESSION(CAR(sl));
1179  independent_p = recursive_store_independent_points_to_reference_p(nt, CDR(sl));
1180  }
1181  else if(array_type_p(t)) {
1182  unsigned int d = array_type_dimension(t);
1183  if(gen_length(sl)<=d)
1184  independent_p = true;
1185  else {
1187  list nsl = sl;
1188  unsigned int i;
1189  // Skip the array subscripts
1190  for(i=0;i<d;i++)
1191  nsl = CDR(nsl);
1192  independent_p = recursive_store_independent_points_to_reference_p(nt, nsl);
1193  }
1194  }
1195  else if(pointer_type_p(t)) {
1196  /* There are indices because of the first test on the number of subscripts */
1197  independent_p = false;
1198  }
1199  else {
1200  // FI: It is more difficult... and it must have been programmed
1201  // somewhere else.
1202  pips_internal_error("Not implemented yet");
1203  }
1204 
1205  return independent_p;
1206 }
bool recursive_store_independent_points_to_reference_p(type t, list sl)
Definition: points_to.c:1169
unsigned int array_type_dimension(type)
Definition: type.c:2947
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 array_type_to_element_type(type)
returns the type of the elements of an array type, as a newly allocated type.
Definition: type.c:5700

References array_type_dimension(), array_type_p(), array_type_to_element_type(), CAR, CDR, ENDP, entity_basic_concrete_type(), EXPRESSION, expression_reference(), f(), gen_length(), pips_internal_error, pointer_type_p(), recursive_store_independent_points_to_reference_p(), reference_variable, and struct_type_p().

Referenced by recursive_store_independent_points_to_reference_p(), and store_independent_points_to_reference_p().

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

◆ related_points_to_cell_in_list_p()

bool related_points_to_cell_in_list_p ( cell  c,
list  L 
)

Two cells are related if they are based on the same entity.

Definition at line 149 of file points_to.c.

150 {
151  bool found_p = false;
153  entity ec = reference_variable(rc);
154  FOREACH(CELL, lc, L) {
155  reference rlc = cell_any_reference(lc);
156  entity elc = reference_variable(rlc);
157  if(ec==elc) {
158  found_p =true;
159  break;
160  }
161  }
162  return found_p;
163 }

References CELL, cell_any_reference(), FOREACH, and reference_variable.

Referenced by filter_formal_context_according_to_actual_context(), freed_list_to_points_to(), new_filter_formal_context_according_to_actual_context(), and recursive_filter_formal_context_according_to_actual_context().

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

◆ related_points_to_cells_p()

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

Definition at line 165 of file points_to.c.

166 {
167  bool related_p = false;
168  reference rc1 = cell_any_reference(c1);
169  entity ec1 = reference_variable(rc1);
170  reference rc2 = cell_any_reference(c2);
171  entity ec2 = reference_variable(rc2);
172  related_p = (ec1==ec2);
173  return related_p;
174 }

References cell_any_reference(), and reference_variable.

Referenced by sink_to_sources(), and unreachable_points_to_cell_p().

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

◆ similar_arc_in_points_to_set_p()

bool similar_arc_in_points_to_set_p ( points_to  spt,
set  in,
approximation pa 
)

See if an arc like "spt" exists in set "in", regardless of its approximation.

If yes, returns the approximation of the arc found in "in".

See also arc_in_points_to_set_p(), which requires full identity

Parameters
sptpt
inn
paa

Definition at line 929 of file points_to.c.

930 {
931  bool in_p = false;
932  cell spt_source = points_to_source(spt);
933  cell spt_sink = points_to_sink(spt);
934  SET_FOREACH(points_to, pt, in) {
935  if(points_to_cell_equal_p(spt_source, points_to_source(pt))
936  && points_to_cell_equal_p(spt_sink, points_to_sink(pt))) {
937  *pa = points_to_approximation(pt);
938  in_p = true;
939  break;
940  }
941  }
942  return in_p;
943 }
bool points_to_cell_equal_p(cell c1, cell c2)
Definition: points_to.c:916

References points_to_approximation, points_to_cell_equal_p(), points_to_sink, points_to_source, and SET_FOREACH.

Referenced by filter_formal_out_context_according_to_formal_in_context().

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

◆ store_independent_points_to_indices_p()

bool store_independent_points_to_indices_p ( list  sl)

check that the subscript list il is either empty or made of integers or fields or unbounded entity "*".

What would you do with a constant range ?

Parameters
sll

Definition at line 1301 of file points_to.c.

1302 {
1303  bool constant_p = true;
1304 
1305  FOREACH(EXPRESSION, se, sl) {
1307  syntax s = expression_syntax(se);
1308  if(syntax_reference_p(s)) {
1309  reference r = syntax_reference(s);
1311  if(!entity_field_p(f)) {
1312  constant_p = false;
1313  break;
1314  }
1315  }
1316  else if(syntax_call_p(s)) {
1317  call c = syntax_call(s);
1318  entity f = call_function(c);
1319  if(!unbounded_entity_p(f)) {
1320  constant_p = false;
1321  break;
1322  }
1323  }
1324  else {
1325  constant_p = false;
1326  break;
1327  }
1328  }
1329  }
1330  return constant_p;
1331 }
bool unbounded_entity_p(entity f)
Definition: expression.c:4323
#define call_function(x)
Definition: ri.h:709
#define syntax_call_p(x)
Definition: ri.h:2734
#define syntax_call(x)
Definition: ri.h:2736

References call_function, constant_p(), entity_field_p(), EXPRESSION, expression_syntax, extended_integer_constant_expression_p(), f(), FOREACH, reference_variable, syntax_call, syntax_call_p, syntax_reference, syntax_reference_p, and unbounded_entity_p().

Referenced by store_independent_points_to_reference_p().

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

◆ store_independent_points_to_reference_p()

bool store_independent_points_to_reference_p ( reference  r)

Functions for points-to references, the kind of references used in points-to cells.

Does this points-to reference define the same set of memory locations regardless of the current (environment and) memory state?

The reference indices can be used to encode fields in data structures and can be applied to pointers as offset.

The types associated to the reference and to prefixes of the index list change. So a pointer dereferencing can be hidden anywhere. For instance, a[i][2] can be:

  • a 2-D array element,
  • a[i]+2 if a[i] is a 1-D array of pointers,
  • a.i[2], the second element of a 1-D array embedded as field i in struct a,
  • a.i+2, if field i is a pointer embedded as field i in struct a,
  • &a[i][2][0]... if a is an array of dimension 3 or more

Remember that *p is equivalent and encoded as p[0].

To guarantee store independence, either

  • the list of indices is empty, which covers abstract locations such as anywhere, null, etc.

or

  • the list of indices is a list of integer constants and fields and none of the intermediate types that are still indexed are pointers unless a multidimensional array is used...

Beware of named types...

Definition at line 1247 of file points_to.c.

1248 {
1249  list il = reference_indices(r);
1250  bool independent_p = ENDP(il); // any variable is a constant address
1251 
1252  if(!independent_p) {
1254  independent_p = false; // at least one index is store-dependent
1255  else {
1256  entity v = reference_variable(r);
1258  if(type_functional_p(t))
1259  independent_p = true;
1260  else
1261  independent_p =
1263  }
1264  }
1265 
1266  return independent_p;
1267 }
bool store_independent_points_to_indices_p(list sl)
check that the subscript list il is either empty or made of integers or fields or unbounded entity "*...
Definition: points_to.c:1301
#define type_functional_p(x)
Definition: ri.h:2950

References ENDP, entity_basic_concrete_type(), recursive_store_independent_points_to_reference_p(), reference_indices, reference_variable, store_independent_points_to_indices_p(), and type_functional_p.

Referenced by analyzed_reference_p(), assign_rhs_to_reflhs_to_transformer(), consistent_points_to_arc_p(), and reference_to_address_entity().

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

◆ stub_points_to_cell_p()

bool stub_points_to_cell_p ( cell  c)

Definition at line 108 of file points_to.c.

109 {
110  bool formal_p = true;
112  entity v = reference_variable(r);
113  formal_p = entity_stub_sink_p(v); // FI: can be a source too
114  return formal_p;
115 }

References cell_any_reference(), entity_stub_sink_p(), and reference_variable.

Referenced by freeable_points_to_cells(), freed_list_to_points_to(), freed_pointer_to_points_to(), null_equal_condition_to_points_to(), and points_to_to_context_points_to().

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