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