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