PIPS
dereferencing.c
Go to the documentation of this file.
1 /*
2 
3  $Id: dereferencing.c 23412 2017-08-09 15:07:09Z irigoin $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 
25 /*
26  * This file contains functions used to make sure that all
27  * dereferencing contained in an expression can be performed within a
28  * given points-to. It might not be a good idea to seperate
29  * dereferenging issues from points-to modifications as side effects
30  * are allowed.
31  *
32  * The argument pt_in is always modified by side-effects and returned.
33  */
34 
35 #include <stdlib.h>
36 #include <stdio.h>
37 
38 #include "genC.h"
39 
40 #include "linear.h"
41 #include "ri-util.h"
42 #include "effects-util.h"
43 
44 #include "misc.h"
45 #include "properties.h"
46 
47 #include "ri.h"
48 #include "prettyprint.h" // for debugging
49 #include "effects.h"
50 
51 // For semantics_user_warning
52 #include "transformer.h"
53 #include "semantics.h"
54 
55 #include "points-to.h"
56 
57 /* FI: As usual in dereferencing.c, it is not clear that this piece of
58  * code has not been implemented somewhere else because of the early
59  * restriction to pointer type only expressions. But all pointer
60  * values must be generated, whether they point to pointers or
61  * anything else.
62  *
63  * This piece of code is designed to handle pointer19.c, and hence
64  * pointer14.c, where arrays of pointers toward arrays of pointers are
65  * used.
66  *
67  * It generates too many arcs, useless arcs, when the subscript list
68  * is broken down into many subscript constructs by PIPS C
69  * parser. This shows in Pointers/pointer14, 15 and 19.
70  */
72 {
73  expression a = subscript_array(sub);
74  type at = expression_to_type(a);
75  type apt = type_to_pointed_type(at);
76  list sel = subscript_indices(sub);
77  /* a cannot evaluate to null or undefined */
78  /* FI: we may need a special case for stubs... */
79  in = dereferencing_to_points_to(a, in);
80  /* We have to take "sel" into account since only the base of the
81  target array is pointed to. */
82  list source_l = expression_to_points_to_sources(a, in);
83  list n_arc_l = NIL;
84 
85  FOREACH(CELL, source, source_l) {
86  /* We have to bother with the source if it is an array, not if it
87  is simply a pointer dereferenced by some subscripts as in
88  dereferencing18.c. */
89  reference source_r = cell_any_reference(source);
90  entity source_v = reference_variable(source_r);
91  type source_v_t = entity_basic_concrete_type(source_v);
92 
93  if(array_type_p(source_v_t)) {
94  /* Look for points-to arcs that must be duplicated using the
95  subscripts as offsets */
97  cell pt_source = points_to_source(pt);
98  //if(points_to_cell_in_list_p(pt_source, source_l)) {
99  if(points_to_cell_equal_p(pt_source, source)) {
100  /* We must generate a new source with the offset defined by sel,
101  and a new sink, with or without a an offset */
102  cell pt_sink = points_to_sink(pt);
103  cell n_source = cell_undefined;
104 
105  /* Update the source cell */
106  if(null_cell_p(pt_source)) {
107  pips_internal_error("NULL cannot be a source cell.\n");;
108  }
109  else if(anywhere_cell_p(pt_source)
110  || cell_typed_anywhere_locations_p(pt_source)) {
111  pips_internal_error("Not sure what should be done here!\n");
112  }
113  else {
114  n_source = copy_cell(pt_source);
115  reference n_source_r = cell_any_reference(n_source);
116  if(adapt_reference_to_type(n_source_r, at,
118  reference_indices(n_source_r) = gen_nconc(reference_indices(n_source_r),
119  gen_full_copy_list(sel));
121  }
122  else
123  pips_internal_error("No idea how to deal with this source cell.\n");
124  }
125 
126  /* Is the source cell already known in the points-to relation? */
127 
128  if(!cell_undefined_p(n_source) && !source_in_pt_map_p(n_source, in)) {
129  cell n_sink = copy_cell(pt_sink);
130 
131  /* Update the sink cell if necessary */
132  if(null_cell_p(pt_sink)) {
133  ;
134  }
135  else if(anywhere_cell_p(pt_sink)
136  || cell_typed_anywhere_locations_p(pt_sink)) {
137  ;
138  }
139  else {
140  reference n_sink_r = cell_any_reference(n_sink);
141  if(adapt_reference_to_type(n_sink_r, apt,
143  reference_indices(n_sink_r) = gen_nconc(reference_indices(n_sink_r),
144  gen_full_copy_list(sel));
146  }
147  else
148  pips_internal_error("No idea how to deal with this sink cell.\n");
149  }
150 
151  /* Build the new points-to arc */
153  points_to n_pt = make_points_to(n_source, n_sink, ap,
155  /* Do not update set "in" while you are enumerating its elements */
156  n_arc_l = CONS(POINTS_TO, n_pt, n_arc_l);
157  }
158  else
159  free_cell(n_source);
160  }
161  }
162  }
163  }
164 
165  /* Update sets "in" with the new arcs. The arc must pre-exist the
166  reference for the effects to be able to translate a non-constant
167  effect. Thus, it should pre-exist the call site. */
168  FOREACH(POINTS_TO, n_pt, n_arc_l) {
169  add_arc_to_pt_map(n_pt, in);
172  }
173  gen_free_list(n_arc_l);
174 
175  /* FI: I am not sure this is useful... */
176  in = expression_to_points_to(a, in, false); // side effects
177 
178  in = expressions_to_points_to(sel, in, false);
179 
180  free_type(at);
181  return in;
182 }
183 
184 
185 /* Make sure that expression p can be dereferenced in points-to graph "in"
186  *
187  * Handling of NULL pointers according to property.
188  *
189  * Handling of undefined pointers according to property.
190  *
191  * "in" is modified by side effects. Arcs certainly incompatible with
192  * a dereferencing are removed. If dereferencing of p is no longer
193  * possible, return an empty points-to "in" as the expression cannot
194  * be evaluated.
195  *
196  * This is conditional to two properties.
197  */
199 {
200  //pt_map out = in;
201  bool null_dereferencing_p
202  = get_bool_property("POINTS_TO_NULL_POINTER_DEREFERENCING");
203  bool nowhere_dereferencing_p
204  = get_bool_property("POINTS_TO_UNINITIALIZED_POINTER_DEREFERENCING");
205  // FI: we cannot use expression_to_points_to_sources or sinks
206  // because side effects are taken into acount each time they are
207  // called.
208  if(!nowhere_dereferencing_p && !null_dereferencing_p) {
209  syntax s = expression_syntax(p);
210  tag t = syntax_tag(s);
211 
212  switch(t) {
213  case is_syntax_reference: {
215  /*out = */reference_dereferencing_to_points_to(r, in,
216  nowhere_dereferencing_p,
217  null_dereferencing_p);
218  break;
219  }
220  case is_syntax_range: {
221  //range r = syntax_range(s);
222  // out = range_to_points_to(r, in);
223  break;
224  }
225  case is_syntax_call: {
226  call c = syntax_call(s);
227  list al = call_arguments(c);
228 
229  // FI: you do not want to apply side-effects twice...
230  // But you then miss the detection of pointers that are not NULL
231  // because they are dereferenced and you miss the recursive descent
232  //in = expressions_to_points_to(al, in, false);
233  //in = call_to_points_to(c, in, el, false);
234 
235  /* You must take care of s.tab, which is encoded by a call */
236  entity f = call_function(c);
237  if(ENTITY_FIELD_P(f)) {
238  expression ae = EXPRESSION(CAR(al));
239  expression fe = EXPRESSION(CAR(CDR(al)));
240  /* EffectsWithPointsTo/struct08.c: ae = (e.champ)[i], fe = p*/
241  //pips_assert("ae and fe are references",
242  // expression_reference_p(ae) && expression_reference_p(fe));
243  pips_assert("fe is a reference", expression_reference_p(fe));
245  entity fv = reference_variable(fr);
247  if(pointer_type_p(ft) || struct_type_p(ft)
249  || array_of_struct_type_p(ft)) {
250  in = dereferencing_to_points_to(ae, in);
251  /* For side effects on "in" */
252  list sink_l = expression_to_points_to_sinks(p, in);
253  gen_free_list(sink_l);
254  }
255  }
256  else {
257  // Do not take side-effects into account or they will be applied twice
258  in = expressions_to_points_to(al, in, false);
259  in = call_to_points_to(c, in, NIL, false);
261  gen_free_list(sl);
262  }
263  break;
264  }
265  case is_syntax_cast: {
266  //cast c = syntax_cast(s);
267  //expression ce = cast_expression(c);
268  //out = expression_to_points_to(ce, in);
269  break;
270  }
272  //sizeofexpression soe = syntax_sizeofexpression(s);
273  //if(sizeofexpression_type_p(soe))
274  //; // in is not modified
275  //else {
276  // expression ne = sizeofexpression_expression(soe);
277  // FI: we have a problem because sizeof(*p) does not imply that
278  // *p is evaluated...
279  // out = expression_to_points_to(ne, in);
280  //;
281  //}
282  break;
283  }
284  case is_syntax_subscript: {
285  subscript sub = syntax_subscript(s);
287  break;
288  }
289  case is_syntax_application: {
290  // FI: we might have to go down here...
291  //application a = syntax_application(s);
292  //out = application_to_points_to(a, out);
293  break;
294  }
295  case is_syntax_va_arg: {
296  // The call to va_arg() does not create a points-to per se
297  //list soel = syntax_va_arg(s);
298  //sizeofexpression soe1 = SIZEOFEXPRESSION(CAR(soel));
299  //sizeofexpression soe2 = SIZEOFEXPRESSION(CAR(CDR(soel)));
300  //expression se = sizeofexpression_expression(soe1);
301  // type t = sizeofexpression_type(soe2);
302  //out = expression_to_points_to(se, out);
303  break;
304  }
305  default:
306  ;
307  }
308  }
309  return in;
310 }
311 
312 /* see if a points_to_reference includes a pointer dereferencing: this is impossible if the points-to reference is consistent. It must be a constant path. */
314 {
315  return false;
316 }
317 
319 {
321  // FI: assume side effects are OK...
322  (void) expression_to_points_to(pae, in, true);
323  free_expression(pae);
324 }
325 
326 /* Can we execute the reference r in points-to context "in" without
327  * segfaulting?
328  *
329  * Do not go down in subscript expressions.
330  *
331  * See also reference_to_points_to_sinks(). Unfortunate cut-and-paste.
332  */
334  pt_map in,
335  bool nowhere_dereferencing_p,
336  bool null_dereferencing_p)
337 {
338  entity e = reference_variable(r);
340  list sl = reference_indices(r);
341 
342  /* Does the reference implies some dereferencing itself? */
343  // FI: I do not remember what this means; examples are nice
346  }
347  else if(pointer_type_p(t) && !ENDP(sl)) {
349  }
350  else if(array_of_pointers_type_p(t)
353  }
354  else if(array_type_p(t) && !array_of_pointers_type_p(t)) {
355  /* C syntactic sugar: *a is equivalent to a[0] when a is an
356  array. No real dereferencing needed. */
357  ;
358  }
359  else {
360  // FI: I am confused here
361  // FI: we might have to do more when a struct or an array is referenced
362  if(pointer_type_p(t) || array_of_pointers_type_p(t)) { // FI: implies ENDP(sl)
363  reference nr = copy_reference(r);
364  cell source = make_cell_reference(nr);
365  /* Remove store-dependent indices */
366  reference_indices(nr) =
368  list sinks = source_to_sinks(source, in, false);
369  int n = (int) gen_length(sinks);
370  FOREACH(CELL, sink, sinks) {
371  if(!nowhere_dereferencing_p && nowhere_cell_p(sink)) {
372  remove_points_to_arcs(source, sink, in);
373  n--;
374  }
375  if(!null_dereferencing_p && null_cell_p(sink)) {
376  remove_points_to_arcs(source, sink, in);
377  n--;
378  }
379  }
380  if(n==0) {
381  clear_pt_map(in);
382  points_to_graph_bottom(in) = true;
384  semantics_user_warning("Null or undefined pointer may be dereferenced because of \"%s\" at line %d.\n",
387  else
388  semantics_user_warning("Null or undefined pointer may be dereferenced because of \"%s\".\n",
390  }
391 
392  gen_free_list(sinks);
393  }
394  }
395  return in;
396 }
397 
398 /* Can expression e be reduced to a reference, without requiring an evaluation?
399  *
400  * For instance expression "p" can be reduced to reference "p".
401  *
402  * Expression "p+i" cannot be reduced to a source reference, unless i==0.
403  *
404  * Ad'hoc development for dereferencing_to_sinks.
405  */
407 {
408  bool source_p = true;
409  syntax s = expression_syntax(e);
410  if(syntax_reference_p(s))
411  source_p = true;
412  else if(syntax_call_p(s)) {
413  call c = syntax_call(s);
414  entity f = call_function(c);
415  if(ENTITY_PLUS_C_P(f))
416  source_p = false;
417  }
418  return source_p;
419 }
420 
421 /* Returns "sinks", the list of cells pointed to by expression "a"
422  * according to points-to graph "in".
423  *
424  * If eval_p is true, perform a second dereferencing on the cells
425  * obtained with the first dereferencing.
426  *
427  * Manage NULL and undefined (nowhere) cells.
428  *
429  * Possibly update the points-to graph when some arcs are incompatible
430  * with the request, assuming the analyzed code is correct.
431  */
433 {
434  list sinks = NIL;
435  /* Locate the pointer, no dereferencing yet... unless no pointer can
436  be found as in *(p+2) in which case an evaluation occurs/might
437  occur/used to occur in expression_to_points_to_sources(). */
439  if(ENDP(cl)) {
440  // The source may not be found, e.g. *(p+i)
441  //sinks = expression_to_points_to_sinks(a, in);
442  cl = expression_to_points_to_sinks(a, in);
443  }
444  /*else*/ { // Some sources have been found
446  bool evaluated_p = !expression_to_points_to_cell_p(a);
447  // evaluated_p = false;
448  if(!evaluated_p || eval_p) {
449  bool null_dereferencing_p
450  = get_bool_property("POINTS_TO_NULL_POINTER_DEREFERENCING");
451  bool nowhere_dereferencing_p
452  = get_bool_property("POINTS_TO_UNINITIALIZED_POINTER_DEREFERENCING");
453 
454  /* Finds what it is pointing to, memory(p) */
455  FOREACH(CELL, c, cl) {
456  /* Do we want to dereference c? */
457  if( (null_dereferencing_p || !null_cell_p(c))
458  && (nowhere_dereferencing_p || !nowhere_cell_p(c))) {
459  list o_pointed = source_to_sinks(c, in, true);
460  remove_impossible_arcs_to_null(&o_pointed, in);
461  /* Do not create sharing between elements of "in" and elements of
462  "sinks". */
463  // list pointed = source_to_sinks(c, in, true);
464  list pointed = gen_full_copy_list(o_pointed);
465  gen_free_list(o_pointed);
466  if(ENDP(pointed)) {
468  entity v = reference_variable(r);
469  string words_to_string(list);
470  pips_user_warning("No pointed location for variable \"%s\" and reference \"%s\"\n",
471  entity_user_name(v),
473  /* The sinks list is empty, whether eval_p is true or not... */
474  }
475  else {
476  if(!evaluated_p && eval_p) {
477  FOREACH(CELL, sc, pointed) {
478  bool to_be_freed;
479  type t = points_to_cell_to_type(sc, &to_be_freed);
480  if(!pointer_type_p(t)) {
481  // FI: it might be necessary to allocate a new copy of sc
482  sinks = gen_nconc(sinks, CONS(CELL, sc, NIL));
483  }
484  else if(array_type_p(t) || struct_type_p(t)) {
485  /* FI: New cells have been allocated by
486  source_to_sinks(): side-effects are OK. In
487  theory... The source code of source_to_sinks() seems
488  to show that fresh_p is not exploited in all
489  situations. */
490  //cell nsc = copy_cell(sc);
491  //points_to_cell_add_zero_subscripts(nsc);
492  //sinks = gen_nconc(sinks, CONS(CELL, nsc, NIL));
493  pips_internal_error("sc assume saturated with 0 subscripts and/or field susbscripts.\n");
494  }
495  else {
496  list starpointed = pointer_source_to_sinks(sc, in);
497  // sinks = gen_nconc(sinks, starpointed);
498  sinks = merge_points_to_cell_lists(sinks, starpointed);
499  }
500  if(to_be_freed) free_type(t);
501  }
502  }
503  else
504  sinks = gen_nconc(sinks, pointed);
505  }
506  }
507  }
508  }
509  else
510  sinks = cl;
511  }
512 
513  return sinks;
514 }
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 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)
points_to copy_points_to(points_to p)
POINTS_TO.
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
#define add_arc_to_pt_map(a, s)
#define clear_pt_map(pt)
#define source_in_pt_map_p(cell, set)
bool cell_typed_anywhere_locations_p(cell c)
test if a cell is the bottom of the lattice
void const char const char const int
pt_map reference_dereferencing_to_points_to(reference r, pt_map in, bool nowhere_dereferencing_p, bool null_dereferencing_p)
Can we execute the reference r in points-to context "in" without segfaulting?
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".
bool pointer_points_to_reference_p(reference r __attribute__((unused)))
see if a points_to_reference includes a pointer dereferencing: this is impossible if the points-to re...
pt_map dereferencing_to_points_to(expression p, pt_map in)
Make sure that expression p can be dereferenced in points-to graph "in".
pt_map dereferencing_subscript_to_points_to(subscript sub, pt_map in)
FI: As usual in dereferencing.c, it is not clear that this piece of code has not been implemented som...
Definition: dereferencing.c:71
void pointer_reference_dereferencing_to_points_to(reference r, pt_map in)
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
bool points_to_cell_equal_p(cell, cell)
Definition: points_to.c:916
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
list merge_points_to_cell_lists(list, list)
Add in "l1" elements of "l2" that are not yet in "l1".
Definition: points_to.c:134
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
bool null_cell_p(cell)
Definition: effects.c:466
#define cell_undefined_p(x)
Definition: effects.h:431
#define cell_undefined
Definition: effects.h:430
#define CELL(x)
CELL.
Definition: effects.h:424
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#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
#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_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
#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 SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
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 add_arc_to_points_to_context(points_to pt)
FI: it should rather work the other way round, with add_arc_to_statement_points_to_context() calling ...
Definition: passes.c:268
pt_map call_to_points_to(call c, pt_map pt_in, list el, bool side_effect_p)
Three different kinds of calls are distinguished:
Definition: expression.c:306
pt_map expressions_to_points_to(list el, pt_map pt_in, bool side_effect_p)
Compute the points-to information pt_out that results from the evaluation of a possibly empty list of...
Definition: expression.c:243
pt_map expression_to_points_to(expression e, pt_map pt_in, bool side_effect_p)
Update pt_in and pt_out according to expression e.
Definition: expression.c:115
list pointer_source_to_sinks(cell, pt_map)
Returns the sinks for a source cell "sc" of type pointer according to the points-to relation "in".
list expression_to_points_to_sinks(expression, pt_map)
The returned list contains cells used in "in".
Definition: sinks.c:1795
void add_arc_to_statement_points_to_context(points_to)
Definition: statement.c:104
list expression_to_points_to_sources(expression, pt_map)
expression_to_points_to_sources() does not always work, especially with pointer arithmetic or subscri...
Definition: sinks.c:1805
bool statement_points_to_context_defined_p(void)
Definition: statement.c:145
void remove_points_to_arcs(cell, cell, pt_map)
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...
#define points_to_approximation(x)
#define points_to_sink(x)
#define points_to_graph_bottom(x)
#define POINTS_TO(x)
POINTS_TO.
#define points_to_graph_set(x)
#define points_to_source(x)
string reference_to_string(reference r)
Definition: expression.c:87
#define ENTITY_PLUS_C_P(e)
#define ENTITY_FIELD_P(e)
C data structure and pointer management.
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
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 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
bool array_of_pointers_type_p(type)
Definition: type.c:3025
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 struct_type_p(type)
Returns true if t is of type derived and if the derived type is a struct.
Definition: type.c:3121
bool array_of_struct_type_p(type)
Definition: type.c:3133
#define syntax_reference_p(x)
Definition: ri.h:2728
#define syntax_reference(x)
Definition: ri.h:2730
#define syntax_tag(x)
Definition: ri.h:2727
#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
@ 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 EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define subscript_indices(x)
Definition: ri.h:2563
#define reference_indices(x)
Definition: ri.h:2328
#define syntax_call(x)
Definition: ri.h:2736
#define subscript_array(x)
Definition: ri.h:2561
#define syntax_subscript(x)
Definition: ri.h:2745
#define call_arguments(x)
Definition: ri.h:711
#define expression_syntax(x)
Definition: ri.h:1247
#define semantics_user_warning
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
string words_to_string(cons *lw)
Definition: print.c:211