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