Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom / l_outdef.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: l_outdef.c,v 3.12 1994/06/24 12:04:50 ceriel Exp $ */
6 /*      Lint outdef construction        */
7
8 #include        "lint.h"
9
10 #ifdef  LINT
11
12 #include        <alloc.h>
13 #include        "interface.h"
14 #ifdef ANSI
15 #include        <flt_arith.h>
16 #endif /* ANSI */
17 #include        "arith.h"
18 #include        "assert.h"
19 #include        "type.h"
20 #include        "declar.h"
21 #include        "decspecs.h"
22 #include        "LLlex.h"
23 #include        "Lpars.h"
24 #include        "stack.h"
25 #include        "def.h"
26 #include        "struct.h"
27 #include        "field.h"
28 #include        "idf.h"
29 #include        "level.h"
30 #include        "label.h"
31 #include        "code.h"
32 #include        "expr.h"
33 #include        "l_lint.h"
34 #include        "l_comment.h"
35 #include        "l_outdef.h"
36 #include        "l_class.h"
37
38 extern char *bts2str();
39 extern char *symbol2str();
40 extern char *strindex();
41
42 int stat_number = 9999;                 /* static scope number */
43 struct outdef OutDef;
44
45 PRIVATE struct outdef OutCall;
46
47 PRIVATE local_EFDC();
48 PRIVATE output_def();
49 PRIVATE outargs();
50 PRIVATE outarg();
51 PRIVATE outargstring();
52 PRIVATE outargtype();
53 PRIVATE add_expr_arg();
54
55 lint_declare_idf(idf, sc)
56         struct idf *idf;
57         int sc;
58 {
59         register struct def *def = idf->id_def;
60         register int is_function = def->df_type->tp_fund == FUNCTION;
61
62         if (level == L_GLOBAL) {
63                 lint_ext_def(idf, sc);
64                 if (is_function)
65                         def2decl(sc);
66                 if (sc != TYPEDEF)
67                         outdef();
68         }
69         else
70         if (level >= L_LOCAL && sc != STATIC && is_function) {
71                 local_EFDC(idf);
72         }
73 }
74
75 lint_non_function_decl(ds, dc)
76         struct decspecs *ds;
77         struct declarator *dc;
78 {
79         register struct def *def = dc->dc_idf->id_def;
80         register int is_function = def->df_type->tp_fund == FUNCTION;
81
82         if (is_function)
83                 def2decl(ds->ds_sc);
84         if (def->df_sc != TYPEDEF)
85                 outdef();
86 }
87
88 lint_ext_def(idf, sc)
89         struct idf *idf;
90 {
91 /* At this place the following fields of the output definition can be
92  * filled:
93  *              name, stat_number, class, file, line, type.
94  * For variable definitions and declarations this will be all.
95  * For functions the fields nrargs and argtps are filled after parsing
96  * the arguments.
97  * The returns-field is known at the end of the function definition.
98  * sc indicates the storage class defined by the declaration specifier.
99  */
100         register struct def *def = idf->id_def;
101         register struct type *type = def->df_type;
102
103         OutDef.od_name = idf->id_text;
104         OutDef.od_statnr = (sc == STATIC ? stat_number : 0);
105
106         switch (type->tp_fund) {
107         case ERRONEOUS:
108                 OutDef.od_class = XXDF;
109                 break;
110         case FUNCTION:
111                 /* For the moment assume it will be a definition.
112                  * If no compound_statement follows, it is a declaration,
113                  * in which case the class will be adjusted by def2decl().
114                  */
115                 OutDef.od_class = (sc == STATIC ? SFDF : EFDF);
116                 break;
117         default:        /* a variable */
118                 OutDef.od_class =
119                         sc == EXTERN ? EVDC :
120                         sc == STATIC ? SVDF : EVDF;
121                 break;
122         }
123         OutDef.od_file = def->df_file;
124         OutDef.od_line = def->df_line;
125         OutDef.od_type = (type->tp_fund == FUNCTION ? type->tp_up : type);
126         OutDef.od_valreturned = NORETURN;
127 }
128
129 def2decl(sc)
130         int sc;
131 {
132 /* It was assumed we were parsing a function definition.
133  * There was no compound statement following, so actually it was a
134  * declaration. This function updates the class.
135  */
136         OutDef.od_class = (sc == STATIC ? XXDF : EFDC);
137 }
138
139 set_od_valreturned(n)
140 {
141         OutDef.od_valreturned = n;
142 }
143
144 PRIVATE
145 local_EFDC(idf)
146         struct idf *idf;
147 {
148         struct outdef od;
149
150         od.od_class = EFDC;
151         od.od_statnr = 0;
152         od.od_name = idf->id_text;
153         od.od_file = idf->id_def->df_file;
154         od.od_line = idf->id_def->df_line;
155         od.od_type = idf->id_def->df_type->tp_up;
156         output_def(&od);
157         /* The other fields are not used for this class. */
158 }
159
160 lint_formals()
161 {
162 /* Make a list of 'struct argument's containing the types of the formal
163  * parameters of the function definition just parsed.
164  */
165         register struct stack_entry *se = stack_level_of(L_FORMAL1)->sl_entry;
166         register struct argument **hook = &OutDef.od_arg;
167         register int nrargs = 0;
168
169         while (se) {
170                 register struct type *type = se->se_idf->id_def->df_type;
171                 register struct argument *arg = new_argument();
172
173                 /*      Do the conversions on the formals that could not be
174                         done in declare_idf().
175                         It is, unfortunately, impossible not to do them,
176                         since the corresponding actuals will have been
177                         converted to generate proper code and we do not
178                         want to duplicate the whole of expression handling
179                         for lint.
180                 */
181                 switch (type->tp_fund) {
182                 case CHAR:
183                 case SHORT:
184                         type = (type->tp_unsigned ? uint_type : int_type);
185                         break;
186                 case FLOAT:
187                         type = double_type;
188                         break;
189                 }
190
191                 if (f_FORMAT && nrargs == f_FORMATn) {
192                         if (    !f_FORMATvar
193                         &&      (       type->tp_fund != POINTER
194                                 ||      type->tp_up->tp_fund != CHAR
195                                 )
196                         ) {
197                                 warning("format parameter %d is not pointer to char",
198                                         nrargs);
199                         }
200                         arg->ar_type = string_type;
201                         arg->ar_class = ArgString;
202                         arg->CAS_VALUE = f_FORMAT;
203                         arg->CAS_LEN = strlen(f_FORMAT);
204                         f_FORMAT = 0;
205                 }
206                 else {
207                         arg->ar_type = type;
208                         arg->ar_class = ArgFormal;
209                 }
210                 *hook = arg;
211                 hook = &arg->next;
212
213                 nrargs++;
214                 se = se->next;
215         }
216
217         if (f_FORMAT) {
218                 /*      f_FORMAT has not been consumed, perhaps due to
219                         a varargs-like construction; add erroneous ArgFormals
220                         until f_FORMATn, then an ArgString, if necessary.
221                 */
222                 if (!f_FORMATvar) {
223                         warning("FORMAT%d function has only %d argument%s",
224                                 f_FORMATn, nrargs, nrargs == 1 ? "" : "s"
225                         );
226                 }
227
228                 while (nrargs < f_FORMATn) {
229                         register struct argument *arg = new_argument();
230                         
231                         arg->ar_type = error_type;
232                         arg->ar_class = ArgFormal;
233                         *hook = arg;
234                         hook = &arg->next;
235                         nrargs++;
236                 }
237                 if (nrargs == f_FORMATn) {
238                         register struct argument *arg = new_argument();
239                         
240                         arg->ar_type = string_type;
241                         arg->ar_class = ArgString;
242                         arg->CAS_VALUE = f_FORMAT;
243                         arg->CAS_LEN = strlen(f_FORMAT);
244                         f_FORMAT = 0;
245                         *hook = arg;
246                         hook = &arg->next;
247                         nrargs++;
248                 }
249                 /* life is full of duplicated code; this is no good */
250         }
251
252         if (f_VARARGSn > nrargs) {
253                 warning("VARARGS%d function has only %d argument%s",
254                         f_VARARGSn, nrargs, nrargs == 1 ? "" : "s"
255                 );
256                 f_VARARGSn = nrargs;
257         }
258         OutDef.od_nrargs = nrargs;
259 }
260
261 output_use(idf)
262         struct idf *idf;
263 {
264 /* Output the usage-definition of the variable described by idf.
265  */
266         OutDef.od_name = idf->id_text;
267         OutDef.od_statnr = (idf->id_def->df_sc == STATIC ? stat_number : 0);
268         OutDef.od_class = VU;
269         OutDef.od_file = FileName;
270         OutDef.od_line = LineNumber;
271         OutDef.od_type = idf->id_def->df_type;
272         outdef();
273 }
274
275 outdef()
276 {
277         output_def(&OutDef);
278 }
279
280 outcall()
281 {
282         output_def(&OutCall);
283 }
284
285 PRIVATE
286 output_def(od)
287         struct outdef *od;
288 {
289 /* As the types are output the 'struct argument's are removed, because they
290  * are then not needed anymore.
291  */
292         if (od->od_class == XXDF || !od->od_name || od->od_name[0] == '#')
293                 return;
294
295         if (LINTLIB) {
296                 switch (od->od_class) {
297                 case EFDF:
298                         od->od_class = LFDF;
299                         break;
300                 case EVDF:
301                         od->od_class = LVDF;
302                         break;
303                 case SFDF:
304                         /* remove 'struct argument's */
305                         while (od->od_arg) {
306                                 register struct argument *tmp = od->od_arg;
307                                 od->od_arg = od->od_arg->next;
308                                 free_argument(tmp);
309                         }
310                         return;
311                 default:
312                         return;
313                 }
314         }
315         printf("%s:%d:%c", od->od_name, od->od_statnr, od->od_class);
316         switch (od->od_class) {
317         case EFDF:
318         case SFDF:
319         case LFDF:
320                 if (f_VARARGSn != -1) {
321                         printf(":%d", -1 - f_VARARGSn);
322                         outargs(od->od_arg, f_VARARGSn);
323                 }
324                 else {
325                         printf(":%d", od->od_nrargs);
326                         outargs(od->od_arg, od->od_nrargs);
327                 }
328                 od->od_arg = 0;
329                 printf(":%d", od->od_valreturned);
330                 break;
331         case FC:
332                 printf(":%d", od->od_nrargs);
333                 outargs(od->od_arg, od->od_nrargs);
334                 od->od_arg = 0;
335                 printf(":%d", od->od_valused);
336                 break;
337         case EVDF:
338         case SVDF:
339         case LVDF:
340         case EFDC:
341         case EVDC:
342         case IFDC:
343         case VU:
344                 break;
345         default:
346                 NOTREACHED();
347                 /*NOTREACHED*/
348         }
349         printf(":");
350         outargtype(od->od_type);
351         printf(":%u:%s\n", od->od_line, od->od_file);
352 }
353
354 PRIVATE
355 outargs(arg, n)
356         struct argument *arg;
357 {
358 /* Output the n arguments in the argument list and remove them */
359
360         register struct argument *tmp;
361
362         while (n--) {
363                 ASSERT(arg);
364                 outarg(arg);
365                 tmp = arg;
366                 arg = arg->next;
367                 free_argument(tmp);
368         }
369         /* remove the remaining entries */
370         while (arg) {
371                 tmp = arg;
372                 arg = arg->next;
373                 free_argument(tmp);
374         }
375 }
376
377 PRIVATE
378 outarg(arg)
379         struct argument *arg;
380 {
381         printf(":");
382         switch (arg->ar_class) {
383         case ArgConst:
384                 if (arg->CAA_VALUE >= 0) {
385                         /* constant non-negative actual parameter */
386                         printf("+");
387                 }
388                 outargtype(arg->ar_type);
389                 break;
390
391         case ArgString:
392                 outargstring(arg);
393                 break;
394
395         case ArgFormal:
396         case ArgExpr:
397                 outargtype(arg->ar_type);
398                 if (arg->ar_type->tp_fund == FUNCTION) {
399                         /* UGLY PATCH !!! ??? */
400                         /*      function names as operands are sometimes
401                                 FUNCTION and sometimes POINTER to FUNCTION,
402                                 depending on opaque circumstances.  E.g., in
403                                         f(main, main);
404                                 the first main is PtF and the second is F.
405                         */
406                         printf("*");
407                 }
408                 break;
409
410         default:
411                 NOTREACHED();
412                 /*NOTREACHED*/
413         }
414 }
415
416 PRIVATE
417 outargstring(arg)
418         struct argument *arg;
419 {
420         char buff[1000];
421         register char *p;
422
423         bts2str(arg->CAS_VALUE, arg->CAS_LEN, buff);
424         for (p = &buff[0]; *p; p++) {
425                 if (*p == '"' || *p == ':')
426                         *p = ' ';
427         }
428         printf("\"%s\"", buff);
429 }
430
431 PRIVATE
432 outargtype(tp)
433         struct type *tp;
434 {
435         switch (tp->tp_fund) {
436         case POINTER:
437                 outargtype(tp->tp_up);
438                 printf("*");
439                 break;
440
441         case ARRAY:
442                 outargtype(tp->tp_up);
443                 printf("*");    /* compatible with [] */
444                 break;
445
446         case FUNCTION:
447                 outargtype(tp->tp_up);
448                 printf("()");
449                 break;
450
451         case STRUCT:
452         case UNION:
453         case ENUM:
454                 /* watch out for anonymous identifiers; the count field does
455                    not have to be the same for all compilation units.
456                    Remove it, so that pass 2 does not see it. The only
457                    problem with this is that pass2 will not see a difference
458                    between two non-tagged types declared on the same line.
459                 */
460                 printf("%s ", symbol2str(tp->tp_fund));
461                 if (is_anon_idf(tp->tp_idf)) {
462                         /* skip the #<num>, replace it by '#anonymous id' */
463                         printf("#anonymous id%s", strindex(tp->tp_idf->id_text, ' '));
464                 }
465                 else printf(tp->tp_idf->id_text);
466                 break;
467
468         case CHAR:
469         case INT:
470         case SHORT:
471         case LONG:
472         case FLOAT:
473         case DOUBLE:
474         case VOID:
475         case ERRONEOUS:
476                 if (tp->tp_unsigned)
477                         printf("unsigned ");
478                 printf("%s", symbol2str(tp->tp_fund));
479                 break;
480         default:
481                 NOTREACHED();
482                 /*NOTREACHED*/
483         }
484 }
485
486 #ifdef  IMPLICIT
487 PRIVATE
488 implicit_func_decl(idf, file, line)
489         struct idf *idf;
490         char *file;
491         unsigned int line;
492 {
493         struct outdef od;
494
495         od.od_class = IFDC;
496         od.od_statnr = 0;
497         od.od_name = idf->id_text;
498         od.od_file = file;
499         od.od_line = line;
500         od.od_type = idf->id_def->df_type->tp_up;
501         output_def(&od);
502         /* The other fields are not used for this class. */
503 }
504 #endif  /* IMPLICIT */
505
506 fill_outcall(ex, used)
507         struct expr *ex;
508         int used;
509 {
510         register struct idf *idf = ex->OP_LEFT->VL_IDF;
511         register struct def *def = idf->id_def;
512
513 #ifdef  IMPLICIT
514         if (def->df_sc == IMPLICIT && !idf->id_def->df_used) {
515                 /* IFDC, first time */
516                 implicit_func_decl(idf, ex->ex_file, ex->ex_line);
517         }
518 #endif  /* IMPLICIT */
519
520         OutCall.od_type = def->df_type->tp_up;
521         OutCall.od_statnr = (def->df_sc == STATIC ? stat_number : 0);
522         OutCall.od_class = FC;
523         OutCall.od_name = idf->id_text;
524         OutCall.od_file = ex->ex_file;
525         OutCall.od_line = ex->ex_line;
526         OutCall.od_arg = (struct argument *)0;
527         OutCall.od_nrargs = 0;
528
529         if ((ex = ex->OP_RIGHT) != 0) {
530                 /* function call with arguments */
531                 /* store types of argument expressions in 'struct argument's */
532                 while (ex->ex_class == Oper && ex->OP_OPER == PARCOMMA) {
533                         add_expr_arg(ex->OP_RIGHT);
534                         ex = ex->OP_LEFT;
535                 }
536                 add_expr_arg(ex);
537         }
538         OutCall.od_valused = used;      /* USED, IGNORED or VOIDED */
539 }
540
541 PRIVATE
542 add_expr_arg(e)
543         struct expr *e;
544 {
545         register struct argument *arg;
546
547         arg = new_argument();
548         arg->ar_type = e->ex_type;
549         if (is_cp_cst(e)) {
550                 arg->ar_class = ArgConst;
551                 arg->CAA_VALUE = e->VL_VALUE;
552         }
553         else if (       e->ex_type == string_type
554                 &&      e->ex_class == Value
555                 &&      e->VL_CLASS == Label
556                 ) {
557                 /* it may be a string; let's look it up */
558                 register struct string_cst *sc = str_list;
559
560                 while (sc) {
561                         if (sc->sc_dlb == e->VL_LBL)
562                                 break;
563                         sc = sc->next;
564                 }
565                 if (sc) {
566                         /* it was a string */
567                         arg->ar_class = ArgString;
568                         arg->CAS_VALUE = sc->sc_value;
569                         arg->CAS_LEN = sc->sc_len - 1;  /* included the \0 */
570                 }
571                 else {
572                         arg->ar_class = ArgExpr;
573                 }
574         }
575         else {
576                 arg->ar_class = ArgExpr;
577         }
578         arg->next = OutCall.od_arg;
579         OutCall.od_arg = arg;
580         OutCall.od_nrargs++;
581 }
582
583 #endif  /* LINT */