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

Go to the source code of this file.

Macros

#define LESS_THAN   0
 See if you can decide that the addresses linked to c1 are xxx than the addresses linked to c2. More...
 
#define LESS_THAN_OR_EQUAL_TO   1
 
#define GREATER_THAN   2
 
#define GREATER_THAN_OR_EQUAL_TO   3
 

Functions

void subscripted_reference_to_points_to (reference r, list sl, pt_map pt_in)
 FI: what is this function supposed to do? Just update "pt_in" to make sure that "r" can be dereferenced? And then recursively, with the different subscripts? More...
 
pt_map expression_to_points_to (expression e, pt_map pt_in, bool side_effect_p)
 Update pt_in and pt_out according to expression e. More...
 
pt_map expressions_to_points_to (list el, pt_map pt_in, bool side_effect_p)
 Compute the points-to information pt_out that results from the evaluation of a possibly empty list of expression. More...
 
pt_map reference_to_points_to (reference r, pt_map pt_in, bool side_effect_p)
 The subscript expressions may impact the points-to information. More...
 
pt_map range_to_points_to (range r, pt_map pt_in, bool side_effect_p)
 
pt_map call_to_points_to (call c, pt_map pt_in, list el, bool side_effect_p)
 Three different kinds of calls are distinguished: More...
 
pt_map constant_call_to_points_to (call c __attribute__((unused)), pt_map pt_in)
 FI: this should not generate any points-to update. More...
 
pt_map intrinsic_call_to_points_to (call c, pt_map pt_in, bool side_effect_p)
 
pt_map pointer_arithmetic_to_points_to (expression lhs, expression delta, pt_map pt_in)
 Update the sink locations associated to the source "lhs" under points-to information pt_map by "delta". More...
 
void offset_array_reference (reference r, expression delta, type et)
 Side effect on reference "r". More...
 
void offset_cells (cell source, list sinks, expression delta, type et, pt_map in)
 Each cell in sinks is replaced by a cell located "delta" elements further up in the memory. More...
 
points_to offset_cell (points_to pt, expression delta, type et)
 Allocate and return a new points-to "npt", copy of "pt", with an offset of "delta" on the sink. More...
 
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. More...
 
void offset_points_to_cell (cell sink, expression delta, type t, bool unique_p __attribute__((__unused__)))
 FI: offset_cell() has been derived from this function. More...
 
pt_map assignment_to_points_to (expression lhs, expression rhs, pt_map pt_in)
 
void check_type_of_points_to_cells (list sinks, type ct, bool eval_p)
 Check that all cells in list "sinks" are compatible with type "ct" if "eval_p" is false, and with the type pointed by "st" if eval_p is true. More...
 
void check_rhs_value_types (expression lhs, expression rhs __attribute__((unused)), list sinks)
 Check that the cells in list "sinks" have types compatible with the expression on the left-hand side, lhs. More...
 
pt_map internal_pointer_assignment_to_points_to (expression lhs, expression rhs, pt_map pt_in)
 Any abstract location of the lhs in L is going to point to any sink of any abstract location of the rhs in R. More...
 
pt_map pointer_assignment_to_points_to (expression lhs, expression rhs, pt_map pt_in)
 
list freeable_points_to_cells (list R)
 Remove from points-to cell list R cells that certainly cannot be freed. More...
 
pt_map freed_list_to_points_to (expression lhs, list L, list R, pt_map pt_in)
 Error detections on "L" and "R" have already been performed. More...
 
pt_map freed_pointer_to_points_to (expression lhs, pt_map pt_in, bool side_effect_p)
 Any abstract location of the lhs in L is going to point to nowhere, maybe. More...
 
cell reduce_cell_to_pointer_type (cell c)
 Remove last subscripts of cell c till its type becomes a scalar pointer. More...
 
list reduce_cells_to_pointer_type (list cl)
 Undo the extra eval performed when stubs are generated: 0 subscripts are added when arrays are involved. More...
 
static list generic_points_to_cell_to_useful_pointer_cells (cell c, set pts)
 Returns a list of cells of pointer type which are included in cell "c". More...
 
list points_to_cell_to_pointer_cells (cell c)
 
list points_to_cell_to_useful_pointer_cells (cell c, set pts)
 
list points_to_cells_to_pointer_cells (list pl)
 Convert cells in l into derived pointer cells when possible. More...
 
pt_map memory_leak_to_more_memory_leaks (cell l, pt_map in)
 Cell "l" has been memory leaked for sure and is not referenced any more in "in". More...
 
pt_map list_assignment_to_points_to (list L, list R, pt_map pt_out)
 Update "pt_out" when any element of L can be assigned any element of R. More...
 
pt_map struct_initialization_to_points_to (expression lhs, expression rhs, pt_map in)
 
pt_map struct_assignment_to_points_to (expression lhs, expression rhs, pt_map pt_in)
 pt_in is modified by side-effects and returned as pt_out More...
 
pt_map application_to_points_to (application a, pt_map pt_in, bool side_effect_p)
 
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. More...
 
pt_map reference_condition_to_points_to (reference r, pt_map in, bool true_p)
 Handle conditions such as "if(p)". More...
 
pt_map call_condition_to_points_to (call c, pt_map in, list el, bool true_p)
 Handle any condition that is a call such as "if(p!=q)", "if(*p)", "if(foo(p=q))"... More...
 
pt_map intrinsic_call_condition_to_points_to (call c, pt_map in, bool true_p)
 We can break down the intrinsics according to their arity or according to their kinds... More...
 
pt_map user_call_condition_to_points_to (call c, pt_map in, list el, bool true_p)
 
pt_map boolean_intrinsic_call_condition_to_points_to (call c, pt_map in, bool true_p)
 Deal with "!", "&&", "||" etc. More...
 
static bool cell_is_xxx_p (cell c1, cell c2, int xxx)
 
bool cell_is_less_than_or_equal_to_p (cell c1, cell c2)
 See if you can decide that the addresses linked to c1 are smaller than the addresses linked to c2. More...
 
bool cell_is_less_than_p (cell c1, cell c2)
 
bool cell_is_greater_than_or_equal_to_p (cell c1, cell c2)
 
bool cell_is_greater_than_p (cell c1, cell c2)
 
pt_map null_equal_condition_to_points_to (expression e, pt_map in)
 The condition is e==NULL. More...
 
pt_map null_non_equal_condition_to_points_to (expression e, pt_map in)
 The condition is e!=NULL. More...
 
pt_map equal_condition_to_points_to (list al, pt_map in)
 The expression list "al" contains exactly two arguments, "lhs" and "rhs". More...
 
pt_map non_equal_condition_to_points_to (list al, pt_map in)
 The expression list "al" contains exactly two arguments. More...
 
pt_map order_condition_to_points_to (entity f, list al, bool true_p, pt_map in)
 The expression list "al" contains exactly two arguments. More...
 
pt_map relational_intrinsic_call_condition_to_points_to (call c, pt_map in, bool true_p)
 Update the points-to information "in" according to the validity of the condition. More...
 

Macro Definition Documentation

◆ GREATER_THAN

#define GREATER_THAN   2

Definition at line 2739 of file expression.c.

◆ GREATER_THAN_OR_EQUAL_TO

#define GREATER_THAN_OR_EQUAL_TO   3

Definition at line 2740 of file expression.c.

◆ LESS_THAN

#define LESS_THAN   0

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

True is returned when a decision can be made.

False is returned when no decision can be made.

Definition at line 2737 of file expression.c.

◆ LESS_THAN_OR_EQUAL_TO

#define LESS_THAN_OR_EQUAL_TO   1

Definition at line 2738 of file expression.c.

Function Documentation

◆ application_to_points_to()

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

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

Parameters
pt_int_in
side_effect_pide_effect_p

Definition at line 2490 of file expression.c.

2491 {
2493  list al = application_arguments(a);
2494  pt_map pt_out = expression_to_points_to(f, pt_in, side_effect_p);
2495 
2496  pt_out = expressions_to_points_to(al, pt_out, side_effect_p);
2497  /* FI: We should also identify the possibly called functions and
2498  update the points-to according to the possible call sites. */
2499  pips_internal_error("Not implemented yet for application\n");
2500 
2501  return pt_out;
2502 }
#define pips_internal_error
Definition: misc-local.h:149
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
pt_map expressions_to_points_to(list el, pt_map pt_in, bool side_effect_p)
Compute the points-to information pt_out that results from the evaluation of a possibly empty list of...
Definition: expression.c:243
pt_map expression_to_points_to(expression e, pt_map pt_in, bool side_effect_p)
Update pt_in and pt_out according to expression e.
Definition: expression.c:115
#define application_arguments(x)
Definition: ri.h:510
#define application_function(x)
Definition: ri.h:508
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

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

Referenced by expression_to_points_to().

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

◆ assignment_to_points_to()

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

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

Can occur in a declaration

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

Parameters
lhshs
rhshs
pt_int_in

Definition at line 1163 of file expression.c.

1164 {
1165  pt_map pt_out = pt_in;
1166  // FI: lhs and rhs have already been used to update pt_in
1167  //pt_map pt_out = expression_to_points_to(lhs, pt_in);
1168  /* It is not obvious that you are allowed to evaluate this before
1169  the sink of lhs, but the standard probably forbid stupid side
1170  effects. */
1171  //pt_out = expression_to_points_to(lhs, pt_out);
1172  bool to_be_freed = false;
1173  type t = points_to_expression_to_type(lhs, &to_be_freed);
1174 
1176  if(pointer_type_p(ut))
1177  pt_out = pointer_assignment_to_points_to(lhs, rhs, pt_out);
1178  else if(struct_type_p(ut))
1179  pt_out = struct_assignment_to_points_to(lhs, rhs, pt_out);
1180  // FI: unions are not dealt with...
1181  else if(array_of_pointers_type_p(ut)) {
1182  /* Can occur in a declaration */
1183  /* When more precision is needed, the BRACE_INTRINSIC arguments
1184  will have to be analyzed... */
1185  pips_assert("lhs is a reference", expression_reference_p(lhs));
1187  list sl = reference_indices(r);
1188  pips_assert("The array reference has no indices", ENDP(sl));
1193  points_to a = make_points_to(source, sink,
1196  pt_out = add_arc_to_pt_map_(a, pt_in);
1197  }
1198  else if(array_of_struct_type_p(ut)) {
1199  pips_internal_error("Initialization of array of structs not implemented yet.\n");
1200  }
1201  else
1202  pt_out = pt_in; // What else?
1203 
1204  if(to_be_freed)
1205  free_type(t);
1206 
1207  return pt_out;
1208 }
cell make_cell_reference(reference _field_)
Definition: effects.c:293
approximation make_approximation_may(void)
Definition: effects.c:179
descriptor make_descriptor_none(void)
Definition: effects.c:442
points_to make_points_to(cell a1, cell a2, approximation a3, descriptor a4)
reference copy_reference(reference p)
REFERENCE.
Definition: ri.c:2047
void free_type(type p)
Definition: ri.c:2658
cell make_anywhere_points_to_cell(type)
Function storing points to information attached to a statement.
Definition: points_to.c:87
void points_to_cell_add_unbounded_subscripts(cell)
Definition: effects.c:1632
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 ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
pt_map struct_assignment_to_points_to(expression lhs, expression rhs, pt_map pt_in)
pt_in is modified by side-effects and returned as pt_out
Definition: expression.c:2319
pt_map pointer_assignment_to_points_to(expression lhs, expression rhs, pt_map pt_in)
Definition: expression.c:1437
pt_map add_arc_to_pt_map_(points_to, pt_map)
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
bool array_of_pointers_type_p(type)
Definition: type.c:3025
bool pointer_type_p(type)
Check for scalar pointers.
Definition: type.c:2993
bool struct_type_p(type)
Returns true if t is of type derived and if the derived type is a struct.
Definition: type.c:3121
type compute_basic_concrete_type(type)
computes a new type which is the basic concrete type of the input type (this new type is not stored i...
Definition: type.c:3556
bool array_of_struct_type_p(type)
Definition: type.c:3133
#define basic_pointer(x)
Definition: ri.h:637
#define type_variable(x)
Definition: ri.h:2949
#define reference_indices(x)
Definition: ri.h:2328
#define variable_basic(x)
Definition: ri.h:3120

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

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

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

◆ boolean_intrinsic_call_condition_to_points_to()

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

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

Combine the conditions

Merge the results of the different conditions...

Parameters
inn
true_prue_p

Definition at line 2695 of file expression.c.

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

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

Referenced by intrinsic_call_condition_to_points_to().

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

◆ call_condition_to_points_to()

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

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

Parameters
inn
ell
true_prue_p

Definition at line 2595 of file expression.c.

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

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

Referenced by condition_to_points_to().

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

◆ call_to_points_to()

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

Three different kinds of calls are distinguished:

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

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

points-to updates due to arguments

Must be a pointer to a function

I do not know if nft must be freed later

points-to updates due to arguments

Parameters
pt_int_in
ell
side_effect_pide_effect_p

Definition at line 306 of file expression.c.

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

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

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

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

◆ cell_is_greater_than_or_equal_to_p()

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

Definition at line 2830 of file expression.c.

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

References cell_is_xxx_p(), and GREATER_THAN_OR_EQUAL_TO.

Referenced by order_condition_to_points_to().

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

◆ cell_is_greater_than_p()

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

Definition at line 2835 of file expression.c.

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

References cell_is_xxx_p(), and GREATER_THAN.

Referenced by order_condition_to_points_to().

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

◆ cell_is_less_than_or_equal_to_p()

bool cell_is_less_than_or_equal_to_p ( cell  c1,
cell  c2 
)

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

True is returned when a decision can be made.

False is returned when no decision can be made.

Parameters
c11
c22

Definition at line 2820 of file expression.c.

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

References cell_is_xxx_p(), and LESS_THAN_OR_EQUAL_TO.

Referenced by order_condition_to_points_to().

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

◆ cell_is_less_than_p()

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

Definition at line 2825 of file expression.c.

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

References cell_is_xxx_p(), and LESS_THAN.

Referenced by order_condition_to_points_to().

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

◆ cell_is_xxx_p()

static bool cell_is_xxx_p ( cell  c1,
cell  c2,
int  xxx 
)
static

You must compare the subscript expressions lexicographically

Definition at line 2742 of file expression.c.

2743 {
2744  bool xxx_p = true;
2745  reference r1 = cell_any_reference(c1);
2746  reference r2 = cell_any_reference(c2);
2747  entity v1 = reference_variable(r1);
2748  entity v2 = reference_variable(r2);
2749  if(v1!=v2) {
2750  xxx_p = false; // FI: useless, but the pips_user_error() may be removed
2751  pips_user_error("Incomparable pointers to \"%s\" and \"%s\" are compared.\n",
2752  reference_to_string(r1),
2753  reference_to_string(r2));
2754  }
2755  else {
2756  /* You must compare the subscript expressions lexicographically */
2757  list sl1 = reference_indices(r1), sl1c = sl1;
2758  list sl2 = reference_indices(r2), sl2c = sl2;
2759  for(sl1c = sl1;
2760  !ENDP(sl1c) && !ENDP(sl2c) && xxx_p;
2761  sl1c = CDR(sl1c), sl2c = CDR(sl2c)) {
2762  expression s1 = EXPRESSION(CAR(sl1c));
2763  expression s2 = EXPRESSION(CAR(sl2c));
2765  xxx_p = false;
2766  else {
2767  value v1 = EvalExpression(s1);
2768  value v2 = EvalExpression(s2);
2769  if(!value_constant_p(v1) || !value_constant_p(v2)) {
2770  // FI: this should be a pips_internal_error due to
2771  // constraints on points_to sets
2772  xxx_p = false;
2773  pips_internal_error("Unexpected subscripts in points-to.\n");
2774  }
2775  else {
2776  constant c1 = value_constant(v1);
2777  constant c2 = value_constant(v2);
2778  if(!constant_int_p(c1) || !constant_int_p(c2)) {
2779  xxx_p = false;
2780  pips_internal_error("Unexpected subscripts in points-to.\n");
2781  }
2782  else {
2783  int i1 = constant_int(c1);
2784  int i2 = constant_int(c2);
2785  // FI: you should break when i1<i2
2786  switch(xxx) {
2787  case LESS_THAN:
2788  xxx_p = (i1<i2);
2789  break;
2790  case LESS_THAN_OR_EQUAL_TO:
2791  xxx_p = (i1<=i2);
2792  break;
2793  case GREATER_THAN:
2794  xxx_p = (i1>i2);
2795  break;
2797  xxx_p = (i1>=i2);
2798  break;
2799  default:
2800  pips_internal_error("Unknown comparison.\n");
2801  }
2802  }
2803  }
2804  }
2805  }
2806  // FI: Not good for a lexicographic order, might need equal_p as
2807  // well, but sufficient for arithmetic02
2808  //if(xxx_p && !ENDP(sl1c))
2809  // xxx_p = false;
2810  }
2811  return xxx_p;
2812 }
reference cell_any_reference(cell)
API for reference.
Definition: effects.c:77
#define pips_user_error
Definition: misc-local.h:147
string reference_to_string(reference r)
Definition: expression.c:87
value EvalExpression(expression e)
Evaluate statically an expression.
Definition: eval.c:108
bool unbounded_expression_p(expression e)
Definition: expression.c:4329
#define value_constant(x)
Definition: ri.h:3073
#define reference_variable(x)
Definition: ri.h:2326
#define constant_int(x)
Definition: ri.h:850
#define constant_int_p(x)
Definition: ri.h:848
s1
Definition: set.c:247

References CAR, CDR, cell_any_reference(), constant_int, constant_int_p, ENDP, EvalExpression(), EXPRESSION, GREATER_THAN, GREATER_THAN_OR_EQUAL_TO, LESS_THAN, LESS_THAN_OR_EQUAL_TO, pips_internal_error, pips_user_error, reference_indices, reference_to_string(), reference_variable, s1, unbounded_expression_p(), value_constant, and value_constant_p.

Referenced by cell_is_greater_than_or_equal_to_p(), cell_is_greater_than_p(), cell_is_less_than_or_equal_to_p(), and cell_is_less_than_p().

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

◆ check_rhs_value_types()

void check_rhs_value_types ( expression  lhs,
expression rhs   __attribute__(unused),
list  sinks 
)

Check that the cells in list "sinks" have types compatible with the expression on the left-hand side, lhs.

List "sinks" is assumed to have been derived from the "rhs" expression.

At least for the NULL pointer...

Definition at line 1277 of file expression.c.

1281 {
1282  // Some expression are synthesized to reuse existing functions.
1283  bool to_be_freed;
1284  type t = points_to_expression_to_type(lhs, &to_be_freed);
1286  type st = type_undefined; // sink type
1287  if(pointer_type_p(ct)) {
1289  }
1290  else if(array_type_p(ct)) {
1292  }
1293  else if(scalar_integer_type_p(ct)) {
1294  /* At least for the NULL pointer... */
1295  st = ct;
1296  }
1297  else
1298  pips_internal_error("Unexpected type for value.\n");
1299 
1300  if(!type_void_star_p(ct)) { // void * is compatible with all types...
1301  check_type_of_points_to_cells(sinks, st, false);
1302  }
1303  // Late free, to be able to see "t" under gdb...
1304  if(to_be_freed) free_type(t);
1305 }
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 array_type_p(type)
Definition: type.c:2942
bool type_void_star_p(type)
Definition: type.c:5765
bool scalar_integer_type_p(type)
Definition: type.c:3276
type array_type_to_element_type(type)
returns the type of the elements of an array type, as a newly allocated type.
Definition: type.c:5700

References array_type_p(), array_type_to_element_type(), check_type_of_points_to_cells(), compute_basic_concrete_type(), free_type(), pips_internal_error, pointer_type_p(), points_to_expression_to_type(), scalar_integer_type_p(), type_to_pointed_type(), type_undefined, and type_void_star_p().

Referenced by internal_pointer_assignment_to_points_to().

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

◆ check_type_of_points_to_cells()

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

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

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

Take care of the constant strings like "hello"

Take care of void

Parameters
sinksinks
ctt
eval_pval_p

Definition at line 1214 of file expression.c.

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

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

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

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

◆ condition_to_points_to()

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

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

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

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

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

Parameters
inn
true_prue_p

Definition at line 2512 of file expression.c.

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

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

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

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

◆ constant_call_to_points_to()

pt_map constant_call_to_points_to ( call c   __attribute__(unused),
pt_map  pt_in 
)

FI: this should not generate any points-to update.

it would be better not to go down here

Definition at line 404 of file expression.c.

405 {
406  pt_map pt_out = pt_in;
407 
408  return pt_out;
409 }

◆ equal_condition_to_points_to()

pt_map equal_condition_to_points_to ( list  al,
pt_map  in 
)

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

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

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

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

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

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

Is it impossible to evaluate lhs?

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

Is it impossible to evaluate rhs?

Is the condition feasible?

Parameters
all
inn

Definition at line 2986 of file expression.c.

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

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

Referenced by relational_intrinsic_call_condition_to_points_to().

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

◆ expression_to_points_to()

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

Update pt_in and pt_out according to expression e.

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

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

list el = expression_to_proper_constant_path_effects(e);

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

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

a cannot evaluate to null or undefined

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

Parameters
pt_int_in
side_effect_pide_effect_p

Definition at line 115 of file expression.c.

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

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

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

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

◆ expressions_to_points_to()

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

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

A new data structure is allocated.

Ignore side-effects unless side_effect_p is set to true.

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

Parameters
ell
pt_int_in
side_effect_pide_effect_p

Definition at line 243 of file expression.c.

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

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

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

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

◆ freeable_points_to_cells()

list freeable_points_to_cells ( list  R)

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


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

Definition at line 1457 of file expression.c.

1458 {
1459  list nhl = NIL; // No heap list: cannot be freed
1460  FOREACH(CELL, c, R) {
1461  if(heap_cell_p(c) || stub_points_to_cell_p(c)) {
1463  list inds = reference_indices(r);
1464  /* if c is a heap location with indices other than zero then we
1465  have bumped into a non-legal free */
1466  if(!ENDP(inds)) {
1467  expression ind = EXPRESSION (CAR(inds));
1468  // No offset allowed for a free()
1469  if(!expression_null_p(ind))
1470  nhl = CONS(CELL, c, nhl);
1471  }
1472  // gen_free_list(inds);
1473  }
1474  else if(!heap_cell_p(c)
1475  && !stub_points_to_cell_p(c)
1477  nhl = CONS(CELL, c, nhl);
1478  }
1479  gen_list_and_not(&R, nhl);
1480  gen_free_list(nhl);
1481  return R;
1482 }
bool stub_points_to_cell_p(cell)
Definition: points_to.c:108
bool heap_cell_p(cell)
Any heap cell, more or less abstract or typed.
Definition: effects.c:420
void gen_list_and_not(list *a, const list b)
Compute A = A inter non B:
Definition: list.c:963
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327

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

Referenced by freed_pointer_to_points_to().

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

◆ freed_list_to_points_to()

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

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

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

First level memory leaks

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

Remove Kill_1 if it is not empty by definition

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

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

Compute and add Gen_2

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

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

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

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

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

Add Gen_2: useless, already performed by Kill_2

More memory leaks?

Clean up the resulting graph

Parameters
lhshs
pt_int_in

Definition at line 1489 of file expression.c.

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

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

Referenced by freed_pointer_to_points_to().

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

◆ freed_pointer_to_points_to()

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

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

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

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

Equations for "free(e);":

Let L = expression_to_sources(e,in)

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

where ^ denotes the set intersection.

If R_1 is empty, an execution error must occur.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Warnings for potential dangling pointers:

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

No warning is issued as those are only potential.

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

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

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

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

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

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

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

A execution error is certain

Free(NULL) has no effect

Remove from R locations that cannot be freed

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

Parameters
lhshs
pt_int_in
side_effect_pide_effect_p

Definition at line 1741 of file expression.c.

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

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

Referenced by intrinsic_call_to_points_to().

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

◆ generic_points_to_cell_to_useful_pointer_cells()

static list generic_points_to_cell_to_useful_pointer_cells ( cell  c,
set  pts 
)
static

Returns a list of cells of pointer type which are included in cell "c".

Useful when "c" is a struct or an array of structs or pointers. Returns a list with cell "c" if it denotes a pointer.

If set "pt" is defined, make sure that each cell in the returned list, "pcl" appears in "pt".

Look for pointer and struct and array of pointers or struct fields

transformer

Definition at line 1862 of file expression.c.

1863 {
1864  list pcl = NIL; // pointer cell list
1866  if(pointer_type_p(c_t) && cell_in_points_to_set_p(c, pts)) {
1867  cell nc = copy_cell(c);
1868  pcl = CONS(CELL, nc, pcl);
1869  }
1870  else if(struct_type_p(c_t)) {
1871  /* Look for pointer and struct and array of pointers or struct fields */
1872  list fl = struct_type_to_fields(c_t);
1873  FOREACH(ENTITY, f, fl) {
1875  if(pointer_type_p(f_t) || struct_type_p(f_t)
1876  || array_of_pointers_type_p(f_t)
1877  || array_of_struct_type_p(f_t)) {
1878  cell nc = copy_cell(c);
1880  // FI: possible memory leak for nc;
1881  // If it is not a pointer, it should be freed
1882  // If it is a pointer, it might be useful or not
1884  pcl = gen_nconc(pcl, ppcl);
1885  // If nc is not in pcl, it should be free
1886  }
1887  }
1888  }
1889  else if(array_of_pointers_type_p(c_t) || array_of_struct_type_p(c_t)) {
1890  /* transformer */
1891  cell nc = copy_cell(c);
1894  // FI: should nc be freed or not ?
1895  // If nc is not in pcl, it should be free
1896  }
1897  return pcl;
1898 }
cell points_to_cell_add_field_dimension(cell, entity)
Functions about points-to cells - There is no cell.c file.
Definition: effects.c:1444
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
static list generic_points_to_cell_to_useful_pointer_cells(cell c, set pts)
Returns a list of cells of pointer type which are included in cell "c".
Definition: expression.c:1862
bool cell_in_points_to_set_p(cell, set)
Check if a cell c appears as source or sink in points-to set pts.
list struct_type_to_fields(type)
Definition: type.c:5798
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755

References array_of_pointers_type_p(), array_of_struct_type_p(), CELL, cell_in_points_to_set_p(), CONS, copy_cell(), ENTITY, entity_basic_concrete_type(), f(), FOREACH, gen_nconc(), NIL, pointer_type_p(), points_to_cell_add_field_dimension(), points_to_cell_add_unbounded_subscripts(), points_to_cell_to_concrete_type(), struct_type_p(), and struct_type_to_fields().

Referenced by points_to_cell_to_pointer_cells(), and points_to_cell_to_useful_pointer_cells().

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

◆ internal_pointer_assignment_to_points_to()

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

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

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

Store independence must be checked.

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

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

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

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

Retrieve the memory locations that might be reached by the rhs

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

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

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

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

Parameters
lhshs
rhshs
pt_int_in

Definition at line 1315 of file expression.c.

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

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

Referenced by pointer_assignment_to_points_to().

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

◆ intrinsic_call_condition_to_points_to()

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

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

or according to both conditions...

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

Parameters
inn
true_prue_p

Definition at line 2618 of file expression.c.

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

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

Referenced by call_condition_to_points_to().

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

◆ intrinsic_call_to_points_to()

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

Is the dereferenced pointer null or undefined?

Is the dereferenced pointer null or undefined?

|| ENTITY_ASSERT_FAIL_SYSTEM_P(f)

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

attempt at using an undefined value

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

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

possible attempt at using an undefined value

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

Parameters
pt_int_in
side_effect_pide_effect_p

Definition at line 411 of file expression.c.

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

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

Referenced by call_to_points_to(), and intrinsic_call_condition_to_points_to().

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

◆ list_assignment_to_points_to()

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

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

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

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

Old description by Amira:

KILL_MAY = kill_may_set() KILL_MUST= kill_must_set()

GEN_MAY = gen_may_set() GEN_MUST= gen_must_set()

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

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

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

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

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

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

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

For memory leaks, let

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

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

This function is described in Amira Mensi's dissertation.

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

Check possible dereferencing errors

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

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

The code cannot be executed

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

out = (in - kill) U gen ?

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

Check kill_must for potential memory leaks

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

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

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

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

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

en_must,

kill,

Parameters
pt_outt_out

Definition at line 2029 of file expression.c.

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

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

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

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

◆ memory_leak_to_more_memory_leaks()

pt_map memory_leak_to_more_memory_leaks ( cell  l,
pt_map  in 
)

Cell "l" has been memory leaked for sure and is not referenced any more in "in".

Its successors may be leaked too.

Remove useless unreachable arcs

Look for a chain of memory leaks

Parameters
inn

Definition at line 1929 of file expression.c.

1930 {
1931  pt_map out = in;
1932  // potential memory leaks
1934  FOREACH(CELL, c, pml) {
1935  // This first test is probably useless because if has been
1936  // partially or fully performed by the caller
1937  if(heap_cell_p(c) && unreachable_points_to_cell_p(c, in)) {
1938  /* Remove useless unreachable arcs */
1939  list dl = NIL, npml = NIL;
1940  set out_s = points_to_graph_set(out);
1941  SET_FOREACH(points_to, pt, out_s) {
1942  cell source = points_to_source(pt);
1943  // FI: a weaker test based on the lattice is needed
1944  if(points_to_cell_equal_p(source, c)) {
1945  dl = CONS(POINTS_TO, pt, dl);
1946  cell sink = points_to_sink(pt);
1947  npml = CONS(CELL, sink, npml);
1948  // FI: we need to remove pt before we can test for unreachability...
1949  /*
1950  if(heap_cell_p(sink) && unreachable_points_to_cell_p(sink, out)) {
1951  pips_user_warning("Heap bucket \"%s\" leaked at line %d.\n",
1952  points_to_cell_to_string(sink),
1953  points_to_context_statement_line_number());
1954  */
1955  }
1956  }
1957  FOREACH(POINTS_TO, d, dl)
1959  gen_free_list(dl);
1960 
1961  FOREACH(CELL, sink, npml) {
1962  if(heap_cell_p(sink) && unreachable_points_to_cell_p(sink, out)) {
1963  if(false)
1964  pips_user_warning("Heap bucket \"%s\" leaked.\n",
1965  points_to_cell_to_string(sink));
1966  else
1967  pips_user_warning("Heap bucket \"%s\" leaked at line %d.\n",
1970  /* Look for a chain of memory leaks */
1971  //if(!points_to_cell_equal_p(c, l))
1973  }
1974  }
1975  gen_free_list(npml);
1976  }
1977  }
1978  return out;
1979 }
list points_to_cell_to_pointer_cells(cell c)
Definition: expression.c:1900

References CELL, CONS, FOREACH, gen_free_list(), heap_cell_p(), NIL, out, pips_user_warning, POINTS_TO, points_to_cell_equal_p(), points_to_cell_to_pointer_cells(), points_to_cell_to_string(), points_to_context_statement_line_number(), points_to_graph_set, points_to_sink, points_to_source, remove_arc_from_pt_map, SET_FOREACH, and unreachable_points_to_cell_p().

Referenced by freed_list_to_points_to(), list_assignment_to_points_to(), and points_to_set_block_projection().

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

◆ non_equal_condition_to_points_to()

pt_map non_equal_condition_to_points_to ( list  al,
pt_map  in 
)

The expression list "al" contains exactly two arguments.

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

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

Is the condition lhs!=rhs certainly impossible to evaluate? If not, is it always false?

Parameters
all
inn

Definition at line 3086 of file expression.c.

3087 {
3088  // FI: this code is almost identical to the code above
3089  // It should be shared with a more general test first and then a
3090  // precise test to decide if you add or remove arcs
3091  pt_map out = in;
3092  expression lhs = EXPRESSION(CAR(al));
3093  expression rhs = EXPRESSION(CAR(CDR(al)));
3094 
3095  // FI: in fact, any integer could be used in a pointer comparison...
3096  if(expression_null_p(lhs))
3098  else if(expression_null_p(rhs))
3100  else {
3101  type lhst = expression_to_type(lhs);
3102  type rhst = expression_to_type(rhs);
3103  if(pointer_type_p(lhst) && pointer_type_p(rhst)) {
3105  list R = expression_to_points_to_sinks(rhs, in);
3106  //bool equal_p = false;
3107  int nL = (int) gen_length(L);
3108  int nR = (int) gen_length(R);
3109  pips_assert("The two expressions can be dereferenced", nL>=1 && nR>=1);
3110  if(nL==1 && nR==1) {
3111  cell cl = CELL(CAR(L));
3112  cell cr = CELL(CAR(R));
3113  /* Is the condition lhs!=rhs certainly impossible to evaluate?
3114  * If not, is it always false? */
3115  if((atomic_points_to_cell_p(cl)
3117  && points_to_cell_equal_p(cl, cr))
3118  || nowhere_cell_p(cl)
3119  || nowhere_cell_p(cr)) {
3120  // one or more expressions is not evaluable or the condition
3121  // is not feasible
3122  clear_pt_map(out);
3123  points_to_graph_bottom(out) = true;
3124  if(nowhere_cell_p(cl))
3125  pips_user_warning("Unitialized pointer is used to evaluate expression"
3126  " \"%s\" at line %d.\n",
3127  expression_to_string(lhs),
3129  if(nowhere_cell_p(cr))
3130  pips_user_warning("Unitialized pointer is used to evaluate expression"
3131  " \"%s\" at line %d.\n",
3132  expression_to_string(rhs),
3134  }
3135  }
3136  else {
3137  // It is possible to remove some arcs? if18.c
3138  int nL = (int) gen_length(L);
3139  int nR = (int) gen_length(R);
3140  cell c = cell_undefined;
3141  list O = list_undefined;
3142  if(nL==1 && atomic_points_to_cell_p(CELL(CAR(L)))) {
3143  c = CELL(CAR(L));
3145  }
3146  else if(nR==1 && atomic_points_to_cell_p(CELL(CAR(R)))) {
3147  c = CELL(CAR(R));
3149  }
3150  if(!cell_undefined_p(c)) {
3151  if((int) gen_length(O)==1) {
3152  cell oc = CELL(CAR(O));
3154  copy_cell(c),
3158  // Should we free pt? Or is it done by remove_arc_from_pt_map()?
3159  }
3160  }
3161  }
3162  }
3163  free_type(lhst), free_type(rhst);
3164  }
3165  return in;
3166 }
pt_map null_non_equal_condition_to_points_to(expression e, pt_map in)
The condition is e!=NULL.
Definition: expression.c:2927

References atomic_points_to_cell_p(), CAR, CDR, CELL, cell_undefined, cell_undefined_p, clear_pt_map, copy_cell(), EXPRESSION, expression_null_p(), expression_to_points_to_sinks(), expression_to_points_to_sources(), expression_to_string(), expression_to_type(), free_type(), gen_length(), int, list_undefined, make_approximation_may(), make_descriptor_none(), make_points_to(), nowhere_cell_p(), null_non_equal_condition_to_points_to(), out, pips_assert, pips_user_warning, pointer_type_p(), points_to_cell_equal_p(), points_to_context_statement_line_number(), points_to_graph_bottom, and remove_arc_from_pt_map.

Referenced by relational_intrinsic_call_condition_to_points_to().

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

◆ null_equal_condition_to_points_to()

pt_map null_equal_condition_to_points_to ( expression  e,
pt_map  in 
)

The condition is e==NULL.

e==NULL may be true if exists c in sinks(e) s.t. {NULL} is included in c. else e==NULL must be false.

Some arcs in in may be removed: forall c in sources(e):

out = in - {pt=(a,b) in in | a in sources(e) and b=NULL}

May the condition be true under "in"?

If NULL initialization is not performed, a stub can represent a NULL.

Remove arcs incompatible with the condition e==NULL and add the arc e->NULL

All arcs starting from fc can be removed and replaced by one arc from fc to NULL.

Parameters
inn

Definition at line 2849 of file expression.c.

2850 {
2851  pt_map out = in;
2852  type et = expression_to_type(e);
2853  if(pointer_type_p(et)) {
2855  bool null_initialization_p
2856  = get_bool_property("POINTS_TO_NULL_POINTER_INITIALIZATION");
2857 
2858  if(ENDP(R)) {
2859  // Maybe, a dereferencement user error occured?
2860  pips_internal_error("A dereferencement should always succeed.\n");
2861  }
2862 
2863  /* May the condition be true under "in"? */
2864  bool found_p = false;
2865  FOREACH(CELL, c, R) {
2866  if(null_cell_p(c)
2867  || anywhere_cell_p(c)
2869  /* If NULL initialization is not performed, a stub can
2870  represent a NULL. */
2871  || (!null_initialization_p && stub_points_to_cell_p(c))) {
2872  found_p = true;
2873  break;
2874  }
2875  }
2876  if(!found_p) {
2877  clear_pt_map(out);
2878  points_to_graph_bottom(out) = true;
2879  }
2880  else {
2881  /* Remove arcs incompatible with the condition e==NULL and add
2882  the arc e->NULL */
2884  pips_assert("A lhs expression has at least one source", !ENDP(L));
2885  int nL = (int) gen_length(L);
2886  cell fc = CELL(CAR(L));
2887  if(nL==1 && atomic_points_to_cell_p(fc)) {
2888  /* All arcs starting from fc can be removed and replaced by
2889  one arc from fc to NULL. */
2892  make_null_cell(),
2895  add_arc_to_pt_map(pt, out);
2896  }
2897  else {
2899  cell source = points_to_source(pt);
2900  if(cell_in_list_p(source, L)) {
2901  cell sink = points_to_sink(pt);
2902  if(!(null_cell_p(sink)
2903  || anywhere_cell_p(sink)
2904  || cell_typed_anywhere_locations_p(sink))) {
2906  }
2907  }
2908  }
2909  }
2910  }
2911  gen_free_list(R); // FI: should be full?
2912  }
2913  return out;
2914 }
#define remove_arc_from_pt_map_(a, s)
bool cell_in_list_p(cell, const list)
cell make_null_cell(void)
Definition: sinks.c:95

References add_arc_to_pt_map, anywhere_cell_p(), atomic_points_to_cell_p(), CAR, CELL, cell_in_list_p(), cell_typed_anywhere_locations_p(), clear_pt_map, copy_cell(), ENDP, expression_to_points_to_sinks(), expression_to_points_to_sources(), expression_to_type(), FOREACH, gen_free_list(), gen_length(), get_bool_property(), int, make_approximation_exact(), make_descriptor_none(), make_null_cell(), make_points_to(), null_cell_p(), out, pips_assert, pips_internal_error, pointer_type_p(), points_to_cell_source_projection(), points_to_graph_bottom, points_to_graph_set, points_to_sink, points_to_source, remove_arc_from_pt_map_, SET_FOREACH, and stub_points_to_cell_p().

Referenced by equal_condition_to_points_to().

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

◆ null_non_equal_condition_to_points_to()

pt_map null_non_equal_condition_to_points_to ( expression  e,
pt_map  in 
)

The condition is e!=NULL.

e!=NULL may be true if exists c in sinks(e) s.t. c != {NULL}

e!=NULL is false if forall c in sinks(e) c is included in {NULL}

Arcs that can be removed:

FI: I decided not to merge this function with the previous one till they are both fully defined and tested.

May the condition be true under "in"?

Remove arcs incompatible with the condition e!=NULL

Parameters
inn

Definition at line 2927 of file expression.c.

2928 {
2929  pt_map out = in;
2930  type et = expression_to_type(e);
2931  if(pointer_type_p(et)) {
2933 
2934  if(ENDP(L)) {
2935  // Maybe, a dereferencement user error occured?
2936  pips_internal_error("A dereferencement should always succeed.\n");
2937  }
2938 
2939  /* May the condition be true under "in"? */
2940  bool found_p = false;
2941  FOREACH(CELL, c, L) {
2942  if(!null_cell_p(c)) {
2943  found_p = true;
2944  break;
2945  }
2946  }
2947  if(!found_p) {
2948  clear_pt_map(out);
2949  points_to_graph_bottom(out) = true;
2950  }
2951  else {
2952  /* Remove arcs incompatible with the condition e!=NULL */
2955  cell source = points_to_source(pt);
2956  if(cell_in_list_p(source, L)) {
2957  cell sink = points_to_sink(pt);
2958  if(null_cell_p(sink)) {
2960  }
2961  }
2962  }
2963  }
2964  }
2965  return out;
2966 }

References CELL, cell_in_list_p(), clear_pt_map, ENDP, expression_to_points_to_sinks(), expression_to_points_to_sources(), expression_to_type(), FOREACH, null_cell_p(), out, pips_internal_error, pointer_type_p(), points_to_graph_bottom, points_to_graph_set, points_to_sink, points_to_source, remove_arc_from_pt_map_, and SET_FOREACH.

Referenced by non_equal_condition_to_points_to().

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

◆ offset_array_reference()

void offset_array_reference ( reference  r,
expression  delta,
type  et 
)

Side effect on reference "r".

r is assumed to be a reference to an array.

The offset is applied to the last suscript.

Parameters
deltaelta
ett

Definition at line 802 of file expression.c.

803 {
804  value v = EvalExpression(delta);
805  list rsl = reference_indices(r);
807  int dv = constant_int(value_constant(v));
808  if(ENDP(rsl)) {
809  // FI: oops, we are in trouble; assume 0...
810  expression se = int_to_expression(dv);
812  }
813  else {
814  // Select the index that should be subscripted
816  expression lse = EXPRESSION(CAR(sl));
817  value vlse = EvalExpression(lse);
818  if(value_constant_p(vlse) && constant_int_p(value_constant(vlse))) {
819  int ov = constant_int(value_constant(vlse));
820  int k = get_int_property("POINTS_TO_SUBSCRIPT_LIMIT");
821  if(-k <= ov && ov <= k) {
822  expression nse = int_to_expression(dv+ov);
823  //EXPRESSION_(CAR(gen_last(sl))) = nse;
824  EXPRESSION_(CAR(sl)) = nse;
825  }
826  else {
828  //EXPRESSION_(CAR(gen_last(sl))) = nse;
829  EXPRESSION_(CAR(sl)) = nse;
830  }
831  free_expression(lse);
832  }
833  else {
834  // FI: assume * is used... UNBOUNDED_DIMENSION
836  //EXPRESSION_(CAR(gen_last(sl))) = nse;
837  EXPRESSION_(CAR(sl)) = nse;
838  free_expression(lse);
839  }
840  }
841  }
842  else {
843  if(ENDP(rsl)) {
845  reference_indices(r) = CONS(EXPRESSION, nse, NIL);
846  }
847  else {
849  expression ose = EXPRESSION(CAR(sl));
851  EXPRESSION_(CAR(sl)) = nse;
852  free_expression(ose);
853  }
854  }
855 }
int get_int_property(const string)
list points_to_reference_to_typed_index(reference, type)
Look for the index in "r" that corresponds to a pointer of type "t" and return the corresponding elem...
Definition: points_to.c:361
expression make_unbounded_expression()
Definition: expression.c:4339
#define EXPRESSION_(x)
Definition: ri.h:1220

References CAR, CONS, constant_int, constant_int_p, ENDP, EvalExpression(), EXPRESSION, EXPRESSION_, free_expression(), get_int_property(), int_to_expression(), make_unbounded_expression(), NIL, points_to_reference_to_typed_index(), reference_indices, value_constant, and value_constant_p.

Referenced by offset_cell().

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

◆ offset_cell()

points_to offset_cell ( points_to  pt,
expression  delta,
type  et 
)

Allocate and return a new points-to "npt", copy of "pt", with an offset of "delta" on the sink.

"et" is used to determine which index should be offseted.

Some kind of k-limiting should be performed here to avoid creating too many new nodes in the points-to graph, such as t[0], t[1],... A fix point t[*] should be used when too may nodes already exist.

Since "sink" is used to compute the key in the hash table used to represent set "in", it is not possible to perform a side effect on "sink" without removing and reinserting the corresponding arc.

FI: I am not sure we have the necessary information to know which subscript must be updated when more than one is available. This is bad for multidimensional arrays and worse for references to stub that may include fields (or not) as subscript as well as lots of articificial dimensions due to the source.

I assumed gen_last() to start with, but it is unlikely in general!

"&a[i]" should be transformed into "&a[i+eval(delta)]" when "delta" can be statically evaluated

| !get_bool_property("POINTS_TO_STRICT_POINTER_TYPES")

Parameters
ptt
deltaelta
ett

Definition at line 937 of file expression.c.

938 {
939  /* "&a[i]" should be transformed into "&a[i+eval(delta)]" when
940  "delta" can be statically evaluated */
941  points_to npt = copy_points_to(pt);
942  cell sink = points_to_sink(npt);
943  reference r = cell_any_reference(sink);
944  entity v = reference_variable(r);
945  if(nowhere_cell_p(sink))
946  ; // user error: possible incrementation of an uninitialized pointer
947  else if(null_cell_p(sink))
948  ; // Impossible: possible incrementation of a NULL pointer
949  else if(anywhere_cell_p(sink))
950  ; // It is already fuzzy no need to add more
951  // FI: it might be necessary to exclude *HEAP* too when a minimal
952  // heap model is used (ABSTRACT_HEAP_LOCATIONS = "unique")
953  else {
955  // FI: I do not understand why this is based on the type of v and
956  // not on the ype of r
957  if(array_type_p(vt)
958  // FI: the property should have been taken care of earlier when
959  // building sink
960  /*|| !get_bool_property("POINTS_TO_STRICT_POINTER_TYPES")*/) {
961  cell source = points_to_source(npt);
962  bool to_be_freed;
963  type source_t = points_to_cell_to_type(source, &to_be_freed);
964  type c_source_t = compute_basic_concrete_type(source_t);
965  if(to_be_freed) free_type(source_t);
966  type pt = type_to_pointed_type(c_source_t);
967  type e_sink_t = compute_basic_concrete_type(pt);
968  if(array_pointer_type_equal_p(vt, e_sink_t)
969  && get_bool_property("POINTS_TO_STRICT_POINTER_TYPES"))
970  pips_user_error("Use of pointer arithmetic on \"%s\" at line %d via reference \"%s\" is not "
971  "standard-compliant.\n"
972  "Reset property \"POINTS_TO_STRICT_POINTER_TYPES\""
973  " for usual non-standard compliant C code.\n",
974  entity_user_name(v),
977  else
978  offset_array_reference(r, delta, et);
979  }
980  else if(struct_type_p(vt)) {
981  // The struct may contain an array field.
982  // FI: should we check the existence of the field in the subscripts?
983  offset_array_reference(r, delta, et);
984  }
986  // FI: waiting for ROM buffers containing the constant strings...
987  offset_array_reference(r, delta, et);
988  }
989  // FI to be extended to pointers and points-to stubs
990  else {
991  cell source = points_to_source(npt);
992  if(get_bool_property("POINTS_TO_STRICT_POINTER_TYPES")) {
993  pips_user_error("Use of pointer arithmetic on \"%s\" at line %d via reference \"%s\" is not "
994  "standard-compliant.\n"
995  "Reset property \"POINTS_TO_STRICT_POINTER_TYPES\""
996  " for usual non-standard compliant C code.\n",
997  entity_user_name(v),
1000  }
1001  else {
1002  pips_user_error("Use of pointer arithmetic on \"%s\" at line %d via reference \"%s\" is not "
1003  "standard-compliant.\n",
1004  entity_user_name(v),
1007  }
1008  }
1009  }
1010  return npt;
1011 }
points_to copy_points_to(points_to p)
POINTS_TO.
void offset_array_reference(reference r, expression delta, type et)
Side effect on reference "r".
Definition: expression.c:802

References anywhere_cell_p(), array_pointer_type_equal_p(), array_type_p(), cell_any_reference(), char_star_constant_function_type_p(), compute_basic_concrete_type(), copy_points_to(), effect_reference_to_string(), entity_basic_concrete_type(), entity_user_name(), free_type(), get_bool_property(), nowhere_cell_p(), null_cell_p(), offset_array_reference(), pips_user_error, points_to_cell_to_type(), points_to_context_statement_line_number(), points_to_sink, points_to_source, reference_variable, struct_type_p(), and type_to_pointed_type().

Referenced by offset_cells().

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

◆ offset_cells()

void offset_cells ( cell  source,
list  sinks,
expression  delta,
type  et,
pt_map  in 
)

Each cell in sinks is replaced by a cell located "delta" elements further up in the memory.

In some cases, the same points-to are removed and added. For instance, t[0],t[1] -> t[1],t[2] because of a p++, and t[1] is removed and added.

If the source may point to null, the corresponding arc is removed. If the source points only to null, the resulting graph is bottom.

This procedure must be used when cells in "sinks" are components of points-to arcs stored in a points-to set.

Parameters
sourceource
sinksinks
deltaelta
ett
inn

Definition at line 869 of file expression.c.

870 {
871  // FI: it would be easier to use two lists of arcs rather than sets.
872  // FI: should we assert that expression delta!=0?
873  pt_map old = new_pt_map();
874  pt_map new = new_pt_map();
875  bool unfeasible_p = false;
876  FOREACH(CELL, sink, sinks) {
877  if(!anywhere_cell_p(sink) && !cell_typed_anywhere_locations_p(sink)) {
878  points_to pt = find_arc_in_points_to_set(source, sink, in);
879  // FI: the arc may not be found; for instance, you know that
880  // _pp_1[1] points towards *NULL_POINTER*, but this is due to an arc
881  // _pp_1[*]->*NULL_POINTER*; this arc does not have to be updated
882  if(!points_to_undefined_p(pt)) {
883  if(null_cell_p(sink)) {
884  add_arc_to_pt_map(pt, old);
885  if(gen_length(sinks)==1) {
886  semantics_user_warning("Arithmetic operation performed on NULL pointer \"%s\".\n", points_to_cell_to_string(source));
887  unfeasible_p = true;
888  }
889  else
890  semantics_user_warning("Arithmetic operation performed on \"%s\", which might be a NULL pointer.\n", points_to_cell_to_string(source));
891  }
892  else {
893  add_arc_to_pt_map(pt, old);
894  points_to npt = offset_cell(pt, delta, et);
895  add_arc_to_pt_map(npt, new);
896  }
897  }
898  else {
899  // Another option would be to generate nothing in this case
900  // since it is taken care of by the lattice...
901 
902  // Since pt has not been found in "in", the approximation must be may
903  pt = make_points_to(copy_cell(source), copy_cell(sink),
906  points_to npt = offset_cell(pt, delta, et);
907  add_arc_to_pt_map(npt, new);
908  }
909  }
910  }
911  difference_of_pt_maps(in, in, old);
912  union_of_pt_maps(in, in, new);
913  if(unfeasible_p)
914  points_to_graph_bottom(in) = true;
915 }
#define difference_of_pt_maps(pt1, pt2, pt3)
#define new_pt_map()
#define union_of_pt_maps(pt1, pt2, pt3)
points_to offset_cell(points_to pt, expression delta, type et)
Allocate and return a new points-to "npt", copy of "pt", with an offset of "delta" on the sink.
Definition: expression.c:937
points_to find_arc_in_points_to_set(cell, cell, pt_map)
The approximation is not taken into account.
#define points_to_undefined_p(x)
#define semantics_user_warning

References add_arc_to_pt_map, anywhere_cell_p(), CELL, cell_typed_anywhere_locations_p(), copy_cell(), difference_of_pt_maps, find_arc_in_points_to_set(), FOREACH, gen_length(), make_approximation_may(), make_descriptor_none(), make_points_to(), new_pt_map, null_cell_p(), offset_cell(), points_to_cell_to_string(), points_to_graph_bottom, points_to_undefined_p, semantics_user_warning, and union_of_pt_maps.

Referenced by pointer_arithmetic_to_points_to().

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

◆ offset_points_to_cell()

void offset_points_to_cell ( cell  sink,
expression  delta,
type  t,
bool unique_p   __attribute__(__unused__) 
)

FI: offset_cell() has been derived from this function.

Some factoring out should be performed.

The naming is all wrong: offset_points_to_cell() can operate on a cell, while offset_cell() is designed to operate on a cell component of a points-to.

Type "t" is used to decide which subscript should be updated by delta.

"&a[i]" should be transformed into "&a[i+eval(delta)]" when "delta" can be statically evaluated

No subscript is possible, but 0 and it does not need to appear

dereferencing18.c: a scalar was malloced

We might use unique_p and the value of delta to detect an error or to warn the user about a possible error

Definition at line 1036 of file expression.c.

1040 {
1041  /* "&a[i]" should be transformed into "&a[i+eval(delta)]" when
1042  "delta" can be statically evaluated */
1043  reference r = cell_any_reference(sink);
1044  entity rv = reference_variable(r);
1045  if(nowhere_cell_p(sink))
1046  ; // user error: possible incrementation of an uninitialized pointer
1047  else if(null_cell_p(sink))
1048  // FI: the operation requested is impossible; the condition should
1049  // be checked above to update the pt_map and/or to signal a bug
1050  ; // Impossible: possible incrementation of a NULL pointer
1051  else if(anywhere_cell_p(sink))
1052  ; // It is already fuzzy no need to add more
1053  // FI: it might be necessary to exclude *HEAP* too when a minimal
1054  // heap model is used (ABSTRACT_HEAP_LOCATIONS = "unique")
1055  // FI: this has been dealt with somewhere else
1056  // else if(entity_array_p(rv)
1057  // || !get_bool_property("POINTS_TO_STRICT_POINTER_TYPES")) {
1058  else if(entity_array_p(rv) || cell_typed_anywhere_locations_p(sink)) {
1059  value val = EvalExpression(delta);
1060  list sl = reference_indices(r);
1061  if(value_constant_p(val) && constant_int_p(value_constant(val))) {
1062  int dv = constant_int(value_constant(val));
1063  if(ENDP(sl)) {
1064  if(entity_array_p(rv)) {
1065  // FI: oops, we are in trouble; assume 0...
1066  expression se = int_to_expression(dv);
1067  reference_indices(r) = CONS(EXPRESSION, se, NIL);
1068  }
1069  else {
1070  ; // FI: No need to add a zero subscript to a scalar variable
1071  }
1072  }
1073  else {
1074  // FI: this is wrong, there is no reason to update the last
1075  // subscript; the type of the offset should be passed as an
1076  // argument. See for instance dereferencing08.c. And
1077  // dereferencing18.c
1078  list tsl = find_points_to_subscript_for_type(sink, t);
1079  if(ENDP(tsl)) {
1080  // dereferencing18: the only possible offset is 0, dv==0,
1081  // Or the points-to information is approximate.
1082  // unique_p should be used here to decide if a warning should
1083  // be emitted
1084  ;
1085  }
1086  else {
1087  // expression lse = EXPRESSION(CAR(gen_last(sl)));
1088  expression lse = EXPRESSION(CAR(tsl));
1089  value vlse = EvalExpression(lse);
1090  if(value_constant_p(vlse) && constant_int_p(value_constant(vlse))) {
1091  int ov = constant_int(value_constant(vlse));
1092  int k = get_int_property("POINTS_TO_SUBSCRIPT_LIMIT");
1093  if(-k <= ov && ov <= k) {
1094  expression nse = int_to_expression(dv+ov);
1095  //EXPRESSION_(CAR(gen_last(sl))) = nse;
1096  EXPRESSION_(CAR(tsl)) = nse;
1097  }
1098  else {
1100  //EXPRESSION_(CAR(gen_last(sl))) = nse;
1101  EXPRESSION_(CAR(tsl)) = nse;
1102  }
1103  free_expression(lse);
1104  }
1105  else {
1106  // If the index cannot be computed, used the unbounded expression
1108  //EXPRESSION_(CAR(gen_last(sl))) = nse;
1109  EXPRESSION_(CAR(tsl)) = nse;
1110  free_expression(lse);
1111  }
1112  }
1113  }
1114  }
1115  else {
1116  if(ENDP(sl)) {
1118  reference_indices(r) = CONS(EXPRESSION, nse, NIL);
1119  }
1120  else {
1121  list tsl = find_points_to_subscript_for_type(sink, t);
1122  if(ENDP(tsl)) {
1123  /* No subscript is possible, but 0 and it does not need to appear */
1124  /* dereferencing18.c: a scalar was malloced */
1125  if(zero_expression_p(delta))
1126  ; // Nothing to be done: the subscript is ignored
1127  else {
1128  /* We might use unique_p and the value of delta to detect
1129  an error or to warn the user about a possible error */
1130  ;
1131  }
1132  }
1133  else {
1134  //expression ose = EXPRESSION(CAR(gen_last(sl)));
1135  expression ose = EXPRESSION(CAR(tsl));
1137  //EXPRESSION_(CAR(gen_last(sl))) = nse;
1138  EXPRESSION_(CAR(tsl)) = nse;
1139  free_expression(ose);
1140  }
1141  }
1142  }
1143  }
1144  // FI to be extended to pointers and points-to stubs
1145  else {
1146  if(zero_expression_p(delta)) {
1147  ;
1148  }
1149  else {
1150  pips_user_error("Use of pointer arithmetic on \"%s\" at line %d is not "
1151  "standard-compliant.\n%s",
1152  entity_user_name(rv),
1154  get_bool_property("POINTS_TO_STRICT_POINTER_TYPES")?
1155  "Try resetting property \"POINTS_TO_STRICT_POINTER_TYPES\""
1156  " for usual non-standard compliant C code.\n"
1157  :"");
1158  }
1159  }
1160 }
list find_points_to_subscript_for_type(cell, type)
Find the subscript in the reference of cell "c" that would make the reference type be "t" if the subs...
Definition: type.c:1274
bool entity_array_p(entity e)
Is e a variable with an array type?
Definition: entity.c:754
bool zero_expression_p(expression e)
Definition: expression.c:1217

References anywhere_cell_p(), CAR, cell_any_reference(), cell_typed_anywhere_locations_p(), CONS, constant_int, constant_int_p, ENDP, entity_array_p(), entity_user_name(), EvalExpression(), EXPRESSION, EXPRESSION_, find_points_to_subscript_for_type(), free_expression(), get_bool_property(), get_int_property(), int_to_expression(), make_unbounded_expression(), NIL, nowhere_cell_p(), null_cell_p(), pips_user_error, points_to_context_statement_line_number(), reference_indices, reference_variable, value_constant, value_constant_p, and zero_expression_p().

Referenced by offset_points_to_cells().

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

◆ offset_points_to_cells()

void offset_points_to_cells ( list  sinks,
expression  delta,
type  t 
)

Each cell in sinks is replaced by a cell located "delta" elements further up in the memory.

Similar to offset_cells(), but, in spite of the name, cannot be used with points-to cells that are part of a points-to belonging to a points-to set.

Parameters
sinksinks
deltaelta

Definition at line 1020 of file expression.c.

1021 {
1022  FOREACH(CELL, sink, sinks) {
1023  offset_points_to_cell(sink, delta, t, ENDP(CDR(sinks)));
1024  }
1025 }
void offset_points_to_cell(cell sink, expression delta, type t, bool unique_p __attribute__((__unused__)))
FI: offset_cell() has been derived from this function.
Definition: expression.c:1036

References CDR, CELL, ENDP, FOREACH, and offset_points_to_cell().

Referenced by expression_to_points_to_sinks_with_offset(), and unary_intrinsic_call_to_points_to_sinks().

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

◆ order_condition_to_points_to()

pt_map order_condition_to_points_to ( entity  f,
list  al,
bool  true_p,
pt_map  in 
)

The expression list "al" contains exactly two arguments.

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

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

The condition cannot violate an exact arc.

The condition cannot violate an exact arc.

Parameters
all
true_prue_p
inn

Definition at line 3176 of file expression.c.

3177 {
3178  pt_map out = in;
3179  bool (*cmp_function)(cell, cell);
3180 
3181  if((ENTITY_LESS_OR_EQUAL_P(f) && true_p)
3182  || (ENTITY_GREATER_THAN_P(f) && !true_p)) {
3183  // cmp_function = cell_is_less_than_or_equal_to_p;
3184  cmp_function = cell_is_greater_than_p;
3185  }
3186  else if((ENTITY_LESS_OR_EQUAL_P(f) && !true_p)
3187  || (ENTITY_GREATER_THAN_P(f) && true_p)) {
3188  // cmp_function = cell_is_greater_than_p;
3189  cmp_function = cell_is_less_than_or_equal_to_p;
3190  }
3191  else if((ENTITY_GREATER_OR_EQUAL_P(f) && true_p)
3192  || (ENTITY_LESS_THAN_P(f) && !true_p)) {
3193  // cmp_function = cell_is_greater_than_or_equal_to_p;
3194  cmp_function = cell_is_less_than_p;
3195  }
3196  else if((ENTITY_GREATER_OR_EQUAL_P(f) && !true_p)
3197  || (ENTITY_LESS_THAN_P(f) && true_p)) {
3198  //cmp_function = cell_is_less_than_p;
3199  cmp_function = cell_is_greater_than_or_equal_to_p;
3200  }
3201  else {
3202  pips_internal_error("Unexpected relational operator.\n");
3203  cmp_function = NULL;
3204  }
3205 
3206  expression lhs = EXPRESSION(CAR(al));
3207  type lhst = expression_to_type(lhs);
3208  expression rhs = EXPRESSION(CAR(CDR(al)));
3209  type rhst = expression_to_type(rhs);
3210  if(pointer_type_p(lhst) || pointer_type_p(rhst)) {
3212  if(gen_length(L)==1) { // FI: one fixed bound
3213  cell lc = CELL(CAR(L));
3215  set out_s = points_to_graph_set(out);
3216  SET_FOREACH(points_to, pt, out_s) {
3217  cell source = points_to_source(pt);
3218  if(cell_in_list_p(source, RR)) {
3219  cell sink = points_to_sink(pt);
3220  if(cmp_function(lc, sink)) {
3222  if(approximation_exact_p(a)) {
3223  /* The condition cannot violate an exact arc. */
3224  // clear_pt_map(out);
3225  points_to_graph_bottom(out) = true;
3226  // Would be useless/different with a union
3228  }
3229  else
3231  }
3232  }
3233  }
3234  }
3235  else {
3236  list R = expression_to_points_to_sinks(rhs, in);
3237  if(gen_length(R)==1) { // FI: one fixed bound
3238  cell rc = CELL(CAR(R));
3239  list LL = expression_to_points_to_sources(lhs, in);
3240  set out_s = points_to_graph_set(out);
3241  SET_FOREACH(points_to, pt, out_s) {
3242  cell source = points_to_source(pt);
3243  if(cell_in_list_p(source, LL)) {
3244  cell sink = points_to_sink(pt);
3245  if(cmp_function(sink, rc)) {
3246  // FI: Oops in middle of the iterator...
3248  if(approximation_exact_p(a)) {
3249  /* The condition cannot violate an exact arc. */
3250  // clear_pt_map(out);
3251  points_to_graph_bottom(out) = true;
3252  // Would be useless/different with a union
3254  }
3255  else
3257  }
3258  }
3259  }
3260  }
3261  }
3262  }
3263  free_type(lhst), free_type(rhst);
3264 
3265  return in;
3266 }
struct _newgen_struct_cell_ * cell
Definition: effects.h:90
#define RR
Definition: genspec.h:95
int bool
we cannot use an enum or stdbool because we need to be compatible with newgen, thus boolean need to h...
Definition: newgen_types.h:78
bool cell_is_greater_than_or_equal_to_p(cell c1, cell c2)
Definition: expression.c:2830
bool cell_is_greater_than_p(cell c1, cell c2)
Definition: expression.c:2835
bool cell_is_less_than_p(cell c1, cell c2)
Definition: expression.c:2825
bool cell_is_less_than_or_equal_to_p(cell c1, cell c2)
See if you can decide that the addresses linked to c1 are smaller than the addresses linked to c2.
Definition: expression.c:2820
#define ENTITY_LESS_THAN_P(e)
#define ENTITY_GREATER_THAN_P(e)
#define ENTITY_LESS_OR_EQUAL_P(e)
#define ENTITY_GREATER_OR_EQUAL_P(e)

References approximation_exact_p, CAR, CDR, CELL, cell_in_list_p(), cell_is_greater_than_or_equal_to_p(), cell_is_greater_than_p(), cell_is_less_than_or_equal_to_p(), cell_is_less_than_p(), ENTITY_GREATER_OR_EQUAL_P, ENTITY_GREATER_THAN_P, ENTITY_LESS_OR_EQUAL_P, ENTITY_LESS_THAN_P, EXPRESSION, expression_to_points_to_sinks(), expression_to_points_to_sources(), expression_to_type(), f(), free_type(), gen_length(), out, pips_internal_error, pointer_type_p(), points_to_approximation, points_to_graph_bottom, points_to_graph_set, points_to_sink, points_to_source, remove_arc_from_pt_map, RR, set_clear(), and SET_FOREACH.

Referenced by relational_intrinsic_call_condition_to_points_to().

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

◆ pointer_arithmetic_to_points_to()

pt_map pointer_arithmetic_to_points_to ( expression  lhs,
expression  delta,
pt_map  pt_in 
)

Update the sink locations associated to the source "lhs" under points-to information pt_map by "delta".

C standard guarantees that the sink objects is unchanged by pointer arithmetic.

Property POINTS_TO_STRICT_POINTER_TYPES is used to be more or less flexible about formal parameters and local variables such as "int * p"

Parameters
lhshs
deltaelta
pt_int_in

Definition at line 760 of file expression.c.

763 {
764  pt_map pt_out = pt_in;
765  list sources = expression_to_points_to_sources(lhs, pt_out);
766  bool to_be_freed;
767  type et = points_to_expression_to_type(lhs, &to_be_freed);
768  FOREACH(CELL, source, sources) {
769  list sinks = source_to_sinks(source, pt_out, false);
770  if(ENDP(sinks)) {
772  //pips_internal_error("Sink missing for a source based on \"%s\".\n",
773  // entity_user_name(v));
774  pips_user_warning("No defined value for pointer \"%s\".\n",
775  entity_user_name(v));
776  if(gen_length(sources)==1)
777  // The code cannot be executed
778  clear_pt_map(pt_out);
779  }
780  offset_cells(source, sinks, delta, et, pt_out);
781  // FI: we could perform some filtering out of pt_in
782  // If an arc points from source to nowehere/undefined or to the
783  // null location, this arc should be removed from pt_in as it
784  // cannot lead to an execution reaching the next statement.
785  FOREACH(CELL, sink, sinks) {
786  if(nowhere_cell_p(sink))
787  remove_points_to_arcs(source, sink, pt_out);
788  else if(null_cell_p(sink))
789  remove_points_to_arcs(source, sink, pt_out);
790  }
791  }
792  // FI: should we free the sources list? Fully free it?
793  return pt_out;
794 }
void offset_cells(cell source, list sinks, expression delta, type et, pt_map in)
Each cell in sinks is replaced by a cell located "delta" elements further up in the memory.
Definition: expression.c:869
void remove_points_to_arcs(cell, cell, pt_map)

References CELL, cell_any_reference(), clear_pt_map, ENDP, entity_user_name(), expression_to_points_to_sources(), FOREACH, gen_length(), nowhere_cell_p(), null_cell_p(), offset_cells(), pips_user_warning, points_to_expression_to_type(), reference_variable, remove_points_to_arcs(), and source_to_sinks().

Referenced by intrinsic_call_to_points_to().

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

◆ pointer_assignment_to_points_to()

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

FI: this is a crazy idea to avoid problems in balancing test branches. It should only be useful when the formal context has to be expanded by this assignment. lhs = lhs;

Of course, it is a catastrophy when expression lhs has side effects...

And it does not work because the current "in" of the test is modified by side-effect no seen when the false branch is analyzed.

Parameters
lhshs
rhshs
pt_int_in

Definition at line 1437 of file expression.c.

1440 {
1441  /* FI: this is a crazy idea to avoid problems in balancing test
1442  * branches. It should only be useful when the formal context has to
1443  * be expanded by this assignment. lhs = lhs;
1444  *
1445  * Of course, it is a catastrophy when expression lhs has side effects...
1446  *
1447  * And it does not work because the current "in" of the test is
1448  * modified by side-effect no seen when the false branch is analyzed.
1449  */
1450  // pt_map pt_out = internal_pointer_assignment_to_points_to(lhs, lhs, pt_in);
1451  pt_map pt_out = internal_pointer_assignment_to_points_to(lhs, rhs, pt_in);
1452  return pt_out;
1453 }
pt_map internal_pointer_assignment_to_points_to(expression lhs, expression rhs, pt_map pt_in)
Any abstract location of the lhs in L is going to point to any sink of any abstract location of the r...
Definition: expression.c:1315

References internal_pointer_assignment_to_points_to().

Referenced by assignment_to_points_to(), and expand_points_to_domain().

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

◆ points_to_cell_to_pointer_cells()

list points_to_cell_to_pointer_cells ( cell  c)

Definition at line 1900 of file expression.c.

1901 {
1903 }
#define set_undefined
Definition: newgen_set.h:48

References generic_points_to_cell_to_useful_pointer_cells(), and set_undefined.

Referenced by memory_leak_to_more_memory_leaks(), and points_to_cells_to_pointer_cells().

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

◆ points_to_cell_to_useful_pointer_cells()

list points_to_cell_to_useful_pointer_cells ( cell  c,
set  pts 
)
Parameters
ptsts

Definition at line 1905 of file expression.c.

1906 {
1908 }

References generic_points_to_cell_to_useful_pointer_cells().

Referenced by filter_formal_context_according_to_actual_context(), and recursive_filter_formal_context_according_to_actual_context().

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

◆ points_to_cells_to_pointer_cells()

list points_to_cells_to_pointer_cells ( list  pl)

Convert cells in l into derived pointer cells when possible.

The elements of list pl are reused in list l

Parameters
pll

Definition at line 1917 of file expression.c.

1918 {
1919  list l = NIL;
1920  FOREACH(CELL, pc, pl) {
1922  l = gen_nconc(l, nl);
1923  }
1924  return l;
1925 }
static hash_table pl
properties are stored in this hash table (string -> property) for fast accesses.
Definition: properties.c:783

References CELL, FOREACH, gen_nconc(), NIL, pl, and points_to_cell_to_pointer_cells().

Referenced by recursive_filter_formal_context_according_to_actual_context().

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

◆ range_to_points_to()

pt_map range_to_points_to ( range  r,
pt_map  pt_in,
bool  side_effect_p 
)
Parameters
pt_int_in
side_effect_pide_effect_p

Definition at line 284 of file expression.c.

285 {
286  pt_map pt_out = pt_in;
287  expression l = range_lower(r);
288  expression u = range_upper(r);
290  pt_out = expression_to_points_to(l, pt_in, side_effect_p);
291  pt_out = expression_to_points_to(u, pt_out, side_effect_p);
292  pt_out = expression_to_points_to(i, pt_out, side_effect_p);
293  return pt_out;
294 }
#define range_upper(x)
Definition: ri.h:2290
#define range_increment(x)
Definition: ri.h:2292
#define range_lower(x)
Definition: ri.h:2288

References expression_to_points_to(), range_increment, range_lower, and range_upper.

Referenced by expression_to_points_to().

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

◆ reduce_cell_to_pointer_type()

cell reduce_cell_to_pointer_type ( cell  c)

Remove last subscripts of cell c till its type becomes a scalar pointer.

This of course may fail.

Remove the last subscript, hopefully 0

Definition at line 1809 of file expression.c.

1810 {
1811  bool to_be_freed;
1812  type t = points_to_cell_to_type(c, &to_be_freed);
1814  list sl = reference_indices(r);
1815  bool remove_p = !pointer_type_p(t);
1816  if(to_be_freed) free_type(t);
1817  while(remove_p) {
1818  if(!ENDP(sl)) {
1819  /* Remove the last subscript, hopefully 0 */
1820  list ls = gen_last(sl); // last subscript
1821  expression lse = EXPRESSION(CAR(ls));
1823  break; // This subscript cannot be removed
1824  gen_list_and_not(&sl, ls);
1825  reference_indices(r) = sl;
1826  // because sl is a sublist of ls, the chunk has already been freed
1827  // gen_full_free_list(ls);
1828  // gen_free_list(ls);
1829  t = points_to_cell_to_type(c, &to_be_freed);
1830  // remove_p = !pointer_type_p(t); we may end up with char[] instead of char*
1831  remove_p = !C_pointer_type_p(t);
1832  if(to_be_freed) free_type(t);
1833  }
1834  else
1835  break; // FI: in fact, an internal error
1836  }
1837  return c;
1838 }
bool field_reference_expression_p(expression)
Check if expression "e" is a reference to a struct field.
Definition: points_to.c:224
list gen_last(list l)
Return the last element of a list.
Definition: list.c:578

References C_pointer_type_p(), CAR, cell_any_reference(), ENDP, EXPRESSION, field_reference_expression_p(), free_type(), gen_last(), gen_list_and_not(), pointer_type_p(), points_to_cell_to_type(), and reference_indices.

Referenced by list_assignment_to_points_to(), and reduce_cells_to_pointer_type().

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

◆ reduce_cells_to_pointer_type()

list reduce_cells_to_pointer_type ( list  cl)

Undo the extra eval performed when stubs are generated: 0 subscripts are added when arrays are involved.

Parameters
cll

Definition at line 1844 of file expression.c.

1845 {
1846  FOREACH(CELL, c, cl) {
1847  if(null_cell_p(c)) // There may be other exceptions...
1848  ;
1849  else
1850  (void) reduce_cell_to_pointer_type(c);
1851  }
1852  return cl;
1853 }

References CELL, FOREACH, null_cell_p(), and reduce_cell_to_pointer_type().

+ Here is the call graph for this function:

◆ reference_condition_to_points_to()

pt_map reference_condition_to_points_to ( reference  r,
pt_map  in,
bool  true_p 
)

Handle conditions such as "if(p)".

Do not take care of side effects in references...

are we dealing with a pointer?

if p points to NULL, the condition is not feasible. If not, remove any arc from p to NULL

Make a points-to NULL and remove the arc from the current out

remove any arc from v to anything and add an arc from p to NULL

Make a points-to NULL and remove the arc from the current out

This condition is always false

Parameters
inn
true_prue_p

Definition at line 2538 of file expression.c.

2539 {
2540  pt_map out = in;
2541  entity v = reference_variable(r);
2543  list sl = reference_indices(r);
2544 
2545  /* Do not take care of side effects in references... */
2546  out = expressions_to_points_to(sl, out, false);
2547 
2548  /* are we dealing with a pointer? */
2549  if(pointer_type_p(vt)) {
2550  if(true_p) {
2551  /* if p points to NULL, the condition is not feasible. If not,
2552  remove any arc from p to NULL */
2553  if(reference_must_points_to_null_p(r, in)) {
2554  // FI: memory leak with clear_pt?
2555  pips_user_warning("Dead code detected.\n");
2556  clear_pt_map(out);
2557  points_to_graph_bottom(out) = true;
2558  }
2559  else {
2560  /* Make a points-to NULL and remove the arc from the current out */
2563  points_to a = make_points_to(source, sink, make_approximation_may(),
2565  remove_arc_from_pt_map(a, in);
2566  free_points_to(a);
2567  }
2568  }
2569  else {
2570  if(reference_may_points_to_null_p(r, in)) {
2571  /* remove any arc from v to anything and add an arc from p to NULL */
2572  set in_s = points_to_graph_set(in);
2573  points_to_source_projection(in_s, v);
2574  /* Make a points-to NULL and remove the arc from the current out */
2579  add_arc_to_pt_map(a, in);
2580  }
2581  else {
2582  /* This condition is always false */
2583  pips_user_warning("Dead code detected.\n");
2584  clear_pt_map(out);
2585  points_to_graph_bottom(out) = true;
2586  }
2587  }
2588  }
2589 
2590  return out;
2591 }
void free_points_to(points_to p)
cell make_null_pointer_value_cell(void)
bool reference_must_points_to_null_p(reference, pt_map)
Definition: sinks.c:1859
bool reference_may_points_to_null_p(reference, pt_map)
Definition: sinks.c:1873
set points_to_source_projection(set, entity)
Remove all arcs starting from e because e has been assigned a new value.

References add_arc_to_pt_map, clear_pt_map, copy_reference(), entity_basic_concrete_type(), expressions_to_points_to(), free_points_to(), make_approximation_exact(), make_approximation_may(), make_cell_reference(), make_descriptor_none(), make_null_pointer_value_cell(), make_points_to(), out, pips_user_warning, pointer_type_p(), points_to_graph_bottom, points_to_graph_set, points_to_source_projection(), reference_indices, reference_may_points_to_null_p(), reference_must_points_to_null_p(), reference_variable, and remove_arc_from_pt_map.

Referenced by condition_to_points_to().

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

◆ reference_to_points_to()

pt_map reference_to_points_to ( reference  r,
pt_map  pt_in,
bool  side_effect_p 
)

The subscript expressions may impact the points-to information.

E.g. a[*(p++)]

FI: I'm surprised that pointers can be indexed instead of being subscripted... This is linked to the parser in expression_to_points_to().

Parameters
pt_int_in
side_effect_pide_effect_p

Definition at line 262 of file expression.c.

263 {
264  pt_map pt_out = pt_in;
265  if(!points_to_graph_bottom(pt_in)) {
266  list sel = reference_indices(r);
267  entity v = reference_variable(r);
269  // FI: some or all of these tests could be placed in
270  // dereferencing_to_points_to()
271  if(!entity_stub_sink_p(v)
272  && !formal_parameter_p(v)
273  && !ENDP(sel)
274  && pointer_type_p(t)) {
276  pt_out = dereferencing_to_points_to(e, pt_in);
277  free_expression(e);
278  }
279  pt_out = expressions_to_points_to(sel, pt_in, side_effect_p);
280  }
281  return pt_out;
282 }
bool entity_stub_sink_p(entity e)
test if an entity is a stub sink for a formal parameter e.g.
bool formal_parameter_p(entity)
Definition: variable.c:1489

References dereferencing_to_points_to(), ENDP, entity_basic_concrete_type(), entity_stub_sink_p(), entity_to_expression(), expressions_to_points_to(), formal_parameter_p(), free_expression(), pointer_type_p(), points_to_graph_bottom, reference_indices, and reference_variable.

Referenced by expression_to_points_to().

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

◆ relational_intrinsic_call_condition_to_points_to()

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

Update the points-to information "in" according to the validity of the condition.

We can remove the arcs that violate the condition or decide that the condition cannot be true.

Parameters
inn
true_prue_p

Definition at line 3274 of file expression.c.

3275 {
3276  pt_map out = in;
3277  entity f = call_function(c);
3278  list al = call_arguments(c);
3279 
3280  if((ENTITY_EQUAL_P(f) && true_p)
3281  || (ENTITY_NON_EQUAL_P(f) && !true_p)) {
3283  }
3284  else if((ENTITY_EQUAL_P(f) && !true_p)
3285  || (ENTITY_NON_EQUAL_P(f) && true_p)) {
3287  }
3288  else if(ENTITY_LESS_OR_EQUAL_P(f)
3291  || ENTITY_LESS_THAN_P(f)) {
3292  out = order_condition_to_points_to(f, al, true_p, in);
3293  }
3294  else {
3295  pips_internal_error("Not implemented yet.\n");
3296  }
3297  pips_assert("out is consistent", points_to_graph_consistent_p(out));
3298  return out;
3299 }
pt_map equal_condition_to_points_to(list al, pt_map in)
The expression list "al" contains exactly two arguments, "lhs" and "rhs".
Definition: expression.c:2986
pt_map order_condition_to_points_to(entity f, list al, bool true_p, pt_map in)
The expression list "al" contains exactly two arguments.
Definition: expression.c:3176
pt_map non_equal_condition_to_points_to(list al, pt_map in)
The expression list "al" contains exactly two arguments.
Definition: expression.c:3086
#define ENTITY_NON_EQUAL_P(e)
#define ENTITY_EQUAL_P(e)

References call_arguments, call_function, ENTITY_EQUAL_P, ENTITY_GREATER_OR_EQUAL_P, ENTITY_GREATER_THAN_P, ENTITY_LESS_OR_EQUAL_P, ENTITY_LESS_THAN_P, ENTITY_NON_EQUAL_P, equal_condition_to_points_to(), f(), non_equal_condition_to_points_to(), order_condition_to_points_to(), out, pips_assert, pips_internal_error, and points_to_graph_consistent_p().

Referenced by intrinsic_call_condition_to_points_to().

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

◆ struct_assignment_to_points_to()

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

pt_in is modified by side-effects and returned as pt_out

This function is also used for declarations, although the syntax for declarations is reacher than the syntax for assignments which can use BRACE_INTRINSIC.

Current arc list (cal): the new arc may be conflicting with an existing must arc

We may have an implicit array of struct in the right or left hand side

rray_type_p(ft) ||

FI: conditionally add zero subscripts necessary to move from an array "a" to its first element, e.g. a[0][0][0]

Parameters
lhshs
rhshs
pt_int_in

Definition at line 2319 of file expression.c.

2322 {
2323  pt_map pt_out = pt_in;
2325  pt_out = struct_initialization_to_points_to(lhs, rhs, pt_in);
2326  else {
2327  list L = expression_to_points_to_sources(lhs, pt_out);
2328  list R = expression_to_points_to_sources(rhs, pt_out);
2329  FOREACH(CELL, lc, L) {
2330  bool l_to_be_freed;
2331  type lt = cell_to_type(lc, &l_to_be_freed);
2333  if(!entity_abstract_location_p(le)) {
2334  FOREACH(CELL, rc, R) {
2335  bool r_to_be_freed;
2336  type rt = cell_to_type(rc, &r_to_be_freed);
2338  if(entity_abstract_location_p(le)) {
2339  if(entity_abstract_location_p(re)) {
2340  pips_internal_error("Not implemented yet.");
2341  }
2342  else {
2343  pips_internal_error("Not implemented yet.");
2344  }
2345  }
2346  else {
2347  if(entity_abstract_location_p(re)) {
2348  // FI: when re==NULL, we could generate a user warning or
2349  // ignore the dereferencement of NULL...
2350 
2351  // All fields are going to point to this abstract
2352  // location... or to the elements pointed by this abstract
2353  // location
2354  pips_assert("Left type is struct",
2355  struct_type_p(lt));
2357  type st = entity_type(ste); // structure type
2358  list fl = type_struct(st); // field list
2359  FOREACH(ENTITY, f, fl) {
2360  type ft = entity_type(f); // field type
2361  if(pointer_type_p(ft)) {
2363  // reference rr = copy_reference(cell_any_reference(rc));
2365  cell lc = make_cell_reference(lr);
2366  type p_t = type_to_pointed_type(ft);
2367  cell rc = make_anywhere_cell(p_t);
2368  // reference_add_field_dimension(rr, f);
2369  // expression nlhs = reference_to_expression(lr);
2370  // expression nrhs = reference_to_expression(rr);
2371 
2372  // FI: too bad this cannot be reused because of an assert in normalize_reference()....
2373  // pt_out = assignment_to_points_to(nlhs, nrhs, pt_out);
2375  // FI: pt is allocated but not used...
2376  // FI: see update_points_to_graph_with_arc()?
2377  /* Current arc list (cal): the new arc may be
2378  conflicting with an existing must arc */
2379  list cal = points_to_source_to_arcs(lc, pt_out, false);
2380  list oal = NIL;
2381  list nal = NIL;
2382  FOREACH(POINTS_TO, a, cal) {
2384  if(approximation_exact_p(ap)) {
2385  oal = CONS(POINTS_TO, a, oal);
2386  points_to na =
2391  nal = CONS(POINTS_TO, na, nal);
2392  }
2393  }
2394  FOREACH(POINTS_TO, oa, oal)
2395  remove_arc_from_pt_map(oa, pt_out);
2396  FOREACH(POINTS_TO, na, nal)
2397  add_arc_to_pt_map(na, pt_out);
2398  gen_free_list(oal), gen_free_list(nal);
2399  add_arc_to_pt_map(pt, pt_out); // FI: I guess...
2400  // FI->FC: it would be nice to have a Newgen free_xxxxs() to
2401  // free a list of objects of type xxx with one call
2402  // FI: why would we free these expressions?
2403  // free_expression(lhs), free_expression(rhs);
2404  }
2405  else if(struct_type_p(ft)) {
2406  pips_internal_error("Not implemented yet.\n");
2407  }
2408  else {
2409  ; // Do nothing
2410  }
2411  }
2412  }
2413  else {
2414  pips_assert("Both types are struct or array of struct",
2416  && (struct_type_p(rt) || array_of_struct_type_p(rt)));
2417  /* We may have an implicit array of struct in the right or
2418  * left hand side
2419  */
2420  // pips_assert("Both type are equal", type_equal_p(lt, rt));
2421  basic ltb = variable_basic(type_variable(lt));
2422  basic rtb = variable_basic(type_variable(rt));
2423  pips_assert("Both type are somehow equal",
2424  basic_equal_p(ltb, rtb));
2426  type st = entity_type(ste); // structure type
2427  list fl = type_struct(st); // field list
2428  FOREACH(ENTITY, f, fl) {
2429  type uft = entity_basic_concrete_type(f); // field type
2430  // type uft = ultimate_type(ft);
2431  bool array_p = /*array_type_p(ft) ||*/ array_type_p(uft);
2432  if(!array_p && (pointer_type_p(uft) || struct_type_p(uft))) {
2435  /* FI: conditionally add zero subscripts necessary to
2436  move from an array "a" to its first element,
2437  e.g. a[0][0][0] */
2444  pt_out = assignment_to_points_to(nlhs, nrhs, pt_out);
2445  // FI->FC: it would be nice to have a Newgen free_xxxxs() to
2446  // free a list of objects of type xxx with one call
2447  // The references within the expressions are now part of pt_out
2448  // free_expression(lhs), free_expression(rhs);
2449  }
2450  else if(array_p && (array_of_pointers_type_p(uft)
2451  || pointer_type_p(uft)
2452  || array_of_struct_type_p(uft)
2453  || struct_type_p(uft))) {
2454  // Same as above, but an unbounded subscript is added...
2455  // Quite a special assign in C...
2463  CONS(EXPRESSION, li, NIL));
2465  CONS(EXPRESSION, ri, NIL));
2468  pt_out = assignment_to_points_to(nlhs, nrhs, pt_out);
2469  }
2470  else {
2471  ; // Do nothing
2472  }
2473  }
2474  }
2475  }
2476  }
2477  }
2478  else {
2479  // FI: the lhs is an unknown struct allocated anywhere
2480  // FI: we might have to generate new arcs. e.g. from HEAP to STACK...
2481  pips_internal_error("Not implemented yet.\n");
2482  }
2483  }
2484  }
2485  // pips_internal_error("Not implemented yet for lhs %p and rhs %p\n", lhs, rhs);
2486 
2487  return pt_out;
2488 }
bool entity_abstract_location_p(entity al)
cell make_anywhere_cell(type t)
reference reference_add_field_dimension(reference, entity)
add a field f as a subscript to a reference r if it is meaningful.
Definition: effects.c:1475
type cell_to_type(cell, bool *)
Definition: type.c:513
reference simple_reference_add_field_dimension(reference, entity)
Do not check anything, just add f as a last subscript.
Definition: effects.c:1581
pt_map struct_initialization_to_points_to(expression lhs, expression rhs, pt_map in)
Definition: expression.c:2262
list points_to_source_to_arcs(cell, pt_map, bool)
Build the list of arcs whose source is "source" according to the points-to graphs "ptm".
expression reference_to_expression(reference r)
Definition: expression.c:196
void reference_add_zero_subscripts(reference r, type t)
Definition: expression.c:261
bool C_initialization_expression_p(expression e)
Definition: expression.c:4056
bool basic_equal_p(basic, basic)
Definition: type.c:927
#define type_struct(x)
Definition: ri.h:2964
#define basic_derived(x)
Definition: ri.h:640

References add_arc_to_pt_map, approximation_exact_p, array_of_pointers_type_p(), array_of_struct_type_p(), array_type_p(), assignment_to_points_to(), basic_derived, basic_equal_p(), C_initialization_expression_p(), CELL, cell_any_reference(), cell_to_type(), CONS, copy_cell(), copy_reference(), ENTITY, entity_abstract_location_p(), entity_basic_concrete_type(), entity_type, EXPRESSION, expression_to_points_to_sources(), f(), FOREACH, gen_free_list(), gen_nconc(), make_anywhere_cell(), make_approximation_may(), make_cell_reference(), make_descriptor_none(), make_points_to(), make_unbounded_expression(), NIL, pips_assert, pips_internal_error, pointer_type_p(), POINTS_TO, points_to_approximation, points_to_sink, points_to_source, points_to_source_to_arcs(), reference_add_field_dimension(), reference_add_zero_subscripts(), reference_indices, reference_to_expression(), reference_variable, remove_arc_from_pt_map, simple_reference_add_field_dimension(), struct_initialization_to_points_to(), struct_type_p(), type_struct, type_to_pointed_type(), type_variable, and variable_basic.

Referenced by assignment_to_points_to().

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

◆ struct_initialization_to_points_to()

pt_map struct_initialization_to_points_to ( expression  lhs,
expression  rhs,
pt_map  in 
)

Temporary implementation: use anywhere as default initialization

We must assign to each relevant field its initial value

Parameters
lhshs
rhshs
inn

Definition at line 2262 of file expression.c.

2265 {
2266  pt_map out = in;
2267  // Implementation 0:
2268  // pips_internal_error("Not implemented yet.\n");
2269  // pips_assert("to please gcc, waiting for implementation", lhs==rhs && in==in);
2271 
2272  // L must contain a unique cell, containing a non-index reference
2273  pips_assert("One struct to initialize", (int) gen_length(L)==1);
2274  cell c = CELL(CAR(L));
2276  entity e = reference_variable(r);
2277  pips_assert("c is not indexed", ENDP(reference_indices(r)));
2278  if(0) {
2279  /* Temporary implementation: use anywhere as default initialization */
2280  // ignore rhs
2282  FOREACH(CELL, source, l) {
2283  bool to_be_freed;
2284  type t = points_to_cell_to_type(source, &to_be_freed);
2286  cell sink = make_anywhere_cell(c_t);
2287  if(to_be_freed) free_type(t);
2288  points_to pt = make_points_to(source, sink,
2291  add_arc_to_pt_map(pt, out);
2292  }
2293  }
2294  else {
2295  /* We must assign to each relevant field its initial value */
2296  list fl = struct_variable_to_fields(e); // list of entities
2298  pips_assert("The field and initial value lists have the same length",
2299  gen_length(fl)==gen_length(vl));
2300  list cvl = vl;
2301  FOREACH(ENTITY, f, fl) {
2302  reference nr =
2305  out = assignment_to_points_to(nlhs, EXPRESSION(CAR(cvl)), out);
2306  POP(cvl);
2307  }
2308  }
2309 
2310  return out;
2311 }
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
list variable_to_pointer_locations(entity)
variable.c
Definition: variable.c:66
list struct_initialization_expression_to_expressions(expression e)
Returns a list of expressions hidden by the brace function.
Definition: expression.c:4073
list struct_variable_to_fields(entity)
Assume that v is declared as a struct.
Definition: variable.c:2045

References add_arc_to_pt_map, assignment_to_points_to(), CAR, CELL, cell_any_reference(), compute_basic_concrete_type(), CONS, ENDP, ENTITY, entity_to_expression(), EXPRESSION, expression_to_points_to_sources(), f(), FOREACH, free_type(), gen_length(), make_anywhere_cell(), make_approximation_exact(), make_descriptor_none(), make_points_to(), make_reference(), NIL, out, pips_assert, points_to_cell_to_type(), POP, reference_indices, reference_to_expression(), reference_variable, struct_initialization_expression_to_expressions(), struct_variable_to_fields(), type_to_pointed_type(), and variable_to_pointer_locations().

Referenced by struct_assignment_to_points_to().

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

◆ subscripted_reference_to_points_to()

void subscripted_reference_to_points_to ( reference  r,
list  sl,
pt_map  pt_in 
)

FI: what is this function supposed to do? Just update "pt_in" to make sure that "r" can be dereferenced? And then recursively, with the different subscripts?

expression.c

FI: we have to find the right location for the subscript to update. Some dimensions are due to the dimension of the source in pt_in, one dimension is due to the fact that we are dealing with a pointer, some dimensions are due to the fact that an array is pointed. The dimension to update may be the first one, the last one, or one in the middle.

This also depends on strict typing...

See for instance, Pointers/pointer20.c

Parameters
sll
pt_int_in

Definition at line 57 of file expression.c.

58 {
59  if(!ENDP(sl)) {
61  if(pointer_type_p(rt)) {
62  //type pt = type_to_pointed_type(rt);
63  //list cl = reference_to_points_to_sinks(r, pt, pt_in, false, true);
64  list cl = reference_to_points_to_sinks(r, rt, pt_in, true, true);
65  // FI: the arc between "r" and NULL should be removed...
67  FOREACH(CELL, c, cl) {
68  if(!ENDP(CDR(sl))) {
69  expression fs = EXPRESSION(CAR(sl));
70  /* FI: we have to find the right location for the subscript
71  * to update. Some dimensions are due to the dimension of
72  * the source in pt_in, one dimension is due to the fact
73  * that we are dealing with a pointer, some dimensions are
74  * due to the fact that an array is pointed. The dimension
75  * to update may be the first one, the last one, or one in
76  * the middle.
77  *
78  * This also depends on strict typing...
79  *
80  * See for instance, Pointers/pointer20.c
81  */
84  list osl = reference_indices(or);
85  if(ENDP(osl)) {
88  NIL);
89  }
90  else {
92  }
95  }
96  else
97  pips_internal_error("reference could not be updated.\n");
98  }
99  }
100  }
101  else if(array_of_pointers_type_p(rt)) {
102  pips_internal_error("Not implemented yet.\n");
103  }
104  else
105  pips_internal_error("Meaningless call.\n");
106  }
107 }
type points_to_reference_to_concrete_type(reference)
Definition: type.c:685
bool adapt_reference_to_type(reference, type, int(*)(void))
FI: a really stupid function...
Definition: type.c:1327
void points_to_cell_update_last_subscript(cell, expression)
Transform reference a[i]...[j] and expression s into reference a[i]..[j+s] if j and s are constant in...
Definition: effects.c:1643
list reference_to_points_to_sinks(reference, type, pt_map, bool, bool)
Returns a list of memory cells "sinks" possibly accessed by the evaluation of reference "r".
Definition: sinks.c:755
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...

References adapt_reference_to_type(), array_of_pointers_type_p(), CAR, CDR, CELL, cell_any_reference(), CONS, copy_expression(), ENDP, EXPRESSION, FOREACH, NIL, pips_internal_error, pointer_type_p(), points_to_cell_update_last_subscript(), points_to_context_statement_line_number(), points_to_reference_to_concrete_type(), reference_indices, reference_to_points_to_sinks(), and remove_impossible_arcs_to_null().

Referenced by expression_to_points_to().

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

◆ user_call_condition_to_points_to()

pt_map user_call_condition_to_points_to ( call  c,
pt_map  in,
list  el,
bool  true_p 
)
Parameters
inn
ell
true_prue_p

Definition at line 2679 of file expression.c.

2680 {
2681  pt_map out = in;
2682  // FI: a call site to handle like any other user call site...
2683  // Althgouh you'd like to know if true or false is returned...
2684  //pips_user_warning("Interprocedural points-to not implemented yet. "
2685  // "Call site fully ignored.\n");
2686  //
2687  if(true_p) // Analyze the call only once?
2688  out = user_call_to_points_to(c, in, el);
2689  else // No, because side-effects must be taken into account for both branches
2690  out = user_call_to_points_to(c, in, el);
2691  return out;
2692 }

References out, and user_call_to_points_to().

Referenced by call_condition_to_points_to().

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