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