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

Go to the source code of this file.

Functions

list entity_to_sinks (entity e)
 allocate a new list of sinks with one element, abstract or concrete, e. More...
 
cell entity_to_cell (entity e)
 
list points_to_null_sinks ()
 
cell make_null_cell (void)
 
list points_to_anywhere_sinks (type t)
 
list call_to_points_to_sinks (call c, type et, pt_map in, bool eval_p, bool constant_p)
 
list intrinsic_call_to_points_to_sinks (call c, pt_map in, bool eval_p, bool constant_p)
 
list unary_intrinsic_call_to_points_to_sinks (call c, pt_map in, bool eval_p, bool constant_p)
 
list binary_intrinsic_call_to_points_to_sinks (call c, pt_map in, bool eval_p)
 
list expression_to_points_to_sinks_with_offset (expression a1, expression a2, pt_map in)
 
list ternary_intrinsic_call_to_points_to_sinks (call c, pt_map in, bool eval_p, bool constant_p)
 
list nary_intrinsic_call_to_points_to_sinks (call c, pt_map in)
 
reference simplified_reference (reference r)
 Return NULL as sink. More...
 
list pointer_reference_to_points_to_sinks (reference r, pt_map in, bool eval_p)
 What to do when a pointer "p" is dereferenced within a reference "r". More...
 
list reference_to_points_to_sinks (reference r, type et, pt_map in, bool eval_p, bool constant_p)
 Returns a list of memory cells "sinks" possibly accessed by the evaluation of reference "r". More...
 
static list process_casted_sinks (list sinks, type t)
 
static list process_casted_sources (list sinks, type t)
 FI: I am not sure that process_casted_sources() is nor should be different from process_casted_sinks() More...
 
list cast_to_points_to_sinks (cast ce, type et __attribute__((unused)), pt_map in, bool eval_p)
 Handling of cast: play it safe! Either the cast is partly redundant and can be ignored or anywhere is returned. More...
 
list sizeofexpression_to_points_to_sinks (sizeofexpression soe, type et __attribute__((unused)), pt_map in)
 
void init_heap_model (statement s)
 
void reset_heap_model ()
 
statement get_heap_statement ()
 
int get_heap_counter ()
 
list malloc_to_points_to_sinks (expression e, pt_map in)
 Heap modelling. More...
 
list unique_malloc_to_points_to_sinks (expression e)
 FI->AM: is "unique" multiple when ALIASING_ACROSS_TYPE is set to false? More...
 
list insensitive_malloc_to_points_to_sinks (expression e)
 FI->AM: what's the difference with the previous option? Reference to your dissertation? More...
 
list flow_sensitive_malloc_to_points_to_sinks (expression e)
 
list application_to_points_to_sinks (application a, type et __attribute__((unused)), pt_map in)
 
expression pointer_subscript_to_expression (cell c, list csl)
 Allocate a new expression based on the reference in "c" and the subscript list "csl". More...
 
list subscript_to_points_to_sinks (subscript s, type et, pt_map in, bool eval_p)
 Generate the corresponding points-to reference(s). More...
 
list range_to_points_to_sinks (range r, pt_map in)
 
list expression_to_points_to_cells (expression e, pt_map in, bool eval_p, bool constant_p)
 Return a possibly empty list of abstract locations whose addresses are possible value of expression "e" evaluated with points-to information "in". More...
 
list expression_to_points_to_sinks (expression e, pt_map in)
 The returned list contains cells used in "in". More...
 
list expression_to_points_to_sources (expression e, pt_map in)
 expression_to_points_to_sources() does not always work, especially with pointer arithmetic or subscripting because p[3], for instance, is not recognized as a valid source: it is not a constant path More...
 
bool reference_must_points_to_null_p (reference r, pt_map in)
 
bool reference_may_points_to_null_p (reference r, pt_map in)
 

Variables

static statement malloc_statement = statement_undefined
 Heap modelling. More...
 
static int malloc_counter = 0
 

Function Documentation

◆ application_to_points_to_sinks()

list application_to_points_to_sinks ( application  a,
type et   __attribute__(unused),
pt_map  in 
)

Definition at line 1388 of file sinks.c.

1391 {
1393  // list args = application_arguments(a);
1394  type t = expression_to_type(f);
1395  entity ne = entity_undefined;
1396  bool type_sensitive_p = !get_bool_property("ALIASING_ACROSS_TYPES");
1397 
1398  pips_user_warning("Case application is not correctly handled &p and %p\n",
1399  a, in);
1400 
1401  if(type_sensitive_p)
1403  else
1405 
1406  reference nr = make_reference(ne, NIL);
1407  cell nc = make_cell_reference(nr);
1408  list sinks = CONS(CELL, nc, NIL);
1409 
1410  // FI: free_type(t); ?
1411 
1412  return sinks;
1413 }
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(string xxx)
return ANY_MODULE:xxx
entity entity_all_xxx_locations_typed(string xxx, type t)
FI->AM: the predicate entity_all_xxx_locations_typed_p() is missing...
#define ANYWHERE_LOCATION
#define CELL(x)
CELL.
Definition: effects.h:424
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#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_user_warning
Definition: misc-local.h:146
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
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
#define entity_undefined
Definition: ri.h:2761
#define application_function(x)
Definition: ri.h:508
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

References ANYWHERE_LOCATION, application_function, CELL, CONS, entity_all_xxx_locations(), entity_all_xxx_locations_typed(), entity_undefined, expression_to_type(), f(), get_bool_property(), make_cell_reference(), make_reference(), NIL, and pips_user_warning.

Referenced by expression_to_points_to_cells().

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

◆ binary_intrinsic_call_to_points_to_sinks()

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

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

Already performed elsewhere. The value returned by expression

Parameters
inn
eval_pval_p

Definition at line 327 of file sinks.c.

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

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

Referenced by intrinsic_call_to_points_to_sinks().

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

◆ call_to_points_to_sinks()

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

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

Parameters
ett
inn
eval_pval_p
constant_ponstant_p

Definition at line 112 of file sinks.c.

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

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

Referenced by expression_to_points_to_cells().

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

◆ cast_to_points_to_sinks()

list cast_to_points_to_sinks ( cast  ce,
type et   __attribute__(unused),
pt_map  in,
bool  eval_p 
)

Handling of cast: play it safe! Either the cast is partly redundant and can be ignored or anywhere is returned.

Design choice: can we have static aliasing with constant paths? Can we have different types for one constant path? Maybe we could have some static aliasing for stubs, using an offset in the formal context, but we cannot manage static aliasing at the reference level, i.e. at the constant path level.

FI: do we need eval_p? Yes! We may need to produce the source or the sink.

Note: the problem linked to eval_p has not been analyzed properly; the code should be simplified.

Relevant test cases: Rice/test03

FI: we need here to return a list of points-to objects so as to warn the user in case the types are not compatible with the property ALIAS_ACROSS_TYPES or to fix the cells allocated in heap. However, this business if more likely to be performed in sinks.c

Definition at line 1091 of file sinks.c.

1095 {
1096  list sinks = list_undefined;
1097  list nsinks = NIL; // In case the cast cannot be handled precisely
1098  expression e = cast_expression(ce);
1100  // FI: should we pass down the expected type? It would be useful for
1101  // heap modelling. No, we might ass well fix the type in the list of
1102  // sinks returned, especially for malloced buckets.
1103  /* FI: we need here to return a list of points-to objects so as to
1104  * warn the user in case the types are not compatible with the
1105  * property ALIAS_ACROSS_TYPES or to fix the cells allocated in
1106  * heap. However, this business if more likely to be performed in
1107  * sinks.c
1108  */
1109  if(eval_p) {
1110  sinks = expression_to_points_to_sinks(e, in);
1111  if(pointer_type_p(t)) {
1112  nsinks = process_casted_sinks(sinks, t);
1113  }
1114  else {
1115  pips_internal_error("Not implemented yet.\n");
1116  }
1117  }
1118  else {
1119  sinks = expression_to_points_to_sources(e, in);
1120  if(pointer_type_p(t)) {
1121  nsinks = process_casted_sources(sinks, t);
1122  }
1123  else {
1124  // FI: should we make sure that we do not tranformer pointers
1125  // into integers or other types?
1126  ;
1127  }
1128  }
1129 
1130  if(!ENDP(nsinks)) {
1131  gen_free_list(sinks);
1132  sinks = nsinks;
1133  }
1134 
1135  return sinks;
1136  }
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
bool pointer_type_p(type)
Check for scalar pointers.
Definition: type.c:2993
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
#define cast_expression(x)
Definition: ri.h:747
#define cast_type(x)
Definition: ri.h:745
static list process_casted_sinks(list sinks, type t)
Definition: sinks.c:979
static list process_casted_sources(list sinks, type t)
FI: I am not sure that process_casted_sources() is nor should be different from process_casted_sinks(...
Definition: sinks.c:1035

References cast_expression, cast_type, compute_basic_concrete_type(), ENDP, expression_to_points_to_sinks(), expression_to_points_to_sources(), gen_free_list(), list_undefined, NIL, pips_internal_error, pointer_type_p(), process_casted_sinks(), and process_casted_sources().

Referenced by expression_to_points_to_cells().

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

◆ entity_to_cell()

cell entity_to_cell ( entity  e)

Definition at line 80 of file sinks.c.

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

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

Referenced by make_null_cell().

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

◆ entity_to_sinks()

list entity_to_sinks ( entity  e)

allocate a new list of sinks with one element, abstract or concrete, e.

sinks.c

No check on e for the time being

Definition at line 72 of file sinks.c.

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

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

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

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

◆ expression_to_points_to_cells()

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

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

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

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

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

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

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

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

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

Parameters
inn
eval_pval_p
constant_ponstant_p

Definition at line 1650 of file sinks.c.

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

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

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

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

◆ expression_to_points_to_sinks()

list expression_to_points_to_sinks ( expression  e,
pt_map  in 
)

The returned list contains cells used in "in".

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

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

Parameters
inn

Definition at line 1795 of file sinks.c.

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

References expression_to_points_to_cells().

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

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

◆ expression_to_points_to_sinks_with_offset()

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

Definition at line 546 of file sinks.c.

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

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

Referenced by binary_intrinsic_call_to_points_to_sinks().

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

◆ expression_to_points_to_sources()

list expression_to_points_to_sources ( expression  e,
pt_map  in 
)

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

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

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

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

Parameters
inn

Definition at line 1805 of file sinks.c.

1806 {
1807  list sinks = expression_to_points_to_cells(e, in, false, true);
1808 
1809  /* Scalar pointers are expected but [0] subscript may have been added */
1811  /* Trouble for fread04... An array element, _line_3[0], is reduced
1812  to an array, _line_3, and you want to capture its address */
1813  // sinks = reduce_cells_to_pointer_type(sinks);
1814  ;
1815  }
1816 
1817  ifdebug(1) {
1818  bool to_be_freed;
1819  type tmp_t = points_to_expression_to_type(e, &to_be_freed);
1820  type et = compute_basic_concrete_type(tmp_t);
1821  FOREACH(CELL, c, sinks) {
1822  if(!null_cell_p(c)) {
1823  bool to_be_freed2;
1824  type ct = points_to_cell_to_type(c, &to_be_freed2);
1826  // Type compatibility check. To be improved with integer used
1827  // as pointer values...
1828  if(!array_pointer_type_equal_p(et, cct)
1829  // Dereferencement via a subscript
1830  && !array_element_type_p(et, cct)
1831  // Constant strings such as "hello"
1832  && !((char_star_type_p(et) || string_type_p(et))
1834  // Dereferencement forced by the syntax of the expression
1835  && !(pointer_type_p(et)
1837  /* A useless [0] may have been added, but it is supposed to
1838  be taken care of above... by callers of this function. */
1839  ifdebug(1) {
1840  pips_debug(1, "Type mismatch for expression: "); print_expression(e);
1841  fprintf(stderr, " with type: "); print_type(et);
1842  fprintf(stderr, "\nand cell: "); print_points_to_cell(c);
1843  fprintf(stderr, " with type: "); print_type(cct);
1844  fprintf(stderr, "\n");
1845 
1846  }
1847  print_expression(e);
1848  pips_internal_error("Type error for an expression\n.");
1849  }
1850  if(to_be_freed2) free_type(ct);
1851  }
1852  }
1853  if(to_be_freed) free_type(tmp_t);
1854  }
1855 
1856  return sinks;
1857 }
bool expression_to_points_to_cell_p(expression e)
Can expression e be reduced to a reference, without requiring an evaluation?
type points_to_cell_to_type(cell, bool *)
FI: I need more generality than is offered by cell_to_type()
Definition: type.c:665
type points_to_expression_to_type(expression, bool *)
FI: I need more generality than is offered by expression_to_type() because fields are assimilated to ...
Definition: type.c:592
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
void print_expression(expression e)
no file descriptor is passed to make is easier to use in a debugging stage.
Definition: expression.c:58
#define print_points_to_cell(x)
Definition: print.c:377
void print_type(type)
For debugging.
Definition: type.c:111
bool array_element_type_p(type, type)
is "et" the type of an element of an array of type "at"?
Definition: type.c:684
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
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...

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

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

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

◆ flow_sensitive_malloc_to_points_to_sinks()

list flow_sensitive_malloc_to_points_to_sinks ( expression  e)

The type of me may en array type because of

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

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

In both case the heap object is an array.

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

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

Definition at line 1321 of file sinks.c.

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

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

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

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

◆ get_heap_counter()

int get_heap_counter ( void  )

Definition at line 1197 of file sinks.c.

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

References malloc_counter.

◆ get_heap_statement()

statement get_heap_statement ( void  )

Definition at line 1191 of file sinks.c.

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

References malloc_statement.

Referenced by flow_sensitive_malloc_to_points_to_sinks().

+ Here is the caller graph for this function:

◆ init_heap_model()

void init_heap_model ( statement  s)

Definition at line 1179 of file sinks.c.

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

References malloc_counter, and malloc_statement.

Referenced by statement_to_points_to().

+ Here is the caller graph for this function:

◆ insensitive_malloc_to_points_to_sinks()

list insensitive_malloc_to_points_to_sinks ( expression  e)

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

Definition at line 1312 of file sinks.c.

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

References flow_sensitive_malloc_to_points_to_sinks(), NIL, and pips_internal_error.

Referenced by malloc_to_points_to_sinks().

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

◆ intrinsic_call_to_points_to_sinks()

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

Definition at line 172 of file sinks.c.

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

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

Referenced by call_to_points_to_sinks().

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

◆ make_null_cell()

cell make_null_cell ( void  )

Definition at line 95 of file sinks.c.

96 {
98  cell c = entity_to_cell(ne);
99  return c;
100 }
entity entity_null_locations()
return TOP-LEVEL:NULL_POINTER The NULL pointer should be a global variable, unique for all modules FI...
cell entity_to_cell(entity e)
Definition: sinks.c:80

References entity_null_locations(), and entity_to_cell().

Referenced by binary_intrinsic_call_to_points_to_sinks(), declaration_statement_to_points_to(), flow_sensitive_malloc_to_points_to_sinks(), and null_equal_condition_to_points_to().

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

◆ malloc_to_points_to_sinks()

list malloc_to_points_to_sinks ( expression  e,
pt_map  in 
)

Heap modelling.

FI: lots of issues here; the potential cast is lost...

FI: the high-level switch I have added to understand the management of options is performed at a much much lower level, which may be good or not. I do not think it's good for readbility, but factoring is good. See malloc_to_abstract_location()

e is the arguments of the malloc call...

Basic heap modelling

ABSTRACT_HEAP_LOCATIONS:

"unique": do not generate heap abstract locations for each line number...

"insensitive": control path are not taken into account; all malloc() located in one function are equivalent.

"flow-sensitive": take into account the line number or the occurence number?

"context-sensitive": take into account the call stack; not implemented

ALIASING_ACROSS_TYPE: you should have one heap per type if aliasing across type is forbidden. The impact of its composition with the previous property is not specified...

The C standard specifies that all pointers that are allocated in the heap have the value "indeterminate".

Parameters
inn

Definition at line 1231 of file sinks.c.

1233 {
1234  list sinks = NIL;
1235  const char * opt = get_string_property("ABSTRACT_HEAP_LOCATIONS");
1236  //bool type_sensitive_p = !get_bool_property("ALIASING_ACROSS_TYPES");
1237 
1238  if(same_string_p(opt, "unique")) {
1240  }
1241  else if(same_string_p(opt, "insensitive")) {
1243  }
1244  else if(same_string_p(opt, "flow-sensitive")) {
1246  }
1247  else if(same_string_p(opt, "context-sensitive")) {
1248  // Context sensitivity is dealt with in the translation functions, not here
1250  }
1251  else {
1252  pips_user_error("Unexpected value \"%s\" for Property ABSTRACT_HEAP_LOCATION."
1253  "Possible values are \"unique\", \"insensitive\","
1254  "\"flow-sensitive\", \"context-sensitive\".\n", opt);
1255  }
1256 
1257  /* The C standard specifies that all pointers that are allocated in
1258  the heap have the value "indeterminate". */
1259  FOREACH(CELL, c, sinks) {
1261  entity v = reference_variable(r);
1263  FOREACH(CELL, source, l) {
1264  list psl = points_to_source_to_sinks(source, in, false);
1265  cell sink = cell_to_nowhere_sink(source);
1267  if(ENDP(psl)) {
1268  pt = make_points_to(source, sink,
1271  }
1272  else {
1273  pt = make_points_to(source, sink,
1276  gen_free_list(psl);
1277  }
1278  add_arc_to_pt_map(pt, in);
1279  }
1280  }
1281 
1282  return sinks;
1283 }
approximation make_approximation_exact(void)
Definition: effects.c:185
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)
#define add_arc_to_pt_map(a, s)
cell cell_to_nowhere_sink(cell source)
assuming source is a reference to a pointer, build the corresponding sink when the pointer is not ini...
char * get_string_property(const char *)
#define pips_user_error
Definition: misc-local.h:147
#define same_string_p(s1, s2)
list points_to_source_to_sinks(cell, pt_map, bool)
Build the sinks of source "source" according to the points-to graphs.
list variable_to_pointer_locations(entity)
variable.c
Definition: variable.c:66
#define points_to_undefined
list unique_malloc_to_points_to_sinks(expression e)
FI->AM: is "unique" multiple when ALIASING_ACROSS_TYPE is set to false?
Definition: sinks.c:1292
list insensitive_malloc_to_points_to_sinks(expression e)
FI->AM: what's the difference with the previous option? Reference to your dissertation?
Definition: sinks.c:1312

References add_arc_to_pt_map, CELL, cell_any_reference(), cell_to_nowhere_sink(), ENDP, flow_sensitive_malloc_to_points_to_sinks(), FOREACH, gen_free_list(), get_string_property(), insensitive_malloc_to_points_to_sinks(), make_approximation_exact(), make_approximation_may(), make_descriptor_none(), make_points_to(), NIL, pips_user_error, points_to_source_to_sinks(), points_to_undefined, reference_variable, same_string_p, unique_malloc_to_points_to_sinks(), and variable_to_pointer_locations().

Referenced by binary_intrinsic_call_to_points_to_sinks(), and unary_intrinsic_call_to_points_to_sinks().

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

◆ nary_intrinsic_call_to_points_to_sinks()

list nary_intrinsic_call_to_points_to_sinks ( call  c,
pt_map  in 
)
Parameters
inn

Definition at line 640 of file sinks.c.

641 {
642  entity f = call_function(c);
643  list sinks = NIL;
644  pips_internal_error("Not implemented for %p and %p\n", c, in);
645  if(ENTITY_COMMA_P(f)) {
646  ;
647  }
648  return sinks;
649 }

References call_function, ENTITY_COMMA_P, f(), NIL, and pips_internal_error.

Referenced by intrinsic_call_to_points_to_sinks().

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

◆ pointer_reference_to_points_to_sinks()

list pointer_reference_to_points_to_sinks ( reference  r,
pt_map  in,
bool  eval_p 
)

What to do when a pointer "p" is dereferenced within a reference "r".

If p is a scalar pointer, p[i] is equivalent to *(p+i) and p[i][j] to *(*(p+i)+j).

If p is a 2-D array of pointers, p[i], p[i][j] do not belong here. But, p[i][j][k] is equivalent to *(p[i][j]+k) and p[i][j][k][l] to *(*(p[i][j]+k)+l).

The equivalent expression is fully allocated to be freed at the end. Which may cause problems if the points-to analysis re-use parts of the internal data structure...

The normalization could have been performed by the parser, but PIPS is source-to-source for the benefit of its human user.

Parameters
inn
eval_pval_p

Definition at line 709 of file sinks.c.

710 {
711  list sinks = NIL;
713 
714  if(eval_p)
715  sinks = expression_to_points_to_sinks(pae, in);
716  else
717  sinks = expression_to_points_to_sources(pae, in);
718 
719  free_expression(pae);
720 
721  return sinks;
722 }
expression pointer_reference_to_expression(reference r)
Assume p is a pointer.
Definition: expression.c:4004

References expression_to_points_to_sinks(), expression_to_points_to_sources(), free_expression(), NIL, and pointer_reference_to_expression().

Referenced by reference_to_points_to_sinks().

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

◆ pointer_subscript_to_expression()

expression pointer_subscript_to_expression ( cell  c,
list  csl 
)

Allocate a new expression based on the reference in "c" and the subscript list "csl".

No sharing with the arguments. The pointer subscripts are transformed into pointer arithmetic and dereferencements.

Parameters
cslsl

Definition at line 1430 of file sinks.c.

1431 {
1434 
1435  FOREACH(EXPRESSION, pse, csl) {
1436  expression npse = copy_expression(pse);
1439  }
1440  return pae;
1441 }
#define DEREFERENCING_OPERATOR_NAME
Definition: ri-util-local.h:93
#define unary_intrinsic_expression(name, e)
Building quickly bool expressions, FC.
#define PLUS_C_OPERATOR_NAME
expression reference_to_expression(reference r)
Definition: expression.c:196

References binary_intrinsic_expression, cell_any_reference(), copy_expression(), copy_reference(), DEREFERENCING_OPERATOR_NAME, EXPRESSION, FOREACH, PLUS_C_OPERATOR_NAME, reference_to_expression(), and unary_intrinsic_expression.

Referenced by subscript_to_points_to_sinks().

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

◆ points_to_anywhere_sinks()

list points_to_anywhere_sinks ( type  t)

Definition at line 102 of file sinks.c.

103 {
104  entity ne;
105  if(type_undefined_p(t))
106  ne = entity_all_locations();
107  else
109  return entity_to_sinks(ne);
110 }
entity entity_all_locations()
eturn ANY_MODULE:ANYWHERE (the top of the lattice)
#define type_undefined_p(x)
Definition: ri.h:2884
list entity_to_sinks(entity e)
allocate a new list of sinks with one element, abstract or concrete, e.
Definition: sinks.c:72

References entity_all_locations(), entity_to_sinks(), entity_typed_anywhere_locations(), and type_undefined_p.

Referenced by call_to_points_to_sinks().

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

◆ points_to_null_sinks()

list points_to_null_sinks ( void  )

The null location is not typed. The impact on dependence test is not clear.

Definition at line 87 of file sinks.c.

88 {
89  /* The null location is not typed. The impact on dependence test is
90  not clear. */
92  return entity_to_sinks(ne);
93 }

References entity_null_locations(), and entity_to_sinks().

Referenced by call_to_points_to_sinks().

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

◆ process_casted_sinks()

static list process_casted_sinks ( list  sinks,
type  t 
)
static

The types are really incompatible, let's use the type lattice, max_type(cct, mct)... if it were implemented

Could we do better for a cast to (void *)? See cast03.

Definition at line 979 of file sinks.c.

980 {
982  list nsinks = NIL;
983  // You may have to update the subscript lists to fit the type
984  // This can only be done on *copies* of references included into
985  // the arcs of the points-to graph
986  FOREACH(CELL, c, sinks) {
987  if(!null_cell_p(c) && !nowhere_cell_p(c) && !anywhere_cell_p(c)) {
989  if(array_pointer_type_equal_p(pt, cct))
990  ; // nothing to do
991  else {
993  if(overloaded_type_p(mct))
994  ; // nothing to do... to be checked
995  else {
996  // You should try to add or remove zero subscripts till the expected
997  // type is reached.
1000  if(!type_void_p(pt)
1003 
1004  if(array_pointer_type_equal_p(pt, mct))
1005  ; // nothing to do
1006  else if(array_type_p(mct)
1008  ; // nothing to do
1009  else {
1010  pips_internal_error("Not implemented yet.\n");
1011  }
1012  }
1013  else {
1014  /* The types are really incompatible, let's use the
1015  * type lattice, max_type(cct, mct)... if it were implemented
1016  *
1017  * Could we do better for a cast to (void *)? See cast03.
1018  */
1021  nsinks = CONS(CELL, nc, nsinks);
1022  // pips_internal_error("Cast handling failure 1.\n");
1023  }
1024  }
1025  }
1026  }
1027  }
1028 
1029  return nsinks;
1030 }
cell make_anywhere_points_to_cell(type)
Function storing points to information attached to a statement.
Definition: points_to.c:87
void complete_points_to_reference_with_zero_subscripts(reference)
Definition: points_to.c:745
type make_scalar_overloaded_type(void)
Definition: type.c:726
bool overloaded_type_p(type)
Returns true if t is a variable type with a basic overloaded.
Definition: type.c:2666
#define type_void_p(x)
Definition: ri.h:2959

References adapt_reference_to_type(), anywhere_cell_p(), array_pointer_type_equal_p(), array_type_p(), array_type_to_element_type(), CELL, cell_any_reference(), complete_points_to_reference_with_zero_subscripts(), compute_basic_concrete_type(), CONS, FOREACH, make_anywhere_points_to_cell(), make_scalar_overloaded_type(), NIL, nowhere_cell_p(), null_cell_p(), overloaded_type_p(), pips_internal_error, points_to_cell_to_concrete_type(), points_to_context_statement_line_number(), type_to_pointed_type(), and type_void_p.

Referenced by cast_to_points_to_sinks().

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

◆ process_casted_sources()

static list process_casted_sources ( list  sinks,
type  t 
)
static

FI: I am not sure that process_casted_sources() is nor should be different from process_casted_sinks()

Cell c is OK if it points towards cells of type compatible with the type pointed to by type t

Update "sinks" with "dsl" and "nsl"

Definition at line 1035 of file sinks.c.

1036 {
1037  list nsinks = NIL; // New sink list
1038  FOREACH(CELL, c, sinks) {
1039  if(!null_cell_p(c) && !nowhere_cell_p(c) && !anywhere_cell_p(c)) {
1041  if(array_pointer_type_equal_p(t, cct))
1042  ; // nothing to do
1043  else { // We should create a stub of the proper type because a
1044  // reference cannot include the address-of operator, "&"
1045  if(pointer_type_p(t) && array_type_p(cct)) {
1049  ;
1050  else
1051  pips_internal_error("Cast handling failure 2.\n");
1052  }
1053  else {
1054  if(type_void_p(cct)) {
1055  /* Cell c is OK if it points towards cells of type
1056  compatible with the type pointed to by type t*/
1057  }
1058  else {
1061  nsinks = CONS(CELL, nc, nsinks);
1062  break;
1063  //pips_internal_error("Not implemented yet: stub with proper type needed.\n");
1064  }
1065  }
1066  }
1067  }
1068  }
1069 
1070  /* Update "sinks" with "dsl" and "nsl" */
1071 
1072  return nsinks;
1073 }

References adapt_reference_to_type(), anywhere_cell_p(), array_pointer_type_equal_p(), array_type_p(), CELL, cell_any_reference(), complete_points_to_reference_with_zero_subscripts(), CONS, FOREACH, make_anywhere_points_to_cell(), make_scalar_overloaded_type(), NIL, nowhere_cell_p(), null_cell_p(), pips_internal_error, pointer_type_p(), points_to_cell_to_concrete_type(), points_to_context_statement_line_number(), and type_void_p.

Referenced by cast_to_points_to_sinks().

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

◆ range_to_points_to_sinks()

list range_to_points_to_sinks ( range  r,
pt_map  in 
)
Parameters
inn

Definition at line 1626 of file sinks.c.

1627 {
1628  list sinks = NIL;
1629  pips_user_warning("Not implemented yet for %p and %p\n", r, in);
1630  return sinks;
1631 }

References NIL, and pips_user_warning.

Referenced by expression_to_points_to_cells().

+ Here is the caller graph for this function:

◆ reference_may_points_to_null_p()

bool reference_may_points_to_null_p ( reference  r,
pt_map  in 
)
Parameters
inn

Definition at line 1873 of file sinks.c.

1874 {
1875  list sinks = reference_to_sinks(r, in, false);
1876  bool may_p = false;
1877 
1878  FOREACH(CELL, c, sinks) {
1879  if(null_cell_p(c)) {
1880  may_p = true;
1881  break;
1882  }
1883  }
1884 
1885  gen_free_list(sinks);
1886  return may_p;
1887 }
list reference_to_sinks(reference, pt_map, bool)

References CELL, FOREACH, gen_free_list(), null_cell_p(), and reference_to_sinks().

Referenced by reference_condition_to_points_to().

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

◆ reference_must_points_to_null_p()

bool reference_must_points_to_null_p ( reference  r,
pt_map  in 
)
Parameters
inn

Definition at line 1859 of file sinks.c.

1860 {
1861  list sinks = reference_to_sinks(r, in, false);
1862  bool must_p = false;
1863 
1864  if(gen_length(sinks)==1) {
1865  // It is a must arc
1866  cell c = CELL(CAR(sinks));
1867  must_p = null_cell_p(c);
1868  }
1869  gen_free_list(sinks);
1870  return must_p;
1871 }

References CAR, CELL, gen_free_list(), gen_length(), null_cell_p(), and reference_to_sinks().

Referenced by reference_condition_to_points_to().

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

◆ reference_to_points_to_sinks()

list reference_to_points_to_sinks ( reference  r,
type  et,
pt_map  in,
bool  eval_p,
bool  constant_p 
)

Returns a list of memory cells "sinks" possibly accessed by the evaluation of reference "r".

No sharing between the returned list "sinks" and the reference "r" or the points-to set "in".

Examples if eval_p==false: x->x, t[1]->t[1], t[1][2]->t[1][2], p->p...

Examples if eval_p==true: x->error, t[1]->t[1][0], t[1][2]->t[1][2][0], p->p[0]...

If constant_p, stored-dependent subscript expressions are replaced by "*" and store-independent expressions are replaced by their values, e.g. x[3+4]->x[7]. Else, subscript expressions are left unchanged. Motivation: constant_p==true for points-to computation, and false for the translation of effects. In the latter case, the transformation into a constant reference is postponed.

Issue: let's assume "t" to be an array "int t[10][10[10];". The C language is (too) flexible. If "p" is an "int ***p;", the impact of assignment "p=t;" leads to "p points-to t" or "p points-to t[0]" or "p points-to t[0][0][0]". Two different criteria can be used: the compatibiliy of the pointer type and the pointed cell type, or the equality of the pointer value and of the pointed cell address.

In the first case, t->t[0]->t[0][0]->t[0][0][0].

In the second case, t->t[0][0][0], t[0]->t[0][0][0], t[0][0]->t[0][0][0].

FI: I do not trust this function. It is already too long. And I am not confident the case disjunction is correct/well chosen.

Two proper possibilities: an array of pointers fully subscribed or any other kind of array partially subscribed. And an unsuitable one: an integer value...

No matter what, the target is obtained by adding a 0 subscript

FI: I do not know if the subscript removal impact the handling of loops by the points-to analysis; see Points-to/array07.c

What is the value of the subscript expression?

scalar case, rhs is already a lvalue

An array name can be used as pointer constant

We should add null indices according to its number of dimensions

This function may be called from the effect library via backward_translation_of_points_to_formal_context()

ips_assert("The expected type and the reference type are equal", array_pointer_type_equal_p(et, rt));

ips_assert("The expected type and the reference type are compatible", concrete_type_equal_p(et, rt));

Parameters
ett
inn
eval_pval_p
constant_ponstant_p

Definition at line 755 of file sinks.c.

758 {
759  list sinks = NIL;
760  entity e = reference_variable(r);
762  list sl = reference_indices(r);
763 
764  ifdebug(8) {
765  pips_debug(8, "Reference r = ");
766  print_reference(r);
767  fprintf(stderr, "\n");
768  }
769 
770  //bool to_be_freed;
772  //type rt = compute_basic_concrete_type(srt);
773  if(false && eval_p && !pointer_type_p(rt)) {
774  // There must be a type mismatch
775  pips_user_error("Type mmismatch for reference \"%s\" at line %d.",
778  }
779  else {
780 
781  // FI: conditional01.c shows that the C parser may not generate the
782  // right construct when a scalar or an pointer is indexed.
783  // FI: maybe more difficult to guess of array of pointers...
784  if(pointer_type_p(t) && !ENDP(sl)) {
785  sinks = pointer_reference_to_points_to_sinks(r, in, eval_p);
786  }
787  else if(array_of_pointers_type_p(t)
789  sinks = pointer_reference_to_points_to_sinks(r, in, eval_p);
790  }
791  else {
792  // FI: to be checked otherwise?
793  //expression rhs = expression_undefined;
794  if (!ENDP(sl)) { // FI: I'm not sure this is a useful disjunction
795  /* Two proper possibilities: an array of pointers fully subscribed
796  or any other kind of array partially subscribed. And an
797  unsuitable one: an integer value... */
798  int nd = NumberOfDimension(e);
799  int rd = (int) gen_length(sl);
800  if (nd > rd) {
801  /* No matter what, the target is obtained by adding a 0 subscript */
802  /* FI: I do not know if the subscript removal impact the
803  handling of loops by the points-to analysis; see
804  Points-to/array07.c */
805  reference nr =
807  cell nc = make_cell_reference(nr);
808  // was:
809  // for(int i=rd; eval_p && i<nd; i++) { // FI: not efficient
810  if (eval_p)
811  {
814  CONS(EXPRESSION, ze, NIL));
815  // FC: this makes the loop to exit on the first iteration?
816  // replaced by an equivalent if, but probably a bug.
817  // i = nd
818  }
819  sinks = CONS(CELL, nc, NIL);
820  }
821  else if (nd == rd) {
822  // FI: eval_p is not used here...
824  cell nc = make_cell_reference(nr);
825  if(eval_p) {
826  sinks = source_to_sinks(nc, in, true); // FI: allocate a new copy
827  }
828  else
829  sinks = CONS(CELL, nc, NIL);
830  }
831  else { // rd is too big
832  // Could be a structure with field accesses expressed as indices
833  // Can be a dereferenced pointer, "p[0]" instead of "*p"
834  type et = ultimate_type(entity_type(e));
835  if(struct_type_p(et)) {
836  reference nr = copy_reference(r);
837  cell nc = make_cell_reference(nr);
838  if(eval_p) {
839  sinks = source_to_sinks(nc, in, true);
840  /*
841  expression ze = int_to_expression(0);
842  reference_indices(nr) = gen_nconc(reference_indices(nr),
843  CONS(EXPRESSION, ze, NIL));
844  */
845  }
846  else
847  sinks = CONS(CELL, nc, NIL);
848  }
849  else if(pointer_type_p(et)) {
850  pips_assert("One subscript", rd==1 && nd==0);
851  /* What is the value of the subscript expression? */
852  //expression sub = EXPRESSION(CAR(reference_indices(r)));
853  // FI: should we try to evaluate the subscript statically?
854  // If the expression is not zero, the target is unchanged but
855  // * must be used as subscript in sinks
856 
857  entity v = reference_variable(r);
858  reference nr = make_reference(v, NIL);
859  cell nc = make_cell_reference(nr);
860  if(eval_p) {
861  // FI: two rounds of source_to_sinks() I guess
862  list sinks_1 = source_to_sinks(nc, in, true);
863  FOREACH(CELL, c, sinks_1) {
864  list sinks_2 = source_to_sinks(c, in, true);
865  sinks = gen_nconc(sinks, sinks_2);
866  }
867  }
868  else {
869  // FI: what's going to happen with subscript expressions?
870  // FI: strict typing?
871  sinks = source_to_sinks(nc, in, true);
872  }
873  // FI FI FI
874  ;
875  }
876  else {
877  // FI: you may have an array of struct to begin with, and of
878  // structs including other structs
879  // Handle it just like a struct
880  //pips_user_error("Too many subscript expressions for array \"%s\".\n",
881  // entity_user_name(e));
882  reference nr = copy_reference(r);
883  cell nc = make_cell_reference(nr);
884  if(eval_p) {
885  sinks = source_to_sinks(nc, in, true);
886  }
887  else
888  sinks = CONS(CELL, nc, NIL);
889  }
890  }
891  }
892  else {
893  /* scalar case, rhs is already a lvalue */
894  if(scalar_type_p(t)) {
896  if(eval_p) {
897  // FI: we have a pointer. It denotes another location.
898  sinks = source_to_sinks(nc, in, true);
899  // FI: in some cases, nc is reused in sinks
900  if(!gen_in_list_p(nc, sinks))
901  free_cell(nc);
902  }
903  else {
904  // FI: without dereferencing
905  sinks = CONS(CELL, nc, NIL);
906  }
907  }
908  else if(array_type_p(t)) { // FI: not OK with typedef
909  /* An array name can be used as pointer constant */
910  /* We should add null indices according to its number of dimensions */
911  reference nr = copy_reference(r);
912  cell nc = make_cell_reference(nr);
913  if (true) {
914  // int n = NumberOfDimension(e);
915  // int rd = (int) gen_length(reference_indices(r));
916  // FI: not efficient and quite convoluted!
917  // FC: brain damaged, this is not a loop, compiler complains
918  // for(int i=rd; eval_p && i<n; i++) {
919  if (eval_p)
920  {
921  reference_indices(nr) =
924  // FC: this assignment make the loop exit on the first iteration?
925  // i = n; // to be type compatible: add at most one subscript
926  }
927  }
928  else {
929  // DEAD CODE
930  // FI: this is not always a good thing. See arithmetic11.c.
931  // The type of the source is needed to determine the number
932  // of zero subscripts...
934  }
935  sinks = CONS(CELL, nc, NIL);
936  }
937  else {
938  pips_internal_error("Pointer assignment from something "
939  "that is not a pointer.\n Could be a "
940  "function assigned to a functional pointer.\n");
941  }
942  }
943  }
944 
945  if(ENDP(sinks)) {
946  /* This function may be called from the effect library via
947  backward_translation_of_points_to_formal_context() */
949  pips_user_warning("Some kind of execution error has been encountered at line %d.\n",
951  }
952  else {
953  pips_user_warning("Some kind of execution error has been encountered.\n");
954  }
955  clear_pt_map(in);
956  points_to_graph_bottom(in) = true;
957  }
958  }
959 
960  /*pips_assert("The expected type and the reference type are equal",
961  array_pointer_type_equal_p(et, rt)); */
962  /*pips_assert("The expected type and the reference type are compatible",
963  concrete_type_equal_p(et, rt)); */
964  pips_assert("The expected type and the reference type are compatible",
965  type_structurally_equal_p(et, rt));
966  check_type_of_points_to_cells(sinks, rt, eval_p);
967 
968  //if(to_be_freed) free_type(srt);
969 
970  ifdebug(8) {
971  pips_debug(8, "Resulting cells: ");
972  print_points_to_cells(sinks);
973  fprintf(stderr, "\n");
974  }
975 
976  return sinks;
977 }
type points_to_reference_to_concrete_type(reference)
Definition: type.c:685
string effect_reference_to_string(reference)
Definition: prettyprint.c:155
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734
void check_type_of_points_to_cells(list sinks, type ct, bool eval_p)
Check that all cells in list "sinks" are compatible with type "ct" if "eval_p" is false,...
Definition: expression.c:1214
bool statement_points_to_context_defined_p(void)
Definition: statement.c:145
void print_reference(reference r)
Definition: expression.c:142
#define print_points_to_cells(x)
Definition: print.c:379
reference reference_with_store_independent_indices(reference r)
Return by side effect a reference whose memory locations includes the memory locations of r in case t...
Definition: expression.c:3045
type ultimate_type(type)
Definition: type.c:3466
bool array_of_pointers_type_p(type)
Definition: type.c:3025
bool scalar_type_p(type)
Definition: type.c:2955
int variable_dimension_number(variable)
Definition: type.c:5632
bool type_structurally_equal_p(type, type)
Type t1 and t2 are equal if their basic concrete components are equal.
Definition: type.c:586
bool struct_type_p(type)
Returns true if t is of type derived and if the derived type is a struct.
Definition: type.c:3121
int NumberOfDimension(entity)
Definition: size.c:588
#define reference_indices(x)
Definition: ri.h:2328
list pointer_reference_to_points_to_sinks(reference r, pt_map in, bool eval_p)
What to do when a pointer "p" is dereferenced within a reference "r".
Definition: sinks.c:709
reference simplified_reference(reference r)
Return NULL as sink.
Definition: sinks.c:670

References array_of_pointers_type_p(), array_type_p(), CELL, check_type_of_points_to_cells(), clear_pt_map, CONS, constant_p(), copy_reference(), effect_reference_to_string(), ENDP, entity_basic_concrete_type(), entity_type, EXPRESSION, FOREACH, fprintf(), free_cell(), gen_in_list_p(), gen_length(), gen_nconc(), ifdebug, int, int_to_expression(), make_cell_reference(), make_reference(), NIL, NumberOfDimension(), pips_assert, pips_debug, pips_internal_error, pips_user_error, pips_user_warning, pointer_reference_to_points_to_sinks(), pointer_type_p(), points_to_cell_add_zero_subscripts(), points_to_context_statement_line_number(), points_to_graph_bottom, points_to_reference_to_concrete_type(), print_points_to_cells, print_reference(), reference_indices, reference_variable, reference_with_store_independent_indices(), scalar_type_p(), simplified_reference(), source_to_sinks(), statement_points_to_context_defined_p(), struct_type_p(), type_structurally_equal_p(), type_variable, ultimate_type(), and variable_dimension_number().

Referenced by expression_to_points_to_cells(), and subscripted_reference_to_points_to().

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

◆ reset_heap_model()

void reset_heap_model ( void  )

Definition at line 1185 of file sinks.c.

1186 {
1188  malloc_counter = 0;
1189 }
#define statement_undefined
Definition: ri.h:2419

References malloc_counter, malloc_statement, and statement_undefined.

Referenced by statement_to_points_to().

+ Here is the caller graph for this function:

◆ simplified_reference()

reference simplified_reference ( reference  r)

Return NULL as sink.

Double definition... list points_to_null_sinks() { entity ne = entity_null_locations(); reference nr = make_reference(ne, NIL); cell nc = make_cell_reference(nr); list sinks = CONS(CELL, nc, NIL); return sinks; } Points-to cannot used any kind of reference, just constant references.

For instance, "x[i]" is transformed into "x[*]" because the value of "i" is unknown. x[3+4] may be transformed into x[7].

A new referencec is allocated. Reference "r" is unchanged.

Definition at line 670 of file sinks.c.

671 {
672  list sl = reference_indices(r);
673  list nsl = NIL;
674 
675  FOREACH(EXPRESSION, s, sl) {
676  value v = EvalExpression(s);
679  int cs = constant_int(value_constant(v));
680  ns = int_to_expression(cs);
681  }
682  else {
684  }
685  nsl = gen_nconc(nsl, CONS(EXPRESSION, ns, NIL));
686  }
687 
688  entity var = reference_variable(r);
689  reference nr = make_reference(var, nsl);
690  return nr;
691 }
value EvalExpression(expression e)
Evaluate statically an expression.
Definition: eval.c:108
#define value_constant_p(x)
Definition: ri.h:3071
#define expression_undefined
Definition: ri.h:1223

References CONS, constant_int, constant_int_p, EvalExpression(), EXPRESSION, expression_undefined, FOREACH, gen_nconc(), int_to_expression(), make_reference(), make_unbounded_expression(), NIL, reference_indices, reference_variable, value_constant, and value_constant_p.

Referenced by reference_to_points_to_sinks().

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

◆ sizeofexpression_to_points_to_sinks()

list sizeofexpression_to_points_to_sinks ( sizeofexpression  soe,
type et   __attribute__(unused),
pt_map  in 
)

Definition at line 1139 of file sinks.c.

1142 {
1143  list sinks = NIL;
1144  // FI: seems just plain wrong for a sink
1145  // pips_internal_error("Not implemented yet");
1146  if( sizeofexpression_expression_p(soe) ){
1148  sinks = expression_to_points_to_sinks(ne, in);
1149  }
1150  if( sizeofexpression_type_p(soe) ){
1152  // FI: a better job could be done. A stub should be allocated in
1153  // the formal context of the procedure
1154  if(pointer_type_p(t)) {
1156  cell c = make_anywhere_cell(pt);
1157  sinks = CONS(CELL, c, NIL);
1158  }
1159  else
1160  pips_internal_error("Unexpected type.\n");
1161  }
1162  return sinks;
1163 }
#define sizeofexpression_type(x)
Definition: ri.h:2406
#define sizeofexpression_expression(x)
Definition: ri.h:2409
#define sizeofexpression_expression_p(x)
Definition: ri.h:2407
#define sizeofexpression_type_p(x)
Definition: ri.h:2404

References CELL, compute_basic_concrete_type(), CONS, expression_to_points_to_sinks(), make_anywhere_cell(), NIL, pips_internal_error, pointer_type_p(), sizeofexpression_expression, sizeofexpression_expression_p, sizeofexpression_type, sizeofexpression_type_p, and type_to_pointed_type().

Referenced by expression_to_points_to_cells().

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

◆ subscript_to_points_to_sinks()

list subscript_to_points_to_sinks ( subscript  s,
type  et,
pt_map  in,
bool  eval_p 
)

Generate the corresponding points-to reference(s).

All access operators such as ., ->, * are replaced by subscripts.

See Strict_typing.sub/assigment11.c: the index is not put back at the right place. It would be easy (?) to fix it in this specific case, not forgetting the field subscripts..., but I do not see how to handle general stubs with artificial dimensions...

FI: In many cases, you do need the source. However, you have different kind of sources because "x" and "&x[0]" are synonyms and because you sometimes need "x" and some other times "&x[0]".

If the first dimension is unbounded, it has (probably) be added because of a pointer. A zero subscript is also added.

Add a zero subscript

Add subscript when possible. For typing reason, typed anywhere cell should be subscripted.

Add the subscripts

The reference "p[i][j]" is transformed into an expression "*(*(p+i)+j)" if "p" is really a pointer expression, not a partial array reference.

Parameters
ett
inn
eval_pval_p

Definition at line 1451 of file sinks.c.

1455 {
1456  expression a = subscript_array(s);
1457  bool to_be_freed;
1458  // If ever a pointer is deferenced somewhere, at is not going to
1459  // take into account the extra dimensions needed for pointer arithmetics
1460  type at = points_to_expression_to_type(a, &to_be_freed);
1461 
1462  /* FI: In many cases, you do need the source. However, you have
1463  * different kind of sources because "x" and "&x[0]" are synonyms
1464  * and because you sometimes need "x" and some other times "&x[0]".
1465  */
1466  list sources = expression_to_points_to_sources(a, in);
1467 
1468  list sl = subscript_indices(s);
1470  list sinks = NIL;
1471  list i_sources = NIL;
1472  bool eval_performed_p = false;
1473 
1474  /* If the first dimension is unbounded, it has (probably) be added
1475  because of a pointer. A zero subscript is also added. */
1476  bool strict_p = get_bool_property("POINTS_TO_STRICT_POINTER_TYPES");
1477  if(array_type_p(at) && !strict_p) {
1478  variable v = type_variable(at);
1480  if(unbounded_dimension_p(d1)) {
1481  /* Add a zero subscript */
1483  csl = CONS(EXPRESSION, z, csl);
1484  }
1485  }
1486 
1487  /* Add subscript when possible. For typing reason, typed anywhere
1488  cell should be subscripted. */
1489  FOREACH(CELL, c, sources) {
1490  // FI: some other lattice abstract elements should be removed like
1491  // STACK, DYNAMIC
1492  if(!nowhere_cell_p(c) && !null_cell_p(c) && !anywhere_cell_p(c)
1493  && !all_heap_locations_cell_p(c)) {
1494  bool to_be_freed2;
1495  type t = points_to_cell_to_type(c, &to_be_freed2);
1497  entity v = reference_variable(r);
1498 
1499  if(array_type_p(at)) {
1500  list ncsl = gen_full_copy_list(csl);
1501  if(entity_stub_sink_p(v)) {
1502  // argv03
1504 
1505  // FI: an horror... fixing a design mistake by a kludge...
1506  // useful for argv03, disastrous for dereferencing08
1507  if(!points_to_array_reference_p(r)) {
1509  ;
1510  else
1511  pips_internal_error("Subscript handling failure 1.\n");
1512  }
1513  // FI: the update depends on the sink model
1514  // points_to_reference_update_final_subscripts(r, ncsl);
1516 
1517  // FI: let's add the zero subscripts again...
1518  // points_to_cell_add_zero_subscripts(c);
1520  }
1521  else {
1522  // Expression "a" does not require any dereferencing, add
1523  // the new indices (Strict_typing.sub/assignment11.c
1524 
1525  // FI: an horror... fixing a design mistake by a kludge...
1527  ;
1528  else
1529  pips_internal_error("Subscript handling failure 1.\n");
1530 
1532  }
1533 
1534  i_sources = CONS(CELL, c, i_sources);
1535  }
1536  else if(struct_type_p(at)) { // Just add the subscript, old version
1537  list ncsl = gen_full_copy_list(csl);
1538  if(entity_stub_sink_p(v)) {
1540  // FI: the update depends on the sink model
1542  }
1543  else {
1544  // Expression "a" does not require any dereferencing, add
1545  // the new indices (Strict_typing.sub/assignment11.c
1547  }
1548  i_sources = CONS(CELL, c, i_sources);
1549  }
1550  else if(pointer_type_p(at)) {
1553  /* Add the subscripts */
1554  list ncsl = gen_full_copy_list(csl);
1556  eval_performed_p = true;
1557  i_sources = CONS(CELL, c, i_sources);
1558  }
1559  else {
1560  /* The reference "p[i][j]" is transformed into an expression
1561  "*(*(p+i)+j)" if "p" is really a pointer expression, not a
1562  partial array reference. */
1563  //expression pae = pointer_subscript_to_expression(c, csl);
1564  // FI: I guess csl might have to be freed...
1565  list nsl = gen_full_copy_list(sl);
1567  i_sources = expression_to_points_to_sources(pae, in);
1568  free_expression(pae);
1569  }
1570  }
1571  else {
1572  pips_internal_error("Unexpected case.\n");
1573  }
1574  if(to_be_freed2) free_type(t);
1575  }
1576  else if(anywhere_cell_p(c)
1577  || all_heap_locations_cell_p(c)) {
1578  i_sources = CONS(CELL, c, i_sources);
1579  }
1580  }
1581 
1582  gen_full_free_list(csl);
1583  gen_free_list(sources);
1584 
1585  if(eval_p && !eval_performed_p) {
1586  FOREACH(CELL, source, i_sources) {
1587  bool to_be_freed;
1588  type t = points_to_cell_to_type(source, &to_be_freed);
1589  reference r = cell_any_reference(source);
1591  //points_to_cell_add_zero_subscripts(source);
1592  //adapt_reference_to_type(r, at, points_to_context_statement_line_number);
1595  CONS(EXPRESSION, z, NIL));
1596  sinks = gen_nconc(sinks, CONS(CELL, source, NIL));
1597  }
1598  else if(pointer_type_p(t)) {
1599  // A real pointer, not an under-subscripted array
1600  list pointed = source_to_sinks(source, in, true);
1601  sinks = gen_nconc(sinks, pointed);
1602  }
1603  else {
1604  // FI: Pretty bad wrt sharing and memory leaks
1605  sinks = gen_nconc(sinks, CONS(CELL, source, NIL));
1606  }
1607  if(to_be_freed) free_type(t);
1608  }
1609  }
1610  else
1611  sinks = i_sources;
1612 
1613  if(to_be_freed) free_type(at);
1614 
1615  if(ENDP(sinks)) {
1616  pips_user_warning("Some kind of execution error has been encountered.\n");
1617  clear_pt_map(in);
1618  points_to_graph_bottom(in) = true;
1619  }
1620 
1621  check_type_of_points_to_cells(sinks, et, eval_p);
1622 
1623  return sinks;
1624 }
bool entity_stub_sink_p(entity e)
test if an entity is a stub sink for a formal parameter e.g.
bool all_heap_locations_cell_p(cell)
Definition: effects.c:432
bool points_to_array_reference_p(reference)
Is this a reference to an array or a reference to a pointer? This is not linked to the type of the re...
Definition: points_to.c:599
void points_to_reference_update_final_subscripts(reference, list)
Substitute the subscripts "sl" in points-to reference "r" just after the last field subscript by "nsl...
Definition: points_to.c:278
expression make_zero_expression(void)
Make a zero expression.
Definition: expression.c:1212
bool unbounded_dimension_p(dimension dim)
bool unbounded_dimension_p(dim) input : a dimension of an array entity.
Definition: expression.c:1130
list subscript_expressions_to_constant_subscript_expressions(list sl)
make a full copy of the subscript expression list, preserve constant subscripts, replace non-constant...
Definition: expression.c:3981
#define subscript_indices(x)
Definition: ri.h:2563
#define subscript_array(x)
Definition: ri.h:2561
expression pointer_subscript_to_expression(cell c, list csl)
Allocate a new expression based on the reference in "c" and the subscript list "csl".
Definition: sinks.c:1430

References adapt_reference_to_type(), all_heap_locations_cell_p(), anywhere_cell_p(), array_type_p(), CAR, CELL, cell_any_reference(), check_type_of_points_to_cells(), clear_pt_map, complete_points_to_reference_with_zero_subscripts(), CONS, DIMENSION, ENDP, entity_stub_sink_p(), EXPRESSION, expression_to_points_to_sources(), FOREACH, free_expression(), free_type(), gen_free_list(), gen_full_copy_list(), gen_full_free_list(), gen_nconc(), get_bool_property(), make_zero_expression(), NIL, nowhere_cell_p(), null_cell_p(), pips_internal_error, pips_user_warning, pointer_subscript_to_expression(), pointer_type_p(), points_to_array_reference_p(), points_to_cell_to_type(), points_to_context_statement_line_number(), points_to_expression_to_type(), points_to_graph_bottom, points_to_reference_update_final_subscripts(), reference_indices, reference_variable, source_to_sinks(), struct_type_p(), subscript_array, subscript_expressions_to_constant_subscript_expressions(), subscript_indices, type_variable, unbounded_dimension_p(), and variable_dimensions.

Referenced by expression_to_points_to_cells().

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

◆ ternary_intrinsic_call_to_points_to_sinks()

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

Definition at line 594 of file sinks.c.

598 {
599  entity f = call_function(c);
600  list al = call_arguments(c);
601  list sinks = NIL;
602 
603  pips_assert("in is consistent", consistent_pt_map_p(in));
604 
605  if(ENTITY_CONDITIONAL_P(f)) {
606  //bool eval_p = true;
607  expression c = EXPRESSION(CAR(al));
608  pt_map in_t = full_copy_pt_map(in);
609  pt_map in_f = full_copy_pt_map(in);
610  in_t = condition_to_points_to(c, in_t, true);
611  in_f = condition_to_points_to(c, in_f, false);
612  expression e1 = EXPRESSION(CAR(CDR(al)));
613  expression e2 = EXPRESSION(CAR(CDR(CDR(al))));
614  list sinks1 = NIL;
615  if(!points_to_graph_bottom(in_t))
616  sinks1 = expression_to_points_to_cells(e1, in_t, eval_p, constant_p);
617  list sinks2 = NIL;
618  if(!points_to_graph_bottom(in_f))
619  sinks2 = expression_to_points_to_cells(e2, in_f, eval_p, constant_p);
620  sinks = gen_nconc(sinks1, sinks2);
621  // The "in" points-to graph may be enriched by both sub-graphs
622  //
623  // side-effects on in? memory leak...
625  points_to_graph_set(in_f));
627  points_to_graph_bottom(in) = true;
628  // The free is too deep. References from points-to arcs in in_t
629  // and in_f may have been integrated in sinks1 and/or sinks2
630  // See conditional05
631  clear_pt_map(in_t), clear_pt_map(in_f);
632  free_pt_map(in_t), free_pt_map(in_f);
633  }
634  // FI: any other ternary intrinsics?
635 
636  return sinks;
637 }
#define consistent_pt_map_p(s)
#define free_pt_map(pt)
pt_map condition_to_points_to(expression c, pt_map in, bool true_p)
Update points-to set "in" according to the content of the expression using side effects.
Definition: expression.c:2512
pt_map full_copy_pt_map(pt_map)
Definition: statement.c:67
set merge_points_to_set(set, set)
Merge two points-to sets.
#define points_to_graph_set(x)
#define ENTITY_CONDITIONAL_P(e)

References call_arguments, call_function, CAR, CDR, clear_pt_map, condition_to_points_to(), consistent_pt_map_p, constant_p(), ENTITY_CONDITIONAL_P, EXPRESSION, expression_to_points_to_cells(), f(), free_pt_map, full_copy_pt_map(), gen_nconc(), merge_points_to_set(), NIL, pips_assert, points_to_graph_bottom, and points_to_graph_set.

Referenced by intrinsic_call_to_points_to_sinks().

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

◆ unary_intrinsic_call_to_points_to_sinks()

list unary_intrinsic_call_to_points_to_sinks ( call  c,
pt_map  in,
bool  eval_p,
bool  constant_p 
)

We have to undo the impact of side effects performed when the arguments were analyzed for points-to information

Needed for dereferencing17.c, but not for properties03 because in the second case the dereferencing is delayed...

There is an issue with eval_p: since we are looking for sinks, we always have to dereference "a" at least once.

We have to undo the impact of side effects performed when the arguments were analyzed for points-to information

Parameters
inn
eval_pval_p
constant_ponstant_p

Definition at line 216 of file sinks.c.

217 {
218  entity f = call_function(c);
219  list al = call_arguments(c);
220  expression a = EXPRESSION(CAR(al));
221  list sinks = NIL;
222  pips_assert("One argument", gen_length(al)==1);
223  // pips_internal_error("Not implemented for %p and %p\n", c, in);
224  if (ENTITY_MALLOC_SYSTEM_P(f)) {
225  sinks = malloc_to_points_to_sinks(a, in);
226  }
227  else if (ENTITY_FREE_SYSTEM_P(f)) {
228  // FI: should be useless because free() returns void
229  sinks = CONS(CELL, make_nowhere_cell(), NIL);
230  }
231  else if(ENTITY_ADDRESS_OF_P(f)) {
232  // sinks = expression_to_constant_paths(statement_undefined, a, in);
233  if(eval_p) {
234  // sinks = expression_to_points_to_sources(a, in);
235  sinks = expression_to_points_to_cells(a, in, false, constant_p);
236  }
237  else {
238  // It is not possible in general to associate a reference to &e
239  // However, we might think of transforming &a[i][j] into a[i]
240  // and &a[0] into a...
241  sinks=NIL;
242  }
243  }
244  else if(ENTITY_DEREFERENCING_P(f)) {
245  if(pt_map_undefined_p(in)) {
247  cell c = make_anywhere_cell(t);
248  sinks = CONS(CELL, c, NIL);
249  }
250  else {
251  // FI: I do not understand why eval_p is only used for dereferencing...
252  // struct18.c sensitive to the test below
253  if(eval_p)
254  sinks = dereferencing_to_sinks(a, in, eval_p);
255  else {
256  sinks = dereferencing_to_sinks(a, in, eval_p);
257  // sinks = expression_to_points_to_sources(a, in);
258  }
259  }
260  }
261  else if(ENTITY_PRE_INCREMENT_P(f)) {
262  if(eval_p) {
263  sinks = expression_to_points_to_sinks(a, in);
264  // FI: this has already been done when the side effects are exploited
265  //expression one = int_to_expression(1);
266  //offset_cells(sinks, one);
267  //free_expression(one);
268  }
269  }
270  else if(ENTITY_PRE_DECREMENT_P(f)) {
271  if(eval_p)
272 {
273  sinks = expression_to_points_to_sinks(a, in);
274  //expression m_one = int_to_expression(-1);
275  //offset_cells(sinks, m_one);
276  //free_expression(m_one);
277  }
278  }
280  //sinks = expression_to_constant_paths(statement_undefined, a, in);
281  // arithmetic05: "q=p++;" p++ must be evaluated
282  //list sources = expression_to_points_to_sinks(a, in);
283  //if(gen_length(sources)==1) {
284  //cell source = CELL(CAR(sources));
285  if(eval_p) {
287  sinks = expression_to_points_to_sinks(a, in);
288  /* We have to undo the impact of side effects performed when the arguments were analyzed for points-to information */
291  delta = int_to_expression(-1);
292  else
293  delta = int_to_expression(1);
294  offset_points_to_cells(sinks, delta, dt);
295  free_expression(delta);
296  }
297  else {
298  if(false) {
299  /* Needed for dereferencing17.c, but not for properties03
300  because in the second case the dereferencing is
301  delayed... */
302  /* There is an issue with eval_p: since we are looking for
303  sinks, we always have to dereference "a" at least once. */
305  sinks = expression_to_points_to_sinks(a, in);
306  /* We have to undo the impact of side effects performed when the arguments were analyzed for points-to information */
309  delta = int_to_expression(-1);
310  else
311  delta = int_to_expression(1);
312  offset_points_to_cells(sinks, delta, dt);
313  free_expression(delta);
314  }
315  }
316  }
317  else {
318  // FI: to be continued
319  pips_internal_error("Unexpected unary pointer operator\n");
320  }
321 
322  return sinks;
323 }
cell make_nowhere_cell()
This file contains all the operators defining constant paths :
list dereferencing_to_sinks(expression a, pt_map in, bool eval_p)
Returns "sinks", the list of cells pointed to by expression "a" according to points-to graph "in".
#define ENTITY_FREE_SYSTEM_P(e)
#define ENTITY_DEREFERENCING_P(e)
#define ENTITY_PRE_DECREMENT_P(e)
#define ENTITY_POST_DECREMENT_P(e)
#define ENTITY_POST_INCREMENT_P(e)
#define ENTITY_PRE_INCREMENT_P(e)
#define ENTITY_MALLOC_SYSTEM_P(e)
#define ENTITY_ADDRESS_OF_P(e)

References call_arguments, call_function, CAR, CELL, CONS, constant_p(), dereferencing_to_sinks(), ENTITY_ADDRESS_OF_P, ENTITY_DEREFERENCING_P, ENTITY_FREE_SYSTEM_P, ENTITY_MALLOC_SYSTEM_P, ENTITY_POST_DECREMENT_P, ENTITY_POST_INCREMENT_P, ENTITY_PRE_DECREMENT_P, ENTITY_PRE_INCREMENT_P, EXPRESSION, expression_to_points_to_cells(), expression_to_points_to_sinks(), expression_undefined, f(), free_expression(), gen_length(), int_to_expression(), make_anywhere_cell(), make_nowhere_cell(), malloc_to_points_to_sinks(), NIL, offset_points_to_cells(), pips_assert, pips_internal_error, points_to_expression_to_concrete_type(), points_to_expression_to_pointed_type(), and pt_map_undefined_p.

Referenced by intrinsic_call_to_points_to_sinks().

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

◆ unique_malloc_to_points_to_sinks()

list unique_malloc_to_points_to_sinks ( expression  e)

FI->AM: is "unique" multiple when ALIASING_ACROSS_TYPE is set to false?

FI->AM: the comments in pipsmake-rc.tex are not sufficient to understand what the choices are.

If ALIASING_ACROSS_TYPES, return an overloaded unique heap entity

We need only one HEAP abstract location: Pointers/assign03

We need one HEAP abstract location per type: Pointers/assign02

Note: we must be careful about dereferencing and fields...

Definition at line 1292 of file sinks.c.

1293 {
1294  list m = NIL;
1295  if(get_bool_property("ALIASING_ACROSS_TYPES")) {
1296  /* We need only one HEAP abstract location: Pointers/assign03 */
1298  }
1299  else {
1300  /* We need one HEAP abstract location per type: Pointers/assign02
1301  *
1302  * Note: we must be careful about dereferencing and fields...
1303  */
1305  }
1306  return m;
1307 }

References flow_sensitive_malloc_to_points_to_sinks(), get_bool_property(), and NIL.

Referenced by malloc_to_points_to_sinks().

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

Variable Documentation

◆ malloc_counter

int malloc_counter = 0
static

Definition at line 1177 of file sinks.c.

Referenced by get_heap_counter(), init_heap_model(), and reset_heap_model().

◆ malloc_statement

statement malloc_statement = statement_undefined
static

Heap modelling.

Rather than passing many arguments, keep a heap_context. May not be a good idea for cast information...

The API should contain renaming function(s) to move the effects up the call graph....

Definition at line 1175 of file sinks.c.

Referenced by get_heap_statement(), init_heap_model(), and reset_heap_model().