]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - usr.bin/xlint/lint1/init.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / usr.bin / xlint / lint1 / init.c
1 /*      $NetBSD: init.c,v 1.9 2001/09/18 18:15:54 wiz Exp $     */
2
3 /*
4  * Copyright (c) 1994, 1995 Jochen Pohl
5  * All Rights Reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by Jochen Pohl for
18  *      The NetBSD Project.
19  * 4. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <sys/cdefs.h>
35 #if defined(__RCSID) && !defined(lint)
36 __RCSID("$NetBSD: init.c,v 1.9 2001/09/18 18:15:54 wiz Exp $");
37 #endif
38 __FBSDID("$FreeBSD$");
39
40 #include <stdlib.h>
41
42 #include "lint1.h"
43
44 /*
45  * initerr is set as soon as a fatal error occurred in an initialisation.
46  * The effect is that the rest of the initialisation is ignored (parsed
47  * by yacc, expression trees built, but no initialisation takes place).
48  */
49 int     initerr;
50
51 /* Pointer to the symbol which is to be initialized. */
52 sym_t   *initsym;
53
54 /* Points to the top element of the initialisation stack. */
55 istk_t  *initstk;
56
57
58 static  void    popi2(void);
59 static  void    popinit(int);
60 static  void    pushinit(void);
61 static  void    testinit(void);
62 static  void    nextinit(int);
63 static  int     strginit(tnode_t *);
64
65
66 /*
67  * Initialize the initialisation stack by putting an entry for the variable
68  * which is to be initialized on it.
69  */
70 void
71 prepinit(void)
72 {
73         istk_t  *istk;
74
75         if (initerr)
76                 return;
77
78         /* free memory used in last initialisation */
79         while ((istk = initstk) != NULL) {
80                 initstk = istk->i_nxt;
81                 free(istk);
82         }
83
84         /*
85          * If the type which is to be initialized is an incomplete type,
86          * it must be duplicated.
87          */
88         if (initsym->s_type->t_tspec == ARRAY && incompl(initsym->s_type))
89                 initsym->s_type = duptyp(initsym->s_type);
90
91         istk = initstk = xcalloc(1, sizeof (istk_t));
92         istk->i_subt = initsym->s_type;
93         istk->i_cnt = 1;
94
95 }
96
97 static void
98 popi2(void)
99 {
100         istk_t  *istk;
101         sym_t   *m;
102
103         initstk = (istk = initstk)->i_nxt;
104         if (initstk == NULL)
105                 lerror("popi2() 1");
106         free(istk);
107
108         istk = initstk;
109
110         istk->i_cnt--;
111         if (istk->i_cnt < 0)
112                 lerror("popi2() 3");
113
114         /*
115          * If the removed element was a structure member, we must go
116          * to the next structure member.
117          */
118         if (istk->i_cnt > 0 && istk->i_type->t_tspec == STRUCT) {
119                 do {
120                         m = istk->i_mem = istk->i_mem->s_nxt;
121                         if (m == NULL)
122                                 lerror("popi2() 2");
123                 } while (m->s_field && m->s_name == unnamed);
124                 istk->i_subt = m->s_type;
125         }
126 }
127
128 static void
129 popinit(int brace)
130 {
131
132         if (brace) {
133                 /*
134                  * Take all entries, including the first which requires
135                  * a closing brace, from the stack.
136                  */
137                 do {
138                         brace = initstk->i_brace;
139                         popi2();
140                 } while (!brace);
141         } else {
142                 /*
143                  * Take all entries which cannot be used for further
144                  * initializers from the stack, but do this only if
145                  * they do not require a closing brace.
146                  */
147                 while (!initstk->i_brace &&
148                        initstk->i_cnt == 0 && !initstk->i_nolimit) {
149                         popi2();
150                 }
151         }
152 }
153
154 static void
155 pushinit(void)
156 {
157         istk_t  *istk;
158         int     cnt;
159         sym_t   *m;
160
161         istk = initstk;
162
163         /* Extend an incomplete array type by one element */
164         if (istk->i_cnt == 0) {
165                 /*
166                  * Inside of other aggregate types must not be an incomplete
167                  * type.
168                  */
169                 if (istk->i_nxt->i_nxt != NULL)
170                         lerror("pushinit() 1");
171                 istk->i_cnt = 1;
172                 if (istk->i_type->t_tspec != ARRAY)
173                         lerror("pushinit() 2");
174                 istk->i_type->t_dim++;
175                 /* from now its a complete type */
176                 setcompl(istk->i_type, 0);
177         }
178
179         if (istk->i_cnt <= 0)
180                 lerror("pushinit() 3");
181         if (istk->i_type != NULL && issclt(istk->i_type->t_tspec))
182                 lerror("pushinit() 4");
183
184         initstk = xcalloc(1, sizeof (istk_t));
185         initstk->i_nxt = istk;
186         initstk->i_type = istk->i_subt;
187         if (initstk->i_type->t_tspec == FUNC)
188                 lerror("pushinit() 5");
189
190         istk = initstk;
191
192         switch (istk->i_type->t_tspec) {
193         case ARRAY:
194                 if (incompl(istk->i_type) && istk->i_nxt->i_nxt != NULL) {
195                         /* initialisation of an incomplete type */
196                         error(175);
197                         initerr = 1;
198                         return;
199                 }
200                 istk->i_subt = istk->i_type->t_subt;
201                 istk->i_nolimit = incompl(istk->i_type);
202                 istk->i_cnt = istk->i_type->t_dim;
203                 break;
204         case UNION:
205                 if (tflag)
206                         /* initialisation of union is illegal in trad. C */
207                         warning(238);
208                 /* FALLTHROUGH */
209         case STRUCT:
210                 if (incompl(istk->i_type)) {
211                         /* initialisation of an incomplete type */
212                         error(175);
213                         initerr = 1;
214                         return;
215                 }
216                 cnt = 0;
217                 for (m = istk->i_type->t_str->memb; m != NULL; m = m->s_nxt) {
218                         if (m->s_field && m->s_name == unnamed)
219                                 continue;
220                         if (++cnt == 1) {
221                                 istk->i_mem = m;
222                                 istk->i_subt = m->s_type;
223                         }
224                 }
225                 if (cnt == 0) {
226                         /* cannot init. struct/union with no named member */
227                         error(179);
228                         initerr = 1;
229                         return;
230                 }
231                 istk->i_cnt = istk->i_type->t_tspec == STRUCT ? cnt : 1;
232                 break;
233         default:
234                 istk->i_cnt = 1;
235                 break;
236         }
237 }
238
239 static void
240 testinit(void)
241 {
242         istk_t  *istk;
243
244         istk = initstk;
245
246         /*
247          * If a closing brace is expected we have at least one initializer
248          * too much.
249          */
250         if (istk->i_cnt == 0 && !istk->i_nolimit) {
251                 switch (istk->i_type->t_tspec) {
252                 case ARRAY:
253                         /* too many array initializers */
254                         error(173);
255                         break;
256                 case STRUCT:
257                 case UNION:
258                         /* too many struct/union initializers */
259                         error(172);
260                         break;
261                 default:
262                         /* too many initializers */
263                         error(174);
264                         break;
265                 }
266                 initerr = 1;
267         }
268 }
269
270 static void
271 nextinit(int brace)
272 {
273
274         if (!brace) {
275                 if (initstk->i_type == NULL &&
276                     !issclt(initstk->i_subt->t_tspec)) {
277                         /* {}-enclosed initializer required */
278                         error(181);
279                 }
280                 /*
281                  * Make sure an entry with a scalar type is at the top
282                  * of the stack.
283                  */
284                 if (!initerr)
285                         testinit();
286                 while (!initerr && (initstk->i_type == NULL ||
287                                     !issclt(initstk->i_type->t_tspec))) {
288                         if (!initerr)
289                                 pushinit();
290                 }
291         } else {
292                 if (initstk->i_type != NULL &&
293                     issclt(initstk->i_type->t_tspec)) {
294                         /* invalid initializer */
295                         error(176);
296                         initerr = 1;
297                 }
298                 if (!initerr)
299                         testinit();
300                 if (!initerr)
301                         pushinit();
302                 if (!initerr)
303                         initstk->i_brace = 1;
304         }
305 }
306
307 void
308 initlbr(void)
309 {
310
311         if (initerr)
312                 return;
313
314         if ((initsym->s_scl == AUTO || initsym->s_scl == REG) &&
315             initstk->i_nxt == NULL) {
316                 if (tflag && !issclt(initstk->i_subt->t_tspec))
317                         /* no automatic aggregate initialization in trad. C*/
318                         warning(188);
319         }
320
321         /*
322          * Remove all entries which cannot be used for further initializers
323          * and do not expect a closing brace.
324          */
325         popinit(0);
326
327         nextinit(1);
328 }
329
330 void
331 initrbr(void)
332 {
333
334         if (initerr)
335                 return;
336
337         popinit(1);
338 }
339
340 void
341 mkinit(tnode_t *tn)
342 {
343         ptrdiff_t offs;
344         sym_t   *sym;
345         tspec_t lt, rt;
346         tnode_t *ln;
347         struct  mbl *tmem;
348         scl_t   sc;
349
350         if (initerr || tn == NULL)
351                 goto end;
352
353         sc = initsym->s_scl;
354
355         /*
356          * Do not test for automatic aggregat initialisation. If the
357          * initializer starts with a brace we have the warning already.
358          * If not, an error will be printed that the initializer must
359          * be enclosed by braces.
360          */
361
362         /*
363          * Local initialisation of non-array-types with only one expression
364          * without braces is done by ASSIGN
365          */
366         if ((sc == AUTO || sc == REG) &&
367             initsym->s_type->t_tspec != ARRAY && initstk->i_nxt == NULL) {
368                 ln = getnnode(initsym, 0);
369                 ln->tn_type = tduptyp(ln->tn_type);
370                 ln->tn_type->t_const = 0;
371                 tn = build(ASSIGN, ln, tn);
372                 expr(tn, 0, 0);
373                 goto end;
374         }
375
376         /*
377          * Remove all entries which cannot be used for further initializers
378          * and do not require a closing brace.
379          */
380         popinit(0);
381
382         /* Initialisations by strings are done in strginit(). */
383         if (strginit(tn))
384                 goto end;
385
386         nextinit(0);
387         if (initerr || tn == NULL)
388                 goto end;
389
390         initstk->i_cnt--;
391
392         /* Create a temporary node for the left side. */
393         ln = tgetblk(sizeof (tnode_t));
394         ln->tn_op = NAME;
395         ln->tn_type = tduptyp(initstk->i_type);
396         ln->tn_type->t_const = 0;
397         ln->tn_lvalue = 1;
398         ln->tn_sym = initsym;           /* better than nothing */
399
400         tn = cconv(tn);
401
402         lt = ln->tn_type->t_tspec;
403         rt = tn->tn_type->t_tspec;
404
405         if (!issclt(lt))
406                 lerror("mkinit() 1");
407
408         if (!typeok(INIT, 0, ln, tn))
409                 goto end;
410
411         /*
412          * Store the tree memory. This is nessesary because otherwise
413          * expr() would free it.
414          */
415         tmem = tsave();
416         expr(tn, 1, 0);
417         trestor(tmem);
418
419         if (isityp(lt) && ln->tn_type->t_isfield && !isityp(rt)) {
420                 /*
421                  * Bit-fields can be initialized in trad. C only by integer
422                  * constants.
423                  */
424                 if (tflag)
425                         /* bit-field initialisation is illegal in trad. C */
426                         warning(186);
427         }
428
429         if (lt != rt || (initstk->i_type->t_isfield && tn->tn_op == CON))
430                 tn = convert(INIT, 0, initstk->i_type, tn);
431
432         if (tn != NULL && tn->tn_op != CON) {
433                 sym = NULL;
434                 offs = 0;
435                 if (conaddr(tn, &sym, &offs) == -1) {
436                         if (sc == AUTO || sc == REG) {
437                                 /* non-constant initializer */
438                                 (void)gnuism(177);
439                         } else {
440                                 /* non-constant initializer */
441                                 error(177);
442                         }
443                 }
444         }
445
446  end:
447         tfreeblk();
448 }
449
450
451 static int
452 strginit(tnode_t *tn)
453 {
454         tspec_t t;
455         istk_t  *istk;
456         int     len;
457         strg_t  *strg;
458
459         if (tn->tn_op != STRING)
460                 return (0);
461
462         istk = initstk;
463         strg = tn->tn_strg;
464
465         /*
466          * Check if we have an array type which can be initialized by
467          * the string.
468          */
469         if (istk->i_subt->t_tspec == ARRAY) {
470                 t = istk->i_subt->t_subt->t_tspec;
471                 if (!((strg->st_tspec == CHAR &&
472                        (t == CHAR || t == UCHAR || t == SCHAR)) ||
473                       (strg->st_tspec == WCHAR && t == WCHAR))) {
474                         return (0);
475                 }
476                 /* Put the array at top of stack */
477                 pushinit();
478                 istk = initstk;
479         } else if (istk->i_type != NULL && istk->i_type->t_tspec == ARRAY) {
480                 t = istk->i_type->t_subt->t_tspec;
481                 if (!((strg->st_tspec == CHAR &&
482                        (t == CHAR || t == UCHAR || t == SCHAR)) ||
483                       (strg->st_tspec == WCHAR && t == WCHAR))) {
484                         return (0);
485                 }
486                 /*
487                  * If the array is already partly initialized, we are
488                  * wrong here.
489                  */
490                 if (istk->i_cnt != istk->i_type->t_dim)
491                         return (0);
492         } else {
493                 return (0);
494         }
495
496         /* Get length without trailing NUL character. */
497         len = strg->st_len;
498
499         if (istk->i_nolimit) {
500                 istk->i_nolimit = 0;
501                 istk->i_type->t_dim = len + 1;
502                 /* from now complete type */
503                 setcompl(istk->i_type, 0);
504         } else {
505                 if (istk->i_type->t_dim < len) {
506                         /* non-null byte ignored in string initializer */
507                         warning(187);
508                 }
509         }
510
511         /* In every case the array is initialized completely. */
512         istk->i_cnt = 0;
513
514         return (1);
515 }