]> andersk Git - splint.git/blame - src/uentry.c
Updating to use the LEnsures and LRequires instead of the ensures requires so
[splint.git] / src / uentry.c
CommitLineData
616915dd 1/*
2** LCLint - annotation-assisted static program checker
3** Copyright (C) 1994-2000 University of Virginia,
4** Massachusetts Institute of Technology
5**
6** This program is free software; you can redistribute it and/or modify it
7** under the terms of the GNU General Public License as published by the
8** Free Software Foundation; either version 2 of the License, or (at your
9** option) any later version.
10**
11** This program is distributed in the hope that it will be useful, but
12** WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14** General Public License for more details.
15**
16** The GNU General Public License is available from http://www.gnu.org/ or
17** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18** MA 02111-1307, USA.
19**
20** For information on lclint: lclint-request@cs.virginia.edu
21** To report a bug: lclint-bug@cs.virginia.edu
22** For more information: http://lclint.cs.virginia.edu
23*/
24/*
25** uentry.c
26*/
27
28# include "lclintMacros.nf"
29# include "basic.h"
30# include "structNames.h"
31# include "nameChecks.h"
32
33/*@i223*/
34/*@-type*/
35static /*@dependent@*/ uentry posRedeclared = uentry_undefined;
36static /*@only@*/ fileloc posLoc = fileloc_undefined;
37static int nuentries = 0;
38static int totuentries = 0;
39
40static void checkGlobalsModifies (/*@notnull@*/ uentry p_ue, sRefSet p_sr) ;
41static void uentry_setDeclDef (uentry p_e, fileloc p_f) /*@modifies p_e@*/ ;
42static bool uentry_isRefCounted (uentry p_ue) /*@*/ ;
43static bool uentry_isRefsField (uentry p_ue) /*@*/ ;
44static bool uentry_isReallySpecified (uentry p_e) /*@*/ ;
45static void uentry_checkIterArgs (uentry p_ue);
46static cstring uentry_dumpAux (uentry p_v, bool p_isParam);
47
48/*@access ekind@*/
49static void checkAliasState (/*@notnull@*/ uentry p_old,
50 /*@notnull@*/ uentry p_unew,
51 bool p_mustConform, bool p_completeConform)
52 /*@modifies p_old, p_unew@*/ ;
53static void checkNullState (/*@notnull@*/ uentry p_old,
54 /*@notnull@*/ uentry p_unew,
55 bool p_mustConform, bool p_completeConform)
56 /*@modifies p_old, p_unew@*/ ;
57
58static void checkVarConformance (/*@notnull@*/ uentry p_old,
59 /*@notnull@*/ uentry p_unew,
60 bool p_mustConform, bool p_completeConform)
61 /*@modifies p_old, p_unew@*/;
62
63# ifndef NOLCL
64static void uentry_setHasMods (uentry p_ue) /*@modifies p_ue@*/;
65static void uentry_setHasGlobs (uentry p_ue) /*@modifies p_ue@*/;
66# endif
67
68static void uentry_reallyFree (/*@notnull@*/ /*@only@*/ uentry p_e);
69
70static void uentry_setSpecDef (/*@special@*/ uentry p_e, /*@keep@*/ fileloc p_f)
71 /*@defines p_e->whereSpecified, p_e->whereDeclared, p_e->whereDefined@*/
72 /*@modifies p_e@*/;
73
74static void returnValueError (/*@notnull@*/ uentry p_old, /*@notnull@*/ uentry p_unew);
75static void nargsError (/*@notnull@*/ uentry p_old, /*@notnull@*/ uentry p_unew);
76static /*@observer@*/ cstring paramStorageName (uentry p_ue) /*@*/ ;
77static /*@observer@*/ cstring fcnErrName (uentry p_ue) /*@*/ ;
78static /*@observer@*/ cstring checkedName (chkind p_checked) /*@*/ ;
79static void
80 paramTypeError (/*@notnull@*/ uentry p_old, /*@notnull@*/ uentry p_oldCurrent,
81 ctype p_oldType, /*@notnull@*/ uentry p_unew,
82 /*@notnull@*/ uentry p_newCurrent,
83 ctype p_newType, int p_paramno) /*@modifies g_msgstream@*/ ;
84
85static /*@only@*/ /*@notnull@*/ uentry
86 uentry_makeVariableAux (cstring p_n, ctype p_t, /*@keep@*/ fileloc p_f,
87 /*@exposed@*/ sRef p_s, bool p_priv, vkind p_kind);
88
89static /*@out@*/ /*@notnull@*/ uentry uentry_alloc (void) /*@*/
90{
91 uentry ue = (uentry) dmalloc (sizeof (*ue));
92 nuentries++;
93 totuentries++;
94
95 return ue;
96}
97
98static cstring uentry_getOptName (uentry p_e) /*@*/ ;
99static void uentry_copyInto (/*@out@*/ /*@unique@*/ uentry p_unew, uentry p_old);
100static void uentry_setNullState (/*@notnull@*/ uentry p_ue, nstate p_ns);
101static void uentry_setAliasKind (/*@notnull@*/ uentry p_ue, alkind p_ak);
102static /*@only@*/ /*@null@*/ uinfo uinfo_copy (uinfo p_u, ekind p_kind);
103static void uinfo_free (/*@only@*/ uinfo p_u, ekind p_kind);
104static void uvinfo_free (/*@only@*/ uvinfo p_u);
105
106# ifdef DOANNOTS
107
108static /*@only@*/ cstring ancontext_unparse (ancontext an)
109{
110 switch (an)
111 {
112 case AN_UNKNOWN: return cstring_makeLiteral ("unknown");
113 case AN_FCNRETURN: return cstring_makeLiteral ("return value");
114 case AN_FCNPARAM: return cstring_makeLiteral ("function param");
115 case AN_SUFIELD: return cstring_makeLiteral ("su field");
116 case AN_TDEFN: return cstring_makeLiteral ("type definition");
117 case AN_GSVAR: return cstring_makeLiteral ("global/static var");
118 case AN_CONST: return cstring_makeLiteral ("constant");
119 BADDEFAULT;
120 }
121 BADEXIT;
122}
123
124static int annots[AN_LAST][QU_LAST];
125static int decls[AN_LAST];
126static int shdecls[AN_LAST];
127static int idecls[AN_LAST];
128
129void initAnnots ()
130{
131 int i, j;
132
133 for (i = AN_UNKNOWN; i < AN_LAST; i++)
134 {
135 decls[i] = 0;
136 shdecls[i] = 0;
137 idecls[i] = 0;
138
139 for (j = QU_UNKNOWN; j < QU_LAST; j++)
140 {
141 annots[i][j] = 0;
142 }
143 }
144}
145
146static void tallyAnnot (ancontext ac, qual q)
147{
148 (annots[ac][q])++;
149}
150
151void printAnnots ()
152{
153 int total[QU_LAST];
154 int alltotals = 0;
155 int totdecls = 0;
156 int totshdecls = 0;
157 int totidecls = 0;
158 int i, j;
159
160 for (j = QU_UNKNOWN; j < QU_LAST; j++)
161 {
162 total[j] = 0;
163 }
164
165 for (i = AN_UNKNOWN; i < AN_LAST; i++)
166 {
167 int tmptot;
168
169 if (decls[i] > 0)
170 {
171 printf ("Context: %s (%d declarations, %d sharable, %d indirect)\n",
172 ancontext_unparse (i),
173 decls[i], shdecls[i], idecls[i]);
174
175 totdecls += decls[i];
176 totshdecls += shdecls[i];
177 totidecls += idecls[i];
178
179 for (j = QU_UNKNOWN; j < QU_LAST; j++)
180 {
181 total[j] += annots[i][j];
182 alltotals += annots[i][j];
183 }
184
185 printf (" Allocation:\n");
186
187 tmptot = 0;
188
189 for (j = QU_UNKNOWN; j < QU_LAST; j++)
190 {
191 if (qual_isAliasQual (j) && !qual_isUnique (j))
192 {
193 if (annots[i][j] > 0)
194 {
195 printf ("\t%10s: %5d (%3.2f%%)\n", qual_unparse (j), annots[i][j],
196 100.0 * (double)annots[i][j] / (double)decls[i]);
197 tmptot += annots[i][j];
198 }
199 }
200 }
201
202 printf (" Exposure:\n");
203
204 tmptot = 0;
205
206 for (j = QU_UNKNOWN; j < QU_LAST; j++)
207 {
208 if (qual_isExQual (j))
209 {
210 if (annots[i][j] > 0)
211 {
212 printf ("\t%10s: %5d (%3.2f%%)\n", qual_unparse (j), annots[i][j],
213 100.0 * (double)annots[i][j] / (double)decls[i]);
214 tmptot += annots[i][j];
215 }
216 }
217 }
218
219 printf (" Definition:\n");
220
221 for (j = QU_UNKNOWN; j < QU_LAST; j++)
222 {
223 if (qual_isAllocQual (j))
224 {
225 if (annots[i][j] > 0)
226 {
227 printf ("\t%10s: %5d (%3.2f%%)\n", qual_unparse (j), annots[i][j],
228 100.0 * (double)annots[i][j] / (double)decls[i]);
229 }
230 }
231 }
232
233 printf (" Null:\n");
234
235 for (j = QU_UNKNOWN; j < QU_LAST; j++)
236 {
237 if (qual_isNull (j) || qual_isNotNull (j) || qual_isRelNull (j))
238 {
239 if (annots[i][j] > 0)
240 {
241 printf ("\t%10s: %5d (%3.2f%%)\n", qual_unparse (j), annots[i][j],
242 100.0 * (double)annots[i][j] / (double)decls[i]);
243 }
244 }
245 }
246
247 printf ("\n");
248 }
249 }
250
251 for (j = QU_UNKNOWN; j < QU_LAST; j++)
252 {
253 bool hasone = FALSE;
254
255 for (i = AN_UNKNOWN; i < AN_LAST; i++)
256 {
257 if (annots[i][j] > 0)
258 {
259 hasone = TRUE;
260 break;
261 }
262 }
263
264 if (hasone)
265 {
266 printf ("Annotation: %s\n", qual_unparse (j));
267
268 for (i = AN_UNKNOWN; i < AN_LAST; i++)
269 {
270 if (annots[i][j] > 0)
271 {
272 printf ("%25s: %5d\n", ancontext_unparse (i), annots[i][j]);
273 }
274 }
275 printf ("\n");
276 }
277 }
278
279 printf ("All Contexts\n");
280
281 for (j = QU_UNKNOWN; j < QU_LAST; j++)
282 {
283 if (total[j] > 0)
284 {
285 printf ("%10s: %5d (%3.2f%%)\n", qual_unparse (j), total[j],
286 100.0 * (double)total[j] / (double)(totdecls));
287 }
288 }
289 printf ("\n");
290
4ab867d6 291 printf ("Total Annotations: %d (%d decls, %d sharable, %d indirect)\n", alltotals, totdecls, totshdecls, totidecls); }
616915dd 292
293extern void uentry_tallyAnnots (uentry u, ancontext kind)
294{
295 alkind ak = sRef_getAliasKind (u->sref);
296 exkind ek = sRef_getExKind (u->sref);
297 nstate ns = sRef_getNullState (u->sref);
298 sstate ss = sRef_getDefState (u->sref);
299 bool recordUnknown = FALSE;
300
301
302 if (kind == AN_UNKNOWN)
303 {
304 ekind e = u->ukind;
305
306 if (e == KENDITER)
307 {
308 return;
309 }
310 else if (e == KCONST || e == KENUMCONST)
311 {
312 kind = AN_CONST;
313 }
314 else if (e == KFCN || e == KITER)
315 {
316 uentryList params = uentry_getParams (u);
317 bool hasRet = FALSE;
318
319 uentryList_elements (params, current)
320 {
321 if (uentry_isReturned (current))
322 {
323 hasRet = TRUE;
324 }
325 if (!uentry_isElipsisMarker (current))
326 {
327 uentry_tallyAnnots (current, AN_FCNPARAM);
328 }
329 } end_uentryList_elements;
330
331 kind = AN_FCNRETURN;
332
333 if (ctype_isFunction (u->utype)
334 && !hasRet
335 && ctype_isVisiblySharable (ctype_realType (ctype_returnValue (u->utype))))
336 {
337 recordUnknown = TRUE;
338 }
339 }
340 else if (e == KDATATYPE || e == KSTRUCTTAG || e == KUNIONTAG || e == KENUMTAG)
341 {
342 ctype t = ctype_realType (u->utype);
343
344 if (ctype_isSU (t))
345 {
346 uentryList fields = ctype_getFields (t);
347
348 uentryList_elements (fields, current)
349 {
350 uentry_tallyAnnots (current, AN_SUFIELD);
351 }
352 } end_uentryList_elements;
353
354 kind = AN_TDEFN;
355
356 if (ctype_isVisiblySharable (u->utype))
357 {
358 recordUnknown = TRUE;
359 }
360 }
361 else
362 {
363 kind = AN_GSVAR;
364
365
366 if (ctype_isVisiblySharable (ctype_realType (u->utype)))
367 {
368 recordUnknown = TRUE;
369 }
370 }
371 }
372
373 decls[kind]++;
374
375 if (kind == AN_FCNRETURN)
376 {
377 if (recordUnknown)
378 {
379 shdecls[kind]++;
380 idecls[kind]++;
381 }
382 else
383 {
384 ;
385 }
386 }
387 else
388 {
389 if (ctype_isVisiblySharable (ctype_realType (u->utype)))
390 {
391 shdecls[kind]++;
392 }
393
394 if (ctype_isRealPointer (ctype_realType (u->utype)))
395 {
396 idecls[kind]++;
397 }
398 }
399
400
401
402
403
404
405
406
407
408
409 switch (ss)
410 {
411 case SS_ALLOCATED: tallyAnnot (kind, QU_OUT); break;
412 case SS_PARTIAL: tallyAnnot (kind, QU_PARTIAL); break;
413 case SS_RELDEF: tallyAnnot (kind, QU_RELDEF); break;
414 case SS_SPECIAL: tallyAnnot (kind, QU_SPECIAL); break;
415 default: break;
416 }
417
418 if (uentry_isReturned (u))
419 {
420 tallyAnnot (kind, QU_RETURNED);
421 }
422
423 switch (ak)
424 {
425 case AK_UNKNOWN:
426 if (ctype_isRefCounted (ctype_realType (u->utype))
427 || (ctype_isFunction (u->utype) &&
428 ctype_isRefCounted (ctype_realType (ctype_returnValue (u->utype)))))
429 {
430 ;
431 }
432 else
433 {
434 if (kind == AN_FCNPARAM)
435 {
436 tallyAnnot (kind, QU_TEMP);
437 }
438 else if (recordUnknown)
439 {
440 if (kind == AN_FCNRETURN)
441 {
442 }
443 tallyAnnot (kind, QU_UNKNOWN);
444 }
445 }
446 break;
447 case AK_ONLY: tallyAnnot (kind, QU_ONLY); break;
448 case AK_IMPONLY: tallyAnnot (kind, QU_ONLY); break;
449 case AK_KEEP: tallyAnnot (kind, QU_KEEP); break;
450 case AK_KEPT: tallyAnnot (kind, QU_KEPT); break;
451 case AK_IMPTEMP:
452 case AK_TEMP: tallyAnnot (kind, QU_TEMP); break;
453 case AK_SHARED: tallyAnnot (kind, QU_SHARED); break;
454 case AK_UNIQUE: tallyAnnot (kind, QU_UNIQUE); break;
455 case AK_RETURNED: tallyAnnot (kind, QU_RETURNED); break;
456 case AK_REFCOUNTED: tallyAnnot (kind, QU_UNKNOWN); break;
457 case AK_REFS: tallyAnnot (kind, QU_REFS); break;
458 case AK_KILLREF: tallyAnnot (kind, QU_KILLREF); break;
459 case AK_NEWREF: tallyAnnot (kind, QU_NEWREF); break;
460 case AK_OWNED: tallyAnnot (kind, QU_OWNED); break;
461 case AK_IMPDEPENDENT:
462 case AK_DEPENDENT: tallyAnnot (kind, QU_DEPENDENT); break;
463 case AK_ERROR:
464 case AK_FRESH:
465 case AK_STACK:
466 case AK_LOCAL:
467 break;
468 }
469
470 switch (ek)
471 {
472 case XO_EXPOSED: tallyAnnot (kind, QU_EXPOSED); break;
473 case XO_OBSERVER: tallyAnnot (kind, QU_OBSERVER); break;
474 default: break;
475 }
476
477 switch (ns)
478 {
479 case NS_ERROR: break;
480 case NS_UNKNOWN: break;
481 case NS_NOTNULL: break;
482 case NS_MNOTNULL: tallyAnnot (kind, QU_NOTNULL); break;
483 case NS_RELNULL: tallyAnnot (kind, QU_RELNULL); break;
484 case NS_CONSTNULL: tallyAnnot (kind, QU_NULL); break;
485 case NS_POSNULL: tallyAnnot (kind, QU_NULL); break;
486 case NS_DEFNULL:
487 case NS_ABSNULL: break;
488 }
489}
490
491# endif
492
493static /*@observer@*/ cstring specCode_unparse (specCode s) /*@*/
494{
495 switch (s)
496 {
497 case SPC_NONE: return cstring_makeLiteralTemp ("normal");
498 case SPC_PRINTFLIKE: return cstring_makeLiteralTemp ("printflike");
499 case SPC_SCANFLIKE: return cstring_makeLiteralTemp ("scanflike");
500 case SPC_MESSAGELIKE: return cstring_makeLiteralTemp ("messagelike");
501 case SPC_LAST: return cstring_makeLiteralTemp ("<error>");
502 }
503
504 BADEXIT;
505}
506
507static specCode specCode_fromInt (int i)
508{
509 /*@+enumint@*/
510 llassert (i >= SPC_NONE && i < SPC_LAST);
511
512 return ((specCode) i);
513 /*@=enumint@*/
514}
515
516/*@observer@*/ cstring uentry_specOrDefName (uentry u)
517{
518 if (uentry_isDeclared (u))
519 {
520 return cstring_makeLiteralTemp ("previously declared");
521 }
522 else
523 {
524 return cstring_makeLiteralTemp ("specified");
525 }
526}
527
528/*@observer@*/ cstring uentry_specDeclName (uentry u)
529{
530 if (uentry_isDeclared (u))
531 {
532 return cstring_makeLiteralTemp ("previous declaration");
533 }
534 else
535 {
536 return cstring_makeLiteralTemp ("specification");
537 }
538}
539
540static /*@observer@*/ cstring uentry_reDefDecl (uentry old, uentry unew) /*@*/
541{
542 if (uentry_isCodeDefined (old) && uentry_isCodeDefined (unew))
543 {
544 return cstring_makeLiteralTemp ("redefined");
545 }
546 else if (uentry_isCodeDefined (unew))
547 {
548 return cstring_makeLiteralTemp ("defined");
549 }
550 else if (uentry_isDeclared (old) && uentry_isDeclared (unew))
551 {
552 return cstring_makeLiteralTemp ("redeclared");
553 }
554 else
555 {
556 return cstring_makeLiteralTemp ("declared");
557 }
558}
559
560
561/*drl7x*/
d46ce6a4 562/*@only@*/ constraintList uentry_getFcnPreconditions (uentry ue)
616915dd 563{
564 if (uentry_isValid (ue))
565 {
566 {
567 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
568 {
4ab867d6 569 TPRINTF(( (message( "Function pointer %s not doing uentry_makeVarFunction", uentry_unparse(ue) )) ));
570 // uentry_makeVarFunction (ue);
616915dd 571 }
572
573 //llassert (uentry_isFunction (ue));
574 //llassert ((ue->info->fcn->preconditions));
575 //llassert ((ue->info->fcn->preconditions));
576 if (!uentry_isFunction (ue))
577 {
470b7798 578 DPRINTF ( (message ("called uentry_getFcnPreconditions on nonfunction %s",
616915dd 579 uentry_unparse (ue) ) ) );
580 if (!uentry_isSpecified (ue) )
581 {
470b7798 582 DPRINTF((message ("called uentry_getFcnPreconditions on nonfunction %s",
616915dd 583 uentry_unparse (ue) ) ));
584 return constraintList_undefined;
585 }
586
587
588 return constraintList_undefined;
589 }
590
4ab867d6 591 if (ue->info->fcn->preconditions != NULL)
616915dd 592 {
593 return constraintList_copy (ue->info->fcn->preconditions);
594 }
595 else
596 {
597 return NULL;
598 }
599 }
600
601 }
602
603 return constraintList_undefined;
604
605}
606
607
608/*drl
609 12/28/2000
610*/
611constraintList uentry_getFcnPostconditions (uentry ue)
612{
613 if (uentry_isValid (ue))
614 {
615 {
616 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
617 {
4ab867d6 618 TPRINTF(( (message( "Function pointer %s not doing uentry_makeVarFunction", uentry_unparse(ue) )) ));
619 //uentry_makeVarFunction (ue);
616915dd 620 }
621
622 //llassert (uentry_isFunction (ue));
623 //llassert ((ue->info->fcn->preconditions));
624 /* if (!uentry_isSpecified (ue) )
625 {
626 TPRINTF((message ("called uentry_getFcnPostconditions on nonfunction %s",
627 uentry_unparse (ue) ) ));
628 // return constraintList_undefined;
629 }*/
630
631 if (!uentry_isFunction (ue))
632 {
470b7798 633 /*llcontbug*/ DPRINTF( (message ("called uentry_getFcnPostconditions on nonfunction %s",
616915dd 634 uentry_unparse (ue) ) ) );
635 return constraintList_undefined;
636 }
637
2934b455 638 if (ue->info->fcn->postconditions != NULL)
616915dd 639 {
640 return constraintList_copy (ue->info->fcn->postconditions);
641 }
642 else
643 {
644 return NULL;
645 }
646 }
647
648 }
649
650 return constraintList_undefined;
651
652}
653
654
655static /*@only@*/ fileloc setLocation (void)
656{
657 fileloc fl = context_getSaveLocation ();
658
659 if (fileloc_isDefined (fl))
660 {
661 return fl;
662 }
663 else
664 {
665 return fileloc_copy (g_currentloc);
666 }
667}
668
669/*@notnull@*/ uentry uentry_makeEnumConstant (cstring n, ctype t)
670{
671 fileloc loc = setLocation ();
672 uentry ue = uentry_makeConstant (n, t, loc);
673
674 ue->ukind = KENUMCONST;
675 uentry_setDefined (ue, loc);
676 return ue;
677}
678
679/*@notnull@*/ uentry uentry_makeEnumInitializedConstant (cstring n, ctype t, exprNode expr)
680{
681 fileloc loc = setLocation ();
682 uentry ue = uentry_makeConstant (n, t, loc);
683 ctype etype = exprNode_getType (expr);
684
685 if (!ctype_isRealInt (etype)) {
686 voptgenerror
687 (FLG_ENUMMEMBERS,
688 message
689 ("Value of enum member is not an integeral type (type %s): %s",
690 ctype_unparse (etype), exprNode_unparse (expr)),
691 exprNode_loc (expr));
692 }
693
694 ue->ukind = KENUMCONST;
695 uentry_setDefined (ue, loc);
696 return ue;
697}
698
699# ifndef NOLCL
700/*@notnull@*/ uentry uentry_makeSpecEnumConstant (cstring n, ctype t, fileloc loc)
701{
702 uentry ue = uentry_makeConstant (n, t, loc);
703
704 ue->ukind = KENUMCONST;
705 return ue;
706}
707# endif
708
709/*@notnull@*/ uentry uentry_makeVariableLoc (cstring n, ctype t)
710{
711 return uentry_makeVariable (n, t, setLocation (), FALSE);
712}
713
714# ifndef NOLCL
715/*@notnull@*/ /*@only@*/ uentry uentry_makeUnnamedVariable (ctype t)
716{
717 return uentry_makeVariable (cstring_undefined, t, setLocation (), FALSE);
718}
719# endif
720
721/*@notnull@*/ uentry uentry_makeIdDatatype (idDecl id)
722{
723 ctype ct = idDecl_getCtype (id);
724 uentry ue = uentry_makeDatatype (idDecl_observeId (id), ct,
725 MAYBE, MAYBE, setLocation ());
726
727 uentry_reflectQualifiers (ue, idDecl_getQuals (id));
728
729 if (!ynm_isOn (ue->info->datatype->abs))
730 {
731 if (ctype_isUnknown (ct))
732 {
733 ue->info->datatype->mut = MAYBE;
734 }
735 else
736 {
737 ue->info->datatype->mut = ynm_fromBool (ctype_isMutable (ct));
738 }
739 }
740
741 return ue;
742}
743
744void uentry_checkParams (uentry ue)
745{
746 if (uentry_isValid (ue))
747 {
748 bool isExt = uentry_isExtern (ue);
749
750 if (uentry_isRealFunction (ue))
751 {
752 uentryList params = uentry_getParams (ue);
753
754 uentryList_elements (params, current)
755 {
756 if (uentry_isValid (current))
757 {
758 ctype ct = current->utype;
759
760 if (ctype_isFixedArray (ct))
761 {
762 if (ctype_isArray (ctype_baseArrayPtr (ct))
763 && !ctype_isFixedArray (ctype_baseArrayPtr (ct)))
764 {
765 ;
766 }
767 else
768 {
769 voptgenerror
770 (FLG_FIXEDFORMALARRAY,
771 message ("Function parameter %q declared as "
772 "manifest array (size constant is meaningless)",
773 uentry_getName (current)),
774 uentry_whereDeclared (current));
775 }
776 }
777 else
778 {
779 if (ctype_isArray (ct))
780 {
781 voptgenerror
782 (FLG_FORMALARRAY,
783 message ("Function parameter %q declared as "
784 "array (treated as pointer)",
785 uentry_getName (current)),
786 uentry_whereDeclared (current));
787 }
788 }
789
790 if (sRef_getNullState (uentry_getSref (current)) == NS_MNOTNULL)
791 {
792 if (ctype_isAbstract (ct) &&
793 (isExt || (ctype_isAbstract (ctype_realType (ct))
794 && !context_hasFileAccess (ctype_typeId (ct)))))
795 {
796 vgenhinterror
797 (FLG_INCONDEFS,
798 message
799 ("Function %q declared with notnull parameter %q of abstract "
800 "type %s",
801 uentry_getName (ue),
802 uentry_getName (current),
803 ctype_unparse (ct)),
804 message
805 ("Since %s is an abstract type, notnull can only be "
806 "used for parameters if the function is static to a "
807 "module where %s is accessible.",
808 ctype_unparse (ct),
809 ctype_unparse (ct)),
810 uentry_whereDeclared (current));
811 }
812 }
813 }
814 } end_uentryList_elements;
815
816 if (sRef_getNullState (uentry_getSref (ue)) == NS_MNOTNULL)
817 {
818 ctype ct = ue->utype;
819
820 if (ctype_isAbstract (ct)
821 && (isExt || (ctype_isAbstract (ctype_realType (ct))
822 && !context_hasFileAccess (ctype_typeId (ct)))))
823 {
824 vgenhinterror
825 (FLG_INCONDEFS,
826 message
827 ("%s %q declared %s notnull storage of abstract type %s",
828 ekind_capName (uentry_getKind (ue)),
829 uentry_getName (ue),
830 fcnErrName (ue),
831 ctype_unparse (ct)),
832 message
833 ("Since %s is an abstract type, notnull can only be used "
834 "if it is static to a module where %s is accessible.",
835 ctype_unparse (ct),
836 ctype_unparse (ct)),
837 uentry_whereDeclared (ue));
838 }
839 }
840 }
841 }
842}
843
844static void reflectImplicitFunctionQualifiers (/*@notnull@*/ uentry ue, bool spec)
845{
846 alkind ak = sRef_getAliasKind (ue->sref);
847
848 if (alkind_isRefCounted (ak))
849 {
850 sRef_setAliasKind (ue->sref, AK_NEWREF, fileloc_undefined);
851 }
852 else
853 {
854 if (alkind_isUnknown (ak))
855 {
856 exkind ek = sRef_getExKind (ue->sref);
857
858 if (exkind_isKnown (ek))
859 {
860 sRef_setAliasKind (ue->sref, AK_IMPDEPENDENT, fileloc_undefined);
861 }
862 else
863 {
864 if (context_getFlag (spec ? FLG_SPECRETIMPONLY : FLG_RETIMPONLY))
865 {
866 if (ctype_isVisiblySharable
867 (ctype_realType (ctype_returnValue (ue->utype))))
868 {
869 if (uentryList_hasReturned (uentry_getParams (ue)))
870 {
871 ;
872 }
873 else
874 {
875 sRef_setAliasKind (ue->sref, AK_IMPONLY,
876 fileloc_undefined);
877 }
878 }
879 }
880 }
881 }
882 }
883}
884
885static /*@notnull@*/ uentry
886uentry_makeFunctionAux (cstring n, ctype t,
887 typeIdSet access,
888 /*@only@*/ globSet globs,
889 /*@only@*/ sRefSet mods,
890 /*@keep@*/ fileloc f, bool priv,
891 /*@unused@*/ bool isForward)
892{
893 uentry e = uentry_alloc ();
894 ctype ret;
895
896 if (ctype_isFunction (t))
897 {
898 ret = ctype_returnValue (t);
899 }
900 else
901 {
902 if (ctype_isKnown (t))
903 {
904 llbug (message ("not function: %s", ctype_unparse (t)));
905 }
906 ret = ctype_unknown;
907 }
908
909 e->ukind = KFCN;
910
911 if (fileloc_isSpec (f) || fileloc_isImport (f))
912 {
913 e->whereSpecified = f;
914 e->whereDeclared = fileloc_undefined;
915 }
916 else
917 {
918 e->whereSpecified = fileloc_undefined;
919 e->whereDeclared = f;
920 }
921
922 /* e->shallowCopy = FALSE; */
923 e->uname = cstring_copy (n);
924 e->utype = t;
925 e->storageclass = SCNONE;
926
927 e->sref = sRef_makeType (ret);
928
929 if (ctype_isUA (ret))
930 {
931 sRef_setStateFromType (e->sref, ret);
932 }
933
934 e->used = FALSE;
935 e->lset = FALSE;
936 e->uses = filelocList_new ();
937 e->isPrivate = priv;
938 e->hasNameError = FALSE;
939
940 e->info = (uinfo) dmalloc (sizeof (*e->info));
941 e->info->fcn = (ufinfo) dmalloc (sizeof (*e->info->fcn));
942
943 e->info->fcn->hasMods = sRefSet_isDefined (mods);
944 e->info->fcn->hasGlobs = globSet_isDefined (globs);
945
946 e->info->fcn->exitCode = XK_UNKNOWN;
947 e->info->fcn->nullPred = QU_UNKNOWN;
948 e->info->fcn->specialCode = SPC_NONE;
949
950 e->info->fcn->access = access;
951 e->info->fcn->globs = globs;
952 e->info->fcn->defparams = uentryList_undefined;
953
954 sRef_setDefined (e->sref, f);
955 e->whereDefined = fileloc_undefined;
956
957 e->info->fcn->mods = sRefSet_undefined;
958 e->info->fcn->specclauses = NULL;
959
960 /*drl 11 29 2000*/
961 e->info->fcn->preconditions = NULL;
962 /*end drl*/
963
964 /*drl 12 28 2000*/
965 e->info->fcn->postconditions = NULL;
966 /*end drl*/
967
968 checkGlobalsModifies (e, mods);
969 e->info->fcn->mods = mods;
970
971 return (e);
972}
973
974/*@notnull@*/ uentry uentry_makeIdFunction (idDecl id)
975{
976 uentry ue =
977 uentry_makeFunction (idDecl_observeId (id), idDecl_getCtype (id),
978 typeId_invalid, globSet_undefined,
979 sRefSet_undefined,
980 setLocation ());
981
982 uentry_reflectQualifiers (ue, idDecl_getQuals (id));
983 reflectImplicitFunctionQualifiers (ue, FALSE);
984
985 if (!uentry_isStatic (ue)
986 && cstring_equalLit (ue->uname, "main"))
987 {
988 ctype typ = ue->utype;
989 ctype retval;
990 uentryList args;
991
992 llassert (ctype_isFunction (typ));
993
994 retval = ctype_returnValue (typ);
995
996 if (!ctype_isInt (retval))
997 {
998 voptgenerror
999 (FLG_MAINTYPE,
1000 message ("Function main declared to return %s, should return int",
1001 ctype_unparse (retval)),
1002 uentry_whereDeclared (ue));
1003 }
1004
1005 args = ctype_argsFunction (typ);
1006
1007 if (uentryList_isMissingParams (args)
1008 || uentryList_size (args) == 0)
1009 {
1010 ;
1011 }
1012 else
1013 {
1014 if (uentryList_size (args) != 2)
1015 {
1016 voptgenerror
1017 (FLG_MAINTYPE,
1018 message ("Function main declared with %d arg%p, "
1019 "should have 2 (int argc, char *argv[])",
1020 uentryList_size (args)),
1021 uentry_whereLast (ue));
1022 }
1023 else
1024 {
1025 uentry arg = uentryList_getN (args, 0);
1026 ctype ct = uentry_getType (arg);
1027
1028 if (!ctype_isInt (ct))
1029 {
1030 voptgenerror
1031 (FLG_MAINTYPE,
1032 message ("Parameter 1, %q, of function main declared "
1033 "with type %t, should have type int",
1034 uentry_getName (arg), ct),
1035 uentry_whereDeclared (arg));
1036 }
1037
1038 arg = uentryList_getN (args, 1);
1039 ct = uentry_getType (arg);
1040
1041 if (ctype_isArrayPtr (ct)
1042 && ctype_isArrayPtr (ctype_baseArrayPtr (ct))
1043 && ctype_isChar (ctype_baseArrayPtr (ctype_baseArrayPtr (ct))))
1044 {
1045 ;
1046 }
1047 else
1048 {
1049 voptgenerror
1050 (FLG_MAINTYPE,
1051 message ("Parameter 2, %q, of function main declared "
1052 "with type %t, should have type char **",
1053 uentry_getName (arg), ct),
1054 uentry_whereDeclared (arg));
1055 }
1056 }
1057 }
1058 }
1059
1060 return ue;
1061}
1062
1063static void uentry_implicitParamAnnots (/*@notnull@*/ uentry e)
1064{
1065 alkind ak = sRef_getAliasKind (e->sref);
1066
1067 if ((alkind_isUnknown (ak) || alkind_isImplicit (ak))
1068 && context_getFlag (FLG_PARAMIMPTEMP))
1069 {
1070 exkind ek = sRef_getExKind (e->sref);
1071
1072 if (exkind_isKnown (ek))
1073 {
1074 sRef_setAliasKind (e->sref, AK_IMPDEPENDENT, fileloc_undefined);
1075 sRef_setOrigAliasKind (e->sref, AK_IMPDEPENDENT);
1076 }
1077 else
1078 {
1079 sRef_setAliasKind (e->sref, AK_IMPTEMP, fileloc_undefined);
1080 sRef_setOrigAliasKind (e->sref, AK_IMPTEMP);
1081 }
1082 }
1083}
1084
1085static /*@only@*/ /*@notnull@*/ uentry
1086uentry_makeVariableParamAux (cstring n, ctype t, sRef s, sstate defstate)
1087{
1088 cstring pname = makeParam (n);
1089 uentry e = uentry_makeVariableAux (pname, t, setLocation (), s, FALSE, VKPARAM);
1090
1091 cstring_free (pname);
1092 uentry_implicitParamAnnots (e);
1093
1094 if (!sRef_isAllocated (e->sref) && !sRef_isPartial (e->sref))
1095 {
1096 sRef_setDefState (e->sref, defstate, uentry_whereDeclared (e));
1097 e->info->var->defstate = defstate;
1098 }
1099
1100 return (e);
1101}
1102
1103# ifndef NOLCL
1104void
1105uentry_setRefCounted (uentry e)
1106{
1107 if (uentry_isValid (e))
1108 {
1109 uentry_setAliasKind (e, AK_REFCOUNTED);
1110 sRef_storeState (e->sref);
1111 }
1112}
1113# endif
1114
1115void
1116uentry_setStatic (uentry c)
1117{
1118 if (uentry_isValid (c))
1119 {
1120 alkind ak = sRef_getAliasKind (c->sref);
1121 c->storageclass = SCSTATIC;
1122
1123 if (uentry_isVariable (c) && !ctype_isFunction (uentry_getType (c)))
1124 {
1125 if (!alkind_isUnknown (ak)
1126 && !alkind_isStatic (ak))
1127 {
1128 if (!(ctype_isRealPointer (uentry_getType (c)))
1129 && !(ctype_isAbstract (ctype_realType (uentry_getType (c))))
1130 && !alkind_isRefCounted (ak))
1131 {
1132 if (alkind_isImplicit (ak)
1133 && alkind_isDependent (ak)
1134 && ctype_isArray (uentry_getType (c)))
1135 {
1136 ; /* no error for observer arrays */
1137 }
1138 else
1139 {
1140 voptgenerror
1141 (FLG_INCONDEFS,
1142 message ("Static storage %q declared as %s",
1143 uentry_getName (c),
1144 alkind_unparse (ak)),
1145 uentry_whereDeclared (c));
1146 }
1147 }
1148 }
1149 else
1150 {
1151 if (alkind_isUnknown (ak)
1152 || (alkind_isImplicit (sRef_getAliasKind (c->sref))
1153 && !alkind_isDependent (sRef_getAliasKind (c->sref))))
1154 {
1155 sRef_setAliasKind (c->sref, AK_STATIC, fileloc_undefined);
1156 sRef_setOrigAliasKind (c->sref, AK_STATIC);
1157 }
1158 }
1159 }
1160 }
1161}
1162
1163void
1164uentry_setExtern (uentry c)
1165{
1166 if (uentry_isValid (c))
1167 c->storageclass = SCEXTERN;
1168}
1169
1170void
1171uentry_setParamNo (uentry ue, int pno)
1172{
1173 llassert (uentry_isAnyParam (ue) && sRef_isParam (ue->sref));
1174 sRef_setParamNo (ue->sref, pno);
1175}
1176
1177static
1178void checkGlobalsModifies (/*@notnull@*/ uentry ue, sRefSet sr)
1179{
1180 sRefSet_allElements (sr, el)
1181 {
1182 sRef base = sRef_getRootBase (el);
1183
1184 if (sRef_isGlobal (base) || sRef_isInternalState (base)
1185 || (sRef_isKindSpecial (base) && !sRef_isNothing (base)))
1186 {
1187 if (!globSet_member (ue->info->fcn->globs, base))
1188 {
1189 if (uentry_hasGlobs (ue)
1190 || context_getFlag (FLG_WARNMISSINGGLOBALSNOGLOBS))
1191 {
1192 if (optgenerror
1193 (FLG_WARNMISSINGGLOBALS,
1194 message
1195 ("Modifies list for %q uses global %q, "
1196 "not included in globals list.",
1197 uentry_getName (ue),
1198 sRef_unparse (base)),
1199 uentry_whereLast (ue)))
1200 {
1201 uentry_showWhereSpecified (ue);
1202 }
1203 }
1204
1205 ue->info->fcn->globs = globSet_insert (ue->info->fcn->globs,
1206 base);
1207 if (sRef_isFileStatic (base))
1208 {
1209 context_recordFileGlobals (ue->info->fcn->globs);
1210 }
1211 }
1212 }
1213 } end_sRefSet_allElements;
1214}
1215
1216uentry
1217uentry_makeVariableSrefParam (cstring n, ctype t, sRef s)
1218{
1219 return (uentry_makeVariableParamAux (n, t, s, SS_UNKNOWN));
1220}
1221
1222void
1223uentry_fixupSref (uentry ue)
1224{
1225 sRef sr;
1226
1227 if (uentry_isUndefined (ue) || uentry_isElipsisMarker (ue))
1228 {
1229 return;
1230 }
1231
1232 sr = uentry_getSref (ue);
1233
1234 sRef_resetState (sr);
1235 sRef_clearDerived (sr);
1236
1237 llassertprint (uentry_isVariable (ue), ("fixing: %s", uentry_unparseFull (ue)));
1238 llassert (sRef_isValid (sr));
1239
1240 if (uentry_isVariable (ue))
1241 {
1242 sRef_setDefState (sr, ue->info->var->defstate, fileloc_undefined);
1243 sRef_setNullState (sr, ue->info->var->nullstate, fileloc_undefined);
1244 }
1245}
1246
1247void uentry_setSpecialClauses (uentry ue, specialClauses clauses)
1248{
1249 llassert (uentry_isFunction (ue));
1250 llassert (!specialClauses_isDefined (ue->info->fcn->specclauses));
1251
1252 ue->info->fcn->specclauses = clauses;
1253 specialClauses_checkAll (ue);
1254}
1255
1256/*
1257** Used for @modifies@ @endmodifies@ syntax.
1258**
1259** If ue is specified, sr must contain *only*:
1260**
1261** o file static globals
1262** o sRef's derived from modifies spec (i.e., more specific than
1263** what was specified)
1264**
1265** Otherwise, if sr has modifies it must match sr.
1266**
1267** If it doesn't have modifies, set them to sr.
1268*/
1269
1270void
1271uentry_setModifies (uentry ue, /*@owned@*/ sRefSet sr)
1272{
1273 if (sRef_modInFunction ())
1274 {
1275 llparseerror
1276 (message ("Modifies list not in function context. "
1277 "A modifies list can only appear following the parameter list "
1278 "in a function declaration or header."));
1279
1280 /*@-mustfree@*/ return; /*@=mustfree@*/
1281 }
1282
1283 if (sRefSet_hasStatic (sr))
1284 {
1285 context_recordFileModifies (sr);
1286 }
1287
1288 if (uentry_isValid (ue))
1289 {
1290 if (uentry_isIter (ue))
1291 {
1292 llassert (sRefSet_isUndefined (ue->info->iter->mods));
1293 ue->info->iter->mods = sr;
1294 }
1295 else
1296 {
1297 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
1298 {
1299 uentry_makeVarFunction (ue);
1300 }
1301
1302 llassertfatal (uentry_isFunction (ue));
1303 llassert (sRefSet_isUndefined (ue->info->fcn->mods));
1304
1305 ue->info->fcn->mods = sr;
1306 ue->info->fcn->hasMods = TRUE;
1307
1308 checkGlobalsModifies (ue, sr);
1309 }
1310
1311 if (context_getFlag (FLG_MODIFIESIMPNOGLOBALS))
1312 {
1313 ue->info->fcn->hasGlobs = TRUE;
1314 }
1315 }
1316 else
1317 {
1318 sRefSet_free (sr);
1319 }
1320}
1321
1322void
920a3797 1323uentry_setPreconditions (uentry ue, /*@only@*/ constraintList preconditions)
616915dd 1324{
1325 if (sRef_modInFunction ())
1326 {
1327 llparseerror
1328 (message ("Precondition list not in function context. "
1329 "A precondition list can only appear following the parameter list "
1330 "in a function declaration or header."));
1331
1332 /*@-mustfree@*/ return; /*@=mustfree@*/
1333 }
1334
1335 if (uentry_isValid (ue))
1336 {
1337 {
1338 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
1339 {
1340 uentry_makeVarFunction (ue);
1341 }
1342
1343 llassertfatal (uentry_isFunction (ue));
1344 // llassert (sRefSet_isUndefined (ue->info->fcn->mods));
bb25bea6 1345
1346 if ((ue->info->fcn->preconditions) != NULL )
1347 {
1348 constraintList_free(ue->info->fcn->preconditions);
1349 ue->info->fcn->preconditions = preconditions;
1350 }
1351 else
1352 ue->info->fcn->preconditions = preconditions;
616915dd 1353 }
1354
1355 }
1356 else
1357 {
920a3797 1358 llfatalbug ( (message("uentry_setPreconditions called with invalid uentry") ));
616915dd 1359 }
1360}
1361
1362/*
1363 drl
1364 added 12/28/2000
1365*/
1366void
920a3797 1367uentry_setPostconditions (uentry ue, /*@only@*/ constraintList postconditions)
616915dd 1368{
1369 if (sRef_modInFunction ())
1370 {
1371 llparseerror
1372 (message ("Postcondition list not in function context. "
1373 "A postcondition list can only appear following the parameter list "
1374 "in a function declaration or header."));
1375
1376 /*@-mustfree@*/ return; /*@=mustfree@*/
1377 }
1378
1379 if (uentry_isValid (ue))
1380 {
1381 {
1382 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
1383 {
1384 uentry_makeVarFunction (ue);
1385 }
1386
1387 llassertfatal (uentry_isFunction (ue));
1388 // llassert (sRefSet_isUndefined (ue->info->fcn->mods));
bb25bea6 1389
1390 if ((ue->info->fcn->postconditions ) == NULL)
1391 ue->info->fcn->postconditions = postconditions;
1392 else
1393 {
1394 constraintList_free(ue->info->fcn->postconditions);
1395 ue->info->fcn->postconditions = postconditions;
1396 }
1397
616915dd 1398 }
1399
1400 }
1401 else
1402 {
920a3797 1403 llfatalbug ( (message("uentry_setPostconditions called with invalid uentry") ));
616915dd 1404 }
1405}
1406
1407/*
1408** requires: new and old are functions
1409*/
1410
1411static void
1412checkGlobalsConformance (/*@notnull@*/ uentry old,
1413 /*@notnull@*/ uentry unew,
1414 bool mustConform, bool completeConform)
1415{
1416 bool hasInternalState = FALSE;
1417
1418 old->info->fcn->hasGlobs |= unew->info->fcn->hasGlobs;
1419
1420 if (globSet_isDefined (unew->info->fcn->globs))
1421 {
1422 globSet_allElements (unew->info->fcn->globs, el)
1423 {
1424 if (sRef_isFileStatic (el))
1425 {
1426 sRef sr = globSet_lookup (old->info->fcn->globs, el);
1427
1428 if (sRef_isInvalid (sr))
1429 {
1430 bool hasError = FALSE;
1431
1432 if (!hasInternalState
1433 && sRef_isInvalid (globSet_lookup (old->info->fcn->globs,
1434 sRef_makeInternalState ()))
1435 && sRef_isInvalid (globSet_lookup (old->info->fcn->globs,
1436 sRef_makeSpecState ())))
1437 {
1438 if (mustConform
1439 && !uentry_isStatic (old)
1440 && optgenerror
1441 (FLG_INCONDEFS,
1442 message ("Globals list for %q includes internal state, %q, "
1443 "but %s without globals internalState.",
1444 uentry_getName (old),
1445 sRef_unparse (el),
1446 uentry_specOrDefName (old)),
1447 uentry_whereLast (unew)))
1448 {
1449 uentry_showWhereSpecified (old);
1450 hasError = TRUE;
1451 }
1452
1453 old->info->fcn->globs = globSet_insert (old->info->fcn->globs,
1454 sRef_makeInternalState ());
1455 hasInternalState = TRUE;
1456 }
1457
1458 if (!hasError
1459 && fileloc_sameFile (uentry_whereDeclared (unew),
1460 uentry_whereDeclared (old)))
1461 {
1462 if (mustConform
1463 && optgenerror
1464 (FLG_INCONDEFS,
1465 message ("Function %q inconsistently %rdeclared (in "
1466 "same file) with file static global %q in "
1467 "globals list",
1468 uentry_getName (unew),
1469 uentry_isDeclared (old),
1470 sRef_unparse (el)),
1471 uentry_whereDeclared (unew)))
1472 {
1473 uentry_showWhereSpecified (old);
1474 }
1475 }
1476 }
1477
1478 old->info->fcn->globs = globSet_insert (old->info->fcn->globs, el);
1479 context_recordFileGlobals (old->info->fcn->globs);
1480 }
1481 else
1482 {
1483 sRef sr = globSet_lookup (old->info->fcn->globs, el);
1484
1485 if (sRef_isInvalid (sr))
1486 {
1487 if (mustConform
1488 && optgenerror
1489 (FLG_INCONDEFS,
1490 message ("Function %q inconsistently %rdeclared with "
1491 "%q in globals list",
1492 uentry_getName (unew),
1493 uentry_isDeclared (old),
1494 sRef_unparse (el)),
1495 uentry_whereDeclared (unew)))
1496 {
1497 old->info->fcn->globs = globSet_insert (old->info->fcn->globs, el);
1498 uentry_showWhereSpecified (old);
1499 }
1500 }
1501 else
1502 {
1503 if (!bool_equal (sRef_isAllocated (el), sRef_isAllocated (sr)))
1504 {
1505 if (mustConform
1506 && optgenerror
1507 (FLG_INCONDEFS,
1508 message
1509 ("Function %q global %q inconsistently "
1510 "%rdeclared as %qout global",
1511 uentry_getName (unew),
1512 sRef_unparse (el),
1513 uentry_isDeclared (old),
1514 cstring_makeLiteral (sRef_isAllocated (el) ? "" : "non-")),
1515 uentry_whereDeclared (unew)))
1516 {
1517 uentry_showWhereSpecified (old);
1518 }
1519 }
1520 }
1521 }
1522 } end_globSet_allElements ;
1523
1524 if (completeConform)
1525 {
1526 globSet_allElements (old->info->fcn->globs, el)
1527 {
1528 sRef sr = globSet_lookup (unew->info->fcn->globs, el);
1529
1530 if (sRef_isInvalid (sr))
1531 {
1532 if (mustConform
1533 && uentry_isReallySpecified (old)
1534 && optgenerror
1535 (FLG_NEEDSPEC,
1536 message ("Function %q specified with %q in globals list, "
1537 "but declared without %q",
1538 uentry_getName (unew),
1539 sRef_unparse (el),
1540 sRef_unparse (el)),
1541 uentry_whereDeclared (unew)))
1542 {
1543 uentry_showWhereSpecified (old);
1544 }
1545 }
1546 } end_globSet_allElements;
1547 }
1548 }
1549 else
1550 {
1551 if (completeConform && !globSet_isEmpty (old->info->fcn->globs))
1552 {
1553 if (uentry_isReallySpecified (old)
1554 && optgenerror
1555 (FLG_NEEDSPEC,
1556 message ("%s %q specified with globals list, but "
1557 "declared with no globals",
1558 ekind_capName (unew->ukind),
1559 uentry_getName (unew)),
1560 uentry_whereDeclared (unew)))
1561 {
1562 llgenindentmsg
1563 (message ("Specification globals: %q",
1564 globSet_unparse (old->info->fcn->globs)),
1565 uentry_whereSpecified (old));
1566 }
1567 }
1568
1569 unew->info->fcn->globs = globSet_copy (unew->info->fcn->globs,
1570 old->info->fcn->globs);
1571 }
1572}
1573
1574/*
1575** new modifies list must be included by old modifies list.
1576**
1577** file static state may be added to new, if old has internal.
1578*/
1579
1580static void
1581checkModifiesConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
1582 bool mustConform, bool completeConform)
1583{
1584 sRefSet newMods;
1585 bool changedMods = FALSE;
1586 bool modInternal = FALSE;
1587
1588 llassert (uentry_isFunction (old) && uentry_isFunction (unew));
1589
1590 old->info->fcn->hasMods |= unew->info->fcn->hasMods;
1591 newMods = unew->info->fcn->mods;
1592
1593 if (sRefSet_isEmpty (newMods))
1594 {
1595 if (completeConform && !sRefSet_isEmpty (old->info->fcn->mods)
1596 && uentry_isReallySpecified (old))
1597 {
1598 if (optgenerror
1599 (FLG_NEEDSPEC,
1600 message ("%s %q specified with modifies clause, "
1601 "but declared with no modifies clause",
1602 ekind_capName (unew->ukind),
1603 uentry_getName (unew)),
1604 uentry_whereDeclared (unew)))
1605 {
1606 llgenindentmsg (message ("Specification has modifies %q",
1607 sRefSet_unparse (old->info->fcn->mods)),
1608 uentry_whereSpecified (old));
1609 }
1610 }
1611
1612 return;
1613 }
1614
1615 sRefSet_allElements (newMods, current)
1616 {
1617 if (sRef_isValid (current))
1618 {
1619 sRef rb = sRef_getRootBase (current);
1620
1621 if (sRef_isFileStatic (rb))
1622 {
1623 if (!modInternal)
1624 {
1625 if (!sRefSet_isSameMember (old->info->fcn->mods,
1626 sRef_makeInternalState ())
1627 && !sRefSet_isSameMember (old->info->fcn->mods,
1628 sRef_makeSpecState ()))
1629 {
1630 if (mustConform
1631 && !uentry_isStatic (old)
1632 && optgenerror
1633 (FLG_INCONDEFS,
1634 message
1635 ("Modifies list for %q includes internal state, "
1636 "but %s without modifies internal.",
1637 uentry_getName (old),
1638 uentry_specOrDefName (old)),
1639 uentry_whereLast (unew)))
1640 {
1641 uentry_showWhereSpecified (old);
1642 }
1643
1644 old->info->fcn->mods =
1645 sRefSet_insert (old->info->fcn->mods,
1646 sRef_makeInternalState ());
1647 modInternal = TRUE;
1648 }
1649 }
1650
1651 old->info->fcn->mods = sRefSet_insert (old->info->fcn->mods,
1652 current);
1653 changedMods = TRUE;
1654 }
1655 else
1656 {
1657 if (sRef_canModifyVal (current, old->info->fcn->mods))
1658 {
1659 int size = sRefSet_size (old->info->fcn->mods);
1660
1661 old->info->fcn->mods = sRefSet_insert (old->info->fcn->mods,
1662 current);
1663
1664 if (sRefSet_size (old->info->fcn->mods) != size)
1665 {
1666 changedMods = TRUE;
1667 }
1668 }
1669 else
1670 {
1671 if (mustConform
1672 && optgenerror
1673 (FLG_INCONDEFS,
1674 message
1675 ("Modifies list for %q contains %q, not modifiable "
1676 "according to %s",
1677 uentry_getName (old),
1678 sRef_unparse (current),
1679 uentry_specDeclName (old)),
1680 uentry_whereLast (unew)))
1681 {
1682 uentry_showWhereSpecified (old);
1683 }
1684 }
1685 }
1686 }
1687 } end_sRefSet_allElements;
1688
1689 if (completeConform && uentry_isReallySpecified (old))
1690 {
1691 sRefSet_allElements (old->info->fcn->mods, el)
1692 {
1693 if (sRef_canModify (el, newMods))
1694 {
1695 ; /* okay */
1696 }
1697 else
1698 {
1699 if (optgenerror
1700 (FLG_NEEDSPEC,
1701 message
1702 ("Specification modifies clause for %q contains %q, "
1703 "not included in declaration modifies clause",
1704 uentry_getName (old),
1705 sRef_unparse (el)),
1706 uentry_whereLast (unew)))
1707 {
1708 uentry_showWhereSpecified (old);
1709 }
1710 }
1711 } end_sRefSet_allElements ;
1712 }
1713
1714 /*
1715 ** Make sure file static elements will be removed.
1716 */
1717
1718 if (changedMods)
1719 {
1720 context_recordFileModifies (old->info->fcn->mods);
1721 }
1722}
1723
1724static void
1725 uentry_checkMutableType (uentry ue)
1726{
1727 ctype ct = uentry_getType (ue);
1728
1729 if (!ctype_isRealPointer (ct) && !ctype_isRealAbstract (ct))
1730 {
1731 voptgenerror (FLG_MUTREP,
1732 message ("Mutable abstract type %q declared without pointer "
1733 "indirection: %t (violates assignment semantics)",
1734 uentry_getName (ue), ct),
1735 uentry_whereDeclared (ue));
1736 }
1737}
1738
1739void
1740uentry_setMutable (uentry e)
1741{
1742 llassert (uentry_isDatatype (e));
1743 e->info->datatype->mut = YES;
1744}
1745
1746static void
1747uentry_checkIterArgs (uentry ue)
1748{
1749 bool hasYield = FALSE;
1750 uentryList args;
1751
1752 llassert (uentry_isIter (ue));
1753
1754 args = uentry_getParams (ue);
1755
1756 uentryList_elements (args, el)
1757 {
1758 sstate ds = uentry_getDefState (el);
1759
1760 if (uentry_isYield (el))
1761 {
1762 hasYield = TRUE;
1763 }
1764
1765 if (sstate_isUnknown (ds))
1766 {
1767 uentry_setDefState (el, SS_DEFINED);
1768 }
1769 else
1770 {
1771 ;
1772 }
1773 } end_uentryList_elements;
1774
1775 if (!hasYield)
1776 {
1777 voptgenerror (FLG_HASYIELD,
1778 message ("Iterator %q declared with no yield parameters",
1779 uentry_getName (ue)),
1780 uentry_whereDeclared (ue));
1781 }
1782}
1783
1784static chkind
1785chkind_fromQual (qual qel)
1786{
1787 if (qual_isChecked (qel))
1788 {
1789 return CH_CHECKED;
1790 }
1791 else if (qual_isCheckMod (qel))
1792 {
1793 return CH_CHECKMOD;
1794 }
1795 else if (qual_isCheckedStrict (qel))
1796 {
1797 return CH_CHECKEDSTRICT;
1798 }
1799 else if (qual_isUnchecked (qel))
1800 {
1801 return CH_UNCHECKED;
1802 }
1803 else
1804 {
1805 BADEXIT;
1806 /*@notreached@*/ return CH_UNKNOWN;
1807 }
1808}
1809
1810static void
1811uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel)
1812{
1813 if (qual_isKillRef (qel) || qual_isNewRef (qel) || qual_isTempRef (qel))
1814 {
1815 if (!uentry_isRefCounted (ue))
1816 {
1817 llerror
1818 (FLG_SYNTAX,
1819 message ("Reference counting qualifier %s used on non-reference "
1820 "counted storage: %q",
1821 qual_unparse (qel),
1822 uentry_unparse (ue)));
1823 }
1824 else
1825 {
1826 alkind ak = alkind_fromQual (qel);
1827
1828 uentry_setAliasKind (ue, ak);
1829 }
1830 }
1831 else if (qual_isRefCounted (qel))
1832 {
1833 ctype ct = ctype_realType (uentry_getType (ue));
1834 ctype rt;
1835
1836 if (ctype_isPointer (ct)
1837 && (ctype_isStruct (rt = ctype_realType (ctype_baseArrayPtr (ct)))))
1838 {
1839 /* check there is a refs field */
1840 uentryList fields = ctype_getFields (rt);
1841 uentry refs = uentry_undefined;
1842
1843 uentryList_elements (fields, field)
1844 {
1845 if (uentry_isRefsField (field))
1846 {
1847 if (uentry_isValid (refs))
1848 {
1849 llerror
1850 (FLG_SYNTAX,
1851 message ("Reference counted structure type %s has "
1852 "multiple refs fields: %q and %q",
1853 ctype_unparse (ct),
1854 uentry_getName (refs),
1855 uentry_getName (field)));
1856 }
1857
1858 refs = field;
1859 }
1860 } end_uentryList_elements;
1861
1862 if (uentry_isInvalid (refs))
1863 {
1864 vgenhinterror
1865 (FLG_SYNTAX,
1866 message ("Reference counted structure type %s has "
1867 "no refs field",
1868 ctype_unparse (ct)),
1869 cstring_makeLiteral
1870 ("To count reference, the structure must have a field named "
1871 "refs of type int."),
1872 g_currentloc);
1873 }
1874 else if (!ctype_isInt (uentry_getType (refs)))
1875 {
1876 llerror
1877 (FLG_SYNTAX,
1878 message ("Reference counted structure type %s refs field has "
1879 "type %s (should be int)", ctype_unparse (ct),
1880 ctype_unparse (uentry_getType (refs))));
1881 }
1882 else
1883 {
1884 sRef_setAliasKind (ue->sref, alkind_fromQual (qel),
1885 uentry_whereDeclared (ue));
1886 }
1887 }
1888 else
1889 {
1890 if ((ctype_isPointer (ct)
1891 && ctype_isUnknown (ctype_realType (ctype_baseArrayPtr (ct))))
1892 ||ctype_isAbstract (ct) || ctype_isUnknown (ct))
1893 {
1894 sRef_setAliasKind (ue->sref, alkind_fromQual (qel),
1895 uentry_whereDeclared (ue));
1896 }
1897 else
1898 {
1899 llerror
1900 (FLG_SYNTAX,
1901 message ("Non-pointer to structure type %s declared with "
1902 "refcounted qualifier",
1903 ctype_unparse (ct)));
1904 }
1905 }
1906 }
1907 else if (qual_isRefs (qel))
1908 {
1909 if (uentry_isVariable (ue) && !uentry_isParam (ue))
1910 {
1911 uentry_setAliasKind (ue, AK_REFS);
1912 }
1913 else
1914 {
1915 llerror
1916 (FLG_SYNTAX,
1917 message ("Refs qualifier used on non-structure field: %q",
1918 uentry_unparse (ue)));
1919 }
1920 }
1921 else if (qual_isAliasQual (qel))
1922 {
1923 alkind ak = alkind_fromQual (qel);
1924 bool okay = TRUE;
1925 alkind oldak = uentry_getAliasKind (ue);
1926 ctype ut = uentry_getType (ue);
1927
1928 if (alkind_isImplicit (ak)
1929 && (alkind_isKnown (oldak) && !alkind_isImplicit (oldak)))
1930 {
1931 /* ignore the implied qualifier */
1932 okay = FALSE;
1933 }
1934
1935 if (uentry_isEitherConstant (ue))
1936 {
1937 llerror
1938 (FLG_SYNTAX,
1939 message ("Alias qualifier %s used on constant: %q",
1940 alkind_unparse (ak), uentry_unparse (ue)));
1941 okay = FALSE;
1942 }
1943
1944 if (ctype_isFunction (ut))
1945 {
1946 ut = ctype_returnValue (ut);
1947 }
1948
1949 if (!(ctype_isVisiblySharable (ut)
1950 || ctype_isRealArray (ut)
1951 || ctype_isRealSU (ut)))
1952 {
1953 if (!qual_isImplied (qel))
1954 {
1955 llerror
1956 (FLG_SYNTAX,
1957 message ("Alias qualifier %s used on unsharable storage type %t: %q",
1958 alkind_unparse (ak), ut, uentry_getName (ue)));
1959 }
1960
1961 okay = FALSE;
1962 }
1963 else
1964 {
1965 if (uentry_isRefCounted (ue))
1966 {
1967 if (!(qual_isRefQual (qel) || qual_isOnly (qel)
1968 || qual_isExposed (qel)
1969 || qual_isObserver (qel)))
1970 {
1971 if (!qual_isImplied (qel))
1972 {
1973 llerror
1974 (FLG_SYNTAX,
1975 message
1976 ("Alias qualifier %s used on reference counted storage: %q",
1977 alkind_unparse (ak),
1978 uentry_unparse (ue)));
1979 }
1980
1981 okay = FALSE;
1982 }
1983 }
1984 else
1985 {
1986 if (qual_isRefQual (qel))
1987 {
1988 llerror
1989 (FLG_SYNTAX,
1990 message ("Qualifier %s used on non-reference counted storage: %q",
1991 alkind_unparse (ak), uentry_unparse (ue)));
1992
1993 okay = FALSE;
1994 }
1995 }
1996 }
1997
1998 if (okay)
1999 {
2000 uentry_setAliasKind (ue, ak);
2001 }
2002 }
2003 else if (qual_isNull (qel))
2004 {
2005 if (uentry_isConstant (ue))
2006 {
2007 sRef_setNullState
2008 (ue->sref,
2009 ctype_isAbstract (ue->utype) ? NS_CONSTNULL : NS_DEFNULL,
2010 uentry_whereDeclared (ue));
2011 }
2012 else
2013 {
2014 uentry_setNullState (ue, NS_POSNULL);
2015 }
2016 }
2017 else if (qual_isRelNull (qel))
2018 {
2019 uentry_setNullState (ue, NS_RELNULL);
2020 }
2021 else if (qual_isNotNull (qel))
2022 {
2023 uentry_setNullState (ue, NS_MNOTNULL);
2024 }
2025 else if (qual_isAbstract (qel)
2026 || qual_isConcrete (qel))
2027 {
2028 if (!uentry_isDatatype (ue))
2029 {
2030 llerror
2031 (FLG_SYNTAX,
2032 message ("Qualifier %s used with non-datatype",
2033 qual_unparse (qel)));
2034 }
2035 else
2036 {
2037 ue->info->datatype->abs = ynm_fromBool (qual_isAbstract (qel));
2038 }
2039 }
2040 else if (qual_isMutable (qel))
2041 {
2042 if (!uentry_isDatatype (ue))
2043 {
2044 llerror (FLG_SYNTAX,
2045 message ("Qualifier %s used with non-datatype", qual_unparse (qel)));
2046 }
2047 else
2048 {
2049 if (!ynm_isOn (ue->info->datatype->mut))
2050 {
2051 uentry_checkMutableType (ue);
2052 }
2053
2054 ue->info->datatype->mut = YES;
2055 }
2056 }
2057 else if (qual_isImmutable (qel))
2058 {
2059 if (!uentry_isDatatype (ue))
2060 {
2061 llerror (FLG_SYNTAX, message ("Qualifier %s used with non-datatype",
2062 qual_unparse (qel)));
2063 }
2064 else
2065 {
2066 ue->info->datatype->mut = NO;
2067 }
2068 }
2069 else if (qual_isNullPred (qel))
2070 {
2071 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
2072 {
2073 uentry_makeVarFunction (ue);
2074 }
2075
2076 if (uentry_isFunction (ue))
2077 {
2078 ctype typ = uentry_getType (ue);
2079 ctype rtype = ctype_returnValue (uentry_getType (ue));
2080
2081 if (ctype_isRealBool (rtype))
2082 {
2083 uentryList pl = ctype_argsFunction (typ);
2084
2085 if (uentryList_size (pl) == 1)
2086 {
2087 ue->info->fcn->nullPred = qel;
2088 }
2089 else
2090 {
2091 llerror (FLG_SYNTAX,
2092 message ("Qualifier %s used with function having %d "
2093 "arguments (should have 1)",
2094 qual_unparse (qel),
2095 uentryList_size (pl)));
2096 }
2097 }
2098 else
2099 {
2100 llerror (FLG_SYNTAX,
2101 message ("Qualifier %s used with function returning %s "
2102 "(should return bool)",
2103 qual_unparse (qel),
2104 ctype_unparse (rtype)));
2105 }
2106 }
2107 else
2108 {
2109 llerror (FLG_SYNTAX,
2110 message ("Qualifier %s used with non-function",
2111 qual_unparse (qel)));
2112 }
2113 }
2114 else if (qual_isExitQual (qel))
2115 {
2116 exitkind exk = exitkind_fromQual (qel);
2117
2118 if (uentry_isFunction (ue))
2119 {
2120 if (exitkind_isKnown (ue->info->fcn->exitCode))
2121 {
2122 llerror (FLG_SYNTAX,
2123 message ("Multiple exit qualifiers used on function %q: %s, %s",
2124 uentry_getName (ue),
2125 exitkind_unparse (ue->info->fcn->exitCode),
2126 exitkind_unparse (exk)));
2127 }
2128
2129 ue->info->fcn->exitCode = exk;
2130 }
2131 else
2132 {
2133 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
2134 {
2135 uentry_makeVarFunction (ue);
2136 ue->info->fcn->exitCode = exk;
2137 }
2138 else
2139 {
2140 llerror (FLG_SYNTAX,
2141 message ("Exit qualifier %s used with non-function (type %s)",
2142 qual_unparse (qel),
2143 ctype_unparse (uentry_getType (ue))));
2144 }
2145 }
2146 }
2147 else
2148 {
2149 if (qual_isCQual (qel))
2150 {
2151 ; /* okay */
2152 }
2153 else
2154 {
2155 llbug (message ("unhandled qualifier: %s", qual_unparse (qel)));
2156 }
2157 }
2158}
2159
2160void
2161uentry_reflectQualifiers (uentry ue, qualList q)
2162{
2163 llassert (uentry_isValid (ue));
2164
2165 qualList_elements (q, qel)
2166 {
2167 if (qual_isStatic (qel))
2168 {
2169 uentry_setStatic (ue);
2170 }
2171 else if (qual_isUnused (qel))
2172 {
2173 uentry_setUsed (ue, fileloc_undefined);
2174 }
2175 else if (qual_isExternal (qel))
2176 {
2177 fileloc_free (ue->whereDefined);
2178 ue->whereDefined = fileloc_createExternal ();
2179 }
2180 else if (qual_isSef (qel))
2181 {
2182 if (uentry_isVariable (ue))
2183 {
2184 vkind vk = ue->info->var->kind;
2185
2186 llassert (vk != VKREFPARAM);
2187
2188 if (vk == VKYIELDPARAM)
2189 {
2190 llerror
2191 (FLG_SYNTAX,
2192 message ("Qualifier sef cannot be used with %s: %q",
2193 cstring_makeLiteralTemp (vk == VKYIELDPARAM ? "yield" : "returned"),
2194 uentry_unparse (ue)));
2195 }
2196 else if (vk == VKRETPARAM)
2197 {
2198 ue->info->var->kind = VKSEFRETPARAM;
2199 }
2200 else
2201 {
2202 ue->info->var->kind = VKSEFPARAM;
2203 }
2204 }
2205 else
2206 {
2207 llerror
2208 (FLG_SYNTAX,
2209 message ("Qualifier sef is meaningful only on parameters: %q",
2210 uentry_unparse (ue)));
2211 }
2212 }
2213 else if (qual_isExtern (qel))
2214 {
2215 ue->storageclass = SCEXTERN;
2216 }
2217 else if (qual_isGlobalQual (qel)) /* undef, killed */
2218 {
2219 if (uentry_isVariable (ue))
2220 {
2221 sstate oldstate = ue->info->var->defstate;
2222 sstate defstate = sstate_fromQual (qel);
2223
2224
2225 if ((oldstate == SS_UNDEFGLOB && defstate == SS_KILLED)
2226 || (oldstate == SS_KILLED && defstate == SS_UNDEFGLOB))
2227 {
2228 defstate = SS_UNDEFKILLED;
2229 }
2230 else
2231 {
2232 ; /* any errors? */
2233 }
2234
2235 sRef_setDefState (ue->sref, defstate, fileloc_undefined);
2236 ue->info->var->defstate = defstate;
2237 }
2238 else
2239 {
2240 llerror
2241 (FLG_SYNTAX,
2242 message ("Qualifier %s used on non-variable: %q",
2243 qual_unparse (qel), uentry_unparse (ue)));
2244 }
2245 }
2246 /* start modifications */
2247
2248 else if( qual_isBufQualifier(qel) ) {
2249 ctype ct = ctype_realType(uentry_getType(ue));
2250
2251 if( ctype_isArray(ct) || ctype_isPointer(ct) ) {
2252
2253 if( uentry_hasBufStateInfo(ue) ) {
2254
2255 if( qual_isNullTerminated(qel) ) { /* handle Nullterm */
2256
2257 if (uentry_isAnyParam(ue) || uentry_isReturned (ue)) {
2258 /* If formal func param */
2259 uentry_setNullTerminatedState(ue);
2260 uentry_setLen (ue, 1);
2261 uentry_setSize (ue, 1);
2262
2263 sRef_setNullTerminatedState(uentry_getSref(ue));
2264 sRef_setLen (uentry_getSref(ue), 1);
2265 sRef_setSize (uentry_getSref(ue), 1);
2266 } else {
2267 uentry_setPossiblyNullTerminatedState(ue);
2268
2269 sRef_setPossiblyNullTerminatedState(uentry_getSref(ue));
2270 }
2271
2272 }
2273 /* put other BufState Qualifiers here */
2274 } else {
2275 cstring s = uentry_getName(ue);
2276 llfatalbug(message("INTERNAL Error: we have a NULL BufState \
2277 struct for identifier %s\n", s) );
2278 }
2279 } else if (ctype_isFunction (ct)) { /* We have to handle function */
2280
2281 sRef retSref = uentry_getSref (ue);
2282 ctype retType = sRef_getType (retSref);
2283
2284 if (ctype_isPointer (retType) || ctype_isArray (retType)) {
2285 sRef_setNullTerminatedState (retSref);
2286
2287 } else {
2288
2289 llerror
2290 (FLG_SYNTAX,
2291 message ("Qualifier %s used on non-pointer on \
2292 function return: %q", qual_unparse (qel),
2293 uentry_unparse (ue)));
2294 }
2295 }
2296
2297 else {
2298 llerror
2299 (FLG_SYNTAX,
2300 message ("Qualifier %s used on non-pointer: %q",
2301 qual_unparse (qel), uentry_unparse (ue)));
2302 }
2303 }/* end else if */
2304 else if (qual_isAllocQual (qel)) /* out, partial, reldef, special, etc. */
2305 {
2306 ctype realType = ctype_realType (ue->utype);
2307 sstate defstate = sstate_fromQual (qel);
2308
2309 if (ctype_isFunction (realType))
2310 {
2311 realType = ctype_realType (ctype_returnValue (realType));
2312 }
2313
2314 if (qual_isRelDef (qel))
2315 {
2316 ; /* okay anywhere */
2317 }
2318 else
2319 {
2320 if (!ctype_isAP (realType)
2321 && !ctype_isSU (realType)
2322 && !ctype_isUnknown (realType)
2323 && !ctype_isAbstract (ue->utype))
2324 {
2325 llerror
2326 (FLG_SYNTAX,
2327 message ("Qualifier %s used on non-pointer or struct: %q",
2328 qual_unparse (qel), uentry_unparse (ue)));
2329 }
2330 }
2331
2332 uentry_setDefState (ue, defstate);
2333
2334 if (sRef_isStateSpecial (ue->sref)
2335 && alkind_isImplicit (sRef_getAliasKind (ue->sref)))
2336 {
2337 sRef_setAliasKind (ue->sref, AK_ERROR, fileloc_undefined);
2338 }
2339 }
2340 else if (qual_isYield (qel))
2341 {
2342 if (uentry_isVariable (ue))
2343 {
2344 ue->info->var->kind = VKYIELDPARAM;
2345 }
2346 else
2347 {
2348 llerror
2349 (FLG_SYNTAX,
2350 message ("Qualifier %s used on non-iterator parameter: %q",
2351 qual_unparse (qel), uentry_unparse (ue)));
2352 }
2353 }
2354 else if (qual_isExQual (qel))
2355 {
2356 exkind ek = exkind_fromQual (qel);
2357 ctype ut = uentry_getType (ue);
2358
2359 if (ctype_isFunction (ut))
2360 {
2361 ut = ctype_returnValue (ut);
2362 }
2363
2364 if (!(ctype_isVisiblySharable (ut))
2365 && !(ctype_isArray (ut)) /* can apply to arrays also! */
2366 && !(ctype_isStruct (ctype_realType (ut)))) /* applies to structure fields! */
2367 {
2368 if (!qual_isImplied (qel))
2369 {
2370 llerror
2371 (FLG_SYNTAX,
2372 message ("Qualifier %s used on unsharable storage type %t: %q",
2373 exkind_unparse (ek), ut, uentry_getName (ue)));
2374 }
2375 }
2376 else
2377 {
2378 alkind ak = sRef_getAliasKind (ue->sref);
2379
2380 sRef_setExKind (ue->sref, ek, uentry_whereDeclared (ue));
2381
2382 if (alkind_isUnknown (ak) || alkind_isImplicit (ak) || alkind_isStatic (ak))
2383 {
2384 if (!alkind_isTemp (ak))
2385 {
2386 uentry_setAliasKind (ue, AK_IMPDEPENDENT);
2387 }
2388 }
2389 else if (alkind_isDependent (ak) || alkind_isTemp (ak)
2390 || alkind_isOwned (ak))
2391 {
2392 ; /* okay */
2393 }
2394 else
2395 {
2396 llerror
2397 (FLG_SYNTAX,
2398 message ("Exposure qualifier %s used on %s storage (should "
2399 "be dependent): %q",
2400 qual_unparse (qel),
2401 alkind_unparse (ak),
2402 uentry_unparse (ue)));
2403 }
2404 }
2405 }
2406 else if (qual_isGlobCheck (qel))
2407 {
2408 if (uentry_isVariable (ue))
2409 {
2410 chkind ch = chkind_fromQual (qel);
2411
2412 if (ue->info->var->checked != CH_UNKNOWN)
2413 {
2414 if (ch == ue->info->var->checked)
2415 {
2416 llerror (FLG_SYNTAX,
2417 message ("Redundant %s qualifier on %q",
2418 qual_unparse (qel),
2419 uentry_getName (ue)));
2420 }
2421 else
2422 {
2423 llerror (FLG_SYNTAX,
2424 message
2425 ("Contradictory %s and %s qualifiers on %q",
2426 qual_unparse (qel),
2427 checkedName (ue->info->var->checked),
2428 uentry_getName (ue)));
2429 }
2430 }
2431
2432 ue->info->var->checked = ch;
2433 }
2434 else
2435 {
2436 llerror
2437 (FLG_SYNTAX,
2438 message ("Qualifier %s used with non-variable",
2439 qual_unparse (qel)));
2440 }
2441 }
2442 else if (qual_isReturned (qel))
2443 {
2444 if (uentry_isVariable (ue))
2445 {
2446 ue->info->var->kind = VKRETPARAM;
2447 }
2448 else
2449 {
2450 llerror (FLG_SYNTAX, message ("Qualifier %s used with non-variable",
2451 qual_unparse (qel)));
2452 }
2453 }
2454 else
2455 {
2456 uentry_reflectOtherQualifier (ue, qel);
2457 }
2458
2459 sRef_storeState (ue->sref);
2460 } end_qualList_elements;
2461
2462 qualList_clear (q);
2463}
2464
2465bool
2466uentry_isOnly (uentry ue)
2467{
2468 return (!uentry_isUndefined (ue)
2469 && uentry_isVariable (ue)
2470 && alkind_isOnly (sRef_getOrigAliasKind (ue->sref)));
2471}
2472
2473static void
2474uentry_setAliasKind (/*@notnull@*/ uentry ue, alkind ak)
2475{
2476 sRef_setAliasKind (ue->sref, ak, uentry_whereDeclared (ue));
2477 sRef_setOrigAliasKind (ue->sref, ak);
2478}
2479
2480static void
2481uentry_setNullState (/*@notnull@*/ uentry ue, nstate ns)
2482{
2483 if (uentry_isVariable (ue))
2484 {
2485 ue->info->var->nullstate = ns;
2486 }
2487
2488 sRef_setNullState (ue->sref, ns, uentry_whereDeclared (ue));
2489}
2490
2491bool
2492uentry_isUnique (uentry ue)
2493{
2494 return (!uentry_isUndefined (ue)
2495 && uentry_isVariable (ue)
2496 && alkind_isUnique (sRef_getOrigAliasKind (ue->sref)));
2497}
2498
2499bool
2500uentry_isFileStatic (uentry ue)
2501{
2502 return (uentry_isStatic (ue)
2503 && (!uentry_isVariable (ue)
2504 || sRef_isFileStatic (uentry_getSref (ue))));
2505}
2506
2507bool
2508uentry_isExported (uentry ue)
2509{
2510 if (uentry_isValid (ue))
2511 {
2512 if (uentry_isVariable (ue))
2513 {
2514 return (sRef_isRealGlobal (uentry_getSref (ue)));
2515 }
2516 else
2517 {
2518 return !uentry_isStatic (ue);
2519 }
2520 }
2521
2522 return FALSE;
2523}
2524
2525bool
2526uentry_isNonLocal (uentry ue)
2527{
2528 return (uentry_isValid (ue) && uentry_isVariable (ue)
2529 && (sRef_isGlobal (ue->sref) || uentry_isStatic (ue)));
2530}
2531
2532bool
2533uentry_isGlobal (uentry ue)
2534{
2535 return (uentry_isValid (ue) && uentry_isVariable (ue) &&
2536 sRef_isGlobal (ue->sref));
2537}
2538
2539bool
2540uentry_isPrintfLike (uentry ue)
2541{
2542 return (uentry_isFunction (ue)
2543 && (ue->info->fcn->specialCode == SPC_PRINTFLIKE));
2544}
2545
2546bool
2547uentry_isScanfLike (uentry ue)
2548{
2549 return (uentry_isFunction (ue)
2550 && (ue->info->fcn->specialCode == SPC_SCANFLIKE));
2551}
2552
2553bool
2554uentry_isMessageLike (uentry ue)
2555{
2556 return (uentry_isFunction (ue)
2557 && (ue->info->fcn->specialCode == SPC_MESSAGELIKE));
2558}
2559
2560static void checkSpecialFunction (/*@notnull@*/ uentry ue)
2561{
2562 uentryList args = uentry_getParams (ue);
2563
2564 if (!uentryList_isMissingParams (args))
2565 {
2566 uentry last = uentry_undefined;
2567
2568 uentryList_elements (args, current)
2569 {
2570 if (uentry_isElipsisMarker (current))
2571 {
2572 if (uentry_isUndefined (last))
2573 {
2574 voptgenerror
2575 (FLG_SYNTAX,
2576 message ("Function %q is marked %s, but has no format "
2577 "string argument before elipsis",
2578 uentry_getName (ue),
2579 specCode_unparse (ue->info->fcn->specialCode)),
2580 uentry_whereLast (ue));
2581 ue->info->fcn->specialCode = SPC_NONE;
2582 }
2583 else
2584 {
2585 ctype rt = ctype_realType (uentry_getType (last));
2586
2587 if (!ctype_match (rt, ctype_string))
2588 {
2589 bool okay = FALSE;
2590
2591 /* wchar_t * is okay too */
2592 if (ctype_isAP (rt))
2593 {
2594 ctype base = ctype_baseArrayPtr (rt);
2595
2596 if (ctype_isArbitraryIntegral (base))
2597 {
2598 okay = TRUE;
2599 }
2600 }
2601
2602 if (!okay)
2603 {
2604 voptgenerror
2605 (FLG_SYNTAX,
2606 message ("Function %q is marked %s, but the argument "
2607 "before the elipsis has type %s (should be char *)",
2608 uentry_getName (ue),
2609 specCode_unparse (ue->info->fcn->specialCode),
2610 ctype_unparse (uentry_getType (last))),
2611 uentry_whereLast (ue));
2612
2613 ue->info->fcn->specialCode = SPC_NONE;
2614 }
2615 }
2616 }
2617 return;
2618 }
2619 last = current;
2620 } end_uentryList_elements ;
2621
2622 voptgenerror
2623 (FLG_SYNTAX,
2624 message ("Function %q is marked %s, but has no elipsis parameter",
2625 uentry_getName (ue),
2626 specCode_unparse (ue->info->fcn->specialCode)),
2627 uentry_whereLast (ue));
2628
2629 ue->info->fcn->specialCode = SPC_NONE;
2630 }
2631}
2632
2633void
2634uentry_setPrintfLike (uentry ue)
2635{
2636 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
2637 {
2638 uentry_makeVarFunction (ue);
2639 }
2640
2641 llassertfatal (uentry_isFunction (ue));
2642 ue->info->fcn->specialCode = SPC_PRINTFLIKE;
2643 checkSpecialFunction (ue);
2644}
2645
2646void
2647uentry_setScanfLike (uentry ue)
2648{
2649 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
2650 {
2651 uentry_makeVarFunction (ue);
2652 }
2653
2654 llassertfatal (uentry_isFunction (ue));
2655 ue->info->fcn->specialCode = SPC_SCANFLIKE;
2656 checkSpecialFunction (ue);
2657}
2658
2659void
2660uentry_setMessageLike (uentry ue)
2661{
2662 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
2663 {
2664 uentry_makeVarFunction (ue);
2665 }
2666
2667 llassertfatal (uentry_isFunction (ue));
2668 ue->info->fcn->specialCode = SPC_MESSAGELIKE;
2669 checkSpecialFunction (ue);
2670}
2671
2672bool
2673uentry_isSpecialFunction (uentry ue)
2674{
2675 return (uentry_isFunction (ue)
2676 && (ue->info->fcn->specialCode != SPC_NONE));
2677}
2678
2679/*@notnull@*/ uentry uentry_makeParam (idDecl t, int i)
2680{
2681 ctype ct = idDecl_getCtype (t);
2682 ctype base = ct;
2683 sRef pref = sRef_makeParam (i, ct);
2684 uentry ue = uentry_makeVariableSrefParam (idDecl_observeId (t), ct, pref);
2685
2686 uentry_reflectQualifiers (ue, idDecl_getQuals (t));
2687 uentry_implicitParamAnnots (ue);
2688
2689 /* Parameter type [][] or [x][] is invalid */
2690
2691 while (ctype_isFixedArray (base)) {
2692 base = ctype_baseArrayPtr (base);
2693 }
2694
2695 if (ctype_isIncompleteArray (base)) {
2696 base = ctype_baseArrayPtr (base);
2697
2698 if (ctype_isArray (base)) {
2699 if (!uentry_hasName (ue)) {
2700 (void) optgenerror (FLG_INCOMPLETETYPE,
2701 message ("Unnamed function parameter %d is incomplete type (inner array must have bounds): %s",
2702 i + 1,
2703 ctype_unparse (ct)),
2704 uentry_whereLast (ue));
2705 } else {
2706 (void) optgenerror (FLG_INCOMPLETETYPE,
2707 message ("Function parameter %q is incomplete type (inner array must have bounds): %s",
2708 uentry_getName (ue),
2709 ctype_unparse (ct)),
2710 uentry_whereLast (ue));
2711 }
2712 }
2713 }
2714
2715 return ue;
2716}
2717
2718/*@only@*/ /*@notnull@*/ uentry uentry_makeIdVariable (idDecl t)
2719{
2720 ctype ct = idDecl_getCtype (t);
2721
2722 if (ctype_isFunction (ct))
2723 {
2724 return (uentry_makeIdFunction (t));
2725 }
2726 else
2727 {
2728 fileloc loc = setLocation ();
2729 uentry ue = uentry_makeVariable (idDecl_observeId (t), ct, loc, FALSE);
2730
2731 uentry_reflectQualifiers (ue, idDecl_getQuals (t));
2732
2733 if (!uentry_isExtern (ue))
2734 {
2735 uentry_setDefined (ue, loc);
2736 }
2737
2738 return ue;
2739 }
2740}
2741
2742# ifndef NOLCL
2743/*@notnull@*/ uentry uentry_makeVariableParam (cstring n, ctype t)
2744{
2745 return (uentry_makeVariableParamAux (n, t, sRef_makeType (t), SS_DEFINED));
2746}
2747# endif
2748
2749/*
2750** constants
2751*/
2752
2753/*@only@*/ /*@notnull@*/
2754uentry uentry_makeConstantAux (cstring n, ctype t,
2755 /*@keep@*/ fileloc f, bool priv,
2756 /*@only@*/ multiVal m)
2757{
2758 uentry e = uentry_alloc ();
2759
2760 e->ukind = KCONST;
2761 e->uname = cstring_copy (n);
2762 e->utype = t;
2763 e->storageclass = SCNONE;
2764
2765 e->sref = sRef_makeConst (t);
2766
2767 e->lset = FALSE;
2768 e->used = FALSE;
2769
2770 e->uses = filelocList_new ();
2771 e->isPrivate = priv;
2772 e->hasNameError = FALSE;
2773
2774 e->info = (uinfo) dmalloc (sizeof (*e->info));
2775 e->info->uconst = (ucinfo) dmalloc (sizeof (*e->info->uconst));
2776 e->info->uconst->val = m;
2777 e->info->uconst->access = typeIdSet_undefined;
2778
2779 uentry_setSpecDef (e, f);
2780
2781 if (multiVal_isInt (m) && (multiVal_forceInt (m) == 0))
2782 {
2783 sRef_setDefNull (e->sref, uentry_whereDeclared (e));
2784 }
2785
2786 return (e);
2787}
2788
2789/*@notnull@*/ uentry uentry_makeConstant (cstring n, ctype t, fileloc f)
2790{
2791 return (uentry_makeConstantAux (n, t, f, FALSE, multiVal_unknown ()));
2792}
2793
2794/*@notnull@*/ uentry uentry_makeIdConstant (idDecl t)
2795{
2796 uentry ue = uentry_makeConstant (idDecl_observeId (t),
2797 idDecl_getCtype (t),
2798 fileloc_undefined);
2799
2800 llassert (fileloc_isUndefined (ue->whereDeclared));
2801 ue->whereDeclared = setLocation ();
2802
2803 uentry_reflectQualifiers (ue, idDecl_getQuals (t));
2804
2805 return ue;
2806}
2807
2808/*
2809** variables
2810*/
2811
2812void uentry_setDefState (uentry ue, sstate defstate)
2813{
2814 if (uentry_isValid (ue))
2815 {
2816 sRef_setDefState (ue->sref, defstate, fileloc_undefined);
2817
2818 if (uentry_isVariable (ue))
2819 {
2820 ue->info->var->defstate = defstate; /* evs 2000-05-17: fixed bug, was SS_DEFINED! */
2821 }
2822 }
2823}
2824
2825bool uentry_isCheckedUnknown (uentry ue)
2826{
2827 return (uentry_isVar (ue)
2828 && (ue->info->var->checked == CH_UNKNOWN));
2829}
2830
2831bool uentry_isCheckMod (uentry ue)
2832{
2833 return (uentry_isVar (ue)
2834 && (ue->info->var->checked == CH_CHECKMOD));
2835}
2836
2837bool uentry_isUnchecked (uentry ue)
2838{
2839 return (uentry_isVar (ue)
2840 && (ue->info->var->checked == CH_UNCHECKED));
2841}
2842
2843bool uentry_isChecked (uentry ue)
2844{
2845 return (uentry_isVar (ue)
2846 && (ue->info->var->checked == CH_CHECKED));
2847}
2848
2849bool uentry_isCheckedModify (uentry ue)
2850{
2851 return (uentry_isVar (ue)
2852 && (ue->info->var->checked == CH_CHECKED
2853 || ue->info->var->checked == CH_CHECKMOD
2854 || ue->info->var->checked == CH_CHECKEDSTRICT));
2855}
2856
2857bool uentry_isCheckedStrict (uentry ue)
2858{
2859 return (uentry_isVar (ue)
2860 && (ue->info->var->checked == CH_CHECKEDSTRICT));
2861}
2862
2863void uentry_setUnchecked (uentry ue)
2864{
2865 llassert (uentry_isVar (ue));
2866
2867 ue->info->var->checked = CH_UNCHECKED;
2868}
2869
2870void uentry_setChecked (uentry ue)
2871{
2872 llassert (uentry_isVar (ue));
2873
2874 ue->info->var->checked = CH_CHECKED;
2875}
2876
2877void uentry_setCheckMod (uentry ue)
2878{
2879 llassert (uentry_isVar (ue));
2880
2881 ue->info->var->checked = CH_CHECKMOD;
2882}
2883
2884void uentry_setCheckedStrict (uentry ue)
2885{
2886 llassert (uentry_isVar (ue));
2887
2888 ue->info->var->checked = CH_CHECKEDSTRICT;
2889}
2890
2891static /*@only@*/ /*@notnull@*/
2892 uentry uentry_makeVariableAux (cstring n, ctype t,
2893 fileloc f,
2894 /*@exposed@*/ sRef s,
2895 bool priv, vkind kind)
2896{
2897 uentry e = uentry_alloc ();
2898 ctype rt = t;
2899
2900 DPRINTF (("Make variable: %s %s %s", n, ctype_unparse (t), sRef_unparse (s)));
2901
2902 e->ukind = KVAR;
2903 e->uname = cstring_copy (n);
2904 e->utype = t;
2905
2906 e->storageclass = SCNONE;
2907
2908 e->sref = s;
2909
2910 e->used = FALSE;
2911 e->lset = FALSE;
2912
2913 e->uses = filelocList_new ();
2914 e->isPrivate = priv;
2915 e->hasNameError = FALSE;
2916
2917 e->info = (uinfo) dmalloc (sizeof (*e->info));
2918 e->info->var = (uvinfo) dmalloc (sizeof (*e->info->var));
2919 e->info->var->kind = kind;
2920
2921 e->info->var->checked = CH_UNKNOWN;
2922
2923 uentry_setSpecDef (e, f);
2924
2925 if (ctype_isFunction (rt))
2926 {
2927 rt = ctype_returnValue (rt);
2928 }
2929
2930 if (ctype_isUA (rt))
2931 {
2932 sRef_setStateFromType (e->sref, rt);
2933 }
2934
2935 e->info->var->defstate = sRef_getDefState (e->sref);
2936 e->info->var->nullstate = sRef_getNullState (e->sref);
2937
2938/* start modifications */
2939/* This function sets the uentry for a pointer or array variable declaration,
2940 it allocates memory and sets the fields. We check if the type of the variable
2941 is a pointer or array and allocate a `bbufinfo' struct accordingly */
2942
2943 if( ctype_isArray (t) || ctype_isPointer(t)) {
2944 /*@i222@*/e->info->var->bufinfo = dmalloc( sizeof(*e->info->var->bufinfo) );
2945 e->info->var->bufinfo->bufstate = BB_NOTNULLTERMINATED;
2946 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
2947 } else {
2948 e->info->var->bufinfo = NULL;
2949 }/* end else */
2950/* end modification */
2951
2952 return (e);
2953}
2954
2955bool
2956uentry_isYield (uentry ue)
2957{
2958 return (uentry_isVariable (ue)
2959 && (ue->info->var->kind == VKYIELDPARAM
2960 || ue->info->var->kind == VKREFYIELDPARAM));
2961}
2962
2963static bool
2964uentry_isRefsField (uentry ue)
2965{
2966 return (uentry_isVariable (ue) && sRef_isRefsField (ue->sref));
2967}
2968
2969/*@only@*/ /*@notnull@*/
2970uentry uentry_makeVariable (cstring n, ctype t, fileloc f, bool isPriv)
2971{
2972 return (uentry_makeVariableAux (n, t, f, sRef_makeType (t), isPriv,
2973 fileloc_isSpec (f) ? VKSPEC : VKNORMAL));
2974}
2975
2976/*
2977** functions
2978*/
2979
2980void uentry_makeVarFunction (uentry ue)
2981{
2982 alkind ak;
2983 exkind ek;
2984 uvinfo oldInfo;
2985 fileloc loc;
2986
2987 llassert (uentry_isValid (ue));
2988 llassert (!sRef_modInFunction ());
2989
2990 ak = sRef_getOrigAliasKind (ue->sref);
2991 ek = sRef_getOrigExKind (ue->sref);
2992
2993 oldInfo = ue->info->var;
2994
2995 llassert (ctype_isUnknown (ue->utype) || ctype_isFunction (ue->utype));
2996
2997 /*
2998 ** expanded macro is marked used (until I write a pre-processor)
2999 */
3000
3001 ue->used |= (oldInfo->kind == VKEXPMACRO);
3002
3003 ue->ukind = KFCN;
3004 ue->info->fcn = (ufinfo) dmalloc (sizeof (*ue->info->fcn));
3005 ue->info->fcn->exitCode = XK_UNKNOWN;
3006 ue->info->fcn->nullPred = QU_UNKNOWN;
3007 ue->info->fcn->specialCode = SPC_NONE;
3008 ue->info->fcn->access = typeIdSet_undefined;
3009 ue->info->fcn->hasGlobs = FALSE;
3010 ue->info->fcn->globs = globSet_undefined;
3011 ue->info->fcn->hasMods = FALSE;
3012 ue->info->fcn->mods = sRefSet_undefined;
3013 ue->info->fcn->specclauses = NULL;
3014 ue->info->fcn->defparams = uentryList_undefined;
3015
3016 /*drl*/
3017 ue->info->fcn->preconditions = constraintList_undefined;
3018 /*end */
3019
3020 /*drl 12/28/2000*/
3021 ue->info->fcn->postconditions = constraintList_undefined;
3022 /*end */
3023
3024
3025 if (ctype_isFunction (ue->utype))
3026 {
3027 ue->sref = sRef_makeType (ctype_returnValue (ue->utype));
3028 }
3029 else
3030 {
3031 ue->sref = sRef_makeType (ctype_unknown);
3032 }
3033
3034 if (sRef_isRefCounted (ue->sref))
3035 {
3036 ak = AK_NEWREF;
3037 }
3038 else
3039 {
3040 if (alkind_isUnknown (ak))
3041 {
3042 if (exkind_isKnown (ek))
3043 {
3044 ak = AK_IMPDEPENDENT;
3045 }
3046 else
3047 {
3048 if (context_getFlag (FLG_RETIMPONLY))
3049 {
3050 if (ctype_isFunction (ue->utype)
3051 && ctype_isVisiblySharable
3052 (ctype_realType (ctype_returnValue (ue->utype))))
3053 {
3054 if (uentryList_hasReturned (uentry_getParams (ue)))
3055 {
3056 ;
3057 }
3058 else
3059 {
3060 ak = AK_IMPONLY;
3061 }
3062 }
3063 }
3064 }
3065 }
3066 }
3067
3068 loc = ue->whereDeclared;
3069
3070 sRef_setAliasKind (ue->sref, ak, loc);
3071 sRef_setNullState (ue->sref, oldInfo->nullstate, loc);
3072 sRef_setDefState (ue->sref, oldInfo->defstate, loc);
3073 sRef_setExKind (ue->sref, ek, loc);
3074
3075 if (oldInfo->kind == VKEXPMACRO)
3076 {
3077 fileloc_free (loc);
3078 ue->whereDeclared = fileloc_undefined;
3079 }
3080 else
3081 {
3082 fileloc_free (ue->whereDefined);
3083 ue->whereDefined = fileloc_undefined;
3084 }
3085
3086 uvinfo_free (oldInfo);
3087}
3088
3089void
3090uentry_setGlobals (uentry ue, /*@owned@*/ globSet globs)
3091{
3092 llassert (uentry_isValid (ue));
3093
3094 if (uentry_isIter (ue))
3095 {
3096 llassert (globSet_isUndefined (ue->info->iter->globs));
3097 ue->info->iter->globs = globs;
3098 }
3099 else
3100 {
3101 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
3102 {
3103 uentry_makeVarFunction (ue);
3104 }
3105
3106 llassert (uentry_isFunction (ue));
3107 llassert (!ue->info->fcn->hasGlobs
3108 && globSet_isUndefined (ue->info->fcn->globs));
3109
3110 ue->info->fcn->hasGlobs = TRUE;
3111 /*@-mustfree@*/ ue->info->fcn->globs = globs;
3112 /*@=mustfree@*/
3113 }
3114
3115 if (globSet_hasStatic (globs))
3116 {
3117 context_recordFileGlobals (globs);
3118 }
3119
3120 if (context_getFlag (FLG_GLOBALSIMPMODIFIESNOTHING))
3121 {
3122 ue->info->fcn->hasMods = TRUE;
3123 }
3124}
3125
3126void uentry_addAccessType (uentry ue, typeId tid)
3127{
3128 if (uentry_isFunction (ue))
3129 {
3130 ue->info->fcn->access = typeIdSet_insert (ue->info->fcn->access, tid);
3131 }
3132 else if (uentry_isEitherConstant (ue))
3133 {
3134 ue->info->uconst->access = typeIdSet_insert (ue->info->uconst->access, tid);
3135 }
3136 else if (uentry_isIter (ue))
3137 {
3138 ue->info->iter->access = typeIdSet_insert (ue->info->iter->access, tid);
3139 }
3140 else if (uentry_isEndIter (ue))
3141 {
3142 ue->info->enditer->access = typeIdSet_insert (ue->info->enditer->access, tid);
3143 }
3144 else
3145 {
3146 llbug (message ("no access for: %q", uentry_unparse (ue)));
3147 }
3148}
3149
3150/*@only@*/ /*@notnull@*/ uentry
3151 uentry_makeFunction (cstring n, ctype t,
3152 typeId access,
3153 /*@only@*/ globSet globs, /*@only@*/ sRefSet mods,
3154 fileloc f)
3155{
3156 return (uentry_makeFunctionAux (n, t,
3157 ((typeId_isInvalid (access)) ? typeIdSet_emptySet ()
3158 : typeIdSet_single (access)),
3159 globs, mods, f,
3160 FALSE, FALSE));
3161}
3162
3163# ifndef NOLCL
3164/*@notnull@*/ uentry
3165 uentry_makePrivFunction2 (cstring n, ctype t,
3166 typeIdSet access,
3167 globSet globs, sRefSet mods,
3168 fileloc f)
3169{
3170 return (uentry_makeFunctionAux (n, t, access, globs, mods, f, TRUE, FALSE));
3171}
3172
3173
3174/*@notnull@*/ uentry
3175 uentry_makeSpecFunction (cstring n, ctype t,
3176 typeIdSet access,
3177 /*@only@*/ globSet globs,
3178 /*@only@*/ sRefSet mods,
3179 fileloc f)
3180{
3181 uentry ue = uentry_makeFunctionAux (n, t, access,
3182 globs, mods, f,
3183 FALSE, FALSE);
3184
3185 uentry_setHasGlobs (ue);
3186 uentry_setHasMods (ue);
3187
3188 reflectImplicitFunctionQualifiers (ue, TRUE);
3189 return (ue);
3190}
3191# endif
3192
3193uentry uentry_makeExpandedMacro (cstring s, fileloc f)
3194{
3195 uentry ue = uentry_makeVariableAux (s, ctype_unknown, fileloc_undefined,
3196 sRef_undefined, FALSE, VKEXPMACRO);
3197
3198 uentry_setDefined (ue, f);
3199 return ue;
3200}
3201
3202/*@notnull@*/ /*@notnull@*/ uentry
3203 uentry_makeForwardFunction (cstring n, typeId access, fileloc f)
3204{
3205 uentry ue = uentry_makeFunctionAux (n, ctype_unknown,
3206 typeIdSet_singleOpt (access),
3207 globSet_undefined, sRefSet_undefined,
3208 fileloc_undefined,
3209 FALSE, TRUE);
3210
3211 ue->whereDeclared = fileloc_update (ue->whereDeclared, f);
3212 return ue;
3213}
3214
3215bool uentry_isForward (uentry e)
3216{
3217 if (uentry_isValid (e))
3218 {
3219 ctype ct = uentry_getType (e);
3220
3221 return (ctype_isUnknown (ct)
3222 || (ctype_isFunction (ct)
3223 && ctype_isUnknown (ctype_returnValue (ct))));
3224 }
3225
3226 return FALSE;
3227}
3228
3229# ifndef NOLCL
3230/*@notnull@*/ uentry
3231uentry_makeTypeListFunction (cstring n, typeIdSet access, fileloc f)
3232{
3233 return (uentry_makeFunctionAux (n, ctype_unknown, access,
3234 globSet_new (),
3235 sRefSet_new (), f,
3236 FALSE, TRUE));
3237}
3238
3239/*@notnull@*/ uentry
3240uentry_makeUnspecFunction (cstring n, ctype t,
3241 typeIdSet access,
3242 fileloc f)
3243{
3244 uentry ue = uentry_makeFunctionAux (n, t, access, globSet_new (),
3245 sRefSet_new (), f, FALSE, TRUE);
3246
3247 reflectImplicitFunctionQualifiers (ue, TRUE);
3248 return ue;
3249}
3250# endif
3251
3252/*
3253** datatypes
3254*/
3255
3256/* is exported for use by usymtab_interface */
3257
3258/*@notnull@*/ uentry
3259 uentry_makeDatatypeAux (cstring n, ctype t, ynm mut, ynm abs,
3260 fileloc f, bool priv)
3261{
3262 uentry e = uentry_alloc ();
3263
3264 DPRINTF (("Make datatype: %s / %s",
3265 n, ctype_unparse (t)));
3266
3267 /* e->shallowCopy = FALSE; */
3268 e->ukind = KDATATYPE;
3269 e->uname = cstring_copy (n);
3270 e->utype = t;
3271 e->storageclass = SCNONE;
3272 e->sref = sRef_makeUnknown ();
3273
3274 if (ctype_isUA (t))
3275 {
3276 sRef_setStateFromType (e->sref, t);
3277 }
3278
3279 uentry_setSpecDef (e, f);
3280
3281 e->uses = filelocList_new ();
3282 e->isPrivate = priv;
3283 e->hasNameError = FALSE;
3284
3285 e->used = FALSE;
3286 e->lset = FALSE;
3287
3288 e->info = (uinfo) dmalloc (sizeof (*e->info));
3289 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
3290 e->info->datatype->abs = abs;
3291 e->info->datatype->mut = mut;
3292 e->info->datatype->type = ctype_undefined;
3293
3294 if (uentry_isDeclared (e))
3295 {
3296 uentry_setDefined (e, f);
3297 }
3298
3299 if (ynm_isOn (abs) && !(uentry_isCodeDefined (e)))
3300 {
3301 sRef_setNullState (e->sref, NS_ABSNULL, uentry_whereDeclared (e));
3302 }
3303
3304 return (e);
3305}
3306
3307/*@notnull@*/ uentry
3308 uentry_makeDatatype (cstring n, ctype t, ynm mut, ynm abs,
3309 fileloc f)
3310{
3311 return (uentry_makeDatatypeAux (n, t, mut, abs, f, FALSE));
3312}
3313
3314/*@notnull@*/ uentry uentry_makeBoolDatatype (ynm abs)
3315{
3316 uentry ret = uentry_makeDatatypeAux (context_getBoolName (),
3317 ctype_bool, NO, abs,
3318 fileloc_getBuiltin (),
3319 FALSE);
3320
3321 ret->info->datatype->type = ctype_bool;
3322 return ret;
3323}
3324
3325/*
3326** iters
3327*/
3328
3329static /*@only@*/ /*@notnull@*/ uentry
3330 uentry_makeIterAux (cstring n, typeIdSet access, ctype ct,
3331 /*@only@*/ fileloc f)
3332{
3333 uentry e = uentry_alloc ();
3334
3335 e->ukind = KITER;
3336 e->uname = cstring_copy (n);
3337 e->utype = ct;
3338 e->sref = sRef_makeUnknown ();
3339 e->storageclass = SCNONE;
3340 e->used = FALSE;
3341 e->lset = FALSE;
3342
3343 uentry_setSpecDef (e, f);
3344
3345 e->uses = filelocList_new ();
3346 e->isPrivate = FALSE;
3347 e->hasNameError = FALSE;
3348
3349 e->info = (uinfo) dmalloc (sizeof (*e->info));
3350 e->info->iter = (uiinfo) dmalloc (sizeof (*e->info->iter));
3351 e->info->iter->access = access;
3352 e->info->iter->mods = sRefSet_undefined;
3353 e->info->iter->globs = globSet_undefined;
3354
3355 uentry_checkIterArgs (e);
3356 return (e);
3357}
3358
3359/*@notnull@*/ uentry uentry_makeIter (cstring n, ctype ct, fileloc f)
3360{
3361 return (uentry_makeIterAux (n, context_fileAccessTypes (), ct, f));
3362}
3363
3364static /*@notnull@*/ uentry
3365uentry_makeEndIterAux (cstring n, typeIdSet access, /*@only@*/ fileloc f)
3366{
3367 uentry e = uentry_alloc ();
3368
3369 /* e->shallowCopy = FALSE; */
3370 e->ukind = KENDITER;
3371 e->storageclass = SCNONE;
3372 e->uname = message ("end_%s", n);
3373 e->utype = ctype_unknown;
3374 e->sref = sRef_makeUnknown ();
3375
3376 uentry_setSpecDef (e, f);
3377
3378 e->used = FALSE;
3379 e->lset = FALSE;
3380
3381 e->uses = filelocList_new ();
3382 e->isPrivate = FALSE;
3383 e->hasNameError = FALSE;
3384
3385 e->info = (uinfo) dmalloc (sizeof (*e->info));
3386 e->info->enditer = (ueinfo) dmalloc (sizeof (*e->info->enditer));
3387
3388 e->info->enditer->access = access;
3389
3390 return (e);
3391}
3392
3393/*@notnull@*/ /*@only@*/ uentry uentry_makeEndIter (cstring n, fileloc f)
3394{
3395 return (uentry_makeEndIterAux (n, context_fileAccessTypes (), f));
3396}
3397
3398/*
3399** tags
3400*/
3401
3402static /*@only@*/ /*@notnull@*/ uentry
3403 uentry_makeTagAux (cstring n, ctype t,
3404 /*@only@*/ fileloc fl,
3405 bool priv, ekind kind)
3406{
3407 uentry e = uentry_alloc ();
3408
3409 if (kind != KSTRUCTTAG && kind != KUNIONTAG && kind != KENUMTAG)
3410 {
3411 llbuglit ("uentry_makeTagAux: not a tag type");
3412 }
3413
3414 e->ukind = kind;
3415 /* e->shallowCopy = FALSE; */
3416 e->uname = cstring_copy (n);
3417
3418 e->utype = t;
3419 e->sref = sRef_makeUnknown ();
3420 e->storageclass = SCNONE;
3421
3422 uentry_setSpecDef (e, fl);
3423
3424 e->used = FALSE;
3425 e->lset = FALSE;
3426
3427 e->uses = filelocList_new ();
3428 e->isPrivate = priv;
3429 e->hasNameError = FALSE;
3430
3431 e->info = (uinfo) dmalloc (sizeof (*e->info));
3432 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
3433 e->info->datatype->abs = NO;
3434 e->info->datatype->mut = (kind == KENUMTAG) ? NO : MAYBE;
3435 e->info->datatype->type = t;
3436
3437 if (uentry_isDeclared (e))
3438 {
3439 uentry_setDefined (e, fl);
3440 }
3441
3442 return (e);
3443}
3444
3445uentry uentry_makeStructTagLoc (cstring n, ctype t)
3446{
3447 cstring sname = makeStruct (n);
3448 uentry ret = uentry_makeTagAux (sname, t, setLocation (), FALSE, KSTRUCTTAG);
3449
3450 cstring_free (sname);
3451 return (ret);
3452}
3453
3454/*@only@*/ uentry
3455uentry_makeStructTag (cstring n, ctype t, fileloc loc)
3456{
3457 cstring sname = makeStruct (n);
3458 uentry ret = uentry_makeTagAux (sname, t, loc, FALSE, KSTRUCTTAG);
3459
3460 cstring_free (sname);
3461 return ret;
3462}
3463
3464/*@only@*/ uentry
3465uentry_makeUnionTag (cstring n, ctype t, fileloc loc)
3466{
3467 cstring uname = makeUnion (n);
3468 uentry ret = uentry_makeTagAux (uname, t, loc, FALSE, KUNIONTAG);
3469
3470 cstring_free (uname);
3471 return (ret);
3472}
3473
3474# ifndef NOLCL
3475uentry
3476uentry_makeEnumTag (cstring n, ctype t, fileloc loc)
3477{
3478 cstring ename = makeEnum (n);
3479 uentry ret = uentry_makeTagAux (ename, t, loc, FALSE, KENUMTAG);
3480
3481 cstring_free (ename);
3482 return ret;
3483}
3484# endif
3485
3486uentry
3487uentry_makeUnionTagLoc (cstring n, ctype t)
3488{
3489 cstring uname = makeUnion (n);
3490 uentry ret = uentry_makeTagAux (uname, t, setLocation (), FALSE, KUNIONTAG);
3491
3492 cstring_free (uname);
3493 return ret;
3494}
3495
3496uentry
3497uentry_makeEnumTagLoc (cstring n, ctype t)
3498{
3499 cstring ename = makeEnum (n);
3500 uentry ret = uentry_makeTagAux (ename, t, setLocation (), FALSE, KENUMTAG);
3501
3502 cstring_free (ename);
3503 return ret;
3504}
3505
3506bool
3507uentry_isStructTag (uentry ue)
3508{
3509 return (uentry_isValid (ue) && ue->ukind == KSTRUCTTAG);
3510}
3511
3512bool
3513uentry_isUnionTag (uentry ue)
3514{
3515 return (uentry_isValid (ue) && ue->ukind == KUNIONTAG);
3516}
3517
3518bool
3519uentry_isEnumTag (uentry ue)
3520{
3521 return (uentry_isValid (ue) && ue->ukind == KENUMTAG);
3522}
3523
3524bool
3525uentry_isAnyTag (uentry ue)
3526{
3527 return (uentry_isStructTag (ue)
3528 || uentry_isUnionTag (ue)
3529 || uentry_isEnumTag (ue));
3530}
3531
3532static /*@unchecked@*/ /*@only@*/ uentry emarker = NULL;
3533
3534extern void uentry_destroyMod (void)
3535 /*@globals killed emarker@*/ /*@modifies emarker@*/
3536{
3537 static bool wasDestroyed = FALSE;
3538
3539 llassert (!wasDestroyed);
3540
3541 if (emarker != NULL)
3542 {
3543 uentry_reallyFree (emarker);
3544 }
3545
3546 wasDestroyed = TRUE;
3547}
3548
3549uentry
3550uentry_makeElipsisMarker (void)
3551{
3552 if (emarker == NULL)
3553 {
3554 emarker = uentry_alloc ();
3555
3556 emarker->ukind = KELIPSMARKER;
3557 emarker->uname = cstring_makeLiteral ("...");
3558 emarker->utype = ctype_elipsMarker;
3559 emarker->sref = sRef_undefined;
3560 emarker->storageclass = SCNONE;
3561 emarker->used = FALSE;
3562 emarker->lset = FALSE;
3563 emarker->info = NULL;
3564
3565 uentry_setSpecDef (emarker, fileloc_undefined);
3566 emarker->uses = filelocList_new ();
3567 emarker->isPrivate = FALSE;
3568 emarker->hasNameError = FALSE;
3569 }
3570
3571 /*@ignore@*/ return (emarker); /*@end@*/
3572}
3573
3574/*
3575** comparisons
3576*/
3577
3578bool
3579uentry_equiv (uentry p1, uentry p2)
3580{
3581 if (uentry_compare (p1, p2) != 0)
3582 {
3583 return FALSE;
3584 }
3585 else
3586 {
3587 return TRUE;
3588 }
3589}
3590
3591int
3592uentry_xcomparealpha (uentry *p1, uentry *p2)
3593{
3594 int res;
3595
3596 if ((res = uentry_compare (*p1, *p2)) == 0) {
3597 if ((*p1 != NULL) && (*p2 != NULL)) {
3598 res = cstring_compare ((*p1)->uname,
3599 (*p2)->uname);
3600 }
3601 }
3602
3603 return res;
3604}
3605
3606int
3607uentry_xcompareuses (uentry *p1, uentry *p2)
3608{
3609 uentry u1 = *p1;
3610 uentry u2 = *p2;
3611
3612 if (uentry_isValid (u1))
3613 {
3614 if (uentry_isValid (u2))
3615 {
3616 return (-1 * int_compare (filelocList_size (u1->uses),
3617 filelocList_size (u2->uses)));
3618 }
3619 else
3620 {
3621 return 1;
3622 }
3623 }
3624 else
3625 {
3626 if (uentry_isValid (u2))
3627 {
3628 return -1;
3629 }
3630 else
3631 {
3632 return 0;
3633 }
3634 }
3635}
3636
3637int
3638uentry_compareStrict (uentry v1, uentry v2)
3639{
3640 COMPARERETURN (uentry_compare (v1, v2));
3641
3642 if (v1 != v2 && uentry_isValid (v1) && uentry_isValid (v2))
3643 {
3644 COMPARERETURN (fileloc_compare (v1->whereDeclared, v2->whereDeclared));
3645 COMPARERETURN (fileloc_compare (v1->whereDefined, v2->whereDefined));
3646 COMPARERETURN (fileloc_compare (v1->whereSpecified, v2->whereSpecified));
3647 }
3648
3649 return 0;
3650}
3651
3652int
3653uentry_compare (uentry u1, uentry u2)
3654{
3655 if (u1 == u2) return 0;
3656
3657 if (uentry_isInvalid (u1)) return -1;
3658 if (uentry_isInvalid (u2)) return 1;
3659
3660 INTCOMPARERETURN (u1->ukind, u2->ukind);
3661 COMPARERETURN (ctype_compare (u1->utype, u2->utype));
3662 COMPARERETURN (bool_compare (uentry_isPriv (u1), uentry_isPriv (u2)));
3663
3664 COMPARERETURN (sRef_compare (u1->sref, u2->sref));
3665
3666 switch (u1->ukind)
3667 {
3668 case KINVALID:
3669 case KELIPSMARKER:
3670 /* bug detected by lclint:
3671 ** uentry.c:753,14: Return value type bool does not match declared type int: TRUE
3672 */
3673 return 0;
3674 case KENUMCONST:
3675 case KCONST:
3676 return (multiVal_compare (u1->info->uconst->val,
3677 u2->info->uconst->val));
3678 case KSTRUCTTAG:
3679 case KUNIONTAG:
3680 case KENUMTAG:
3681 return (ctype_compare (u1->info->datatype->type, u2->info->datatype->type));
3682 case KITER:
3683 COMPARERETURN (typeIdSet_compare (uentry_accessType (u1),
3684 uentry_accessType (u2)));
3685 return (uentryList_compareParams (uentry_getParams (u1),
3686 uentry_getParams (u2)));
3687 case KENDITER:
3688 return (typeIdSet_compare (uentry_accessType (u1),
3689 uentry_accessType (u2)));
3690 case KFCN:
3691 COMPARERETURN (typeIdSet_compare (uentry_accessType (u1),
3692 uentry_accessType (u2)));
3693 COMPARERETURN (globSet_compare (uentry_getGlobs (u1),
3694 uentry_getGlobs (u2)));
3695 COMPARERETURN (uentryList_compareParams (uentry_getParams (u1),
3696 uentry_getParams (u2)));
3697 COMPARERETURN (generic_compare (u1->info->fcn->specialCode,
3698 u2->info->fcn->specialCode));
3699 COMPARERETURN (generic_compare (u1->info->fcn->nullPred,
3700 u2->info->fcn->nullPred));
3701
3702 return (sRefSet_compare (uentry_getMods (u1), uentry_getMods (u2)));
3703 case KVAR:
3704 COMPARERETURN (generic_compare (u1->info->var->kind, u2->info->var->kind));
3705 COMPARERETURN (generic_compare (sRef_getOrigAliasKind (u1->sref),
3706 sRef_getOrigAliasKind (u2->sref)));
3707 COMPARERETURN (generic_compare (sRef_getOrigExKind (u1->sref),
3708 sRef_getOrigExKind (u2->sref)));
3709 COMPARERETURN (generic_compare (u1->info->var->checked,
3710 u2->info->var->checked));
3711 COMPARERETURN (generic_compare (u1->info->var->defstate,
3712 u2->info->var->defstate));
3713 return (generic_compare (u1->info->var->nullstate,
3714 u2->info->var->nullstate));
3715 case KDATATYPE:
3716 COMPARERETURN (ctype_compare (u1->info->datatype->type,
3717 u2->info->datatype->type));
3718 COMPARERETURN (ynm_compare (u1->info->datatype->mut,
3719 u2->info->datatype->mut));
3720 return (ynm_compare (u1->info->datatype->abs, u2->info->datatype->abs));
3721 }
3722
3723 BADEXIT;
3724}
3725
3726/*
3727** library format:
3728**
3729** all entries are: <type>[@<info>]*#<name>
3730**
3731** info depends on kind:
3732*/
3733
3734static void
3735advanceField (char **s)
3736{
3737 checkChar (s, '@');
3738}
3739
3740static void
3741advanceName (char **s)
3742{
3743 checkChar (s, '#');
3744}
3745
3746static vkind
3747vkind_fromInt (int i)
3748{
3749 if /*@+enumint@*/ (i < VKFIRST || i > VKLAST) /*@=enumint@*/
3750 {
3751 llbuglit ("vkind_fromInt: out of range");
3752 }
3753
3754 return (vkind)i;
3755}
3756
3757static uentry
3758 uentry_makeConstantBase (/*@only@*/ cstring name, ctype ct,
3759 typeIdSet access, nstate nullstate,
3760 /*@keep@*/ fileloc loc, /*@only@*/ multiVal m)
3761{
3762 uentry e = uentry_alloc ();
3763
3764 e->ukind = KCONST;
3765 e->uname = name;
3766 e->utype = ct;
3767 e->sref = sRef_makeConst (ct);
3768
3769 sRef_setNullState (e->sref, nullstate, loc);
3770 e->storageclass = SCNONE;
3771
3772 if (fileloc_isSpec (loc))
3773 {
3774 e->whereSpecified = loc;
3775 e->whereDeclared = fileloc_undefined;
3776 }
3777 else
3778 {
3779 e->whereSpecified = fileloc_undefined;
3780 e->whereDeclared = loc;
3781 }
3782
3783 e->whereDefined = fileloc_undefined;
3784 e->uses = filelocList_new ();
3785 e->isPrivate = FALSE;
3786 e->hasNameError = FALSE;
3787
3788 e->used = FALSE;
3789 e->lset = FALSE;
3790
3791 e->info = (uinfo) dmalloc (sizeof (*e->info));
3792 e->info->uconst = (ucinfo) dmalloc (sizeof (*e->info->uconst));
3793 e->info->uconst->val = m;
3794 e->info->uconst->access = access;
3795
3796 sRef_storeState (e->sref);
3797
3798 return (e);
3799}
3800
3801static /*@only@*/ uentry
3802 uentry_makeVariableBase (/*@only@*/ cstring name, ctype ct, vkind kind,
3803 sstate defstate, nstate isnull, alkind aliased,
3804 exkind exp, chkind checked,
3805 /*@only@*/ fileloc loc)
3806{
3807 uentry e = uentry_alloc ();
3808
3809 e->ukind = KVAR;
3810 e->uname = name;
3811 e->utype = ct;
3812 e->storageclass = SCNONE;
3813
3814 e->sref = sRef_makeType (ct);
3815 sRef_setNullState (e->sref, isnull, loc);
3816
3817 e->whereDefined = fileloc_undefined;
3818
3819 if (fileloc_isSpec (loc))
3820 {
3821 e->whereSpecified = loc;
3822 e->whereDeclared = fileloc_undefined;
3823 }
3824 else
3825 {
3826 e->whereSpecified = fileloc_undefined;
3827 e->whereDeclared = loc;
3828 }
3829
3830 e->isPrivate = FALSE;
3831 e->hasNameError = FALSE;
3832
3833 e->used = FALSE;
3834 e->lset = FALSE;
3835
3836 e->uses = filelocList_new ();
3837
3838 e->info = (uinfo) dmalloc (sizeof (*e->info));
3839 e->info->var = (uvinfo) dmalloc (sizeof (*e->info->var));
3840 e->info->var->kind = kind;
3841 e->info->var->checked = checked;
3842 e->info->var->defstate = defstate;
3843
3844 sRef_setDefState (e->sref, defstate, loc);
3845
3846 e->info->var->nullstate = sRef_getNullState (e->sref);
3847
3848 sRef_setExKind (e->sref, exp, loc);
3849 sRef_setAliasKind (e->sref, aliased, loc);
3850
3851 sRef_storeState (e->sref);
3852
3853 /*DRL ADDED 9-1-2000 */
3854 e->info->var->bufinfo = NULL;
3855
3856 return (e);
3857}
3858
3859static /*@only@*/ uentry
3860uentry_makeDatatypeBase (/*@only@*/ cstring name, ctype ct, ynm abs,
3861 ynm mut, ctype rtype, alkind ak, exkind exp,
3862 sstate defstate, nstate isnull,
3863 /*@only@*/ fileloc loc)
3864{
3865 uentry e = uentry_alloc ();
3866
3867 e->ukind = KDATATYPE;
3868 /* e->shallowCopy = FALSE; */
3869 e->uname = name;
3870 e->utype = ct;
3871 e->storageclass = SCNONE;
3872 e->sref = sRef_makeUnknown ();
3873
3874 /*
3875 ** This is only setting null state. (I think?)
3876 */
3877
3878 if (ctype_isUA (ct))
3879 {
3880 uentry te = usymtab_getTypeEntrySafe (ctype_typeId (ct));
3881
3882 if (uentry_isValid (te))
3883 {
3884 sRef_setStateFromUentry (e->sref, te);
3885 }
3886 else
3887 {
3888 /* problem for recursive type definitions */
3889 }
3890 }
3891
3892 sRef_setAliasKind (e->sref, ak, loc);
3893 sRef_setExKind (e->sref, exp, loc);
3894
3895 sRef_setDefState (e->sref, defstate, loc);
3896
3897 if (ynm_isOn (abs) && ctype_isUnknown (ct) && isnull == NS_UNKNOWN)
3898 {
3899 isnull = NS_ABSNULL;
3900 }
3901
3902 sRef_mergeNullState (e->sref, isnull);
3903
3904 e->whereDefined = fileloc_copy (loc); /*< bogus! (but necessary for lexer) >*/
3905
3906 if (fileloc_isSpec (loc))
3907 {
3908 e->whereSpecified = loc;
3909 e->whereDeclared = fileloc_undefined;
3910 }
3911 else
3912 {
3913 e->whereSpecified = fileloc_undefined;
3914 e->whereDeclared = loc;
3915 }
3916
3917 e->isPrivate = FALSE;
3918 e->hasNameError = FALSE;
3919
3920 e->used = FALSE;
3921 e->lset = FALSE;
3922 e->uses = filelocList_new ();
3923
3924 e->info = (uinfo) dmalloc (sizeof (*e->info));
3925 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
3926 e->info->datatype->abs = abs;
3927 e->info->datatype->mut = mut;
3928 e->info->datatype->type = rtype;
3929
3930 sRef_storeState (e->sref);
3931
3932 return (e);
3933}
3934
3935# ifndef NOLCL
3936static void uentry_setHasGlobs (uentry ue)
3937{
3938 llassert (uentry_isFunction (ue));
3939
3940 ue->info->fcn->hasGlobs = TRUE;
3941}
3942
3943static void uentry_setHasMods (uentry ue)
3944{
3945 llassert (uentry_isFunction (ue));
3946
3947 ue->info->fcn->hasMods = TRUE;
3948}
3949# endif
3950
3951bool uentry_hasGlobs (uentry ue)
3952{
3953 if (uentry_isFunction (ue))
3954 {
3955 return (ue->info->fcn->hasGlobs);
3956 }
3957
3958 return FALSE;
3959}
3960
3961bool uentry_hasSpecialClauses (uentry ue)
3962{
3963 return (uentry_isFunction (ue) && specialClauses_isDefined (ue->info->fcn->specclauses));
3964}
3965
3966specialClauses uentry_getSpecialClauses (uentry ue)
3967{
3968 llassert (uentry_isFunction (ue));
3969 return ue->info->fcn->specclauses;
3970}
3971
3972bool uentry_hasMods (uentry ue)
3973{
3974 if (uentry_isFunction (ue))
3975 {
3976 return (ue->info->fcn->hasMods);
3977 }
3978
3979 return FALSE;
3980}
3981
3982static uentry
3983 uentry_makeFunctionBase (/*@only@*/ cstring name, ctype ct,
3984 typeIdSet access,
3985 bool hasGlobs, /*@only@*/ globSet globs,
3986 bool hasMods, /*@only@*/ sRefSet mods,
3987 alkind ak, exkind exp,
3988 sstate defstate, nstate isnull,
3989 exitkind exitCode,
3990 specCode sCode,
3991 qual nullPred,
3992 /*@only@*/ specialClauses specclauses,
3993 /*@only@*/ fileloc loc)
3994{
3995 uentry e = uentry_alloc ();
3996 ctype ret;
3997
3998 /* e->shallowCopy = FALSE; */
3999 e->ukind = KFCN;
4000 e->uname = name;
4001 e->utype = ct;
4002 e->storageclass = SCNONE;
4003
4004 if (ctype_isFunction (ct))
4005 {
4006 ret = ctype_returnValue (ct);
4007 }
4008 else
4009 {
4010 if (ctype_isKnown (ct))
4011 {
4012 llbug (message ("not function: %s", ctype_unparse (ct)));
4013 }
4014
4015 ret = ctype_unknown;
4016 }
4017
4018 e->sref = sRef_makeType (ret);
4019
4020 if (ctype_isUA (ret))
4021 {
4022 sRef_setStateFromType (e->sref, ret);
4023 }
4024
4025 sRef_setDefined (e->sref, loc);
4026 sRef_setNullState (e->sref, isnull, loc);
4027
4028 sRef_setAliasKind (e->sref, ak, loc);
4029 sRef_setExKind (e->sref, exp, loc);
4030 sRef_setDefState (e->sref, defstate, loc);
4031
4032 e->whereSpecified = loc;
4033 e->whereDefined = fileloc_undefined;
4034
4035 e->isPrivate = FALSE;
4036 e->hasNameError = FALSE;
4037
4038 e->used = FALSE;
4039 e->lset = FALSE;
4040 e->uses = filelocList_new ();
4041
4042 e->info = (uinfo) dmalloc (sizeof (*e->info));
4043 e->info->fcn = (ufinfo) dmalloc (sizeof (*e->info->fcn));
4044
4045 e->info->fcn->exitCode = exitCode;
4046 e->info->fcn->specialCode = sCode;
4047 e->info->fcn->nullPred = nullPred;
4048 e->info->fcn->access = access;
4049
4050 e->info->fcn->specclauses = specclauses;
4051 e->info->fcn->hasGlobs = hasGlobs;
4052 e->info->fcn->globs = globs;
4053
4054 e->info->fcn->hasMods = hasMods;
4055 e->info->fcn->mods = mods;
4056
4057 e->info->fcn->defparams = uentryList_undefined;
4058 e->whereDeclared = fileloc_undefined;
4059
4060 sRef_storeState (e->sref);
4061
4062 /*drl 111 30 2000*/
4063 e->info->fcn->preconditions = NULL;
4064 /* end drl */
4065
4066 /*drl 12 28 2000*/
4067 e->info->fcn->postconditions = NULL;
4068 /* end drl */
4069
4070 return (e);
4071}
4072
4073static /*@only@*/ uentry
4074 uentry_makeTagBase (/*@only@*/ cstring name, ekind tagkind,
4075 ctype ct, ctype rtype, /*@only@*/ fileloc loc)
4076{
4077 uentry e = uentry_alloc ();
4078
4079 if (tagkind != KSTRUCTTAG && tagkind != KUNIONTAG && tagkind != KENUMTAG)
4080 {
4081 llbuglit ("uentry_makeTagBase: not a tag type");
4082 }
4083
4084 /* e->shallowCopy = FALSE; */
4085 e->ukind = tagkind;
4086 e->uname = name;
4087 e->utype = ct;
4088 e->sref = sRef_makeUnknown ();
4089 e->storageclass = SCNONE;
4090
4091 if (fileloc_isSpec (loc))
4092 {
4093 e->whereSpecified = loc;
4094 e->whereDeclared = fileloc_undefined;
4095 }
4096 else
4097 {
4098 e->whereDeclared = loc;
4099 e->whereSpecified = fileloc_undefined;
4100 }
4101
4102 e->whereDefined = fileloc_undefined;
4103
4104 e->isPrivate = FALSE;
4105 e->hasNameError = FALSE;
4106
4107 e->used = FALSE;
4108 e->lset = FALSE;
4109 e->uses = filelocList_new ();
4110
4111 e->info = (uinfo) dmalloc (sizeof (*e->info));
4112 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
4113 e->info->datatype->abs = NO;
4114 e->info->datatype->mut = MAYBE;
4115 e->info->datatype->type = rtype;
4116
4117 sRef_storeState (e->sref);
4118
4119 return (e);
4120}
4121
4122static uentry
4123 uentry_makeIterBase (/*@only@*/ cstring name, typeIdSet access,
4124 ctype ct, /*@only@*/ fileloc loc)
4125{
4126 uentry e = uentry_alloc ();
4127
4128 /* e->shallowCopy = FALSE; */
4129 e->ukind = KITER;
4130 e->uname = name;
4131 e->utype = ct;
4132 e->sref = sRef_makeUnknown ();
4133 e->storageclass = SCNONE;
4134
4135 if (fileloc_isSpec (loc))
4136 {
4137 e->whereSpecified = loc;
4138 e->whereDeclared = fileloc_undefined;
4139 }
4140 else
4141 {
4142 e->whereDeclared = loc;
4143 e->whereSpecified = fileloc_undefined;
4144 }
4145
4146 e->whereDefined = fileloc_undefined;
4147
4148 e->isPrivate = FALSE;
4149 e->hasNameError = FALSE;
4150
4151 e->used = FALSE;
4152 e->lset = FALSE;
4153 e->uses = filelocList_new ();
4154
4155 e->info = (uinfo) dmalloc (sizeof (*e->info));
4156 e->info->iter = (uiinfo) dmalloc (sizeof (*e->info->iter));
4157 e->info->iter->access = access;
4158 e->info->iter->mods = sRefSet_undefined;
4159 e->info->iter->globs = globSet_undefined;
4160
4161 sRef_storeState (e->sref);
4162 return (e);
4163}
4164
4165static uentry
4166 uentry_makeEndIterBase (/*@only@*/ cstring name, typeIdSet access,
4167 /*@only@*/ fileloc loc)
4168{
4169 uentry e = uentry_alloc ();
4170
4171 /* e->shallowCopy = FALSE; */
4172 e->ukind = KENDITER;
4173 e->storageclass = SCNONE;
4174 e->uname = name;
4175 e->utype = ctype_unknown;
4176 e->sref = sRef_makeUnknown ();
4177
4178 if (fileloc_isSpec (loc))
4179 {
4180 e->whereSpecified = loc;
4181 e->whereDeclared = fileloc_undefined;
4182 }
4183 else
4184 {
4185 e->whereDeclared = loc;
4186 e->whereSpecified = fileloc_undefined;
4187 }
4188
4189 e->whereDefined = fileloc_undefined;
4190
4191 e->isPrivate = FALSE;
4192 e->hasNameError = FALSE;
4193
4194 e->used = FALSE;
4195 e->lset = FALSE;
4196 e->uses = filelocList_new ();
4197
4198 e->info = (uinfo) dmalloc (sizeof (*e->info));
4199 e->info->enditer = (ueinfo) dmalloc (sizeof (*e->info->enditer));
4200 e->info->enditer->access = access;
4201 sRef_storeState (e->sref);
4202
4203 return (e);
4204}
4205
4206void uentry_markFree (/*@unused@*/ /*@owned@*/ uentry u)
4207{
4208 /* should save u */
4209/*@-mustfree@*/
4210}
4211/*@=mustfree@*/
4212
4213/*@only@*/ uentry
4214uentry_undump (ekind kind, fileloc loc, char **s)
4215{
4216 uentry ue;
4217
4218 if (**s == '!')
4219 {
4220 checkChar (s, '!');
4221 checkChar (s, '.');
4222 ue = uentry_makeElipsisMarker ();
4223 }
4224 else
4225 {
4226 ctype ct = ctype_undump (s);
4227 cstring name;
4228
4229 switch (kind)
4230 {
4231 case KVAR:
4232 {
4233 vkind tkind;
4234 sstate defstate;
4235 nstate isnull;
4236 alkind aliased;
4237 exkind exp;
4238 chkind checked;
4239
4240 checkChar (s, '|');
4241
4242 if (optCheckChar (s, '@'))
4243 {
4244 tkind = vkind_fromInt (getInt (s));
4245 checkChar (s, '|');
4246 }
4247 else
4248 {
4249 tkind = VKPARAM;
4250 }
4251
4252 if (optCheckChar (s, '$'))
4253 {
4254 defstate = SS_UNKNOWN;
4255 isnull = NS_UNKNOWN;
4256 aliased = AK_IMPTEMP;
4257 exp = XO_UNKNOWN;
4258 checked = CH_UNKNOWN;
4259 }
4260 else if (optCheckChar (s, '&'))
4261 {
4262 defstate = SS_DEFINED;
4263 isnull = NS_UNKNOWN;
4264 aliased = AK_IMPTEMP;
4265 exp = XO_UNKNOWN;
4266 checked = CH_UNKNOWN;
4267 }
4268 else if (optCheckChar (s, '^'))
4269 {
4270 defstate = SS_UNKNOWN;
4271 isnull = NS_UNKNOWN;
4272 aliased = AK_IMPTEMP;
4273 exp = XO_UNKNOWN;
4274 checked = CH_UNKNOWN;
4275 }
4276 else
4277 {
4278 defstate = sstate_fromInt (getInt (s));
4279 advanceField (s); isnull = nstate_fromInt (getInt (s));
4280 advanceField (s); aliased = alkind_fromInt (getInt (s));
4281
4282 if (optCheckChar (s, '&'))
4283 {
4284 exp = XO_UNKNOWN;
4285 checked = CH_UNKNOWN;
4286 }
4287 else
4288 {
4289 advanceField (s); exp = exkind_fromInt (getInt (s));
4290 advanceField (s); checked = (chkind) (getInt (s));
4291 }
4292 }
4293
4294 advanceName (s);
4295 name = getStringWord (s);
4296
4297 ue = uentry_makeVariableBase (name, ct, tkind, defstate,
4298 isnull, aliased, exp,
4299 checked, fileloc_copy (loc));
4300 }
4301 break;
4302 case KDATATYPE:
4303 {
4304 ynm abs;
4305 ynm mut;
4306 ctype rtype;
4307 sstate defstate;
4308 nstate isnull;
4309 alkind aliased;
4310 exkind exp;
4311
4312 advanceField (s); abs = ynm_fromCodeChar (loadChar (s));
4313 advanceField (s); mut = ynm_fromCodeChar (loadChar (s));
4314 advanceField (s); defstate = sstate_fromInt (getInt (s));
4315 advanceField (s); isnull = nstate_fromInt (getInt (s));
4316 advanceField (s); aliased = alkind_fromInt (getInt (s));
4317 advanceField (s); exp = exkind_fromInt (getInt (s));
4318 advanceField (s); rtype = ctype_undump (s);
4319 advanceName (s);
4320 name = getStringWord (s);
4321
4322 ue = uentry_makeDatatypeBase (name, ct, abs, mut, rtype,
4323 aliased, exp, defstate, isnull,
4324 fileloc_copy (loc));
4325 }
4326 break;
4327 case KFCN:
4328 {
4329 alkind ak;
4330 exkind exp;
4331 sstate defstate;
4332 nstate isnull;
4333 exitkind exitCode;
4334 specCode specc;
4335 qual nullPred;
4336 typeIdSet access;
4337 bool hasGlobs;
4338 globSet globs;
4339 bool hasMods;
4340 sRefSet mods;
4341 specialClauses specclauses;
4342
4343 if (optCheckChar (s, '$'))
4344 {
4345 defstate = SS_DEFINED;
4346 isnull = NS_UNKNOWN;
4347 exitCode = XK_UNKNOWN;
4348 specc = SPC_NONE;
4349 nullPred = QU_UNKNOWN;
4350 }
4351 else
4352 {
4353 advanceField (s); defstate = sstate_fromInt (getInt (s));
4354 advanceField (s); isnull = nstate_fromInt (getInt (s));
4355 advanceField (s); exitCode = exitkind_fromInt (getInt (s));
4356 advanceField (s); specc = specCode_fromInt (getInt (s));
4357 advanceField (s); nullPred = qual_fromInt (getInt (s));
4358 }
4359
4360 if (optCheckChar (s, '$'))
4361 {
4362 hasGlobs = FALSE;
4363 globs = globSet_undefined;
4364 hasMods = FALSE;
4365 mods = sRefSet_undefined;
4366 }
4367 else if (optCheckChar (s, '^'))
4368 {
4369 hasGlobs = TRUE;
4370 globs = globSet_undefined;
4371 hasMods = TRUE;
4372 mods = sRefSet_undefined;
4373 }
4374 else
4375 {
4376 advanceField (s); hasGlobs = bool_fromInt (getInt (s));
4377 advanceField (s); globs = globSet_undump (s);
4378 advanceField (s); hasMods = bool_fromInt (getInt (s));
4379 advanceField (s); mods = sRefSet_undump (s);
4380 }
4381
4382 if (optCheckChar (s, '$'))
4383 {
4384 ak = AK_UNKNOWN;
4385 exp = XO_UNKNOWN;
4386 }
4387 else
4388 {
4389 advanceField (s); ak = alkind_fromInt (getInt (s));
4390 advanceField (s); exp = exkind_fromInt (getInt (s));
4391 }
4392
4393 advanceField (s); access = typeIdSet_undump (s);
4394
4395 if (optCheckChar (s, '@'))
4396 {
4397 specclauses = specialClauses_undump (s);
4398 }
4399 else
4400 {
4401 specclauses = specialClauses_undefined;
4402 }
4403
4404 advanceName (s); name = getStringWord (s);
4405
4406 ue = uentry_makeFunctionBase (name, ct, access,
4407 hasGlobs, globs,
4408 hasMods, mods,
4409 ak, exp, defstate, isnull,
4410 exitCode, specc, nullPred,
4411 specclauses,
4412 fileloc_copy (loc));
4413 DPRINTF (("Undump: %s", uentry_unparse (ue)));
4414 }
4415 break;
4416 case KITER:
4417 {
4418 typeIdSet access;
4419
4420 advanceField (s); access = typeIdSet_undump (s);
4421 advanceName (s); name = getStringWord (s);
4422
4423 ue = uentry_makeIterBase (name, access, ct,
4424 fileloc_copy (loc));
4425 }
4426 break;
4427 case KENDITER:
4428 {
4429 typeIdSet access;
4430
4431 advanceField (s); access = typeIdSet_undump (s);
4432 advanceName (s); name = getStringWord (s);
4433
4434 ue = uentry_makeEndIterBase (name, access, fileloc_copy (loc));
4435 }
4436 break;
4437 case KENUMCONST:
4438 case KCONST:
4439 {
4440 typeIdSet access;
4441 multiVal val;
4442 nstate nullstate;
4443
4444 if (optCheckChar (s, '$'))
4445 {
4446 val = multiVal_undefined;
4447 access = typeIdSet_undefined;
4448 nullstate = NS_UNKNOWN;
4449 }
4450 else
4451 {
4452 advanceField (s); val = multiVal_undump (s);
4453 advanceField (s); access = typeIdSet_undump (s);
4454 advanceField (s); nullstate = nstate_fromInt (getInt (s));
4455 }
4456
4457 advanceName (s); name = getStringWord (s);
4458
4459 ue = uentry_makeConstantBase (name, ct, access,
4460 nullstate, fileloc_copy (loc), val);
4461 break;
4462 }
4463 case KSTRUCTTAG:
4464 case KUNIONTAG:
4465 case KENUMTAG:
4466 {
4467 ctype rtype;
4468
4469 advanceField (s); rtype = ctype_undump (s);
4470 advanceName (s); name = getStringWord (s);
4471 ue = uentry_makeTagBase (name, kind, ct, rtype, fileloc_copy (loc));
4472 }
4473 break;
4474 case KINVALID:
4475 llcontbuglit ("uentry_undump: invalid");
4476 ue = uentry_undefined;
4477 break;
4478 case KELIPSMARKER:
4479 llcontbuglit ("uentry_undump: elips marker");
4480 ue = uentry_undefined;
4481 break;
4482 }
4483 }
4484
4485 return (ue);
4486}
4487
4488cstring
4489uentry_dump (uentry v)
4490{
4491 return (uentry_dumpAux (v, FALSE));
4492}
4493
4494cstring
4495uentry_dumpParam (uentry v)
4496{
4497 llassertprint (uentry_isVariable (v) || uentry_isElipsisMarker (v),
4498 ("dump: %s", uentry_unparseFull (v)));
4499
4500 return (uentry_dumpAux (v, TRUE));
4501}
4502
4503static cstring
4504uentry_dumpAux (uentry v, bool isParam)
4505{
4506 llassert (uentry_isValid (v));
4507
4508 DPRINTF (("Dumping entry: %s", uentry_unparseFull (v)));
4509
4510 switch (v->ukind)
4511 {
4512 case KINVALID:
4513 llcontbuglit ("uentry_dump: invalid entry");
4514 return cstring_undefined;
4515 case KELIPSMARKER:
4516 return (message ("!."));
4517 case KVAR:
4518 {
4519 cstring sdump;
4520 vkind vk = v->info->var->kind;
4521 sstate dss = sRef_getDefState (v->sref);
4522 nstate nst = sRef_getNullState (v->sref);
4523 alkind alk = sRef_getAliasKind (v->sref);
4524 exkind exk = sRef_getExKind (v->sref);
4525 chkind chk = v->info->var->checked;
4526
4527 DPRINTF (("Dumping var"));
4528
4529 if (dss == SS_UNKNOWN
4530 && nst == NS_UNKNOWN
4531 && alk == AK_IMPTEMP
4532 && exk == XO_UNKNOWN
4533 && chk == CH_UNKNOWN)
4534 {
4535 sdump = cstring_makeLiteral ("$");
4536 }
4537 else if (dss == SS_DEFINED
4538 && nst == NS_UNKNOWN
4539 && alk == AK_IMPTEMP
4540 && exk == XO_UNKNOWN
4541 && chk == CH_UNKNOWN)
4542 {
4543 sdump = cstring_makeLiteral ("&");
4544 }
4545 else if (dss == SS_UNKNOWN
4546 && nst == NS_UNKNOWN
4547 && alk == AK_UNKNOWN
4548 && exk == XO_UNKNOWN
4549 && chk == CH_UNKNOWN)
4550 {
4551 sdump = cstring_makeLiteral ("^");
4552 }
4553 else if (exk == XO_UNKNOWN
4554 && chk == CH_UNKNOWN)
4555 {
4556 sdump = message ("%d@%d@%d&",
4557 (int) dss,
4558 (int) nst,
4559 (int) alk);
4560 }
4561 else
4562 {
4563 sdump = message ("%d@%d@%d@%d@%d",
4564 (int) dss,
4565 (int) nst,
4566 (int) alk,
4567 (int) exk,
4568 (int) chk);
4569 }
4570
4571
4572 if (vk != VKPARAM)
4573 {
4574 return (message ("%q|@%d|%q#%s",
4575 ctype_dump (v->utype),
4576 (int) vk,
4577 sdump,
4578 isParam ? cstring_undefined : v->uname));
4579 }
4580 else
4581 {
4582 return (message ("%q|%q#%s",
4583 ctype_dump (v->utype),
4584 sdump,
4585 isParam ? cstring_undefined : v->uname));
4586 }
4587
4588 }
4589 case KDATATYPE:
4590 return (message ("%q@%s@%s@%d@%d@%d@%d@%q#%s",
4591 ctype_dump (v->utype),
4592 ynm_unparseCode (v->info->datatype->abs),
4593 ynm_unparseCode (v->info->datatype->mut),
4594 (int) sRef_getDefState (v->sref),
4595 (int) sRef_getNullState (v->sref),
4596 (int) sRef_getAliasKind (v->sref),
4597 (int) sRef_getExKind (v->sref),
4598 ctype_dump (v->info->datatype->type),
4599 v->uname));
4600 case KFCN:
4601 {
4602 cstring sdump, gdump, adump;
4603 alkind alk = sRef_getAliasKind (v->sref);
4604 exkind exk = sRef_getExKind (v->sref);
4605
4606 if (sRef_getDefState (v->sref) == SS_DEFINED
4607 && !nstate_isKnown (sRef_getNullState (v->sref))
4608 && !exitkind_isKnown (v->info->fcn->exitCode)
4609 && v->info->fcn->specialCode == SPC_NONE
4610 && v->info->fcn->nullPred == QU_UNKNOWN)
4611 {
4612 sdump = cstring_makeLiteral ("$");
4613 }
4614 else
4615 {
4616 sdump = message ("@%d@%d@%d@%d@%d",
4617 (int) sRef_getDefState (v->sref),
4618 (int) sRef_getNullState (v->sref),
4619 (int) v->info->fcn->exitCode,
4620 (int) v->info->fcn->specialCode,
4621 (int) v->info->fcn->nullPred);
4622 }
4623
4624 if (!uentry_hasGlobs(v) && !uentry_hasMods (v))
4625 {
4626 gdump = cstring_makeLiteral ("$");
4627 }
4628 else if (uentry_hasGlobs (v) && globSet_isEmpty (uentry_getGlobs (v))
4629 && uentry_hasMods (v) && sRefSet_isEmpty (uentry_getMods (v)))
4630 {
4631 gdump = cstring_makeLiteral ("^");
4632 }
4633 else
4634 {
4635 gdump = message ("@%s@%q@%s@%q",
4636 bool_dump (uentry_hasGlobs (v)),
4637 globSet_dump (uentry_getGlobs (v)),
4638 bool_dump (uentry_hasMods (v)),
4639 sRefSet_dump (uentry_getMods (v)));
4640 }
4641
4642 if (alk == AK_UNKNOWN && exk == XO_UNKNOWN)
4643 {
4644 adump = cstring_makeLiteral ("$");
4645 }
4646 else
4647 {
4648 adump = message ("@%d@%d", (int) alk, (int) exk);
4649 }
4650
4651 if (uentry_hasSpecialClauses (v))
4652 {
4653 return (message ("%q%q%q%q@%q@%q#%s",
4654 ctype_dump (v->utype),
4655 sdump,
4656 gdump,
4657 adump,
4658 typeIdSet_dump (uentry_accessType (v)),
4659 specialClauses_dump (v->info->fcn->specclauses),
4660 v->uname));
4661 }
4662 else
4663 {
4664 return (message ("%q%q%q%q@%q#%s",
4665 ctype_dump (v->utype),
4666 sdump,
4667 gdump,
4668 adump,
4669 typeIdSet_dump (uentry_accessType (v)),
4670 v->uname));
4671 }
4672 }
4673 case KITER:
4674 return (message ("%q@%q#%s",
4675 ctype_dump (v->utype),
4676 typeIdSet_dump (v->info->iter->access),
4677 v->uname));
4678 case KENDITER:
4679 return (message ("%q@%q#%s",
4680 ctype_dump (v->utype),
4681 typeIdSet_dump (uentry_accessType (v)),
4682 v->uname));
4683 case KENUMCONST:
4684 case KCONST:
4685 {
4686 cstring sdump;
4687
4688 if (multiVal_isUnknown (v->info->uconst->val)
4689 && typeIdSet_isEmpty (uentry_accessType (v))
4690 && (sRef_getNullState (v->sref) == NS_UNKNOWN))
4691 {
4692 sdump = cstring_makeLiteral ("$");
4693 }
4694 else
4695 {
4696 sdump = message ("@%q@%q@%d",
4697 multiVal_dump (v->info->uconst->val),
4698 typeIdSet_dump (uentry_accessType (v)),
4699 (int) sRef_getNullState (v->sref));
4700 }
4701
4702 return (message ("%q%q#%s",
4703 ctype_dump (v->utype),
4704 sdump,
4705 v->uname));
4706 }
4707 case KSTRUCTTAG:
4708 case KUNIONTAG:
4709 case KENUMTAG:
4710 return (message ("%q@%q#%s",
4711 ctype_dump (v->utype),
4712 ctype_dump (v->info->datatype->type), v->uname));
4713 }
4714
4715 BADEXIT;
4716}
4717
4718/*@only@*/ cstring
4719uentry_unparseAbbrev (uentry v)
4720{
4721 if (!uentry_isVariable (v))
4722 {
4723 llcontbuglit ("uentry_unparseAbbrev: not variable");
4724 return uentry_unparse (v);
4725 }
4726
4727 return (message ("%s %q", ctype_unparseDeep (v->utype), uentry_getName (v)));
4728}
4729
4730/*@only@*/ cstring
4731uentry_unparse (uentry v)
4732{
4733 cstring st;
4734
4735 if (uentry_isUndefined (v)) return (cstring_makeLiteral ("<undefined>"));
4736 if (uentry_isElipsisMarker (v)) return (cstring_makeLiteral ("..."));
4737
4738 st = uentry_getName (v);
4739
4740 if (cstring_isDefined (st))
4741 {
4742 return (ctype_unparseDeclaration (v->utype, st));
4743 }
4744 else
4745 {
4746 cstring_free (st);
4747 return (cstring_copy (ctype_unparse (v->utype)));
4748 }
4749}
4750
4751/*@only@*/ cstring
4752uentry_unparseFull (uentry v)
4753{
4754 if (uentry_isUndefined (v))
4755 {
4756 return (cstring_makeLiteral ("<undefined>"));
4757 }
4758 else if (uentry_isDatatype (v))
4759 {
4760 return (message ("[%d] [%s] %s %q : %t [%t] %s %s // %q [s: %q; d: %q]",
4761 (int) v,
4762 ekind_unparse (v->ukind),
4763 v->uname,
4764 uentry_getName (v),
4765 v->utype,
4766 ctype_isDefined (v->info->datatype->type)
4767 ? v->info->datatype->type : ctype_unknown,
4768 ynm_unparse (v->info->datatype->mut),
4769 ynm_unparse (v->info->datatype->abs),
4770 sRef_unparseState (v->sref),
4771 fileloc_unparse (v->whereSpecified),
4772 fileloc_unparse (v->whereDefined)));
4773 }
4774 else if (uentry_isFunction (v))
4775 {
4776 return (message ("[%w] = [%s] %q : %t / sref: %q / mods: %q / "
4777 "globs: %q / [s: %q; decl: %q; def: %q]",
4778 (long unsigned) v,
4779 ekind_unparse (v->ukind),
4780 uentry_getName (v),
4781 v->utype,
4782 sRef_unparseFull (v->sref),
4783 sRefSet_unparse (v->info->fcn->mods),
4784 globSet_unparse (v->info->fcn->globs),
4785 fileloc_unparse (v->whereSpecified),
4786 fileloc_unparse (v->whereDeclared),
4787 fileloc_unparse (v->whereDefined)));
4788 }
4789 else if (uentry_isIter (v))
4790 {
4791 return (message ("[%s] %q: %t / %q [s: %q; d: %q]",
4792 ekind_unparse (v->ukind),
4793 uentry_getName (v),
4794 v->utype,
4795 sRef_unparseFull (v->sref),
4796 fileloc_unparse (v->whereSpecified),
4797 fileloc_unparse (v->whereDefined)));
4798 }
4799 else if (uentry_isVariable (v))
4800 {
4801 return
4802 (message ("[check: %s] / [%w] = [%s] %s : %t %q [s: %q; def: %q; dec: %q] "
4803 "kind <%d> isout <%d> used <%d>",
4804 checkedName (v->info->var->checked),
4805 (long unsigned) v,
4806 ekind_unparse (v->ukind),
4807 v->uname,
4808 v->utype,
4809 sRef_unparseDeep (v->sref),
4810 fileloc_unparse (v->whereSpecified),
4811 fileloc_unparse (v->whereDefined),
4812 fileloc_unparse (v->whereDeclared),
4813 (int) v->info->var->kind,
4814 (int) v->info->var->defstate,
4815 (int) v->used));
4816 }
4817 else
4818 {
4819 return (message ("[%s] %s : %t %q at [s: %q; d: %q]",
4820 ekind_unparse (v->ukind),
4821 v->uname,
4822 v->utype,
4823 sRef_unparseFull (v->sref),
4824 fileloc_unparse (v->whereSpecified),
4825 fileloc_unparse (v->whereDefined)));
4826
4827 }
4828}
4829
4830bool uentry_hasAccessType (uentry e)
4831{
4832 if (uentry_isValid (e))
4833 {
4834 switch (e->ukind)
4835 {
4836 case KITER:
4837 return (!typeIdSet_isEmpty (e->info->iter->access));
4838 case KENDITER:
4839 return (!typeIdSet_isEmpty (e->info->enditer->access));
4840 case KFCN:
4841 return (!typeIdSet_isEmpty (e->info->fcn->access));
4842 case KENUMCONST:
4843 case KCONST:
4844 return (!typeIdSet_isEmpty (e->info->uconst->access));
4845 default:
4846 return FALSE;
4847 }
4848 }
4849
4850 return FALSE;
4851}
4852
4853typeIdSet uentry_accessType (uentry e)
4854{
4855 if (uentry_isValid (e))
4856 {
4857 switch (e->ukind)
4858 {
4859 case KITER:
4860 return (e->info->iter->access);
4861 case KENDITER:
4862 return (e->info->enditer->access);
4863 case KFCN:
4864 return (e->info->fcn->access);
4865 case KENUMCONST:
4866 case KCONST:
4867 return (e->info->uconst->access);
4868 default:
4869 break;
4870 }
4871 }
4872
4873 return typeIdSet_undefined;
4874}
4875
4876bool
4877uentry_isVariable (uentry e)
4878{
4879 return (uentry_isVar (e));
4880}
4881
4882bool
4883uentry_isSpecified (uentry e)
4884{
4885 return (uentry_isValid (e) && !fileloc_isUndefined (e->whereSpecified));
4886}
4887
4888static bool
4889uentry_isReallySpecified (uentry e)
4890{
4891 return (uentry_isValid (e)
4892 && fileloc_isRealSpec (e->whereSpecified));
4893}
4894
4895bool
4896uentry_isVar (uentry e)
4897{
4898 return (!uentry_isUndefined (e) && e->ukind == KVAR);
4899}
4900
4901bool
4902uentry_isFakeTag (uentry e)
4903{
4904 return (uentry_isValid (e) && strchr (cstring_toCharsSafe (e->uname), '!') != 0);
4905}
4906
4907bool
4908uentry_isDatatype (uentry e)
4909{
4910 return (!uentry_isUndefined (e) &&
4911 (e->ukind == KDATATYPE || e->ukind == KSTRUCTTAG ||
4912 e->ukind == KUNIONTAG || e->ukind == KENUMTAG));
4913}
4914
4915void
4916uentry_setAbstract (uentry e)
4917{
4918 typeId oldid;
4919
4920 llassert (uentry_isDatatype (e)
4921 && (ynm_isMaybe (e->info->datatype->abs)));
4922
4923 oldid = ctype_typeId (e->info->datatype->type);
4924 e->info->datatype->abs = YES;
4925 e->info->datatype->type = ctype_createAbstract (oldid);
4926}
4927
4928void
4929uentry_setConcrete (uentry e)
4930{
4931 llassert (uentry_isDatatype (e)
4932 && (ynm_isMaybe (e->info->datatype->abs)));
4933
4934 e->info->datatype->abs = NO;
4935}
4936
4937bool
4938uentry_isAbstractDatatype (uentry e)
4939{
4940 return (uentry_isDatatype (e)
4941 && (ynm_isOn (e->info->datatype->abs)));
4942}
4943
4944bool
4945uentry_isMaybeAbstract (uentry e)
4946{
4947 return (uentry_isDatatype (e)
4948 && (ynm_isMaybe (e->info->datatype->abs)));
4949}
4950
4951bool
4952uentry_isMutableDatatype (uentry e)
4953{
4954 bool res = uentry_isDatatype (e)
4955 && (ynm_toBoolRelaxed (e->info->datatype->mut));
4956
4957 return res;
4958}
4959
4960bool
4961uentry_isRefCountedDatatype (uentry e)
4962{
4963 return (uentry_isDatatype (e) && (sRef_isRefCounted (uentry_getSref (e))));
4964}
4965
4966bool
4967uentry_isParam (uentry u)
4968{
4969 return (uentry_isVariable (u) && (u->info->var->kind == VKPARAM
4970 || u->info->var->kind == VKYIELDPARAM));
4971}
4972
4973bool
4974uentry_isExpandedMacro (uentry u)
4975{
4976 return (uentry_isVariable (u) && (u->info->var->kind == VKEXPMACRO));
4977}
4978
4979bool
4980uentry_isSefParam (uentry u)
4981{
4982 return (uentry_isVariable (u)
4983 && (u->info->var->kind == VKSEFPARAM
4984 || u->info->var->kind == VKREFSEFPARAM
4985 || u->info->var->kind == VKSEFRETPARAM
4986 || u->info->var->kind == VKREFSEFRETPARAM));
4987}
4988
4989bool
4990uentry_isRefParam (uentry u)
4991{
4992 return (uentry_isVariable (u)
4993 && (u->info->var->kind == VKREFPARAM
4994 || u->info->var->kind == VKREFYIELDPARAM
4995 || u->info->var->kind == VKREFSEFPARAM
4996 || u->info->var->kind == VKREFSEFRETPARAM));
4997}
4998
4999bool
5000uentry_isAnyParam (uentry u)
5001{
5002 return (uentry_isVariable (u)
5003 && ((u->info->var->kind == VKPARAM)
5004 || (u->info->var->kind == VKSEFPARAM)
5005 || (u->info->var->kind == VKYIELDPARAM)
5006 || (u->info->var->kind == VKRETPARAM)
5007 || (u->info->var->kind == VKSEFRETPARAM)));
5008}
5009
5010sstate
5011uentry_getDefState (uentry u)
5012{
5013 if (uentry_isValid (u))
5014 {
5015 return (sRef_getDefState (u->sref));
5016 }
5017 else
5018 {
5019 return (SS_UNKNOWN);
5020 }
5021}
5022
5023bool
5024uentry_isOut (uentry u)
5025{
5026 return ((uentry_isVariable (u) && (u->info->var->defstate == SS_ALLOCATED))
5027 || (uentry_isDatatype (u) && (sRef_isAllocated (u->sref))));
5028}
5029
5030bool
5031uentry_isPartial (uentry u)
5032{
5033 return ((uentry_isVariable (u) && (u->info->var->defstate == SS_PARTIAL))
5034 || (uentry_isDatatype (u) && (sRef_isAllocated (u->sref))));
5035}
5036
5037bool
5038uentry_isStateSpecial (uentry u)
5039{
5040 return ((uentry_isVariable (u)
5041 && (u->info->var->defstate == SS_SPECIAL))
5042 || (uentry_isValid (u) && sRef_isStateSpecial (u->sref)));
5043}
5044
5045exitkind uentry_getExitCode (uentry ue)
5046{
5047 if (uentry_isFunction (ue))
5048 {
5049 return ue->info->fcn->exitCode;
5050 }
5051 else
5052 {
5053 return XK_UNKNOWN;
5054 }
5055}
5056
5057qual
5058uentry_nullPred (uentry u)
5059{
5060 llassert (uentry_isRealFunction (u));
5061
5062 if (uentry_isFunction (u))
5063 {
5064 return (u->info->fcn->nullPred);
5065 }
5066 else
5067 {
5068 return QU_UNKNOWN;
5069 }
5070}
5071
5072bool
5073uentry_possiblyNull (uentry u)
5074{
5075 return ((uentry_isVariable (u) && (nstate_possiblyNull (u->info->var->nullstate)))
5076 || (uentry_isDatatype (u) && (sRef_possiblyNull (u->sref))));
5077}
5078
5079alkind
5080uentry_getAliasKind (uentry u)
5081{
5082 if (uentry_isValid (u))
5083 {
5084 return (sRef_getAliasKind (uentry_getSref (u)));
5085 }
5086 else
5087 {
5088 return AK_UNKNOWN;
5089 }
5090}
5091
5092exkind
5093uentry_getExpKind (uentry u)
5094{
5095 if (uentry_isValid (u))
5096 {
5097 return (sRef_getExKind (uentry_getSref (u)));
5098 }
5099 else
5100 {
5101 return XO_UNKNOWN;
5102 }
5103}
5104
5105bool
5106uentry_isIter (uentry e)
5107{
5108 return (!uentry_isUndefined (e) && e->ukind == KITER);
5109}
5110
5111bool
5112uentry_isEndIter (uentry e)
5113{
5114 return (!uentry_isUndefined (e) && e->ukind == KENDITER);
5115}
5116
5117bool
5118uentry_isRealFunction (uentry e)
5119{
5120 return (uentry_isFunction (e) ||
5121 (uentry_isVariable (e) && ctype_isFunction (uentry_getType (e))));
5122}
5123
5124bool
5125uentry_hasName (uentry e)
5126{
5127 if (uentry_isValid (e))
5128 {
5129 cstring s = e->uname;
5130
5131 return (!(cstring_isEmpty (s) || cstring_equalLit (s, "...")));
5132 }
5133 else
5134 {
5135 return FALSE;
5136 }
5137}
5138
5139bool uentry_hasRealName (uentry e)
5140{
5141 return (uentry_isValid (e) && cstring_isNonEmpty (e->uname));
5142}
5143
5144
5145/*@observer@*/ globSet
5146uentry_getGlobs (uentry l)
5147{
5148 if (uentry_isInvalid (l))
5149 {
5150 return globSet_undefined;
5151 }
5152
5153 if (l->ukind != KFCN)
5154 {
5155 if (l->ukind != KITER && l->ukind != KENDITER)
5156 {
5157 if (l->ukind == KVAR)
5158 {
5159 llbug (message ("Bad call to uentry_getGlobs (var): %q (%s)",
5160 uentry_unparse (l),
5161 ekind_unparse (l->ukind)));
5162 }
5163 else
5164 {
5165 llbug (message ("Bad call to uentry_getGlobs: %q (%s)",
5166 uentry_unparse (l),
5167 ekind_unparse (l->ukind)));
5168 }
5169 }
5170 return globSet_undefined;
5171 }
5172
5173 return l->info->fcn->globs;
5174}
5175
5176/*@observer@*/ sRefSet
5177uentry_getMods (uentry l)
5178{
5179 llassert (uentry_isValid (l));
5180
5181 if (l->ukind != KFCN && l->ukind != KITER && l->ukind != KENDITER)
5182 {
5183 llcontbug (message ("Bad call to uentry_getMods: %q", uentry_unparse (l)));
5184 return sRefSet_undefined;
5185 }
5186
5187 return l->info->fcn->mods;
5188}
5189
5190ekind
5191uentry_getKind (uentry e)
5192{
5193 llassert (uentry_isValid (e));
5194
5195 return (e->ukind);
5196}
5197
5198/*@observer@*/ multiVal uentry_getConstantValue (uentry e)
5199{
5200 llassert (uentry_isEitherConstant (e));
5201
5202 return (e->info->uconst->val);
5203}
5204
5205/*@observer@*/ uentryList
5206uentry_getParams (uentry l)
5207{
5208 if (uentry_isInvalid (l)) return uentryList_undefined;
5209
5210 switch (l->ukind)
5211 {
5212 case KFCN:
5213 case KITER:
5214 {
5215 ctype ct = l->utype;
5216
5217 if (ctype_isFunction (ct))
5218 {
5219 return (ctype_argsFunction (ct));
5220 }
5221 else
5222 {
5223 return uentryList_undefined;
5224 }
5225 }
5226 case KVAR:
5227 {
5228 ctype ct = l->utype;
5229
5230 llassert (ctype_isFunction (ct));
5231 return (ctype_argsFunction (ct));
5232 }
5233 BADDEFAULT;
5234 }
5235 BADEXIT;
5236}
5237
5238/*@observer@*/ cstring
5239uentry_rawName (uentry e)
5240{
5241 if (uentry_isValid (e))
5242 {
5243 return (e->uname);
5244 }
5245 else
5246 {
5247 return cstring_undefined;
5248 }
5249}
5250
5251static cstring
5252uentry_getOptName (uentry e)
5253{
5254 cstring s = uentry_getName (e);
5255
5256 if (cstring_isDefined (s))
5257 {
5258 s = cstring_appendChar (s, ' ');
5259 }
5260
5261 return s;
5262}
5263
5264/*@only@*/ cstring
5265uentry_getName (uentry e)
5266{
5267 cstring ret = cstring_undefined;
5268
5269 if (uentry_isValid (e))
5270 {
5271
5272 if (uentry_isAnyTag (e))
5273 {
5274 ret = fixTagName (e->uname);
5275 }
5276 else if (uentry_isAnyParam (e))
5277 {
5278 ret = cstring_copy (fixParamName (e->uname));
5279 }
5280 else
5281 {
5282 ret = cstring_copy (e->uname);
5283 }
5284 }
5285
5286 return ret;
5287}
5288
5289cstring uentry_getRealName (uentry e)
5290{
5291 if (uentry_isValid (e))
5292 {
5293 if (uentry_isAnyTag (e))
5294 {
5295 return (cstring_undefined);
5296 }
5297 else
5298 {
5299 return (e->uname);
5300 }
5301 }
5302 return cstring_undefined;
5303}
5304
5305ctype uentry_getType (uentry e)
5306{
5307 if (uentry_isValid (e))
5308 {
5309 return e->utype;
5310 }
5311 else
5312 {
5313 return ctype_unknown;
5314 }
5315}
5316
5317fileloc uentry_whereLast (uentry e)
5318{
5319 fileloc loc;
5320
5321 if (uentry_isInvalid (e))
5322 {
5323 return fileloc_undefined;
5324 }
5325
5326 loc = e->whereDefined;
5327
5328 if (fileloc_isValid (loc) && !fileloc_isExternal (loc))
5329 {
5330 return loc;
5331 }
5332
5333 loc = uentry_whereDeclared (e);
5334
5335 if (fileloc_isValid (loc) && !fileloc_isExternal (loc))
5336 {
5337 return loc;
5338 }
5339
5340 loc = uentry_whereSpecified (e);
5341 return loc;
5342}
5343
5344fileloc uentry_whereEither (uentry e)
5345{
5346 if (uentry_isInvalid (e)) return fileloc_undefined;
5347
5348 if (fileloc_isDefined (e->whereDefined)
5349 && !fileloc_isExternal (e->whereDefined))
5350 {
5351 return e->whereDefined;
5352 }
5353 else if (fileloc_isDefined (e->whereDeclared))
5354 {
5355 return e->whereDeclared;
5356 }
5357 else
5358 {
5359 return e->whereSpecified;
5360 }
5361}
5362
5363fileloc uentry_whereSpecified (uentry e)
5364{
5365 if (uentry_isInvalid (e)) return fileloc_undefined;
5366
5367 return (e->whereSpecified);
5368}
5369
5370fileloc uentry_whereDefined (uentry e)
5371{
5372 if (uentry_isInvalid (e)) return fileloc_undefined;
5373
5374 return (e->whereDefined);
5375}
5376
5377fileloc uentry_whereDeclared (uentry e)
5378{
5379 if (uentry_isInvalid (e)) return fileloc_undefined;
5380
5381 return (e->whereDeclared);
5382}
5383
5384/*@observer@*/ fileloc
5385uentry_whereEarliest (uentry e)
5386{
5387 if (uentry_isInvalid (e)) return fileloc_undefined;
5388
5389 if (fileloc_isDefined (e->whereSpecified))
5390 {
5391 return (e->whereSpecified);
5392 }
5393 else if (fileloc_isDefined (e->whereDeclared))
5394 {
5395 return (e->whereDeclared);
5396 }
5397 else
5398 {
5399 return e->whereDefined;
5400 }
5401}
5402
5403void
5404uentry_setFunctionDefined (uentry e, fileloc loc)
5405{
5406 if (uentry_isValid (e))
5407 {
5408 llassert (uentry_isFunction (e));
5409
5410 if (fileloc_isUndefined (e->whereDeclared))
5411 {
5412 e->whereDeclared = fileloc_update (e->whereDeclared, loc);
5413 }
5414
5415 if (!fileloc_isDefined (e->whereDefined))
5416 {
5417 e->whereDefined = fileloc_update (e->whereDefined, loc);
5418 }
5419 }
5420}
5421
5422void
5423uentry_setDeclDef (uentry e, fileloc f)
5424{
5425 uentry_setDeclared (e, f);
5426
5427 if (!uentry_isFunction (e)
5428 && !(uentry_isVariable (e) && uentry_isExtern (e)))
5429 {
5430 uentry_setDefined (e, f);
5431 }
5432}
5433
5434void
5435uentry_setDeclaredForce (uentry e, fileloc f)
5436{
5437 llassert (uentry_isValid (e));
5438 e->whereDeclared = fileloc_update (e->whereDeclared, f);
5439}
5440
5441void
5442uentry_setDeclaredForceOnly (uentry e, fileloc f)
5443{
5444 llassert (uentry_isValid (e));
5445 fileloc_free (e->whereDeclared);
5446 e->whereDeclared = f;
5447}
5448
5449void
5450uentry_setDeclaredOnly (uentry e, /*@only@*/ fileloc f)
5451{
5452 fileloc oldloc;
5453
5454 llassert (uentry_isValid (e));
5455 oldloc = e->whereDeclared;
5456
5457 if (fileloc_isDefined (oldloc))
5458 {
5459 if (fileloc_isLib (oldloc) || fileloc_isImport (oldloc))
5460 {
5461 e->whereDeclared = f;
5462 fileloc_free (oldloc);
5463 }
5464 else
5465 {
5466 fileloc_free (f);
5467 }
5468 }
5469 else
5470 {
5471 e->whereDeclared = f;
5472 fileloc_free (oldloc);
5473 }
5474}
5475
5476void
5477uentry_setDeclared (uentry e, fileloc f)
5478{
5479 fileloc oldloc;
5480
5481 llassert (uentry_isValid (e));
5482 oldloc = e->whereDeclared;
5483
5484 if (fileloc_isDefined (oldloc))
5485 {
5486 if (fileloc_isLib (oldloc) || fileloc_isImport (oldloc))
5487 {
5488 e->whereDeclared = fileloc_update (e->whereDeclared, f);
5489 }
5490 else
5491 {
5492 ;
5493 }
5494 }
5495 else
5496 {
5497 e->whereDeclared = fileloc_update (e->whereDeclared, f);
5498 }
5499}
5500
5501void
5502uentry_clearDefined (uentry e)
5503{
5504 if (uentry_isValid (e))
5505 {
5506 e->whereDefined = fileloc_update (e->whereDefined, fileloc_undefined);
5507 }
5508}
5509
5510void
5511uentry_setDefined (uentry e, fileloc f)
5512{
5513 fileloc oldloc;
5514
5515 llassert (uentry_isValid (e));
5516 oldloc = e->whereDefined;
5517
5518 if (fileloc_isDefined (oldloc))
5519 {
5520 if (fileloc_isLib (oldloc)
5521 || fileloc_isImport (oldloc)
5522 || fileloc_isBuiltin (oldloc)
5523 || fileloc_isPreproc (oldloc))
5524 {
5525 e->whereDefined = fileloc_update (e->whereDefined, f);
5526 }
5527 else
5528 {
5529 if (fileloc_equal (oldloc, f) || context_processingMacros ())
5530 {
5531 ; /* okay */
5532 }
5533 else
5534 {
5535 if (optgenerror (FLG_REDEF,
5536 message ("%s %q redefined",
5537 ekind_capName (e->ukind),
5538 uentry_getName (e)),
5539 f))
5540 {
5541 llgenindentmsg (message ("Previous definition of %q",
5542 uentry_getName (e)),
5543 e->whereDefined);
5544 }
5545 }
5546 }
5547 }
5548 else
5549 {
5550 e->whereDefined = fileloc_update (e->whereDefined, f);
5551 }
5552}
5553
5554bool
5555uentry_isCodeDefined (uentry e)
5556{
5557 return (uentry_isValid (e) && fileloc_isDefined (e->whereDefined));
5558}
5559
5560bool
5561uentry_isDeclared (uentry e)
5562{
5563 if (uentry_isValid (e))
5564 {
5565 return (fileloc_isDefined (e->whereDeclared));
5566 }
5567
5568 return FALSE;
5569}
5570
5571sRef uentry_getSref (uentry e)
5572{
5573 /* not true, used for functions too (but shouldn't be? */
5574 /* llassertprint (e->ukind == KVAR, ("uentry_getSref: not variable!")); */
5575
5576 if (uentry_isInvalid (e)) return sRef_undefined;
5577
5578 return (e->sref);
5579}
5580
5581sRef uentry_getOrigSref (uentry e)
5582{
5583 if (uentry_isValid (e))
5584 {
5585 sRef sr = sRef_copy (uentry_getSref (e));
5586
5587 sRef_resetState (sr);
5588 sRef_clearDerived (sr);
5589
5590 if (uentry_isVariable (e))
5591 {
5592 sRef_setDefState (sr, e->info->var->defstate, fileloc_undefined);
5593 sRef_setNullState (sr, e->info->var->nullstate, fileloc_undefined);
5594 }
5595
5596 return (sr);
5597 }
5598 else
5599 {
5600 return sRef_undefined;
5601 }
5602}
5603
5604/*
5605** requires: uentry e is not in a hashed symbol table
5606*/
5607
5608void
5609uentry_setName (uentry e, /*@only@*/ cstring n)
5610{
5611 llassert (uentry_isValid (e));
5612
5613 cstring_free (e->uname);
5614 e->uname = n;
5615}
5616
5617void
5618uentry_setType (uentry e, ctype t)
5619{
5620 if (uentry_isValid (e))
5621 {
5622 e->utype = t;
5623 sRef_setType (e->sref, t);
5624 }
5625}
5626
5627void
5628uentry_resetParams (uentry ue, /*@only@*/ uentryList pn)
5629{
5630 ctype rct;
5631 ctype rettype = ctype_unknown;
5632
5633 llassert (uentry_isValid (ue));
5634
5635 rct = ctype_realType (ue->utype);
5636
5637 if (uentry_isVariable (ue) && (ctype_isFunction (rct) || ctype_isUnknown (rct)))
5638 {
5639 uentry_makeVarFunction (ue);
5640 }
5641
5642 llassert (uentry_isFunction (ue));
5643
5644 if (ctype_isFunction (rct))
5645 {
5646 rettype = ctype_returnValue (rct);
5647 }
5648
5649 ue->utype = ctype_makeNFParamsFunction (rettype, pn);
5650}
5651
5652void
5653uentry_setRefParam (uentry e)
5654{
5655
5656 if (!uentry_isVar (e))
5657 {
5658 llbug (message ("uentry_setParam: not variable: %q", uentry_unparse (e)));
5659 }
5660 else
5661 {
5662 if (e->info->var->kind == VKSEFPARAM)
5663 {
5664 e->info->var->kind = VKREFSEFPARAM;
5665 }
5666 else if (e->info->var->kind == VKSEFRETPARAM)
5667 {
5668 e->info->var->kind = VKREFSEFRETPARAM;
5669 }
5670 else if (e->info->var->kind == VKYIELDPARAM)
5671 {
5672 e->info->var->kind = VKREFYIELDPARAM;
5673 }
5674 else
5675 {
5676 e->info->var->kind = VKREFPARAM;
5677 }
5678 }
5679}
5680
5681void
5682uentry_setParam (uentry e)
5683{
5684 if (!uentry_isVar (e))
5685 {
5686 if (uentry_isElipsisMarker (e))
5687 {
5688
5689 }
5690 else
5691 {
5692 llbug (message ("uentry_setParam: not variable: %q", uentry_unparse (e)));
5693 }
5694 }
5695 else
5696 {
5697 cstring oldname;
5698
5699 if (e->info->var->kind == VKYIELDPARAM
5700 || e->info->var->kind == VKSEFPARAM
5701 || e->info->var->kind == VKSEFRETPARAM)
5702 {
5703 ;
5704 }
5705 else
5706 {
5707 e->info->var->kind = VKPARAM;
5708 }
5709
5710 oldname = e->uname;
5711 e->uname = makeParam (e->uname);
5712 cstring_free (oldname);
5713 }
5714}
5715
5716void
5717uentry_setSref (uentry e, sRef s)
5718{
5719 if (uentry_isValid (e))
5720 {
5721 if (sRef_isValid (e->sref))
5722 {
5723 sRef_mergeStateQuietReverse (e->sref, s);
5724 }
5725 else
5726 {
5727 e->sref = sRef_saveCopy (s);
5728 }
5729 }
5730}
5731
5732ctype
5733uentry_getAbstractType (uentry e)
5734{
5735 llassert (uentry_isDatatype (e));
5736
5737 /*
5738 ** This assertion removed.
5739 ** Okay to have undefined type, for system types
5740
5741 llassertprintret (!ctype_isUndefined (e->info->datatype->type),
5742 ("uentry_getAbstractType %q: undefined", uentry_unparseFull (e)),
5743 e->utype);
5744
5745 */
5746
5747 if (ctype_isUndefined (e->info->datatype->type))
5748 {
5749 return ctype_unknown;
5750 }
5751
5752 /*
5753 ** Sadly, a kludge...
5754 */
5755
5756 if (ctype_isUserBool (e->info->datatype->type)) {
5757 return ctype_bool;
5758 }
5759
5760 return e->info->datatype->type;
5761}
5762
5763ctype uentry_getRealType (uentry e)
5764{
5765 ctype ct;
5766 typeId uid = USYMIDINVALID;
5767
5768 if (uentry_isInvalid (e))
5769 {
5770 return ctype_unknown;
5771 }
5772
5773 llassertprint (uentry_isDatatype (e), ("not datatype: %s", uentry_unparse (e)));
5774
5775 if (uentry_isAnyTag (e))
5776 {
5777 return (e->utype);
5778 }
5779
5780 if (uentry_isAbstractType (e))
5781 {
5782 ct = uentry_getAbstractType (e);
5783
5784 if (ctype_isManifestBool (ct)) {
5785 return ct;
5786 }
5787
5788 llassert (ctype_isUA (ct));
5789
5790 uid = ctype_typeId (ct);
5791
5792 if (!context_hasAccess (uid))
5793 {
5794 return (ct);
5795 }
5796 }
5797
5798 ct = uentry_getType (e);
5799
5800 /* if (ctype_isUserBool (ct)) return ct; */
5801
5802 if (ctype_isManifestBool (ct)) {
5803 return ctype_bool;
5804 }
5805
5806 if (ctype_isUA (ct))
5807 {
5808 usymId iid = ctype_typeId (ct);
5809
5810 if /*@access usymId@*/ (iid == uid) /*@noaccess usymId@*/
5811 {
5812 llcontbug (message ("uentry_getRealType: recursive type! %s",
5813 ctype_unparse (ct)));
5814 return ct;
5815 }
5816 else
5817 {
5818 /* evs 2000-07-25: possible infinite recursion ? */
5819 uentry ue2 = usymtab_getTypeEntry (iid);
5820 llassertprint (ue2 != e, ("Bad recursion: %s", uentry_unparseFull (e)));
5821
5822 return uentry_getRealType (ue2);
5823 }
5824 }
5825 else
5826 {
5827 return ct;
5828 }
5829}
5830
5831ctype uentry_getForceRealType (uentry e)
5832{
5833 ctype ct;
5834 typeId uid = USYMIDINVALID;
5835
5836 if (uentry_isInvalid (e))
5837 {
5838 return ctype_unknown;
5839 }
5840
5841 llassertprint (uentry_isDatatype (e), ("not datatype: %s", uentry_unparse (e)));
5842
5843 if (uentry_isAnyTag (e))
5844 {
5845 return (e->utype);
5846 }
5847
5848 if (uentry_isAbstractType (e))
5849 {
5850 ct = uentry_getAbstractType (e);
5851 llassert (ctype_isUA (ct));
5852
5853 uid = ctype_typeId (ct);
5854 /* no check for access! */
5855 }
5856
5857 ct = uentry_getType (e);
5858
5859 /* evs 2000-07-25 */
5860 /* if (ctype_isUserBool (ct)) return ct; */
5861
5862 if (ctype_isManifestBool (ct)) {
5863 return ctype_bool;
5864 }
5865
5866 if (ctype_isUA (ct))
5867 {
5868 usymId iid = ctype_typeId (ct);
5869
5870 if /*@access usymId@*/ (iid == uid) /*@noaccess usymId@*/
5871 {
5872 llcontbug (message ("uentry_getRealType: recursive type! %s",
5873 ctype_unparse (ct)));
5874 return ct;
5875 }
5876 else
5877 {
5878 return uentry_getForceRealType (usymtab_getTypeEntry (iid));
5879 }
5880 }
5881 else
5882 {
5883 return ct;
5884 }
5885}
5886
5887uentry uentry_nameCopy (cstring name, uentry e)
5888{
5889 uentry enew = uentry_alloc ();
5890
5891 llassert (uentry_isValid (e));
5892
5893 /* enew->shallowCopy = FALSE; */
5894 enew->ukind = e->ukind;
5895 enew->uname = name;
5896 enew->utype = e->utype;
5897 enew->whereSpecified = fileloc_copy (e->whereSpecified);
5898 enew->whereDefined = fileloc_copy (e->whereDefined);
5899 enew->whereDeclared = fileloc_copy (e->whereDeclared);
5900 enew->sref = sRef_copy (e->sref);
5901 enew->used = e->used;
5902 enew->lset = FALSE;
5903 enew->isPrivate = e->isPrivate;
5904 enew->hasNameError = FALSE;
5905
5906 enew->uses = filelocList_new ();
5907
5908 enew->storageclass = e->storageclass;
5909 enew->info = uinfo_copy (e->info, e->ukind);
5910
5911 return enew;
5912}
5913
5914void
5915uentry_setDatatype (uentry e, usymId uid)
5916{
5917 llassert (uentry_isDatatype (e));
5918
5919 if (uentry_isAbstractType (e))
5920 {
5921 e->info->datatype->type = ctype_createAbstract (uid);
5922 }
5923 else
5924 {
5925 e->info->datatype->type = ctype_createUser (uid);
5926 }
5927}
5928
5929static void
5930uentry_setSpecDef (/*@special@*/ uentry e, /*@keep@*/ fileloc f)
5931 /*@defines e->whereSpecified, e->whereDeclared, e->whereDefined@*/
5932 /*@modifies e@*/
5933{
5934 llassert (uentry_isValid (e));
5935
5936 if (fileloc_isSpec (f) || fileloc_isImport (f))
5937 {
5938 e->whereSpecified = f;
5939 e->whereDeclared = fileloc_undefined;
5940 e->whereDefined = fileloc_undefined;
5941 }
5942 else
5943 {
5944 e->whereSpecified = fileloc_undefined;
5945 e->whereDeclared = f;
5946 e->whereDefined = fileloc_undefined;
5947 }
5948}
5949
5950static void
5951ucinfo_free (/*@only@*/ ucinfo u)
5952{
5953 multiVal_free (u->val);
5954 sfree (u);
5955}
5956
5957static void
5958uvinfo_free (/*@only@*/ uvinfo u)
5959{
5960 sfree (u);
5961}
5962
5963static void
5964udinfo_free (/*@only@*/ udinfo u)
5965{
5966 sfree (u);
5967}
5968
5969static void
5970ufinfo_free (/*@only@*/ ufinfo u)
5971{
5972 globSet_free (u->globs);
5973 sRefSet_free (u->mods);
5974 specialClauses_free (u->specclauses);
5975
bb25bea6 5976 /*@i33*/
5977 /*fix up if this is the right way to handle this --drl*/
2934b455 5978 if (u->preconditions != NULL)
bb25bea6 5979 constraintList_free(u->preconditions);
2934b455 5980 if (u->postconditions != NULL)
bb25bea6 5981 constraintList_free(u->postconditions);
5982
616915dd 5983 sfree (u);
5984}
5985
5986static void
5987uiinfo_free (/*@only@*/ uiinfo u)
5988{
5989 sfree (u);
5990}
5991
5992static void
5993ueinfo_free (/*@only@*/ ueinfo u)
5994{
5995 sfree (u);
5996}
5997
5998static /*@only@*/ ucinfo
5999ucinfo_copy (ucinfo u)
6000{
6001 ucinfo ret = (ucinfo) dmalloc (sizeof (*ret));
6002
6003 ret->val = multiVal_copy (u->val);
6004 ret->access = u->access;
6005
6006 return ret;
6007}
6008
6009static /*@only@*/ uvinfo
6010uvinfo_copy (uvinfo u)
6011{
6012 uvinfo ret = (uvinfo) dmalloc (sizeof (*ret));
6013
6014 ret->kind = u->kind;
6015 ret->nullstate = u->nullstate;
6016 ret->defstate = u->defstate;
6017 ret->checked = u->checked;
6018 //make sure line ok
6019 //ret->bufinfo = u->bufinfo;
6020 /*@i334@*/ return ret;
6021}
6022
6023static /*@only@*/ udinfo
6024udinfo_copy (udinfo u)
6025{
6026 udinfo ret = (udinfo) dmalloc (sizeof (*ret));
6027
6028 ret->abs = u->abs;
6029 ret->mut = u->mut;
6030 ret->type = u->type;
6031
6032 return ret;
6033}
6034
6035static /*@only@*/ ufinfo
6036ufinfo_copy (ufinfo u)
6037{
6038 ufinfo ret = (ufinfo) dmalloc (sizeof (*ret));
6039
6040 ret->hasGlobs = u->hasGlobs;
6041 ret->hasMods = u->hasMods;
6042 ret->exitCode = u->exitCode;
6043 ret->specialCode = u->specialCode;
6044 ret->nullPred = u->nullPred;
6045 ret->access = u->access;
6046 ret->globs = globSet_newCopy (u->globs);
6047 ret->mods = sRefSet_newCopy (u->mods);
6048 ret->defparams = u->defparams;
6049 ret->specclauses = specialClauses_copy (u->specclauses);
6050
6051 /*drl 11 30 2000 */
2934b455 6052 /* change 6/8/01 */
6053
6054 if (u->preconditions != NULL)
6055 ret->preconditions = constraintList_copy(u->preconditions);
6056 else
6057 ret->preconditions = NULL;
616915dd 6058 /* end drl */
616915dd 6059
2934b455 6060 if (u->postconditions != NULL)
6061 ret->postconditions = constraintList_copy(u->postconditions);
6062 else
6063 ret->postconditions = NULL;
616915dd 6064 /* end drl */
6065
6066 return ret;
6067}
6068
6069static /*@only@*/ uiinfo
6070uiinfo_copy (uiinfo u)
6071{
6072 uiinfo ret = (uiinfo) dmalloc (sizeof (*ret));
6073
6074 ret->access = u->access;
6075 ret->globs = globSet_newCopy (u->globs);
6076 ret->mods = sRefSet_newCopy (u->mods);
6077
6078 return (ret);
6079}
6080
6081static /*@only@*/ ueinfo
6082ueinfo_copy (ueinfo u)
6083{
6084 ueinfo ret = (ueinfo) dmalloc (sizeof (*ret));
6085
6086 ret->access = u->access;
6087 return ret;
6088}
6089
6090static void
6091uinfo_free (uinfo u, ekind kind)
6092{
6093 switch (kind)
6094 {
6095 case KENUMCONST:
6096 case KCONST: ucinfo_free (u->uconst); break;
6097 case KVAR: uvinfo_free (u->var); break;
6098 case KSTRUCTTAG:
6099 case KUNIONTAG:
6100 case KENUMTAG:
6101 case KDATATYPE: udinfo_free (u->datatype); break;
6102 case KFCN: ufinfo_free (u->fcn); break;
6103 case KITER: uiinfo_free (u->iter); break;
6104 case KENDITER: ueinfo_free (u->enditer); break;
6105 case KELIPSMARKER: break;
6106 case KINVALID: break;
6107 }
6108
6109 sfree (u);
6110}
6111
6112static /*@only@*/ /*@null@*/ uinfo
6113uinfo_copy (uinfo u, ekind kind)
6114{
6115 if (kind == KELIPSMARKER || kind == KINVALID)
6116 {
6117 return NULL;
6118 }
6119 else
6120 {
6121 uinfo ret = (uinfo) dmalloc (sizeof (*ret));
6122
6123 switch (kind)
6124 {
6125 case KENUMCONST:
6126 case KCONST: ret->uconst = ucinfo_copy (u->uconst); break;
6127 case KVAR: ret->var = uvinfo_copy (u->var); break;
6128 case KSTRUCTTAG:
6129 case KUNIONTAG:
6130 case KENUMTAG:
6131 case KDATATYPE: ret->datatype = udinfo_copy (u->datatype); break;
6132 case KFCN: ret->fcn = ufinfo_copy (u->fcn); break;
6133 case KITER: ret->iter = uiinfo_copy (u->iter); break;
6134 case KENDITER: ret->enditer = ueinfo_copy (u->enditer); break;
6135 BADDEFAULT;
6136 }
6137 return ret;
6138 }
6139}
6140
6141static void
6142uentry_reallyFree (/*@notnull@*/ /*@only@*/ uentry e)
6143{
6144 filelocList_free (e->uses);
6145 cstring_free (e->uname);
6146
6147 uinfo_free (e->info, e->ukind);
6148
6149 fileloc_free (e->whereSpecified);
6150 fileloc_free (e->whereDefined);
6151 fileloc_free (e->whereDeclared);
6152
6153 nuentries--;
6154 sfree (e);
6155 }
6156
6157extern void uentry_markOwned (/*@owned@*/ uentry u)
6158{
6159 sfreeEventually (u);
6160}
6161
6162void
6163uentry_free (/*@only@*/ uentry e)
6164{
6165 if (uentry_isValid (e) && !uentry_isElipsisMarker (e))
6166 {
6167 uentry_reallyFree (e);
6168 }
6169}
6170
6171/*
6172** For uentry's in the global or file scope
6173*/
6174
6175void
6176uentry_freeComplete (/*@only@*/ uentry e)
6177{
6178 if (uentry_isValid (e) && !uentry_isElipsisMarker (e))
6179 {
6180 /*@i@*/ sRef_free (e->sref);
6181 e->sref = sRef_undefined;
6182 uentry_reallyFree (e);
6183 }
6184}
6185
6186/*
6187** requires old->kind != new->kind, old->uname = new->uname
6188*/
6189
6190static void
6191KindConformanceError (/*@unique@*/ uentry old, uentry unew, bool mustConform)
6192{
6193 llassert (uentry_isValid (old));
6194 llassert (uentry_isValid (unew));
6195
6196 if (uentry_isEitherConstant (unew)
6197 && (fileloc_isPreproc (uentry_whereDeclared (old))
6198 || ctype_isUnknown (old->utype))
6199 && !uentry_isSpecified (old))
6200 {
6201 ; /* no error */
6202 }
6203 else
6204 {
6205 if (mustConform)
6206 {
6207 if (!uentry_isDeclared (old))
6208 {
6209 if (uentry_isSpecified (old))
6210 {
6211 if (uentry_isSpecified (unew))
6212 {
6213 llbuglit ("Respecification!");
6214 }
6215 else if (uentry_isDeclared (unew))
6216 {
6217 if (optgenerror
6218 (FLG_INCONDEFS,
6219 message ("%s %q inconsistently declared as %s: %t",
6220 ekind_capName (old->ukind),
6221 uentry_getName (unew),
6222 ekind_unparseLong (unew->ukind),
6223 unew->utype),
6224 uentry_whereDeclared (unew)))
6225 {
6226 uentry_showWhereLast (old);
6227 }
6228 }
6229 else
6230 {
6231 BADEXIT;
6232 }
6233 }
6234 else
6235 {
6236 if (optgenerror
6237 (FLG_INCONDEFS,
6238 message ("%s %q inconsistently declared as %s: %t",
6239 ekind_capName (old->ukind),
6240 uentry_getName (unew),
6241 ekind_unparseLong (unew->ukind),
6242 unew->utype),
6243 uentry_whereDeclared (unew)))
6244 {
6245 uentry_showWhereLast (old);
6246 }
6247 }
6248 }
6249 else
6250 {
6251 llassert (uentry_isDeclared (unew));
6252
6253 if (optgenerror
6254 (FLG_INCONDEFS,
6255 message ("%s %q inconsistently redeclared as %s",
6256 ekind_capName (old->ukind),
6257 uentry_getName (unew),
6258 ekind_unparseLong (unew->ukind)),
6259 uentry_whereDeclared (unew)))
6260 {
6261 uentry_showWhereLast (old);
6262 }
6263 }
6264 }
6265 }
6266
6267 uentry_copyInto (old, unew);
6268}
6269
6270/*
6271** def is the definition of spec, modifies spec
6272**
6273** reports any inconsistencies
6274** returns the summary of all available information
6275** if spec and def are inconsistent, def is returned
6276*/
6277
6278void
6279uentry_showWhereLast (uentry spec)
6280{
6281 if (uentry_isValid (spec))
6282 {
6283 if (fileloc_isDefined (spec->whereDefined)
6284 && !fileloc_isLib (spec->whereDefined)
6285 && !fileloc_isPreproc (spec->whereDefined))
6286 {
6287 llgenindentmsg (message ("Previous definition of %q: %t",
6288 uentry_getName (spec),
6289 uentry_getType (spec)),
6290 uentry_whereDefined (spec));
6291 }
6292 else if (uentry_isDeclared (spec))
6293 {
6294 llgenindentmsg (message ("Previous declaration of %q: %t",
6295 uentry_getName (spec),
6296 uentry_getType (spec)),
6297 uentry_whereDeclared (spec));
6298 }
6299 else if (uentry_isSpecified (spec))
6300 {
6301 if (uentry_hasName (spec))
6302 {
6303 llgenindentmsg (message ("Specification of %q: %t",
6304 uentry_getName (spec),
6305 uentry_getType (spec)),
6306 uentry_whereSpecified (spec));
6307 }
6308 else
6309 {
6310 llgenindentmsg (message ("Specification: %t", uentry_getType (spec)),
6311 uentry_whereSpecified (spec));
6312 }
6313 }
6314 else
6315 {
6316 /* nothing to show */
6317 }
6318 }
6319}
6320
6321void
6322uentry_showDefSpecInfo (uentry ce, fileloc fwhere)
6323{
6324 fileloc loc = uentry_whereDefined (ce);
6325
6326 if (fileloc_isUser (loc) && !fileloc_equal (loc, fwhere))
6327 {
6328 llgenindentmsg (message ("Definition of %q", uentry_getName (ce)),
6329 loc);
6330 }
6331
6332 loc = uentry_whereSpecified (ce);
6333
6334 if (fileloc_isUser (loc) && !fileloc_equal (loc, fwhere))
6335 {
6336 llgenindentmsg (message ("Specification of %q", uentry_getName (ce)),
6337 loc);
6338 }
6339}
6340
6341void uentry_showWhereLastExtra (uentry spec, cstring extra)
6342{
6343 if (uentry_isDeclared (spec))
6344 {
6345 llgenindentmsg (message ("Previous declaration of %q: %q",
6346 uentry_getName (spec), extra),
6347 uentry_whereDeclared (spec));
6348 }
6349 else if (uentry_isSpecified (spec))
6350 {
6351 llgenindentmsg (message ("Specification of %q: %q",
6352 uentry_getName (spec), extra),
6353 uentry_whereSpecified (spec));
6354 }
6355 else
6356 {
6357 cstring_free (extra);
6358 }
6359}
6360
6361void
6362uentry_showWhereDeclared (uentry spec)
6363{
6364 if (uentry_isDeclared (spec))
6365 {
6366 if (uentry_hasName (spec))
6367 {
6368 llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
6369 uentry_whereDeclared (spec));
6370 }
6371 else
6372 {
6373 llgenindentmsg (cstring_makeLiteral ("Declaration"), uentry_whereDeclared (spec));
6374 }
6375 }
6376 else if (uentry_isSpecified (spec))
6377 {
6378 if (uentry_hasName (spec))
6379 {
6380 llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
6381 uentry_whereSpecified (spec));
6382 }
6383 else
6384 {
6385 llgenindentmsg (cstring_makeLiteral ("Specification"), uentry_whereSpecified (spec));
6386 }
6387 }
6388 else
6389 {
6390 /* nothing to show */
6391 }
6392
6393}
6394
6395void
6396uentry_showWhereAny (uentry spec)
6397{
6398 if (uentry_isDeclared (spec))
6399 {
6400 if (uentry_hasName (spec))
6401 {
6402 llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
6403 uentry_whereDeclared (spec));
6404 }
6405 else
6406 {
6407 llgenindentmsg (cstring_makeLiteral ("Declaration"), uentry_whereDeclared (spec));
6408 }
6409 }
6410 else if (uentry_isSpecified (spec))
6411 {
6412 if (uentry_hasName (spec))
6413 {
6414 llgenindentmsg (message ("Specification of %q",
6415 uentry_getName (spec)),
6416 uentry_whereSpecified (spec));
6417 }
6418 else
6419 {
6420 llgenindentmsg (cstring_makeLiteral ("Specification"),
6421 uentry_whereSpecified (spec));
6422 }
6423 }
6424 else if (fileloc_isDefined (uentry_whereDefined (spec)))
6425 {
6426 if (uentry_hasName (spec))
6427 {
6428 llgenindentmsg (message ("Definition of %q", uentry_getName (spec)),
6429 uentry_whereDefined (spec));
6430 }
6431 else
6432 {
6433 llgenindentmsg (cstring_makeLiteral ("Definition"), uentry_whereDefined (spec));
6434 }
6435 }
6436 else
6437 {
6438 /* nothing to show */
6439 }
6440}
6441
6442void
6443uentry_showWhereDefined (uentry spec)
6444{
6445 if (uentry_isCodeDefined (spec))
6446 {
6447 llgenindentmsg (message ("Previous definition of %q", uentry_getName (spec)),
6448 uentry_whereDefined (spec));
6449 }
6450}
6451
6452void
6453uentry_showWhereLastPlain (uentry spec)
6454{
6455 if (uentry_isDeclared (spec))
6456 {
6457 llgenindentmsg (message ("Previous declaration of %q", uentry_getName (spec)),
6458 uentry_whereDeclared (spec));
6459 }
6460 else if (uentry_isSpecified (spec))
6461 {
6462 llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
6463 uentry_whereSpecified (spec));
6464 }
6465 else
6466 {
6467 }
6468}
6469
6470static void
6471uentry_showWhereLastVal (uentry spec, cstring val)
6472{
6473 if (uentry_isDeclared (spec))
6474 {
6475 llgenindentmsg (message ("Previous declaration of %q: %s",
6476 uentry_getName (spec), val),
6477 uentry_whereDeclared (spec));
6478 }
6479 else if (uentry_isSpecified (spec))
6480 {
6481 llgenindentmsg (message ("Specification of %q: %s",
6482 uentry_getName (spec), val),
6483 uentry_whereSpecified (spec));
6484 }
6485 else
6486 {
6487 }
6488}
6489
6490void
6491uentry_showWhereSpecified (uentry spec)
6492{
6493 if (uentry_isSpecified (spec))
6494 {
6495 if (uentry_hasName (spec))
6496 {
6497 llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
6498 uentry_whereSpecified (spec));
6499 }
6500 else
6501 {
6502 llgenindentmsg (cstring_makeLiteral ("Specification"),
6503 uentry_whereSpecified (spec));
6504 }
6505 }
6506 else if (uentry_isDeclared (spec))
6507 {
6508 llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
6509 uentry_whereDeclared (spec));
6510 }
6511 else
6512 {
6513 /* nothing to show */
6514 }
6515}
6516
6517void
6518uentry_showWhereSpecifiedExtra (uentry spec, cstring s)
6519{
6520 if (uentry_isSpecified (spec))
6521 {
6522 if (uentry_hasName (spec))
6523 {
6524 llgenindentmsg (message ("Specification of %q: %q",
6525 uentry_getName (spec), s),
6526 uentry_whereSpecified (spec));
6527 }
6528 else
6529 {
6530 llgenindentmsg (message ("Specification: %q", s),
6531 uentry_whereSpecified (spec));
6532 }
6533 }
6534 else if (uentry_isDeclared (spec))
6535 {
6536 llgenindentmsg (message ("Declaration of %q: %q",
6537 uentry_getName (spec), s),
6538 uentry_whereDeclared (spec));
6539 }
6540 else
6541 {
6542 llgenindentmsg (message ("Previous: %q", s),
6543 uentry_whereLast (spec));
6544 }
6545}
6546
6547/*
6548**
6549*/
6550
6551static void
6552checkStructConformance (uentry old, uentry unew)
6553{
6554 ctype oldr, newr;
6555 uentryList fold, fnew;
6556
6557 /*
6558 ** requires: types of old and new are structs or unions
6559 */
6560
6561 llassert (uentry_isValid (old));
6562 llassert (uentry_isValid (unew));
6563
6564 oldr = ctype_realType (old->utype);
6565 fold = ctype_getFields (oldr);
6566
6567 newr = ctype_realType (unew->utype);
6568 fnew = ctype_getFields (newr);
6569
6570 if (!uentryList_matchFields (fold, fnew))
6571 {
6572 if (fileloc_equal (uentry_whereLast (old),
6573 uentry_whereLast (unew)))
6574 {
6575 ; /* cheat! */
6576 }
6577 else
6578 {
6579 if (optgenerror
6580 (FLG_MATCHFIELDS,
6581 message ("%q %q %rdeclared with fields { %q }, %s "
6582 "with fields { %q }",
6583 cstring_makeLiteral (ctype_isStruct (newr) ? "Structure": "Union"),
6584 uentry_getName (old),
6585 uentry_isDeclared (old),
6586 uentryList_unparseAbbrev (fnew),
6587 uentry_specOrDefName (old),
6588 uentryList_unparseAbbrev (fold)),
6589 uentry_whereDeclared (unew)))
6590 {
6591 uentry_showWhereLastPlain (old);
6592 uentryList_showFieldDifference (fold, fnew);
6593 }
6594 }
6595
6596 old->utype = unew->utype;
6597 }
6598}
6599
6600static void
6601checkEnumConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
6602{
6603 /*
6604 ** requires old and new are enums
6605 */
6606
6607 ctype rold = ctype_realType (old->utype);
6608 ctype rnew = ctype_realType (unew->utype);
6609 enumNameList eold = ctype_elist (rold);
6610 enumNameList enew = ctype_elist (rnew);
6611
6612 if (!enumNameList_match (eold, enew))
6613 {
6614 if (optgenerror
6615 (FLG_MATCHFIELDS,
6616 message ("Enum %q declared with members { %q } but "
6617 "specified with members { %q }",
6618 uentry_getName (old),
6619 enumNameList_unparse (enew),
6620 enumNameList_unparse (eold)),
6621 uentry_whereDeclared (unew)))
6622 {
6623 uentry_showWhereSpecified (old);
6624 old->utype = unew->utype;
6625 }
6626 }
6627}
6628
6629/*
6630** either oldCurrent or newCurrent may be undefined!
6631*/
6632
6633static void
6634paramTypeError (uentry old, uentry oldCurrent, ctype oldType,
6635 uentry unew, uentry newCurrent, ctype newType,
6636 int paramno)
6637{
6638 bool hasError = FALSE;
6639
6640 if (uentry_isValid (newCurrent) && uentry_isDeclared (newCurrent))
6641 {
6642 if (uentry_hasName (newCurrent))
6643 {
6644 hasError = optgenerror
6645 (FLG_TYPE,
6646 message ("Parameter %d, %q, of function %q has inconsistent type: "
6647 "declared %t, %s %t",
6648 paramno + 1, uentry_getName (newCurrent),
6649 uentry_getName (unew),
6650 newType, uentry_specOrDefName (old), oldType),
6651 uentry_whereDeclared (newCurrent));
6652 }
6653 else
6654 {
6655 hasError = optgenerror
6656 (FLG_TYPE,
6657 message ("Parameter %d of function %q has inconsistent type: "
6658 "declared %t, %s %t",
6659 paramno + 1, uentry_getName (unew),
6660 newType, uentry_specOrDefName (old), oldType),
6661 uentry_whereDeclared (newCurrent));
6662
6663 DPRINTF (("type: %s / %s",
6664 ctype_unparse (newType),
6665 ctype_unparse (ctype_realType (newType))));
6666 }
6667 }
6668 else
6669 {
6670 if (uentry_isDeclared (unew))
6671 {
6672 hasError = optgenerror
6673 (FLG_TYPE,
6674 message ("Parameter %d of function %s has inconsistent type: "
6675 "declared %t, %s %t",
6676 paramno + 1, unew->uname,
6677 newType, uentry_specOrDefName (old), oldType),
6678 uentry_whereDeclared (unew));
6679 }
6680 else
6681 {
6682 hasError = optgenerror
6683 (FLG_TYPE,
6684 message ("Parameter %d of function %s has inconsistent type: "
6685 "declared %t, %s %t",
6686 paramno + 1, unew->uname,
6687 newType, uentry_specOrDefName (old), oldType),
6688 uentry_whereDeclared (unew));
6689 }
6690 }
6691
6692 if (hasError)
6693 {
6694 if (!uentry_isUndefined (oldCurrent))
6695 {
6696 if (!uentry_isUndefined (newCurrent)
6697 && cstring_equal (uentry_rawName (newCurrent), uentry_rawName (oldCurrent)))
6698 {
6699 uentry_showWhereLast (oldCurrent);
6700 }
6701 else
6702 {
6703 uentry_showWhereLastPlain (old);
6704 }
6705
6706 uentry_setType (oldCurrent, newType);
6707 }
6708 else
6709 {
6710 uentry_showWhereLastPlain (old);
6711 }
6712 }
6713}
6714
6715static void
6716nargsError (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
6717{
6718 if (optgenerror
6719 (FLG_TYPE,
6720 message ("Function %s %rdeclared with %d arg%p, %s with %d",
6721 unew->uname,
6722 uentry_isDeclared (old),
6723 uentryList_size (uentry_getParams (unew)),
6724 uentry_specOrDefName (old),
6725 uentryList_size (uentry_getParams (old))),
6726 uentry_whereDeclared (unew)))
6727 {
6728 uentry_showWhereLastPlain (old);
6729 }
6730}
6731
6732static void
6733returnValueError (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
6734{
6735 if (optgenerror
6736 (FLG_INCONDEFS,
6737 message ("Function %s inconsistently %rdeclared to return %t",
6738 unew->uname,
6739 uentry_isDeclared (old),
6740 ctype_returnValue (unew->utype)),
6741 uentry_whereDeclared (unew)))
6742 {
6743 uentry_showWhereLastVal (old, ctype_unparse (ctype_returnValue (old->utype)));
6744 }
6745}
6746
6747static cstring paramStorageName (uentry ue)
6748{
6749 return (cstring_makeLiteralTemp (uentry_isParam (ue) ? "param" : "storage"));
6750}
6751
6752static cstring fcnErrName (uentry ue)
6753{
6754 return (cstring_makeLiteralTemp (uentry_isFunction (ue) ? "to return" : "as"));
6755}
6756
6757extern /*@observer@*/ cstring uentry_checkedName (uentry ue)
6758{
6759 if (uentry_isVar (ue))
6760 {
6761 return (checkedName (ue->info->var->checked));
6762 }
6763 else
6764 {
6765 return (cstring_makeLiteralTemp ("<checked invalid>"));
6766 }
6767}
6768
6769static cstring checkedName (chkind checked)
6770{
6771 switch (checked)
6772 {
6773 case CH_UNKNOWN: return (cstring_makeLiteralTemp ("unknown"));
6774 case CH_UNCHECKED: return (cstring_makeLiteralTemp ("unchecked"));
6775 case CH_CHECKED: return (cstring_makeLiteralTemp ("checked"));
6776 case CH_CHECKMOD: return (cstring_makeLiteralTemp ("checkmod"));
6777 case CH_CHECKEDSTRICT: return (cstring_makeLiteralTemp ("checkedstrict"));
6778 }
6779 BADEXIT;
6780}
6781
6782static
6783void checkNullState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, bool mustConform, bool completeConform)
6784{
6785 nstate oldState;
6786 nstate newState;
6787
6788 if (uentry_isVar (unew))
6789 {
6790 llassert (uentry_isVar (old));
6791
6792 oldState = old->info->var->nullstate;
6793 newState = unew->info->var->nullstate;
6794 }
6795 else
6796 {
6797 oldState = sRef_getNullState (old->sref);
6798 newState = sRef_getNullState (unew->sref);
6799 }
6800
6801 if (oldState == NS_ABSNULL)
6802 {
6803 if (uentry_isVar (old))
6804 {
6805 old->info->var->nullstate = newState;
6806 }
6807
6808 sRef_mergeNullState (old->sref, newState);
6809 }
6810 else if (newState == NS_UNKNOWN)
6811 {
6812 if (completeConform && newState != oldState
6813 && uentry_isReallySpecified (old))
6814 {
6815 if (optgenerror
6816 (FLG_NEEDSPEC,
6817 message ("%s %q specified as %s, but declared without %s qualifier",
6818 ekind_capName (unew->ukind),
6819 uentry_getName (unew),
6820 nstate_unparse (oldState),
6821 nstate_unparse (oldState)),
6822 uentry_whereDeclared (unew)))
6823 {
6824 uentry_showWhereSpecified (old);
6825 }
6826 }
6827
6828 if (uentry_isVar (unew))
6829 {
6830 unew->info->var->nullstate = oldState;
6831 }
6832
6833 sRef_mergeNullState (unew->sref, oldState);
6834 }
6835 else if (newState == NS_POSNULL)
6836 {
6837 if (oldState == NS_MNOTNULL
6838 && (ctype_isUA (unew->utype)
6839 || (uentry_isFunction (unew)
6840 && ctype_isUA (ctype_returnValue (unew->utype)))))
6841 {
6842 if (uentry_isVar (unew))
6843 {
6844 unew->info->var->nullstate = oldState;
6845 }
6846
6847 sRef_mergeNullState (unew->sref, oldState);
6848 }
6849 else
6850 {
6851 if (oldState == NS_NOTNULL || oldState == NS_MNOTNULL
6852 || oldState == NS_UNKNOWN)
6853 {
6854 if (mustConform)
6855 {
6856 if (optgenerror
6857 (FLG_INCONDEFS,
6858 message
6859 ("%s %q inconsistently %rdeclared %s possibly null storage, "
6860 "%s %q qualifier",
6861 uentry_ekindName (unew),
6862 uentry_getName (unew),
6863 uentry_isDeclared (old),
6864 fcnErrName (unew),
6865 uentry_specOrDefName (old),
6866 cstring_makeLiteral (oldState == NS_MNOTNULL ? "with notnull" : "without null")),
6867 uentry_whereDeclared (unew)))
6868 {
6869 uentry_showWhereSpecified (old);
6870 }
6871 }
6872 }
6873
6874 if (uentry_isVar (old))
6875 {
6876 old->info->var->nullstate = newState;
6877 }
6878
6879 sRef_mergeNullState (old->sref, newState);
6880 }
6881 }
6882 else if (newState == NS_MNOTNULL)
6883 {
6884 if (oldState != NS_MNOTNULL)
6885 {
6886 if (mustConform)
6887 {
6888 if (optgenerror
6889 (FLG_INCONDEFS,
6890 message ("%s %q inconsistently %rdeclared %s notnull storage, "
6891 "%s without notnull qualifier",
6892 uentry_ekindName (unew),
6893 uentry_getName (unew),
6894 uentry_isDeclared (old),
6895 fcnErrName (unew),
6896 uentry_specOrDefName (old)),
6897 uentry_whereDeclared (unew)))
6898 {
6899 uentry_showWhereSpecified (old);
6900 }
6901 }
6902
6903 if (uentry_isVar (old))
6904 {
6905 old->info->var->nullstate = newState;
6906 }
6907
6908 sRef_mergeNullState (old->sref, newState);
6909 }
6910 }
6911 else
6912 {
6913 if (uentry_isVar (unew))
6914 {
6915 unew->info->var->nullstate = oldState;
6916 }
6917
6918 sRef_mergeNullState (unew->sref, oldState);
6919 }
6920}
6921
6922static
6923void checkDefState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
6924 bool mustConform, bool completeConform)
6925{
6926 sstate oldState;
6927 sstate newState;
6928 bool vars = FALSE;
6929
6930 if (uentry_isVar (old) && uentry_isVar (unew))
6931 {
6932 oldState = old->info->var->defstate;
6933 newState = unew->info->var->defstate;
6934 vars = TRUE;
6935 }
6936 else
6937 {
6938 oldState = sRef_getDefState (old->sref);
6939 newState = sRef_getDefState (unew->sref);
6940 }
6941
6942 if (newState != oldState && newState != SS_UNKNOWN && newState != SS_DEFINED)
6943 {
6944 if (mustConform)
6945 {
6946 if (optgenerror
6947 (FLG_INCONDEFS,
6948 message ("%s %q inconsistently %rdeclared %s %s %s, "
6949 "%s %s %s %s",
6950 uentry_ekindName (unew),
6951 uentry_getName (unew),
6952 uentry_isDeclared (old),
6953 fcnErrName (unew),
6954 sstate_unparse (newState),
6955 paramStorageName (unew),
6956 uentry_specOrDefName (old),
6957 fcnErrName (unew),
6958 sstate_unparse (oldState),
6959 paramStorageName (unew)),
6960 uentry_whereDeclared (unew)))
6961 {
6962 uentry_showWhereSpecified (old);
6963 }
6964 }
6965
6966 if (vars) old->info->var->defstate = newState;
6967 sRef_setDefState (old->sref, newState, uentry_whereDeclared (unew));
6968 }
6969 else
6970 {
6971 if (completeConform
6972 && (newState != oldState) && (oldState != SS_DEFINED)
6973 && uentry_isReallySpecified (old))
6974 {
6975 if (optgenerror
6976 (FLG_NEEDSPEC,
6977 message ("%s %q specified as %s, but declared without %s qualifier",
6978 ekind_capName (unew->ukind),
6979 uentry_getName (unew),
6980 sstate_unparse (oldState),
6981 sstate_unparse (oldState)),
6982 uentry_whereDeclared (unew)))
6983 {
6984 uentry_showWhereSpecified (old);
6985 }
6986 }
6987
6988 if (vars) unew->info->var->defstate = oldState;
6989 sRef_setDefState (unew->sref, oldState, uentry_whereDeclared (unew));
6990 }
6991}
6992
6993static void
6994 checkAliasState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
6995 bool mustConform, bool completeConform)
6996{
6997 alkind newKind;
6998 alkind oldKind;
6999
7000 oldKind = sRef_getAliasKind (old->sref);
7001 newKind = sRef_getAliasKind (unew->sref);
7002
7003 if (alkind_isImplicit (newKind)
7004 || (alkind_isRefCounted (newKind) && !uentry_isDatatype (unew)))
7005 {
7006 if (completeConform && !alkind_equal (newKind, oldKind)
7007 && uentry_isReallySpecified (old))
7008 {
7009 if (optgenerror
7010 (FLG_NEEDSPEC,
7011 message ("%s %q specified as %s, but declared without "
7012 "explicit alias qualifier",
7013 ekind_capName (unew->ukind),
7014 uentry_getName (unew),
7015 alkind_unparse (oldKind)),
7016 uentry_whereDeclared (unew)))
7017 {
7018 uentry_showWhereSpecified (old);
7019 }
7020 }
7021
7022 /*
7023 ** This really shouldn't be necessary, but it is!
7024 ** Function params (?) use new here.
7025 */
7026
7027 sRef_setAliasKind (unew->sref, oldKind, uentry_whereDeclared (unew));
7028 return;
7029 }
7030
7031 if (alkind_isKnown (newKind))
7032 {
7033 if (!alkind_equal (oldKind, newKind))
7034 {
7035 if (alkind_isKnown (oldKind))
7036 {
7037 if (mustConform &&
7038 optgenerror
7039 (FLG_INCONDEFS,
7040 message ("%s %q inconsistently %rdeclared %s %s storage, "
7041 "%s as %s storage",
7042 uentry_ekindName (unew),
7043 uentry_getName (unew),
7044 uentry_isDeclared (old),
7045 fcnErrName (unew),
7046 alkind_unparse (newKind),
7047 uentry_specOrDefName (old),
7048 alkind_unparse (oldKind)),
7049 uentry_whereDeclared (unew)))
7050 {
7051 uentry_showWhereSpecified (old);
7052
7053 sRef_setAliasKind (old->sref, AK_ERROR,
7054 uentry_whereDeclared (unew));
7055 }
7056 else
7057 {
7058 sRef_setAliasKind (old->sref, newKind,
7059 uentry_whereDeclared (unew));
7060 }
7061 }
7062 else
7063 {
7064 if (!(alkind_isImplicit (newKind)))
7065 {
7066 if (mustConform &&
7067 !uentry_isFunction (unew) &&
7068 optgenerror
7069 (FLG_INCONDEFS,
7070 message ("%s %q inconsistently %rdeclared %s %s storage, "
7071 "implicitly %s as temp storage",
7072 uentry_ekindName (unew),
7073 uentry_getName (unew),
7074 uentry_isDeclared (old),
7075 fcnErrName (unew),
7076 alkind_unparse (newKind),
7077 uentry_specOrDefName (old)),
7078 uentry_whereDeclared (unew)))
7079 {
7080 uentry_showWhereSpecified (old);
7081 oldKind = AK_ERROR;
7082 }
7083
7084 sRef_setAliasKind (old->sref, newKind,
7085 uentry_whereDeclared (unew));
7086 }
7087 else /* newKind is temp or refcounted */
7088 {
7089 ;
7090 }
7091 }
7092 }
7093 }
7094 else /* newKind unknown */
7095 {
7096 ;
7097 }
7098}
7099
7100static void
7101 checkExpState(/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
7102 bool mustConform, bool completeConform)
7103{
7104 exkind newKind;
7105 exkind oldKind;
7106
7107 oldKind = sRef_getExKind (old->sref);
7108 newKind = sRef_getExKind (unew->sref);
7109
7110 if (exkind_isKnown (newKind))
7111 {
7112 if (oldKind != newKind)
7113 {
7114 if (exkind_isKnown (oldKind))
7115 {
7116 if (mustConform &&
7117 optgenerror
7118 (FLG_INCONDEFS,
7119 message ("%s %q inconsistently %rdeclared %s %s, %s as %s",
7120 uentry_ekindName (unew),
7121 uentry_getName (unew),
7122 uentry_isDeclared (old),
7123 fcnErrName (unew),
7124 exkind_unparse (newKind),
7125 uentry_specOrDefName (old),
7126 exkind_unparse (oldKind)),
7127 uentry_whereDeclared (unew)))
7128 {
7129 uentry_showWhereSpecified (old);
7130 }
7131
7132 sRef_setExKind (old->sref, newKind, uentry_whereDefined (unew));
7133 }
7134 else
7135 {
7136 if (mustConform &&
7137 optgenerror
7138 (FLG_INCONDEFS,
7139 message ("%s %q inconsistently %rdeclared %s %s, "
7140 "implicitly %s without exposure qualifier",
7141 uentry_ekindName (unew),
7142 uentry_getName (unew),
7143 uentry_isDeclared (old),
7144 fcnErrName (unew),
7145 exkind_unparse (newKind),
7146 uentry_specOrDefName (old)),
7147 uentry_whereDeclared (unew)))
7148 {
7149 uentry_showWhereSpecified (old);
7150 }
7151
7152 sRef_setExKind (old->sref, newKind, uentry_whereDefined (unew));
7153 }
7154 }
7155 }
7156 else
7157 {
7158 if (completeConform && exkind_isKnown (oldKind)
7159 && uentry_isReallySpecified (old))
7160 {
7161 if (optgenerror
7162 (FLG_NEEDSPEC,
7163 message ("%s %q specified as %s, but declared without "
7164 "exposure qualifier",
7165 ekind_capName (unew->ukind),
7166 uentry_getName (unew),
7167 exkind_unparse (oldKind)),
7168 uentry_whereDeclared (unew)))
7169 {
7170 uentry_showWhereSpecified (old);
7171 }
7172 }
7173
7174 /* yes, this is necessary! (if its a param) */
7175 sRef_setExKind (unew->sref, oldKind, fileloc_undefined);
7176 }
7177}
7178
7179static void
7180uentry_checkStateConformance (/*@notnull@*/ uentry old,
7181 /*@notnull@*/ uentry unew,
7182 bool mustConform, bool completeConform)
7183{
7184 checkDefState (old, unew, mustConform, completeConform);
7185 checkNullState (old, unew, mustConform, completeConform);
7186 checkAliasState (old, unew, mustConform, completeConform);
7187 checkExpState (old, unew, mustConform, completeConform);
7188
7189 sRef_storeState (old->sref);
7190 sRef_storeState (unew->sref);
7191}
7192
7193static void
7194checkVarConformance (uentry old, uentry unew, bool mustConform, bool completeConform)
7195{
7196 if (uentry_isElipsisMarker (old) || uentry_isElipsisMarker (unew))
7197 {
7198 return;
7199 }
7200
7201 llassert (uentry_isVar (old));
7202 llassert (uentry_isVar (unew));
7203
7204 if (cstring_isEmpty (old->uname))
7205 {
7206 cstring_free (old->uname);
7207 old->uname = cstring_copy (unew->uname);
7208 }
7209
7210 if (unew->info->var->kind == VKRETPARAM
7211 || unew->info->var->kind == VKSEFRETPARAM)
7212 {
7213 if (old->info->var->kind != VKRETPARAM
7214 && old->info->var->kind != VKSEFRETPARAM)
7215 {
7216 if (optgenerror
7217 (FLG_INCONDEFS,
7218 message ("Parameter %q inconsistently %rdeclared as "
7219 "returned parameter",
7220 uentry_getName (unew),
7221 uentry_isDeclared (old)),
7222 uentry_whereDeclared (unew)))
7223 {
7224 uentry_showWhereSpecified (old);
7225 old->info->var->kind = unew->info->var->kind;
7226 }
7227 }
7228 }
7229
7230
7231 if (unew->info->var->kind == VKSEFPARAM || unew->info->var->kind == VKSEFRETPARAM)
7232 {
7233 if (old->info->var->kind != VKSEFPARAM
7234 && old->info->var->kind != VKSEFRETPARAM)
7235 {
7236 if (optgenerror
7237 (FLG_INCONDEFS,
7238 message ("Parameter %qinconsistently %rdeclared as "
7239 "sef parameter",
7240 uentry_getOptName (unew),
7241 uentry_isDeclared (old)),
7242 uentry_whereDeclared (unew)))
7243 {
7244 uentry_showWhereSpecified (old);
7245 old->info->var->kind = unew->info->var->kind;
7246 }
7247 }
7248 }
7249
7250 if (old->info->var->kind == VKSPEC)
7251 {
7252 old->info->var->kind = unew->info->var->kind;
7253 }
7254 else
7255 {
7256 unew->info->var->kind = old->info->var->kind;
7257 }
7258
7259 if (unew->info->var->checked != CH_UNKNOWN
7260 && unew->info->var->checked != old->info->var->checked)
7261 {
7262 if (old->info->var->checked == CH_UNKNOWN
7263 && !fileloc_isUser (uentry_whereLast (old)))
7264 {
7265 ; /* no error */
7266 }
7267 else
7268 {
7269 if (optgenerror
7270 (FLG_INCONDEFS,
7271 message ("Variable %q inconsistently %rdeclared as "
7272 "%s parameter (was %s)",
7273 uentry_getName (unew),
7274 uentry_isDeclared (old),
7275 checkedName (unew->info->var->checked),
7276 checkedName (old->info->var->checked)),
7277 uentry_whereDeclared (unew)))
7278 {
7279 uentry_showWhereSpecified (old);
7280 }
7281 }
7282
7283 old->info->var->checked = unew->info->var->checked;
7284 }
7285 else
7286 {
7287 if (completeConform
7288 && (old->info->var->checked != CH_UNKNOWN)
7289 && uentry_isReallySpecified (old))
7290 {
7291 if (optgenerror
7292 (FLG_NEEDSPEC,
7293 message ("%s %q specified as %s, but declared without %s qualifier",
7294 ekind_capName (unew->ukind),
7295 uentry_getName (unew),
7296 checkedName (old->info->var->checked),
7297 checkedName (old->info->var->checked)),
7298 uentry_whereDeclared (unew)))
7299 {
7300 uentry_showWhereSpecified (old);
7301 }
7302 }
7303
7304 unew->info->var->checked = old->info->var->checked;
7305 }
7306
7307 uentry_checkStateConformance (old, unew, mustConform, completeConform);
7308}
7309
7310void uentry_checkMatchParam (uentry u1, uentry u2, int paramno, exprNode e)
7311{
7312 if (uentry_isElipsisMarker (u1) || uentry_isElipsisMarker (u2))
7313 {
7314 return;
7315 }
7316
7317 llassert (uentry_isVar (u1));
7318 llassert (uentry_isVar (u2));
7319
7320 if (u1->info->var->kind != u2->info->var->kind) {
7321 if (u1->info->var->kind == VKSEFRETPARAM) {
7322 if (u2->info->var->kind == VKRETPARAM) {
7323 voptgenerror
7324 (FLG_TYPE,
7325 message ("Function types are inconsistent. Parameter %d is "
7326 "sef parameter, but non-sef parameter in "
7327 "assigned function: %s",
7328 paramno, exprNode_unparse (e)),
7329 exprNode_loc (e));
7330 } else if (u2->info->var->kind == VKSEFPARAM) {
7331 voptgenerror
7332 (FLG_TYPE,
7333 message ("Function types are inconsistent. Parameter %d is "
7334 "returns parameter, but non-returns parameter in "
7335 "assigned function: %s",
7336 paramno, exprNode_unparse (e)),
7337 exprNode_loc (e));
7338 } else {
7339 voptgenerror
7340 (FLG_TYPE,
7341 message ("Function types are inconsistent. Parameter %d is "
7342 "sef returns parameter, but non-sef returns parameter in "
7343 "assigned function: %s",
7344 paramno, exprNode_unparse (e)),
7345 exprNode_loc (e));
7346 }
7347 } else if (u1->info->var->kind == VKRETPARAM) {
7348 voptgenerror
7349 (FLG_TYPE,
7350 message ("Function types are inconsistent. Parameter %d is "
7351 "returns parameter, but non-returns parameter in "
7352 "assigned function: %s",
7353 paramno, exprNode_unparse (e)),
7354 exprNode_loc (e));
7355 } else if (u1->info->var->kind == VKSEFPARAM) {
7356 voptgenerror
7357 (FLG_TYPE,
7358 message ("Function types are inconsistent. Parameter %d is "
7359 "sef parameter, but non-sef parameter in "
7360 "assigned function: %s",
7361 paramno, exprNode_unparse (e)),
7362 exprNode_loc (e));
7363 } else {
7364 if (u2->info->var->kind == VKSEFRETPARAM) {
7365 voptgenerror
7366 (FLG_TYPE,
7367 message ("Function types are inconsistent. Parameter %d is "
7368 "normal parameter, but sef returns parameter in "
7369 "assigned function: %s",
7370 paramno, exprNode_unparse (e)),
7371 exprNode_loc (e));
7372 } else if (u2->info->var->kind == VKSEFPARAM) {
7373 voptgenerror
7374 (FLG_TYPE,
7375 message ("Function types are inconsistent. Parameter %d is "
7376 "normal parameter, but sef parameter in "
7377 "assigned function: %s",
7378 paramno, exprNode_unparse (e)),
7379 exprNode_loc (e));
7380 } else if (u2->info->var->kind == VKRETPARAM) {
7381 voptgenerror
7382 (FLG_TYPE,
7383 message ("Function types are inconsistent. Parameter %d is "
7384 "normal parameter, but returns parameter in "
7385 "assigned function: %s",
7386 paramno, exprNode_unparse (e)),
7387 exprNode_loc (e));
7388 } else {
7389 BADBRANCH;
7390 }
7391 }
7392 }
7393
7394 if (u1->info->var->defstate != u2->info->var->defstate)
7395 {
7396 voptgenerror
7397 (FLG_TYPE,
7398 message ("Function types are inconsistent. Parameter %d is "
7399 "%s, but %s in assigned function: %s",
7400 paramno,
7401 sstate_unparse (u1->info->var->defstate),
7402 sstate_unparse (u2->info->var->defstate),
7403 exprNode_unparse (e)),
7404 exprNode_loc (e));
7405 }
7406
7407 if (u1->info->var->nullstate != u2->info->var->nullstate)
7408 {
7409 voptgenerror
7410 (FLG_TYPE,
7411 message ("Function types are inconsistent. Parameter %d is "
7412 "%s, but %s in assigned function: %s",
7413 paramno,
7414 nstate_unparse (u1->info->var->nullstate),
7415 nstate_unparse (u2->info->var->nullstate),
7416 exprNode_unparse (e)),
7417 exprNode_loc (e));
7418 }
7419
7420 if (sRef_getAliasKind (u1->sref) != sRef_getAliasKind (u2->sref))
7421 {
7422 voptgenerror
7423 (FLG_TYPE,
7424 message ("Function types are inconsistent. Parameter %d is "
7425 "%s, but %s in assigned function: %s",
7426 paramno,
7427 alkind_unparse (sRef_getAliasKind (u1->sref)),
7428 alkind_unparse (sRef_getAliasKind (u2->sref)),
7429 exprNode_unparse (e)),
7430 exprNode_loc (e));
7431 }
7432
7433 if (sRef_getExKind (u1->sref) != sRef_getExKind (u2->sref))
7434 {
7435 voptgenerror
7436 (FLG_TYPE,
7437 message ("Function types are inconsistent. Parameter %d is "
7438 "%s, but %s in assigned function: %s",
7439 paramno,
7440 exkind_unparse (sRef_getExKind (u1->sref)),
7441 exkind_unparse (sRef_getExKind (u2->sref)),
7442 exprNode_unparse (e)),
7443 exprNode_loc (e));
7444 }
7445}
7446
7447static void
7448checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old,
7449 /*@notnull@*/ uentry unew,
7450 bool mustConform, /*@unused@*/ bool completeConform)
7451{
7452 uentryList oldParams = uentry_getParams (old);
7453 uentryList newParams = uentry_getParams (unew);
7454 ctype newType = unew->utype;
7455 ctype oldType = old->utype;
7456 ctype oldRetType = ctype_unknown;
7457 ctype newRetType = ctype_unknown;
7458
7459 if (uentry_isForward (old))
7460 {
7461 mustConform = FALSE;
7462 uentry_copyInto (old, unew);
7463 return;
7464 }
7465
7466 /*
7467 ** check return values
7468 */
7469
7470 if (ctype_isKnown (oldType))
7471 {
7472 llassert (ctype_isFunction (oldType));
7473
7474 oldRetType = ctype_returnValue (oldType);
7475 }
7476
7477 if (ctype_isKnown (newType))
7478 {
7479 llassert (ctype_isFunction (newType));
7480
7481 newRetType = ctype_returnValue (newType);
7482 }
7483
7484 if (ctype_isKnown (oldRetType) && ctype_isKnown (newRetType)
7485 && !ctype_matchDef (newRetType, oldRetType))
7486 {
7487 if (mustConform) returnValueError (old, unew);
7488 }
7489 else
7490 {
7491 if (ctype_isConj (newRetType))
7492 {
7493 if (ctype_isConj (oldRetType))
7494 {
7495 if (!ctype_sameAltTypes (newRetType, oldRetType))
7496 {
7497 if (optgenerror
7498 (FLG_INCONDEFS,
7499 message ("Function %q inconsistently %rdeclared to "
7500 "return alternate types %s "
7501 "(types match, but alternates are not identical, "
7502 "so checking may not be correct)",
7503 uentry_getName (unew),
7504 uentry_isDeclared (old),
7505 ctype_unparse (newRetType)),
7506 uentry_whereDeclared (unew)))
7507 {
7508 uentry_showWhereLastVal (old, ctype_unparse (oldRetType));
7509 }
7510 }
7511 }
7512 else
7513 {
7514 old->utype = ctype_makeFunction (oldRetType, uentryList_copy (newParams));
7515 }
7516 }
7517 }
7518
7519 uentry_checkStateConformance (old, unew, mustConform, completeConform);
7520
7521 if (!exitkind_equal (unew->info->fcn->exitCode, old->info->fcn->exitCode))
7522 {
7523 if (exitkind_isKnown (unew->info->fcn->exitCode))
7524 {
7525 if (optgenerror
7526 (FLG_INCONDEFS,
7527 message ("Function %q inconsistently %rdeclared using %s",
7528 uentry_getName (unew),
7529 uentry_isDeclared (old),
7530 exitkind_unparse (unew->info->fcn->exitCode)),
7531 uentry_whereDeclared (unew)))
7532 {
7533 uentry_showWhereSpecified (old);
7534 }
7535 }
7536 else
7537 {
7538 unew->info->fcn->exitCode = old->info->fcn->exitCode;
7539 }
7540 }
7541
7542 if (!qual_isUnknown (unew->info->fcn->nullPred))
7543 {
7544 if (!qual_equal (old->info->fcn->nullPred, unew->info->fcn->nullPred))
7545 {
7546 if (optgenerror
7547 (FLG_INCONDEFS,
7548 message ("Function %q inconsistently %rdeclared using %s",
7549 uentry_getName (unew),
7550 uentry_isDeclared (old),
7551 qual_unparse (unew->info->fcn->nullPred)),
7552 uentry_whereDeclared (unew)))
7553 {
7554 uentry_showWhereSpecified (old);
7555 }
7556 }
7557 }
7558 else
7559 {
7560 unew->info->fcn->nullPred = old->info->fcn->nullPred;
7561 }
7562
7563 if (unew->info->fcn->specialCode != SPC_NONE)
7564 {
7565 if (old->info->fcn->specialCode != unew->info->fcn->specialCode)
7566 {
7567 if (optgenerror
7568 (FLG_INCONDEFS,
7569 message ("Function %q inconsistently %rdeclared using %s",
7570 uentry_getName (unew),
7571 uentry_isDeclared (old),
7572 specCode_unparse (unew->info->fcn->specialCode)),
7573 uentry_whereDeclared (unew)))
7574 {
7575 uentry_showWhereSpecified (old);
7576 }
7577 }
7578 }
7579 else
7580 {
7581 unew->info->fcn->specialCode = old->info->fcn->specialCode;
7582 }
7583
7584 /*
7585 ** check parameters
7586 */
7587
7588 if (!uentryList_sameObject (oldParams, newParams)
7589 && (!uentryList_isMissingParams (oldParams)))
7590 {
7591 if (!uentryList_isMissingParams (newParams))
7592 {
7593 int paramno = 0;
7594 int nparams = uentryList_size (oldParams);
7595 bool checknames = context_maybeSet (FLG_DECLPARAMMATCH);
7596
7597 if (nparams != uentryList_size (newParams))
7598 {
7599 nargsError (old, unew);
7600 }
7601
7602 if (uentryList_size (newParams) < nparams)
7603 {
7604 nparams = uentryList_size (newParams);
7605 }
7606
7607 while (paramno < nparams)
7608 {
7609 uentry oldCurrent = uentryList_getN (oldParams, paramno);
7610 uentry newCurrent = uentryList_getN (newParams, paramno);
7611 ctype oldCurrentType = uentry_getType (oldCurrent);
7612 ctype newCurrentType = uentry_getType (newCurrent);
7613
7614 llassert (uentry_isValid (oldCurrent)
7615 && uentry_isValid (newCurrent));
7616
7617 if (!uentry_isElipsisMarker (oldCurrent)
7618 && !uentry_isElipsisMarker (newCurrent))
7619 {
7620 checkVarConformance (oldCurrent, newCurrent,
7621 mustConform, completeConform);
7622 }
7623
7624 if (checknames)
7625 {
7626 if (uentry_hasName (oldCurrent)
7627 && uentry_hasName (newCurrent))
7628 {
7629 cstring oldname = uentry_getName (oldCurrent);
7630 cstring pfx = context_getString (FLG_DECLPARAMPREFIX);
7631 cstring oname;
7632 cstring nname = uentry_getName (newCurrent);
7633 cstring nnamefix;
7634
7635 if (cstring_isDefined (pfx)
7636 && cstring_equalPrefix (oldname, cstring_toCharsSafe (pfx)))
7637 {
7638 oname = cstring_suffix (oldname, cstring_length (pfx));
7639 }
7640 else
7641 {
7642 oname = oldname;
7643 /*@-branchstate@*/ } /*@=branchstate@*/
7644
7645 if (cstring_isDefined (pfx)
7646 && cstring_equalPrefix (nname, cstring_toCharsSafe (pfx)))
7647 {
7648 nnamefix = cstring_suffix (nname, cstring_length (pfx));
7649 }
7650 else
7651 {
7652 nnamefix = nname;
7653 /*@-branchstate@*/ } /*@=branchstate@*/
7654
7655 if (!cstring_equal (oname, nnamefix))
7656 {
7657 if (optgenerror
7658 (FLG_DECLPARAMMATCH,
7659 message ("Definition parameter name %s does not match "
7660 "name of corresponding parameter in "
7661 "declaration: %s",
7662 nnamefix, oname),
7663 uentry_whereLast (newCurrent)))
7664 {
7665 uentry_showWhereLastPlain (oldCurrent);
7666 }
7667 }
7668
7669 cstring_free (oldname);
7670 cstring_free (nname);
7671 }
7672 }
7673
7674 if (!ctype_match (oldCurrentType, newCurrentType))
7675 {
7676 paramTypeError (old, oldCurrent, oldCurrentType,
7677 unew, newCurrent, newCurrentType, paramno);
7678 }
7679 else
7680 {
7681 if (ctype_isMissingParamsMarker (newCurrentType)
7682 || ctype_isElips (newCurrentType)
7683 || ctype_isMissingParamsMarker (oldCurrentType)
7684 || ctype_isElips (oldCurrentType))
7685 {
7686 ;
7687 }
7688 else
7689 {
7690 if (ctype_isConj (newCurrentType))
7691 {
7692 if (ctype_isConj (oldCurrentType))
7693 {
7694 if (!ctype_sameAltTypes (newCurrentType, oldCurrentType))
7695 {
7696 if (optgenerror
7697 (FLG_INCONDEFS,
7698 message ("Parameter %q inconsistently %rdeclared with "
7699 "alternate types %s "
7700 "(types match, but alternates are not identical, "
7701 "so checking may not be correct)",
7702 uentry_getName (newCurrent),
7703 uentry_isDeclared (oldCurrent),
7704 ctype_unparse (newCurrentType)),
7705 uentry_whereDeclared (unew)))
7706 {
7707 uentry_showWhereLastVal (oldCurrent,
7708 ctype_unparse (oldCurrentType));
7709 }
7710 }
7711 }
7712 else
7713 {
7714 if (optgenerror
7715 (FLG_INCONDEFS,
7716 message ("Parameter %q inconsistently %rdeclared with "
7717 "alternate types %s",
7718 uentry_getName (newCurrent),
7719 uentry_isDeclared (oldCurrent),
7720 ctype_unparse (newCurrentType)),
7721 uentry_whereDeclared (unew)))
7722 {
7723 uentry_showWhereLastVal (oldCurrent,
7724 ctype_unparse (oldCurrentType));
7725
7726 }
7727 }
7728 }
7729 else
7730 {
7731 if (ctype_isConj (oldCurrentType))
7732 {
7733 uentry_setType (newCurrent, oldCurrentType);
7734 }
7735 }
7736 }
7737 }
7738
7739 paramno++;
7740 /*
7741 ** Forgot this! detected by lclint:
7742 ** uentry.c:1257,15: Suspected infinite loop
7743 */
7744 }
7745 }
7746 }
7747
7748 if (!uentryList_isMissingParams (newParams))
7749 {
7750 if (ctype_isConj (oldRetType))
7751 {
7752 old->utype = ctype_makeFunction (oldRetType,
7753 uentryList_copy (newParams));
7754 }
7755 else
7756 {
7757 old->utype = unew->utype;
7758 }
7759 }
7760
7761 checkGlobalsConformance (old, unew, mustConform, completeConform);
7762 checkModifiesConformance (old, unew, mustConform, completeConform);
7763
7764 if (specialClauses_isDefined (unew->info->fcn->specclauses))
7765 {
7766 if (!specialClauses_isDefined (old->info->fcn->specclauses))
7767 {
7768 if (optgenerror
7769 (FLG_INCONDEFS,
7770 message ("Function %q redeclared using special clauses (can only "
7771 "be used in first declaration)",
7772 uentry_getName (unew)),
7773 uentry_whereDeclared (unew)))
7774 {
7775 uentry_showWhereLast (old);
7776 }
7777 }
7778 else
7779 {
7780 specialClauses_checkEqual (old, unew);
7781 }
7782 }
7783
7784 if (fileloc_isUndefined (old->whereDeclared))
7785 {
7786 old->whereDeclared = fileloc_copy (unew->whereDeclared);
7787 }
7788 else if (fileloc_isUndefined (unew->whereDeclared))
7789 {
7790 unew->whereDeclared = fileloc_copy (old->whereDeclared);
7791 }
7792 else
7793 {
7794 /* no change */
7795 }
7796}
7797
7798void
7799uentry_mergeConstantValue (uentry ue, /*@only@*/ multiVal m)
7800{
7801 multiVal uval;
7802
7803 llassert (uentry_isValid (ue));
7804 llassert (uentry_isEitherConstant (ue));
7805
7806 uval = ue->info->uconst->val;
7807
7808 if (multiVal_isDefined (uval))
7809 {
7810 if (multiVal_isDefined (m))
7811 {
7812 if (!multiVal_equiv (uval, m))
7813 {
7814 if (optgenerror
7815 (FLG_INCONDEFS,
7816 message ("%s %q defined with inconsistent value: %q",
7817 ekind_capName (ue->ukind),
7818 uentry_getName (ue),
7819 multiVal_unparse (m)),
7820 g_currentloc))
7821 {
7822 uentry_showWhereLastExtra (ue, multiVal_unparse (uval));
7823 }
7824 }
7825 }
7826 multiVal_free (m);
7827 }
7828 else
7829 {
7830 ue->info->uconst->val = m;
7831 multiVal_free (uval);
7832 }
7833}
7834
7835static
7836bool checkTypeConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
7837 bool mustConform)
7838{
7839 bool typeError = FALSE;
7840
7841 if (uentry_isStructTag (old) || uentry_isUnionTag (old))
7842 {
7843 if (ctype_isSU (old->utype) && ctype_isSU (unew->utype))
7844 {
7845 if (mustConform)
7846 {
7847 checkStructConformance (old, unew);
7848 }
7849 }
7850 else
7851 {
7852 if (!(ctype_isBogus (old->utype) || ctype_isBogus (unew->utype)))
7853 {
7854 llbug (message ("struct tags: bad types: %t / %t",
7855 old->utype, unew->utype));
7856 }
7857 }
7858 }
7859 else if (uentry_isEnumTag (old))
7860 {
7861 if (ctype_isEnum (old->utype) && ctype_isEnum (unew->utype))
7862 {
7863 if (mustConform) checkEnumConformance (old, unew);
7864 }
7865 else
7866 {
7867 if (!(ctype_isBogus (old->utype) || ctype_isBogus (unew->utype)))
7868 {
7869 llbug (message ("enum! bad type: %s / %s", ctype_unparse (old->utype),
7870 ctype_unparse (unew->utype)));
7871 }
7872 }
7873 }
7874 else if (!ctype_match (old->utype, unew->utype))
7875 {
7876 if (cstring_equal (uentry_rawName (old), context_getBoolName ()))
7877 {
7878 ctype realt = ctype_realType (unew->utype);
7879
7880 if (ctype_isRealInt (realt) || ctype_isChar (realt))
7881 {
7882 unew->utype = ctype_bool;
7883 }
7884 else
7885 {
7886 if (mustConform)
7887 {
7888 typeError = optgenerror
7889 (FLG_INCONDEFS,
7890 message ("%q defined as %s", uentry_getName (old),
7891 ctype_unparse (realt)),
7892 uentry_whereDeclared (unew));
7893 }
7894 }
7895 }
7896 else
7897 {
7898 if (mustConform)
7899 {
7900 ctype oldr = ctype_realType (old->utype);
7901 ctype newr = ctype_realType (unew->utype);
7902
7903 if (ctype_isStruct (oldr) && ctype_isStruct (newr))
7904 {
7905 checkStructConformance (old, unew);
7906 }
7907 else if (ctype_isUnion (oldr) && ctype_isUnion (newr))
7908 {
7909 checkStructConformance (old, unew);
7910 }
7911 else if (ctype_isEnum (oldr) && ctype_isEnum (newr))
7912 {
7913 checkEnumConformance (old, unew);
7914 }
7915 else if (uentry_isConstant (old)
7916 && (ctype_isAbstract (oldr) && ctype_isEnum (newr)))
7917 {
7918 /* okay...for now! (should check the type is reset later... */
7919 }
7920 else
7921 {
7922 DPRINTF (("YABA!"));
7923 if (optgenerror
7924 (FLG_INCONDEFS,
7925 message ("%s %q %rdeclared with inconsistent type: %t",
7926 ekind_capName (unew->ukind),
7927 uentry_getName (unew),
7928 uentry_isDeclared (old),
7929 unew->utype),
7930 uentry_whereDeclared (unew)))
7931 {
7932 uentry_showWhereLast (old);
7933 typeError = TRUE;
7934 }
7935 }
7936 }
7937 }
7938 }
7939 else
7940 {
7941 /* no error */
7942 }
7943
7944 return typeError;
7945}
7946
7947static void
7948uentry_checkDatatypeConformance (/*@notnull@*/ uentry old,
7949 /*@notnull@*/ uentry unew,
7950 bool mustConform, bool completeConform)
7951{
7952 if (ctype_isDefined (unew->info->datatype->type))
7953 {
7954 /*
7955 ** bool is hard coded here, since it is built into LCL.
7956 ** For now, we're stuck with LCL's types.
7957 */
7958
7959 if (ctype_isDirectBool (old->utype) &&
7960 cstring_equalLit (unew->uname, "bool"))
7961 {
7962 /* if (!context_getFlag (FLG_ABSTRACTBOOL))
7963 evs 2000-07-25: removed
7964 */
7965 unew->utype = ctype_bool;
7966 }
7967
7968 if (ctype_isUnknown (old->info->datatype->type))
7969 {
7970 old->info->datatype->type = unew->info->datatype->type;
7971 }
7972 else
7973 {
7974 DPRINTF (("Old: %s / New: %s",
7975 uentry_unparseFull (old),
7976 uentry_unparseFull (unew)));
7977 DPRINTF (("Types: %s / %s",
7978 ctype_unparse (old->info->datatype->type),
7979 ctype_unparse (unew->info->datatype->type)));
7980
7981 if (ctype_matchDef (old->info->datatype->type,
7982 unew->info->datatype->type))
7983 {
7984 ;
7985 }
7986 else
7987 {
7988 if (optgenerror
7989 (FLG_INCONDEFS,
7990 message
7991 ("Type %q %s with inconsistent type: %t",
7992 uentry_getName (unew),
7993 uentry_reDefDecl (old, unew),
7994 unew->info->datatype->type),
7995 uentry_whereDeclared (unew)))
7996 {
7997 uentry_showWhereLastExtra
7998 (old, cstring_copy (ctype_unparse (old->info->datatype->type)));
7999 }
8000
8001 old->info->datatype->type = unew->info->datatype->type;
8002 }
8003 }
8004 }
8005
8006 if (unew->info->datatype->abs != MAYBE)
8007 {
8008 if (ynm_isOff (old->info->datatype->abs)
8009 && ynm_isOn (unew->info->datatype->abs))
8010 {
8011 if (!ctype_isDirectBool (old->utype))
8012 {
8013 if (optgenerror
8014 (FLG_INCONDEFS,
8015 message
8016 ("Datatype %q inconsistently %rdeclared as abstract type",
8017 uentry_getName (unew),
8018 uentry_isDeclared (old)),
8019 uentry_whereDeclared (unew)))
8020 {
8021 uentry_showWhereLastPlain (old);
8022 }
8023 }
8024 }
8025 else if (ynm_isOn (old->info->datatype->abs)
8026 && ynm_isOff (unew->info->datatype->abs))
8027 {
8028 if (!ctype_isDirectBool (old->utype))
8029 {
8030 if (optgenerror
8031 (FLG_INCONDEFS,
8032 message
8033 ("Datatype %q inconsistently %rdeclared as concrete type",
8034 uentry_getName (unew),
8035 uentry_isDeclared (old)),
8036 uentry_whereDeclared (unew)))
8037 {
8038 uentry_showWhereLastPlain (old);
8039 }
8040 }
8041 }
8042 else
8043 {
8044 ;
8045 }
8046 }
8047 else
8048 {
8049 if (ynm_isOn (old->info->datatype->abs))
8050 {
8051 old->sref = unew->sref;
8052 unew->info->datatype->mut = old->info->datatype->mut;
8053
8054 if (completeConform
8055 && uentry_isReallySpecified (old))
8056 {
8057 if (optgenerror
8058 (FLG_NEEDSPEC,
8059 message
8060 ("Datatype %q specified as abstract, "
8061 "but abstract annotation not used in declaration",
8062 uentry_getName (unew)),
8063 uentry_whereDeclared (unew)))
8064 {
8065 uentry_showWhereLastPlain (old);
8066 }
8067 }
8068 }
8069 }
8070
8071 unew->info->datatype->abs = old->info->datatype->abs;
8072
8073 if (ynm_isMaybe (unew->info->datatype->mut))
8074 {
8075 if (completeConform && ynm_isOff (old->info->datatype->mut)
8076 && uentry_isReallySpecified (old))
8077 {
8078 if (optgenerror
8079 (FLG_NEEDSPEC,
8080 message
8081 ("Datatype %q specified as immutable, "
8082 "but immutable annotation not used in declaration",
8083 uentry_getName (unew)),
8084 uentry_whereDeclared (unew)))
8085 {
8086 uentry_showWhereLastPlain (old);
8087 }
8088 }
8089
8090 unew->info->datatype->mut = old->info->datatype->mut;
8091 }
8092 else if (ynm_isMaybe (old->info->datatype->mut))
8093 {
8094 old->info->datatype->mut = unew->info->datatype->mut;
8095 }
8096 else
8097 {
8098 if (ynm_isOn (old->info->datatype->abs))
8099 {
8100 if (ynm_isOn (old->info->datatype->mut) && ynm_isOff (unew->info->datatype->mut))
8101 {
8102 if (optgenerror
8103 (FLG_INCONDEFS,
8104 message ("Datatype %q inconsistently %rdeclared as immutable",
8105 uentry_getName (unew),
8106 uentry_isDeclared (old)),
8107 uentry_whereDeclared (unew)))
8108 {
8109 uentry_showWhereLastPlain (old);
8110 }
8111 }
8112 else
8113 {
8114 if (ynm_isOff (old->info->datatype->mut)
8115 && ynm_isOn (unew->info->datatype->mut))
8116 {
8117 if (optgenerror
8118 (FLG_INCONDEFS,
8119 message ("Datatype %q inconsistently %rdeclared as mutable",
8120 uentry_getName (unew),
8121 uentry_isDeclared (old)),
8122 uentry_whereDeclared (unew)))
8123 {
8124 uentry_showWhereLastPlain (old);
8125 }
8126 }
8127 }
8128 }
8129 old->info->datatype->mut = unew->info->datatype->mut;
8130 }
8131
8132 uentry_checkStateConformance (old, unew, mustConform, completeConform);
8133}
8134
8135static void
8136uentry_checkConstantConformance (/*@notnull@*/ uentry old,
8137 /*@notnull@*/ uentry unew,
8138 bool mustConform,
8139 /*@unused@*/ bool completeConform)
8140{
8141 multiVal oldVal = old->info->uconst->val;
8142 multiVal newVal = unew->info->uconst->val;
8143
8144 if (multiVal_isDefined (oldVal))
8145 {
8146 if (multiVal_isDefined (newVal))
8147 {
8148 if (!multiVal_equiv (oldVal, newVal))
8149 {
8150 if (mustConform
8151 && optgenerror
8152 (FLG_INCONDEFS,
8153 message ("%s %q %rdeclared with inconsistent value: %q",
8154 ekind_capName (unew->ukind),
8155 uentry_getName (unew),
8156 uentry_isDeclared (old),
8157 multiVal_unparse (newVal)),
8158 uentry_whereDeclared (unew)))
8159 {
8160 uentry_showWhereLastExtra (old, multiVal_unparse (oldVal));
8161 }
8162 }
8163
8164 unew->info->uconst->val = multiVal_copy (oldVal);
8165 multiVal_free (newVal);
8166 }
8167 else
8168 {
8169 ;
8170 }
8171 }
8172 else
8173 {
8174 old->info->uconst->val = multiVal_copy (newVal);
8175 }
8176}
8177
8178static void
8179uentry_checkConformance (/*@unique@*/ /*@notnull@*/ uentry old,
8180 /*@notnull@*/ uentry unew, bool mustConform,
8181 bool completeConform)
8182{
8183 bool typeError = FALSE;
8184 bool fcnConformance = FALSE;
8185
8186 if (!ekind_equal (unew->ukind, old->ukind))
8187 {
8188 /*
8189 ** okay, only if one is a function and the other is
8190 ** a variable of type function.
8191 */
8192
8193 if (unew->ukind == KENUMCONST
8194 && old->ukind == KCONST)
8195 {
8196 old->ukind = KENUMCONST;
8197 goto nokinderror;
8198 }
8199
8200 if (unew->ukind == KFCN
8201 && old->ukind == KCONST
8202 && ctype_isUnknown (old->utype))
8203 {
8204 /*
8205 ** When a function is defined with an unparam macro
8206 */
8207
8208 uentry_copyInto (old, unew);
8209 return;
8210 }
8211
8212 if (uentry_isExpandedMacro (old)
8213 && uentry_isEitherConstant (unew))
8214 {
8215 uentry_copyInto (old, unew);
8216 return;
8217 }
8218
8219 if (uentry_isEndIter (unew))
8220 {
8221 if (ctype_isUnknown (old->utype))
8222 {
8223 if (!uentry_isSpecified (old)
8224 && uentry_isCodeDefined (unew))
8225 {
8226 if (!fileloc_withinLines (uentry_whereDefined (old),
8227 uentry_whereDeclared (unew), 2))
8228 { /* bogus! will give errors if there is too much whitespace */
8229 voptgenerror
8230 (FLG_SYNTAX,
8231 message
8232 ("Iterator finalized name %q does not match name in "
8233 "previous iter declaration (should be end_%q). This iter "
8234 "is declared at %q",
8235 uentry_getName (unew),
8236 uentry_getName (old),
8237 fileloc_unparse (uentry_whereDefined (old))),
8238 uentry_whereDeclared (old));
8239 }
8240 }
8241
8242 uentry_copyInto (old, unew);
8243 return;
8244 }
8245 else
8246 {
8247 KindConformanceError (old, unew, mustConform);
8248 }
8249 }
8250
8251 if (uentry_isFunction (unew))
8252 {
8253 if (uentry_isVariable (old))
8254 {
8255 if (!ctype_isUnknown (old->utype))
8256 {
8257 if (ctype_isFunction (old->utype))
8258 {
8259 uentry_makeVarFunction (old);
8260 checkFunctionConformance (old, unew, mustConform,
8261 completeConform);
8262 fcnConformance = TRUE;
8263 }
8264 else
8265 {
8266 KindConformanceError (old, unew, mustConform);
8267 }
8268 }
8269 else
8270 {
8271 if (uentry_isExpandedMacro (old))
8272 {
8273 if (fileloc_isUndefined (unew->whereDefined))
8274 {
8275 unew->whereDefined = fileloc_update (unew->whereDefined,
8276 old->whereDefined);
8277 }
8278
8279 uentry_copyInto (old, unew);
8280 old->used = unew->used = TRUE;
8281 return;
8282 }
8283 else
8284 {
8285 /* undeclared identifier */
8286 old->utype = unew->utype;
8287 uentry_makeVarFunction (old);
8288 checkFunctionConformance (old, unew, FALSE, FALSE);
8289 fcnConformance = TRUE;
8290 }
8291 }
8292 }
8293 else
8294 {
8295 KindConformanceError (old, unew, mustConform);
8296 }
8297 }
8298 else if (uentry_isFunction (old) && uentry_isVariable (unew))
8299 {
8300 if (!ctype_isUnknown (unew->utype))
8301 {
8302 if (ctype_isFunction (unew->utype))
8303 {
8304 uentry_makeVarFunction (unew);
8305 checkFunctionConformance (old, unew, mustConform, completeConform);
8306 fcnConformance = TRUE;
8307 }
8308 else
8309 {
8310 KindConformanceError (old, unew, mustConform);
8311 }
8312 }
8313 else
8314 {
8315 KindConformanceError (old, unew, mustConform);
8316 }
8317 }
8318 else
8319 {
8320 KindConformanceError (old, unew, mustConform);
8321 }
8322 }
8323 else
8324 {
8325 /*
8326 ** check parameter lists for functions
8327 ** (before type errors, to get better messages
8328 */
8329
8330 if (uentry_isFunction (old))
8331 {
8332 checkFunctionConformance (old, unew, mustConform, completeConform);
8333 fcnConformance = TRUE;
8334 }
8335 else
8336 {
8337 if (!ctype_isUndefined (old->utype))
8338 {
8339 typeError = checkTypeConformance (old, unew, mustConform);
8340 }
8341 }
8342 }
8343
8344 nokinderror:
8345
8346 if (uentry_isEitherConstant (old) && uentry_isEitherConstant (unew))
8347 {
8348 uentry_checkConstantConformance (old, unew, mustConform, completeConform);
8349 }
8350
8351 if (uentry_isDatatype (old) && uentry_isDatatype (unew))
8352 {
8353 DPRINTF (("Check datatype: %s / %s",
8354 uentry_unparseFull (old),
8355 uentry_unparseFull (unew)));
8356
8357 uentry_checkDatatypeConformance (old, unew, mustConform, completeConform);
8358 }
8359
8360 if (uentry_isVariable (old) && uentry_isVariable (unew))
8361 {
8362 if (!typeError &&
8363 !ctype_matchDef (old->utype, unew->utype))
8364 {
8365 if (optgenerror
8366 (FLG_INCONDEFS,
8367 message
8368 ("Variable %q %s with inconsistent type (arrays and pointers are "
8369 "not identical in variable declarations): %t",
8370 uentry_getName (unew),
8371 uentry_reDefDecl (old, unew),
8372 unew->utype),
8373 uentry_whereDeclared (unew)))
8374 {
8375 uentry_showWhereLast (old);
8376
8377 /*
8378 ** Avoid repeated errors.
8379 */
8380
8381 if (uentry_isCodeDefined (old) && uentry_isCodeDefined (unew))
8382 {
8383 old->whereDefined = fileloc_update (old->whereDefined,
8384 fileloc_undefined);
8385 }
8386
8387 typeError = TRUE;
8388 }
8389 }
8390
8391 checkVarConformance (old, unew, mustConform, completeConform);
8392 }
8393
8394 if (fcnConformance)
8395 {
8396 /* old->utype = unew->utype; */
8397 }
8398 else
8399 {
8400 if (ctype_isConj (old->utype))
8401 {
8402 if (ctype_isConj (unew->utype))
8403 {
8404 if (!ctype_sameAltTypes (old->utype, unew->utype))
8405 {
8406 if (optgenerror
8407 (FLG_INCONDEFS,
8408 message ("%s %q inconsistently %rdeclared with "
8409 "alternate types %s "
8410 "(types match, but alternates are not identical, "
8411 "so checking may not be correct)",
8412 ekind_capName (uentry_getKind (old)),
8413 uentry_getName (unew),
8414 uentry_isDeclared (old),
8415 ctype_unparse (unew->utype)),
8416 uentry_whereDeclared (unew)))
8417 {
8418 uentry_showWhereLastVal (old, ctype_unparse (old->utype));
8419 }
8420 else
8421 {
8422 old->utype = unew->utype;
8423 }
8424 }
8425 }
8426 }
8427 else
8428 {
8429 if (ctype_isUnknown (old->utype))
8430 {
8431 old->utype = unew->utype;
8432 }
8433 }
8434 }
8435
8436 if (unew->ukind == old->ukind)
8437 {
8438 sfree (unew->info);
8439 unew->info = uinfo_copy (old->info, old->ukind);
8440 }
8441
8442 sRef_storeState (old->sref);
8443 sRef_storeState (unew->sref);
8444}
8445
8446/*
8447** modifies spec to reflect def, reports any inconsistencies
8448*/
8449
8450void
8451uentry_mergeEntries (uentry spec, /*@only@*/ uentry def)
8452{
8453 llassert (uentry_isValid (spec));
8454 llassert (uentry_isValid (def));
8455 llassert (cstring_equal (spec->uname, def->uname));
8456
8457 uentry_checkConformance (spec, def, TRUE,
8458 context_getFlag (FLG_NEEDSPEC));
8459
8460 /* was: !(fileloc_isImport (uentry_whereSpecified (spec)))); */
8461
8462 /*
8463 ** okay, declarations conform. Propagate extra information.
8464 */
8465
8466 uentry_setDefined (spec, uentry_whereDefined (def));
8467 uentry_setDeclared (spec, uentry_whereDeclared (def));
8468
8469 if (uentry_isStatic (def))
8470 {
8471 if (optgenerror
8472 (FLG_INCONDEFS,
8473 message ("%s %q specified, but declared as static",
8474 ekind_capName (def->ukind),
8475 uentry_getName (def)),
8476 uentry_whereDeclared (def)))
8477 {
8478 uentry_showWhereSpecified (spec);
8479 }
8480 }
8481 else
8482 {
8483 spec->storageclass = def->storageclass;
8484 }
8485
8486 sRef_storeState (spec->sref);
8487
8488 spec->used = def->used || spec->used;
8489 spec->hasNameError |= def->hasNameError;
8490
8491 uentry_free (def);
8492
8493 if (!spec->hasNameError)
8494 {
8495 uentry_checkName (spec);
8496 }
8497 else
8498 {
8499 ;
8500 }
8501}
8502
8503/*
8504** Can't generate function redeclaration errors when the
8505** entries are merged, since we don't yet know if its the
8506** definition of the function.
8507*/
8508
8509void
8510uentry_clearDecl (void)
8511{
8512 posRedeclared = uentry_undefined;
8513 fileloc_free (posLoc);
8514 posLoc = fileloc_undefined;
8515}
8516
8517void
8518uentry_checkDecl (void)
8519{
8520 if (uentry_isValid (posRedeclared))
8521 {
8522 llassert (fileloc_isDefined (posLoc));
8523
8524 if (uentry_isCodeDefined (posRedeclared))
8525 {
8526 if (optgenerror (FLG_REDECL,
8527 message ("%s %q declared after definition",
8528 ekind_capName (posRedeclared->ukind),
8529 uentry_getName (posRedeclared)),
8530 posLoc))
8531 {
8532 llgenindentmsg (message ("Definition of %q",
8533 uentry_getName (posRedeclared)),
8534 posRedeclared->whereDeclared);
8535 }
8536 }
8537 else
8538 {
8539 if (optgenerror (FLG_REDECL,
8540 message ("%s %q declared more than once",
8541 ekind_capName (posRedeclared->ukind),
8542 uentry_getName (posRedeclared)),
8543 posLoc))
8544 {
8545 llgenindentmsg (message ("Previous declaration of %q",
8546 uentry_getName (posRedeclared)),
8547 posRedeclared->whereDeclared);
8548 }
8549 }
8550 }
8551
8552 fileloc_free (posLoc);
8553 posLoc = fileloc_undefined;
8554 posRedeclared = uentry_undefined;
8555}
8556
8557/*
8558** Redefinition of old as unew.
8559** modifies old to reflect unew, reports any inconsistencies
8560*/
8561
8562void
8563uentry_mergeDefinition (uentry old, /*@only@*/ uentry unew)
8564{
8565 fileloc olddef = uentry_whereDeclared (old);
8566 fileloc unewdef = uentry_whereDeclared (unew);
8567 bool mustConform;
8568 bool wasForward;
8569
8570 if (uentry_isExtern (unew))
8571 {
8572 uentry_setUsed (old, unewdef);
8573 }
8574
8575 wasForward =
8576 fileloc_isUndefined (olddef)
8577 && fileloc_isDefined (uentry_whereDefined (old))
8578 && !uentry_isExpandedMacro (old);
8579
8580 if (!context_getFlag (FLG_INCONDEFSLIB)
8581 && (fileloc_isLib (olddef) || fileloc_isImport (olddef)))
8582 {
8583 mustConform = FALSE;
8584 }
8585 else
8586 {
8587 mustConform = TRUE;
8588 }
8589
8590 llassert (uentry_isValid (old));
8591 llassert (uentry_isValid (unew));
8592 llassert (cstring_equal (old->uname, unew->uname));
8593
8594 /*
8595 ** should check old one was extern!
8596 */
8597
8598 if (uentry_isStatic (old))
8599 {
8600 if (!(uentry_isStatic (unew)))
8601 {
8602 if (optgenerror
8603 (FLG_SHADOW,
8604 message ("%s %q shadows static declaration",
8605 ekind_capName (unew->ukind),
8606 uentry_getName (unew)),
8607 unewdef))
8608 {
8609 uentry_showWhereLast (old);
8610 }
8611 }
8612 else
8613 {
8614 uentry_setDeclDef (old, unewdef);
8615 }
8616 }
8617 else if (uentry_isStatic (unew))
8618 {
8619 uentry_setDeclDef (old, unewdef);
8620 }
8621 else if (uentry_isExtern (old))
8622 {
8623 uentry_setDeclared (old, unewdef);
8624 }
8625 else
8626 {
8627 if (!uentry_isExtern (unew) && !uentry_isForward (old)
8628 && !fileloc_equal (olddef, unewdef)
8629 && !fileloc_isUndefined (olddef)
8630 && !fileloc_isUndefined (unewdef)
8631 && !fileloc_isBuiltin (olddef)
8632 && !fileloc_isBuiltin (unewdef)
8633 && !uentry_isYield (old)
8634 && !(fileloc_isLib (olddef) || fileloc_isImport (olddef)))
8635 {
8636 if (uentry_isVariable (old) || uentry_isVariable (unew))
8637 {
8638 ; /* will report redeclaration error later */
8639 }
8640 else
8641 {
8642 if (fileloc_isDefined (uentry_whereDefined (old)))
8643 {
8644 if (optgenerror
8645 (FLG_REDEF,
8646 message ("%s %q defined more than once",
8647 ekind_capName (unew->ukind),
8648 uentry_getName (unew)),
8649 uentry_whereLast (unew)))
8650 {
8651 llgenindentmsg
8652 (message ("Previous definition of %q",
8653 uentry_getName (old)),
8654 uentry_whereLast (old));
8655 }
8656 /*
8657 if (uentry_isDatatype (old) || uentry_isAnyTag (old))
8658 {
8659 uentry_copyInto (old, unew);
8660 old->sref = sRef_saveCopy (old->sref);
8661 }
8662 */
8663 }
8664 }
8665 }
8666 else
8667 {
8668 if (fileloc_isLib (olddef)
8669 || fileloc_isUndefined (olddef)
8670 || fileloc_isImport (olddef))
8671 {
8672 if (uentry_isExtern (unew))
8673 {
8674 if (uentry_isExtern (old)
8675 || (fileloc_isDefined (uentry_whereDeclared (old))
8676 && (!fileloc_equal (uentry_whereDeclared (old),
8677 uentry_whereDefined (old)))))
8678 {
8679 if (optgenerror
8680 (FLG_REDECL,
8681 message ("%s %q declared more than once",
8682 ekind_capName (unew->ukind),
8683 uentry_getName (unew)),
8684 unew->whereDeclared))
8685 {
8686 llgenindentmsg
8687 (message ("Previous declaration of %q",
8688 uentry_getName (old)),
8689 old->whereDeclared);
8690 }
8691 }
8692
8693 uentry_setExtern (old);
8694 }
8695 else
8696 {
8697 uentry_setDefined (old, unewdef);
8698 }
8699 }
8700 }
8701 }
8702
8703 uentry_checkConformance (old, unew, mustConform, FALSE);
8704
8705 old->used = old->used || unew->used;
8706 old->uses = filelocList_append (old->uses, unew->uses);
8707 unew->uses = filelocList_undefined;
8708
8709 sRef_storeState (old->sref);
8710 sRef_storeState (unew->sref);
8711
8712 if (wasForward)
8713 {
8714 old->whereDefined = fileloc_update (old->whereDefined,
8715 fileloc_undefined);
8716 }
8717
8718 /*
8719 ** No redeclaration errors for functions here, since we
8720 ** don't know if this is the definition of the function.
8721 */
8722
8723 if (fileloc_isUser (old->whereDeclared)
8724 && fileloc_isUser (unew->whereDeclared)
8725 && !fileloc_equal (old->whereDeclared, unew->whereDeclared)
8726 && !fileloc_isDefined (unew->whereDefined))
8727 {
8728 if (uentry_isFunction (old))
8729 {
8730 /*@-temptrans@*/ posRedeclared = old; /*@=temptrans@*/
8731 posLoc = fileloc_update (posLoc, unew->whereDeclared);
8732 }
8733 else
8734 {
8735 if (optgenerror (FLG_REDECL,
8736 message ("%s %q declared more than once",
8737 ekind_capName (unew->ukind),
8738 uentry_getName (unew)),
8739 unew->whereDeclared))
8740 {
8741 llgenindentmsg (message ("Previous declaration of %q",
8742 uentry_getName (old)),
8743 old->whereDeclared);
8744 }
8745 }
8746 }
8747
8748 if (fileloc_isUndefined (old->whereDefined))
8749 {
8750 old->whereDefined = fileloc_update (old->whereDefined, unew->whereDefined);
8751 }
8752 else
8753 {
8754 if (!context_processingMacros ()
8755 && fileloc_isUser (old->whereDefined)
8756 && fileloc_isUser (unew->whereDefined)
8757 && !fileloc_equal (old->whereDefined, unew->whereDefined))
8758 {
8759 if (uentry_isVariable (unew) || uentry_isFunction (unew))
8760 {
8761 if (uentry_isVariable (unew)
8762 && uentry_isExtern (unew))
8763 {
8764 if (optgenerror (FLG_REDECL,
8765 message ("%s %q declared after definition",
8766 ekind_capName (unew->ukind),
8767 uentry_getName (unew)),
8768 unew->whereDeclared))
8769 {
8770 llgenindentmsg (message ("Definition of %q",
8771 uentry_getName (old)),
8772 old->whereDefined);
8773 }
8774 }
8775 else
8776 {
8777 if (optgenerror (FLG_REDEF,
8778 message ("%s %q redefined",
8779 ekind_capName (unew->ukind),
8780 uentry_getName (unew)),
8781 unew->whereDefined))
8782 {
8783 llgenindentmsg (message ("Previous definition of %q",
8784 uentry_getName (old)),
8785 old->whereDefined);
8786 }
8787 }
8788 }
8789 }
8790 }
8791
8792 if (uentry_isExternal (unew))
8793 {
8794 old->whereDefined = fileloc_createExternal ();
8795 }
8796
8797 if (unew->hasNameError)
8798 {
8799 old->hasNameError = TRUE;
8800 }
8801
8802 uentry_free (unew);
8803
8804 if (!old->hasNameError)
8805 {
8806 uentry_checkName (old);
8807 }
8808
8809 llassert (!ctype_isUndefined (old->utype));
8810}
8811
8812void
8813uentry_copyState (uentry res, uentry other)
8814{
8815 llassert (uentry_isValid (res));
8816 llassert (uentry_isValid (other));
8817
8818 res->used = other->used;
8819
8820 res->info->var->kind = other->info->var->kind;
8821 res->info->var->defstate = other->info->var->defstate;
8822 res->info->var->nullstate = other->info->var->nullstate;
8823 res->info->var->checked = other->info->var->checked;
8824
8825 sRef_copyState (res->sref, other->sref);
8826}
8827
8828bool
8829uentry_sameKind (uentry u1, uentry u2)
8830{
8831 if (uentry_isValid (u1) && uentry_isValid (u2))
8832 {
8833 if (uentry_isVar (u1) && uentry_isVar (u2))
8834 {
8835 ctype c1 = u1->utype;
8836 ctype c2 = u2->utype;
8837
8838 if (ctype_isUnknown (c1) || ctype_isUnknown (c2)) return FALSE;
8839
8840 /*
8841 ** both functions, or both not functions
8842 */
8843
8844 return (bool_equal (ctype_isFunction (c1), ctype_isFunction (c2)));
8845 }
8846 else
8847 {
8848 return ((u1->ukind == u2->ukind));
8849 }
8850 }
8851
8852 return FALSE;
8853}
8854
8855static void uentry_copyInto (/*@unique@*/ uentry unew, uentry old)
8856{
8857 llassert (uentry_isValid (unew));
8858 llassert (uentry_isValid (old));
8859
8860 unew->ukind = old->ukind;
8861 unew->uname = cstring_copy (old->uname);
8862 unew->utype = old->utype;
8863
8864 unew->whereSpecified = fileloc_copy (old->whereSpecified);
8865 unew->whereDefined = fileloc_copy (old->whereDefined);
8866 unew->whereDeclared = fileloc_copy (old->whereDeclared);
8867
8868 unew->sref = sRef_saveCopy (old->sref); /* Memory leak! */
8869 unew->used = old->used;
8870 unew->lset = FALSE;
8871 unew->isPrivate = old->isPrivate;
8872 unew->hasNameError = old->hasNameError;
8873 unew->uses = filelocList_undefined;
8874
8875 unew->storageclass = old->storageclass;
8876 unew->info = uinfo_copy (old->info, old->ukind);
8877}
8878
8879
8880uentry
8881uentry_copy (uentry e)
8882{
8883 if (uentry_isValid (e))
8884 {
8885 uentry enew = uentry_alloc ();
8886 DPRINTF (("copy: %s", uentry_unparseFull (e)));
8887 uentry_copyInto (enew, e);
8888 DPRINTF (("Here we are..."));
8889 DPRINTF (("original: %s", uentry_unparseFull (e)));
8890 DPRINTF (("copy: %s", uentry_unparse (enew)));
8891 DPRINTF (("copy: %s", uentry_unparseFull (enew)));
8892 return enew;
8893 }
8894 else
8895 {
8896 return uentry_undefined;
8897 }
8898}
8899
8900void
8901uentry_setState (uentry res, uentry other)
8902{
8903 llassert (uentry_isValid (res));
8904 llassert (uentry_isValid (other));
8905
8906 llassert (res->ukind == other->ukind);
8907 llassert (res->ukind == KVAR);
8908
8909 res->sref = sRef_saveCopy (other->sref);
8910 res->used = other->used;
8911 filelocList_free (res->uses);
8912 res->uses = other->uses;
8913 other->uses = filelocList_undefined;
8914 res->lset = other->lset;
8915}
8916
8917void
8918uentry_mergeUses (uentry res, uentry other)
8919{
8920 llassert (uentry_isValid (res));
8921 llassert (uentry_isValid (other));
8922
8923 res->used = other->used || res->used;
8924 res->lset = other->lset || res->lset;
8925 res->uses = filelocList_append (res->uses, other->uses);
8926 other->uses = filelocList_undefined;
8927}
8928
8929
8930/*
8931** This is a really ugly routine.
8932**
8933** gack...fix this one day.
8934*/
8935
8936/*
8937** flip == TRUE
8938** >> res is the false branch, other is the true branch (or continuation)
8939** flip == FALSE
8940** >> res is the true branch, other is the false branch (or continutation)
8941**
8942** opt == TRUE if,
8943**
8944** <other>
8945** if <res> ;
8946**
8947** References not effected by res are propagated from other.
8948*/
8949
8950static void
8951 branchStateError (/*@notnull@*/ uentry res, /*@notnull@*/ uentry other,
8952 bool flip, clause cl, fileloc loc)
8953{
8954 if (optgenerror
8955 (FLG_BRANCHSTATE,
8956 message ("%s %q is %s %s, but %s %s.",
8957 ekind_capName (res->ukind), uentry_getName (res),
8958 sRef_stateVerb (res->sref), clause_nameFlip (cl, flip),
8959 sRef_stateAltVerb (res->sref), clause_nameFlip (cl, !flip)),
8960 loc))
8961 {
8962 if (sRef_isDead (res->sref))
8963 {
8964 sRef_showStateInfo (res->sref);
8965 }
8966 else if (sRef_isKept (res->sref))
8967 {
8968 sRef_showAliasInfo (res->sref);
8969 }
8970 else /* dependent */
8971 {
8972 sRef_showAliasInfo (res->sref);
8973 sRef_showAliasInfo (other->sref);
8974 }
8975
8976 sRef_setAliasKind (res->sref, AK_ERROR, fileloc_undefined);
8977 }
8978}
8979
8980static bool incompatibleStates (sRef rs, sRef os)
8981{
8982 alkind rk = sRef_getAliasKind (rs);
8983 alkind ok = sRef_getAliasKind (os);
8984
8985 if (alkind_isError (rk) || alkind_isError (ok))
8986 {
8987 return FALSE;
8988 }
8989 else
8990 {
8991 return ((sRef_isDead (rs)
8992 || (alkind_isKept (rk) && !alkind_isKept (ok))
8993 || (alkind_isDependent (rk)
8994 && !alkind_isDependent (ok) && !alkind_isTemp (ok)))
8995 && (sRef_isAllocated (os) || sRef_isStateDefined (os)));
8996 }
8997}
8998
8999static void
9000 branchStateAltError (/*@notnull@*/ uentry res,
9001 /*@notnull@*/ uentry other, bool flip,
9002 clause cl, fileloc loc)
9003{
9004 if (optgenerror
9005 (FLG_BRANCHSTATE,
9006 message ("%s %q is %s %s, but %s %s.",
9007 ekind_capName (res->ukind), uentry_getName (res),
9008 sRef_stateVerb (other->sref), clause_nameFlip (cl, flip),
9009 sRef_stateAltVerb (other->sref), clause_nameFlip (cl, !flip)),
9010 loc))
9011 {
9012 if (sRef_isDead (other->sref))
9013 {
9014 sRef_showStateInfo (other->sref);
9015 }
9016 else /* kept */
9017 {
9018 sRef_showAliasInfo (other->sref);
9019 }
9020
9021 sRef_setAliasKind (res->sref, AK_ERROR, fileloc_undefined);
9022 sRef_setDefinedComplete (res->sref, fileloc_undefined);
9023
9024 sRef_setAliasKind (other->sref, AK_ERROR, fileloc_undefined);
9025 sRef_setDefinedComplete (other->sref, fileloc_undefined);
9026 }
9027}
9028
9029static bool notNull (sRef sr, bool flip)
9030{
9031 return (!sRef_definitelyNull (sr)
9032 && !(sRef_isKept (sr))
9033 && !(sRef_isDependent (sr))
9034 && !(flip ? usymtab_isProbableDeepNull (sr)
9035 : usymtab_isAltProbablyDeepNull (sr)));
9036}
9037
9038void
9039uentry_mergeState (uentry res, uentry other, fileloc loc,
9040 bool mustReturn, bool flip, bool opt,
9041 clause cl)
9042{
9043 llassert (uentry_isValid (res));
9044 llassert (uentry_isValid (other));
9045
9046 llassert (res->ukind == other->ukind);
9047 llassert (res->ukind == KVAR);
9048
9049 DPRINTF (("Merge state: %s / %s",
9050 uentry_unparse (res),
9051 uentry_unparse (other)));
9052
9053 if (sRef_isValid (res->sref))
9054 {
9055 if (!mustReturn)
9056 {
9057 if (incompatibleStates (res->sref, other->sref))
9058 {
9059 if (sRef_isThroughArrayFetch (res->sref)
9060 && !context_getFlag (FLG_STRICTBRANCHSTATE))
9061 {
9062 if (sRef_isKept (res->sref) || sRef_isKept (other->sref))
9063 {
9064 sRef_maybeKill (res->sref, loc);
9065 }
9066 else if (sRef_isPossiblyDead (other->sref))
9067 {
9068 sRef_maybeKill (res->sref, loc);
9069 }
9070 else
9071 {
9072 ;
9073 }
9074 }
9075 else
9076 {
9077 if (notNull (other->sref, flip))
9078 {
9079 if (sRef_isLocalParamVar (res->sref)
9080 && (sRef_isLocalState (other->sref)
9081 || sRef_isDependent (other->sref)))
9082 {
9083 if (sRef_isDependent (res->sref))
9084 {
9085 sRef_setDependent (other->sref, loc);
9086 }
9087 else
9088 {
9089 sRef_setDefState (res->sref, SS_UNUSEABLE, loc);
9090 }
9091 }
9092 else
9093 {
9094 branchStateError (res, other, flip, cl, loc);
9095 }
9096 }
9097 }
9098
9099 if (sRef_isKept (res->sref))
9100 {
9101 sRef_setKept (other->sref, loc);
9102 }
9103 }
9104 else
9105 {
9106 if (incompatibleStates (other->sref, res->sref))
9107 {
9108 if (notNull (res->sref, !flip))
9109 {
9110 if (sRef_isLocalParamVar (res->sref)
9111 && (sRef_isDependent (res->sref)
9112 || sRef_isLocalState (res->sref)))
9113 {
9114 if (sRef_isDependent (other->sref))
9115 {
9116 sRef_setDependent (res->sref, loc);
9117 }
9118 else
9119 {
9120 sRef_setDefState (res->sref, SS_UNUSEABLE, loc);
9121 }
9122 }
9123 else
9124 {
9125 if (sRef_isParam (other->sref))
9126 {
9127 /*
9128 ** If the local variable associated
9129 ** with the param has the correct state,
9130 ** its okay.
9131 ** (e.g., free (s); s = new(); ...
9132 */
9133
9134 uentry uvar = usymtab_lookupSafe (other->uname);
9135
9136 if (uentry_isValid (uvar)
9137 && ((sRef_isDead (other->sref)
9138 && sRef_isOnly (uvar->sref))
9139 || (sRef_isDependent (other->sref)
9140 && sRef_isOwned (uvar->sref))))
9141 {
9142 /* no error */
9143 }
9144 else
9145 {
9146 branchStateAltError (res, other,
9147 flip, cl, loc);
9148 }
9149 }
9150 else
9151 {
9152 branchStateAltError (res, other,
9153 flip, cl, loc);
9154 }
9155 }
9156 }
9157 }
9158
9159 if (sRef_isKept (other->sref))
9160 {
9161 sRef_setKept (res->sref, loc);
9162 }
9163 }
9164
9165 if (opt)
9166 {
9167 DPRINTF (("Merge opt..."));
9168 sRef_mergeOptState (res->sref, other->sref, cl, loc);
9169 DPRINTF (("Done!"));
9170 }
9171 else
9172 {
9173 sRef_mergeState (res->sref, other->sref, cl, loc);
9174 }
9175 }
9176 else
9177 {
9178 if (sRef_isModified (other->sref))
9179 {
9180 sRef_setModified (res->sref);
9181 }
9182 }
9183
9184 if (cl == DOWHILECLAUSE)
9185 {
9186 res->used = other->used || res->used;
9187 res->lset = other->lset || res->lset;
9188 res->uses = filelocList_append (res->uses, other->uses);
9189 other->uses = filelocList_undefined;
9190 }
9191 else
9192 {
9193 if (sRef_isMacroParamRef (res->sref)
9194 && !uentry_isSefParam (other)
9195 && !uentry_isSefParam (res))
9196 {
9197 bool hasError = FALSE;
9198
9199 if (bool_equal (res->used, other->used))
9200 {
9201 res->used = other->used;
9202 }
9203 else
9204 {
9205 if (other->used && !flip)
9206 {
9207 hasError =
9208 optgenerror
9209 (FLG_MACROPARAMS,
9210 message ("Macro parameter %q used in true clause, "
9211 "but not in false clause",
9212 uentry_getName (res)),
9213 uentry_whereDeclared (res));
9214 }
9215 else
9216 {
9217 hasError =
9218 optgenerror
9219 (FLG_MACROPARAMS,
9220 message ("Macro parameter %q used in false clause, "
9221 "but not in true clause",
9222 uentry_getName (res)),
9223 uentry_whereDeclared (res));
9224 }
9225 res->used = TRUE;
9226
9227 if (hasError)
9228 {
9229 /* make it sef now, prevent more errors */
9230 res->info->var->kind = VKREFSEFPARAM;
9231 }
9232 }
9233 }
9234 else
9235 {
9236 res->used = other->used || res->used;
9237 res->lset = other->lset || res->lset;
9238 res->uses = filelocList_append (res->uses, other->uses);
9239 other->uses = filelocList_undefined;
9240 }
9241 }
9242 }
9243}
9244
9245void uentry_setUsed (uentry e, fileloc loc)
9246{
9247 static bool firstTime = TRUE;
9248 static bool showUses = FALSE;
9249 static bool exportLocal = FALSE;
9250
9251 if (firstTime)
9252 {
9253 /* need to track uses is FLG_SHOWUSES or FLG_EXPORTLOCAL is true */
9254
9255 showUses = context_getFlag (FLG_SHOWUSES);
9256 exportLocal = context_maybeSet (FLG_EXPORTLOCAL);
9257
9258 firstTime = FALSE;
9259 }
9260
9261 if (uentry_isValid (e))
9262 {
9263 int dp;
9264
9265 if (sRef_isMacroParamRef (e->sref))
9266 {
9267 if (uentry_isYield (e) || uentry_isSefParam (e))
9268 {
9269 ;
9270 }
9271 else
9272 {
9273 if (context_inConditional ())
9274 {
9275 if (optgenerror
9276 (FLG_MACROPARAMS,
9277 message ("Macro parameter %q used in conditionally "
9278 "executed code (may or may not be "
9279 "evaluated exactly once)",
9280 uentry_getName (e)),
9281 loc))
9282 {
9283 e->info->var->kind = VKREFSEFPARAM;
9284 }
9285 }
9286 else
9287 {
9288 if ((e)->used)
9289 {
9290 if (optgenerror
9291 (FLG_MACROPARAMS,
9292 message ("Macro parameter %q used more than once",
9293 uentry_getName (e)),
9294 uentry_whereDeclared (e)))
9295 {
9296 e->info->var->kind = VKREFSEFPARAM;
9297 }
9298 }
9299 }
9300 }
9301 }
9302
9303 if ((dp = uentry_directParamNo (e)) >= 0)
9304 {
9305 uentry_setUsed (usymtab_getParam (dp), loc);
9306 }
9307
9308 e->used = TRUE;
9309
9310 if (!sRef_isLocalVar (e->sref))
9311 {
9312 if (showUses)
9313 {
9314 e->uses = filelocList_add (e->uses, fileloc_copy (loc));
9315 }
9316 else
9317 {
9318 if (exportLocal)
9319 {
9320 if (context_inMacro ())
9321 {
9322 e->uses = filelocList_addUndefined (e->uses);
9323 }
9324 else
9325 {
9326 e->uses = filelocList_addDifferentFile
9327 (e->uses,
9328 uentry_whereDeclared (e),
9329 loc);
9330 }
9331 }
9332 }
9333 }
9334 }
9335}
9336
9337bool uentry_isReturned (uentry u)
9338{
9339 return (uentry_isValid (u) && uentry_isVar (u)
9340 && (u->info->var->kind == VKRETPARAM
9341 || u->info->var->kind == VKSEFRETPARAM));
9342}
9343
9344/*@exposed@*/ sRef uentry_returnedRef (uentry u, exprNodeList args)
9345{
9346 llassert (uentry_isRealFunction (u));
9347
9348 if (ctype_isFunction (u->utype)
9349 && sRef_isStateSpecial (uentry_getSref (u)))
9350 {
9351 specialClauses clauses = uentry_getSpecialClauses (u);
9352 sRef res = sRef_makeNew (ctype_returnValue (u->utype), u->sref, u->uname);
9353
9354 sRef_setAllocated (res, g_currentloc);
9355
9356 specialClauses_postElements (clauses, cl)
9357 {
9358 sRefSet refs = specialClause_getRefs (cl);
9359 sRefMod modf = specialClause_getEffectFunction (cl);
9360
9361 sRefSet_elements (refs, el)
9362 {
9363 sRef base = sRef_getRootBase (el);
9364
9365 if (sRef_isResult (base))
9366 {
9367 if (modf != NULL)
9368 {
9369 sRef sr = sRef_fixBase (el, res);
9370 modf (sr, g_currentloc);
9371 }
9372 }
9373 else
9374 {
9375 ;
9376 }
9377 } end_sRefSet_elements ;
9378
9379 } end_specialClauses_postElements ;
9380
9381 return res;
9382 }
9383 else
9384 {
9385 uentryList params;
9386 alkind ak;
9387 sRefSet prefs = sRefSet_new ();
9388 sRef res = sRef_undefined;
9389 int paramno = 0;
9390
9391 params = uentry_getParams (u);
9392
9393 uentryList_elements (params, current)
9394 {
9395 if (uentry_isReturned (current))
9396 {
9397 if (exprNodeList_size (args) >= paramno)
9398 {
9399 exprNode ecur = exprNodeList_nth (args, paramno);
9400 sRef tref = exprNode_getSref (ecur);
9401
9402 if (sRef_isValid (tref))
9403 {
9404 sRef tcref = sRef_copy (tref);
9405
9406 if (sRef_isDead (tcref))
9407 {
9408 sRef_setDefined (tcref, g_currentloc);
9409 sRef_setOnly (tcref, g_currentloc);
9410 }
9411
9412 if (sRef_isRefCounted (tcref))
9413 {
9414 /* could be a new ref now (but only if its returned) */
9415 sRef_setAliasKindComplete (tcref, AK_ERROR, g_currentloc);
9416 }
9417
9418 sRef_makeSafe (tcref);
9419
9420 prefs = sRefSet_insert (prefs, tcref);
9421 }
9422 }
9423 }
9424
9425 paramno++;
9426 } end_uentryList_elements ;
9427
9428 if (sRefSet_size (prefs) > 0)
9429 {
9430 nstate n = sRef_getNullState (u->sref);
9431
9432 if (sRefSet_size (prefs) == 1)
9433 {
9434 res = sRefSet_choose (prefs);
9435 }
9436 else
9437 {
9438 res = sRefSet_mergeIntoOne (prefs);
9439 }
9440
9441 if (nstate_isKnown (n))
9442 {
9443 sRef_setNullState (res, n, g_currentloc);
9444 }
9445 }
9446 else
9447 {
9448 if (ctype_isFunction (u->utype))
9449 {
9450 res = sRef_makeNew (ctype_returnValue (u->utype), u->sref, u->uname);
9451 }
9452 else
9453 {
9454 res = sRef_makeNew (ctype_unknown, u->sref, u->uname);
9455 }
9456
9457 if (sRef_isRefCounted (res))
9458 {
9459 sRef_setAliasKind (res, AK_NEWREF, g_currentloc);
9460 }
9461 }
9462
9463 if (sRef_getNullState (res) == NS_ABSNULL)
9464 {
9465 ctype ct = ctype_realType (u->utype);
9466
9467 if (ctype_isAbstract (ct))
9468 {
9469 sRef_setNotNull (res, g_currentloc);
9470 }
9471 else
9472 {
9473 if (ctype_isUser (ct))
9474 {
9475 sRef_setStateFromUentry (res, usymtab_getTypeEntry (ctype_typeId (ct)));
9476 }
9477 else
9478 {
9479 sRef_setNotNull (res, g_currentloc);
9480 }
9481 }
9482 }
9483
9484 if (sRef_isRefCounted (res))
9485 {
9486 sRef_setAliasKind (res, AK_NEWREF, g_currentloc);
9487 }
9488 else if (sRef_isKillRef (res))
9489 {
9490 sRef_setAliasKind (res, AK_REFCOUNTED, g_currentloc);
9491 }
9492 else
9493 {
9494 ;
9495 }
9496
9497 ak = sRef_getAliasKind (res);
9498
9499 if (alkind_isImplicit (ak))
9500 {
9501 sRef_setAliasKind (res,
9502 alkind_fixImplicit (ak),
9503 g_currentloc);
9504 }
9505
9506 sRefSet_free (prefs);
9507
9508 return res;
9509 }
9510}
9511
9512static bool uentry_isRefCounted (uentry ue)
9513{
9514 ctype ct = uentry_getType (ue);
9515
9516 if (ctype_isFunction (ct))
9517 {
9518 return (ctype_isRefCounted (ctype_returnValue (ct)));
9519 }
9520 else
9521 {
9522 return (ctype_isRefCounted (ct));
9523 }
9524}
9525
9526/*
9527** old was declared yield in the specification.
9528** new is declared in the iter implementation.
9529*/
9530
9531void uentry_checkYieldParam (uentry old, uentry unew)
9532{
9533 cstring name;
9534
9535 llassert (uentry_isVariable (old));
9536 llassert (uentry_isVariable (unew));
9537
9538 unew->info->var->kind = VKYIELDPARAM;
9539 (void) checkTypeConformance (old, unew, TRUE);
9540 checkVarConformance (old, unew, TRUE, FALSE);
9541
9542 /* get rid of param marker */
9543
9544 name = uentry_getName (unew);
9545 cstring_free (unew->uname);
9546 unew->uname = name;
9547 unew->info->var->kind = VKREFYIELDPARAM;
9548
9549 uentry_setUsed (old, fileloc_undefined);
9550 uentry_setUsed (unew, fileloc_undefined);
9551}
9552
9553/*@observer@*/ cstring
9554uentry_ekindName (uentry ue)
9555{
9556 if (uentry_isValid (ue))
9557 {
9558 switch (ue->ukind)
9559 {
9560 case KINVALID:
9561 return cstring_makeLiteralTemp ("<Error: invalid uentry>");
9562 case KDATATYPE:
9563 return cstring_makeLiteralTemp ("Datatype");
9564 case KENUMCONST:
9565 return cstring_makeLiteralTemp ("Enum member");
9566 case KCONST:
9567 return cstring_makeLiteralTemp ("Constant");
9568 case KVAR:
9569 if (uentry_isParam (ue))
9570 {
9571 return cstring_makeLiteralTemp ("Parameter");
9572 }
9573 else if (uentry_isExpandedMacro (ue))
9574 {
9575 return cstring_makeLiteralTemp ("Expanded macro");
9576 }
9577 else
9578 {
9579 return cstring_makeLiteralTemp ("Variable");
9580 }
9581 case KFCN:
9582 return cstring_makeLiteralTemp ("Function");
9583 case KITER:
9584 return cstring_makeLiteralTemp ("Iterator");
9585 case KENDITER:
9586 return cstring_makeLiteralTemp ("Iterator finalizer");
9587 case KSTRUCTTAG:
9588 return cstring_makeLiteralTemp ("Struct tag");
9589 case KUNIONTAG:
9590 return cstring_makeLiteralTemp ("Union tag");
9591 case KENUMTAG:
9592 return cstring_makeLiteralTemp ("Enum tag");
9593 case KELIPSMARKER:
9594 return cstring_makeLiteralTemp ("Optional parameters");
9595 }
9596 }
9597 else
9598 {
9599 return cstring_makeLiteralTemp ("<Undefined>");
9600 }
9601
9602 BADEXIT;
9603}
9604
9605void uentry_setHasNameError (uentry ue)
9606{
9607 llassert (uentry_isValid (ue));
9608
9609 ue->hasNameError = TRUE;
9610}
9611
9612void uentry_checkName (uentry ue)
9613{
9614 if (uentry_isValid (ue)
9615 && !uentry_isElipsisMarker (ue)
9616 && context_getFlag (FLG_NAMECHECKS)
9617 && !ue->hasNameError
9618 && !uentry_isEndIter (ue)
9619 && !fileloc_isBuiltin (uentry_whereLast (ue))
9620 && (uentry_isExpandedMacro (ue) || !uentry_isForward (ue)))
9621 {
9622
9623 if (uentry_isPriv (ue))
9624 {
9625 ; /* any checks here? */
9626 }
9627 else if (fileloc_isExternal (uentry_whereDefined (ue)))
9628 {
9629 ; /* no errors for externals */
9630 }
9631 else
9632 {
9633 int scope;
9634
9635 if (uentry_isExpandedMacro (ue))
9636 {
9637 scope = globScope;
9638 }
9639 else
9640 {
9641 if (uentry_isExpandedMacro (ue))
9642 {
9643 scope = fileScope;
9644 }
9645 else if (uentry_isVariable (ue))
9646 {
9647 sRef sr = uentry_getSref (ue);
9648
9649 if (sRef_isValid (sr))
9650 {
9651 scope = sRef_getScope (sr);
9652 }
9653 else
9654 {
9655 scope = fileScope;
9656 }
9657 }
9658 else if (uentry_isFunction (ue)
9659 || uentry_isIter (ue)
9660 || uentry_isEndIter (ue)
9661 || uentry_isConstant (ue))
9662 {
9663 scope = uentry_isStatic (ue) ? fileScope : globScope;
9664 }
9665 else /* datatypes, etc. must be global */
9666 {
9667 scope = globScope;
9668 }
9669
9670 usymtab_checkDistinctName (ue, scope);
9671 }
9672
9673 if (context_getFlag (FLG_CPPNAMES))
9674 {
9675 if (checkCppName (uentry_rawName (ue), uentry_whereLast (ue)))
9676 {
9677 uentry_setHasNameError (ue);
9678 }
9679 }
9680
9681 if (scope == globScope)
9682 {
9683 checkGlobalName (ue);
9684
9685 if (context_getFlag (FLG_ANSIRESERVED))
9686 {
9687 if (uentry_hasName (ue)
9688 && !uentry_isAnyTag (ue))
9689 {
9690 if (checkAnsiName (uentry_rawName (ue),
9691 uentry_whereLast (ue)))
9692 {
9693 uentry_setHasNameError (ue);
9694 }
9695 }
9696 }
9697 }
9698 else
9699 {
9700 checkLocalName (ue);
9701
9702 if (context_getFlag (FLG_ANSIRESERVEDLOCAL))
9703 {
9704 if (uentry_hasName (ue)
9705 && !uentry_isAnyTag (ue))
9706 {
9707 if (checkAnsiName (uentry_rawName (ue),
9708 uentry_whereLast (ue)))
9709 {
9710 uentry_setHasNameError (ue);
9711 }
9712 }
9713 }
9714 }
9715
9716 DPRINTF (("Check prefix: %s", uentry_unparse (ue)));
9717 checkPrefix (ue);
9718 }
9719 }
9720}
9721
9722/*@exposed@*/ uentry uentry_makeUnrecognized (cstring c, /*@keep@*/ fileloc loc)
9723{
9724 uentry ue;
9725 fileloc tloc;
9726
9727 /*
9728 ** Can't but unrecognized ids in macros in global scope, because srefs will break! */
9729 if (!context_inMacro ())
9730 {
9731 sRef_setGlobalScopeSafe ();
9732 }
9733
9734 ue = uentry_makeVariable (c, ctype_unknown, loc, FALSE);
9735 uentry_setUsed (ue, loc);
9736
9737 tloc = fileloc_createExternal ();
9738 uentry_setDefined (ue, tloc);
9739 fileloc_free (tloc);
9740 uentry_setHasNameError (ue);
9741
9742 if (context_getFlag (FLG_REPEATUNRECOG))
9743 {
9744 uentry_markOwned (ue);
9745 }
9746 else
9747 {
9748 ue = usymtab_supReturnFileEntry (ue);
9749 }
9750
9751 if (!context_inMacro ())
9752 {
9753 sRef_clearGlobalScopeSafe ();
9754 }
9755
9756 return ue;
9757}
9758
9759/* new start modifications */
dc92450f 9760/*
616915dd 9761void uentry_testInRange (uentry p_e, uentry cconstant) {
9762 if( uentry_isValid(p_e) ) {
9763 if( sRef_isValid (p_e->sref) ) {
9764 char * t = cstring_toCharsSafe (uentry_unparse(cconstant) );
9765 int index = atoi( t );
9766 free (t);
9767 usymtab_testInRange (p_e->sref, index);
9768 }//end if
9769 }//endif
9770}
dc92450f 9771*/
616915dd 9772
bb25bea6 9773/* void uentry_setStringLength (uentry p_e, uentry cconstant) { */
9774/* if( uentry_isValid(p_e) ) { */
9775/* if( p_e->info != NULL) { */
9776/* if( p_e->info->var != NULL) { */
9777/* char *t = cstring_toCharsSafe (uentry_unparse(cconstant)); */
9778/* int length = atoi( t ); */
9779/* free (t); */
9780/* p_e->info->var->bufinfo->len = length; */
9781/* p_e->sref->bufinfo.len = length; */
9782/* printf("Set string length of buff to %d \n", p_e->sref->bufinfo.size); */
9783/* }//end if */
9784/* }//endif */
9785/* }//end if */
9786/* } */
9787
9788
9789static void uentry_setBufferSize (uentry p_e, exprNode cconstant) {
616915dd 9790if( uentry_isValid(p_e) ) {
9791 if( p_e->info != NULL) {
9792 if( p_e->info->var != NULL) {
9793 int size = atoi(cstring_toCharsSafe(exprNode_unparse(cconstant) ) );
9794 p_e->info->var->bufinfo->size = size;
9795 p_e->sref->bufinfo.size = size;
9796 printf("Set buffer size to %d \n", p_e->sref->bufinfo.size);
9797 // fprintf(stderr, "For %s and %s\n", uentry_unparse(p_e) );
9798 // fprintf(stderr, "and %d\n", size );
9799
9800 }//end if
9801 }//endif
9802}//end if
9803}
9804
9805
9806/* start modifications */
9807/*
9808requires: p_e is defined, is a ptr/array variable
9809modifies: p_e
9810effects: sets the state of the variable
9811*/
9812
9813void uentry_setPossiblyNullTerminatedState (uentry p_e) {
9814 if( uentry_isValid(p_e) ) {
9815 if( p_e->info != NULL) {
9816 if( p_e->info->var != NULL) {
9817 p_e->info->var->bufinfo->bufstate = BB_POSSIBLYNULLTERMINATED;
9818 p_e->sref->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
9819 return;
9820 }/* End if */
9821 }/* End if */
9822 }/* End if */
9823
9824 fprintf(stderr, "uentry:Error in setPossiblyNullTerminatedState\n");
9825}
9826
9827/*
9828requires: p_e is defined, is a ptr/array variable
9829modifies: p_e
9830effects: sets the size of the buffer
9831*/
9832
9833void uentry_setNullTerminatedState (uentry p_e) {
9834 if( uentry_isValid(p_e) ) {
9835 if( p_e->info != NULL) {
9836 if( p_e->info->var != NULL) {
9837 p_e->info->var->bufinfo->bufstate = BB_NULLTERMINATED;
9838 p_e->sref->bufinfo.bufstate = BB_NULLTERMINATED;
9839 return;
9840 }//End if
9841 }//End if
9842 }//End if
9843
9844 fprintf(stderr, "uentry:Error in setNullTerminatedState\n");
9845}
9846
9847
9848/*
9849requires: p_e is defined, is a ptr/array variable
9850modifies: p_e
9851effects: sets the state of the variable
9852*/
9853
bb25bea6 9854/* void uentry_setNotNullTerminatedState (uentry p_e) { */
9855/* if( uentry_isValid(p_e) ) { */
9856/* if( p_e->info != NULL) { */
9857/* if( p_e->info->var != NULL) { */
9858/* p_e->info->var->bufinfo->bufstate = BB_NOTNULLTERMINATED; */
9859/* p_e->sref->bufinfo.bufstate = BB_NOTNULLTERMINATED; */
9860/* return; */
9861/* }//End if */
9862/* }//End if */
9863/* }//End if */
616915dd 9864
bb25bea6 9865/* fprintf(stderr, "uentry:Error in setNotNullTerminatedState\n"); */
9866/* } */
616915dd 9867
9868
9869/*
9870requires: p_e is defined, is a ptr/array variable
9871modifies: p_e
9872effects: sets the size of the buffer
9873*/
9874
9875void uentry_setSize (uentry p_e, int size) {
9876 if( uentry_isValid(p_e) ) {
9877 if( p_e->info != NULL) {
9878 if( p_e->info->var != NULL) {
9879 p_e->info->var->bufinfo->size = size;
9880 p_e->sref->bufinfo.size = size;
9881 return;
9882 }//End if
9883 }//End if
9884 }//End if
9885
9886 fprintf(stderr, "uentry:Error in setSize\n");
9887}
9888
9889
9890/*
9891requires: p_e is defined, is a ptr/array variable
9892modifies: p_e
9893effects: sets the length of the buffer
9894*/
9895
bb25bea6 9896 void uentry_setLen (uentry p_e, int len) {
616915dd 9897 if( uentry_isValid(p_e) ) {
9898 if( p_e->info != NULL) {
9899 if( p_e->info->var != NULL) {
9900 p_e->info->var->bufinfo->len = len;
9901 p_e->sref->bufinfo.len = len;
9902 return;
9903 }//End if
9904 }//End if
9905 }//End if
9906
9907 fprintf(stderr, "uentry:Error in setLen\n");
9908}
9909
9910/*@=type*/
This page took 1.363829 seconds and 5 git commands to generate.