PIPS
points_to.c
Go to the documentation of this file.
1 /*
2 
3  $Id: points_to.c 23412 2017-08-09 15:07:09Z irigoin $
4 
5  Copyright 1989-2016 MINES ParisTech
6  Copyright 2009-2010 HPC Project
7 
8  This file is part of PIPS.
9 
10  PIPS is free software: you can redistribute it and/or modify it
11  under the terms of the GNU General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  any later version.
14 
15  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
16  WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  FITNESS FOR A PARTICULAR PURPOSE.
18 
19  See the GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
23 
24 */
25 #ifdef HAVE_CONFIG_H
26  #include "pips_config.h"
27 #endif
28 
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 
33 #include "genC.h"
34 #include "linear.h"
35 #include "ri.h"
36 #include "effects.h"
37 #include "ri-util.h"
38 #include "prettyprint.h"
39 
40 #include "effects-util.h"
41 #include "text-util.h"
42 
43 #include "misc.h"
44 #include "properties.h"
45 
46 /***************************************/
47 /* Function storing points to information attached to a statement
48  */
49 
50 /* Generate a global variable holding a statement_points_to, a mapping
51  * from statements to lists of points-to arcs. The variable is called
52  * "pt_to_list_object".
53  *
54  * The macro also generates a set of functions used to deal with this global variables.
55  *
56  * The functions are defined in newgen_generic_function.h:
57  *
58  * pt_to_list_undefined_p()
59  *
60  * reset_pt_to_list()
61  *
62  * error_reset_pt_to_list()
63  *
64  * set_pt_to_list(o)
65  *
66  * get_pt_to_list()
67  *
68  * store_pt_to_list(k, v)
69  *
70  * update_pt_to_list(k, v)
71  *
72  * load_pt_to_list(k)
73  *
74  * delete_pt_to_list(k)
75  *
76  * bound_pt_to_list_p(k)
77  *
78  * store_or_update_pt_to_list(k, v)
79 */
81 
82 /* Functions specific to points-to analysis
83 */
84 
85 /*
86  */
88 {
90  if(get_bool_property("ALIASING_ACROSS_TYPES"))
92  else
96  return c;
97 }
98 
100 {
101  bool formal_p = true;
103  entity v = reference_variable(r);
104  formal_p = formal_parameter_p(v);
105  return formal_p;
106 }
107 
109 {
110  bool formal_p = true;
112  entity v = reference_variable(r);
113  formal_p = entity_stub_sink_p(v); // FI: can be a source too
114  return formal_p;
115 }
116 
118 {
119  bool found_p = false;
120  FOREACH(CELL, lc, L) {
121  if(cell_equal_p(c,lc)) {
122  found_p =true;
123  break;
124  }
125  }
126  return found_p;
127 }
128 
129 /* Add in "l1" elements of "l2" that are not yet in "l1". List "l2" is
130  * then destroyed.
131  *
132  * This is a set union.
133  */
135 {
136  list lt = NIL;
137  FOREACH(CELL, c2, l2) {
138  if(!points_to_cell_in_list_p(c2, l1)) {
139  lt = CONS(CELL,c2, lt);
140  }
141  }
142  lt = gen_nreverse(lt);
143  l1 = gen_nconc(l1, lt);
144  gen_free_list(l2);
145  return l1;
146 }
147 
148 /* Two cells are related if they are based on the same entity */
150 {
151  bool found_p = false;
153  entity ec = reference_variable(rc);
154  FOREACH(CELL, lc, L) {
155  reference rlc = cell_any_reference(lc);
156  entity elc = reference_variable(rlc);
157  if(ec==elc) {
158  found_p =true;
159  break;
160  }
161  }
162  return found_p;
163 }
164 
166 {
167  bool related_p = false;
168  reference rc1 = cell_any_reference(c1);
169  entity ec1 = reference_variable(rc1);
170  reference rc2 = cell_any_reference(c2);
171  entity ec2 = reference_variable(rc2);
172  related_p = (ec1==ec2);
173  return related_p;
174 }
175 
176  /* Debug: print a cell list for points-to. Parameter f is not useful
177  in a debugging context. */
178 void fprint_points_to_cell(FILE * f __attribute__ ((unused)), cell c)
179 {
180  int dn = cell_domain_number(c);
181 
182  // For debugging with gdb, dynamic type checking
183  if(dn==cell_domain) {
184  if(cell_undefined_p(c))
185  fprintf(stderr, "cell undefined\n");
186  else {
188  print_reference(r);
189  }
190  }
191  else
192  fprintf(stderr, "Not a Newgen cell object\n");
193 }
194 
195 /* Debug: use stderr */
197 {
198  fprint_points_to_cell(stderr, c);
199 }
200 
201 /* Debug */
203 {
204  if(ENDP(cl))
205  fprintf(stderr, "Empty cell list");
206  else {
208  FOREACH(CELL, c, cl) {
210  entity v = reference_variable(r);
211  /* *ANY_MODULE* is unfortunately not an entity... */
213  if(!entity_undefined_p(mv) && m!=mv)
214  fprintf(stderr,"%s" MODULE_SEP_STRING, entity_local_name(mv));
216  if(!ENDP(CDR(cl)))
217  fprintf(stderr, ", ");
218  }
219  }
220  fprintf(stderr, "\n");
221 }
222 
223 /* Check if expression "e" is a reference to a struct field. */
225 {
226  bool field_p = false;
227  syntax s = expression_syntax(e);
228  if(syntax_reference_p(s)) {
231  field_p = entity_field_p(f);
232  }
233  return field_p;
234 }
235 
236 /* Compute the number of array subscript at the end of a points_to_reference
237  *
238  * Look for the last field subscript and count the number of
239  * subscripts after it. If no field susbcript is found, then all
240  * subscripts are final array subscripts.
241  *
242  * To make thinks easier, the subscript list is reversed.
243  */
245 {
246  list sl = reference_indices(r);
247  sl = gen_nreverse(sl);
248  int d = 0;
249  FOREACH(EXPRESSION, e, sl) {
251  break;
252  else
253  d++;
254  }
255  sl = gen_nreverse(sl);
256  reference_indices(r) = sl;
257  return d;
258 }
259 
260 /* Substitute the subscripts "sl" in points-to reference "r" just after the
261  * last field subscript by "nsl".
262  *
263  * "sl" must be broken into three parts, possibly empty:
264  *
265  * 1. The first part that ends up at the last field reference. It may
266  * be empty when no field is referenced.
267  *
268  * 2. The second part that starts just after the last field reference
269  * and that counts at most as many elements as the new subscript
270  * list, "nsl". This part must be substituted.
271  *
272  * 3. The third part that is left unchanged after substitution.
273  *
274  * Issue: how do you know that the initial array subscript must be
275  * preserved because it is an implicit dimension added for pointer
276  * arithmetics?
277  */
279 {
280  list sl = reference_indices(r);
281  list sl1 = NIL, sl3 = NIL, sl23 = NIL;
282 
283  sl = gen_nreverse(sl); // sl1 and sl23 are built in the right order
284  bool found_p = false;
285  bool skip_one_p = false; // to skip indices added for pointer arithmetic
286  FOREACH(EXPRESSION, e, sl) {
288  type et = expression_to_type(e);
289  if(pointer_type_p(et))
290  skip_one_p = true;
291  found_p = true;
292  free_type(et);
293  }
294  if(found_p) {
295  /* build sl1 */
296  sl1 = CONS(EXPRESSION, e , sl1);
297  }
298  else
299  sl23 = CONS(EXPRESSION, e , sl23);
300  }
301 
302  if(skip_one_p && ENDP(sl23) && !ENDP(nsl)) {
303  pips_internal_error("We are not generating a memory access constant path.\n");
304  }
305 
306  // FI: place the new indices as early as possible
307 #if 0
308  int n = (int) gen_length(nsl);
309  int i = 0;
310  FOREACH(EXPRESSION, e, sl23) {
311  if(skip_one_p) {
312  sl1 = gen_nconc(sl1, CONS(EXPRESSION, e , NIL));
313  skip_one_p = false;
314  }
315  else {
316  if(i<n)
317  free_expression(e);
318  else
319  sl3 = gen_nconc(sl3, CONS(EXPRESSION, e, NIL));
320  i++;
321  }
322  }
323 
324  sl = gen_nconc(sl1, nsl);
325  sl = gen_nconc(sl, sl3);
326 #endif
327 
328  // FI: place the new indices as late as possible
329  int n = (int) gen_length(nsl);
330  int n23 = (int) gen_length(sl23);
331  int i = 0;
332  FOREACH(EXPRESSION, e, sl23) {
333  if(i>=n23-n)
334  free_expression(e);
335  else
336  sl3 = gen_nconc(sl3, CONS(EXPRESSION, e, NIL));
337  i++;
338  }
339 
340  sl = gen_nconc(sl1, sl3);
341  sl = gen_nconc(sl, nsl);
342 
343  gen_free_list(sl23);
344  reference_indices(r) = sl;
345 
346  // We do not want to generate indirection in the reference
347  // The exactitude information is not relevant here
348  // bool exact_p;
349  // pips_assert("The reference is a constant memory access path",
350  // !effect_reference_dereferencing_p( r, &exact_p));
351  // Might only work for standard references and not for points-to
352  // references: core dumps with points-to references.
353 }
354 
355 /* Look for the index in "r" that corresponds to a pointer of type "t"
356  * and return the corresponding element list. In other words, the type
357  * of "&r" is "t".
358  *
359  * It is done in a very inefficient way
360  */
362 {
363  bool to_be_freed;
364  type rt = points_to_reference_to_type(r, &to_be_freed);
365  list rsl = reference_indices(r); // reference subscript list
366  pips_assert("t is a pointer type", C_pointer_type_p(t));
368  list psl = list_undefined; // pointed subscript list
369 
370  if(array_pointer_type_equal_p(rt, pt))
371  psl = gen_last(rsl);
372  else {
373  if(to_be_freed) free_type(rt);
374  entity v = reference_variable(r);
375  list nl = NIL;
376  int i;
377  int n = (int) gen_length(rsl);
378  reference nr = make_reference(v, nl);
379  bool found_p = false;
380 
381  for(i=0;i<n;i++) {
382  nl = gen_nconc(nl, CONS(EXPRESSION,
384  NIL));
385  reference_indices(nr) = nl;
386  rt = points_to_reference_to_type(nr, &to_be_freed);
387  if(array_pointer_type_equal_p(rt, pt)) {
388  found_p = true;
389  break;
390  }
391  }
392 
393  free_reference(nr);
394 
395  if(found_p)
396  psl = gen_nthcdr(i, rsl);
397  else {
398  // The issue may be due to a user bug, as was the case in
399  // Strict_typing.sub/malloc03.c
400  if(entity_heap_location_p(v)) {
401  // It would be nice to have a current statement stack...
402  pips_user_error("The dynamic allocation of \"%s\" is likely "
403  "to be inadequate with its use in the current "
404  "statement.\n", entity_local_name(v));
405  }
406  else
407  pips_internal_error("Type not found.\n");
408  }
409  }
410 
411  free_type(pt);
412 
413  return psl;
414 }
415 
416 /* Is it a unique concrete memory location?
417  *
418  * Plus NULL? No doubt about the value of the pointer...
419  *
420  * Plus undefined? No doubt about the indeterminate value of the
421  * pointer according to C standard...
422  */
424 {
426  bool atomic_p = null_cell_p(c)
427  || nowhere_cell_p(c) // FI: added for EffectsWithPointsTo/call30.c
429 
430  // FI: atomic_p should be false for all abstract locations
431  // This is dealt with by atomic_points_to_reference_p()
432  /*
433  if(atomic_p && (heap_cell_p(c) || all_heap_locations_cell_p(c)))
434  atomic_p = false;
435 
436  if(atomic_p) {
437  atomic_p = !cell_abstract_location_p(c);
438  }
439  */
440 
441  return atomic_p;
442 }
443 
444 /* Is it a unique concrete memory location?
445  *
446  * If strict_p, stubs are not considered atomic, as is the case in an
447  * interprocedural setting since they can be associated to several
448  * cells in the caller frame.
449  *
450  * Else, stubs are not considered non atomic per se.
451  */
452 bool generic_atomic_points_to_cell_p(cell c, bool strict_p)
453 {
455  bool atomic_p = null_cell_p(c)
456  || generic_atomic_points_to_reference_p(r, strict_p);
457 
458  return atomic_p;
459 }
460 
461 /* Is it a unique concrete memory location?
462  *
463  * No, if it is a reference to an abstract location.
464  *
465  * No, if the subscripts include an unbounded expression.
466  *
467  * Very preliminary version. One of the keys to Amira Mensi's work.
468  *
469  * More about stubs: a stub is not NULL but there is no information to
470  * know if they represent one address or a set of addresses. Unless
471  * the intraprocedural points-to analysis is performed for each
472  * combination of atomic/non-atomic stub, safety implies that
473  * stub-based references are not atomic (strict_p=true). In some other
474  * cases, you know that a stub does represent a unique location
475  * (strict_p=false).
476  *
477  * Note: it is assumed that the reference is a points-to
478  * reference. All subscripts are constants, field references or
479  * unbounded expressions.
480  *
481  * Note: FI, I have a probleme when calling this function from a
482  * proper effects environment. In that case, stubs might be assumed to
483  * be unique memory locations. The exactness information can be
484  * derived from the numer of targets in the matching list.
485  *
486  * Note 2: FI, I do not understand why the type of the reference is
487  * not taken into account.
488  */
490 {
491  bool atomic_p = false;
492  entity v = reference_variable(r);
493 
494  if(!entity_null_locations_p(v) // FI: NULL is considered atomic
498  && !entity_heap_location_p(v)) {
499  list sl = reference_indices(r);
500  //entity v = reference_variable(r);
501  if(!entity_stub_sink_p(v) || !strict_p) {
502  atomic_p = true;
503  FOREACH(EXPRESSION, se, sl) {
504  if(unbounded_expression_p(se)) {
505  atomic_p = false;
506  break;
507  }
508  else if(expression_range_p(se)) {
509  atomic_p = false;
510  break;
511  }
512  }
513  }
514  }
515 
516  return atomic_p;
517 }
518 
520 {
521  return generic_atomic_points_to_reference_p(r, true);
522 }
523 
524 /* points-to cells use abstract addresses, hence the proper comparison
525  * is an intersection. simple references are considered to be
526  * singleton.
527  *
528  * Assume no aliasing between variables and within data structures.
529  *
530  * It is safe to assume intersection...
531  */
533 {
534  bool intersect_p = false;
535  if(cell_equal_p(lc, rc)) {
536  // FI: too simple... All the subscript should be checked.
537  // unbounded expressions should be used to decide about a possible
538  // intersection... Unless this is guarded by
539  // atomic_points_to_reference_p(). To be investigated.
540  intersect_p = true;
541  }
542  else {
543  // Look for abstract domains
544  // Probably pretty complex...
545  // Simple first version...
546  reference lr = cell_any_reference(lc);
547  entity le = reference_variable(lr);
548  reference rr = cell_any_reference(rc);
549  entity re = reference_variable(rr);
550  intersect_p = entities_may_conflict_p(le, re);
551  }
552  return intersect_p;
553 }
554 
555 /* Allocate a cell that is the minimal upper bound of the cells in
556  * list "cl" according to the points-to cell lattice...
557  *
558  * An over-approximation is always safe. So, an anywhere cell, typed
559  * or not, can be returned in a first drat implementation.
560  *
561  * The points-to cell lattice is the product of three lattices, the
562  * module lattice, the type lattice and the abstracct reference
563  * lattice...
564  */
566 {
567 #if 0
571  cell c = make_cell_reference(r);
572 #endif
575  return c;
576 }
577 
579 {
581  return m;
582 }
583 
585 {
586  type t = type_undefined;
587  return t;
588 }
589 
591 {
593  return r;
594 }
595 
596 /* Is this a reference to an array or a reference to a pointer? This
597  is not linked to the type of the reference, as a reference may be a
598  pointer, such as "a[10]" when "a" is declared int "a[10][20]".*/
600 {
601  bool array_p = false;
602  list sl = reference_indices(r);
603  entity v = reference_variable(r);
604 
605  if(ENDP(sl)) {
607  array_p = array_type_p(t);
608  }
609  else {
610  /* Look for the last field among the subscript */
611  list rsl = gen_nreverse(sl);
612  type t = type_undefined;
613  int i = 0;
614  FOREACH(EXPRESSION, se, rsl) {
618  break;
619  }
620  i++;
621  }
622  if(type_undefined_p(t)) {
624  variable vt = type_variable(t);
625  list dl = variable_dimensions(vt);
626  int d = (int) gen_length(dl);
627  int i = (int) gen_length(rsl);
628  if(i<d)
629  array_p = true;
630  }
631  else {
632  if(i==0) { // FI: could be merged with the "else if" clause
633  array_p = array_type_p(t);
634  }
635  else if(array_type_p(t)) {
636  variable vt = type_variable(t);
637  list dl = variable_dimensions(vt);
638  int d = (int) gen_length(dl);
639  if(i<d)
640  array_p = true;
641  }
642  }
644  }
645  return array_p;
646 }
647 
648 /* If this is an array reference, what is the type of the underlying array type?
649  *
650  * This information cannot be obtained by direct type information
651  * because subarrays are typed as pointers to even smaller arrays.
652  *
653  * If it is not an array reference, the returned type is undefined.
654  *
655  * No new type is allocated.
656  */
658 {
659  list sl = reference_indices(r);
660  entity v = reference_variable(r);
661  type t = type_undefined;
662 
663  if(ENDP(sl)) {
665  }
666  else {
667  /* Look for the last field among the subscript */
668  list rsl = gen_nreverse(sl);
669  FOREACH(EXPRESSION, se, rsl) {
673  break;
674  }
675  }
676  if(type_undefined_p(t)) {
678  }
679  else {
680  ;
681  }
683  }
684  return t;
685 }
686 
687 ␌
688 /* Add a set of zero subscripts to a constant memory path reference "r" by side effect.
689  *
690  * Used when a partial array reference must be converted into a
691  * reference to the first array element (zero_p==true) or to any
692  * element (zero_p==false).
693  *
694  * The difficulty lies with field subscripts...
695  */
697 {
698  type t = type_undefined;
699 
700  // FI: this assert makes sense within the ri-util framework but is
701  // too strong for the kind of references used in effects-util
702  // pips_assert("scalar type", ENDP(reference_indices(r)));
703 
704  /* Find the current number of effective subscripts: is there a field
705  subscript somewhere? */
706  list sl = reference_indices(r);
707  entity v = reference_variable(r);
708  list rsl = gen_nreverse(sl); // sl is no longer available
709  int i = 0;
710  bool field_found_p = false;
711 
712  FOREACH(EXPRESSION, se, rsl) {
713  if(field_expression_p(se)) {
717  field_found_p = true;
718  break;
719  }
720  i++;
721  }
722 
723  if(!field_found_p)
725 
726  variable vt = type_variable(t);
727  list dl = variable_dimensions(vt);
728  int d = (int) gen_length(dl);
729 
730  /* FI: this may happen when reference "r" is not a constant memory path */
731  pips_assert("Not too many subscripts wrt the type.\n", i<=d);
732 
733  list nsl = NIL; // subscript list
734  int j;
735  for(j=i+1;j<=d;j++) {
737  // reference_indices(r) = CONS(EXPRESSION, s, reference_indices(r));
738  nsl = CONS(EXPRESSION, s, nsl);
739  }
740 
743 }
744 
746 {
748 }
749 ␌
751 {
752  bool must_p = true;
753  pips_assert("The input list is not empty", !ENDP(cl));
754  FOREACH(CELL, c, cl) {
755  if(!null_cell_p(c)) {
756  must_p = false;
757  break;
758  }
759  }
760  return must_p;
761 }
762 
764 {
765  bool may_not_p = true;
766  pips_assert("The input list is not empty", !ENDP(cl));
767  FOREACH(CELL, c, cl) {
768  if(null_cell_p(c) || nowhere_cell_p(c)) {
769  may_not_p = false;
770  break;
771  }
772  }
773  return may_not_p;
774 }
775 ␌
776 /* A set of functions called cell_points_to_xxxx(cell s, set pts)
777  * where set pts is a points-to relation set.
778  *
779  * The definition domain of these functions is key to their use:
780  *
781  * 1. if the type of the source s is not a pointer type, should we
782  * return false or abort because s is not in the definition domain?
783  *
784  * 2. if source s does not appear at all in pts, should we return
785  * false or abort because s is not in the definition domain?
786  *
787  * If both conditions are selected, the resulting definition domain is
788  * the definition domain of the mapping pts.
789  *
790  * If a more relaxed definition domain is sometimes useful, then
791  * strict and non-strict versions of these functions should be
792  * provided, with a clear semantics for their true and false results.
793  *
794  * Because cell s may point to one or many cells in pts, which is a
795  * relation and not a mapping, the caller may be interested in a may
796  * or must point. The information may be convened directly by using
797  * distinct function names, cell_must_points_to_xxxx or
798  * cell_may_points_to_xxxx, or by adding a pointer to a boolean,
799  * exact_p, in the function profiles, which may save time by not
800  * looping twice on pts arcs.
801  *
802  * This can be implemented using the approximation information of the
803  * arcs in pts... if it is trusted. Or recomputed from the arcs in pts.
804  *
805  * Flexibility is also introduced by the use of cell_equivalent_p()
806  * instead of cell_equal_p(). If the former is used, cells derived
807  * from cell s are considered when s if not a pointer. This leads to
808  * weird behaviors. For instance, if the source s is a struct, s.f1
809  * and s.f2 will be considered. If s.f1 points to some concrete
810  * location and s.f2 points to nowhere (undefined pointer), what
811  * result should be returned? The advantage is that the caller does
812  * not have to generate s.f1 and s.f2 which are simply found in set
813  * pts.
814  */
815 
816 /* Does cell "source" points toward a non null fully defined cell in
817  * points-to set pts?
818  *
819  * The function name is not well chosen. Something like
820  * cell_points_to_defined_cell_p()/
821  */
823 {
824  bool non_null_p = false;
826  pips_assert("The cell is a pointer", !array_type_p(st) && pointer_type_p(st));
827  SET_FOREACH(points_to, pt, pts) {
828  cell pt_source = points_to_source(pt);
829  if(cell_equal_p(pt_source, source)) {
830  //if(cell_equivalent_p(pt_source, source)) {
831  cell pt_sink = points_to_sink(pt);
832  if(null_cell_p(pt_sink))
833  ;
834  else if(nowhere_cell_p(pt_sink))
835  ;
836  else {
837  non_null_p = true;
838  break;
839  }
840  }
841  }
842  return non_null_p;
843 }
844 
846 {
847  bool nowhere_p = false;
849  pips_assert("The cell is a pointer", !array_type_p(st) && pointer_type_p(st));
850  SET_FOREACH(points_to, pt, pts) {
851  cell pt_source = points_to_source(pt);
852  if(cell_equal_p(pt_source, source)) {
853  //if(cell_equivalent_p(pt_source, source)) {
854  cell pt_sink = points_to_sink(pt);
855  if(null_cell_p(pt_sink))
856  ;
857  else if(nowhere_cell_p(pt_sink)) {
858  nowhere_p = true;
859  break;
860  }
861  else {
862  ;
863  }
864  }
865  }
866  return nowhere_p;
867 }
868 
869 /* How are array handled in pts? do we have arcs "a->a"? */
871 {
872  bool nowhere_p = false;
874  pips_assert("The cell is a pointer", !array_type_p(st) && pointer_type_p(st));
875  //type st = points_to_cell_to_concrete_type(source);
876  //if(!array_type_p(st) && pointer_type_p(st)) {
877  SET_FOREACH(points_to, pt, pts) {
878  cell pt_source = points_to_source(pt);
879  if(cell_equal_p(pt_source, source)) {
880  //if(cell_equivalent_p(pt_source, source)) {
881  cell pt_sink = points_to_sink(pt);
882  if(null_cell_p(pt_sink))
883  ;
884  else if(nowhere_cell_p(pt_sink)) {
886  nowhere_p = approximation_must_p(ap) || approximation_exact_p(ap);
887  break;
888  }
889  else {
890  ;
891  }
892  }
893  }
894  //}
895  return nowhere_p;
896 }
897 
899 {
900  bool null_p = false;
902  pips_assert("The cell is a pointer", !array_type_p(st) && pointer_type_p(st));
903  SET_FOREACH(points_to, pt, pts) {
904  cell pt_source = points_to_source(pt);
905  if(cell_equal_p(pt_source, source)) {
906  cell pt_sink = points_to_sink(pt);
907  if(null_cell_p(pt_sink)) {
908  null_p = true;
909  break;
910  }
911  }
912  }
913  return null_p;
914 }
915 ␌
917 {
918  reference r1 = cell_any_reference(c1);
919  reference r2 = cell_any_reference(c2);
920  return reference_equal_p(r1,r2);
921 }
922 
923 /* See if an arc like "spt" exists in set "in", regardless of its
924  * approximation. If yes, returns the approximation of the arc found
925  * in "in".
926  *
927  * See also arc_in_points_to_set_p(), which requires full identity
928  */
930 {
931  bool in_p = false;
932  cell spt_source = points_to_source(spt);
933  cell spt_sink = points_to_sink(spt);
934  SET_FOREACH(points_to, pt, in) {
935  if(points_to_cell_equal_p(spt_source, points_to_source(pt))
936  && points_to_cell_equal_p(spt_sink, points_to_sink(pt))) {
937  *pa = points_to_approximation(pt);
938  in_p = true;
939  break;
940  }
941  }
942  return in_p;
943 }
944 ␌
945 /* Return a list of cells that are larger than cell "c" in the
946  * points-to cell lattice.
947  *
948  * This goal is quite open because a[1][2] is dominated by both
949  * a[*][2] and a[1][*], then by a[*][*]. Assuming "a" is variable of
950  * function "foo", then we have "foo:*STACK*_b0",
951  * "*ANYMODULE*:*STACK*_b0", "foo:*ANYWHERE*_b0",
952  * "*ANYMODULE*:*ANYWHERE*_b0", "*ANYMODULE*:*ANYWHERE*".
953  *
954  * They would all be useful to guarantee the consistency of the
955  * points-to information wrt the points-to cell lattice, but we'd
956  * rather maintain a partially consistent points-to graph and rely on
957  * functions using it to add the necessary points-to arcs.
958  *
959  * A lattice-consistent points-to graph would contain too many arcs as
960  * x->y implies x'->y' for all x' bigger than x and y' bigger then
961  * y...
962  *
963  * For the time being, we only need to convert a[i][j][k] into a[*][*][*]
964  * when i, j and k are real subscript expressions, not fields.
965  *
966  * We return an empty list when cell "c" does not need any upper
967  * bound, as is the case with a, a[f] where f is a field, a[*] and all
968  * the abstract locations.
969  *
970  * So, for the time being, this function returns a list with one or
971  * zero elements.
972  */
974 {
975  list ubl = NIL; // upper bound list
977  entity v = reference_variable(r);
979  list sel = reference_indices(r); // subscript expression list
980  list nsel = NIL; // new subscript expression list
981  bool new_cell_p = false;
982  FOREACH(EXPRESSION, se, sel) {
984  if(integer_expression_p(se)) {
986  new_cell_p = true;
987  }
988  else
989  nse = copy_expression(se);
990  nsel = CONS(EXPRESSION, nse, nsel);
991  }
992  if(new_cell_p) {
993  nsel = gen_nreverse(nsel);
994  reference nr = make_reference(v, nsel);
995  cell nc = make_cell_reference(nr);
996  ubl = CONS(CELL, nc, ubl);
997  }
998  else
999  gen_full_free_list(nsel);
1000  }
1001  return ubl;
1002 }
1003 
1004 /* Add to list "l" cells that are upper bound cells of the cells
1005  * already in list "l" and return list "l".
1006  */
1008 {
1009  list ubl = NIL;
1010  FOREACH(CELL, c, cl) {
1012  ubl = gen_nconc(ubl, cubl);
1013  }
1014  ubl = gen_nconc(cl, ubl);
1015  return ubl;
1016 }
1017 
1018 /* See if the subscript list sl is precise, i.e. if is does not
1019  * contain any unbounded expression.
1020  *
1021  * It is assumed that it is a points-to subscript list. Each subscript
1022  * is either an integer constant, or a field reference or an unbounded
1023  * expression.
1024  *
1025  * This function may have been defined several times...
1026  */
1028 {
1029  bool exact_p = true;
1030  FOREACH(EXPRESSION, s, sl) {
1031  if(unbounded_expression_p(s)) {
1032  exact_p = false;
1033  break;
1034  }
1035  }
1036  return exact_p;
1037 }
1038 
1039 /* Two subscript are compatible if they are equal or if one of them is
1040  unbounded. */
1042 {
1043  bool compatible_p = true;
1044  bool u1 = unbounded_expression_p(s1);
1045  if(!u1) {
1046  bool u2 = unbounded_expression_p(s2);
1047  if(!u2) {
1048  /* In the ponts-to context s1 and s2 should be either integer
1049  constants or field references. */
1050  compatible_p = expression_equal_p(s1, s2);
1051  }
1052  }
1053  return compatible_p;
1054 }
1055 
1056 /* The value of the source can often be expressed with different
1057  * subscript lists. For instance, a, a[0], a[0][0] have different
1058  * types but the same value if a is a 2-D array.
1059  *
1060  * This function allocated a new points-to object whose sink has a
1061  * minimal number of indices.
1062  *
1063  * FI: I have added this function to deal with pointers to arrays. It
1064  * is called from generic_reference_to_points_to_matching_list() to
1065  * try to adapt the points-to information to the undefined
1066  * requirements of Beatrice's functions for regions_with_points_to. I
1067  * do not think the function below is correct when structs are
1068  * involved... The stripping may be useful, but it should be much more careful.
1069  *
1070  * adapt_reference_to_type() might be better here to adjust the
1071  * subscripts in sink.
1072  *
1073  */
1075  int (*line_number_func)(void))
1076 {
1077  cell source = points_to_source(pt);
1078  cell sink = points_to_sink(pt);
1079  cell new_sink_cell = cell_undefined;
1080 
1081  // FI: first implementation
1082  if(false) {
1083  reference source_r = cell_any_reference(source);
1084  list source_sl = reference_indices(source_r);
1085  list c_source_sl = list_undefined;
1086 
1087  reference sink_r = cell_any_reference(sink);
1088  // FI: sink_sl is longer than source_sl if pt is semantically correct
1089  list sink_sl = reference_indices(sink_r);
1090  list c_sink_sl = list_undefined;
1091  entity sink_e = reference_variable(sink_r);
1092 
1093  list new_sink_sl = NIL;
1094  for(c_source_sl = source_sl, c_sink_sl = sink_sl;
1095  !ENDP(c_source_sl);
1096  POP(c_source_sl), POP(c_sink_sl)) {
1097  expression s = copy_expression(EXPRESSION(CAR(c_sink_sl)));
1098  new_sink_sl = CONS(EXPRESSION, s, new_sink_sl);
1099  }
1100  if(!get_bool_property("POINTS_TO_STRICT_POINTER_TYPES")
1101  && !anywhere_cell_p(sink)
1103  && !ENDP(c_sink_sl)) {
1104  /* Add the implicit dimension */
1105  expression s = copy_expression(EXPRESSION(CAR(c_sink_sl)));
1106  new_sink_sl = CONS(EXPRESSION, s, new_sink_sl);
1107  }
1108  new_sink_sl = gen_nreverse(new_sink_sl);
1109 
1110  new_sink_cell = make_cell_reference(make_reference(sink_e, new_sink_sl));
1111  }
1112  else {
1113  // Second implementation
1115  || null_cell_p(sink) || nowhere_cell_p(sink)
1116  // FI: why is the typed heap cell not handled too?
1117  || heap_cell_p(sink)) {
1118  new_sink_cell = copy_cell(sink);
1119  }
1120  else {
1121  new_sink_cell = copy_cell(sink);
1122  reference n_sink_r = cell_any_reference(new_sink_cell);
1123  type source_t = points_to_cell_to_concrete_type(source);
1124  if(pointer_type_p(source_t)) {
1125  type source_pt = type_to_pointed_type(source_t);
1126  if(adapt_reference_to_type(n_sink_r, source_pt, line_number_func))
1127  ;
1128  else {
1129  /* Dealing with the special case of a constant p -> "foo"
1130  *
1131  * The other option would be to accept "foo"[0] as a valid
1132  * reference... Extending references to constant functions
1133  * is a first step...
1134  */
1135  bool ok_p = false;
1136  type sink_t = points_to_reference_to_concrete_type(n_sink_r);
1137  if(char_type_p(source_pt)) {
1139  ok_p = true;
1140  }
1141  if(!ok_p)
1142  pips_internal_error("The type of a sink cell, \"%s\", is not compatible with the source cell, \"%s\".\n",
1143  safe_type_to_string(sink_t),
1144  safe_type_to_string(source_t));
1145  }
1146  }
1147 
1148  else
1149  pips_internal_error("The type of a source cell is not a pointer.\n");
1150  }
1151  }
1152 
1153  points_to npt = make_points_to(copy_cell(source),
1154  new_sink_cell,
1157  return npt;
1158 }
1159 ␌
1160 /**
1161  * \param t any type, but here initial reference type
1162  * \param sl remaining subscript list, all subscripts are supposed
1163  * to be store independent
1164  * \return true none of the subsequence subscript implies
1165  * a dereferencing
1166  *
1167  * Reduce the length of the subscript list
1168  */
1170  bool independent_p = false;
1171 
1172  if(ENDP(sl))
1173  independent_p = true;
1174  else if(struct_type_p(t)) {
1175  expression se = EXPRESSION(CAR(sl));
1179  independent_p = recursive_store_independent_points_to_reference_p(nt, CDR(sl));
1180  }
1181  else if(array_type_p(t)) {
1182  unsigned int d = array_type_dimension(t);
1183  if(gen_length(sl)<=d)
1184  independent_p = true;
1185  else {
1187  list nsl = sl;
1188  unsigned int i;
1189  // Skip the array subscripts
1190  for(i=0;i<d;i++)
1191  nsl = CDR(nsl);
1192  independent_p = recursive_store_independent_points_to_reference_p(nt, nsl);
1193  }
1194  }
1195  else if(pointer_type_p(t)) {
1196  /* There are indices because of the first test on the number of subscripts */
1197  independent_p = false;
1198  }
1199  else {
1200  // FI: It is more difficult... and it must have been programmed
1201  // somewhere else.
1202  pips_internal_error("Not implemented yet");
1203  }
1204 
1205  return independent_p;
1206 }
1207 
1208 /* Functions for points-to references, the kind of references used in
1209  * points-to cells.
1210  */
1211 
1212 /* Does this points-to reference define the same set of memory locations
1213  * regardless of the current (environment and) memory state?
1214  *
1215  * The reference indices can be used to encode fields in data
1216  * structures and can be applied to pointers as offset.
1217  *
1218  * The types associated to the reference and to prefixes of the index
1219  * list change. So a pointer dereferencing can be hidden anywhere. For
1220  * instance, a[i][2] can be:
1221  *
1222  * - a 2-D array element,
1223  *
1224  * - a[i]+2 if a[i] is a 1-D array of pointers,
1225  *
1226  * - a.i[2], the second element of a 1-D array embedded as field i in struct a,
1227  *
1228  * - a.i+2, if field i is a pointer embedded as field i in struct a,
1229  *
1230  * - &a[i][2][0]... if a is an array of dimension 3 or more
1231  *
1232  * Remember that *p is equivalent and encoded as p[0].
1233  *
1234  * To guarantee store independence, either
1235  *
1236  * - the list of indices is empty, which covers abstract locations
1237  * such as anywhere, null, etc.
1238  *
1239  * or
1240  *
1241  * - the list of indices is a list of integer constants and fields and
1242  * none of the intermediate types that are still indexed are
1243  * pointers unless a multidimensional array is used...
1244  *
1245  * Beware of named types...
1246  */
1248 {
1249  list il = reference_indices(r);
1250  bool independent_p = ENDP(il); // any variable is a constant address
1251 
1252  if(!independent_p) {
1254  independent_p = false; // at least one index is store-dependent
1255  else {
1256  entity v = reference_variable(r);
1258  if(type_functional_p(t))
1259  independent_p = true;
1260  else
1261  independent_p =
1263  }
1264  }
1265 
1266  return independent_p;
1267 }
1268 
1269 /* check that the subscript list il is either empty or made of integers or
1270  * fields.
1271  */
1273 {
1274  bool constant_p = true;
1275 
1276  FOREACH(EXPRESSION, se, sl) {
1278  syntax s = expression_syntax(se);
1279  if(syntax_reference_p(s)) {
1280  reference r = syntax_reference(s);
1282  if(!entity_field_p(f)) {
1283  constant_p = false;
1284  break;
1285  }
1286  }
1287  else {
1288  constant_p = false;
1289  break;
1290  }
1291  }
1292  }
1293  return constant_p;
1294 }
1295 
1296 /* check that the subscript list il is either empty or made of integers or
1297  * fields or unbounded entity "*".
1298  *
1299  * What would you do with a constant range ?
1300  */
1302 {
1303  bool constant_p = true;
1304 
1305  FOREACH(EXPRESSION, se, sl) {
1307  syntax s = expression_syntax(se);
1308  if(syntax_reference_p(s)) {
1309  reference r = syntax_reference(s);
1311  if(!entity_field_p(f)) {
1312  constant_p = false;
1313  break;
1314  }
1315  }
1316  else if(syntax_call_p(s)) {
1317  call c = syntax_call(s);
1318  entity f = call_function(c);
1319  if(!unbounded_entity_p(f)) {
1320  constant_p = false;
1321  break;
1322  }
1323  }
1324  else {
1325  constant_p = false;
1326  break;
1327  }
1328  }
1329  }
1330  return constant_p;
1331 }
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
approximation copy_approximation(approximation p)
APPROXIMATION.
Definition: effects.c:132
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
void free_type(type p)
Definition: ri.c:2658
bool entity_heap_location_p(entity b)
package abstract location.
bool entity_null_locations_p(entity e)
test if an entity is the NULL POINTER
bool entity_abstract_location_p(entity al)
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_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
entity entity_all_locations()
eturn ANY_MODULE:ANYWHERE (the top of the lattice)
bool entity_typed_nowhere_locations_p(entity e)
test if an entity is the bottom of the lattice
void const char const char const int
#define ANYWHERE_LOCATION
bool cells_must_point_to_null_p(list cl)
Definition: points_to.c:750
bool store_independent_points_to_reference_p(reference r)
Functions for points-to references, the kind of references used in points-to cells.
Definition: points_to.c:1247
type points_to_cells_minimal_type_upper_bound(list cl __attribute__((unused)))
Definition: points_to.c:584
int points_to_reference_to_final_dimension(reference r)
Compute the number of array subscript at the end of a points_to_reference.
Definition: points_to.c:244
bool cell_points_to_nowhere_sink_in_set_p(cell source, set pts)
Definition: points_to.c:845
bool points_to_cell_in_list_p(cell c, list L)
Definition: points_to.c:117
bool generic_atomic_points_to_cell_p(cell c, bool strict_p)
Is it a unique concrete memory location?
Definition: points_to.c:452
list points_to_reference_to_typed_index(reference r, type t)
Look for the index in "r" that corresponds to a pointer of type "t" and return the corresponding elem...
Definition: points_to.c:361
type points_to_array_reference_to_type(reference r)
If this is an array reference, what is the type of the underlying array type?
Definition: points_to.c:657
bool points_to_cell_equal_p(cell c1, cell c2)
Definition: points_to.c:916
list merge_points_to_cell_lists(list l1, list l2)
Add in "l1" elements of "l2" that are not yet in "l1".
Definition: points_to.c:134
bool field_reference_expression_p(expression e)
Check if expression "e" is a reference to a struct field.
Definition: points_to.c:224
bool cell_points_to_null_sink_in_set_p(cell source, set pts)
Definition: points_to.c:898
bool store_independent_points_to_indices_p(list sl)
check that the subscript list il is either empty or made of integers or fields or unbounded entity "*...
Definition: points_to.c:1301
points_to points_to_with_stripped_sink(points_to pt, int(*line_number_func)(void))
The value of the source can often be expressed with different subscript lists.
Definition: points_to.c:1074
void print_points_to_cell(cell c)
Debug: use stderr.
Definition: points_to.c:196
bool related_points_to_cells_p(cell c1, cell c2)
Definition: points_to.c:165
bool points_to_array_reference_p(reference r)
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 cell_must_point_to_nowhere_sink_in_set_p(cell source, set pts)
How are array handled in pts? do we have arcs "a->a"?
Definition: points_to.c:870
bool constant_points_to_indices_p(list sl)
check that the subscript list il is either empty or made of integers or fields.
Definition: points_to.c:1272
bool formal_parameter_points_to_cell_p(cell c)
Definition: points_to.c:99
void fprint_points_to_cell(FILE *f __attribute__((unused)), cell c)
Debug: print a cell list for points-to.
Definition: points_to.c:178
bool compatible_points_to_subscripts_p(expression s1, expression s2)
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_reference_p(reference r, bool strict_p)
Is it a unique concrete memory location?
Definition: points_to.c:489
bool atomic_points_to_reference_p(reference r)
Definition: points_to.c:519
void print_points_to_cells(list cl)
Debug.
Definition: points_to.c:202
bool cells_may_not_point_to_null_p(list cl)
Definition: points_to.c:763
bool cell_points_to_non_null_sink_in_set_p(cell source, set pts)
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
reference points_to_cells_minimal_reference_upper_bound(entity m __attribute__((unused)), type t __attribute__((unused)), list cl __attribute__((unused)))
Definition: points_to.c:590
void complete_points_to_reference_with_zero_subscripts(reference r)
Definition: points_to.c:745
cell make_anywhere_points_to_cell(type t)
Function storing points to information attached to a statement.
Definition: points_to.c:87
bool points_to_cells_intersect_p(cell lc, cell rc)
points-to cells use abstract addresses, hence the proper comparison is an intersection.
Definition: points_to.c:532
bool stub_points_to_cell_p(cell c)
Definition: points_to.c:108
void points_to_reference_update_final_subscripts(reference r, list nsl)
Substitute the subscripts "sl" in points-to reference "r" just after the last field subscript by "nsl...
Definition: points_to.c:278
entity points_to_cells_minimal_module_upper_bound(list cl __attribute__((unused)))
Definition: points_to.c:578
bool recursive_store_independent_points_to_reference_p(type t, list sl)
Definition: points_to.c:1169
bool related_points_to_cell_in_list_p(cell c, list L)
Two cells are related if they are based on the same entity.
Definition: points_to.c:149
bool atomic_points_to_cell_p(cell c)
Is it a unique concrete memory location?
Definition: points_to.c:423
list points_to_cells_to_upper_bound_points_to_cells(list cl)
Add to list "l" cells that are upper bound cells of the cells already in list "l" and return list "l"...
Definition: points_to.c:1007
bool similar_arc_in_points_to_set_p(points_to spt, set in, approximation *pa)
See if an arc like "spt" exists in set "in", regardless of its approximation.
Definition: points_to.c:929
bool exact_points_to_subscript_list_p(list sl)
See if the subscript list sl is precise, i.e.
Definition: points_to.c:1027
cell points_to_cells_minimal_upper_bound(list cl __attribute__((unused)))
Allocate a cell that is the minimal upper bound of the cells in list "cl" according to the points-to ...
Definition: points_to.c:565
list points_to_cell_to_upper_bound_points_to_cells(cell c)
Return a list of cells that are larger than cell "c" in the points-to cell lattice.
Definition: points_to.c:973
void complete_points_to_reference_with_fixed_subscripts(reference r, bool zero_p)
Add a set of zero subscripts to a constant memory path reference "r" by side effect.
Definition: points_to.c:696
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
type points_to_cell_to_concrete_type(cell)
Definition: type.c:676
type points_to_reference_to_type(reference, bool *)
FI: I need more generality than is offered by cell_to_type()
Definition: type.c:527
bool anywhere_cell_p(cell)
Is it an anywhere cell?
Definition: effects.c:367
bool nowhere_cell_p(cell)
Target of an undefined pointer.
Definition: effects.c:455
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
#define cell_undefined_p(x)
Definition: effects.h:431
#define cell_domain_number(x)
Definition: effects.h:465
#define cell_undefined
Definition: effects.h:430
#define approximation_exact_p(x)
Definition: effects.h:369
#define cell_domain
newgen_cell_interpretation_domain_defined
Definition: effects.h:85
#define CELL(x)
CELL.
Definition: effects.h:424
#define approximation_must_p(x)
Definition: effects.h:366
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
bool entities_may_conflict_p(entity e1, entity e2)
Check if two entities may conflict.
Definition: conflicts.c:984
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
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
#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
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
list gen_nthcdr(int n, const list lx)
caution: the first item is 0! was: return( (n<=0) ? l : gen_nthcdr( n-1, CDR( l ))) ; if n>gen_length...
Definition: list.c:700
gen_chunk gen_nth(int n, const list l)
to be used as ENTITY(gen_nth(3, l))...
Definition: list.c:710
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
#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 MODULE_SEP_STRING
Definition: naming-local.h:30
#define GENERIC_GLOBAL_FUNCTION(name, type)
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
#define points_to_approximation(x)
#define points_to_sink(x)
#define points_to_source(x)
void print_reference(reference r)
Definition: expression.c:142
static bool constant_p(entity e)
This function return a bool indicating if related entity e represents a constant.
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 module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
bool entity_field_p(entity e)
e is the field of a structure
Definition: entity.c:857
const char * entity_module_name(entity e)
See comments about module_name().
Definition: entity.c:1092
bool unbounded_entity_p(entity f)
Definition: expression.c:4323
bool extended_integer_constant_expression_p(expression e)
More extensive than next function.
Definition: expression.c:858
expression make_unbounded_expression()
Definition: expression.c:4339
bool field_expression_p(expression e)
The expression is of kind "a", where "a" is a field of some struct "s".
Definition: expression.c:498
bool expression_equal_p(expression e1, expression e2)
Syntactic equality e1==e2.
Definition: expression.c:1347
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 integer_expression_p(expression e)
Definition: expression.c:601
bool reference_equal_p(reference r1, reference r2)
Definition: expression.c:1500
bool unbounded_expression_p(expression e)
Definition: expression.c:4329
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
bool expression_range_p(expression e)
Definition: expression.c:1848
bool char_star_constant_function_type_p(type)
Beware of typedefs.
Definition: type.c:5787
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
type C_type_to_pointed_type(type)
returns a copy of t if t is not a pointer type, and the pointed type if t is a pointer type or.
Definition: type.c:5288
string safe_type_to_string(const type)
Definition: type.c:59
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
unsigned int array_type_dimension(type)
Definition: type.c:2947
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 formal_parameter_p(entity)
Definition: variable.c:1489
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
bool char_type_p(type)
return true whether ‘t’ is a char or an unsigned char
Definition: type.c:2877
bool C_pointer_type_p(type)
Returns OK for "char[]" as well as for "char *".
Definition: type.c:3011
#define type_functional_p(x)
Definition: ri.h:2950
#define syntax_reference_p(x)
Definition: ri.h:2728
#define syntax_reference(x)
Definition: ri.h:2730
#define reference_undefined
Definition: ri.h:2302
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define syntax_call_p(x)
Definition: ri.h:2734
#define type_variable(x)
Definition: ri.h:2949
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define type_undefined_p(x)
Definition: ri.h:2884
#define entity_undefined_p(x)
Definition: ri.h:2762
#define entity_undefined
Definition: ri.h:2761
#define expression_undefined
Definition: ri.h:1223
#define reference_indices(x)
Definition: ri.h:2328
#define syntax_call(x)
Definition: ri.h:2736
#define variable_dimensions(x)
Definition: ri.h:3122
#define type_undefined
Definition: ri.h:2883
#define expression_syntax(x)
Definition: ri.h:1247
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
s1
Definition: set.c:247
Definition: pip__tab.h:30
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