PIPS
interprocedural.c
Go to the documentation of this file.
1 /*
2 
3  $Id: interprocedural.c 23412 2017-08-09 15:07:09Z irigoin $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 
25 /*
26  * This file contains functions used to compute points-to sets at user
27  * call sites.
28  *
29  * The argument pt_in is always modified by side-effects and returned.
30  */
31 
32 #include <stdlib.h>
33 #include <stdio.h>
34 
35 #include "genC.h"
36 #include "linear.h"
37 
38 #include "ri.h"
39 #include "effects.h"
40 
41 #include "misc.h"
42 #include "properties.h"
43 
44 #include "ri-util.h"
45 #include "effects-util.h"
46 
47 #include "effects-generic.h"
48 
49 #include "pipsdbm.h"
50 
51 #include "prettyprint.h" // for debugging
52 
53 #include "points-to.h"
54 
55 // FI: just to access semantics_user_warning()
56 #include "transformer.h"
57 #include "semantics.h"
58 
59 // FI: this piece of code has been developed assuming that pt_map was
60 // a synonym for the set type
61 // FI: Not a good idea, to many interfaces with functions from other files
62 // #define pt_map set
63 
64 /* Transform a list of parameters of type "entity" to a list of cells
65  *
66  * The list is not sorted. It is probably a reversed list.
67  */
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 }
84 
85 
86 /* Transform a list of arguments of type "expression" to a list of cells
87  *
88  * The list is not sorted. It is probably a reversed list.
89  */
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 }
102 
103 
104 
105 /* FI: limited to the interprocedural option */
107  points_to_graph pt_in,
108  list el) // effect list
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 }
145 
146 /* FI: I assume we do not need the eval_p parameter here. No, we
147  * return either the return value, or the cells pointed by the return
148  * value.
149  */
151  type et __attribute__ ((unused)),
152  pt_map in __attribute__ ((unused)),
153  bool eval_p)
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 }
228 
229 // FI: why is this function located in interprocedural.c?
230 // Because it is used only in this file...
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 }
251 
252 /*Compute the points to relations in a fast interprocedural way
253  *
254  * "c" is the call site
255  *
256  * "pt_in" is the points-to information available before the call site
257  * is executed.
258  *
259  * "csel" is the call site effect list
260  *
261  */
263  pt_map pt_in,
264  list csel __attribute__ ((unused)))
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 }
345 ␌
346 /* This function looks for successors of elements of list "fcl" both
347  * in points-to relations "pt_in" and "pt_binded". Update the formal
348  * context defined by "pt_binded" on demand as necessary according to
349  * "pt_in", update the translation mapping "binding" according to the
350  * new pairs found, and go down recursively with a new list of
351  * constant paths, "nfcl", the possible successors in the formal
352  * context of the callee of elements in "fcl" when possible. In fact,
353  * the elements in "nfcl" must be pointers and are not necessarily the
354  * successors of elements of "fcl", but pointers contained in them.
355  *
356  * This function is very similar to
357  * filter_formal_context_according_to_actual_context(), but a little
358  * bit more tricky. Amira Mensi unified both in her own version, but
359  * the unification makes the maintenance more difficult.
360  */
361 bool
363  set pt_in,
364  set pt_binded,
365  set binding,
366  set filtered)
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 }
519 ␌
520 /* We have to handle constant strings such as "Hello!" and not to
521  * forget functional parameters or other types. Basically, type "t" is
522  * returned unchanged, unless "t" is a functional type "void->string".
523  *
524  * The initial implementation of this function used the cell "ac" and the
525  * variable "a" whose type is sought and was safer:
526  *
527  * reference ar = cell_any_reference(ac);
528  * entity a = reference_variable(ar);
529  * if(constant_string_entity_p(a))
530  * nt = ...
531  *
532  * Any function of type "void->string" is considered a "string"
533  * object. Let's hope it is ok in the points-to environment. Else, an
534  * additional parameter must be passed.
535  *
536  * This function is located in the points-to library because it is
537  * where it is useful. It would be even more useful if it returned a
538  * "char *" or a "char[]", but this would imply a type allocation. As
539  * it is, no new type is allocated.
540  *
541  * To be fully effective, the argument must be a basic concrete type.
542  */
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 }
555 ␌
556 /* Filter "pt_in" according to "pt_binded". For instance, a
557  * formal parameter can point to NULL in "pt_in" only if it
558  * also points to NULL in "pt_binded". In the same way, a formal
559  * parameter can point to a points-to stub in "pt_in" only if
560  * it points to a non-NULL target in "pt_binded". Also, a formal
561  * parameter cannot points exactly to UNDEFINED in "pt_binded" as
562  * it would be useless (not clear if we can remove such an arc
563  * when it is a may arc...). Finally, each formal parameter must
564  * still point to something.
565  *
566  * The context of the caller may be insufficiently developped because
567  * its does not use explictly a pointer that is a formal parameter for
568  * it. For instance:
569  *
570  * foo(int ***p) {bar(int ***p);}
571  *
572  * The formal context of "foo()" must be developped when the formal
573  * context of "bar()" is imported. For instance, *p, **p and ***p may
574  * be accessed in "bar()", generating points-to stub in "bar". Similar
575  * stubs must be generated here for "foo()" before the translation can
576  * be performed.
577  *
578  * This is also true for global variables. pt_in may contain arcs that
579  * should exist in pt_binded, and hence pt_caller. It may also contain
580  * arcs that deny the existence of some arcs in pt_caller.
581  */
583  set pt_in,
584  set pt_binded,
585  set binding)
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 }
799 ␌
801 (cell fc, cell ac, approximation ap, set pt_in, set pt_binded, set binding, set filtered);
802 
803 /* Handle constant cells such as NULL and UNDEFINED (nowhere) in "fcl"
804  * and "acl"
805  *
806  * Update "fcl" is needed, as well as "pt_binded" and "filtered", a
807  * subset of "pt_in".
808  */
809 static bool merge_actual_and_formal_sinks(cell fc, list *pfcl, cell ac, list * pacl, set pt_in, set pt_binded, set filtered)
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 }
878 
879 /* fc and ac are two pointer cells with same or compatible pointer type
880  *
881  * Update binding and filtered according to their sinks.
882  *
883  * For instance, if "ac" only points to the undefined cells, the call
884  * site is not consistent because "fc" is assumed by the caller to
885  * point to a defined cell. "ok_p" is set to false.
886  *
887  * if "fc" points to NULL in pt_in, but "ac" does not point to NULL,
888  * the corresponding arc is not copied in "filtered".
889  *
890  * if "fc" points to "nfc" in "pt_in" and "ac" points to "nac" in
891  * "pt_binded", then arc "fc->nfc" is copied in "pt_binded" and arc
892  * "nfc->nac" is added in "binding".
893  *
894  * No optimization in number of scans for the different sets
895 */
897 (cell fc, cell ac, approximation ap, set pt_in, set pt_binded, set binding, set filtered)
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 }
964 
965 /* The code is derived from
966  * generic_points_to_cell_to_useful_pointer_cell() with no filtering
967  * and a direct processing of the pairs of pointers obtained.
968  *
969  * cells fc and ac are assumed type compatible.
970 */
972 (cell fc, cell ac, approximation ap, set pt_in, set pt_binded, set binding, set filtered)
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 }
1038 
1040  set pt_in,
1041  set pt_binded,
1042  set binding)
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 }
1251 ␌
1252 /* If an address has not been written, i.e. it is not in list "wpl",
1253  * then the points-to information is the intersection of the in and
1254  * out information.
1255  *
1256  * The set "in" may be modified by side effect. A new set,
1257  * "filtered_out" is computed. By definition, they are equivalent for
1258  * the addresses that are not in list "wpl".
1259  *
1260  * The arcs are shared by the different sets. But I may allocate new
1261  * ones: yet another potential memory leak...
1262  */
1264 (set out, set in, list wpl, entity f)
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 }
1364 ␌
1366  cell ac,
1367  approximation a,
1368  type st,
1369  set translation)
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 }
1432 
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 }
1480 
1481 /* List al and fpcl are assumed consistent, and consistent with the
1482  formal parameter ranks. */
1484  list al,
1485  pt_map pt_in,
1486  set translation)
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 }
1616 ␌
1617 /* Initial comments: add arcs of set "pt_caller" to set "pt_kill" if
1618  * their origin cells are not in the list of written pointers "wpl"
1619  * but is the origin of some exact arc in
1620  * "pt_out_callee_filtered". This is beneficial when "pt_out" is more
1621  * precise than "pt_caller" because of a free or a test. This is
1622  * detrimental when "pt_caller" is more precise than
1623  * "pt_out_callee_filtered" because the intraprocedural analysis of
1624  * the callee had to assume a possible NULL pointer that did not
1625  * really exist (see Mensi.sub/struct_inter03.c). So it would be
1626  * better to compute the intersection of "pt_caller" and
1627  * "translation(pt_out, binding)" and to kill all arcs in "pt_caller"
1628  * minus this intersection... if they are related in some way to the
1629  * callee... Some more thinking needed.
1630  *
1631  * Equations retrieved from the C code
1632  *
1633  * K = { c | \exits pt c=source(pt) !\in Written
1634  * ^ |translation(source(pt), binding, f)|==1
1635  * ^ atomic(translation(source(pt), binding, f) }
1636  *
1637  * pt_kill = {pt in pt_caller | \exists c \in K binding(c)==source(pt)}
1638  *
1639  * K is a set of cells defined in the frame of the callee and pt_kill
1640  * a set of points-to defined in the frame of the caller.
1641  *
1642  * Examples:
1643  *
1644  * Indirect free of a pointed cell
1645  *
1646  * "main() {p = malloc(); * my_free(p);}" with "my_free(int * p) {free(p);}".
1647  *
1648  * p->heap in pt_caller must be removed from pt_end, hence p->heap
1649  * belongs to pt_kill
1650  *
1651  * Other possibilities must be linked to tests and executions errors.
1652  *
1653  * void foo(int * ap) {bar(ap);}
1654  *
1655  * void bar(int * fp) { *p = 1;}
1656  *
1657  * As a result ap->_ap_1, EXACT because ap->NULL has been killed
1658  *
1659  * void bar(int * fp) {if(fp==NULL) exit(1); return;}
1660  *
1661  * The result should be the same as above.
1662  */
1664  list wpl,
1665  set pt_caller,
1666  set pt_out_callee_filtered,
1667  set binding,
1668  entity f)
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 }
1701 ␌
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 }
1732 
1733 /* See if two cells in "fpcl" point toward the same location via the
1734  transitive closure of "translation". */
1735 bool aliased_translation_p(list fpcl, set translation)
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 }
1799 ␌
1800 /* It is partly a kill and partly a gen operation.
1801  *
1802  * FI: the very same function must exist for pointer assignments I guess
1803  */
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 }
1828 ␌
1829 /* Compute the binding relations in a complete interprocedural way:
1830  * be as accurate as possible.
1831  *
1832  * This piece of code has been copied from
1833  * user_call_to_points_to_interprocedural(), which should be modularized...
1834  */
1836  pt_map pt_caller)
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 }
1887 ␌
1888 /* Compute the points-to relations in a complete interprocedural way:
1889  * be as accurate as possible.
1890  *
1891  */
1893  pt_map pt_caller)
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 }
2116 
2118  pt_map pt_in,
2119  list el __attribute__ ((unused)))
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 }
2140 
2141 /* Translate the "out" set into the scope of the caller
2142  *
2143  * Shouldn't it be the "written" list that needs to be translated?
2144  *
2145  */
2146 set compute_points_to_kill_set(list written_must_translated,
2147  set pt_caller,
2148  set binding __attribute__ ((unused)))
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 }
2203 
2204 /* Compute the list of cells that correspond to cell "sr1" according
2205  * to the translation mapping "bm" when function "f" is called.
2206  *
2207  * The check with rv may be useless, for instance when a sink cell is
2208  * checked, as it is impossible (in C at least) to points toward the
2209  * return value.
2210  */
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 }
2278 
2279 /* Allocate a new list with the translations of the cells in cl, when
2280  * their translation make sense. Effects on copied parameters are
2281  * discarded.
2282  *
2283  * If exact_p is required, translate only cells that can be translated
2284  * exactly.
2285  */
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 }
2313 
2314 /* Allocate a new list with the translations of the cells in cl, when
2315  * their translation make sense. Effects on copied parameters are
2316  * discarded.
2317  */
2319 {
2320  return generic_points_to_cells_translation(cl, binding, f, false);
2321 }
2322 
2323 /* Allocate a new list with the translations of the cells in cl, when
2324  * their translation make sense and is unique (one-to-one
2325  * mapping). Effects on copied parameters are discarded.
2326  */
2328 {
2329  return generic_points_to_cells_translation(cl, binding, f, true);
2330 }
2331 
2332 /* Translate the out set in the scope of the caller using the binding
2333  * information, but eliminate irrelevant arcs using Written and the
2334  * type of the source.
2335  *
2336  * This is pt_gen_1 in Amira Mensi's dissertation.
2337  *
2338  * Also, pay attention to translation errors because they are related
2339  * to programming bugs, such as pointer arithmetic applied to pointers
2340  * to scalar.
2341  */
2343  list Written,
2344  set binding,
2345  entity f)
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 }
2491 
2492 
2493 /* Recursively find all the arcs, "ai", starting from the argument
2494  * "c1" using "in", find all the arcs, "aj", starting from the
2495  * parameter "c2" using "pt_binded", map each node "ai" to its
2496  * corresponding "aj" and store the "ai->aj" arc in a new set, "bm".
2497  *
2498  * "pt_binded" contains the correspondance between formal and actual
2499  * parameters, e.g. "fp->ap", with some information about the possible
2500  * approximations because one formal parameter can points toward
2501  * several actual memory locations of the caller.
2502  *
2503  * "in" contains the formal context of the callee, as it stands at its
2504  * entry point (DBR_POINTS_TO_IN).
2505  *
2506  * "bm" is the binding relationship between references of the formal
2507  * context of the callees towards addresses of the caller. For
2508  * instance, when function "void foo(int ** fp)" is called as "ap=&q;
2509  * foo(ap);", bm = {(_ap_1, q)}.
2510  *
2511  * See Amira Mensi's PhD dissertation, chapter about interprocedural analysis
2512  */
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 }
2588 
2589 /* Filter out written effects on pointers */
2590 static list generic_written_pointers_set(list eff, bool exact_p)
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 }
2607 
2608 /* Filter out written effects on pointers */
2610  return generic_written_pointers_set(eff, false);
2611 }
2612 
2613 /* Filter out certainly written effects on pointers */
2615  return generic_written_pointers_set(eff, true);
2616 }
2617 
2618 /* For each actual argument "r" and its corresponding formal one "f",
2619  * create the assignment "f = r;" and then compute the points-to set
2620  * "s" generated by the assignment. The result is the union of
2621  * "pt_caller" and "s".
2622  */
2624  list real_args,
2625  set pt_caller,
2626  bool * success_p)
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 }
2766 
2767 
2768 /* Apply points_to_binding_arguments() to each pair (, complete the
2769  * process of binding each element of "in" to its corresponding memory
2770  * address at the call site. Necessary to translate the fields of structures.
2771  *
2772  * "args": list of formal parameters of some callee
2773  *
2774  * "in": points-to in of the callee
2775  *
2776  * "pt_binded": points-to from formal to actual parameters for a specific call site
2777  *
2778  * A new set is allocated.
2779  */
2780 set points_to_binding(list args, set in, set pt_binded)
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 }
2820 
2821 /* Add cells referencing a points-to stub found in parameter "s" are
2822  * copied and added to list "osl".
2823  *
2824  * The stubs are returned as cells not as entities.
2825  *
2826  * New cells are allocated. No sharing is created between parameter
2827  * "s" and result "sl".
2828  */
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 }
2854 
2856 {
2858 }
2859 
2861 {
2862  return generic_points_to_set_to_stub_cell_list(m, s, osl);
2863 }
2864 
2865 /* Let "pt_binded" be the results of assignments of actual arguments
2866  * to formal arguments (see compute_points_to_binded_set()).
2867  *
2868  * Let "pt" be a points-to arc in "pt_binded".
2869  *
2870  * Find for the source of p its corresponding alias, which means
2871  * finding another source that points to the same location.
2872  */
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 }
float a2sf[2] __attribute__((aligned(16)))
USER generates a user error (i.e., non fatal) by printing the given MSG according to the FMT.
Definition: 3dnow.h:3
cell make_cell_reference(reference _field_)
Definition: effects.c:293
void free_cell(cell p)
Definition: effects.c:249
approximation make_approximation_exact(void)
Definition: effects.c:185
approximation copy_approximation(approximation p)
APPROXIMATION.
Definition: effects.c:132
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
void free_approximation(approximation p)
Definition: effects.c:135
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
reference copy_reference(reference p)
REFERENCE.
Definition: ri.c:2047
#define remove_arc_from_simple_pt_map(a, s)
#define add_arc_to_simple_pt_map(a, s)
#define consistent_pt_map_p(s)
#define clear_pt_map(pt)
#define new_simple_pt_map()
static FILE * out
Definition: alias_check.c:128
static bool written
Definition: alias_check.c:512
bool stub_entity_of_module_p(entity s, entity m)
bool entity_stub_sink_p(entity e)
test if an entity is a stub sink for a formal parameter e.g.
bool cell_typed_anywhere_locations_p(cell c)
test if a cell is the bottom of the lattice
bool entity_typed_anywhere_locations_p(entity e)
Test if an entity is the bottom of the lattice.
entity entity_anywhere_locations()
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...
bool entity_anywhere_locations_p(entity e)
test if an entity is the bottom of the lattice
void const char const char const int
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...
bool constant_string_entity_p(entity e)
Definition: constant.c:356
list load_body_effects(entity e)
list load_summary_effects(entity e)
FI->FI, FI->BC: these two functions should be moved into effects-util or effects-simple.
bool effect_pointer_type_p(effect)
list effects_write_effects(list)
#define ANYWHERE_LOCATION
bool cell_points_to_null_sink_in_set_p(cell, set)
Definition: points_to.c:898
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
bool location_entity_p(entity)
Definition: locations.c:349
bool cell_equal_p(cell, cell)
CELLS.
Definition: effects.c:1226
type points_to_reference_to_concrete_type(reference)
Definition: type.c:685
reference cell_any_reference(cell)
API for reference.
Definition: effects.c:77
cell points_to_cell_add_field_dimension(cell, entity)
Functions about points-to cells - There is no cell.c file.
Definition: effects.c:1444
void points_to_cell_add_unbounded_subscripts(cell)
Definition: effects.c:1632
type points_to_cell_to_concrete_type(cell)
Definition: type.c:676
bool cell_points_to_nowhere_sink_in_set_p(cell, set)
Definition: points_to.c:845
bool points_to_cell_equal_p(cell, cell)
Definition: points_to.c:916
reference cell_to_reference(cell)
FI: probably to be moved elsewhere in ri-util.
Definition: effects.c:1326
bool anywhere_cell_p(cell)
Is it an anywhere cell?
Definition: effects.c:367
list recursive_cell_to_pointer_cells(cell)
Definition: effects.c:1680
void points_to_cell_complete_with_zero_subscripts(cell)
Definition: effects.c:1626
bool cell_entity_equal_p(cell, cell)
Definition: effects.c:1234
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
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
bool generic_atomic_points_to_cell_p(cell, bool)
Is it a unique concrete memory location?
Definition: points_to.c:452
bool nowhere_cell_p(cell)
Target of an undefined pointer.
Definition: effects.c:455
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
bool points_to_cell_in_list_p(cell, list)
Definition: points_to.c:117
bool atomic_points_to_cell_p(cell)
Is it a unique concrete memory location?
Definition: points_to.c:423
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 null_cell_p(cell)
Definition: effects.c:466
bool heap_cell_p(cell)
Any heap cell, more or less abstract or typed.
Definition: effects.c:420
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
#define cell_undefined_p(x)
Definition: effects.h:431
#define cell_undefined
Definition: effects.h:430
#define approximation_exact_p(x)
Definition: effects.h:369
#define approximation_may_p(x)
Definition: effects.h:363
#define CELL(x)
CELL.
Definition: effects.h:424
#define approximation_must_p(x)
Definition: effects.h:366
#define approximation_undefined
Definition: effects.h:326
#define effect_approximation(x)
Definition: effects.h:644
#define effect_cell(x)
Definition: effects.h:640
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
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
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
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
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
void gen_remove_once(list *pl, const void *o)
Remove the first occurence of o in list pl:
Definition: list.c:691
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#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
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
gen_chunk gen_nth(int n, const list l)
to be used as ENTITY(gen_nth(3, l))...
Definition: list.c:710
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
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
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
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 debug_on(env)
Definition: misc-local.h:157
#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_user_warning
Definition: misc-local.h:146
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
#define debug_off()
Definition: misc-local.h:160
#define pips_user_error
Definition: misc-local.h:147
#define HASH_MAP(k, v, code, ht)
Definition: newgen_hash.h:60
@ hash_pointer
Definition: newgen_hash.h:32
#define same_string_p(s1, s2)
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_assign_list(set, const list)
assigns a list contents to a set all duplicated elements are lost
Definition: set.c:474
set set_del_element(set, const set, const void *)
Definition: set.c:265
#define set_undefined
Definition: newgen_set.h:48
set set_assign(set, const set)
Assign a set with the content of another set.
Definition: set.c:129
set set_difference(set, const set, const set)
Definition: set.c:256
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
void set_free(set)
Definition: set.c:332
set set_clear(set)
Assign the empty set to s s := {}.
Definition: set.c:326
set set_union(set, const set, const set)
Definition: set.c:211
@ set_private
Definition: newgen_set.h:45
#define set_undefined_p(s)
Definition: newgen_set.h:49
set set_add_element(set, const set, const void *)
Definition: set.c:152
struct cons * list
Definition: newgen_types.h:106
int(* gen_cmp_func_t)(const void *, const void *)
Definition: newgen_types.h:114
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
bool interprocedural_points_to_analysis_p()
Definition: passes.c:550
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
bool fast_interprocedural_points_to_analysis_p()
Definition: passes.c:555
list points_to_cell_to_useful_pointer_cells(cell c, set pts)
Definition: expression.c:1905
list points_to_cells_to_pointer_cells(list pl)
Convert cells in l into derived pointer cells when possible.
Definition: expression.c:1917
pt_map assignment_to_points_to(expression lhs, expression rhs, pt_map pt_in)
Definition: expression.c:1163
static list generic_written_pointers_set(list eff, bool exact_p)
Filter out written effects on pointers.
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.
list points_to_set_to_stub_cell_list(set s, list osl)
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
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
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 ...
list translation_transitive_closure(cell c, set translation)
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.
void remove_arcs_from_pt_map(points_to pts, set pt_out)
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...
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...
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 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".
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 written_pointers_set(list eff)
Filter out written effects on pointers.
list user_call_to_points_to_sinks(call c, type et __attribute__((unused)), pt_map in __attribute__((unused)), bool eval_p)
FI: I assume we do not need the eval_p parameter here.
static bool 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...
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.
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)
bool points_to_translation_mapping_is_typed_p(set translation)
void points_to_translation_of_struct_formal_parameter(cell fc, cell ac, approximation a, type st, 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.
points_to_graph user_call_to_points_to(call c, points_to_graph pt_in, list el)
FI: limited to the interprocedural option.
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.
list points_to_cells_pointer_arguments(list al)
Transform a list of arguments of type "expression" to a list of cells.
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)))
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,...
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".
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 "...
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...
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.
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".
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 ...
list expression_to_points_to_sinks(expression, pt_map)
The returned list contains cells used in "in".
Definition: sinks.c:1795
points_to create_stub_points_to(cell, type, bool)
bool source_subset_in_set_p(cell, set)
test if a cell "source" appears as a source in a set of points-to
bool source_in_graph_p(cell, points_to_graph)
list points_to_sources_to_effective_sinks(list, pt_map, bool)
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
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_some_sinks(cell, pt_map, bool)
May not retrieve all sinks of the source.
_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 ...
bool statement_points_to_context_defined_p(void)
Definition: statement.c:145
list points_to_source_to_sinks(cell, pt_map, bool)
Build the sinks of source "source" according to the points-to graphs.
bool source_in_set_p(cell, set)
test if a cell appear as a source in a set of points-to
list points_to_source_to_any_sinks(cell, pt_map, bool)
Retrieve all possible sinks of the source.
bool points_to_compare_ptr_cell(const void *, const void *)
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 entity_to_sinks(entity)
sinks.c
Definition: sinks.c:72
list any_source_to_sinks(cell, pt_map, bool)
Generalization of source_to_sinks().
void print_points_to_set(string, set)
string points_to_cell_name(cell)
Create a string which is the cell reference in C syntax.
bool consistent_points_to_set(set)
make sure that set "s" does not contain redundant or contradictory elements
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
bool arc_in_points_to_set_p(points_to, set)
Check if points-to arc "spt" belongs to points-to set "pts".
int points_to_context_statement_line_number(void)
Definition: statement.c:120
string points_to_cell_to_string(cell)
bool points_to_compare_cell(cell, cell)
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
pt_map points_to_context_statement_in(void)
Definition: statement.c:127
#define points_to_approximation(x)
#define points_to_sink(x)
#define points_to_list_list(x)
#define points_to_graph_bottom(x)
#define POINTS_TO(x)
POINTS_TO.
#define points_to_list_bottom(x)
struct _newgen_struct_points_to_list_ * points_to_list
#define points_to_graph_set(x)
#define points_to_source(x)
string reference_to_string(reference r)
Definition: expression.c:87
#define print_points_to_cells(x)
Definition: print.c:379
string type_to_full_string_definition(type)
type.c
Definition: type.c:45
static hash_table pl
properties are stored in this hash table (string -> property) for fast accesses.
Definition: properties.c:783
static int tc
Internal variables
Definition: reindexing.c:107
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
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
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
entity entity_to_module_entity(entity e)
Find the enclosing module of an entity.
Definition: entity.c:2053
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
bool zero_expression_p(expression e)
Definition: expression.c:1217
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_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
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
void free_expressions(list el)
Free a list of expressions.
Definition: expression.c:4084
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
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
entity function_to_return_value(entity m)
Returns the entity rv that carries the value returned by module m, when m is not a C void function or...
Definition: module.c:509
bool char_star_constant_function_type_p(type)
Beware of typedefs.
Definition: type.c:5787
type ultimate_type(type)
Definition: type.c:3466
bool array_type_p(type)
Definition: type.c:2942
bool array_of_pointers_type_p(type)
Definition: type.c:3025
bool scalar_type_p(type)
Definition: type.c:2955
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_equal_p(type, type)
Definition: type.c:547
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
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 type_structurally_equal_p(type, type)
Type t1 and t2 are equal if their basic concrete components are equal.
Definition: type.c:586
bool formal_parameter_p(entity)
Definition: variable.c:1489
list struct_type_to_fields(type)
Definition: type.c:5798
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 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
type compute_basic_concrete_type(type)
computes a new type which is the basic concrete type of the input type (this new type is not stored i...
Definition: type.c:3556
bool overloaded_type_p(type)
Returns true if t is a variable type with a basic overloaded.
Definition: type.c:2666
bool string_type_p(type)
Definition: type.c:2854
bool array_of_struct_type_p(type)
Definition: type.c:3133
bool char_type_p(type)
return true whether ‘t’ is a char or an unsigned char
Definition: type.c:2877
entity find_ith_parameter(entity, int)
Definition: util.c:93
#define type_functional_p(x)
Definition: ri.h:2950
#define formal_offset(x)
Definition: ri.h:1408
#define functional_result(x)
Definition: ri.h:1444
#define parameter_type(x)
Definition: ri.h:1819
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define type_functional(x)
Definition: ri.h:2952
#define entity_storage(x)
Definition: ri.h:2794
#define code_declarations(x)
Definition: ri.h:784
#define storage_formal(x)
Definition: ri.h:2524
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define entity_undefined_p(x)
Definition: ri.h:2762
#define entity_undefined
Definition: ri.h:2761
#define functional_parameters(x)
Definition: ri.h:1442
#define PARAMETER(x)
PARAMETER.
Definition: ri.h:1788
#define reference_indices(x)
Definition: ri.h:2328
#define value_code(x)
Definition: ri.h:3067
#define type_varargs_p(x)
Definition: ri.h:2953
#define type_undefined
Definition: ri.h:2883
#define call_arguments(x)
Definition: ri.h:711
#define entity_initial(x)
Definition: ri.h:2796
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
#define semantics_user_warning
s1
Definition: set.c:247
#define ifdebug(n)
Definition: sg.c:47
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
The structure used to build lists in NewGen.
Definition: newgen_list.h:41