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

Go to the source code of this file.

Functions

list points_to_cells_parameters (list dl)
 Transform a list of parameters of type "entity" to a list of cells. More...
 
list points_to_cells_pointer_arguments (list al)
 Transform a list of arguments of type "expression" to a list of cells. More...
 
points_to_graph user_call_to_points_to (call c, points_to_graph pt_in, list el)
 FI: limited to the interprocedural option. More...
 
list user_call_to_points_to_sinks (call c, type et __attribute__((unused)), pt_map in __attribute__((unused)), bool eval_p)
 FI: I assume we do not need the eval_p parameter here. More...
 
void remove_arcs_from_pt_map (points_to pts, set pt_out)
 
pt_map user_call_to_points_to_fast_interprocedural (call c, pt_map pt_in, list csel __attribute__((unused)))
 ompute the points to relations in a fast interprocedural way More...
 
bool recursive_filter_formal_context_according_to_actual_context (list fcl, set pt_in, set pt_binded, set binding, set filtered)
 This function looks for successors of elements of list "fcl" both in points-to relations "pt_in" and "pt_binded". More...
 
static type constant_string_type_to_string_type (type t)
 We have to handle constant strings such as "Hello!" and not to forget functional parameters or other types. More...
 
set filter_formal_context_according_to_actual_context (list fpcl, set pt_in, set pt_binded, set binding)
 Filter "pt_in" according to "pt_binded". More...
 
static bool new_recursive_filter_formal_context_according_to_actual_context (cell fc, cell ac, approximation ap, set pt_in, set pt_binded, set binding, set filtered)
 The code is derived from generic_points_to_cell_to_useful_pointer_cell() with no filtering and a direct processing of the pairs of pointers obtained. More...
 
static bool merge_actual_and_formal_sinks (cell fc, list *pfcl, cell ac, list *pacl, set pt_in, set pt_binded, set filtered)
 Handle constant cells such as NULL and UNDEFINED (nowhere) in "fcl" and "acl". More...
 
static bool new_recursive_filter_formal_context_according_to_actual_context_for_pointer_pair (cell fc, cell ac, approximation ap, set pt_in, set pt_binded, set binding, set filtered)
 fc and ac are two pointer cells with same or compatible pointer type More...
 
set new_filter_formal_context_according_to_actual_context (list fpcl, set pt_in, set pt_binded, set binding)
 
set filter_formal_out_context_according_to_formal_in_context (set out, set in, list wpl, entity f)
 If an address has not been written, i.e. More...
 
void points_to_translation_of_struct_formal_parameter (cell fc, cell ac, approximation a, type st, set translation)
 
bool points_to_translation_mapping_is_typed_p (set translation)
 
void points_to_translation_of_formal_parameters (list fpcl, list al, pt_map pt_in, set translation)
 List al and fpcl are assumed consistent, and consistent with the formal parameter ranks. More...
 
void add_implicitly_killed_arcs_to_kill_set (set pt_kill, list wpl, set pt_caller, set pt_out_callee_filtered, set binding, entity f)
 Initial comments: add arcs of set "pt_caller" to set "pt_kill" if their origin cells are not in the list of written pointers "wpl" but is the origin of some exact arc in "pt_out_callee_filtered". More...
 
list translation_transitive_closure (cell c, set translation)
 
bool aliased_translation_p (list fpcl, set translation)
 See if two cells in "fpcl" point toward the same location via the transitive closure of "translation". More...
 
static set lower_points_to_approximations_according_to_write_effects (set pt_end, list wpl)
 It is partly a kill and partly a gen operation. More...
 
set user_call_to_points_to_interprocedural_binding_set (call c, pt_map pt_caller)
 Compute the binding relations in a complete interprocedural way: be as accurate as possible. More...
 
pt_map user_call_to_points_to_interprocedural (call c, pt_map pt_caller)
 Compute the points-to relations in a complete interprocedural way: be as accurate as possible. More...
 
pt_map user_call_to_points_to_intraprocedural (call c, pt_map pt_in, list el __attribute__((unused)))
 
set compute_points_to_kill_set (list written_must_translated, set pt_caller, set binding __attribute__((unused)))
 Translate the "out" set into the scope of the caller. More...
 
list points_to_cell_translation (cell sr1, set binding, entity f)
 Compute the list of cells that correspond to cell "sr1" according to the translation mapping "bm" when function "f" is called. More...
 
list generic_points_to_cells_translation (list cl, set binding, entity f, bool exact_p)
 Allocate a new list with the translations of the cells in cl, when their translation make sense. More...
 
list points_to_cells_translation (list cl, set binding, entity f)
 Allocate a new list with the translations of the cells in cl, when their translation make sense. More...
 
list points_to_cells_exact_translation (list cl, set binding, entity f)
 Allocate a new list with the translations of the cells in cl, when their translation make sense and is unique (one-to-one mapping). More...
 
set compute_points_to_gen_set (set pt_out, list Written, set binding, entity f)
 Translate the out set in the scope of the caller using the binding information, but eliminate irrelevant arcs using Written and the type of the source. More...
 
set points_to_binding_arguments (cell c1, cell c2, set in, set pt_binded)
 Recursively find all the arcs, "ai", starting from the argument "c1" using "in", find all the arcs, "aj", starting from the parameter "c2" using "pt_binded", map each node "ai" to its corresponding "aj" and store the "ai->aj" arc in a new set, "bm". More...
 
static list generic_written_pointers_set (list eff, bool exact_p)
 Filter out written effects on pointers. More...
 
list written_pointers_set (list eff)
 Filter out written effects on pointers. More...
 
list certainly_written_pointers_set (list eff)
 Filter out certainly written effects on pointers. More...
 
set compute_points_to_binded_set (entity called_func, list real_args, set pt_caller, bool *success_p)
 For each actual argument "r" and its corresponding formal one "f", create the assignment "f = r;" and then compute the points-to set "s" generated by the assignment. More...
 
set points_to_binding (list args, set in, set pt_binded)
 Apply points_to_binding_arguments() to each pair (, complete the process of binding each element of "in" to its corresponding memory address at the call site. More...
 
list generic_points_to_set_to_stub_cell_list (entity f, set s, list osl)
 Add cells referencing a points-to stub found in parameter "s" are copied and added to list "osl". More...
 
list points_to_set_to_stub_cell_list (set s, list osl)
 
list points_to_set_to_module_stub_cell_list (entity m, set s, list osl)
 
cell points_to_source_alias (points_to pt, set pt_binded)
 Let "pt_binded" be the results of assignments of actual arguments to formal arguments (see compute_points_to_binded_set()). More...
 

Function Documentation

◆ add_implicitly_killed_arcs_to_kill_set()

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

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

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

Equations retrieved from the C code

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

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

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

Examples:

Indirect free of a pointed cell

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

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

Other possibilities must be linked to tests and executions errors.

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

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

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

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

The result should be the same as above.

Arc out_pt has been implicitly obtained

Parameters
pt_killt_kill
wplpl
pt_callert_caller
pt_out_callee_filteredt_out_callee_filtered
bindinginding

Definition at line 1663 of file interprocedural.c.

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

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

Referenced by user_call_to_points_to_interprocedural().

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

◆ aliased_translation_p()

bool aliased_translation_p ( list  fpcl,
set  translation 
)

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

| must_conflict_p

Print the transitive closures

Clean up the hash-table...

Parameters
fpclpcl
translationranslation

Definition at line 1735 of file interprocedural.c.

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

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

Referenced by user_call_to_points_to_interprocedural().

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

◆ certainly_written_pointers_set()

list certainly_written_pointers_set ( list  eff)

Filter out certainly written effects on pointers.

Parameters
effff

Definition at line 2614 of file interprocedural.c.

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

References generic_written_pointers_set().

Referenced by user_call_to_points_to_interprocedural().

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

◆ compute_points_to_binded_set()

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

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

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

Be careful with vararags

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

C does not support array assignments...

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

A formal array can be called with a dereferencing expression

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

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

In the short term, build the assignment...

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

Parameters
called_funcalled_func
real_argseal_args
pt_callert_caller
success_puccess_p

Definition at line 2623 of file interprocedural.c.

2627 {
2629  points_to_rank);
2631  points_to_rank);
2632 
2633  *success_p = true; // default value
2634 
2635  /* Be careful with vararags
2636  *
2637  * This is not sufficient to handle varargs. Much more thinking
2638  * needed. And corect examples.
2639  */
2640  type ft = entity_basic_concrete_type(called_func); // function type
2641  functional fft = type_functional(ft);
2642  list ptl = functional_parameters(fft); // parameter type list
2643  int mnp = (int) gen_length(ptl); // maximum number of formal parameters
2644  if(!ENDP(ptl)) {
2645  // last parameter type
2646  type lpt = parameter_type(PARAMETER(CAR(gen_last(ptl))));
2647  if(type_varargs_p(lpt))
2648  mnp--;
2649  }
2650 
2651  cons *pc;
2652  int ipc;
2653  s = set_assign(s, pt_caller);
2654  for (ipc = 1, pc = real_args; pc != NIL; pc = CDR(pc), ipc++) {
2655  expression rhs = EXPRESSION(CAR(pc));
2656  int tr = ipc>mnp? mnp : ipc;
2657  entity fp = find_ith_parameter(called_func, tr);
2658  type fpt = entity_basic_concrete_type(fp);
2659  if(array_type_p(fpt)) {
2660  /* C does not support array assignments... */
2661  if(expression_reference_p(rhs)) {
2663  entity v = reference_variable(r);
2664  list nptl = NIL; // New points-to list
2665  SET_FOREACH(points_to, pt, pt_caller) {
2666  cell c = points_to_source(pt);
2667  reference cr = cell_any_reference(c);
2668  entity cv = reference_variable(cr);
2669  if(cv==v) {
2670  points_to npt = copy_points_to(pt);
2671  cell nc = points_to_source(npt);
2672  reference ncr = cell_any_reference(nc);
2673  reference_variable(ncr) = fp;
2674  nptl = CONS(POINTS_TO, npt, nptl);
2675  }
2676  }
2677  FOREACH(POINTS_TO, npt, nptl)
2678  add_arc_to_simple_pt_map(npt, s);
2679  gen_free_list(nptl);
2680  }
2681  else if(expression_call_p(rhs) && expression_string_constant_p(rhs)) {
2682  /* This may happen with a constant string as actual parameter
2683  and an array, bounded or not, as formal parameter. */
2684  ; // Nothing to do: the constant string does not point to anything
2685  }
2686  else if(expression_call_p(rhs)) {
2687  type et = array_type_to_element_type(fpt);
2688  if(struct_type_p(et)) {
2689  /* A formal array can be called with a dereferencing expression
2690  *
2691  * See Pointers/Mensi.sub/array_pointer_free01: array fp is
2692  * associated to &p[0] or to p->q or to c.a ...
2693  */
2694  call c = expression_call(rhs);
2695  entity f = call_function(c);
2696  pips_internal_error("Not implemented yet. Function \"%s\".\n",
2697  entity_user_name(f));
2698  }
2699  else if(pointer_type_p(et)) {
2700  call c = expression_call(rhs);
2701  entity f = call_function(c);
2702  pips_internal_error("Not implemented yet. Function \"%s\".\n",
2703  entity_user_name(f));
2704  }
2705  else {
2706  // No pointer related information
2707  ;
2708  }
2709  }
2710  else
2711  pips_internal_error("Not implemented yet.\n");
2712  }
2713  else {
2714  /* It would be nice to build an assignment of rhs to fp and to
2715  let it deal with the many possible kinds of assignments. But
2716  if it is a pure points-to function, the symbolic subscripts
2717  are going to be lost. This is fine for points-to translation,
2718  but not OK for effects translation. */
2719 
2720  if(pointer_type_p(fpt)) {
2721  points_to_graph s_g = make_points_to_graph(false, s);
2722  list sinks = expression_to_points_to_cells(rhs, s_g, true, false);
2723  int nsinks = (int) gen_length(sinks);
2724  FOREACH(CELL, sink, sinks) {
2726  cell d = copy_cell(sink);
2727  bool anywhere_p = anywhere_cell_p(d)
2729  bool heap_p = heap_cell_p(d);
2730  approximation a = (nsinks==1 && !anywhere_p && !heap_p) ? make_approximation_exact() :
2733  points_to pt = make_points_to(o, d, a, desc);
2735  }
2736  }
2737  else if(struct_type_p(fpt)) {
2738  /* In the short term, build the assignment... */
2739  expression lhs = entity_to_expression(fp);
2740  points_to_graph s_g = make_points_to_graph(false, s);
2741  points_to_graph a_g = assignment_to_points_to(lhs, rhs, s_g);
2742  if(points_to_graph_bottom(a_g)) {
2743  /* The assignment failed because the call site is not
2744  compatible with the caller. */
2745  *success_p = false;
2746  }
2747  else {
2748  s = set_assign(s, points_to_graph_set(a_g));
2749  }
2750  }
2751  else {
2752  ; // do nothing for other types
2753  }
2754  }
2755  }
2756 
2757  SET_FOREACH(points_to, pt, s) {
2759  entity e = reference_variable(r);
2760  if(stub_entity_of_module_p(e, called_func))
2761  s = set_del_element(s,s,(void*)pt);
2762  }
2763  pt_binded = set_union(pt_binded, s, pt_caller);
2764  return pt_binded;
2765 }
cell make_cell_reference(reference _field_)
Definition: effects.c:293
approximation make_approximation_exact(void)
Definition: effects.c:185
approximation make_approximation_may(void)
Definition: effects.c:179
descriptor make_descriptor_none(void)
Definition: effects.c:442
cell copy_cell(cell p)
CELL.
Definition: effects.c:246
points_to make_points_to(cell a1, cell a2, approximation a3, descriptor a4)
points_to copy_points_to(points_to p)
POINTS_TO.
points_to_graph make_points_to_graph(bool a1, set a2)
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
bool stub_entity_of_module_p(entity s, entity m)
bool cell_typed_anywhere_locations_p(cell c)
test if a cell is the bottom of the lattice
bool anywhere_cell_p(cell)
Is it an anywhere cell?
Definition: effects.c:367
bool heap_cell_p(cell)
Any heap cell, more or less abstract or typed.
Definition: effects.c:420
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
list gen_last(list l)
Return the last element of a list.
Definition: list.c:578
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#define pips_internal_error
Definition: misc-local.h:149
set set_generic_make(set_type, hash_equals_t, hash_rank_t)
what about this replacement? #define SET_MAP(the_item, the_code, the_set) \ { SET_FOREACH(void *,...
Definition: set.c:83
set set_del_element(set, const set, const void *)
Definition: set.c:265
set set_assign(set, const set)
Assign a set with the content of another set.
Definition: set.c:129
set set_union(set, const set, const set)
Definition: set.c:211
@ set_private
Definition: newgen_set.h:45
pt_map assignment_to_points_to(expression lhs, expression rhs, pt_map pt_in)
Definition: expression.c:1163
_uint points_to_rank(const void *, size_t)
create a key which is a concatenation of the source's name, the sink's name and the approximation of ...
set add_subscript_dependent_arc_to_simple_pt_map(points_to, set)
The source and destination references imply no dereferencing but the subscripts may be any kind of ex...
list expression_to_points_to_cells(expression, pt_map, bool, bool)
Return a possibly empty list of abstract locations whose addresses are possible value of expression "...
Definition: sinks.c:1650
int points_to_equal_p(const void *, const void *)
returns true if two points-to arcs "vpt1" and "vpt2" are equal.
Definition: points_to_set.c:98
#define points_to_sink(x)
#define points_to_graph_bottom(x)
#define POINTS_TO(x)
POINTS_TO.
#define points_to_graph_set(x)
bool expression_call_p(expression e)
Definition: expression.c:415
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
bool expression_string_constant_p(expression exp)
Definition: expression.c:2398
call expression_call(expression e)
Definition: expression.c:445
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_type_p(type)
Definition: type.c:2942
type entity_basic_concrete_type(entity)
retrieves or computes and then returns the basic concrete type of an entity
Definition: type.c:3677
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 array_type_to_element_type(type)
returns the type of the elements of an array type, as a newly allocated type.
Definition: type.c:5700
entity find_ith_parameter(entity, int)
Definition: util.c:93
#define parameter_type(x)
Definition: ri.h:1819
#define call_function(x)
Definition: ri.h:709
#define type_functional(x)
Definition: ri.h:2952
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define functional_parameters(x)
Definition: ri.h:1442
#define PARAMETER(x)
PARAMETER.
Definition: ri.h:1788
#define type_varargs_p(x)
Definition: ri.h:2953
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59

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

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

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

◆ compute_points_to_gen_set()

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

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

This is pt_gen_1 in Amira Mensi's dissertation.

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

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

Keep arcs whose source is:

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

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

Translate sr1

Translate sk1 if needed

The translation of pt's sink failed.

Note: the piece of code below is replicated

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

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

See for instance Pointers/formal_parameter01.c

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

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

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

Parameters
pt_outt_out
Writtenritten
bindinginding

Definition at line 2342 of file interprocedural.c.

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

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

Referenced by user_call_to_points_to_interprocedural().

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

◆ compute_points_to_kill_set()

set compute_points_to_kill_set ( list  written_must_translated,
set  pt_caller,
set binding   __attribute__(unused) 
)

Translate the "out" set into the scope of the caller.

Shouldn't it be the "written" list that needs to be translated?

Remove all points-to arc from pt_caller whose origin has been fully written

Definition at line 2146 of file interprocedural.c.

2149 {
2150  set kill = new_simple_pt_map();
2151  list written_cs = written_must_translated;
2152 #if 0
2153  list written_cs = NIL;
2154  set bm = binding;
2155 
2156  FOREACH(CELL, c, written) {
2157  cell new_sr = cell_undefined;
2158  reference r_1 = cell_any_reference(c);
2159  entity v_1 = reference_variable(r_1);
2160  if(!formal_parameter_p(v_1)) {
2161  list ind1 = reference_indices(r_1);
2162  SET_FOREACH(points_to, pp, bm) {
2163  cell sr2 = points_to_source(pp);
2164  cell sk2 = points_to_sink(pp);
2166  /* FI->AM: this test is loop invariant... and performed within the loop */
2167  if(!source_in_set_p(c, bm)) {
2168  reference r_12 = cell_any_reference(sr2);
2169  entity v_12 = reference_variable( r_12 );
2172  gen_full_copy_list(ind1));
2173  new_sr = make_cell_reference(r22);
2174  // FI->AM: I guess this statement was forgotten
2175  written_cs = CONS(CELL, new_sr, written_cs);
2176  break;
2177  }
2178  else if (heap_cell_p(c)) {
2179  written_cs = CONS(CELL, c, written_cs);
2180  }
2181  }
2182  else if(points_to_compare_cell(c,sr2)) {
2183  written_cs = CONS(CELL, points_to_sink(pp), written_cs);
2184  // break; // FI: why not look for other possible translations?
2185  }
2186  }
2187  }
2188  }
2189 #endif
2190 
2191  /* Remove all points-to arc from pt_caller whose origin has been
2192  fully written */
2193  FOREACH(CELL, c, written_cs) {
2194  SET_FOREACH(points_to, pt, pt_caller) {
2197  set_add_element(kill, kill, (void*)pt);
2198  }
2199  }
2200 
2201  return kill;
2202 }
reference copy_reference(reference p)
REFERENCE.
Definition: ri.c:2047
static bool written
Definition: alias_check.c:512
reference cell_to_reference(cell)
FI: probably to be moved elsewhere in ri-util.
Definition: effects.c:1326
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
#define same_string_p(s1, s2)
bool source_in_set_p(cell, set)
test if a cell appear as a source in a set of points-to
bool points_to_compare_cell(cell, cell)
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 reference_indices(x)
Definition: ri.h:2328

References atomic_points_to_cell_p(), CELL, cell_any_reference(), cell_to_reference(), cell_undefined, CONS, copy_reference(), entity_local_name(), FOREACH, formal_parameter_p(), gen_full_copy_list(), gen_nconc(), heap_cell_p(), make_cell_reference(), new_simple_pt_map, NIL, points_to_cell_equal_p(), points_to_compare_cell(), points_to_sink, points_to_source, reference_indices, reference_variable, same_string_p, set_add_element(), SET_FOREACH, source_in_set_p(), and written.

Referenced by user_call_to_points_to_fast_interprocedural(), and user_call_to_points_to_interprocedural().

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

◆ constant_string_type_to_string_type()

static type constant_string_type_to_string_type ( type  t)
static

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

Basically, type "t" is returned unchanged, unless "t" is a functional type "void->string".

The initial implementation of this function used the cell "ac" and the variable "a" whose type is sought and was safer:

reference ar = cell_any_reference(ac); entity a = reference_variable(ar); if(constant_string_entity_p(a)) nt = ...

Any function of type "void->string" is considered a "string" object. Let's hope it is ok in the points-to environment. Else, an additional parameter must be passed.

This function is located in the points-to library because it is where it is useful. It would be even more useful if it returned a "char *" or a "char[]", but this would imply a type allocation. As it is, no new type is allocated.

To be fully effective, the argument must be a basic concrete type.

Definition at line 543 of file interprocedural.c.

544 {
545  type nt = t; // default returned value: no change
546  if(type_functional_p(t)) {
548  type rt = functional_result(f);
550  if(ENDP(pl) && string_type_p(rt))
551  nt = rt;
552  }
553  return nt;
554 }
static hash_table pl
properties are stored in this hash table (string -> property) for fast accesses.
Definition: properties.c:783
bool string_type_p(type)
Definition: type.c:2854
#define type_functional_p(x)
Definition: ri.h:2950
#define functional_result(x)
Definition: ri.h:1444

References ENDP, f(), functional_parameters, functional_result, pl, string_type_p(), type_functional, and type_functional_p.

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

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

◆ filter_formal_context_according_to_actual_context()

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

Filter "pt_in" according to "pt_binded".

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

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

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

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

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

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

Do we have the same arc in pt_binded?

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

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

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

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

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

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

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

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

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

Parameters
fpclpcl
pt_int_in
pt_bindedt_binded
bindinginding

Definition at line 582 of file interprocedural.c.

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

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

+ Here is the call graph for this function:

◆ filter_formal_out_context_according_to_formal_in_context()

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

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

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

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

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

First, filter out according to in

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

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

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

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

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

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

Parameters
outut
inn
wplpl

Definition at line 1263 of file interprocedural.c.

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

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

Referenced by user_call_to_points_to_interprocedural().

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

◆ generic_points_to_cells_translation()

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

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

Effects on copied parameters are discarded.

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

Parameters
cll
bindinginding
exact_pxact_p

Definition at line 2286 of file interprocedural.c.

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

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

Referenced by points_to_cells_exact_translation(), and points_to_cells_translation().

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

◆ generic_points_to_set_to_stub_cell_list()

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

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

The stubs are returned as cells not as entities.

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

Parameters
oslsl

Definition at line 2829 of file interprocedural.c.

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

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

Referenced by points_to_set_to_module_stub_cell_list(), and points_to_set_to_stub_cell_list().

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

◆ generic_written_pointers_set()

static list generic_written_pointers_set ( list  eff,
bool  exact_p 
)
static

Filter out written effects on pointers.

Definition at line 2590 of file interprocedural.c.

2591 {
2592  list written_l = NIL;
2593  debug_on("EFFECTS_DEBUG_LEVEL");
2594  list wr_eff = effects_write_effects(eff);
2595  FOREACH(effect, ef, wr_eff) {
2597  if(!exact_p || approximation_must_p(a) || approximation_exact_p(a)) {
2598  if(effect_pointer_type_p(ef)){
2599  cell c = effect_cell(ef);
2600  written_l = gen_nconc(CONS(CELL, c, NIL), written_l);
2601  }
2602  }
2603  }
2604  debug_off();
2605  return written_l;
2606 }
bool effect_pointer_type_p(effect)
list effects_write_effects(list)
#define approximation_must_p(x)
Definition: effects.h:366
#define effect_approximation(x)
Definition: effects.h:644
#define effect_cell(x)
Definition: effects.h:640
#define debug_on(env)
Definition: misc-local.h:157
#define debug_off()
Definition: misc-local.h:160

References approximation_exact_p, approximation_must_p, CELL, CONS, debug_off, debug_on, effect_approximation, effect_cell, effect_pointer_type_p(), effects_write_effects(), FOREACH, gen_nconc(), and NIL.

Referenced by certainly_written_pointers_set(), and written_pointers_set().

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

◆ lower_points_to_approximations_according_to_write_effects()

static set lower_points_to_approximations_according_to_write_effects ( set  pt_end,
list  wpl 
)
static

It is partly a kill and partly a gen operation.

FI: the very same function must exist for pointer assignments I guess

Definition at line 1804 of file interprocedural.c.

1805 {
1806  list optl = NIL, nptl = NIL;
1807  SET_FOREACH(points_to, pt, pt_end) {
1808  cell source = points_to_source(pt);
1809  // FI->FI: en fait, il faudrait prendre en compte le treillis et
1810  // tester les conflits,
1811  // written_effects_conflict_with_points_to_cell()
1812  if(points_to_cell_in_list_p(source, wpl)) {
1813  optl = CONS(POINTS_TO, pt, optl);
1814  cell sink = points_to_sink(pt);
1815  points_to npt = make_points_to(copy_cell(source),
1816  copy_cell(sink),
1819  nptl = CONS(POINTS_TO, npt, nptl);
1820  }
1821  }
1822  FOREACH(POINTS_TO, opt, optl)
1823  remove_arc_from_simple_pt_map(opt, pt_end);
1824  FOREACH(POINTS_TO, npt, nptl)
1825  add_arc_to_simple_pt_map(npt, pt_end);
1826  return pt_end;
1827 }

References add_arc_to_simple_pt_map, CONS, copy_cell(), FOREACH, make_approximation_may(), make_descriptor_none(), make_points_to(), NIL, POINTS_TO, points_to_cell_in_list_p(), points_to_sink, points_to_source, remove_arc_from_simple_pt_map, and SET_FOREACH.

Referenced by user_call_to_points_to_interprocedural().

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

◆ merge_actual_and_formal_sinks()

static bool merge_actual_and_formal_sinks ( cell  fc,
list pfcl,
cell  ac,
list pacl,
set  pt_in,
set  pt_binded,
set  filtered 
)
static

Handle constant cells such as NULL and UNDEFINED (nowhere) in "fcl" and "acl".

Update "fcl" is needed, as well as "pt_binded" and "filtered", a subset of "pt_in".

A points-to arc should be removed from pt_binded and/or added to a pt_kill set...

Definition at line 809 of file interprocedural.c.

810 {
811  bool ok_p = true;
812 
813  list acl = *pacl;
814  int nacl = 0;
815  bool a_null_p = false;
816  bool a_nowhere_p = false;
817 
818  list fcl = *pfcl;
819  bool f_null_p = false;
820  int nfcl = 0;
821 
822  FOREACH(CELL, ac, acl) {
823  nacl++;
824  if(null_cell_p(fc))
825  a_null_p = true;
826  else if(nowhere_cell_p(fc))
827  a_nowhere_p = true;
828  }
829 
830  cell null_c = cell_undefined;
831  FOREACH(CELL, fc, fcl) {
832  nfcl++;
833  if(null_cell_p(fc)) {
834  f_null_p = true;
835  if(!a_null_p)
836  null_c = fc;
837  }
838  }
839 
840  if(nfcl>0 && nacl==1 && a_nowhere_p) {
841  // The callee dereferences an undefined pointer
842  ok_p = false;
843  }
844  else if(nfcl>0 && a_nowhere_p) {
845  /* A points-to arc should be removed from pt_binded and/or added
846  * to a pt_kill set...
847  */
848  SET_FOREACH(points_to, pt, pt_binded) {
849  cell s = points_to_source(pt);
850  if(s==ac) {
851  pt_binded = remove_arc_from_simple_pt_map(pt, pt_binded);
852  }
853  }
854  }
855 
856  // A points-to arc should not be copied from "pt_in" into "filtered"
857  bool no_null_p = f_null_p && !a_null_p;
858 
859  SET_FOREACH(points_to, pt, pt_in) {
860  cell s = points_to_source(pt);
861  if(s==fc) {
862  cell d = points_to_sink(pt);
863  if(!no_null_p || !null_cell_p(d)) {
864  points_to npt = copy_points_to(pt);
865  add_arc_to_simple_pt_map(npt, filtered);
866  }
867  }
868  }
869 
870  if(no_null_p) {
871  // Remove the NULL cell from "fcl" list
872  // fcl = fcl - null_c
873  gen_remove(pfcl, (void *) null_c);
874  }
875 
876  return ok_p;
877 }
void gen_remove(list *cpp, const void *o)
remove all occurences of item o from list *cpp, which is thus modified.
Definition: list.c:685

References add_arc_to_simple_pt_map, CELL, cell_undefined, copy_points_to(), FOREACH, gen_remove(), nowhere_cell_p(), null_cell_p(), points_to_sink, points_to_source, remove_arc_from_simple_pt_map, and SET_FOREACH.

Referenced by new_recursive_filter_formal_context_according_to_actual_context_for_pointer_pair().

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

◆ new_filter_formal_context_according_to_actual_context()

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

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

Do we have the same arc in pt_binded?

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

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

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

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

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

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

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

Parameters
fpclpcl
pt_int_in
pt_bindedt_binded
bindinginding

Definition at line 1039 of file interprocedural.c.

1043 {
1044  bool ok_p = true;
1045  set filtered = new_simple_pt_map();
1046 
1047  /* Copy arcs "pt" from "pt_in" into the "filtered" set if they are
1048  compatible with "pt_binded". The set "filtered" is a subset of
1049  "pt_in". */
1050  SET_FOREACH(points_to, pt, pt_in) {
1051  cell source = points_to_source(pt);
1052  if(related_points_to_cell_in_list_p(source, fpcl)) {
1053  cell sink = points_to_sink(pt);
1054  if(null_cell_p(sink)) {
1055  /* Do we have the same arc in pt_binded? */
1056  if(arc_in_points_to_set_p(pt, pt_binded)) {
1057  points_to npt = copy_points_to(pt);
1058  add_arc_to_simple_pt_map(npt, filtered);
1059  }
1060  else {
1061  ; // do not copy this arc in filtered set
1062  }
1063  }
1064  else {
1065  if(cell_points_to_non_null_sink_in_set_p(source, pt_binded)) {
1066  points_to npt = copy_points_to(pt);
1067  add_arc_to_simple_pt_map(npt, filtered);
1068  }
1069  else {
1070  ; // do not copy this arc in filtered set
1071  }
1072  }
1073  }
1074  else {
1075  /* We have to deal recursively with stubs of the formal context
1076  and first with the global variables... although they, or their
1077  stubs, do not require any translation? Why is the points-to
1078  information about q lost in the translation of the call site
1079  to call03 in main (PointersWithEffects/call03.c) */
1080  reference r = cell_any_reference(source);
1081  entity v = reference_variable(r);
1082  if(!arc_in_points_to_set_p(pt, pt_binded)) {
1083  // FI: necessary for Pointers/global10
1085  //gvcl = CONS(CELL, source, gvcl);
1086  points_to npt = copy_points_to(pt);
1087  add_arc_to_simple_pt_map(npt, filtered);
1088  /* FI: I do not understand why I have to do this for
1089  EffectsWithPointsTo/pointer_modif04.c. Because the arc "pt"
1090  in "pt_in" is more precise than the information available
1091  in "pt_caller". For instance, "pt_in" may contain
1092  "stderr->_stderr_0[0], Exact", while "pt_caller" may
1093  contain "stderr->_stderr_0[0], May", "stderr->NULL,
1094  May". Basically, we have not thought about the kill set
1095  generated for the global variables. */
1097  /* Useless when called from effects... In fact, it should
1098  never be called from effects... */
1099  //add_arc_to_points_to_context(npt);
1101  }
1102  else {
1103  // pips_internal_error("This function should not reach this point"
1104  // " when called from effects, simple or generic.");
1105  // update_points_to_context_with_arc(npt);
1106  ; // Do nothing
1107  }
1108  }
1109  else {
1110  /* FI: we do not know what we really do here... An arc is not
1111  taken into account, but it might be taken into account
1112  recursively below. */
1113  ;
1114  }
1115  }
1116  }
1117  }
1118 
1119  /* Compute the binding relation for sinks of the formal arguments
1120  and global variables */
1121  points_to_graph filtered_g = make_points_to_graph(false, filtered);
1122  points_to_graph pt_binded_g = make_points_to_graph(false, pt_binded);
1123  FOREACH(CELL, c, fpcl) {
1124  list fl = points_to_source_to_any_sinks(c, filtered_g, false); // formal list
1125  list al = points_to_source_to_any_sinks(c, pt_binded_g, false); // actual list
1126  int nfl = (int) gen_length(fl);
1127  int nal = (int) gen_length(al);
1129 
1130  // FI: que fait-on avec nfl==0, comme dans
1131  // Pointers/StrictTyping.sub/struct08.c ou nfl vaut 0 parce que le
1132  // parametre effectif est undefined?
1133 
1134  if(nfl==1 && nal==1)
1135  approx = make_approximation_exact();
1136  else
1137  approx = make_approximation_may();
1138  FOREACH(CELL, fc, fl) {
1139  if(!null_cell_p(fc)) {
1140  FOREACH(CELL, ac, al) {
1141  if(!null_cell_p(ac) && !nowhere_cell_p(ac)) {
1145  /* We have to handle constant strings such as "Hello!"
1146  and not to forget functional parameters. */
1147  if(type_functional_p(ac_t)) {
1148  reference ar = cell_any_reference(ac);
1149  entity a = reference_variable(ar);
1150  if(constant_string_entity_p(a)) {
1151  ac_t = functional_result(type_functional(iac_t));
1152  }
1153  }
1154  // FI: which type equality should be chosen ?
1155  // if(!type_structurally_equal_p(fc_t, ac_t)
1156  if(!array_pointer_string_type_equal_p(fc_t, ac_t)
1157  && !overloaded_type_p(ac_t)) {
1158  if(array_type_p(ac_t)) {
1161  if(!type_structurally_equal_p(fc_t, ac_nt) && !overloaded_type_p(ac_nt)) {
1162  // Pointers/pointer14.c
1163  // FI: I am not sure it is the best translation
1164  // It might be better to remove some zero subscripts from fc
1167  if(!type_structurally_equal_p(fc_t, ac_nnt) && !overloaded_type_p(ac_nnt))
1168  pips_internal_error("translation failure for an array.\n");
1169  }
1170  }
1171  else {
1172  reference fr = cell_any_reference(fc);
1174  ;
1175  else {
1177  reference ar = cell_any_reference(ac);
1178  semantics_user_warning("Type \"%s\" for formal reference \"%s\" is incompatible with type \"%s\" for actual reference \"%s\".\n",
1180  reference_to_string(fr),
1182  reference_to_string(ar));
1183  if(get_bool_property("POINTS_TO_STRICT_POINTER_TYPES")) {
1185  ("Translation failure for actual parameter \"%s\" at line %d.\n"
1186  "Maybe property POINTS_TO_STRICT_POINTER_TYPES should be reset.\n",
1187  reference_to_string(ar),
1189  // pips_internal_error("translation failure.\n");
1190  }
1191  else {
1193  ("Translation failure for actual parameter \"%s\" at line %d.\n",
1194  reference_to_string(ar),
1196  }
1197  }
1198  }
1199  }
1201  copy_cell(ac),
1202  copy_approximation(approx),
1206  (fc, ac, approx, pt_in, pt_binded, binding, filtered);
1207  }
1208  else if(null_cell_p(ac)) {
1209  ; // What should be done?
1210  }
1211  else {
1212  // nowhere_cell_p(ac)
1213  ; // What should be done?
1214  }
1215  }
1216  }
1217  }
1218 
1219  free_approximation(approx);
1220  }
1221 
1222  ifdebug(8) {
1223  pips_debug(8, "First filtered IN set for callee at call site:\n");
1224  print_points_to_set("", filtered);
1225  pips_debug(8, "First translation mapping for call site:\n");
1226  print_points_to_set("", binding);
1227  }
1228 
1229  pips_assert("The points-to translation mapping is well typed",
1231 
1232  if(ok_p) {
1233  /* Some arcs have been removed, so other arcs may be promoted from
1234  "may" to "exact". */
1236  }
1237  else {
1238  set_free(filtered);
1239  filtered = set_undefined;
1240  }
1241 
1242  ifdebug(8) {
1243  pips_debug(8, "Final filtered IN set for callee at call site:\n");
1244  print_points_to_set("", filtered);
1245  pips_debug(8, "Final mapping for call site:\n");
1246  print_points_to_set("", binding);
1247  }
1248 
1249  return filtered;
1250 }
static bool new_recursive_filter_formal_context_according_to_actual_context(cell fc, cell ac, approximation ap, set pt_in, set pt_binded, set binding, set filtered)
The code is derived from generic_points_to_cell_to_useful_pointer_cell() with no filtering and a dire...

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

Referenced by user_call_to_points_to_interprocedural(), and user_call_to_points_to_interprocedural_binding_set().

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

◆ new_recursive_filter_formal_context_according_to_actual_context()

static bool new_recursive_filter_formal_context_according_to_actual_context ( cell  fc,
cell  ac,
approximation  ap,
set  pt_in,
set  pt_binded,
set  binding,
set  filtered 
)
static

The code is derived from generic_points_to_cell_to_useful_pointer_cell() with no filtering and a direct processing of the pairs of pointers obtained.

cells fc and ac are assumed type compatible.

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

transformer

Definition at line 971 of file interprocedural.c.

973 {
974  bool ok_p = true;
977  if(null_cell_p(ac)) {
978  pips_internal_error("Cannot be called with a null cell.\n");
979  }
980  // array_pointer_string_type_equal_p() ?
981  else if(!type_equal_p(fc_t, ac_t)
983  if(overloaded_type_p(ac_t)) {
984  // Something has failed and probably led to an anywhere astract location
985  ;
986  }
987  else {
988  pips_internal_error("Incompatible types for binded cells.\n");
989  }
990  else if(pointer_type_p(fc_t)) {
992  (fc, ac, ap, pt_in, pt_binded, binding, filtered);
993  }
994  else if(struct_type_p(fc_t)) {
995  /* Look for pointer and struct and array of pointers or struct fields */
996  list fl = struct_type_to_fields(fc_t);
997  FOREACH(ENTITY, f, fl) {
999  if(pointer_type_p(f_t) || struct_type_p(f_t)
1000  || array_of_pointers_type_p(f_t)
1001  || array_of_struct_type_p(f_t)) {
1002  cell nfc = copy_cell(fc);
1004  cell nac = copy_cell(ac);
1006  if(pointer_type_p(f_t)) {
1009  points_to npt = make_points_to(nfc, nac, nap, d);
1010  add_arc_to_simple_pt_map(npt, binding);
1012  (nfc, nac, nap, pt_in, pt_binded, binding, filtered);
1013  }
1014  else {
1016  (nfc, nac, ap, pt_in, pt_binded, binding, filtered);
1017  }
1018  }
1019  }
1020  }
1021  else if(array_of_pointers_type_p(fc_t) || array_of_struct_type_p(fc_t)) {
1022  /* transformer */
1023  cell nfc = copy_cell(fc);
1025  cell nac = copy_cell(ac);
1027  if(array_of_pointers_type_p(fc_t)) {
1029  (nfc, nac, ap, pt_in, pt_binded, binding, filtered);
1030  }
1031  else {
1033  (nfc, nac, ap, pt_in, pt_binded, binding, filtered);
1034  }
1035  }
1036  return ok_p;
1037 }
cell points_to_cell_add_field_dimension(cell, entity)
Functions about points-to cells - There is no cell.c file.
Definition: effects.c:1444
void points_to_cell_add_unbounded_subscripts(cell)
Definition: effects.c:1632
static bool new_recursive_filter_formal_context_according_to_actual_context_for_pointer_pair(cell fc, cell ac, approximation ap, set pt_in, set pt_binded, set binding, set filtered)
fc and ac are two pointer cells with same or compatible pointer type
bool char_star_constant_function_type_p(type)
Beware of typedefs.
Definition: type.c:5787
bool array_of_pointers_type_p(type)
Definition: type.c:3025
bool type_equal_p(type, type)
Definition: type.c:547
list struct_type_to_fields(type)
Definition: type.c:5798
bool array_of_struct_type_p(type)
Definition: type.c:3133
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755

References add_arc_to_simple_pt_map, array_of_pointers_type_p(), array_of_struct_type_p(), char_star_constant_function_type_p(), copy_approximation(), copy_cell(), ENTITY, entity_basic_concrete_type(), f(), FOREACH, make_descriptor_none(), make_points_to(), new_recursive_filter_formal_context_according_to_actual_context_for_pointer_pair(), null_cell_p(), overloaded_type_p(), pips_internal_error, pointer_type_p(), points_to_cell_add_field_dimension(), points_to_cell_add_unbounded_subscripts(), points_to_cell_to_concrete_type(), struct_type_p(), struct_type_to_fields(), and type_equal_p().

Referenced by new_filter_formal_context_according_to_actual_context(), and new_recursive_filter_formal_context_according_to_actual_context_for_pointer_pair().

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

◆ new_recursive_filter_formal_context_according_to_actual_context_for_pointer_pair()

static bool new_recursive_filter_formal_context_according_to_actual_context_for_pointer_pair ( cell  fc,
cell  ac,
approximation  ap,
set  pt_in,
set  pt_binded,
set  binding,
set  filtered 
)
static

fc and ac are two pointer cells with same or compatible pointer type

Update binding and filtered according to their sinks.

For instance, if "ac" only points to the undefined cells, the call site is not consistent because "fc" is assumed by the caller to point to a defined cell. "ok_p" is set to false.

if "fc" points to NULL in pt_in, but "ac" does not point to NULL, the corresponding arc is not copied in "filtered".

if "fc" points to "nfc" in "pt_in" and "ac" points to "nac" in "pt_binded", then arc "fc->nfc" is copied in "pt_binded" and arc "nfc->nac" is added in "binding".

No optimization in number of scans for the different sets

pointer fc is not dereferenced, no need to go down

FI: the algorithm seems wrong because a dynamic allocation can occur in the callee and be unknown from pt_binded. See Ancourt3009.sub/call09 and call10. I do not understand why call10 provides a result... and call09 fails utterly.

The caller may not have had yet a need for the corresponding stub

Definition at line 896 of file interprocedural.c.

898 {
899  bool ok_p = true;
900  points_to_graph pt_in_g = make_points_to_graph(false, pt_in);
901  list fcl = points_to_source_to_some_sinks(fc, pt_in_g, false);
902  if(ENDP(fcl)) {
903  /* pointer fc is not dereferenced, no need to go down */
904  ;
905  }
906  else {
907  /* FI: the algorithm seems wrong because a dynamic allocation can
908  occur in the callee and be unknown from pt_binded. See
909  Ancourt3009.sub/call09 and call10. I do not understand why
910  call10 provides a result... and call09 fails utterly. */
911  points_to_graph pt_binded_g = make_points_to_graph(false, pt_binded);
912  list acl = points_to_source_to_some_sinks(ac, pt_binded_g, false);
913  if(ENDP(acl)) {
914  /* The caller may not have had yet a need for the corresponding stub */
916  cell d = points_to_sink(npt);
917  acl = CONS(CELL, d, NIL);
918  // add_arc_to_simple_pt_map(npt, pt_binded); // FI: not sure it is useful
919 
920  // Add arc to the points-to in set of the caller and of the
921  // current statement
923  }
924  ok_p = merge_actual_and_formal_sinks(fc, &fcl, ac, &acl, pt_in, pt_binded, filtered);
925  if(ok_p) {
926  // Update binding
927  int nfcl = gen_length(fcl);
928  int nacl = gen_length(acl);
929  FOREACH(CELL, dfc, fcl) { // destination cells
930  FOREACH(CELL, dac, acl) { // destination cells
931  if(nowhere_cell_p(dac)) {
932  if(nacl==1) {
933  semantics_user_warning("An undefined pointer \"%s\" (formal: \"%s\") has been dereferenced to reach \"%s\".\n", points_to_cell_to_string(ac), points_to_cell_to_string(fc), points_to_cell_to_string(dfc));
934  ok_p = false;
935  // FI: the choice is to let the analysis proceeds
936  // although a user error has been detected; it may occur
937  // in dead code... The opposite choice has been made in
938  // effects analyses
939  }
940  else {
941  semantics_user_warning("An undefined pointer \"%s\" (formal: \"%s\") may be dereferenced to reach \"%s\".\n", points_to_cell_to_string(ac), points_to_cell_to_string(fc), points_to_cell_to_string(dfc));
942  }
943  }
944  else {
945  cell nfc = copy_cell(dfc);
946  cell nac = copy_cell(dac);
947  approximation nap = (nfcl==1 && nacl==1 && approximation_exact_p(ap)) ?
951  points_to npt = make_points_to(nfc, nac, nap, d);
952  add_arc_to_simple_pt_map(npt, binding);
953  ok_p = new_recursive_filter_formal_context_according_to_actual_context(nfc, nac, nap, pt_in, pt_binded, binding, filtered);
954  }
955  }
956  }
957  }
958  // Free pt_binded_g but not pt_binded
959  }
960  // Free pt_in_g but not pt_in
961 
962  return ok_p;
963 }
static bool merge_actual_and_formal_sinks(cell fc, list *pfcl, cell ac, list *pacl, set pt_in, set pt_binded, set filtered)
Handle constant cells such as NULL and UNDEFINED (nowhere) in "fcl" and "acl".
points_to create_stub_points_to(cell, type, bool)
list points_to_source_to_some_sinks(cell, pt_map, bool)
May not retrieve all sinks of the source.
string points_to_cell_to_string(cell)
#define type_undefined
Definition: ri.h:2883

References add_arc_to_simple_pt_map, approximation_exact_p, CELL, CONS, copy_cell(), create_stub_points_to(), ENDP, FOREACH, gen_length(), make_approximation_exact(), make_approximation_may(), make_descriptor_none(), make_points_to(), make_points_to_graph(), merge_actual_and_formal_sinks(), new_recursive_filter_formal_context_according_to_actual_context(), NIL, nowhere_cell_p(), points_to_cell_to_string(), points_to_sink, points_to_source_to_some_sinks(), semantics_user_warning, type_undefined, and update_points_to_context_with_arc().

Referenced by new_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_binding()

set points_to_binding ( list  args,
set  in,
set  pt_binded 
)

Apply points_to_binding_arguments() to each pair (, complete the process of binding each element of "in" to its corresponding memory address at the call site.

Necessary to translate the fields of structures.

"args": list of formal parameters of some callee

"in": points-to in of the callee

"pt_binded": points-to from formal to actual parameters for a specific call site

A new set is allocated.

Process each formal parameter and look for its actual values in "pt_binded"

Parameters
argsrgs
inn
pt_bindedt_binded

Definition at line 2780 of file interprocedural.c.

2781 {
2782 
2783  set bm = new_simple_pt_map();
2784  //set bm1 = new_simple_pt_map();
2785 
2786  /* Process each formal parameter and look for its actual values in
2787  "pt_binded" */
2788  SET_FOREACH(points_to, pt, pt_binded) {
2789  FOREACH(CELL, c1, args) {
2790  cell source = points_to_source(pt);
2791  if(cell_equal_p(c1, source)) {
2792  cell c2 = points_to_source_alias(pt, pt_binded);
2793  // FI: We end up with c1=c2=one formal parameter...
2794  // No need to add "p->p" in "bm"...
2795  //approximation a = make_approximation_exact();
2796  //points_to new_pt = make_points_to(c1, c2, a, make_descriptor_none());
2797  //add_arc_to_simple_pt_map(new_pt, bm);
2798  set c1c2 = points_to_binding_arguments(c1, c2, in, pt_binded);
2799  bm = set_union(bm, bm, c1c2);
2800  set_clear(c1c2), set_free(c1c2);
2801  }
2802  else if(cell_entity_equal_p(c1, source)) {
2803  pips_assert("c1 is a reference with no indices",
2805  cell c2 = copy_cell(source);
2806  // FI: We end up with c1=c2=one formal parameter...
2807  // No need to add "p->p" in "bm"...
2808  //approximation a = make_approximation_exact();
2809  //points_to new_pt = make_points_to(c1, c2, a, make_descriptor_none());
2810  //add_arc_to_simple_pt_map(new_pt, bm);
2811  set c1c2 = points_to_binding_arguments(source, c2, in, pt_binded);
2812  bm = set_union(bm, bm, c1c2);
2813  set_clear(c1c2), set_free(c1c2);
2814  }
2815  }
2816  }
2817 
2818  return bm;
2819 }
bool cell_equal_p(cell, cell)
CELLS.
Definition: effects.c:1226
bool cell_entity_equal_p(cell, cell)
Definition: effects.c:1234
set set_clear(set)
Assign the empty set to s s := {}.
Definition: set.c:326
set points_to_binding_arguments(cell c1, cell c2, set in, set pt_binded)
Recursively find all the arcs, "ai", starting from the argument "c1" using "in", find all the arcs,...
cell points_to_source_alias(points_to pt, set pt_binded)
Let "pt_binded" be the results of assignments of actual arguments to formal arguments (see compute_po...

References CELL, cell_any_reference(), cell_entity_equal_p(), cell_equal_p(), copy_cell(), ENDP, FOREACH, new_simple_pt_map, pips_assert, points_to_binding_arguments(), points_to_source, points_to_source_alias(), reference_indices, set_clear(), SET_FOREACH, set_free(), and set_union().

Referenced by user_call_to_points_to_fast_interprocedural().

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

◆ points_to_binding_arguments()

set points_to_binding_arguments ( cell  c1,
cell  c2,
set  in,
set  pt_binded 
)

Recursively find all the arcs, "ai", starting from the argument "c1" using "in", find all the arcs, "aj", starting from the parameter "c2" using "pt_binded", map each node "ai" to its corresponding "aj" and store the "ai->aj" arc in a new set, "bm".

"pt_binded" contains the correspondance between formal and actual parameters, e.g. "fp->ap", with some information about the possible approximations because one formal parameter can points toward several actual memory locations of the caller.

"in" contains the formal context of the callee, as it stands at its entry point (DBR_POINTS_TO_IN).

"bm" is the binding relationship between references of the formal context of the callees towards addresses of the caller. For instance, when function "void foo(int ** fp)" is called as "ap=&q; foo(ap);", bm = {(_ap_1, q)}.

See Amira Mensi's PhD dissertation, chapter about interprocedural analysis

Recursive call down the different points_to paths

Here we have, for instance, "q[*]" in "c1" for "q[4]" in "in".

FI: I do not see how to handle incompatibility between assumptions...

(!source_in_set_p(c1, in) && !source_subset_in_set_p(c1, in))

c1 is not a pointer: it is simply mapped to c2

Parameters
c11
c22
inn
pt_bindedt_binded

Definition at line 2513 of file interprocedural.c.

2514 {
2515  set bm = new_simple_pt_map();
2516 
2517  if(source_in_set_p(c1, in) || source_subset_in_set_p(c1, in)) {
2518  // FI: impedance problem... and memory leak
2519  points_to_graph in_g = make_points_to_graph(false, in);
2520  points_to_graph pt_binded_g = make_points_to_graph(false, pt_binded);
2521  // FI: allocate a new copy for sink1 and sink2
2522  //list c1_children = cell_to_pointer_cells(c1);
2523  //list c2_children = cell_to_pointer_cells(c2);
2524  list c1_children = recursive_cell_to_pointer_cells(c1);
2525  list c2_children = recursive_cell_to_pointer_cells(c2);
2526  FOREACH(CELL,c1c, c1_children) {
2527  FOREACH(CELL,c2c, c2_children) {
2528  list sinks1 = points_to_source_to_some_sinks(c1c, in_g, true);
2529  list sinks2 = points_to_source_to_some_sinks(c2c, pt_binded_g, true);
2530  pips_assert("sinks1 is not empty", !ENDP(sinks1));
2531  pips_assert("sinks2 is not empty", !ENDP(sinks2));
2532  // FI Allocate more copies
2533  list tmp1 = gen_full_copy_list(sinks1);
2534  list tmp2 = gen_full_copy_list(sinks2);
2535 
2536  FOREACH(CELL, s1, sinks1) { // Formal cell: fp->_fp_1 or fp->NULL
2537  // FI: no need to translate constants NULL and UNDEFINED
2538  if(!null_cell_p(s1) && !nowhere_cell_p(s1)) {
2539  FOREACH(CELL, s2, sinks2) { // Actual cell: ap-> i... NOWHERE... NULL...
2540  // FI: _fp_1 may or not exist since it is neither null nor undefined
2541  if(!null_cell_p(s2) && !nowhere_cell_p(s2)) {
2543  if((size_t)gen_length(sinks2)>1) // FI->FI: atomicity should be tested too
2544  a = make_approximation_may();
2545  else
2547  cell sink1 = copy_cell(s1);
2548  cell sink2 = copy_cell(s2);
2549  // Build arc _fp_1->... NOWHERE ... NULL ...
2550  points_to pt = make_points_to(sink1, sink2, a, make_descriptor_none());
2551  add_arc_to_simple_pt_map(pt, bm);
2552  }
2553  //gen_remove(&sinks2, (void*)s2);
2554  }
2555  }
2556  //gen_remove(&sinks1, (void*)s1);
2557  }
2558 
2559  /* Recursive call down the different points_to paths*/
2560  FOREACH(CELL, sr1, tmp1) {
2561  if(!null_cell_p(sr1) && !nowhere_cell_p(sr1)) {
2562  FOREACH(CELL, sr2, tmp2) {
2563  if(!null_cell_p(sr2) && !nowhere_cell_p(sr2)) {
2564  set sr1sr2 = points_to_binding_arguments(sr1, sr2, in, pt_binded);
2565  bm = set_union(bm, sr1sr2, bm);
2566  set_clear(sr1sr2), set_free(sr1sr2);
2567  }
2568  }
2569  }
2570  }
2571  }
2572  }
2573  }
2574  else if(source_subset_in_set_p(c1, in)) { // Not reachable
2575  /* Here we have, for instance, "q[*]" in "c1" for "q[4]" in "in". */
2576  /* FI: I do not see how to handle incompatibility between assumptions... */
2577  pips_internal_error("Do not know how to handle subsets...\n");
2578  }
2579  else /* (!source_in_set_p(c1, in) && !source_subset_in_set_p(c1, in)) */ {
2580  // FI: this has already been performed
2581  /* c1 is not a pointer: it is simply mapped to c2 */
2582  // points_to pt = make_points_to(c1, c2, make_approximation_exact(), make_descriptor_none());
2583  // add_arc_to_simple_pt_map(pt, bm);
2584  ;
2585  }
2586  return bm;
2587 }
list recursive_cell_to_pointer_cells(cell)
Definition: effects.c:1680
bool source_subset_in_set_p(cell, set)
test if a cell "source" appears as a source in a set of points-to
s1
Definition: set.c:247

References add_arc_to_simple_pt_map, approximation_undefined, CELL, copy_cell(), ENDP, FOREACH, gen_full_copy_list(), gen_length(), make_approximation_exact(), make_approximation_may(), make_descriptor_none(), make_points_to(), make_points_to_graph(), new_simple_pt_map, nowhere_cell_p(), null_cell_p(), pips_assert, pips_internal_error, points_to_source_to_some_sinks(), recursive_cell_to_pointer_cells(), s1, set_clear(), set_free(), set_union(), source_in_set_p(), and source_subset_in_set_p().

Referenced by points_to_binding().

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

◆ points_to_cell_translation()

list points_to_cell_translation ( cell  sr1,
set  binding,
entity  f 
)

Compute the list of cells that correspond to cell "sr1" according to the translation mapping "bm" when function "f" is called.

The check with rv may be useless, for instance when a sink cell is checked, as it is impossible (in C at least) to points toward the return value.

Translate sr1 if needed

No translation is needed.

We assume here that the subscript list of sr1, the reference to translate, is longer than the subscript list of sr2, the source of its translation.

Parameters
sr1r1
bindinginding

Definition at line 2211 of file interprocedural.c.

2212 {
2213  list new_sr_l = NIL;
2215 
2216  /* Translate sr1 if needed */
2217  reference r_1 = cell_any_reference(sr1);
2218  entity v_1 = reference_variable(r_1);
2221  || heap_cell_p(sr1)
2222  || v_1 == rv
2223  || entity_to_module_entity(v_1)!=f) {
2224  /* No translation is needed. */
2225  cell new_sr = copy_cell(sr1);
2226  new_sr_l = CONS(CELL, new_sr, new_sr_l);
2227  }
2228  else {
2229  list ind1 = reference_indices(r_1);
2230  SET_FOREACH(points_to, pp, binding) {
2231  cell sr2 = points_to_source(pp);
2232  cell sk2 = points_to_sink(pp);
2234  // FI: this test should be factored out
2235  if(!source_in_set_p(sr1, binding)) {
2236  // sr1 cannot be translated directly, let's try to remove
2237  // (some) subscripts
2238  reference r_12 = cell_any_reference(sr2);
2239  entity v_12 = reference_variable( r_12 );
2241  /* We assume here that the subscript list of sr1, the
2242  reference to translate, is longer than the subscript
2243  list of sr2, the source of its translation. */
2244  list ind2 = reference_indices(r_12);
2245  pips_assert("The effective subscript list is longer than "
2246  "the translated subscript list",
2247  gen_length(ind1)>=gen_length(ind2));
2248  // Either we check the subscript compatibility or we trust it
2249  // Let's trust it: no!
2250  list cind1 = ind1, cind2 = ind2;
2251  bool compatible_p = true;
2252  while(!ENDP(cind2)) {
2253  expression s1 = EXPRESSION(CAR(cind1));
2254  expression s2 = EXPRESSION(CAR(cind2));
2256  compatible_p = false;
2257  break;
2258  }
2259  POP(cind1), POP(cind2);
2260  }
2261  if(compatible_p) {
2262  // Propagate the remaining subscripts on the translation target
2263  reference_indices(r22) = gen_nconc(reference_indices(r22),cind1);
2264  cell new_sr = make_cell_reference(r22);
2265  new_sr_l = CONS(CELL, new_sr, new_sr_l);
2266  }
2267  }
2268  }
2269  else if(points_to_compare_cell(sr1,sr2)) {
2270  // sr1 can be translated directly as sk2
2271  cell new_sr = copy_cell(points_to_sink(pp));
2272  new_sr_l = CONS(CELL, new_sr, new_sr_l);
2273  }
2274  }
2275  }
2276  return new_sr_l;
2277 }
bool entity_typed_anywhere_locations_p(entity e)
Test if an entity is the bottom of the lattice.
bool entity_anywhere_locations_p(entity e)
test if an entity is the bottom of the lattice
bool compatible_points_to_subscripts_p(expression, expression)
Two subscript are compatible if they are equal or if one of them is unbounded.
Definition: points_to.c:1041

References any_function_to_return_value(), CAR, CELL, cell_any_reference(), cell_to_reference(), compatible_points_to_subscripts_p(), CONS, copy_cell(), copy_reference(), ENDP, entity_anywhere_locations_p(), entity_local_name(), entity_to_module_entity(), entity_typed_anywhere_locations_p(), EXPRESSION, f(), gen_length(), gen_nconc(), heap_cell_p(), make_cell_reference(), NIL, pips_assert, points_to_compare_cell(), points_to_sink, points_to_source, POP, reference_indices, reference_variable, s1, same_string_p, SET_FOREACH, and source_in_set_p().

Referenced by add_implicitly_killed_arcs_to_kill_set(), compute_points_to_gen_set(), and generic_points_to_cells_translation().

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

◆ points_to_cells_exact_translation()

list points_to_cells_exact_translation ( list  cl,
set  binding,
entity  f 
)

Allocate a new list with the translations of the cells in cl, when their translation make sense and is unique (one-to-one mapping).

Effects on copied parameters are discarded.

Parameters
cll
bindinginding

Definition at line 2327 of file interprocedural.c.

2328 {
2329  return generic_points_to_cells_translation(cl, binding, f, true);
2330 }
list generic_points_to_cells_translation(list cl, set binding, entity f, bool exact_p)
Allocate a new list with the translations of the cells in cl, when their translation make sense.

References f(), and generic_points_to_cells_translation().

Referenced by user_call_to_points_to_interprocedural().

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

◆ points_to_cells_parameters()

list points_to_cells_parameters ( list  dl)

Transform a list of parameters of type "entity" to a list of cells.

interprocedural.c

The list is not sorted. It is probably a reversed list.

Parameters
dll

Definition at line 68 of file interprocedural.c.

69 {
70  list fpcl = NIL;
71  FOREACH(ENTITY, fp, dl) {
72  if(formal_parameter_p(fp) && !location_entity_p(fp)) {
74  // FI: not all formal parameter may impact points-to
75  if(pointer_type_p(fpt) || struct_type_p(fpt) || array_type_p(fpt)) {
76  reference r = make_reference(fp, NIL);
78  fpcl = gen_nconc(CONS(CELL, c, NULL), fpcl);
79  }
80  }
81  }
82  return fpcl;
83 }
bool location_entity_p(entity)
Definition: locations.c:349

References array_type_p(), CELL, CONS, ENTITY, entity_basic_concrete_type(), FOREACH, formal_parameter_p(), gen_nconc(), location_entity_p(), make_cell_reference(), make_reference(), NIL, pointer_type_p(), and struct_type_p().

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

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

◆ points_to_cells_pointer_arguments()

list points_to_cells_pointer_arguments ( list  al)

Transform a list of arguments of type "expression" to a list of cells.

The list is not sorted. It is probably a reversed list.

Parameters
all

Definition at line 90 of file interprocedural.c.

91 {
92  list apcl = NIL;
93  FOREACH(EXPRESSION, ap, al) {
97  apcl = gen_nconc(CONS(CELL, c, NULL), apcl);
98  }
99  }
100  return apcl;
101 }
bool expression_pointer_p(expression e)
we get the type of the expression by calling expression_to_type() which allocates a new one.
Definition: expression.c:506

References CELL, CONS, EXPRESSION, expression_pointer_p(), expression_reference(), expression_reference_p(), FOREACH, gen_nconc(), make_cell_reference(), and NIL.

Referenced by user_call_to_points_to_fast_interprocedural().

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

◆ points_to_cells_translation()

list points_to_cells_translation ( list  cl,
set  binding,
entity  f 
)

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

Effects on copied parameters are discarded.

Parameters
cll
bindinginding

Definition at line 2318 of file interprocedural.c.

2319 {
2320  return generic_points_to_cells_translation(cl, binding, f, false);
2321 }

References f(), and generic_points_to_cells_translation().

Referenced by user_call_to_points_to_interprocedural().

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

◆ points_to_set_to_module_stub_cell_list()

list points_to_set_to_module_stub_cell_list ( entity  m,
set  s,
list  osl 
)
Parameters
oslsl

Definition at line 2860 of file interprocedural.c.

2861 {
2862  return generic_points_to_set_to_stub_cell_list(m, s, osl);
2863 }
list generic_points_to_set_to_stub_cell_list(entity f, set s, list osl)
Add cells referencing a points-to stub found in parameter "s" are copied and added to list "osl".

References generic_points_to_set_to_stub_cell_list().

Referenced by user_call_to_points_to_interprocedural().

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

◆ points_to_set_to_stub_cell_list()

list points_to_set_to_stub_cell_list ( set  s,
list  osl 
)
Parameters
oslsl

Definition at line 2855 of file interprocedural.c.

2856 {
2858 }
#define entity_undefined
Definition: ri.h:2761

References entity_undefined, and generic_points_to_set_to_stub_cell_list().

+ Here is the call graph for this function:

◆ points_to_source_alias()

cell points_to_source_alias ( points_to  pt,
set  pt_binded 
)

Let "pt_binded" be the results of assignments of actual arguments to formal arguments (see compute_points_to_binded_set()).

Let "pt" be a points-to arc in "pt_binded".

Find for the source of p its corresponding alias, which means finding another source that points to the same location.

Parameters
ptt
pt_bindedt_binded

Definition at line 2873 of file interprocedural.c.

2874 {
2875  cell source = cell_undefined;
2876  cell sink1 = points_to_sink(pt);
2877  SET_FOREACH(points_to, p, pt_binded) {
2878  cell sink2 = points_to_sink(p);
2879  if(cell_equal_p(sink1, sink2)) {
2880  source = points_to_source(p);
2881  break;
2882  }
2883  }
2884  if(cell_undefined_p(source))
2885  pips_internal_error("At least one alias should be found.\n");
2886 
2887  return source;
2888 }
#define cell_undefined_p(x)
Definition: effects.h:431

References cell_equal_p(), cell_undefined, cell_undefined_p, pips_internal_error, points_to_sink, points_to_source, and SET_FOREACH.

Referenced by points_to_binding().

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

◆ points_to_translation_mapping_is_typed_p()

bool points_to_translation_mapping_is_typed_p ( set  translation)

FI: for some reason, the translation was built wrongly to express the fact that the source points to any element of the sink as in Semantics-New/Ancourt3009/memcpy09c where pointer arithmetic is used in the actual argument expression.

out -> buffer_out[*]

out cannot be replaced by buffer_out, because out[i] would result in buffer_out[i] instead of buffer_out[*].

Parameters
translationranslation

Definition at line 1433 of file interprocedural.c.

1434 {
1435  bool typed_p = true;
1436  SET_FOREACH(points_to, pt, translation) {
1437  cell source = points_to_source(pt);
1438  cell sink = points_to_sink(pt);
1439  type source_t = points_to_cell_to_concrete_type(source);
1440  type isink_t = points_to_cell_to_concrete_type(sink);
1441  type sink_t = constant_string_type_to_string_type(isink_t);
1442 #if 0
1443  if(type_functional_p(isink_t)) {
1444  reference ar = cell_any_reference(ac);
1445  entity a = reference_variable(ar);
1446  if(constant_string_entity_p(a)) {
1447  sink_t = ...;
1448  }
1449  }
1450 #endif
1451  if(char_type_p(source_t) && char_star_constant_function_type_p(isink_t)) {
1452  // an array of char points to a constant string, e.g. "YES"
1453  typed_p = true;
1454  }
1455  else if(!array_pointer_string_type_equal_p(source_t, sink_t)
1456  && !overloaded_type_p(sink_t)) {
1457  /* FI: for some reason, the translation was built wrongly to
1458  * express the fact that the source points to any element of the
1459  * sink as in Semantics-New/Ancourt3009/memcpy09c where pointer
1460  * arithmetic is used in the actual argument expression.
1461  *
1462  * out -> buffer_out[*]
1463  *
1464  * out cannot be replaced by buffer_out, because out[i] would
1465  * result in buffer_out[i] instead of buffer_out[*].
1466  */
1467  type st = type_to_pointed_type(source_t);
1468  // FI: if(type_structurally_equal_p(source_t, sink_t)? slower?
1469  if(array_pointer_string_type_equal_p(st, sink_t))
1470  typed_p = true;
1471  else {
1472  typed_p = false;
1473  pips_internal_error("Badly typed points-to translation mapping.\n");
1474  }
1475  break;
1476  }
1477  }
1478  return typed_p;
1479 }
type type_to_pointed_type(type)
returns t if t is not a pointer type, and the pointed type if t is a pointer type.
Definition: type.c:5265
bool char_type_p(type)
return true whether ‘t’ is a char or an unsigned char
Definition: type.c:2877

References array_pointer_string_type_equal_p(), cell_any_reference(), char_star_constant_function_type_p(), char_type_p(), constant_string_entity_p(), constant_string_type_to_string_type(), overloaded_type_p(), pips_internal_error, points_to_cell_to_concrete_type(), points_to_sink, points_to_source, reference_variable, SET_FOREACH, type_functional_p, and type_to_pointed_type().

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

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

◆ points_to_translation_of_formal_parameters()

void points_to_translation_of_formal_parameters ( list  fpcl,
list  al,
pt_map  pt_in,
set  translation 
)

List al and fpcl are assumed consistent, and consistent with the formal parameter ranks.

assumption about fpcl

This function does not return constant memory paths... This could fixed below with calls to points_to_indices_to_unbounded_indices(), but it could/should also be fixed later in the processing, at callees level. See EffectsWithPointsTo.sub/call05.c

See also EffectsWithPointsTo.sub/call08.c: &y[i][1] You need expression_to_points_to_sinks() on such a lhs expression...

This occurs with actual argument "&e": when the address-of operator is used, the relation between the formal parameter, let say "p", and "e" cannot be expressed unless we build a location entity with name "&e".

Beware of constant character strings

Likely to be wrong whe the formal parameter is a pointer and the actual parameter is a simple pointer, or a pointer to an array with fewer dimensions.

Parameters
fpclpcl
all
pt_int_in
translationranslation

Definition at line 1483 of file interprocedural.c.

1487 {
1488  FOREACH(CELL, fc, fpcl) {
1489  /* assumption about fpcl */
1492  expression a = EXPRESSION(gen_nth(n-1, al));
1493  /* This function does not return constant memory paths... This
1494  * could fixed below with calls to
1495  * points_to_indices_to_unbounded_indices(), but it could/should also be
1496  * fixed later in the processing, at callees level. See
1497  * EffectsWithPointsTo.sub/call05.c
1498  *
1499  * See also EffectsWithPointsTo.sub/call08.c: &y[i][1]
1500  * You need expression_to_points_to_sinks() on such a lhs expression...
1501  */
1502  list acl = expression_to_points_to_sources(a, pt_in);
1503  if(false && ENDP(acl)) {
1504  /* This occurs with actual argument "&e": when the address-of
1505  operator is used, the relation between the formal parameter,
1506  let say "p", and "e" cannot be expressed unless we build a
1507  location entity with name "&e". */
1508  acl = expression_to_points_to_sinks(a, pt_in);
1509  }
1510  int nacl = (int) gen_length(acl);
1511  // FI->FI: you should check nacl==0... OK, but to do what ?
1512  approximation ap = nacl==1? make_approximation_exact() :
1514  FOREACH(CELL, ac, acl) {
1515  cell source = copy_cell(fc);
1516  //bool to_be_freed;
1517  //type a_source_t = points_to_cell_to_type(ac, &to_be_freed);
1518  //type source_t = compute_basic_concrete_type(a_source_t);
1519  type source_t = points_to_cell_to_concrete_type(source);
1520  if(pointer_type_p(source_t)) {
1521  cell n_source = copy_cell(fc);
1522  cell n_sink = copy_cell(ac);
1523  type e_sink_t = points_to_cell_to_concrete_type(n_sink);
1524  type sink_t = e_sink_t;
1525  /* Beware of constant character strings */
1526  if(type_functional_p(e_sink_t)) {
1527  functional f = type_functional(sink_t);
1529  sink_t = functional_result(f);
1530  }
1531  //reference n_sink_r = cell_any_reference(n_sink);
1532  // points_to_indices_to_unbounded_indices(reference_indices(n_sink_r));
1533  if(type_equal_p(source_t, sink_t)) {
1534  if(array_pointer_string_type_equal_p(source_t, sink_t))
1535  ; // do nothing: a 1D array is equivalent to a pointer
1536  else if(array_type_p(sink_t)) {
1537  // FI: I do not remember in which case I needed this
1539  }
1540  else if(scalar_type_p(sink_t)) {
1541  // Pointers/dereferencing11.c:
1542  // "i", double *, and "fifi[3][0]", double [2][3]
1543  reference n_sink_r = cell_any_reference(n_sink);
1544  list n_sink_sl = reference_indices(n_sink_r);
1545  bool succeed_p = false;
1546  if(!ENDP(n_sink_sl)) {
1547  expression ls = EXPRESSION(CAR(gen_last(n_sink_sl)));
1548  if(zero_expression_p(ls)) {
1549  // points_to_cell_remove_last_zero_subscript(n_sink);
1550  gen_remove_once(&reference_indices(n_sink_r), ls);
1551  succeed_p = true;
1552  }
1553  }
1554  if(!succeed_p)
1555  pips_internal_error("Not implemented yet.\n");
1556  }
1557  else
1558  pips_internal_error("Not implemented yet.\n");
1559  }
1560  points_to pt = make_points_to(n_source, n_sink, copy_approximation(ap),
1563  }
1564  else if(array_type_p(source_t)) {
1565  if(array_of_pointers_type_p(source_t)) {
1566  /* Likely to be wrong whe the formal parameter is a pointer
1567  and the actual parameter is a simple pointer, or a
1568  pointer to an array with fewer dimensions. */
1569  cell n_source = copy_cell(fc);
1570  cell n_sink = copy_cell(ac);
1571  //reference n_sink_r = cell_any_reference(n_sink);
1572  // points_to_indices_to_unbounded_indices(reference_indices(n_sink_r));
1573  points_to pt = make_points_to(n_source, n_sink, copy_approximation(ap),
1575  add_arc_to_simple_pt_map(pt, translation);
1576  //pips_internal_error("Not implemented yet.\n");
1577  }
1578  else if(array_of_struct_type_p(source_t)) {
1579  list fl = struct_type_to_fields(source_t);
1580  FOREACH(ENTITY, f, fl) {
1582  if(pointer_type_p(ft))
1583  pips_internal_error("Not implemented yet.\n");
1584  if(struct_type_p(ft))
1585  pips_internal_error("Not implemented yet.\n");
1586  else {
1587  ; // ignore
1588  }
1589  }
1590  }
1591  else {
1592  ; // Do no worry about these arrays
1593  }
1594  }
1595  else if(struct_type_p(source_t)) {
1596  // Can we make an artificial lhs and rhs and call
1597  // assign_to_points_to() in that specific case?
1598  // Or do we have to program yet another recursive descent in structs?
1599  // How do we keep track of the approximation?
1601  ac,
1602  ap,
1603  source_t,
1604  translation);
1605  }
1606  else {
1607  ; // No need
1608  }
1609  //if(to_be_freed) free_type(a_source_t);
1610  }
1611  free_approximation(ap);
1612  }
1613  pips_assert("The points-to translation mapping is well typed",
1615 }
void gen_remove_once(list *pl, const void *o)
Remove the first occurence of o in list pl:
Definition: list.c:691
gen_chunk gen_nth(int n, const list l)
to be used as ENTITY(gen_nth(3, l))...
Definition: list.c:710
void points_to_translation_of_struct_formal_parameter(cell fc, cell ac, approximation a, type st, set translation)
list expression_to_points_to_sinks(expression, pt_map)
The returned list contains cells used in "in".
Definition: sinks.c:1795
list expression_to_points_to_sources(expression, pt_map)
expression_to_points_to_sources() does not always work, especially with pointer arithmetic or subscri...
Definition: sinks.c:1805
bool zero_expression_p(expression e)
Definition: expression.c:1217
bool scalar_type_p(type)
Definition: type.c:2955
#define formal_offset(x)
Definition: ri.h:1408
#define entity_storage(x)
Definition: ri.h:2794
#define storage_formal(x)
Definition: ri.h:2524

References add_arc_to_simple_pt_map, add_subscript_dependent_arc_to_simple_pt_map(), array_of_pointers_type_p(), array_of_struct_type_p(), array_pointer_string_type_equal_p(), array_type_p(), CAR, CELL, cell_any_reference(), copy_approximation(), copy_cell(), ENDP, ENTITY, entity_basic_concrete_type(), entity_storage, EXPRESSION, expression_to_points_to_sinks(), expression_to_points_to_sources(), f(), FOREACH, formal_offset, free_approximation(), functional_parameters, functional_result, gen_last(), gen_length(), gen_nth(), gen_remove_once(), int, make_approximation_exact(), make_approximation_may(), make_descriptor_none(), make_points_to(), pips_assert, pips_internal_error, pointer_type_p(), points_to_cell_add_zero_subscript(), points_to_cell_to_concrete_type(), points_to_translation_mapping_is_typed_p(), points_to_translation_of_struct_formal_parameter(), reference_indices, reference_variable, scalar_type_p(), storage_formal, struct_type_p(), struct_type_to_fields(), type_equal_p(), type_functional, type_functional_p, and zero_expression_p().

Referenced by user_call_to_points_to_interprocedural(), and user_call_to_points_to_interprocedural_binding_set().

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

◆ points_to_translation_of_struct_formal_parameter()

void points_to_translation_of_struct_formal_parameter ( cell  fc,
cell  ac,
approximation  a,
type  st,
set  translation 
)

We assume that cell fc and cell ac are of type st and that st is a struct type.

Parameters
fcc
acc
stt
translationranslation

Definition at line 1365 of file interprocedural.c.

1370 {
1371  /* We assume that cell fc and cell ac are of type st and that st is
1372  a struct type. */
1373  // pips_internal_error("Not implemented yet.\n");
1374  list fl = struct_type_to_fields(st);
1375 
1376  FOREACH(ENTITY, f, fl) {
1378  if(pointer_type_p(ft)) {
1379  cell nfc = copy_cell(fc);
1380  cell nac = copy_cell(ac);
1383  points_to pt = make_points_to(nfc, nac, copy_approximation(a),
1385  add_arc_to_simple_pt_map(pt, translation);
1386  }
1387  else if(struct_type_p(ft)) {
1388  cell nfc = copy_cell(fc);
1389  cell nac = copy_cell(ac);
1393  ac,
1394  a,
1395  ft,
1396  translation);
1397  free_cell(nfc), free_cell(nac);
1398  }
1399  else if(array_of_pointers_type_p(ft)) {
1400  cell nfc = copy_cell(fc);
1401  cell nac = copy_cell(ac);
1406  points_to pt = make_points_to(nfc, nac, copy_approximation(a),
1408  add_arc_to_simple_pt_map(pt, translation);
1409  }
1410  else if(array_of_struct_type_p(ft)) {
1411  cell nfc = copy_cell(fc);
1412  cell nac = copy_cell(ac);
1420  ac,
1421  a,
1422  cet,
1423  translation);
1424  free_cell(nfc), free_cell(nac);
1425  }
1426  else {
1427  ; // do nothing
1428  }
1429  }
1430 
1431 }
void free_cell(cell p)
Definition: effects.c:249
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

References add_arc_to_simple_pt_map, array_of_pointers_type_p(), array_of_struct_type_p(), array_type_to_element_type(), compute_basic_concrete_type(), copy_approximation(), copy_cell(), ENTITY, entity_basic_concrete_type(), f(), FOREACH, free_cell(), make_descriptor_none(), make_points_to(), pointer_type_p(), points_to_cell_add_field_dimension(), points_to_cell_add_unbounded_subscripts(), struct_type_p(), and struct_type_to_fields().

Referenced by points_to_translation_of_formal_parameters().

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

◆ recursive_filter_formal_context_according_to_actual_context()

bool recursive_filter_formal_context_according_to_actual_context ( list  fcl,
set  pt_in,
set  pt_binded,
set  binding,
set  filtered 
)

This function looks for successors of elements of list "fcl" both in points-to relations "pt_in" and "pt_binded".

Update the formal context defined by "pt_binded" on demand as necessary according to "pt_in", update the translation mapping "binding" according to the new pairs found, and go down recursively with a new list of constant paths, "nfcl", the possible successors in the formal context of the callee of elements in "fcl" when possible. In fact, the elements in "nfcl" must be pointers and are not necessarily the successors of elements of "fcl", but pointers contained in them.

This function is very similar to filter_formal_context_according_to_actual_context(), but a little bit more tricky. Amira Mensi unified both in her own version, but the unification makes the maintenance more difficult.

Copy only possible arcs "pt" from "pt_in" into the "filtered" set

FI: this assert may be too strong FI: This assert is too strong for Pointers/formal_parameter01 and its message is misleading because "source" is not an element of "fcl". Elements of "fcl" must be translated, but related elements may not be translatable because the effective context is not as rich as the formal context. For instance, the formal context may expect an array for each formal scalar pointer, but the effective target may be a scalar. And an error must be raised if pointer arithmetic is used in the callee.

Make sure pt_binded is large enough: the pointer may be initialized before the call to the caller and used only in the callee. Because of the on-demand approach, pt_binded does not contain enough elements.

Do we have a similar arc in pt_binded?

Compute the binding relation for sinks of the formal context list "fcl"

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

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

Parameters
fclcl
pt_int_in
pt_bindedt_binded
bindinginding
filterediltered

Definition at line 362 of file interprocedural.c.

367 {
368  bool ok_p = true;
369  points_to_graph binding_g = make_points_to_graph(false, binding);
370 
371  /* Copy only possible arcs "pt" from "pt_in" into the "filtered" set */
372  SET_FOREACH(points_to, pt, pt_in) {
373  cell source = points_to_source(pt);
374  if(related_points_to_cell_in_list_p(source, fcl)) {
375  cell sink = points_to_sink(pt);
376  list ptsl = points_to_source_to_sinks(source, binding_g, false);
377 
378  /* FI: this assert may be too strong FI: This assert is too
379  * strong for Pointers/formal_parameter01 and its message is
380  * misleading because "source" is not an element of
381  * "fcl". Elements of "fcl" must be translated, but related
382  * elements may not be translatable because the effective
383  * context is not as rich as the formal context. For instance,
384  * the formal context may expect an array for each formal scalar
385  * pointer, but the effective target may be a scalar. And an
386  * error must be raised if pointer arithmetic is used in the
387  * callee.
388  */
389  if(points_to_cell_in_list_p(source, fcl ))
390  pips_assert("Elements of \"fcl\" can be translated", !ENDP(ptsl));
391 
393  gen_free_list(ptsl);
394 
395  if(!ENDP(tsl)) {
396  /* Make sure pt_binded is large enough: the pointer may be
397  initialized before the call to the caller and used only in
398  the callee. Because of the on-demand approach, pt_binded
399  does not contain enough elements. */
400  pt_map pt_binded_g = make_points_to_graph(false, pt_binded);
401  FOREACH(CELL, c, tsl) {
402  list sinks = any_source_to_sinks(c, pt_binded_g, false);
403  gen_free_list(sinks);
404  }
405 
406  if(null_cell_p(sink)) {
407  /* Do we have a similar arc in pt_binded? */
408  FOREACH(CELL, tc, tsl) {
409  if(cell_points_to_null_sink_in_set_p(tc, pt_binded)) {
410  points_to npt = copy_points_to(pt);
411  add_arc_to_simple_pt_map(npt, filtered);
412  break;
413  }
414  else {
415  ; // do not copy this arc in filtered set
416  }
417  }
418  }
419  else {
420  FOREACH(CELL, tc, tsl) {
422  /* */
423  semantics_user_warning("An uninitialized pointer, \"%s\", may be reached.\n ", points_to_cell_to_string(tc));
424  //ok_p = false;
425  }
426  else if(cell_points_to_non_null_sink_in_set_p(tc, pt_binded)) {
427  if(cell_points_to_nowhere_sink_in_set_p(tc, pt_binded)) {
428  /* */
429  semantics_user_warning("An uninitialized pointer, \"%s\", might be reached.\n ", points_to_cell_to_string(tc));
430  }
431  points_to npt = copy_points_to(pt);
432  add_arc_to_simple_pt_map(npt, filtered);
433  break;
434  }
435  else {
436  ; // do not copy this arc in filtered set
437  }
438  }
439  }
440  gen_free_list(tsl);
441  }
442  else {
443  ; // do not copy this arc in filtered set
444  }
445  }
446  }
447 
448  /* Compute the binding relation for sinks of the formal context list "fcl" */
449  list nfcl = NIL;
450  FOREACH(CELL, c, fcl) {
451  points_to_graph filtered_g = make_points_to_graph(false, filtered);
452  list fl = points_to_source_to_some_sinks(c, filtered_g, false); // formal list
453  if(!ENDP(fl)) {
454  // FI: I am in trouble with _nl_1 and _nl_1[next]; the first one
455  // is not recognized in the second one.
456  //list tsl = points_to_source_to_sinks(c, binding_g, false);
457  list tsl = points_to_source_to_some_sinks(c, binding_g, false);
458  //list tsl = source_to_sinks(c, binding_g, false);
459  FOREACH(CELL, tc, tsl) {
460  points_to_graph pt_binded_g = make_points_to_graph(false, pt_binded);
461  list al = points_to_source_to_some_sinks(tc, pt_binded_g, false); // formal list
462  int nfl = (int) gen_length(fl);
463  int nal = (int) gen_length(al);
465  if(nfl==1 && nal==1)
467  else
469  FOREACH(CELL, fc, fl) {
470  if(!null_cell_p(fc)) {
471  FOREACH(CELL, ac, al) {
472  if(!null_cell_p(ac) && !nowhere_cell_p(ac)) {
475  // FI: why not use array_pointer_string_type_equal_p()?
476  if(!type_equal_p(fc_t, ac_t) && !overloaded_type_p(ac_t)) {
479  if(!type_equal_p(fc_t, ac_nt))
480  pips_internal_error("translation failure.\n");
481  }
485  add_arc_to_simple_pt_map(tr, binding);
486  }
487  }
488  /* If "fc" is not a pointer, look for pointers in "fc" */
490  nfcl = gen_nconc(nfcl, pcl);
491  //nfcl = CONS(CELL, fc, nfcl);
492  }
493  }
495  }
496  }
497  else {
498  ; // No need to go down... if we stop with a good reason, not
499  // because of a bug
500  // pips_internal_error("Translation error.\n");
501  }
502  }
503 
504  pips_assert("The points-to translation mapping is well typed",
506 
507  /* Now, we have to call about the same function recursively on the
508  list of formal sinks */
509  if(ok_p && !ENDP(nfcl)) {
511  (nfcl, pt_in, pt_binded, binding, filtered);
512  gen_free_list(nfcl);
513  }
514 
515  // FI binding_g should be freed, but not the set in it...
516 
517  return ok_p;
518 }
bool cell_points_to_null_sink_in_set_p(cell, set)
Definition: points_to.c:898
bool cell_points_to_nowhere_sink_in_set_p(cell, set)
Definition: points_to.c:845
bool cell_must_point_to_nowhere_sink_in_set_p(cell, set)
How are array handled in pts? do we have arcs "a->a"?
Definition: points_to.c:870
list points_to_cells_to_pointer_cells(list pl)
Convert cells in l into derived pointer cells when possible.
Definition: expression.c:1917
list points_to_source_to_sinks(cell, pt_map, bool)
Build the sinks of source "source" according to the points-to graphs.
list any_source_to_sinks(cell, pt_map, bool)
Generalization of source_to_sinks().
static int tc
Internal variables
Definition: reindexing.c:107

References add_arc_to_simple_pt_map, any_source_to_sinks(), approximation_undefined, CELL, cell_must_point_to_nowhere_sink_in_set_p(), cell_points_to_non_null_sink_in_set_p(), cell_points_to_nowhere_sink_in_set_p(), cell_points_to_null_sink_in_set_p(), copy_approximation(), copy_cell(), copy_points_to(), ENDP, FOREACH, free_approximation(), gen_free_list(), gen_length(), gen_nconc(), int, make_approximation_exact(), make_approximation_may(), make_descriptor_none(), make_points_to(), make_points_to_graph(), NIL, nowhere_cell_p(), null_cell_p(), overloaded_type_p(), pips_assert, pips_internal_error, points_to_cell_add_zero_subscript(), points_to_cell_in_list_p(), points_to_cell_to_concrete_type(), points_to_cell_to_string(), points_to_cell_to_useful_pointer_cells(), points_to_cells_to_pointer_cells(), points_to_sink, points_to_source, points_to_source_to_sinks(), points_to_source_to_some_sinks(), points_to_translation_mapping_is_typed_p(), related_points_to_cell_in_list_p(), semantics_user_warning, SET_FOREACH, tc, and type_equal_p().

Referenced by filter_formal_context_according_to_actual_context().

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

◆ remove_arcs_from_pt_map()

void remove_arcs_from_pt_map ( points_to  pts,
set  pt_out 
)
Parameters
ptsts
pt_outt_out

Definition at line 231 of file interprocedural.c.

232 {
233  cell sink = points_to_sink(pts);
234  cell source = points_to_source(pts);
235 
236 
237  SET_FOREACH(points_to, pt, pt_out) {
238  if(cell_equal_p(points_to_source(pt), sink) ||cell_equal_p(points_to_source(pt), source) ) {
239  remove_arc_from_simple_pt_map(pts, pt_out);
241  reference r = make_reference(e, NIL);
242  cell source = make_cell_reference(r);
243  cell sink = copy_cell(source);
245  points_to npt = make_points_to(source, sink, a, make_descriptor_none());
246  add_arc_to_simple_pt_map(npt, pt_out);
247  remove_arcs_from_pt_map(pt, pt_out);
248  }
249  }
250 }
entity entity_anywhere_locations()
void remove_arcs_from_pt_map(points_to pts, set pt_out)

References add_arc_to_simple_pt_map, cell_equal_p(), copy_cell(), entity_anywhere_locations(), make_approximation_exact(), make_cell_reference(), make_descriptor_none(), make_points_to(), make_reference(), NIL, points_to_sink, points_to_source, remove_arc_from_simple_pt_map, and SET_FOREACH.

Referenced by user_call_to_points_to_intraprocedural().

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

◆ translation_transitive_closure()

list translation_transitive_closure ( cell  c,
set  translation 
)

We are done

Parameters
translationranslation

Definition at line 1702 of file interprocedural.c.

1703 {
1704  list succ = CONS(CELL, c, NIL);
1705  list n_succ = gen_copy_seq(succ);
1706  bool finished_p = false;
1707  while(!finished_p) {
1708  points_to_graph translation_g = make_points_to_graph(false, translation);
1709  // Do not worry about sharing due to NULL or UNDEFINED/NOWHERE
1710  // Potentially new successors
1711  list pn_succ = points_to_sources_to_effective_sinks(n_succ, translation_g, false);
1712  list n_succ = NIL; // Reealy new successors
1713  // FI: does not work in general because the content is not used, shallow
1714  // gen_list_and_not(&n_succ, succ);
1715  FOREACH(CELL, c, pn_succ) {
1716  if(!points_to_cell_in_list_p(c, succ))
1717  n_succ = CONS(CELL, c, n_succ);
1718  }
1719  gen_free_list(pn_succ);
1720  if(ENDP(n_succ)) {
1721  /* We are done */
1722  finished_p = true;
1723  break;
1724  }
1725  else {
1726  succ = gen_nconc(succ, n_succ);
1727  n_succ = gen_copy_seq(n_succ);
1728  }
1729  }
1730  return succ;
1731 }
list points_to_sources_to_effective_sinks(list, pt_map, bool)

References CELL, CONS, ENDP, FOREACH, gen_copy_seq(), gen_free_list(), gen_nconc(), make_points_to_graph(), NIL, points_to_cell_in_list_p(), and points_to_sources_to_effective_sinks().

Referenced by aliased_translation_p().

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

◆ user_call_to_points_to()

points_to_graph user_call_to_points_to ( call  c,
points_to_graph  pt_in,
list  el 
)

FI: limited to the interprocedural option.

pcl =

Using memory effects does not simplify the points-to analysis, which is a preliminary analusis wrt memory effects

Parameters
pt_int_in
ell

Definition at line 106 of file interprocedural.c.

109 {
110  points_to_graph pt_out = pt_in;
111  if(!points_to_graph_bottom(pt_in)) {
112  entity f = call_function(c);
113  //list al = call_arguments(c);
114 
115  // FI: intraprocedural, use effects
116  // FI: interprocedural, check alias compatibility, generate gen and kill sets,...
117  pt_out = pt_in;
118 
119  // Code by Amira
120  //list fpcl = NIL; // Formal parameter cell list
122  if(type_functional_p(t)) {
124  /*fpcl = */points_to_cells_parameters(dl);
125  }
126  else {
127  pips_internal_error("Function has not a functional type.\n");
128  }
129 
130  /* Using memory effects does not simplify the points-to analysis,
131  which is a preliminary analusis wrt memory effects */
133  pt_out = user_call_to_points_to_interprocedural(c, pt_in);
134  }
136  pt_out = user_call_to_points_to_fast_interprocedural(c, pt_in, el);
137  }
138  else {
139  pt_out = user_call_to_points_to_intraprocedural(c, pt_in, el);
140  }
141  }
142 
143  return pt_out;
144 }
bool interprocedural_points_to_analysis_p()
Definition: passes.c:550
bool fast_interprocedural_points_to_analysis_p()
Definition: passes.c:555
pt_map user_call_to_points_to_fast_interprocedural(call c, pt_map pt_in, list csel __attribute__((unused)))
ompute the points to relations in a fast interprocedural way
list points_to_cells_parameters(list dl)
Transform a list of parameters of type "entity" to a list of cells.
pt_map user_call_to_points_to_interprocedural(call c, pt_map pt_caller)
Compute the points-to relations in a complete interprocedural way: be as accurate as possible.
pt_map user_call_to_points_to_intraprocedural(call c, pt_map pt_in, list el __attribute__((unused)))
#define code_declarations(x)
Definition: ri.h:784
#define value_code(x)
Definition: ri.h:3067
#define entity_initial(x)
Definition: ri.h:2796

References call_function, code_declarations, entity_basic_concrete_type(), entity_initial, f(), fast_interprocedural_points_to_analysis_p(), interprocedural_points_to_analysis_p(), pips_internal_error, points_to_cells_parameters(), points_to_graph_bottom, type_functional_p, user_call_to_points_to_fast_interprocedural(), user_call_to_points_to_interprocedural(), user_call_to_points_to_intraprocedural(), and value_code.

Referenced by call_to_points_to(), and user_call_condition_to_points_to().

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

◆ user_call_to_points_to_fast_interprocedural()

pt_map user_call_to_points_to_fast_interprocedural ( call  c,
pt_map  pt_in,
list csel   __attribute__(unused) 
)

ompute the points to relations in a fast interprocedural way

"c" is the call site

"pt_in" is the points-to information available before the call site is executed.

"csel" is the call site effect list

Compute kill_1 = effective parameters of pointer type should point to nowhere in case the function call the free routine.

Definition at line 262 of file interprocedural.c.

265 {
266  set pt_in_s = points_to_graph_set(pt_in);
267  pt_map pt_out = pt_in;
271  entity f = call_function(c);
272  list al = call_arguments(c);
274  list fpcl = points_to_cells_parameters(dl);
275  /* Compute kill_1 = effective parameters of pointer type should point to
276  nowhere in case the function call the free routine.
277  */
279  FOREACH(CELL, ac, apcl) {
280  SET_FOREACH(points_to, pt, pt_in_s) {
282  points_to npt = copy_points_to(pt);
283  (void) add_arc_to_simple_pt_map(npt, kill_1);
284  }
285  }
286  }
287  ifdebug(8) print_points_to_set("kill_1",kill_1);
288 
289  SET_FOREACH(points_to, pt_to, kill_1) {
291  cell sr = copy_cell(points_to_source(pt_to));
292  cell sk = copy_cell(points_to_sink(pt_to));
293  points_to npt = make_points_to(sr, sk, a, make_descriptor_none());
294  (void) add_arc_to_simple_pt_map(npt, gen_1);
295  }
296  ifdebug(8) print_points_to_set("gen_1",gen_1);
297 
298 
299  SET_FOREACH(points_to, pt_to1, gen_1) {
300  cell source = copy_cell(points_to_source(pt_to1));
301  cell nc = cell_to_nowhere_sink(source);
303  points_to npt = make_points_to(source, nc, a, make_descriptor_none());
304  (void) add_arc_to_simple_pt_map(npt, gen_2);
305  }
306  ifdebug(8) print_points_to_set("gen_1",gen_2);
307 
308 
309 
310  extern list load_summary_effects(entity e);
312  list wpl = written_pointers_set(el);
313  points_to_list pts_to_in = (points_to_list)
314  db_get_memory_resource(DBR_POINTS_TO_IN, module_local_name(f), true);
315  list l_pt_to_in = gen_full_copy_list(points_to_list_list(pts_to_in));
316  set pt_in_callee = new_simple_pt_map();
317  pt_in_callee = set_assign_list(pt_in_callee, l_pt_to_in);
318  // list l_pt_to_out = gen_full_copy_list(points_to_list_list(pts_to_out));
319  // pt_map pt_out_callee = set_assign_list(pt_out_callee, l_pt_to_out);
320  bool success_p = false;
321  set pts_binded = compute_points_to_binded_set(f, al, pt_in_s, & success_p);
322  // FI->AM: for the time being, ignore success_p...
323  ifdebug(8) print_points_to_set("pt_binded", pts_binded);
324  set bm = points_to_binding(fpcl, pt_in_callee, pts_binded);
325  set pts_kill = compute_points_to_kill_set(wpl, pt_in_s, bm);
326  ifdebug(8) print_points_to_set("pts_kill", pts_kill);
327  set pts_gen = new_simple_pt_map();
328  SET_FOREACH(points_to, pt, pts_kill) {
329  cell source = points_to_source(pt);
330  cell nc = cell_to_nowhere_sink(source);
332  points_to npt = make_points_to(source, nc, a, make_descriptor_none());
333  (void) add_arc_to_simple_pt_map(npt, pts_gen);
334  }
335  set pt_end = new_simple_pt_map();
336  pts_kill = set_union(pts_kill, pts_kill, kill_1);
337  pt_end = set_difference(pt_end, pt_in_s, pts_kill);
338  pts_gen = set_union(pts_gen, pts_gen, gen_1);
339  pts_gen = set_union(pts_gen, pts_gen, gen_2);
340  pt_end = set_union(pt_end, pt_end, pts_gen);
341  ifdebug(8) print_points_to_set("pt_end =", pt_end);
342  points_to_graph_set(pt_out) = pt_end;
343  return pt_out;
344 }
cell cell_to_nowhere_sink(cell source)
assuming source is a reference to a pointer, build the corresponding sink when the pointer is not ini...
list load_summary_effects(entity e)
FI->FI, FI->BC: these two functions should be moved into effects-util or effects-simple.
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755
set set_assign_list(set, const list)
assigns a list contents to a set all duplicated elements are lost
Definition: set.c:474
set set_difference(set, const set, const set)
Definition: set.c:256
#define true
Definition: newgen_types.h:81
#define false
Definition: newgen_types.h:80
set compute_points_to_kill_set(list written_must_translated, set pt_caller, set binding __attribute__((unused)))
Translate the "out" set into the scope of the caller.
set compute_points_to_binded_set(entity called_func, list real_args, set pt_caller, bool *success_p)
For each actual argument "r" and its corresponding formal one "f", create the assignment "f = r;" and...
list written_pointers_set(list eff)
Filter out written effects on pointers.
list points_to_cells_pointer_arguments(list al)
Transform a list of arguments of type "expression" to a list of cells.
set points_to_binding(list args, set in, set pt_binded)
Apply points_to_binding_arguments() to each pair (, complete the process of binding each element of "...
#define points_to_list_list(x)
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
#define call_arguments(x)
Definition: ri.h:711

References add_arc_to_simple_pt_map, call_arguments, call_function, CELL, cell_to_nowhere_sink(), code_declarations, compute_points_to_binded_set(), compute_points_to_kill_set(), copy_cell(), copy_points_to(), db_get_memory_resource(), entity_initial, f(), FOREACH, gen_full_copy_list(), ifdebug, load_summary_effects(), make_approximation_exact(), make_approximation_may(), make_descriptor_none(), make_points_to(), module_local_name(), new_simple_pt_map, points_to_binding(), points_to_cell_equal_p(), points_to_cells_parameters(), points_to_cells_pointer_arguments(), points_to_equal_p(), points_to_graph_set, points_to_list_list, points_to_rank(), points_to_sink, points_to_source, print_points_to_set(), set_assign_list(), set_difference(), SET_FOREACH, set_generic_make(), set_private, set_union(), value_code, and written_pointers_set().

Referenced by user_call_to_points_to().

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

◆ user_call_to_points_to_interprocedural()

pt_map user_call_to_points_to_interprocedural ( call  c,
pt_map  pt_caller 
)

Compute the points-to relations in a complete interprocedural way: be as accurate as possible.

Not much to do if both IN and OUT are empty, except if OUT is bottom (see below)

This used to be only useful when a free occurs with the callee, since information about formal parameters used to be normally projected out.

Global variables do not require any translation in C, but it might more convenient to apply translation uniformly, without checking for global variables... Or the other way round?

Filter "pt_in" according to "pt_binded". For instance, a formal parameter can point to NULL in "pt_in" only if it also points to NULL in pt_binded. In the same way, a formal parameter can point to a points-to stub in "pt_in" only if it points to a non-NULL target in pt_binded. Also, a formal parameter cannot points exactly to UNDEFINED in "pt_binded" as it would be useless (not clear if we can remove such an arc when it is a may arc...). Finally, each formal parameter must still point to something. The mapping "binding" is augmented as needed. as well as "pt_caller" because of the on-demand approach. But "pt_binded" is not updated accordingly (?).

set pt_in_filtered =

filter_formal_context_according_to_actual_context(fpcl,

pt_in,

pt_binded,

binding);

We have to test if pt_binded is compatible with pt_in_callee

We have to start by computing all the elements of E (stubs)

See if two formal parameters can reach the same memory cell, i.e. transitive closure of binding map. We should take care of global variables too...

If no pointer is written, aliasing is not an issue

Explicitly written pointers imply some arc removals; pointer assignments directly or indirectly in the callee.

FI: pt_caller_s may have been modified implictly because the formal context has been increased according to the needs of the callee. But pt_caller_s may also have been updated by what has happened prevously when analyzing the current statement. See for instance Pointers/sort01.c.

Compute pt_kill_2

Implicitly written pointers imply some arc removals: free(), tests and exits. These are the elements of pt_kill_1, although the equations do not seem to fit at all since pt_in_filtered is not an argument...

Translation failure, incompatibility between the call site and the callee.

Some check

Use written/wpl to reduce the precision of exact arcs in pt_end. This is equivalent to pt_kill_3 and pt_gen_3.

FI: I do not understand why the precision of the write is not exploited. We may need to use mwpl instead of wpl

Some check

This cannot be performed earlier because the points-to precondition of the caller may have to be enriched according to the formal context of the callee, or the effect computation is going to fail.

Parameters
pt_callert_caller

Definition at line 1892 of file interprocedural.c.

1894 {
1895  pt_map pt_end_f = pt_caller;
1896  pips_assert("pt_caller is valid", !points_to_graph_bottom(pt_caller));
1897  pips_assert("pt_caller is consistent", consistent_pt_map_p(pt_caller));
1898  entity f = call_function(c);
1899  list al = call_arguments(c);
1901  list fpcl = points_to_cells_parameters(dl);
1902  points_to_list pts_to_in = (points_to_list)
1903  db_get_memory_resource(DBR_POINTS_TO_IN, module_local_name(f), true);
1904  list l_pt_to_in = gen_full_copy_list(points_to_list_list(pts_to_in));
1905  points_to_list pts_to_out = (points_to_list)
1906  db_get_memory_resource(DBR_POINTS_TO_OUT, module_local_name(f), true);
1907  bool out_bottom_p = points_to_list_bottom(pts_to_out);
1908 
1909  list l_pt_to_out = gen_full_copy_list(points_to_list_list(pts_to_out));
1910 
1911  /* Not much to do if both IN and OUT are empty, except if OUT is
1912  bottom (see below) */
1913  if(!(ENDP(l_pt_to_out) && ENDP(l_pt_to_in))) {
1914  // FI: this function should be moved from semantics into effects-util
1915  extern list load_body_effects(entity e);
1916  list el = load_body_effects(f);
1917  list wpl = written_pointers_set(el);
1919  set pt_caller_s = points_to_graph_set(pt_caller);
1920  set pt_in = set_assign_list(new_simple_pt_map(), l_pt_to_in);
1921  set pt_out = set_assign_list(new_simple_pt_map(), l_pt_to_out);
1922 
1923  // FI: function name... set or list?
1924  bool success_p = false;
1925  set pt_binded = compute_points_to_binded_set(f, al, pt_caller_s, &success_p);
1926  ifdebug(8) print_points_to_set("pt_binded", pt_binded);
1927 
1928  if(success_p) {
1929  set binding = new_simple_pt_map();
1930  /* This used to be only useful when a free occurs with the
1931  callee, since information about formal parameters used to be
1932  normally projected out. */
1933  points_to_translation_of_formal_parameters(fpcl, al, pt_caller, binding);
1934 
1935  /* Global variables do not require any translation in C, but it
1936  might more convenient to apply translation uniformly, without
1937  checking for global variables... Or the other way round? */
1938  //points_to_translation_of_global_variables(pt_out, pt_caller, binding);
1939 
1940  /* Filter "pt_in" according to "pt_binded". For instance, a
1941  formal parameter can point to NULL in "pt_in" only if it
1942  also points to NULL in pt_binded. In the same way, a formal
1943  parameter can point to a points-to stub in "pt_in" only
1944  if it points to a non-NULL target in pt_binded. Also, a
1945  formal parameter cannot points exactly to UNDEFINED in
1946  "pt_binded" as it would be useless (not clear if we can remove
1947  such an arc when it is a may arc...). Finally, each formal
1948  parameter must still point to something. The mapping
1949  "binding" is augmented as needed. as well as "pt_caller"
1950  because of the on-demand approach. But "pt_binded" is not
1951  updated accordingly (?). */
1952  /* set pt_in_filtered = */
1953  /* filter_formal_context_according_to_actual_context(fpcl, */
1954  /* pt_in, */
1955  /* pt_binded, */
1956  /* binding); */
1957  set pt_in_filtered =
1959  pt_in,
1960  pt_binded,
1961  binding);
1962 
1963  /* We have to test if pt_binded is compatible with pt_in_callee */
1964  /* We have to start by computing all the elements of E (stubs) */
1965  //list stubs = stubs_list(pt_in_callee, pt_out_callee);
1966  // bool compatible_p = true;
1967  // FI: I do not understand Amira's test
1968  // = sets_binded_and_in_compatible_p(stubs, fpcl, pt_binded,
1969  // pt_in_callee_filtered, pt_out_callee,
1970  // binding);
1971  /* See if two formal parameters can reach the same memory cell,
1972  * i.e. transitive closure of binding map. We should take care
1973  * of global variables too... */
1974  // compatible_p = compatible_p && !aliased_translation_p(fpcl, pt_binded);
1975 
1976  // pt_binded and pt_in are incompatible for instance because the
1977  // caller not initialized a pointer
1978  if(set_undefined_p(pt_in_filtered)) {
1979  out_bottom_p = true;
1980  }
1981  /* If no pointer is written, aliasing is not an issue */
1982  else if(ENDP(wpl) || !aliased_translation_p(fpcl, pt_binded)) {
1983 
1984  set pt_out_filtered =
1986  (pt_out, pt_in_filtered, wpl, f);
1987 
1988  /* Explicitly written pointers imply some arc removals; pointer
1989  assignments directly or indirectly in the callee. */
1990  // pt_end = set_difference(pt_end, pt_caller_s, pts_kill);
1991 
1992  /* FI: pt_caller_s may have been modified implictly because the
1993  * formal context has been increased according to the needs of
1994  * the callee. But pt_caller_s may also have been updated by what
1995  * has happened prevously when analyzing the current
1996  * statement. See for instance Pointers/sort01.c.
1997  */
1999  c_pt_caller_s = set_union(c_pt_caller_s, c_pt_caller_s, pt_caller_s);
2000 
2001  list tcwpl = points_to_cells_exact_translation(cwpl, binding, f);
2002  /* Compute pt_kill_2 */
2003  set pt_kill = compute_points_to_kill_set(tcwpl, c_pt_caller_s, binding);
2004  /* Implicitly written pointers imply some arc removals:
2005  * free(), tests and exits. These are the elements of
2006  * pt_kill_1, although the equations do not seem to fit at
2007  * all since pt_in_filtered is not an argument...
2008  */
2010  wpl,
2011  c_pt_caller_s,
2012  pt_out_filtered,
2013  binding,
2014  f);
2015  ifdebug(8) print_points_to_set("pt_kill", pt_kill);
2016 
2017  set pt_end = new_simple_pt_map();
2018  // FI: c_pr_in_s is probably pt_{caller} in the dissertation
2019  pt_end = set_difference(pt_end, c_pt_caller_s, pt_kill);
2020 
2021  set pt_gen_1 = compute_points_to_gen_set(pt_out_filtered,
2022  wpl,
2023  binding, f);
2024 
2025  if(set_undefined_p(pt_gen_1)) {
2026  /* Translation failure, incompatibility between the call site
2027  and the callee. */
2028  pips_user_warning("Incompatibility between call site and "
2029  "callee's output.\n");
2030  out_bottom_p = true;
2031  }
2032  else {
2033  pips_assert("pt_gen_1 is consistent", consistent_points_to_set(pt_gen_1));
2034 
2035  // FI->FI: Not satisfying; kludge to solve issue with Pointers/inter04
2036  // FI->FI: this causes a core dump for Pointers/formal_parameter01.c
2037  // A lot should be said about this test case, which is revealing
2038  // because of the test it contains, and because of the
2039  // pointer arithmetic, and because the useless primature
2040  // expansion of_pi_1[1] in _pi_1[*] which is semantically
2041  // correct but fuzzy as it implies possible unexisting arcs
2042  // for _pi_1[0], _pi_1[2], etc...
2043  // FI->FI: the upgrade must be postponed
2044  /*
2045  pt_map pt_gen_1_g = make_points_to_graph(false, pt_gen_1);
2046  upgrade_approximations_in_points_to_set(pt_gen_1_g);
2047 
2048  pips_assert("pt_gen_1 is consistent after upgrade",
2049  consistent_points_to_set(pt_gen_1));
2050  */
2051 
2052  /* Some check */
2053  list stubs = points_to_set_to_module_stub_cell_list(f, pt_gen_1, NIL);
2054  if(!ENDP(stubs)) {
2055  pips_internal_error("Translation failure in pt_gen_1.\n");
2056  }
2057 
2058  /* Use written/wpl to reduce the precision of exact arcs in
2059  * pt_end. This is equivalent to pt_kill_3 and pt_gen_3.
2060  *
2061  *
2062  * FI: I do not understand why the precision of the write is not
2063  * exploited. We may need to use mwpl instead of wpl
2064  *
2065  */
2066  list twpl = points_to_cells_translation(wpl, binding, f);
2067  pt_end =
2069  // FI: I keep it temporarily for debugging purposes
2070  // gen_free_list(twpl);
2071 
2072  // FI: set_union is unsafe; the union of two consistent
2073  // points-to graph is not a consistent points-to graph
2074  pt_end = set_union(pt_end, pt_end, pt_gen_1);
2075  pips_assert("pt_end is consistent", consistent_points_to_set(pt_end));
2076  ifdebug(8) print_points_to_set("pt_end =",pt_end);
2077  /* Some check */
2078  stubs = points_to_set_to_module_stub_cell_list(f, pt_end, NIL);
2079  if(!ENDP(stubs)) {
2080  pips_internal_error("Translation failure in pt_end.\n");
2081  }
2082  points_to_graph_set(pt_end_f) = pt_end;
2083  }
2084  }
2085  else {
2086  pips_user_warning("Aliasing between arguments at line %d.\n"
2087  "We would have to create a new formal context "
2088  "and to restart the points-to analysis "
2089  "and to modify the IN and OUT data structures...\n"
2090  "Or use a simpler analysis, here an intraprocedural one.\n",
2092 
2093  pt_end_f = user_call_to_points_to_intraprocedural(c, pt_caller, el);
2094  }
2095  }
2096  else
2097  out_bottom_p = true;
2098  }
2099  else {
2100  // FI: I do not think we want this warning in general!
2101  pips_user_warning("Function \"%s\" has no side effect on its formal context "
2102  "via pointer variables.\n", entity_user_name(f));
2103  }
2104 
2105  /* This cannot be performed earlier because the points-to
2106  precondition of the caller may have to be enriched according to
2107  the formal context of the callee, or the effect computation is
2108  going to fail. */
2109  if(out_bottom_p) {
2110  clear_pt_map(pt_end_f);
2111  points_to_graph_bottom(pt_end_f) = true;
2112  }
2113 
2114  return pt_end_f;
2115 }
#define consistent_pt_map_p(s)
#define clear_pt_map(pt)
list load_body_effects(entity e)
if(!(yy_init))
Definition: genread_lex.c:1029
list points_to_set_to_module_stub_cell_list(entity m, set s, list osl)
void add_implicitly_killed_arcs_to_kill_set(set pt_kill, list wpl, set pt_caller, set pt_out_callee_filtered, set binding, entity f)
Initial comments: add arcs of set "pt_caller" to set "pt_kill" if their origin cells are not in the l...
set filter_formal_out_context_according_to_formal_in_context(set out, set in, list wpl, entity f)
If an address has not been written, i.e.
bool aliased_translation_p(list fpcl, set translation)
See if two cells in "fpcl" point toward the same location via the transitive closure of "translation"...
set compute_points_to_gen_set(set pt_out, list Written, set binding, entity f)
Translate the out set in the scope of the caller using the binding information, but eliminate irrelev...
static set lower_points_to_approximations_according_to_write_effects(set pt_end, list wpl)
It is partly a kill and partly a gen operation.
list points_to_cells_translation(list cl, set binding, entity f)
Allocate a new list with the translations of the cells in cl, when their translation make sense.
set new_filter_formal_context_according_to_actual_context(list fpcl, set pt_in, set pt_binded, set binding)
void points_to_translation_of_formal_parameters(list fpcl, list al, pt_map pt_in, set translation)
List al and fpcl are assumed consistent, and consistent with the formal parameter ranks.
list points_to_cells_exact_translation(list cl, set binding, entity f)
Allocate a new list with the translations of the cells in cl, when their translation make sense and i...
list certainly_written_pointers_set(list eff)
Filter out certainly written effects on pointers.
bool consistent_points_to_set(set)
make sure that set "s" does not contain redundant or contradictory elements
pt_map points_to_context_statement_in(void)
Definition: statement.c:127
#define points_to_list_bottom(x)
struct _newgen_struct_points_to_list_ * points_to_list

References add_implicitly_killed_arcs_to_kill_set(), aliased_translation_p(), call_arguments, call_function, certainly_written_pointers_set(), clear_pt_map, code_declarations, compute_points_to_binded_set(), compute_points_to_gen_set(), compute_points_to_kill_set(), consistent_points_to_set(), consistent_pt_map_p, db_get_memory_resource(), ENDP, entity_initial, entity_user_name(), f(), filter_formal_out_context_according_to_formal_in_context(), gen_full_copy_list(), ifdebug, load_body_effects(), lower_points_to_approximations_according_to_write_effects(), module_local_name(), new_filter_formal_context_according_to_actual_context(), new_simple_pt_map, NIL, pips_assert, pips_internal_error, pips_user_warning, points_to_cells_exact_translation(), points_to_cells_parameters(), points_to_cells_translation(), points_to_context_statement_in(), points_to_context_statement_line_number(), points_to_graph_bottom, points_to_graph_set, points_to_list_bottom, points_to_list_list, points_to_set_to_module_stub_cell_list(), points_to_translation_of_formal_parameters(), print_points_to_set(), set_assign_list(), set_difference(), set_undefined_p, set_union(), user_call_to_points_to_intraprocedural(), value_code, and written_pointers_set().

Referenced by user_call_to_points_to().

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

◆ user_call_to_points_to_interprocedural_binding_set()

set user_call_to_points_to_interprocedural_binding_set ( call  c,
pt_map  pt_caller 
)

Compute the binding relations in a complete interprocedural way: be as accurate as possible.

This piece of code has been copied from user_call_to_points_to_interprocedural(), which should be modularized...

Not much to do if both IN and OUT are empty, except if OUT is bottom (see below)

For the side effect on binding

set pt_in_filtered =

filter_formal_context_according_to_actual_context(fpcl,

pt_in,

pt_binded,

binding);

Parameters
pt_callert_caller

Definition at line 1835 of file interprocedural.c.

1837 {
1838  set binding = new_simple_pt_map();
1839  pips_assert("pt_caller is valid", !points_to_graph_bottom(pt_caller));
1840  pips_assert("pt_caller is consistent", consistent_pt_map_p(pt_caller));
1841  entity f = call_function(c);
1842  list al = call_arguments(c);
1844  list fpcl = points_to_cells_parameters(dl);
1845  points_to_list pts_to_in = (points_to_list)
1846  db_get_memory_resource(DBR_POINTS_TO_IN, module_local_name(f), true);
1847  list l_pt_to_in = gen_full_copy_list(points_to_list_list(pts_to_in));
1848  points_to_list pts_to_out = (points_to_list)
1849  db_get_memory_resource(DBR_POINTS_TO_OUT, module_local_name(f), true);
1850 
1851  list l_pt_to_out = gen_full_copy_list(points_to_list_list(pts_to_out));
1852 
1853  /* Not much to do if both IN and OUT are empty, except if OUT is
1854  bottom (see below) */
1855  if(!(ENDP(l_pt_to_out) && ENDP(l_pt_to_in))) {
1856  set pt_caller_s = points_to_graph_set(pt_caller);
1857  set pt_in = set_assign_list(new_simple_pt_map(), l_pt_to_in);
1858 
1859  bool success_p = false;
1860  set pt_binded = compute_points_to_binded_set(f, al, pt_caller_s, &success_p);
1861  ifdebug(8) print_points_to_set("pt_binded", pt_binded);
1862 
1863  if(success_p) {
1864  points_to_translation_of_formal_parameters(fpcl, al, pt_caller, binding);
1865  /* For the side effect on binding */
1866  /* set pt_in_filtered = */
1867  /* filter_formal_context_according_to_actual_context(fpcl, */
1868  /* pt_in, */
1869  /* pt_binded, */
1870  /* binding); */
1871  set pt_in_filtered =
1873  pt_in,
1874  pt_binded,
1875  binding);
1876  if(!set_undefined_p(pt_in_filtered))
1877  set_free(pt_in_filtered);
1878  else {
1879  // Part of the effects can/could be translated...
1881  semantics_user_warning("Call site in \"%s\" incompatible with callee \"%s\".", entity_user_name(m), entity_user_name(f));
1882  }
1883  }
1884  }
1885  return binding;
1886 }
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85

References call_arguments, call_function, code_declarations, compute_points_to_binded_set(), consistent_pt_map_p, db_get_memory_resource(), ENDP, entity_initial, entity_user_name(), f(), gen_full_copy_list(), get_current_module_entity(), ifdebug, module_local_name(), new_filter_formal_context_according_to_actual_context(), new_simple_pt_map, pips_assert, points_to_cells_parameters(), points_to_graph_bottom, points_to_graph_set, points_to_list_list, points_to_translation_of_formal_parameters(), print_points_to_set(), semantics_user_warning, set_assign_list(), set_free(), set_undefined_p, and value_code.

+ Here is the call graph for this function:

◆ user_call_to_points_to_intraprocedural()

pt_map user_call_to_points_to_intraprocedural ( call  c,
pt_map  pt_in,
list el   __attribute__(unused) 
)

Definition at line 2117 of file interprocedural.c.

2120 {
2121  pt_map pt_out = pt_in;
2122  list al = call_arguments(c);
2123 
2124  FOREACH(expression, arg, al) {
2125  list l_sink = expression_to_points_to_sources(arg, pt_out);
2126  set pt_out_s = points_to_graph_set(pt_out);
2127  SET_FOREACH(points_to, pts, pt_out_s) {
2128  FOREACH(cell, cel, l_sink) {
2129  cell source = points_to_source(pts);
2130  if(cell_equal_p(source, cel)) {
2131  cell sink = points_to_sink(pts);
2132  if(source_in_graph_p(sink, pt_out))
2133  remove_arcs_from_pt_map(pts, pt_out_s);
2134  }
2135  }
2136  }
2137  }
2138  return pt_out;
2139 }
bool source_in_graph_p(cell, points_to_graph)

References call_arguments, cell_equal_p(), expression_to_points_to_sources(), FOREACH, points_to_graph_set, points_to_sink, points_to_source, remove_arcs_from_pt_map(), SET_FOREACH, and source_in_graph_p().

Referenced by user_call_to_points_to(), and user_call_to_points_to_interprocedural().

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

◆ user_call_to_points_to_sinks()

list user_call_to_points_to_sinks ( call  c,
type et   __attribute__(unused),
pt_map in   __attribute__(unused),
bool  eval_p 
)

FI: I assume we do not need the eval_p parameter here.

No, we return either the return value, or the cells pointed by the return value.

This is a very convoluted way to return the return value...

Remove all arcs related to the return value of the callee. This never happens when eval_p is false because rvptl is NIL

FI: definitely the intraprocedural version

Definition at line 150 of file interprocedural.c.

154 {
155  bool type_sensitive_p = !get_bool_property("ALIASING_ACROSS_TYPES");
159  list sinks = NIL;
160  entity f = call_function(c);
161  // Interprocedural version
162  // Check if there is a return value at the level of POINTS TO OUT, if yes return its sink
163  if(!eval_p) {
164  // Return the return value
166  reference rvr = make_reference(rv, NIL);
167  cell rvc = make_cell_reference(rvr);
168  sinks = CONS(CELL, rvc, NIL);
169  }
172  const char* mn = entity_local_name(f);
173  // FI: Warning, they are not translated into the caller's frame...
174  // FI: An up-to-date version of in should be better
175  //points_to_list pts_to_out = (points_to_list)
176  //db_get_memory_resource(DBR_POINTS_TO_OUT, module_local_name(f), true);
177  //list l_pt_to_out = gen_full_copy_list(points_to_list_list(pts_to_out));
178  //set pt_out_callee = new_simple_pt_map();
179  //pt_out_callee = set_assign_list(pt_out_callee, l_pt_to_out);
180  // SET_FOREACH( points_to, pt, pt_out_callee) {
181  set in_s = points_to_graph_set(in);
182  list rvptl = NIL;
183  SET_FOREACH( points_to, pt, in_s) {
184  cell s = points_to_source(pt);
186  entity se = reference_variable(sr);
187  const char* sn = entity_local_name(se);
188  if( strcmp(mn, sn)==0) {
189  if(eval_p) {
190  cell sc = copy_cell(points_to_sink(pt));
191  sinks = gen_nconc(CONS(CELL, sc, NULL), sinks);
192  rvptl = CONS(POINTS_TO, pt, rvptl);
193  }
194  else {
195  /* This is a very convoluted way to return the return value... */
196  cell sc = copy_cell(points_to_source(pt));
197  reference scr = cell_any_reference(sc);
199  reference_indices(scr) = NIL;
200  sinks = gen_nconc(CONS(CELL, sc, NULL), sinks);
201  }
202  }
203  }
204  /* Remove all arcs related to the return value of the callee. This
205  never happens when eval_p is false because rvptl is NIL*/
206  FOREACH(POINTS_TO, rvpt, rvptl) {
207  remove_arc_from_simple_pt_map(rvpt, in_s);
208  }
209  gen_free_list(rvptl);
210  /* FI: definitely the intraprocedural version */
211  }
212  else {
213  if(type_sensitive_p) {
214  if(eval_p) {
217  }
218  else
220  }
221  else
223 
224  sinks = entity_to_sinks(ne);
225  }
226  return sinks;
227 }
entity entity_all_xxx_locations(string xxx)
return ANY_MODULE:xxx
entity entity_all_xxx_locations_typed(string xxx, type t)
FI->AM: the predicate entity_all_xxx_locations_typed_p() is missing...
#define ANYWHERE_LOCATION
list entity_to_sinks(entity)
sinks.c
Definition: sinks.c:72
void free_expressions(list el)
Free a list of expressions.
Definition: expression.c:4084
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
type ultimate_type(type)
Definition: type.c:3466

References ANYWHERE_LOCATION, call_function, CELL, cell_any_reference(), compute_basic_concrete_type(), CONS, copy_cell(), entity_all_xxx_locations(), entity_all_xxx_locations_typed(), entity_basic_concrete_type(), entity_local_name(), entity_to_sinks(), entity_undefined, f(), fast_interprocedural_points_to_analysis_p(), FOREACH, free_expressions(), function_to_return_value(), functional_result, gen_free_list(), gen_nconc(), get_bool_property(), interprocedural_points_to_analysis_p(), make_cell_reference(), make_reference(), NIL, POINTS_TO, points_to_graph_set, points_to_sink, points_to_source, reference_indices, reference_variable, remove_arc_from_simple_pt_map, SET_FOREACH, type_functional, type_to_pointed_type(), and ultimate_type().

Referenced by call_to_points_to_sinks().

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

◆ written_pointers_set()

list written_pointers_set ( list  eff)

Filter out written effects on pointers.

Parameters
effff

Definition at line 2609 of file interprocedural.c.

2609  {
2610  return generic_written_pointers_set(eff, false);
2611 }

References generic_written_pointers_set().

Referenced by user_call_to_points_to_fast_interprocedural(), and user_call_to_points_to_interprocedural().

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