Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom.ansi / proto.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  */
5 /* $Id: proto.c,v 1.25 1994/06/27 08:01:56 ceriel Exp $ */
6 /*  P R O T O T Y P E   F I D D L I N G  */
7
8 #include        "lint.h"
9 #include        "debug.h"
10 #include        "idfsize.h"
11 #include        "nparams.h"
12 #include        "botch_free.h"
13 #include        <alloc.h>
14 #include        "Lpars.h"
15 #include        "level.h"
16 #include        <flt_arith.h>
17 #include        "arith.h"
18 #include        "align.h"
19 #include        "stack.h"
20 #include        "idf.h"
21 #include        "def.h"
22 #include        "type.h"
23 #include        "struct.h"
24 #include        "label.h"
25 #include        "expr.h"
26 #include        "declar.h"
27 #include        "decspecs.h"
28 #include        "proto.h"
29 #include        "assert.h"
30
31 extern char options[];
32
33 check_for_void(pl)
34         register struct proto *pl;
35 {
36         register int errcnt = 0;
37
38         if (!pl) return;
39         if ((pl->pl_flag & PL_VOID) && !(pl->next)) return;
40
41         while (pl) {
42                 if (pl->pl_flag & PL_VOID) {
43                         if (!errcnt && !(pl->pl_flag & PL_ERRGIVEN))
44                                 error("illegal use of void in argument list");
45                         pl->pl_flag |= PL_ERRGIVEN;
46                         errcnt++;
47                 }
48                 pl = pl->next;
49         }
50 }
51
52 add_proto(pl, ds, dc, lvl)
53         struct proto *pl;
54         struct decspecs *ds;
55         struct declarator *dc;
56         int lvl;
57 {
58         /*      The full typed identifier or abstract type, described
59                 by the structures decspecs and declarator are turned
60                 a into parameter type list structure.
61                 The parameters will be declared at level L_FORMAL2,
62                 later on it's decided whether they were prototypes
63                 or actual declarations.
64         */
65         register struct idf *idf = dc->dc_idf;
66         register struct def *def = idf ? idf->id_def : (struct def *)0;
67         register int sc = ds->ds_sc;
68         register struct type *type;
69         char formal_array = 0;
70
71         ASSERT(ds->ds_type != (struct type *)0);
72
73         pl->pl_flag = PL_FORMAL;
74         type = declare_type(ds->ds_type, dc);
75         if (type->tp_size < (arith)0 && actual_declaration(sc, type)) {
76                 extern char *symbol2str();
77                 if (type->tp_fund != VOID)
78                         error("unknown %s-type", symbol2str(type->tp_fund));
79                 else {
80                         if (idf != (struct idf *)0
81                             || ds->ds_sc_given
82                             || ds->ds_typequal) {
83                                 error("illegal use of void in argument list");
84                                 pl->pl_flag |= PL_ERRGIVEN;
85                         }
86                         /* set PL_VOID anyway */
87                         pl->pl_flag |= PL_VOID;
88                 }
89         }
90         if (ds->ds_sc_given && ds->ds_sc != REGISTER) {
91                 if (!(pl->pl_flag & PL_ERRGIVEN)) {
92                     if (ds->ds_sc != AUTO) {
93                         error("illegal storage class in parameter declaration");
94                     } else {
95                         warning("illegal storage class in parameter declaration");
96                     }
97                 }
98         }
99
100         /*      Perform some special conversions for parameters.
101         */
102         if (type->tp_fund == FUNCTION) {
103                 type = construct_type(POINTER, type, 0, (arith) 0, NO_PROTO);
104         } else if (type->tp_fund == ARRAY) {
105                 type = construct_type(POINTER, type->tp_up, 0, (arith) 0, NO_PROTO);
106                 formal_array = 1;
107         }
108
109         /*      According to the standard we should ignore the storage
110                 class of a parameter, unless it's part of a function
111                 definition.
112                 However, in the routine declare_protos we don't know decspecs,
113                 and therefore we can't complain up there. So we build up the
114                 storage class, and keep quiet until we reach declare_protos.
115         */
116         sc = (ds->ds_sc_given && ds->ds_sc != REGISTER) ?
117                                 0 : sc == 0 ? FORMAL : REGISTER;
118
119         if (def && (def->df_level == lvl /* || def->df_level < L_PROTO */ )) {
120                 /* redeclaration at the same level */
121                 error("parameter %s redeclared", idf->id_text);
122         } else if (idf != (struct idf *)0) {
123                 /*      New definition, redefinition hides earlier one
124                 */
125                 register struct def *newdef = new_def();
126                 
127                 newdef->next = def;
128                 newdef->df_level = lvl;
129                 newdef->df_sc = sc;
130                 newdef->df_type = type;
131                 newdef->df_formal_array = formal_array;
132                 newdef->df_file = idf->id_file;
133                 newdef->df_line = idf->id_line;
134 #ifdef LINT
135                 newdef->df_set = (type->tp_fund == ARRAY);
136                 /* newdef->df_firstbrace = 0; */
137 #endif
138                 /*      We can't put the idf onto the stack, since these kinds
139                         of declaration may occurs at any level, and the idf
140                         does not necessarily go at this level. E.g.
141
142                         f() {
143                         ...
144                                 { int func(int a, int b);
145                                 ...
146                                 }
147                         }
148
149                         The idf's a and b declared in the prototype declaration
150                         do not go at any level, they are simply ignored.
151                         However, in
152
153                         f(int a, int b) {
154                         ...
155                         }
156
157                         They should go at level L_FORMAL2. But at this stage
158                         we don't know whether we have a prototype or function
159                         definition. So, this process is postponed.
160                 */
161                 idf->id_def = newdef;
162                 update_ahead(idf);
163         }
164
165         pl->pl_idf = idf;
166         pl->pl_type = type;
167 }
168
169 struct tag *
170 gettag(tp, idpp)
171 struct type *tp;
172 struct idf **idpp;
173 {
174         struct tag *tg = (struct tag *)0;
175         register int fund = tp->tp_fund;
176
177         while (fund == FIELD || fund == POINTER
178                 || fund == ARRAY || fund == FUNCTION) {
179                 tp = tp->tp_up;
180                 fund = tp->tp_fund;
181         }
182         *idpp = tp->tp_idf;
183         switch(tp->tp_fund) {
184         case ENUM:
185         case UNION:
186         case STRUCT: tg = tp->tp_idf->id_tag; break;
187         }
188         return tg;
189 }
190
191
192 declare_protos(dc)
193         register struct declarator *dc;
194 {
195         /*      At this points we know that the idf's in protolist are formal
196                 parameters. So it's time to declare them at level L_FORMAL2.
197         */
198         struct stack_level *stl = stack_level_of(L_FORMAL1);
199         register struct decl_unary *du;
200         register struct type *type;
201         register struct proto *pl;
202         register struct def *def;
203
204 #ifdef  DEBUG
205         if (options['t'])
206                 dumpidftab("start declare_protos", 0);
207 #endif  /* DEBUG */
208         du = dc->dc_decl_unary;
209         while (du) {
210                 if (du->du_fund == FUNCTION) {
211                         if (du->next != (struct decl_unary *) 0) {
212                                 remove_proto_idfs(du->du_proto);
213                                 du->du_proto = 0;
214                         } else break;
215                 }
216                 du = du->next;
217         }
218         pl = du ? du->du_proto : NO_PROTO;
219         if (pl) {
220 #if     0 /* the id_proto member is deleted (???) */
221                 idf->id_proto = 0;
222 #endif  /* 0 */
223                 do {
224                         struct tag *tg;
225                         struct idf *idp = 0;
226
227                         type = pl->pl_type;
228
229                         /* `...' only for type checking */
230                         if (pl->pl_flag & PL_ELLIPSIS) {
231                                 pl = pl->next;
232                                 continue;
233                         }
234
235                         /* special case: int f(void) { ; } */
236                         if (type->tp_fund == VOID)
237                                 break;
238
239                         if (!pl->pl_idf || !(def = pl->pl_idf->id_def)) {
240                                 error("no parameter identifier supplied");
241                                 pl = pl->next;
242                                 continue;
243                         }
244
245                         /*      Postponed storage class checking.
246                         */
247                         if (def->df_sc == 0)
248                                 error("illegal storage class in parameter declaration");
249
250                         def->df_level = L_FORMAL2;
251                         stack_idf(pl->pl_idf, stl);
252                         pl = pl->next;
253
254                         tg = gettag(type, &idp);
255                         if (tg && tg->tg_level <= L_PROTO) {
256                                 tg->tg_level = L_FORMAL2;
257                                 stack_idf(idp, stl);
258                         }
259                 } while (pl);
260         }
261 #ifdef  DEBUG
262         if (options['t'])
263                 dumpidftab("end declare_protos", 0);
264 #endif  /* DEBUG */
265 }
266
267
268 update_proto(tp, otp)
269         register struct type *tp, *otp;
270 {
271         /*      This routine performs the proto type updates.
272                 Consider the following code:
273
274                 int f(double g());
275                 int f(double g(int f(), int));
276                 int f(double g(int f(long double), int));
277
278                 The most accurate definition is the third line.
279                 This routine will silently update all lists,
280                 and removes the redundant occupied space.
281         */
282         register struct proto *pl, *opl;
283
284         if (tp == otp) return;
285         if (!tp || !otp) return;
286
287         while (tp->tp_fund != FUNCTION) {
288                 if (tp->tp_fund != POINTER && tp->tp_fund != ARRAY) return;
289                 tp = tp->tp_up;
290                 otp = otp->tp_up;
291                 if (!tp) return;
292         }
293
294         pl = tp->tp_proto;
295         opl = otp->tp_proto;
296         if (pl && opl) {
297                 /* both have prototypes */
298                 while (pl && opl) {
299                         update_proto(pl->pl_type, opl->pl_type);
300                         pl = pl->next;
301                         opl = opl->next;
302                 }
303                 /* Do not free the old prototype list. It might be part of
304                  * a typedef.
305                  */
306                 otp->tp_proto = tp->tp_proto;
307         } else if (opl) {
308                 /* old decl has type */
309         } else if (pl) {
310                 otp->tp_proto = pl;
311         }
312
313         update_proto(tp->tp_up, otp->tp_up);
314 }
315
316 /* struct/union and enum tags can be declared inside prototypes
317  * remove them from the symbol-table
318  */
319 remove_proto_tag(tp)
320 struct type *tp;
321 {
322         register struct idf *ident;
323         register struct tag *tgp, **tgpp;
324         register int fund = tp->tp_fund;
325
326         while (fund == FIELD || fund == POINTER
327                 || fund == ARRAY || fund == FUNCTION) {
328                 tp = tp->tp_up;
329                 fund = tp->tp_fund;
330         }
331
332         ident = tp->tp_idf;
333         switch (tp->tp_fund) {
334         case ENUM:
335         case STRUCT:
336         case UNION: tgpp = &(ident->id_tag); break;
337         default: return;
338         }
339
340         while((*tgpp) && (*tgpp)->tg_type != tp) {
341                 tgpp = &((*tgpp)->next);
342         }
343         if (!*tgpp) return;
344
345         tgp = *tgpp;
346         if (tgp->tg_level > L_PROTO) return;
347
348 #ifdef DEBUG
349         if (options['t'])
350                 print("Removing idf %s from list\n",
351                         ident->id_text);
352 #endif
353
354         (*tgpp) = tgp->next;
355         free_tag(tgp);
356 }
357
358 remove_proto_idfs(pl)
359         register struct proto *pl;
360 {
361         /*      Remove all the identifier definitions from the
362                 prototype list.
363         */
364         register struct def *def;
365
366         while (pl) {
367                 if (pl->pl_idf) {
368 #ifdef DEBUG
369                         if (options['t'])
370                                 print("Removing idf %s from list\n",
371                                         pl->pl_idf->id_text);
372 #endif
373                         def = pl->pl_idf->id_def;
374                         if (def && def->df_level <= L_PROTO) {
375                                 pl->pl_idf->id_def = def->next;
376                                 free_def(def);
377                         }
378                         pl->pl_idf = (struct idf *) 0;
379                 }
380                 if (pl->pl_type) {
381                         remove_proto_tag(pl->pl_type);
382                 }
383                 pl = pl->next;
384         }
385 }
386
387 call_proto(expp)
388         register struct expr **expp;
389 {
390         /*      If the function specified by (*expp)->OP_LEFT has a prototype,
391                 the parameters are converted according the rules specified in
392                 par. 3.3.2.2. E.i. the parameters are converted to the prototype
393                 counter parts as if by assignment. For the parameters falling
394                 under ellipsis clause the old parameters conversion stuff
395                 applies.
396         */
397         register struct expr *left = (*expp)->OP_LEFT;
398         register struct expr *right = (*expp)->OP_RIGHT;
399         register struct proto *pl = NO_PROTO;
400         static struct proto ellipsis = { 0, 0, 0, PL_ELLIPSIS };
401
402         if (left != NILEXPR) {          /* in case of an error */
403                 register struct type *tp = left->ex_type;
404
405                 while (tp && tp->tp_fund != FUNCTION && tp != error_type)
406                         tp = tp->tp_up;
407                 if (tp && tp->tp_proto)
408                         pl = tp->tp_proto;
409         }
410
411         if (right != NILEXPR) {         /* function call with parameters */
412                 register struct expr **ep = &((*expp)->OP_RIGHT);
413                 register int ecnt = 0, pcnt = 0;
414                 struct expr **estack[NPARAMS];
415                 struct proto *pstack[NPARAMS];
416
417                 /* stack up the parameter expressions */
418                 while (right->ex_class == Oper && right->OP_OPER == PARCOMMA) {
419                         if (ecnt == STDC_NPARAMS)
420                                 expr_strict(right, "number of parameters exceeds ANSI limit");
421                         if (ecnt >= NPARAMS-1) {
422                                 expr_error(right, "too many parameters");
423                                 return;
424                         }
425                         estack[ecnt++] = &(right->OP_RIGHT);
426                         ep = &(right->OP_LEFT);
427                         right = right->OP_LEFT;
428                 }
429                 estack[ecnt] = ep;
430
431                 /*      Declarations like int f(void) do not expect any
432                         parameters.
433                 */
434                 if (pl && pl->pl_flag & PL_VOID) {
435                         expr_strict(*expp, "no parameters expected");
436                         pl = NO_PROTO;
437                 }
438
439                 /* stack up the prototypes */
440                 if (pl) {
441                         pcnt--;
442                         do {
443                                 /* stack prototypes */
444                                 pstack[++pcnt] = pl;
445                                 pl = pl->next;
446                         } while (pl);
447                 }
448                 else {
449                         pstack[0] = &ellipsis;
450                 }
451
452                 for (ecnt; ecnt >= 0; ecnt--) {
453                         /*      Only the parameters specified in the prototype
454                                 are checked and converted. The parameters that
455                                 fall under the ellipsis clause are neither
456                                 checked nor converted !
457                         */
458                         if (pcnt < 0) {
459                                 expr_error(*expp, "more parameters than specified in prototype");
460                                 break;
461                         }
462                         else if (!(pstack[pcnt]->pl_flag & PL_ELLIPSIS)) {
463                                 ch3cast(estack[ecnt],CASTAB,pstack[pcnt]->pl_type);
464                                 pcnt--;
465                         } else
466                                 any2parameter(estack[ecnt]);
467                 }
468                 if (pcnt > 0 || (pcnt == 0 && !(pstack[0]->pl_flag & PL_ELLIPSIS)))
469                         expr_error(*expp, "fewer parameters than specified in prototype");
470         } else {
471                 if (pl && !(pl->pl_flag & PL_VOID))
472                         expr_error(*expp, "fewer parameters than specified in prototype");
473         }
474 }