PIPS
sinks.c
Go to the documentation of this file.
1 /*
2 
3  $Id: sinks.c 23415 2017-08-14 22:02:20Z 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
27  * the expression level.
28  *
29  * Most important function:
30  *
31  * list expression_to_points_to_cells(expression lhs, pt_map in, bool
32  * eval_p, bool constant_p)
33  *
34  * The purpose of this function and the functions in this C file is to
35  * return a list of memory cells addressed when evaluated in the
36  * memory context "in".
37  *
38  * If eval_p is false, possible addresses for "lhs" are returned.
39  *
40  * If eval_p is true, possible addresses for "*lhs" are returned.
41  *
42  * The memory context "in" may be modified by side-effects if new
43  * memory locations have to be added, for instance when formal or
44  * global pointers are dereferenced.
45  *
46  * The similar functions in Amira's implementation are located in
47  * constant-path-utils.c.
48  */
49 
50 #include <stdlib.h>
51 #include <stdio.h>
52 #include "genC.h"
53 #include "linear.h"
54 
55 #include "ri.h"
56 #include "ri-util.h"
57 
58 #include "prettyprint.h" // For debugging
59 
60 #include "effects.h"
61 #include "effects-util.h"
62 #include "misc.h"
63 #include "properties.h"
64 #include "bootstrap.h" // MakeIOFileArray
65 
66 #include "points-to.h"
67 
68 /* allocate a new list of sinks with one element, abstract or concrete, e.
69  *
70  * No check on e for the time being
71  */
73 {
74  reference nr = make_reference(e, NIL);
75  cell nc = make_cell_reference(nr);
76  list sinks = CONS(CELL, nc, NIL);
77  return sinks;
78 }
79 
81 {
82  reference nr = make_reference(e, NIL);
83  cell nc = make_cell_reference(nr);
84  return nc;
85 }
86 
88 {
89  /* The null location is not typed. The impact on dependence test is
90  not clear. */
92  return entity_to_sinks(ne);
93 }
94 
96 {
98  cell c = entity_to_cell(ne);
99  return c;
100 }
101 
103 {
104  entity ne;
105  if(type_undefined_p(t))
106  ne = entity_all_locations();
107  else
109  return entity_to_sinks(ne);
110 }
111 ␌
112 list call_to_points_to_sinks(call c, type et, pt_map in, bool eval_p, bool constant_p)
113 {
114  list sinks = NIL;
115  entity f = call_function(c);
116  //list al = call_arguments(c);
117  value v = entity_initial(f);
118  tag tt = value_tag(v);
119  switch (tt) {
120  case is_value_code:
121  sinks = user_call_to_points_to_sinks(c, et, in, eval_p);
122  break;
123  case is_value_symbolic:
124  break;
125  case is_value_constant: {
126  constant zero = value_constant(v);
127  if(constant_int_p(zero) && constant_int(zero)==0)
128  sinks = points_to_null_sinks(); // et could be used according to PJ
129  else {
131  if(string_type_p(t)) {
132  // FI: we could generate a special location for each string
133  // FI: we could reuse the constant function
134  // FI: we could use the static area of the current module
135  // FI: we can always use anywhere...
136  // FI: does not depend oneval_p... involution...
138  cell c = make_cell_reference(r);
139  sinks = CONS(CELL, c, NIL);
140  }
141  else {
142  sinks = points_to_anywhere_sinks(t);
143  }
144  }
145  }
146  break;
147  case is_value_unknown:
148  pips_internal_error("function %s has an unknown value\n",
149  entity_name(f));
150  break;
151  case is_value_intrinsic:
152  // FI: here is the action, &p, *p, p->q, p.q, etc...
153  sinks = intrinsic_call_to_points_to_sinks(c, in, eval_p, constant_p);
154  break;
155  default:
156  pips_internal_error("unknown value tag %d\n", tt);
157  break;
158  }
159 
160  /* No check, but all elements of sinks should be of a type
161  compatible with type "et". */
162 
163  return sinks;
164 }
165 
166 /*
167  * Sinks: "malloc(exp)", "p", "p++", "p--", "p+e", "p-e" , "p=e", "p, q, r",
168  * "p->q", "p.q",...
169  *
170  * "(cast) p" is not an expression.
171  */
173  bool constant_p)
174 {
175  list sinks = NIL;
176  entity f = call_function(c);
177  list al = call_arguments(c);
178  int nary = (int) gen_length(al);
179 
180  // You do not know the number of arguments for the comma operator
181  if(ENTITY_COMMA_P(f)) {
182  expression e = EXPRESSION(CAR(gen_last(al)));
183  sinks = expression_to_points_to_sinks(e, in);
184  }
185  else {
186  // Switch on number of arguments to avoid long switch on character
187  // string or memoizing of intrinsics
188  switch(nary) {
189  case 0:
190  pips_internal_error("Probably a constant or a symbolic. Not handled here\n");
191  break;
192  case 1:
193  sinks = unary_intrinsic_call_to_points_to_sinks(c, in, eval_p, constant_p);
194  break;
195  case 2:
196  sinks = binary_intrinsic_call_to_points_to_sinks(c, in, eval_p);
197  break;
198  case 3:
200  break;
201  default:
203  break;
204  }
205  }
206 
207  return sinks;
208 }
209 
210 /*
211  * malloc, &p, *p, p++, p--, ++p, --p,
212  *
213  * Do not create any sharing between elements of in and elements part
214  * of the returned list, sinks.
215  */
217 {
218  entity f = call_function(c);
219  list al = call_arguments(c);
220  expression a = EXPRESSION(CAR(al));
221  list sinks = NIL;
222  pips_assert("One argument", gen_length(al)==1);
223  // pips_internal_error("Not implemented for %p and %p\n", c, in);
224  if (ENTITY_MALLOC_SYSTEM_P(f)) {
225  sinks = malloc_to_points_to_sinks(a, in);
226  }
227  else if (ENTITY_FREE_SYSTEM_P(f)) {
228  // FI: should be useless because free() returns void
229  sinks = CONS(CELL, make_nowhere_cell(), NIL);
230  }
231  else if(ENTITY_ADDRESS_OF_P(f)) {
232  // sinks = expression_to_constant_paths(statement_undefined, a, in);
233  if(eval_p) {
234  // sinks = expression_to_points_to_sources(a, in);
235  sinks = expression_to_points_to_cells(a, in, false, constant_p);
236  }
237  else {
238  // It is not possible in general to associate a reference to &e
239  // However, we might think of transforming &a[i][j] into a[i]
240  // and &a[0] into a...
241  sinks=NIL;
242  }
243  }
244  else if(ENTITY_DEREFERENCING_P(f)) {
245  if(pt_map_undefined_p(in)) {
247  cell c = make_anywhere_cell(t);
248  sinks = CONS(CELL, c, NIL);
249  }
250  else {
251  // FI: I do not understand why eval_p is only used for dereferencing...
252  // struct18.c sensitive to the test below
253  if(eval_p)
254  sinks = dereferencing_to_sinks(a, in, eval_p);
255  else {
256  sinks = dereferencing_to_sinks(a, in, eval_p);
257  // sinks = expression_to_points_to_sources(a, in);
258  }
259  }
260  }
261  else if(ENTITY_PRE_INCREMENT_P(f)) {
262  if(eval_p) {
263  sinks = expression_to_points_to_sinks(a, in);
264  // FI: this has already been done when the side effects are exploited
265  //expression one = int_to_expression(1);
266  //offset_cells(sinks, one);
267  //free_expression(one);
268  }
269  }
270  else if(ENTITY_PRE_DECREMENT_P(f)) {
271  if(eval_p)
272 {
273  sinks = expression_to_points_to_sinks(a, in);
274  //expression m_one = int_to_expression(-1);
275  //offset_cells(sinks, m_one);
276  //free_expression(m_one);
277  }
278  }
280  //sinks = expression_to_constant_paths(statement_undefined, a, in);
281  // arithmetic05: "q=p++;" p++ must be evaluated
282  //list sources = expression_to_points_to_sinks(a, in);
283  //if(gen_length(sources)==1) {
284  //cell source = CELL(CAR(sources));
285  if(eval_p) {
287  sinks = expression_to_points_to_sinks(a, in);
288  /* We have to undo the impact of side effects performed when the arguments were analyzed for points-to information */
291  delta = int_to_expression(-1);
292  else
293  delta = int_to_expression(1);
294  offset_points_to_cells(sinks, delta, dt);
295  free_expression(delta);
296  }
297  else {
298  if(false) {
299  /* Needed for dereferencing17.c, but not for properties03
300  because in the second case the dereferencing is
301  delayed... */
302  /* There is an issue with eval_p: since we are looking for
303  sinks, we always have to dereference "a" at least once. */
305  sinks = expression_to_points_to_sinks(a, in);
306  /* We have to undo the impact of side effects performed when the arguments were analyzed for points-to information */
309  delta = int_to_expression(-1);
310  else
311  delta = int_to_expression(1);
312  offset_points_to_cells(sinks, delta, dt);
313  free_expression(delta);
314  }
315  }
316  }
317  else {
318  // FI: to be continued
319  pips_internal_error("Unexpected unary pointer operator\n");
320  }
321 
322  return sinks;
323 }
324 
325 // p=q, p.x, p->y, p+e, p-e, p+=e, p-=e
326 // What other binary operator could be part of a lhs expression?
328 {
329  entity f = call_function(c);
330  list al = call_arguments(c);
331  expression a1 = EXPRESSION(CAR(al));
332  expression a2 = EXPRESSION(CAR(CDR(al)));
333  list sinks = NIL;
334 
335  pips_assert("in is consistent on entry or undefined",
338 
339  if(ENTITY_ASSIGN_P(f)) {
340  // FI: you need to dereference this according to in...
341  // See assignment01.c
342  sinks = expression_to_points_to_sinks(a1, in);
343  }
344  else if(ENTITY_POINT_TO_P(f)) { // p->a
345  // FI: allocation of a fully fresh list? Theroretically...
346  if(pt_map_undefined_p(in)) {
348  cell c = make_anywhere_cell(t);
349  sinks = CONS(CELL, c, NIL);
350  }
351  else {
354  pips_assert("in is consistent after computing L",
356  // a2 must be a field entity
358  FOREACH(CELL, pc, L) {
359  if(null_cell_p(pc)) {
360  ; // FI: should be an execution error if gen_length(L)==1
361  }
362  else if(nowhere_cell_p(pc)) {
363  ; // FI: same, and, at least, pc should be removed from L
364  }
365  else if(anywhere_cell_p(pc)) {
367  // FI: we should assert ALIASING_ACROSS_TYPES==false..
371  reference_variable(r) = ne;
372  }
373  else {
374  ; // do nothing
375  }
376  }
377  else {
378  // FI: side effect or allocation of a new cell?
379  cell npc = copy_cell(pc);
380  if(!heap_cell_p(npc))
383  // FI: does this call allocate a full new list?
385  if(eval_p && !array_type_p(ft)) {
386  list dL = source_to_sinks(npc, in, true);
387  pips_assert("in is consistent after computing dL",
389  free_cell(npc);
390  if(ENDP(dL)) {// FI: this might mean dead code...
391  pips_internal_error("Dereferencing error or user error?\n");
392  if(ENDP(sinks)) {
393  pips_user_warning("Some kind of execution error has been encountered at line %d.\n", points_to_context_statement_line_number());
394  clear_pt_map(in);
395  points_to_graph_bottom(in) = true;
396  }
397  }
398  else {
399  FOREACH(CELL, ec, dL) {
400  // (void) cell_add_field_dimension(ec, f);
401  // FI: should we allocate new cells? Done
402  sinks = gen_nconc(sinks, CONS(CELL, ec, NIL));
403  }
404  }
405  }
406  else
407  sinks = gen_nconc(sinks, CONS(CELL, npc, NIL));
408  }
409  }
410  }
411  }
412  else if(ENTITY_FIELD_P(f)) { // p.1
413  // Seems to have no impact whatsoever
416  // FI: memory leak, but you need a copy to add the field
417  list L = gen_full_copy_list(oL);
418  // a2 must be a field entity
421  FOREACH(CELL, pc, L) {
422  // FI: there may cells that should
423  // not be processed, such as an anywhere non type
424  if(null_cell_p(pc)) {
425  // FI: Should we removed the arc generating a NULL as it is
426  // incompatible with the program execution?
427  ;
428  }
429  else if(anywhere_cell_p(pc)) {
430  // Leave it unmodified
431  ;
432  }
433  else if(cell_typed_anywhere_locations_p(pc)) {
434  // The type of the anywhere location must be updated
436  if(cell_reference_p(pc)) {
438  cell_reference(pc) = r;
439  }
440  else if(cell_preference_p(pc))
441  pips_internal_error("prefrence unexpected in cell.\n");
442  else if(cell_gap_p(pc))
443  pips_internal_error("gap unexpected in cell.\n");
444  else
445  pips_internal_error("tag %d unexpected in cell.\n", cell_tag(pc));
446  }
447  else {
448  (void) points_to_cell_add_field_dimension(pc, fe);
449  /* FI: it might be better to integrate this update in
450  * points_to_cell_add_field_dimension() in order to exploit available
451  * information directly and to return a consistent cell.
452  * Anyway, seems useless here
453  */
455  }
456  }
457  if(eval_p && !array_type_p(ft)) {
458  FOREACH(CELL, pc, L) {
459  // No need to check that LL is not empty: NULL might be one of
460  // the cells in L, but there may be other cells
461  list LL = source_to_sinks(pc, in, true);
462  sinks = gen_nconc(sinks, LL);
463  }
465  }
466  else
467  sinks = L;
468  }
469  // The internal conversion from PLUS_C to PLUS pays attention to
470  // pointers but not to arrays
471  else if(ENTITY_PLUS_C_P(f) || ENTITY_PLUS_P(f)) { // p+1, a+1
472  // FI: this should be conditioned by eval_p==true; else, no sink exists...
473  // FI: but we do need something for our lhs expressions, not
474  // matter what eval specifies
475  if(true || eval_p)
476  sinks = expression_to_points_to_sinks_with_offset(a1, a2, in);
477  else {
478  // pips_internal_error("The request cannot be satisfied.\n");
479  if(false && zero_expression_p(a2)) {
480  sinks = expression_to_points_to_sources(a1, in);
481  }
482  else { //FI: an exception or an error code should be raised
483  sinks = NIL;
484  }
485  }
486  }
487  else if(ENTITY_MINUS_C_P(f) || ENTITY_MINUS_P(f)) {
490  sinks = expression_to_points_to_sinks_with_offset(a1, ma2, in);
491  free_expression(ma2);
492  }
493  else if(ENTITY_PLUS_UPDATE_P(f)) {
494  sinks = expression_to_points_to_sinks(a1, in);
495  // offset_cells(sinks, a2);
496  }
497  else if(ENTITY_MINUS_UPDATE_P(f)) {
498  sinks = expression_to_points_to_sinks(a1, in);
499  /// Already performed elsewhere. The value returned by expression
500  // "p -= e" is simply "p", here "a1"
501  //entity um = FindOrCreateTopLevelEntity(UNARY_MINUS_OPERATOR_NAME);
502  //expression ma2 = MakeUnaryCall(um, copy_expression(a2));
503  //offset_cells(sinks, ma2);
504  //free_expression(ma2);
505  }
506  else if (ENTITY_CALLOC_SYSTEM_P(f)) { // CALLOC has two arguments
507  // FI: we need a calloc_to_points_to_sinks() to exploit both arguments...
509  copy_expression(a1),
510  copy_expression(a2));
511  sinks = malloc_to_points_to_sinks(e, in);
512  free_expression(e);
513  }
514  else if (ENTITY_REALLOC_SYSTEM_P(f)) { // REALLOC has two arguments
515  // FI: see man realloc() for its complexity:-(
516  // FI: we need a realloc_to_points_to_sinks() to exploit both arguments...
517  sinks = malloc_to_points_to_sinks(a2, in);
518  }
519  else if(ENTITY_FOPEN_P(f)) {
520  entity io_files = MakeIoFileArray(f);
522  reference r = make_reference(io_files, CONS(EXPRESSION, s, NIL));
523  cell ac = make_cell_reference(r);
524  // Since fopen() may fail, a NULL can also be returned
525  cell nc = make_null_cell();
526  sinks = CONS(CELL, ac, CONS(CELL, nc, NIL));
527  }
528  else {
529  // FI: two options, 1) generate an anywhere as sink to be always safe,
530  // 2) raise an internal error to speed up developement...
531  // But do not let go as the caller will block...
532  pips_internal_error("Unrecognized operator or function.\n");
533  ; // Nothing to do
534  }
535  if(ENDP(sinks)) {
536  pips_user_warning("Some kind of execution error has been encountered.\n");
537  clear_pt_map(in);
538  points_to_graph_bottom(in) = true;
539  }
540  pips_assert("in is consistent or undefined when returning",
543  return sinks;
544 }
545 
547 {
548  list sinks = NIL;
549  type t1 = expression_to_type(a1);
550  type t2 = expression_to_type(a2);
551  // FI: the first two cases should be unified with a=a1 or a2
553  // expression_to_points_to_sinks() returns pointers to arcs in the
554  // points-to graph. No side effect is then possible.
555  list e_sinks = expression_to_points_to_sinks(a1, in);
556  sinks = gen_full_copy_list(e_sinks);
557  gen_free_list(e_sinks);
559  offset_points_to_cells(sinks, a2, t);
560  }
561  else if(pointer_type_p(t2) && (scalar_integer_type_p(t1) || unbounded_expression_p(a1))) {
562  list e_sinks = expression_to_points_to_sinks(a2, in);
563  sinks = gen_full_copy_list(e_sinks);
564  gen_free_list(e_sinks);
566  offset_points_to_cells(sinks, a1, t);
567  }
568  else if(array_type_p(t1) && scalar_integer_type_p(t2)) {
569  list e_sinks = expression_to_points_to_sources(a1, in);
570  sinks = gen_full_copy_list(e_sinks);
571  gen_free_list(e_sinks);
573  offset_points_to_cells(sinks, a2, t);
574  }
575  else if(array_type_p(t2) && scalar_integer_type_p(t1)) {
576  list e_sinks = expression_to_points_to_sources(a2, in);
577  sinks = gen_full_copy_list(e_sinks);
578  gen_free_list(e_sinks);
580  offset_points_to_cells(sinks, a1, t);
581  }
582  else {
583  // These types do not lead to sources or sinks
584  //pips_internal_error("Not implemented for \"%s\" and \"%s\" and %p\n",
585  // expression_to_string(a1), expression_to_string(a2), in);
586  ; // ignore
587  }
588  free_type(t1);
589  free_type(t2);
590  return sinks;
591 }
592 
593 // c?p:q
595  pt_map in,
596  bool eval_p,
597  bool constant_p)
598 {
599  entity f = call_function(c);
600  list al = call_arguments(c);
601  list sinks = NIL;
602 
603  pips_assert("in is consistent", consistent_pt_map_p(in));
604 
605  if(ENTITY_CONDITIONAL_P(f)) {
606  //bool eval_p = true;
607  expression c = EXPRESSION(CAR(al));
608  pt_map in_t = full_copy_pt_map(in);
609  pt_map in_f = full_copy_pt_map(in);
610  in_t = condition_to_points_to(c, in_t, true);
611  in_f = condition_to_points_to(c, in_f, false);
612  expression e1 = EXPRESSION(CAR(CDR(al)));
613  expression e2 = EXPRESSION(CAR(CDR(CDR(al))));
614  list sinks1 = NIL;
615  if(!points_to_graph_bottom(in_t))
616  sinks1 = expression_to_points_to_cells(e1, in_t, eval_p, constant_p);
617  list sinks2 = NIL;
618  if(!points_to_graph_bottom(in_f))
619  sinks2 = expression_to_points_to_cells(e2, in_f, eval_p, constant_p);
620  sinks = gen_nconc(sinks1, sinks2);
621  // The "in" points-to graph may be enriched by both sub-graphs
622  //
623  // side-effects on in? memory leak...
625  points_to_graph_set(in_f));
627  points_to_graph_bottom(in) = true;
628  // The free is too deep. References from points-to arcs in in_t
629  // and in_f may have been integrated in sinks1 and/or sinks2
630  // See conditional05
631  clear_pt_map(in_t), clear_pt_map(in_f);
632  free_pt_map(in_t), free_pt_map(in_f);
633  }
634  // FI: any other ternary intrinsics?
635 
636  return sinks;
637 }
638 
639 // comma operator
641 {
642  entity f = call_function(c);
643  list sinks = NIL;
644  pips_internal_error("Not implemented for %p and %p\n", c, in);
645  if(ENTITY_COMMA_P(f)) {
646  ;
647  }
648  return sinks;
649 }
650 
651 /* Return NULL as sink */
652 /* Double definition...
653 list points_to_null_sinks()
654 {
655  entity ne = entity_null_locations();
656  reference nr = make_reference(ne, NIL);
657  cell nc = make_cell_reference(nr);
658  list sinks = CONS(CELL, nc, NIL);
659  return sinks;
660 }
661 */
662 
663 /* Points-to cannot used any kind of reference, just constant references.
664  *
665  * For instance, "x[i]" is transformed into "x[*]" because the value
666  * of "i" is unknown. x[3+4] may be transformed into x[7].
667  *
668  * A new referencec is allocated. Reference "r" is unchanged.
669  */
671 {
672  list sl = reference_indices(r);
673  list nsl = NIL;
674 
675  FOREACH(EXPRESSION, s, sl) {
676  value v = EvalExpression(s);
679  int cs = constant_int(value_constant(v));
680  ns = int_to_expression(cs);
681  }
682  else {
684  }
685  nsl = gen_nconc(nsl, CONS(EXPRESSION, ns, NIL));
686  }
687 
688  entity var = reference_variable(r);
689  reference nr = make_reference(var, nsl);
690  return nr;
691 }
692 
693 /* What to do when a pointer "p" is dereferenced within a reference "r".
694  *
695  * If p is a scalar pointer, p[i] is equivalent to *(p+i) and p[i][j]
696  * to *(*(p+i)+j).
697  *
698  * If p is a 2-D array of pointers, p[i], p[i][j] do not belong here.
699  * But, p[i][j][k] is equivalent to *(p[i][j]+k) and p[i][j][k][l]
700  * to *(*(p[i][j]+k)+l).
701  *
702  * The equivalent expression is fully allocated to be freed at the
703  * end. Which may cause problems if the points-to analysis re-use
704  * parts of the internal data structure...
705  *
706  * The normalization could have been performed by the parser, but PIPS
707  * is source-to-source for the benefit of its human user.
708  */
710 {
711  list sinks = NIL;
713 
714  if(eval_p)
715  sinks = expression_to_points_to_sinks(pae, in);
716  else
717  sinks = expression_to_points_to_sources(pae, in);
718 
719  free_expression(pae);
720 
721  return sinks;
722 }
723 
724  /* Returns a list of memory cells "sinks" possibly accessed by the evaluation
725  * of reference "r". No sharing between the returned list "sinks" and
726  * the reference "r" or the points-to set "in".
727  *
728  * Examples if eval_p==false: x->x, t[1]->t[1], t[1][2]->t[1][2], p->p...
729  *
730  * Examples if eval_p==true: x->error, t[1]->t[1][0],
731  * t[1][2]->t[1][2][0], p->p[0]...
732  *
733  * If constant_p, stored-dependent subscript expressions are replaced
734  * by "*" and store-independent expressions are replaced by their
735  * values, e.g. x[3+4]->x[7]. Else, subscript expressions are left
736  * unchanged. Motivation: constant_p==true for points-to computation,
737  * and false for the translation of effects. In the latter case, the
738  * transformation into a constant reference is postponed.
739  *
740  * Issue: let's assume "t" to be an array "int t[10][10[10];". The C
741  * language is (too) flexible. If "p" is an "int ***p;", the impact
742  * of assignment "p=t;" leads to "p points-to t" or "p points-to
743  * t[0]" or "p points-to t[0][0][0]". Two different criteria can be
744  * used: the compatibiliy of the pointer type and the pointed cell
745  * type, or the equality of the pointer value and of the pointed cell
746  * address.
747  *
748  * In the first case, t->t[0]->t[0][0]->t[0][0][0].
749  *
750  * In the second case, t->t[0][0][0], t[0]->t[0][0][0], t[0][0]->t[0][0][0].
751  *
752  * FI: I do not trust this function. It is already too long. And I am
753  * not confident the case disjunction is correct/well chosen.
754  */
756  bool eval_p,
757  bool constant_p)
758 {
759  list sinks = NIL;
760  entity e = reference_variable(r);
762  list sl = reference_indices(r);
763 
764  ifdebug(8) {
765  pips_debug(8, "Reference r = ");
766  print_reference(r);
767  fprintf(stderr, "\n");
768  }
769 
770  //bool to_be_freed;
772  //type rt = compute_basic_concrete_type(srt);
773  if(false && eval_p && !pointer_type_p(rt)) {
774  // There must be a type mismatch
775  pips_user_error("Type mmismatch for reference \"%s\" at line %d.",
778  }
779  else {
780 
781  // FI: conditional01.c shows that the C parser may not generate the
782  // right construct when a scalar or an pointer is indexed.
783  // FI: maybe more difficult to guess of array of pointers...
784  if(pointer_type_p(t) && !ENDP(sl)) {
785  sinks = pointer_reference_to_points_to_sinks(r, in, eval_p);
786  }
787  else if(array_of_pointers_type_p(t)
789  sinks = pointer_reference_to_points_to_sinks(r, in, eval_p);
790  }
791  else {
792  // FI: to be checked otherwise?
793  //expression rhs = expression_undefined;
794  if (!ENDP(sl)) { // FI: I'm not sure this is a useful disjunction
795  /* Two proper possibilities: an array of pointers fully subscribed
796  or any other kind of array partially subscribed. And an
797  unsuitable one: an integer value... */
798  int nd = NumberOfDimension(e);
799  int rd = (int) gen_length(sl);
800  if (nd > rd) {
801  /* No matter what, the target is obtained by adding a 0 subscript */
802  /* FI: I do not know if the subscript removal impact the
803  handling of loops by the points-to analysis; see
804  Points-to/array07.c */
805  reference nr =
807  cell nc = make_cell_reference(nr);
808  // was:
809  // for(int i=rd; eval_p && i<nd; i++) { // FI: not efficient
810  if (eval_p)
811  {
814  CONS(EXPRESSION, ze, NIL));
815  // FC: this makes the loop to exit on the first iteration?
816  // replaced by an equivalent if, but probably a bug.
817  // i = nd
818  }
819  sinks = CONS(CELL, nc, NIL);
820  }
821  else if (nd == rd) {
822  // FI: eval_p is not used here...
824  cell nc = make_cell_reference(nr);
825  if(eval_p) {
826  sinks = source_to_sinks(nc, in, true); // FI: allocate a new copy
827  }
828  else
829  sinks = CONS(CELL, nc, NIL);
830  }
831  else { // rd is too big
832  // Could be a structure with field accesses expressed as indices
833  // Can be a dereferenced pointer, "p[0]" instead of "*p"
834  type et = ultimate_type(entity_type(e));
835  if(struct_type_p(et)) {
836  reference nr = copy_reference(r);
837  cell nc = make_cell_reference(nr);
838  if(eval_p) {
839  sinks = source_to_sinks(nc, in, true);
840  /*
841  expression ze = int_to_expression(0);
842  reference_indices(nr) = gen_nconc(reference_indices(nr),
843  CONS(EXPRESSION, ze, NIL));
844  */
845  }
846  else
847  sinks = CONS(CELL, nc, NIL);
848  }
849  else if(pointer_type_p(et)) {
850  pips_assert("One subscript", rd==1 && nd==0);
851  /* What is the value of the subscript expression? */
852  //expression sub = EXPRESSION(CAR(reference_indices(r)));
853  // FI: should we try to evaluate the subscript statically?
854  // If the expression is not zero, the target is unchanged but
855  // * must be used as subscript in sinks
856 
857  entity v = reference_variable(r);
858  reference nr = make_reference(v, NIL);
859  cell nc = make_cell_reference(nr);
860  if(eval_p) {
861  // FI: two rounds of source_to_sinks() I guess
862  list sinks_1 = source_to_sinks(nc, in, true);
863  FOREACH(CELL, c, sinks_1) {
864  list sinks_2 = source_to_sinks(c, in, true);
865  sinks = gen_nconc(sinks, sinks_2);
866  }
867  }
868  else {
869  // FI: what's going to happen with subscript expressions?
870  // FI: strict typing?
871  sinks = source_to_sinks(nc, in, true);
872  }
873  // FI FI FI
874  ;
875  }
876  else {
877  // FI: you may have an array of struct to begin with, and of
878  // structs including other structs
879  // Handle it just like a struct
880  //pips_user_error("Too many subscript expressions for array \"%s\".\n",
881  // entity_user_name(e));
882  reference nr = copy_reference(r);
883  cell nc = make_cell_reference(nr);
884  if(eval_p) {
885  sinks = source_to_sinks(nc, in, true);
886  }
887  else
888  sinks = CONS(CELL, nc, NIL);
889  }
890  }
891  }
892  else {
893  /* scalar case, rhs is already a lvalue */
894  if(scalar_type_p(t)) {
896  if(eval_p) {
897  // FI: we have a pointer. It denotes another location.
898  sinks = source_to_sinks(nc, in, true);
899  // FI: in some cases, nc is reused in sinks
900  if(!gen_in_list_p(nc, sinks))
901  free_cell(nc);
902  }
903  else {
904  // FI: without dereferencing
905  sinks = CONS(CELL, nc, NIL);
906  }
907  }
908  else if(array_type_p(t)) { // FI: not OK with typedef
909  /* An array name can be used as pointer constant */
910  /* We should add null indices according to its number of dimensions */
911  reference nr = copy_reference(r);
912  cell nc = make_cell_reference(nr);
913  if (true) {
914  // int n = NumberOfDimension(e);
915  // int rd = (int) gen_length(reference_indices(r));
916  // FI: not efficient and quite convoluted!
917  // FC: brain damaged, this is not a loop, compiler complains
918  // for(int i=rd; eval_p && i<n; i++) {
919  if (eval_p)
920  {
921  reference_indices(nr) =
924  // FC: this assignment make the loop exit on the first iteration?
925  // i = n; // to be type compatible: add at most one subscript
926  }
927  }
928  else {
929  // DEAD CODE
930  // FI: this is not always a good thing. See arithmetic11.c.
931  // The type of the source is needed to determine the number
932  // of zero subscripts...
934  }
935  sinks = CONS(CELL, nc, NIL);
936  }
937  else {
938  pips_internal_error("Pointer assignment from something "
939  "that is not a pointer.\n Could be a "
940  "function assigned to a functional pointer.\n");
941  }
942  }
943  }
944 
945  if(ENDP(sinks)) {
946  /* This function may be called from the effect library via
947  backward_translation_of_points_to_formal_context() */
949  pips_user_warning("Some kind of execution error has been encountered at line %d.\n",
951  }
952  else {
953  pips_user_warning("Some kind of execution error has been encountered.\n");
954  }
955  clear_pt_map(in);
956  points_to_graph_bottom(in) = true;
957  }
958  }
959 
960  /*pips_assert("The expected type and the reference type are equal",
961  array_pointer_type_equal_p(et, rt)); */
962  /*pips_assert("The expected type and the reference type are compatible",
963  concrete_type_equal_p(et, rt)); */
964  pips_assert("The expected type and the reference type are compatible",
965  type_structurally_equal_p(et, rt));
966  check_type_of_points_to_cells(sinks, rt, eval_p);
967 
968  //if(to_be_freed) free_type(srt);
969 
970  ifdebug(8) {
971  pips_debug(8, "Resulting cells: ");
972  print_points_to_cells(sinks);
973  fprintf(stderr, "\n");
974  }
975 
976  return sinks;
977 }
978 ␌
980 {
982  list nsinks = NIL;
983  // You may have to update the subscript lists to fit the type
984  // This can only be done on *copies* of references included into
985  // the arcs of the points-to graph
986  FOREACH(CELL, c, sinks) {
987  if(!null_cell_p(c) && !nowhere_cell_p(c) && !anywhere_cell_p(c)) {
989  if(array_pointer_type_equal_p(pt, cct))
990  ; // nothing to do
991  else {
993  if(overloaded_type_p(mct))
994  ; // nothing to do... to be checked
995  else {
996  // You should try to add or remove zero subscripts till the expected
997  // type is reached.
1000  if(!type_void_p(pt)
1003 
1004  if(array_pointer_type_equal_p(pt, mct))
1005  ; // nothing to do
1006  else if(array_type_p(mct)
1008  ; // nothing to do
1009  else {
1010  pips_internal_error("Not implemented yet.\n");
1011  }
1012  }
1013  else {
1014  /* The types are really incompatible, let's use the
1015  * type lattice, max_type(cct, mct)... if it were implemented
1016  *
1017  * Could we do better for a cast to (void *)? See cast03.
1018  */
1021  nsinks = CONS(CELL, nc, nsinks);
1022  // pips_internal_error("Cast handling failure 1.\n");
1023  }
1024  }
1025  }
1026  }
1027  }
1028 
1029  return nsinks;
1030 }
1031 
1032 /* FI: I am not sure that process_casted_sources() is nor should be
1033  * different from process_casted_sinks()
1034  */
1036 {
1037  list nsinks = NIL; // New sink list
1038  FOREACH(CELL, c, sinks) {
1039  if(!null_cell_p(c) && !nowhere_cell_p(c) && !anywhere_cell_p(c)) {
1041  if(array_pointer_type_equal_p(t, cct))
1042  ; // nothing to do
1043  else { // We should create a stub of the proper type because a
1044  // reference cannot include the address-of operator, "&"
1045  if(pointer_type_p(t) && array_type_p(cct)) {
1049  ;
1050  else
1051  pips_internal_error("Cast handling failure 2.\n");
1052  }
1053  else {
1054  if(type_void_p(cct)) {
1055  /* Cell c is OK if it points towards cells of type
1056  compatible with the type pointed to by type t*/
1057  }
1058  else {
1061  nsinks = CONS(CELL, nc, nsinks);
1062  break;
1063  //pips_internal_error("Not implemented yet: stub with proper type needed.\n");
1064  }
1065  }
1066  }
1067  }
1068  }
1069 
1070  /* Update "sinks" with "dsl" and "nsl" */
1071 
1072  return nsinks;
1073 }
1074 
1075 /* Handling of cast: play it safe! Either the cast is partly redundant
1076  * and can be ignored or anywhere is returned.
1077  *
1078  * Design choice: can we have static aliasing with constant paths? Can
1079  * we have different types for one constant path? Maybe we could have
1080  * some static aliasing for stubs, using an offset in the formal
1081  * context, but we cannot manage static aliasing at the reference
1082  * level, i.e. at the constant path level.
1083  *
1084  * FI: do we need eval_p? Yes! We may need to produce the source or the sink.
1085  *
1086  * Note: the problem linked to eval_p has not been analyzed properly;
1087  * the code should be simplified.
1088  *
1089  * Relevant test cases: Rice/test03
1090  */
1092  type et __attribute__ ((unused)),
1093  pt_map in,
1094  bool eval_p)
1095 {
1096  list sinks = list_undefined;
1097  list nsinks = NIL; // In case the cast cannot be handled precisely
1098  expression e = cast_expression(ce);
1100  // FI: should we pass down the expected type? It would be useful for
1101  // heap modelling. No, we might ass well fix the type in the list of
1102  // sinks returned, especially for malloced buckets.
1103  /* FI: we need here to return a list of points-to objects so as to
1104  * warn the user in case the types are not compatible with the
1105  * property ALIAS_ACROSS_TYPES or to fix the cells allocated in
1106  * heap. However, this business if more likely to be performed in
1107  * sinks.c
1108  */
1109  if(eval_p) {
1110  sinks = expression_to_points_to_sinks(e, in);
1111  if(pointer_type_p(t)) {
1112  nsinks = process_casted_sinks(sinks, t);
1113  }
1114  else {
1115  pips_internal_error("Not implemented yet.\n");
1116  }
1117  }
1118  else {
1119  sinks = expression_to_points_to_sources(e, in);
1120  if(pointer_type_p(t)) {
1121  nsinks = process_casted_sources(sinks, t);
1122  }
1123  else {
1124  // FI: should we make sure that we do not tranformer pointers
1125  // into integers or other types?
1126  ;
1127  }
1128  }
1129 
1130  if(!ENDP(nsinks)) {
1131  gen_free_list(sinks);
1132  sinks = nsinks;
1133  }
1134 
1135  return sinks;
1136  }
1137 
1138 // FI: do we need eval_p? eval_p is assumed always true
1140  type et __attribute__ ((unused)),
1141  pt_map in)
1142 {
1143  list sinks = NIL;
1144  // FI: seems just plain wrong for a sink
1145  // pips_internal_error("Not implemented yet");
1146  if( sizeofexpression_expression_p(soe) ){
1148  sinks = expression_to_points_to_sinks(ne, in);
1149  }
1150  if( sizeofexpression_type_p(soe) ){
1152  // FI: a better job could be done. A stub should be allocated in
1153  // the formal context of the procedure
1154  if(pointer_type_p(t)) {
1156  cell c = make_anywhere_cell(pt);
1157  sinks = CONS(CELL, c, NIL);
1158  }
1159  else
1160  pips_internal_error("Unexpected type.\n");
1161  }
1162  return sinks;
1163 }
1164 
1165 ␌
1166 /* Heap modelling
1167  *
1168  * Rather than passing many arguments, keep a heap_context. May not be
1169  * a good idea for cast information...
1170  *
1171  * The API should contain renaming function(s) to move the effects up
1172  * the call graph....
1173  */
1174 // Current statement where the malloc is performed
1176 // number of malloc occurences already met in the malloc statement
1177 static int malloc_counter = 0;
1178 
1180 {
1181  malloc_statement = s;
1182  malloc_counter = 0;
1183 }
1184 
1186 {
1188  malloc_counter = 0;
1189 }
1190 
1192 {
1194  return s;
1195 }
1196 
1198 {
1199  return ++malloc_counter;
1200 }
1201 
1202 /* Heap modelling
1203  *
1204  * FI: lots of issues here; the potential cast is lost...
1205  *
1206  * FI: the high-level switch I have added to understand the management
1207  * of options is performed at a much much lower level, which may be
1208  * good or not. I do not think it's good for readbility, but factoring
1209  * is good. See malloc_to_abstract_location()
1210  *
1211  * e is the arguments of the malloc call...
1212  *
1213  * Basic heap modelling
1214  *
1215  * ABSTRACT_HEAP_LOCATIONS:
1216  *
1217  * "unique": do not generate heap abstract
1218  * locations for each line number...
1219  *
1220  * "insensitive": control path are not taken into account; all
1221  * malloc() located in one function are equivalent.
1222  *
1223  * "flow-sensitive": take into account the line number or the occurence number?
1224  *
1225  * "context-sensitive": take into account the call stack; not implemented
1226  *
1227  * ALIASING_ACROSS_TYPE: you should have one heap per type if aliasing
1228  * across type is forbidden. The impact of its composition with the
1229  * previous property is not specified...
1230  */
1232  pt_map in)
1233 {
1234  list sinks = NIL;
1235  const char * opt = get_string_property("ABSTRACT_HEAP_LOCATIONS");
1236  //bool type_sensitive_p = !get_bool_property("ALIASING_ACROSS_TYPES");
1237 
1238  if(same_string_p(opt, "unique")) {
1240  }
1241  else if(same_string_p(opt, "insensitive")) {
1243  }
1244  else if(same_string_p(opt, "flow-sensitive")) {
1246  }
1247  else if(same_string_p(opt, "context-sensitive")) {
1248  // Context sensitivity is dealt with in the translation functions, not here
1250  }
1251  else {
1252  pips_user_error("Unexpected value \"%s\" for Property ABSTRACT_HEAP_LOCATION."
1253  "Possible values are \"unique\", \"insensitive\","
1254  "\"flow-sensitive\", \"context-sensitive\".\n", opt);
1255  }
1256 
1257  /* The C standard specifies that all pointers that are allocated in
1258  the heap have the value "indeterminate". */
1259  FOREACH(CELL, c, sinks) {
1261  entity v = reference_variable(r);
1263  FOREACH(CELL, source, l) {
1264  list psl = points_to_source_to_sinks(source, in, false);
1265  cell sink = cell_to_nowhere_sink(source);
1267  if(ENDP(psl)) {
1268  pt = make_points_to(source, sink,
1271  }
1272  else {
1273  pt = make_points_to(source, sink,
1276  gen_free_list(psl);
1277  }
1278  add_arc_to_pt_map(pt, in);
1279  }
1280  }
1281 
1282  return sinks;
1283 }
1284 
1285 /* FI->AM: is "unique" multiple when ALIASING_ACROSS_TYPE is set to false?
1286  *
1287  * FI->AM: the comments in pipsmake-rc.tex are not sufficient to
1288  * understand what the choices are.
1289  *
1290  * If ALIASING_ACROSS_TYPES, return an overloaded unique heap entity
1291  */
1293 {
1294  list m = NIL;
1295  if(get_bool_property("ALIASING_ACROSS_TYPES")) {
1296  /* We need only one HEAP abstract location: Pointers/assign03 */
1298  }
1299  else {
1300  /* We need one HEAP abstract location per type: Pointers/assign02
1301  *
1302  * Note: we must be careful about dereferencing and fields...
1303  */
1305  }
1306  return m;
1307 }
1308 
1309 /* FI->AM: what's the difference with the previous option? Reference
1310  * to your dissertation?
1311  */
1313 {
1314  list m = NIL;
1315  // FI: I'm waiting for this error to happen
1316  pips_internal_error("Not implemented yet?");
1318  return m;
1319 }
1320 
1322 {
1323  // expression sizeof_exp = EXPRESSION (CAR(call_arguments(expression_call(rhs))));
1324  // FI: kind of dumb since it is int or size_t
1325  // FI: the expected type should be passed down all these function calls...
1326  // type t = expression_to_type(e);
1327  /*
1328  reference nr = original_malloc_to_abstract_location(e,
1329  type_undefined,
1330  type_undefined,
1331  e,
1332  get_current_module_entity(),
1333  get_heap_statement());
1334  */
1335 
1336  // FI: the heap number is not yet used
1340  NIL);
1341 
1342  // FI: why use &si instead of si?
1343  entity me = malloc_to_abstract_location(e, &si);
1344 
1346  /* The type of me may en array type because of
1347  *
1348  * int * p = (int *) malloc(nb*sizeof(int))
1349  *
1350  * or int (*p)[nb] = (int (*)[nb]) malloc(sizeof(int[nb]))
1351  *
1352  * In both case the heap object is an array.
1353  *
1354  * We need the heap reference to be compatible with the pointer
1355  * type. Adding a [0] subscript or not should be decided later, when
1356  * the points-to arc is built. Or we might be able to guess right in
1357  * case the first dimension is unbounded...
1358  *
1359  * See Points-to/dereference19.c, line 19 for case 1, and line 17
1360  * for case 2.
1361  */
1362  if(!entity_array_p(me)) {
1363  mr = make_reference(me, NIL);
1364  }
1365  else {
1366  type t = entity_type(me);
1367  variable v = type_variable(t);
1368  list dl = variable_dimensions(v);
1369  dimension d = DIMENSION(CAR(dl));
1370  expression u = dimension_upper(d);
1371  if(unbounded_expression_p(u))
1373  else
1374  mr = make_reference(me, NIL);
1375  }
1376 
1377  cell mc = make_cell_reference(mr);
1378  list sinks = CONS(CELL, mc, NIL);
1379 
1380  if(!get_bool_property("POINTS_TO_SUCCESSFUL_MALLOC_ASSUMED")) {
1381  cell nc = make_null_cell();
1382  sinks = CONS(CELL, nc, sinks);
1383  }
1384 
1385  return sinks;
1386 }
1387 ␌
1389  type et __attribute__ ((unused)),
1390  pt_map in)
1391 {
1393  // list args = application_arguments(a);
1394  type t = expression_to_type(f);
1395  entity ne = entity_undefined;
1396  bool type_sensitive_p = !get_bool_property("ALIASING_ACROSS_TYPES");
1397 
1398  pips_user_warning("Case application is not correctly handled &p and %p\n",
1399  a, in);
1400 
1401  if(type_sensitive_p)
1403  else
1405 
1406  reference nr = make_reference(ne, NIL);
1407  cell nc = make_cell_reference(nr);
1408  list sinks = CONS(CELL, nc, NIL);
1409 
1410  // FI: free_type(t); ?
1411 
1412  return sinks;
1413 }
1414 
1415 // Duplicate?
1416 /*
1417 list sizeofexpression_to_points_to_sinks(sizeofexpression soe, pt_map in)
1418 {
1419  list sinks = NIL;
1420  pips_user_warning("Not implemented yet for %p and %p\n", soe, in);
1421  return sinks;
1422 }
1423 */
1424 ␌
1425  /* Allocate a new expression based on the reference in "c" and the
1426  * subscript list "csl". No sharing with the arguments. The pointer
1427  * subscripts are transformed into pointer arithmetic and
1428  * dereferencements.
1429  */
1431 {
1434 
1435  FOREACH(EXPRESSION, pse, csl) {
1436  expression npse = copy_expression(pse);
1439  }
1440  return pae;
1441 }
1442 
1443  /* Generate the corresponding points-to reference(s). All access
1444  * operators such as ., ->, * are replaced by subscripts.
1445  *
1446  * See Strict_typing.sub/assigment11.c: the index is not put back at
1447  * the right place. It would be easy (?) to fix it in this specific
1448  * case, not forgetting the field subscripts..., but I do not see how
1449  * to handle general stubs with artificial dimensions...
1450  */
1452  type et,
1453  pt_map in,
1454  bool eval_p)
1455 {
1456  expression a = subscript_array(s);
1457  bool to_be_freed;
1458  // If ever a pointer is deferenced somewhere, at is not going to
1459  // take into account the extra dimensions needed for pointer arithmetics
1460  type at = points_to_expression_to_type(a, &to_be_freed);
1461 
1462  /* FI: In many cases, you do need the source. However, you have
1463  * different kind of sources because "x" and "&x[0]" are synonyms
1464  * and because you sometimes need "x" and some other times "&x[0]".
1465  */
1466  list sources = expression_to_points_to_sources(a, in);
1467 
1468  list sl = subscript_indices(s);
1470  list sinks = NIL;
1471  list i_sources = NIL;
1472  bool eval_performed_p = false;
1473 
1474  /* If the first dimension is unbounded, it has (probably) be added
1475  because of a pointer. A zero subscript is also added. */
1476  bool strict_p = get_bool_property("POINTS_TO_STRICT_POINTER_TYPES");
1477  if(array_type_p(at) && !strict_p) {
1478  variable v = type_variable(at);
1480  if(unbounded_dimension_p(d1)) {
1481  /* Add a zero subscript */
1483  csl = CONS(EXPRESSION, z, csl);
1484  }
1485  }
1486 
1487  /* Add subscript when possible. For typing reason, typed anywhere
1488  cell should be subscripted. */
1489  FOREACH(CELL, c, sources) {
1490  // FI: some other lattice abstract elements should be removed like
1491  // STACK, DYNAMIC
1492  if(!nowhere_cell_p(c) && !null_cell_p(c) && !anywhere_cell_p(c)
1493  && !all_heap_locations_cell_p(c)) {
1494  bool to_be_freed2;
1495  type t = points_to_cell_to_type(c, &to_be_freed2);
1497  entity v = reference_variable(r);
1498 
1499  if(array_type_p(at)) {
1500  list ncsl = gen_full_copy_list(csl);
1501  if(entity_stub_sink_p(v)) {
1502  // argv03
1504 
1505  // FI: an horror... fixing a design mistake by a kludge...
1506  // useful for argv03, disastrous for dereferencing08
1507  if(!points_to_array_reference_p(r)) {
1509  ;
1510  else
1511  pips_internal_error("Subscript handling failure 1.\n");
1512  }
1513  // FI: the update depends on the sink model
1514  // points_to_reference_update_final_subscripts(r, ncsl);
1516 
1517  // FI: let's add the zero subscripts again...
1518  // points_to_cell_add_zero_subscripts(c);
1520  }
1521  else {
1522  // Expression "a" does not require any dereferencing, add
1523  // the new indices (Strict_typing.sub/assignment11.c
1524 
1525  // FI: an horror... fixing a design mistake by a kludge...
1527  ;
1528  else
1529  pips_internal_error("Subscript handling failure 1.\n");
1530 
1532  }
1533 
1534  i_sources = CONS(CELL, c, i_sources);
1535  }
1536  else if(struct_type_p(at)) { // Just add the subscript, old version
1537  list ncsl = gen_full_copy_list(csl);
1538  if(entity_stub_sink_p(v)) {
1540  // FI: the update depends on the sink model
1542  }
1543  else {
1544  // Expression "a" does not require any dereferencing, add
1545  // the new indices (Strict_typing.sub/assignment11.c
1547  }
1548  i_sources = CONS(CELL, c, i_sources);
1549  }
1550  else if(pointer_type_p(at)) {
1553  /* Add the subscripts */
1554  list ncsl = gen_full_copy_list(csl);
1556  eval_performed_p = true;
1557  i_sources = CONS(CELL, c, i_sources);
1558  }
1559  else {
1560  /* The reference "p[i][j]" is transformed into an expression
1561  "*(*(p+i)+j)" if "p" is really a pointer expression, not a
1562  partial array reference. */
1563  //expression pae = pointer_subscript_to_expression(c, csl);
1564  // FI: I guess csl might have to be freed...
1565  list nsl = gen_full_copy_list(sl);
1567  i_sources = expression_to_points_to_sources(pae, in);
1568  free_expression(pae);
1569  }
1570  }
1571  else {
1572  pips_internal_error("Unexpected case.\n");
1573  }
1574  if(to_be_freed2) free_type(t);
1575  }
1576  else if(anywhere_cell_p(c)
1577  || all_heap_locations_cell_p(c)) {
1578  i_sources = CONS(CELL, c, i_sources);
1579  }
1580  }
1581 
1582  gen_full_free_list(csl);
1583  gen_free_list(sources);
1584 
1585  if(eval_p && !eval_performed_p) {
1586  FOREACH(CELL, source, i_sources) {
1587  bool to_be_freed;
1588  type t = points_to_cell_to_type(source, &to_be_freed);
1589  reference r = cell_any_reference(source);
1591  //points_to_cell_add_zero_subscripts(source);
1592  //adapt_reference_to_type(r, at, points_to_context_statement_line_number);
1595  CONS(EXPRESSION, z, NIL));
1596  sinks = gen_nconc(sinks, CONS(CELL, source, NIL));
1597  }
1598  else if(pointer_type_p(t)) {
1599  // A real pointer, not an under-subscripted array
1600  list pointed = source_to_sinks(source, in, true);
1601  sinks = gen_nconc(sinks, pointed);
1602  }
1603  else {
1604  // FI: Pretty bad wrt sharing and memory leaks
1605  sinks = gen_nconc(sinks, CONS(CELL, source, NIL));
1606  }
1607  if(to_be_freed) free_type(t);
1608  }
1609  }
1610  else
1611  sinks = i_sources;
1612 
1613  if(to_be_freed) free_type(at);
1614 
1615  if(ENDP(sinks)) {
1616  pips_user_warning("Some kind of execution error has been encountered.\n");
1617  clear_pt_map(in);
1618  points_to_graph_bottom(in) = true;
1619  }
1620 
1621  check_type_of_points_to_cells(sinks, et, eval_p);
1622 
1623  return sinks;
1624 }
1625 
1627 {
1628  list sinks = NIL;
1629  pips_user_warning("Not implemented yet for %p and %p\n", r, in);
1630  return sinks;
1631 }
1632 
1633 /* Return a possibly empty list of abstract locations whose addresses
1634  * are possible value of expression "e" evaluated with points-to
1635  * information "in".
1636  *
1637  * Expression "e" is assumed to evaluate as a lhs, i.e. some memory
1638  * address. If not, an empty list is returned.
1639  *
1640  * Additional information could be passed in a second pass analysis,
1641  * e.g. preconditions.
1642  *
1643  * The generated sinks are all constant memory paths. A more advanced
1644  * analysis could use storage-sentitive information, that would have
1645  * to be updated with effects and transformers.
1646  *
1647  * The list returned should be fully allocated with no sharing between
1648  * it and the in points-to set. Hopefully...
1649  */
1651  pt_map in,
1652  bool eval_p,
1653  bool constant_p)
1654 {
1655  /* reference + range + call + cast + sizeofexpression + subscript +
1656  application*/
1657  list sinks = NIL;
1658  //bool to_be_freed;
1659  //type et = points_to_expression_to_type(e, &to_be_freed);
1660  //type cet = compute_basic_concrete_type(et);
1661  //if(to_be_freed) free_type(et);
1663  tag tt ;
1664  syntax s = expression_syntax(e);
1665 
1666  switch (tt = syntax_tag(s)) {
1667  case is_syntax_reference: {
1668  reference r = syntax_reference(s);
1669  sinks = reference_to_points_to_sinks(r, cet, in, eval_p, constant_p);
1670  break;
1671  }
1672  case is_syntax_range: {
1673  range r = syntax_range(s);
1674  sinks = range_to_points_to_sinks(r, in);
1675  break;
1676  }
1677  case is_syntax_call: {
1678  call c = syntax_call(s);
1679  sinks = call_to_points_to_sinks(c, cet, in, eval_p, constant_p);
1680  break;
1681  }
1682  case is_syntax_cast: {
1683  cast c = syntax_cast(s);
1684  sinks = cast_to_points_to_sinks(c, cet, in, eval_p);
1685  break;
1686  }
1688  // FI: no sink should be returned...
1689  //sinks = sizeofexpression_to_points_to_sinks(st, rhs, lhs, in);
1690  break;
1691  }
1692  case is_syntax_subscript: {
1693  subscript sub = syntax_subscript(s);
1694  sinks = subscript_to_points_to_sinks(sub, cet, in, eval_p);
1695  break;
1696  }
1697  case is_syntax_application: {
1699  sinks = application_to_points_to_sinks(a, cet, in);
1700  break;
1701  }
1702  case is_syntax_va_arg: {
1703  // FI: useful?
1704  //pips_internal_error("Not implemented yet\n");
1705  list soel = syntax_va_arg(s);
1706  //sizeofexpression soev = SIZEOFEXPRESSION(CAR(soel));
1707  sizeofexpression soet = SIZEOFEXPRESSION(CAR(CDR(soel)));
1708  sinks = sizeofexpression_to_points_to_sinks(soet, cet, in);
1709  break;
1710  }
1711  default:
1712  pips_internal_error("unknown expression tag %d\n", tt);
1713  break;
1714  }
1715 
1716  ifdebug(1) {
1717  type e_t = expression_to_type(e);
1718  type e_c_t = compute_basic_concrete_type(e_t);
1719  type f_e_t = e_c_t;
1720  bool free_f_e_t = false;
1721  if(eval_p) {
1722  if(pointer_type_p(e_c_t))
1723  f_e_t = type_to_pointed_type(e_c_t);
1724  else if(array_type_p(e_c_t)) {
1725  // free_f_e_t = true;
1726  // f_e_t = array_type_to_pointer_type(e_c_t);
1727  type et = array_type_to_element_type(e_c_t);
1728  if(pointer_type_p(et)) {
1729  f_e_t = type_to_pointed_type(et);
1730  }
1731  else {
1732  pips_internal_error("could be a struct - not implemented");
1733  }
1734  }
1735  }
1736  FOREACH(CELL, s, sinks) {
1737  if(!null_cell_p(s)) {
1739  /* This test does not make sense for pointer19.c. Since the
1740  sink_cell is saturated with indices, its type is
1741  double. e_c_t is a 3-D array of pointers to double, f_e_t is a
1742  pointer towards a 2-D array of pointers to double... What
1743  could be checked here? */
1744  /* This test does not make sence for pointer22.c either. We
1745  only need to check that the sink reference can be modified
1746  by dropping a few subscript to match the pointer type. */
1747  if(!array_pointer_string_type_equal_p(f_e_t, s_t)) {
1748  if(array_type_p(f_e_t)) {
1749  type et = array_type_to_element_type(e_c_t);
1750  if(pointer_type_p(et)) {
1751  type pet = type_to_pointed_type(et);
1752  if(!array_pointer_string_type_equal_p(pet, s_t)) {
1755  ; // pips_internal_error("Possible type discrepancy\n");
1756  }
1757  free_reference(sink_r);
1758  }
1759  else {
1760  ; // We are fine
1761  }
1762  }
1763  else {
1764  if(!array_pointer_string_type_equal_p(et, s_t)) {
1765  pips_internal_error("Type discrepancy\n");
1766  }
1767  else {
1768  ; // We are fine
1769  }
1770  }
1771  }
1772  else {
1773  if((char_star_type_p(e_t) || string_type_p(e_t))
1775  ;
1776  else
1777  pips_internal_error("Type discrepancy\n");
1778  }
1779  }
1780  }
1781  }
1782  free_type(e_t);
1783  if(free_f_e_t) free_type(f_e_t);
1784  }
1785 
1786  return sinks;
1787 }
1788 
1789 /* The returned list contains cells used in "in". They should be copied
1790  * if they must be changed by side effects or "in" will become
1791  * inconsistent.
1792  *
1793  * This function computes the possible constant values of a pointer expression.
1794  */
1796 {
1797  list sinks = expression_to_points_to_cells(e, in, true, true);
1798 
1799  return sinks;
1800 }
1801 
1802 /* expression_to_points_to_sources() does not always work, especially
1803  with pointer arithmetic or subscripting because p[3], for instance,
1804  is not recognized as a valid source: it is not a constant path */
1806 {
1807  list sinks = expression_to_points_to_cells(e, in, false, true);
1808 
1809  /* Scalar pointers are expected but [0] subscript may have been added */
1811  /* Trouble for fread04... An array element, _line_3[0], is reduced
1812  to an array, _line_3, and you want to capture its address */
1813  // sinks = reduce_cells_to_pointer_type(sinks);
1814  ;
1815  }
1816 
1817  ifdebug(1) {
1818  bool to_be_freed;
1819  type tmp_t = points_to_expression_to_type(e, &to_be_freed);
1820  type et = compute_basic_concrete_type(tmp_t);
1821  FOREACH(CELL, c, sinks) {
1822  if(!null_cell_p(c)) {
1823  bool to_be_freed2;
1824  type ct = points_to_cell_to_type(c, &to_be_freed2);
1826  // Type compatibility check. To be improved with integer used
1827  // as pointer values...
1828  if(!array_pointer_type_equal_p(et, cct)
1829  // Dereferencement via a subscript
1830  && !array_element_type_p(et, cct)
1831  // Constant strings such as "hello"
1832  && !((char_star_type_p(et) || string_type_p(et))
1834  // Dereferencement forced by the syntax of the expression
1835  && !(pointer_type_p(et)
1837  /* A useless [0] may have been added, but it is supposed to
1838  be taken care of above... by callers of this function. */
1839  ifdebug(1) {
1840  pips_debug(1, "Type mismatch for expression: "); print_expression(e);
1841  fprintf(stderr, " with type: "); print_type(et);
1842  fprintf(stderr, "\nand cell: "); print_points_to_cell(c);
1843  fprintf(stderr, " with type: "); print_type(cct);
1844  fprintf(stderr, "\n");
1845 
1846  }
1847  print_expression(e);
1848  pips_internal_error("Type error for an expression\n.");
1849  }
1850  if(to_be_freed2) free_type(ct);
1851  }
1852  }
1853  if(to_be_freed) free_type(tmp_t);
1854  }
1855 
1856  return sinks;
1857 }
1858 
1860 {
1861  list sinks = reference_to_sinks(r, in, false);
1862  bool must_p = false;
1863 
1864  if(gen_length(sinks)==1) {
1865  // It is a must arc
1866  cell c = CELL(CAR(sinks));
1867  must_p = null_cell_p(c);
1868  }
1869  gen_free_list(sinks);
1870  return must_p;
1871 }
1872 
1874 {
1875  list sinks = reference_to_sinks(r, in, false);
1876  bool may_p = false;
1877 
1878  FOREACH(CELL, c, sinks) {
1879  if(null_cell_p(c)) {
1880  may_p = true;
1881  break;
1882  }
1883  }
1884 
1885  gen_free_list(sinks);
1886  return may_p;
1887 }
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 make_approximation_may(void)
Definition: effects.c:179
descriptor make_descriptor_none(void)
Definition: effects.c:442
cell copy_cell(cell p)
CELL.
Definition: effects.c:246
points_to make_points_to(cell a1, cell a2, approximation a3, descriptor a4)
void free_reference(reference p)
Definition: ri.c:2050
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
void free_expression(expression p)
Definition: ri.c:853
reference copy_reference(reference p)
REFERENCE.
Definition: ri.c:2047
void free_type(type p)
Definition: ri.c:2658
sensitivity_information make_sensitivity_information(statement current_stmt, entity current_module, list enclosing_flow)
entity malloc_to_abstract_location(expression malloc_exp, sensitivity_information *psi)
generate an abstract heap location entity
#define add_arc_to_pt_map(a, s)
#define pt_map_undefined_p(pt)
#define consistent_pt_map_p(s)
#define clear_pt_map(pt)
#define free_pt_map(pt)
entity entity_null_locations()
return TOP-LEVEL:NULL_POINTER The NULL pointer should be a global variable, unique for all modules FI...
entity entity_typed_anywhere_locations(type t)
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
reference make_anywhere_reference(type t)
This function should be located somewhere in effect-util in or near abstract 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...
entity entity_all_locations()
eturn ANY_MODULE:ANYWHERE (the top of the lattice)
cell make_anywhere_cell(type t)
void const char const char const int
entity MakeIoFileArray(entity f)
This array is pointed by FILE * pointers returned or used by fopen, fclose,...
Definition: bootstrap.c:5705
cell make_nowhere_cell()
This file contains all the operators defining constant paths :
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 expression_to_points_to_cell_p(expression e)
Can expression e be reduced to a reference, without requiring an evaluation?
list dereferencing_to_sinks(expression a, pt_map in, bool eval_p)
Returns "sinks", the list of cells pointed to by expression "a" according to points-to graph "in".
#define ANYWHERE_LOCATION
type points_to_reference_to_concrete_type(reference)
Definition: type.c:685
cell make_anywhere_points_to_cell(type)
Function storing points to information attached to a statement.
Definition: points_to.c:87
type points_to_cell_to_type(cell, bool *)
FI: I need more generality than is offered by cell_to_type()
Definition: type.c:665
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
type points_to_cell_to_concrete_type(cell)
Definition: type.c:676
type points_to_expression_to_pointed_type(expression)
Return a new allocated type "t" of the address pointed by expression "e", if expression "e" denotes a...
Definition: type.c:631
type points_to_expression_to_type(expression, bool *)
FI: I need more generality than is offered by expression_to_type() because fields are assimilated to ...
Definition: type.c:592
bool anywhere_cell_p(cell)
Is it an anywhere cell?
Definition: effects.c:367
bool all_heap_locations_cell_p(cell)
Definition: effects.c:432
type points_to_expression_to_concrete_type(expression)
The type returned is stored in a hash-table.
Definition: type.c:617
bool nowhere_cell_p(cell)
Target of an undefined pointer.
Definition: effects.c:455
bool points_to_array_reference_p(reference)
Is this a reference to an array or a reference to a pointer? This is not linked to the type of the re...
Definition: points_to.c:599
bool adapt_reference_to_type(reference, type, int(*)(void))
FI: a really stupid function...
Definition: type.c:1327
void complete_points_to_reference_with_zero_subscripts(reference)
Definition: points_to.c:745
string effect_reference_to_string(reference)
Definition: prettyprint.c:155
void points_to_reference_update_final_subscripts(reference, list)
Substitute the subscripts "sl" in points-to reference "r" just after the last field subscript by "nsl...
Definition: points_to.c:278
bool null_cell_p(cell)
Definition: effects.c:466
void points_to_cell_add_zero_subscripts(cell)
Definition: effects.c:1615
bool heap_cell_p(cell)
Any heap cell, more or less abstract or typed.
Definition: effects.c:420
#define cell_reference(x)
Definition: effects.h:469
#define cell_reference_p(x)
Definition: effects.h:467
#define cell_gap_p(x)
Definition: effects.h:473
#define CELL(x)
CELL.
Definition: effects.h:424
#define cell_tag(x)
Definition: effects.h:466
#define cell_preference_p(x)
Definition: effects.h:470
char * get_string_property(const char *)
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
void gen_full_free_list(list l)
Definition: genClib.c:1023
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
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#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
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
#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 pips_user_error
Definition: misc-local.h:147
#define same_string_p(s1, s2)
int tag
TAG.
Definition: newgen_types.h:92
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
void check_type_of_points_to_cells(list sinks, type ct, bool eval_p)
Check that all cells in list "sinks" are compatible with type "ct" if "eval_p" is false,...
Definition: expression.c:1214
pt_map condition_to_points_to(expression c, pt_map in, bool true_p)
Update points-to set "in" according to the content of the expression using side effects.
Definition: expression.c:2512
void offset_points_to_cells(list sinks, expression delta, type t)
Each cell in sinks is replaced by a cell located "delta" elements further up in the memory.
Definition: expression.c:1020
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.
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.
list reference_to_sinks(reference, pt_map, bool)
pt_map full_copy_pt_map(pt_map)
Definition: statement.c:67
set merge_points_to_set(set, set)
Merge two points-to sets.
list variable_to_pointer_locations(entity)
variable.c
Definition: variable.c:66
void remove_impossible_arcs_to_null(list *, pt_map)
You know that null and undefined cells in "*pL" are impossible because of the operation that is going...
int points_to_context_statement_line_number(void)
Definition: statement.c:120
list source_to_sinks(cell, pt_map, bool)
Return a list of cells, "sinks", that are sink for some arc whose source is "source" or related to "s...
bool consistent_points_to_graph_p(points_to_graph)
#define points_to_undefined
#define points_to_graph_undefined_p(x)
#define points_to_graph_bottom(x)
#define points_to_graph_set(x)
void print_expression(expression e)
no file descriptor is passed to make is easier to use in a debugging stage.
Definition: expression.c:58
void print_reference(reference r)
Definition: expression.c:142
#define print_points_to_cells(x)
Definition: print.c:379
#define print_points_to_cell(x)
Definition: print.c:377
void print_type(type)
For debugging.
Definition: type.c:111
static bool constant_p(entity e)
This function return a bool indicating if related entity e represents a constant.
#define ENTITY_PLUS_UPDATE_P(e)
#define ENTITY_CALLOC_SYSTEM_P(e)
#define ENTITY_FREE_SYSTEM_P(e)
#define ENTITY_ASSIGN_P(e)
#define ENTITY_MINUS_P(e)
#define ENTITY_COMMA_P(e)
#define ENTITY_DEREFERENCING_P(e)
#define ENTITY_PLUS_P(e)
#define ENTITY_POINT_TO_P(e)
#define ENTITY_PRE_DECREMENT_P(e)
#define ENTITY_POST_DECREMENT_P(e)
#define DEREFERENCING_OPERATOR_NAME
Definition: ri-util-local.h:93
#define ENTITY_FOPEN_P(e)
#define ENTITY_POST_INCREMENT_P(e)
#define ENTITY_REALLOC_SYSTEM_P(e)
#define ENTITY_CONDITIONAL_P(e)
#define unary_intrinsic_expression(name, e)
Building quickly bool expressions, FC.
#define ENTITY_PRE_INCREMENT_P(e)
#define binary_intrinsic_expression(name, e1, e2)
#define ENTITY_PLUS_C_P(e)
#define ENTITY_FIELD_P(e)
C data structure and pointer management.
#define ENTITY_MINUS_C_P(e)
#define UNARY_MINUS_OPERATOR_NAME
#define ENTITY_MALLOC_SYSTEM_P(e)
#define ENTITY_ADDRESS_OF_P(e)
#define ENTITY_MINUS_UPDATE_P(e)
#define MULTIPLY_OPERATOR_NAME
#define PLUS_C_OPERATOR_NAME
bool entity_array_p(entity e)
Is e a variable with an array type?
Definition: entity.c:754
entity FindOrCreateTopLevelEntity(const char *name)
Return a top-level entity.
Definition: entity.c:1603
value EvalExpression(expression e)
Evaluate statically an expression.
Definition: eval.c:108
expression reference_to_expression(reference r)
Definition: expression.c:196
bool zero_expression_p(expression e)
Definition: expression.c:1217
expression make_unbounded_expression()
Definition: expression.c:4339
expression make_zero_expression(void)
Make a zero expression.
Definition: expression.c:1212
expression int_to_expression(_int i)
transform an int into an expression and generate the corresponding entity if necessary; it is not cle...
Definition: expression.c:1188
bool unbounded_dimension_p(dimension dim)
bool unbounded_dimension_p(dim) input : a dimension of an array entity.
Definition: expression.c:1130
expression MakeUnaryCall(entity f, expression a)
Creates a call expression to a function with one argument.
Definition: expression.c:342
bool unbounded_expression_p(expression e)
Definition: expression.c:4329
reference reference_with_store_independent_indices(reference r)
Return by side effect a reference whose memory locations includes the memory locations of r in case t...
Definition: expression.c:3045
expression pointer_reference_to_expression(reference r)
Assume p is a pointer.
Definition: expression.c:4004
list subscript_expressions_to_constant_subscript_expressions(list sl)
make a full copy of the subscript expression list, preserve constant subscripts, replace non-constant...
Definition: expression.c:3981
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
type expression_to_type(expression)
For an array declared as int a[10][20], the type returned for a[i] is int [20].
Definition: type.c:2486
type make_scalar_overloaded_type(void)
Definition: type.c:726
bool array_element_type_p(type, type)
is "et" the type of an element of an array of type "at"?
Definition: type.c:684
bool array_of_pointers_type_p(type)
Definition: type.c:3025
bool scalar_integer_type_p(type)
Definition: type.c:3276
bool scalar_type_p(type)
Definition: type.c:2955
int variable_dimension_number(variable)
Definition: type.c:5632
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 array_pointer_type_equal_p(type, type)
assume that a pointer to type x is equal to a 1-D array of x
Definition: type.c:609
bool 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
int NumberOfDimension(entity)
Definition: size.c:588
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 char_star_type_p(type)
Beware of typedefs.
Definition: type.c:5774
bool string_type_p(type)
Definition: type.c:2854
type type_to_returned_type(type)
returns t if t is not a functoional type, and the returned type if t is a functional type.
Definition: type.c:5316
#define value_tag(x)
Definition: ri.h:3064
#define value_constant(x)
Definition: ri.h:3073
#define syntax_reference(x)
Definition: ri.h:2730
#define syntax_tag(x)
Definition: ri.h:2727
#define reference_undefined
Definition: ri.h:2302
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define SIZEOFEXPRESSION(x)
SIZEOFEXPRESSION.
Definition: ri.h:2364
#define sizeofexpression_type(x)
Definition: ri.h:2406
#define constant_int(x)
Definition: ri.h:850
#define sizeofexpression_expression(x)
Definition: ri.h:2409
#define syntax_cast(x)
Definition: ri.h:2739
#define syntax_application(x)
Definition: ri.h:2748
#define syntax_va_arg(x)
Definition: ri.h:2751
#define type_variable(x)
Definition: ri.h:2949
@ is_value_intrinsic
Definition: ri.h:3034
@ is_value_unknown
Definition: ri.h:3035
@ is_value_constant
Definition: ri.h:3033
@ is_value_code
Definition: ri.h:3031
@ is_value_symbolic
Definition: ri.h:3032
#define syntax_range(x)
Definition: ri.h:2733
@ is_syntax_range
Definition: ri.h:2692
@ is_syntax_application
Definition: ri.h:2697
@ is_syntax_cast
Definition: ri.h:2694
@ is_syntax_call
Definition: ri.h:2693
@ is_syntax_va_arg
Definition: ri.h:2698
@ is_syntax_reference
Definition: ri.h:2691
@ is_syntax_sizeofexpression
Definition: ri.h:2695
@ is_syntax_subscript
Definition: ri.h:2696
#define value_constant_p(x)
Definition: ri.h:3071
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define cast_expression(x)
Definition: ri.h:747
#define subscript_indices(x)
Definition: ri.h:2563
#define type_undefined_p(x)
Definition: ri.h:2884
#define entity_undefined
Definition: ri.h:2761
#define constant_int_p(x)
Definition: ri.h:848
#define expression_undefined
Definition: ri.h:1223
#define type_void_p(x)
Definition: ri.h:2959
#define entity_name(x)
Definition: ri.h:2790
#define dimension_upper(x)
Definition: ri.h:982
#define reference_indices(x)
Definition: ri.h:2328
#define sizeofexpression_expression_p(x)
Definition: ri.h:2407
#define sizeofexpression_type_p(x)
Definition: ri.h:2404
#define syntax_call(x)
Definition: ri.h:2736
#define cast_type(x)
Definition: ri.h:745
#define subscript_array(x)
Definition: ri.h:2561
#define application_function(x)
Definition: ri.h:508
#define variable_dimensions(x)
Definition: ri.h:3122
#define syntax_subscript(x)
Definition: ri.h:2745
#define call_arguments(x)
Definition: ri.h:711
#define entity_type(x)
Definition: ri.h:2792
#define expression_syntax(x)
Definition: ri.h:1247
#define statement_undefined
Definition: ri.h:2419
#define entity_initial(x)
Definition: ri.h:2796
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
#define ifdebug(n)
Definition: sg.c:47
static int malloc_counter
Definition: sinks.c:1177
list reference_to_points_to_sinks(reference r, type et, pt_map in, bool eval_p, bool constant_p)
Returns a list of memory cells "sinks" possibly accessed by the evaluation of reference "r".
Definition: sinks.c:755
list entity_to_sinks(entity e)
allocate a new list of sinks with one element, abstract or concrete, e.
Definition: sinks.c:72
list range_to_points_to_sinks(range r, pt_map in)
Definition: sinks.c:1626
expression pointer_subscript_to_expression(cell c, list csl)
Allocate a new expression based on the reference in "c" and the subscript list "csl".
Definition: sinks.c:1430
list expression_to_points_to_cells(expression e, pt_map in, bool eval_p, bool constant_p)
Return a possibly empty list of abstract locations whose addresses are possible value of expression "...
Definition: sinks.c:1650
static list process_casted_sinks(list sinks, type t)
Definition: sinks.c:979
list subscript_to_points_to_sinks(subscript s, type et, pt_map in, bool eval_p)
Generate the corresponding points-to reference(s).
Definition: sinks.c:1451
list pointer_reference_to_points_to_sinks(reference r, pt_map in, bool eval_p)
What to do when a pointer "p" is dereferenced within a reference "r".
Definition: sinks.c:709
statement get_heap_statement()
Definition: sinks.c:1191
static statement malloc_statement
Heap modelling.
Definition: sinks.c:1175
list unique_malloc_to_points_to_sinks(expression e)
FI->AM: is "unique" multiple when ALIASING_ACROSS_TYPE is set to false?
Definition: sinks.c:1292
list cast_to_points_to_sinks(cast ce, type et __attribute__((unused)), pt_map in, bool eval_p)
Handling of cast: play it safe! Either the cast is partly redundant and can be ignored or anywhere is...
Definition: sinks.c:1091
list sizeofexpression_to_points_to_sinks(sizeofexpression soe, type et __attribute__((unused)), pt_map in)
Definition: sinks.c:1139
list malloc_to_points_to_sinks(expression e, pt_map in)
Heap modelling.
Definition: sinks.c:1231
cell entity_to_cell(entity e)
Definition: sinks.c:80
reference simplified_reference(reference r)
Return NULL as sink.
Definition: sinks.c:670
list insensitive_malloc_to_points_to_sinks(expression e)
FI->AM: what's the difference with the previous option? Reference to your dissertation?
Definition: sinks.c:1312
cell make_null_cell(void)
Definition: sinks.c:95
list points_to_null_sinks()
Definition: sinks.c:87
list points_to_anywhere_sinks(type t)
Definition: sinks.c:102
bool reference_must_points_to_null_p(reference r, pt_map in)
Definition: sinks.c:1859
static list process_casted_sources(list sinks, type t)
FI: I am not sure that process_casted_sources() is nor should be different from process_casted_sinks(...
Definition: sinks.c:1035
bool reference_may_points_to_null_p(reference r, pt_map in)
Definition: sinks.c:1873
list unary_intrinsic_call_to_points_to_sinks(call c, pt_map in, bool eval_p, bool constant_p)
Definition: sinks.c:216
void init_heap_model(statement s)
Definition: sinks.c:1179
list nary_intrinsic_call_to_points_to_sinks(call c, pt_map in)
Definition: sinks.c:640
void reset_heap_model()
Definition: sinks.c:1185
list expression_to_points_to_sources(expression e, pt_map in)
expression_to_points_to_sources() does not always work, especially with pointer arithmetic or subscri...
Definition: sinks.c:1805
list flow_sensitive_malloc_to_points_to_sinks(expression e)
Definition: sinks.c:1321
list binary_intrinsic_call_to_points_to_sinks(call c, pt_map in, bool eval_p)
Definition: sinks.c:327
list intrinsic_call_to_points_to_sinks(call c, pt_map in, bool eval_p, bool constant_p)
Definition: sinks.c:172
list ternary_intrinsic_call_to_points_to_sinks(call c, pt_map in, bool eval_p, bool constant_p)
Definition: sinks.c:594
list expression_to_points_to_sinks_with_offset(expression a1, expression a2, pt_map in)
Definition: sinks.c:546
int get_heap_counter()
Definition: sinks.c:1197
list application_to_points_to_sinks(application a, type et __attribute__((unused)), pt_map in)
Definition: sinks.c:1388
list call_to_points_to_sinks(call c, type et, pt_map in, bool eval_p, bool constant_p)
Definition: sinks.c:112
list expression_to_points_to_sinks(expression e, pt_map in)
The returned list contains cells used in "in".
Definition: sinks.c:1795
Definition: pip__tab.h:30
The structure used to build lists in NewGen.
Definition: newgen_list.h:41