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