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