]> andersk Git - splint.git/blame - src/uentry.c
Fixed processing of multi-dimensional arrays.
[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)));
c09ebffe 3080 DPRINTF (("Base: %s [%d]", ctype_unparse (base), ctype_isFixedArray (base)));
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
28bf4b0b 3360 DPRINTF (("Here we are: %s", sRef_unparseFull (e->sref)));
616915dd 3361 e->info->var->defstate = sRef_getDefState (e->sref);
3362 e->info->var->nullstate = sRef_getNullState (e->sref);
3363
6970c11b 3364 /* start modifications */
3365 /* This function sets the uentry for a pointer or array variable declaration,
3366 it allocates memory and sets the fields. We check if the type of the variable
3367 is a pointer or array and allocate a `bbufinfo' struct accordingly */
3368
abd7f895 3369 if (ctype_isArray (t) || ctype_isPointer(t))
3370 {
b73d1009 3371 e->info->var->bufinfo = dmalloc (sizeof (*e->info->var->bufinfo));
abd7f895 3372 e->info->var->bufinfo->bufstate = BB_NOTNULLTERMINATED;
3373 sRef_setNotNullTerminatedState (s);
3374 }
3375 else
3376 {
3377 e->info->var->bufinfo = NULL;
3378 }/* end else */
3379 /* end modification */
616915dd 3380
3381 return (e);
3382}
3383
3384bool
3385uentry_isYield (uentry ue)
3386{
3387 return (uentry_isVariable (ue)
3388 && (ue->info->var->kind == VKYIELDPARAM
3389 || ue->info->var->kind == VKREFYIELDPARAM));
3390}
3391
3392static bool
3393uentry_isRefsField (uentry ue)
3394{
3395 return (uentry_isVariable (ue) && sRef_isRefsField (ue->sref));
3396}
3397
3398/*@only@*/ /*@notnull@*/
3399uentry uentry_makeVariable (cstring n, ctype t, fileloc f, bool isPriv)
3400{
3401 return (uentry_makeVariableAux (n, t, f, sRef_makeType (t), isPriv,
3402 fileloc_isSpec (f) ? VKSPEC : VKNORMAL));
3403}
3404
3405/*
3406** functions
3407*/
3408
3409void uentry_makeVarFunction (uentry ue)
3410{
3411 alkind ak;
3412 exkind ek;
3413 uvinfo oldInfo;
3414 fileloc loc;
3415
3416 llassert (uentry_isValid (ue));
3417 llassert (!sRef_modInFunction ());
3418
3419 ak = sRef_getOrigAliasKind (ue->sref);
3420 ek = sRef_getOrigExKind (ue->sref);
3421
b072092f 3422 llassert (uentry_isVariable (ue));
616915dd 3423 oldInfo = ue->info->var;
3424
ac35a6ab 3425 DPRINTF (("ue: %s", uentry_unparseFull (ue)));
3426 llassert (ctype_isUnknown (ue->utype) || ctype_isFunction (ctype_realType (ue->utype)));
616915dd 3427
3428 /*
ac35a6ab 3429 ** expanded macro is marked used
616915dd 3430 */
3431
efd360a3 3432 ue->used = ue->used || (oldInfo->kind == VKEXPMACRO);
616915dd 3433
3434 ue->ukind = KFCN;
3435 ue->info->fcn = (ufinfo) dmalloc (sizeof (*ue->info->fcn));
3436 ue->info->fcn->exitCode = XK_UNKNOWN;
28bf4b0b 3437 ue->info->fcn->nullPred = qual_createUnknown ();
616915dd 3438 ue->info->fcn->specialCode = SPC_NONE;
3439 ue->info->fcn->access = typeIdSet_undefined;
3440 ue->info->fcn->hasGlobs = FALSE;
3441 ue->info->fcn->globs = globSet_undefined;
3442 ue->info->fcn->hasMods = FALSE;
3443 ue->info->fcn->mods = sRefSet_undefined;
3444 ue->info->fcn->specclauses = NULL;
3445 ue->info->fcn->defparams = uentryList_undefined;
3446
3447 /*drl*/
3814599d 3448 ue->info->fcn->preconditions = functionConstraint_undefined;
616915dd 3449 /*end */
3450
3451 /*drl 12/28/2000*/
efd360a3 3452 ue->info->fcn->postconditions = functionConstraint_undefined;
616915dd 3453 /*end */
616915dd 3454
3455 if (ctype_isFunction (ue->utype))
3456 {
28bf4b0b 3457 ue->sref = sRef_makeType (ctype_getReturnType (ue->utype));
616915dd 3458 }
3459 else
3460 {
3461 ue->sref = sRef_makeType (ctype_unknown);
3462 }
3463
3464 if (sRef_isRefCounted (ue->sref))
3465 {
3466 ak = AK_NEWREF;
3467 }
3468 else
3469 {
3470 if (alkind_isUnknown (ak))
3471 {
3472 if (exkind_isKnown (ek))
3473 {
28bf4b0b 3474 DPRINTF (("imp dep: %s", uentry_unparseFull (ue)));
616915dd 3475 ak = AK_IMPDEPENDENT;
3476 }
3477 else
3478 {
3479 if (context_getFlag (FLG_RETIMPONLY))
3480 {
3481 if (ctype_isFunction (ue->utype)
3482 && ctype_isVisiblySharable
28bf4b0b 3483 (ctype_realType (ctype_getReturnType (ue->utype))))
616915dd 3484 {
3485 if (uentryList_hasReturned (uentry_getParams (ue)))
3486 {
3487 ;
3488 }
3489 else
3490 {
28bf4b0b 3491 if (ctype_isImmutableAbstract (ctype_getReturnType (ue->utype)))
3492 {
3493 ;
3494 }
3495 else
3496 {
3497 ak = AK_IMPONLY;
3498 }
3499 }
616915dd 3500 }
3501 }
3502 }
3503 }
3504 }
3505
3506 loc = ue->whereDeclared;
3507
3508 sRef_setAliasKind (ue->sref, ak, loc);
3509 sRef_setNullState (ue->sref, oldInfo->nullstate, loc);
3510 sRef_setDefState (ue->sref, oldInfo->defstate, loc);
3511 sRef_setExKind (ue->sref, ek, loc);
3512
3513 if (oldInfo->kind == VKEXPMACRO)
3514 {
efd360a3 3515 ;
616915dd 3516 }
3517 else
3518 {
3519 fileloc_free (ue->whereDefined);
3520 ue->whereDefined = fileloc_undefined;
3521 }
3522
3523 uvinfo_free (oldInfo);
3524}
3525
b072092f 3526void uentry_makeConstantFunction (uentry ue)
3527{
3528 alkind ak;
3529 exkind ek;
3530 ucinfo oldInfo;
3531 fileloc loc;
3532
3533 llassert (uentry_isValid (ue));
3534 llassert (!sRef_modInFunction ());
3535
3536 ak = sRef_getOrigAliasKind (ue->sref);
3537 ek = sRef_getOrigExKind (ue->sref);
3538
3539 llassert (uentry_isConstant (ue));
3540 oldInfo = ue->info->uconst;
3541
3542 llassert (ctype_isUnknown (ue->utype) || ctype_isFunction (ue->utype));
3543
3544 /*
3545 ** expanded macro is marked used (until I write a pre-processor)
3546 */
3547
3548 ue->ukind = KFCN;
3549 ue->info->fcn = (ufinfo) dmalloc (sizeof (*ue->info->fcn));
3550 ue->info->fcn->exitCode = XK_UNKNOWN;
3551 ue->info->fcn->nullPred = qual_createUnknown ();
3552 ue->info->fcn->specialCode = SPC_NONE;
3553 ue->info->fcn->access = typeIdSet_undefined;
3554 ue->info->fcn->hasGlobs = FALSE;
3555 ue->info->fcn->globs = globSet_undefined;
3556 ue->info->fcn->hasMods = FALSE;
3557 ue->info->fcn->mods = sRefSet_undefined;
3558 ue->info->fcn->specclauses = NULL;
3559 ue->info->fcn->defparams = uentryList_undefined;
3560
3561 /*drl*/
3562 ue->info->fcn->preconditions = functionConstraint_undefined;
3563 /*end */
3564
3565 /*drl 12/28/2000*/
3566 ue->info->fcn->postconditions = functionConstraint_undefined;
3567 /*end */
3568
3569
3570 if (ctype_isFunction (ue->utype))
3571 {
3572 ue->sref = sRef_makeType (ctype_getReturnType (ue->utype));
3573 }
3574 else
3575 {
3576 ue->sref = sRef_makeType (ctype_unknown);
3577 }
3578
3579 if (sRef_isRefCounted (ue->sref))
3580 {
3581 ak = AK_NEWREF;
3582 }
3583 else
3584 {
3585 if (alkind_isUnknown (ak))
3586 {
3587 if (exkind_isKnown (ek))
3588 {
3589 DPRINTF (("imp dep: %s", uentry_unparseFull (ue)));
3590 ak = AK_IMPDEPENDENT;
3591 }
3592 else
3593 {
3594 if (context_getFlag (FLG_RETIMPONLY))
3595 {
3596 if (ctype_isFunction (ue->utype)
3597 && ctype_isVisiblySharable
3598 (ctype_realType (ctype_getReturnType (ue->utype))))
3599 {
3600 if (uentryList_hasReturned (uentry_getParams (ue)))
3601 {
3602 ;
3603 }
3604 else
3605 {
3606 if (ctype_isImmutableAbstract (ctype_getReturnType (ue->utype)))
3607 {
3608 ;
3609 }
3610 else
3611 {
3612 ak = AK_IMPONLY;
3613 }
3614 }
3615 }
3616 }
3617 }
3618 }
3619 }
3620
3621 loc = ue->whereDeclared;
3622
3623 sRef_setAliasKind (ue->sref, ak, loc);
3624 sRef_setExKind (ue->sref, ek, loc);
3625
3626 fileloc_free (ue->whereDefined);
3627 ue->whereDefined = fileloc_undefined;
3628 ucinfo_free (oldInfo);
3629}
3630
616915dd 3631void
b87215ab 3632uentry_setGlobals (uentry ue, /*@only@*/ globSet globs)
616915dd 3633{
3634 llassert (uentry_isValid (ue));
3635
b87215ab 3636 globSet_markImmutable (globs);
3637
616915dd 3638 if (uentry_isIter (ue))
3639 {
b87215ab 3640 ue->info->iter->globs = globSet_unionFree (ue->info->iter->globs, globs);
616915dd 3641 }
3642 else
3643 {
efd360a3 3644 uentry_convertVarFunction (ue);
616915dd 3645 llassert (uentry_isFunction (ue));
616915dd 3646
b87215ab 3647 ue->info->fcn->hasGlobs = TRUE;
3648 ue->info->fcn->globs = globSet_unionFree (ue->info->fcn->globs, globs);
616915dd 3649 }
3650
3651 if (context_getFlag (FLG_GLOBALSIMPMODIFIESNOTHING))
3652 {
3653 ue->info->fcn->hasMods = TRUE;
3654 }
3655}
3656
3657void uentry_addAccessType (uentry ue, typeId tid)
3658{
3659 if (uentry_isFunction (ue))
3660 {
3661 ue->info->fcn->access = typeIdSet_insert (ue->info->fcn->access, tid);
3662 }
3663 else if (uentry_isEitherConstant (ue))
3664 {
3665 ue->info->uconst->access = typeIdSet_insert (ue->info->uconst->access, tid);
3666 }
3667 else if (uentry_isIter (ue))
3668 {
3669 ue->info->iter->access = typeIdSet_insert (ue->info->iter->access, tid);
3670 }
3671 else if (uentry_isEndIter (ue))
3672 {
3673 ue->info->enditer->access = typeIdSet_insert (ue->info->enditer->access, tid);
3674 }
3675 else
3676 {
3677 llbug (message ("no access for: %q", uentry_unparse (ue)));
3678 }
3679}
3680
3681/*@only@*/ /*@notnull@*/ uentry
3682 uentry_makeFunction (cstring n, ctype t,
3683 typeId access,
3684 /*@only@*/ globSet globs, /*@only@*/ sRefSet mods,
28bf4b0b 3685 /*@only@*/ warnClause warn,
616915dd 3686 fileloc f)
3687{
b73d1009 3688 llassert (warnClause_isUndefined (warn));
616915dd 3689 return (uentry_makeFunctionAux (n, t,
3690 ((typeId_isInvalid (access)) ? typeIdSet_emptySet ()
3691 : typeIdSet_single (access)),
28bf4b0b 3692 globs, mods, warn,
3693 f,
616915dd 3694 FALSE, FALSE));
3695}
3696
616915dd 3697/*@notnull@*/ uentry
3698 uentry_makePrivFunction2 (cstring n, ctype t,
3699 typeIdSet access,
3700 globSet globs, sRefSet mods,
3701 fileloc f)
3702{
28bf4b0b 3703 return (uentry_makeFunctionAux (n, t, access, globs, mods, warnClause_undefined,
3704 f, TRUE, FALSE));
616915dd 3705}
3706
3707
3708/*@notnull@*/ uentry
3709 uentry_makeSpecFunction (cstring n, ctype t,
3710 typeIdSet access,
3711 /*@only@*/ globSet globs,
3712 /*@only@*/ sRefSet mods,
3713 fileloc f)
3714{
3715 uentry ue = uentry_makeFunctionAux (n, t, access,
28bf4b0b 3716 globs, mods, warnClause_undefined,
3717 f, FALSE, FALSE);
616915dd 3718
3719 uentry_setHasGlobs (ue);
3720 uentry_setHasMods (ue);
3721
3722 reflectImplicitFunctionQualifiers (ue, TRUE);
3723 return (ue);
3724}
616915dd 3725
3726uentry uentry_makeExpandedMacro (cstring s, fileloc f)
3727{
3728 uentry ue = uentry_makeVariableAux (s, ctype_unknown, fileloc_undefined,
3729 sRef_undefined, FALSE, VKEXPMACRO);
3730
3731 uentry_setDefined (ue, f);
3732 return ue;
3733}
3734
3735/*@notnull@*/ /*@notnull@*/ uentry
3736 uentry_makeForwardFunction (cstring n, typeId access, fileloc f)
3737{
3738 uentry ue = uentry_makeFunctionAux (n, ctype_unknown,
3739 typeIdSet_singleOpt (access),
3740 globSet_undefined, sRefSet_undefined,
28bf4b0b 3741 warnClause_undefined,
616915dd 3742 fileloc_undefined,
3743 FALSE, TRUE);
3744
3745 ue->whereDeclared = fileloc_update (ue->whereDeclared, f);
3746 return ue;
3747}
3748
3749bool uentry_isForward (uentry e)
3750{
3751 if (uentry_isValid (e))
3752 {
3753 ctype ct = uentry_getType (e);
3754
3755 return (ctype_isUnknown (ct)
3756 || (ctype_isFunction (ct)
28bf4b0b 3757 && ctype_isUnknown (ctype_getReturnType (ct))));
616915dd 3758 }
3759
3760 return FALSE;
3761}
3762
616915dd 3763/*@notnull@*/ uentry
3764uentry_makeTypeListFunction (cstring n, typeIdSet access, fileloc f)
3765{
3766 return (uentry_makeFunctionAux (n, ctype_unknown, access,
28bf4b0b 3767 globSet_undefined, sRefSet_undefined, warnClause_undefined,
3768 f,FALSE, TRUE));
616915dd 3769}
3770
3771/*@notnull@*/ uentry
3772uentry_makeUnspecFunction (cstring n, ctype t,
3773 typeIdSet access,
3774 fileloc f)
3775{
28bf4b0b 3776 uentry ue = uentry_makeFunctionAux (n, t, access, globSet_undefined,
3777 sRefSet_undefined, warnClause_undefined,
3778 f, FALSE, TRUE);
616915dd 3779
3780 reflectImplicitFunctionQualifiers (ue, TRUE);
3781 return ue;
3782}
616915dd 3783
3784/*
3785** datatypes
3786*/
3787
3788/* is exported for use by usymtab_interface */
3789
3790/*@notnull@*/ uentry
e5081f8c 3791 uentry_makeDatatypeAux (cstring n, ctype t, ynm mut, qual abstract,
616915dd 3792 fileloc f, bool priv)
3793{
3794 uentry e = uentry_alloc ();
3795
3796 DPRINTF (("Make datatype: %s / %s",
3797 n, ctype_unparse (t)));
3798
3799 /* e->shallowCopy = FALSE; */
3800 e->ukind = KDATATYPE;
3801 e->uname = cstring_copy (n);
3802 e->utype = t;
3803 e->storageclass = SCNONE;
3804 e->sref = sRef_makeUnknown ();
3805
3806 if (ctype_isUA (t))
3807 {
3808 sRef_setStateFromType (e->sref, t);
3809 }
3810
3811 uentry_setSpecDef (e, f);
3812
b73d1009 3813 e->warn = warnClause_undefined;
616915dd 3814 e->uses = filelocList_new ();
3815 e->isPrivate = priv;
3816 e->hasNameError = FALSE;
3817
3818 e->used = FALSE;
3819 e->lset = FALSE;
3820
3821 e->info = (uinfo) dmalloc (sizeof (*e->info));
3822 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
28bf4b0b 3823 e->info->datatype->abs = abstract;
616915dd 3824 e->info->datatype->mut = mut;
3825 e->info->datatype->type = ctype_undefined;
3826
3827 if (uentry_isDeclared (e))
3828 {
3829 uentry_setDefined (e, f);
3830 }
3831
e5081f8c 3832 if (qual_isAbstract (abstract) && !(uentry_isCodeDefined (e)))
616915dd 3833 {
3834 sRef_setNullState (e->sref, NS_ABSNULL, uentry_whereDeclared (e));
3835 }
3836
3837 return (e);
3838}
3839
3840/*@notnull@*/ uentry
e5081f8c 3841 uentry_makeDatatype (cstring n, ctype t, ynm mut, qual abstract, fileloc f)
616915dd 3842{
28bf4b0b 3843 return (uentry_makeDatatypeAux (n, t, mut, abstract, f, FALSE));
616915dd 3844}
3845
e5081f8c 3846/*@notnull@*/ uentry uentry_makeBoolDatatype (qual abstract)
616915dd 3847{
3848 uentry ret = uentry_makeDatatypeAux (context_getBoolName (),
28bf4b0b 3849 ctype_bool, NO, abstract,
616915dd 3850 fileloc_getBuiltin (),
3851 FALSE);
3852
3853 ret->info->datatype->type = ctype_bool;
3854 return ret;
3855}
3856
3857/*
3858** iters
3859*/
3860
3861static /*@only@*/ /*@notnull@*/ uentry
3862 uentry_makeIterAux (cstring n, typeIdSet access, ctype ct,
3863 /*@only@*/ fileloc f)
3864{
3865 uentry e = uentry_alloc ();
3866
3867 e->ukind = KITER;
3868 e->uname = cstring_copy (n);
3869 e->utype = ct;
3870 e->sref = sRef_makeUnknown ();
3871 e->storageclass = SCNONE;
3872 e->used = FALSE;
3873 e->lset = FALSE;
3874
3875 uentry_setSpecDef (e, f);
3876
b73d1009 3877 e->warn = warnClause_undefined;
616915dd 3878 e->uses = filelocList_new ();
3879 e->isPrivate = FALSE;
3880 e->hasNameError = FALSE;
3881
3882 e->info = (uinfo) dmalloc (sizeof (*e->info));
3883 e->info->iter = (uiinfo) dmalloc (sizeof (*e->info->iter));
3884 e->info->iter->access = access;
3885 e->info->iter->mods = sRefSet_undefined;
3886 e->info->iter->globs = globSet_undefined;
3887
3888 uentry_checkIterArgs (e);
3889 return (e);
3890}
3891
3892/*@notnull@*/ uentry uentry_makeIter (cstring n, ctype ct, fileloc f)
3893{
3894 return (uentry_makeIterAux (n, context_fileAccessTypes (), ct, f));
3895}
3896
3897static /*@notnull@*/ uentry
3898uentry_makeEndIterAux (cstring n, typeIdSet access, /*@only@*/ fileloc f)
3899{
3900 uentry e = uentry_alloc ();
3901
3902 /* e->shallowCopy = FALSE; */
3903 e->ukind = KENDITER;
3904 e->storageclass = SCNONE;
3905 e->uname = message ("end_%s", n);
3906 e->utype = ctype_unknown;
3907 e->sref = sRef_makeUnknown ();
3908
3909 uentry_setSpecDef (e, f);
3910
3911 e->used = FALSE;
3912 e->lset = FALSE;
3913
3914 e->uses = filelocList_new ();
3915 e->isPrivate = FALSE;
3916 e->hasNameError = FALSE;
3917
3918 e->info = (uinfo) dmalloc (sizeof (*e->info));
3919 e->info->enditer = (ueinfo) dmalloc (sizeof (*e->info->enditer));
3920
3921 e->info->enditer->access = access;
b73d1009 3922 e->warn = warnClause_undefined;
616915dd 3923
3924 return (e);
3925}
3926
3927/*@notnull@*/ /*@only@*/ uentry uentry_makeEndIter (cstring n, fileloc f)
3928{
3929 return (uentry_makeEndIterAux (n, context_fileAccessTypes (), f));
3930}
3931
3932/*
3933** tags
3934*/
3935
3936static /*@only@*/ /*@notnull@*/ uentry
3937 uentry_makeTagAux (cstring n, ctype t,
3938 /*@only@*/ fileloc fl,
3939 bool priv, ekind kind)
3940{
3941 uentry e = uentry_alloc ();
3942
3943 if (kind != KSTRUCTTAG && kind != KUNIONTAG && kind != KENUMTAG)
3944 {
3945 llbuglit ("uentry_makeTagAux: not a tag type");
3946 }
3947
3948 e->ukind = kind;
3949 /* e->shallowCopy = FALSE; */
3950 e->uname = cstring_copy (n);
3951
3952 e->utype = t;
3953 e->sref = sRef_makeUnknown ();
3954 e->storageclass = SCNONE;
3955
3956 uentry_setSpecDef (e, fl);
3957
3958 e->used = FALSE;
3959 e->lset = FALSE;
3960
3961 e->uses = filelocList_new ();
3962 e->isPrivate = priv;
3963 e->hasNameError = FALSE;
3964
3965 e->info = (uinfo) dmalloc (sizeof (*e->info));
3966 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
e5081f8c 3967 e->info->datatype->abs = qual_createUnknown ();
616915dd 3968 e->info->datatype->mut = (kind == KENUMTAG) ? NO : MAYBE;
3969 e->info->datatype->type = t;
b73d1009 3970 e->warn = warnClause_undefined;
616915dd 3971
3972 if (uentry_isDeclared (e))
3973 {
3974 uentry_setDefined (e, fl);
3975 }
3976
3977 return (e);
3978}
3979
3980uentry uentry_makeStructTagLoc (cstring n, ctype t)
3981{
3982 cstring sname = makeStruct (n);
3983 uentry ret = uentry_makeTagAux (sname, t, setLocation (), FALSE, KSTRUCTTAG);
3984
3985 cstring_free (sname);
3986 return (ret);
3987}
3988
3989/*@only@*/ uentry
3990uentry_makeStructTag (cstring n, ctype t, fileloc loc)
3991{
3992 cstring sname = makeStruct (n);
3993 uentry ret = uentry_makeTagAux (sname, t, loc, FALSE, KSTRUCTTAG);
3994
3995 cstring_free (sname);
3996 return ret;
3997}
3998
3999/*@only@*/ uentry
4000uentry_makeUnionTag (cstring n, ctype t, fileloc loc)
4001{
4002 cstring uname = makeUnion (n);
4003 uentry ret = uentry_makeTagAux (uname, t, loc, FALSE, KUNIONTAG);
4004
4005 cstring_free (uname);
4006 return (ret);
4007}
4008
616915dd 4009uentry
4010uentry_makeEnumTag (cstring n, ctype t, fileloc loc)
4011{
4012 cstring ename = makeEnum (n);
4013 uentry ret = uentry_makeTagAux (ename, t, loc, FALSE, KENUMTAG);
4014
4015 cstring_free (ename);
4016 return ret;
4017}
616915dd 4018
4019uentry
4020uentry_makeUnionTagLoc (cstring n, ctype t)
4021{
4022 cstring uname = makeUnion (n);
4023 uentry ret = uentry_makeTagAux (uname, t, setLocation (), FALSE, KUNIONTAG);
4024
4025 cstring_free (uname);
4026 return ret;
4027}
4028
4029uentry
4030uentry_makeEnumTagLoc (cstring n, ctype t)
4031{
4032 cstring ename = makeEnum (n);
4033 uentry ret = uentry_makeTagAux (ename, t, setLocation (), FALSE, KENUMTAG);
4034
4035 cstring_free (ename);
4036 return ret;
4037}
4038
4039bool
4040uentry_isStructTag (uentry ue)
4041{
4042 return (uentry_isValid (ue) && ue->ukind == KSTRUCTTAG);
4043}
4044
4045bool
4046uentry_isUnionTag (uentry ue)
4047{
4048 return (uentry_isValid (ue) && ue->ukind == KUNIONTAG);
4049}
4050
4051bool
4052uentry_isEnumTag (uentry ue)
4053{
4054 return (uentry_isValid (ue) && ue->ukind == KENUMTAG);
4055}
4056
4057bool
4058uentry_isAnyTag (uentry ue)
4059{
4060 return (uentry_isStructTag (ue)
4061 || uentry_isUnionTag (ue)
4062 || uentry_isEnumTag (ue));
4063}
4064
4065static /*@unchecked@*/ /*@only@*/ uentry emarker = NULL;
4066
4067extern void uentry_destroyMod (void)
4068 /*@globals killed emarker@*/ /*@modifies emarker@*/
4069{
4070 static bool wasDestroyed = FALSE;
4071
4072 llassert (!wasDestroyed);
4073
4074 if (emarker != NULL)
4075 {
4076 uentry_reallyFree (emarker);
4077 }
4078
4079 wasDestroyed = TRUE;
4080}
4081
4082uentry
4083uentry_makeElipsisMarker (void)
4084{
4085 if (emarker == NULL)
4086 {
4087 emarker = uentry_alloc ();
4088
4089 emarker->ukind = KELIPSMARKER;
4090 emarker->uname = cstring_makeLiteral ("...");
4091 emarker->utype = ctype_elipsMarker;
4092 emarker->sref = sRef_undefined;
4093 emarker->storageclass = SCNONE;
4094 emarker->used = FALSE;
4095 emarker->lset = FALSE;
4096 emarker->info = NULL;
4097
4098 uentry_setSpecDef (emarker, fileloc_undefined);
4099 emarker->uses = filelocList_new ();
4100 emarker->isPrivate = FALSE;
4101 emarker->hasNameError = FALSE;
4102 }
4103
4104 /*@ignore@*/ return (emarker); /*@end@*/
4105}
4106
4107/*
4108** comparisons
4109*/
4110
4111bool
4112uentry_equiv (uentry p1, uentry p2)
4113{
4114 if (uentry_compare (p1, p2) != 0)
4115 {
4116 return FALSE;
4117 }
4118 else
4119 {
4120 return TRUE;
4121 }
4122}
4123
4124int
4125uentry_xcomparealpha (uentry *p1, uentry *p2)
4126{
4127 int res;
4128
4129 if ((res = uentry_compare (*p1, *p2)) == 0) {
4130 if ((*p1 != NULL) && (*p2 != NULL)) {
4131 res = cstring_compare ((*p1)->uname,
4132 (*p2)->uname);
4133 }
4134 }
4135
4136 return res;
4137}
4138
4139int
4140uentry_xcompareuses (uentry *p1, uentry *p2)
4141{
4142 uentry u1 = *p1;
4143 uentry u2 = *p2;
4144
4145 if (uentry_isValid (u1))
4146 {
4147 if (uentry_isValid (u2))
4148 {
4149 return (-1 * int_compare (filelocList_size (u1->uses),
4150 filelocList_size (u2->uses)));
4151 }
4152 else
4153 {
4154 return 1;
4155 }
4156 }
4157 else
4158 {
4159 if (uentry_isValid (u2))
4160 {
4161 return -1;
4162 }
4163 else
4164 {
4165 return 0;
4166 }
4167 }
4168}
4169
4170int
4171uentry_compareStrict (uentry v1, uentry v2)
4172{
4173 COMPARERETURN (uentry_compare (v1, v2));
4174
4175 if (v1 != v2 && uentry_isValid (v1) && uentry_isValid (v2))
4176 {
4177 COMPARERETURN (fileloc_compare (v1->whereDeclared, v2->whereDeclared));
4178 COMPARERETURN (fileloc_compare (v1->whereDefined, v2->whereDefined));
4179 COMPARERETURN (fileloc_compare (v1->whereSpecified, v2->whereSpecified));
4180 }
4181
4182 return 0;
4183}
4184
4185int
4186uentry_compare (uentry u1, uentry u2)
4187{
4188 if (u1 == u2) return 0;
4189
4190 if (uentry_isInvalid (u1)) return -1;
4191 if (uentry_isInvalid (u2)) return 1;
4192
4193 INTCOMPARERETURN (u1->ukind, u2->ukind);
4194 COMPARERETURN (ctype_compare (u1->utype, u2->utype));
4195 COMPARERETURN (bool_compare (uentry_isPriv (u1), uentry_isPriv (u2)));
616915dd 4196 COMPARERETURN (sRef_compare (u1->sref, u2->sref));
4197
4198 switch (u1->ukind)
4199 {
4200 case KINVALID:
4201 case KELIPSMARKER:
1b8ae690 4202 /* bug detected by splint:
616915dd 4203 ** uentry.c:753,14: Return value type bool does not match declared type int: TRUE
4204 */
4205 return 0;
4206 case KENUMCONST:
4207 case KCONST:
b9904f57 4208 return (multiVal_compare (uentry_getConstantValue (u1),
4209 uentry_getConstantValue (u2)));
616915dd 4210 case KSTRUCTTAG:
4211 case KUNIONTAG:
4212 case KENUMTAG:
4213 return (ctype_compare (u1->info->datatype->type, u2->info->datatype->type));
4214 case KITER:
4215 COMPARERETURN (typeIdSet_compare (uentry_accessType (u1),
4216 uentry_accessType (u2)));
4217 return (uentryList_compareParams (uentry_getParams (u1),
4218 uentry_getParams (u2)));
4219 case KENDITER:
4220 return (typeIdSet_compare (uentry_accessType (u1),
4221 uentry_accessType (u2)));
4222 case KFCN:
28bf4b0b 4223 /*
4224 ** Functions are never equivalent
4225 */
4226
b7e84605 4227 if (u1 - u2 < 0) /* evans 2001-08-21: was: ((int) u1 < (int) u2), changed to remove gcc warning */
28bf4b0b 4228 {
4229 return -1;
4230 }
4231 else
4232 {
4233 return 1;
4234 }
4235 case KVAR:
4236
4237 COMPARERETURN (generic_compare (u1->info->var->kind, u2->info->var->kind));
4238 COMPARERETURN (generic_compare (sRef_getOrigAliasKind (u1->sref),
4239 sRef_getOrigAliasKind (u2->sref)));
4240 COMPARERETURN (generic_compare (sRef_getOrigExKind (u1->sref),
4241 sRef_getOrigExKind (u2->sref)));
616915dd 4242 COMPARERETURN (generic_compare (u1->info->var->checked,
4243 u2->info->var->checked));
4244 COMPARERETURN (generic_compare (u1->info->var->defstate,
4245 u2->info->var->defstate));
4246 return (generic_compare (u1->info->var->nullstate,
4247 u2->info->var->nullstate));
4248 case KDATATYPE:
4249 COMPARERETURN (ctype_compare (u1->info->datatype->type,
4250 u2->info->datatype->type));
4251 COMPARERETURN (ynm_compare (u1->info->datatype->mut,
4252 u2->info->datatype->mut));
e5081f8c 4253 return (generic_compare (u1->info->datatype->abs, u2->info->datatype->abs));
616915dd 4254 }
4255
4256 BADEXIT;
4257}
4258
4259/*
4260** library format:
4261**
4262** all entries are: <type>[@<info>]*#<name>
4263**
4264** info depends on kind:
4265*/
4266
4267static void
4268advanceField (char **s)
4269{
28bf4b0b 4270 reader_checkChar (s, '@');
616915dd 4271}
4272
4273static void
4274advanceName (char **s)
4275{
28bf4b0b 4276 reader_checkChar (s, '#');
616915dd 4277}
4278
4279static vkind
4280vkind_fromInt (int i)
4281{
4282 if /*@+enumint@*/ (i < VKFIRST || i > VKLAST) /*@=enumint@*/
4283 {
4284 llbuglit ("vkind_fromInt: out of range");
4285 }
4286
4287 return (vkind)i;
4288}
4289
4290static uentry
4291 uentry_makeConstantBase (/*@only@*/ cstring name, ctype ct,
4292 typeIdSet access, nstate nullstate,
4293 /*@keep@*/ fileloc loc, /*@only@*/ multiVal m)
4294{
4295 uentry e = uentry_alloc ();
4296
4297 e->ukind = KCONST;
4298 e->uname = name;
4299 e->utype = ct;
4300 e->sref = sRef_makeConst (ct);
4301
4302 sRef_setNullState (e->sref, nullstate, loc);
4303 e->storageclass = SCNONE;
4304
4305 if (fileloc_isSpec (loc))
4306 {
4307 e->whereSpecified = loc;
4308 e->whereDeclared = fileloc_undefined;
4309 }
4310 else
4311 {
4312 e->whereSpecified = fileloc_undefined;
4313 e->whereDeclared = loc;
4314 }
4315
4316 e->whereDefined = fileloc_undefined;
4317 e->uses = filelocList_new ();
4318 e->isPrivate = FALSE;
4319 e->hasNameError = FALSE;
4320
4321 e->used = FALSE;
4322 e->lset = FALSE;
4323
b73d1009 4324 e->warn = warnClause_undefined;
28bf4b0b 4325
616915dd 4326 e->info = (uinfo) dmalloc (sizeof (*e->info));
4327 e->info->uconst = (ucinfo) dmalloc (sizeof (*e->info->uconst));
616915dd 4328 e->info->uconst->access = access;
b73d1009 4329 e->info->uconst->macro = FALSE; /* fix this when macro info added to library */
b9904f57 4330 uentry_setConstantValue (e, m);
616915dd 4331 sRef_storeState (e->sref);
4332
4333 return (e);
4334}
4335
4336static /*@only@*/ uentry
4337 uentry_makeVariableBase (/*@only@*/ cstring name, ctype ct, vkind kind,
4338 sstate defstate, nstate isnull, alkind aliased,
4339 exkind exp, chkind checked,
4340 /*@only@*/ fileloc loc)
4341{
4342 uentry e = uentry_alloc ();
4343
4344 e->ukind = KVAR;
4345 e->uname = name;
4346 e->utype = ct;
4347 e->storageclass = SCNONE;
4348
4349 e->sref = sRef_makeType (ct);
4350 sRef_setNullState (e->sref, isnull, loc);
4351
4352 e->whereDefined = fileloc_undefined;
4353
4354 if (fileloc_isSpec (loc))
4355 {
4356 e->whereSpecified = loc;
4357 e->whereDeclared = fileloc_undefined;
4358 }
4359 else
4360 {
4361 e->whereSpecified = fileloc_undefined;
4362 e->whereDeclared = loc;
4363 }
4364
4365 e->isPrivate = FALSE;
4366 e->hasNameError = FALSE;
4367
4368 e->used = FALSE;
4369 e->lset = FALSE;
4370
4371 e->uses = filelocList_new ();
b73d1009 4372 e->warn = warnClause_undefined;
616915dd 4373
4374 e->info = (uinfo) dmalloc (sizeof (*e->info));
4375 e->info->var = (uvinfo) dmalloc (sizeof (*e->info->var));
4376 e->info->var->kind = kind;
4377 e->info->var->checked = checked;
4378 e->info->var->defstate = defstate;
4379
4380 sRef_setDefState (e->sref, defstate, loc);
4381
4382 e->info->var->nullstate = sRef_getNullState (e->sref);
4383
4384 sRef_setExKind (e->sref, exp, loc);
4385 sRef_setAliasKind (e->sref, aliased, loc);
4386
4387 sRef_storeState (e->sref);
4388
4389 /*DRL ADDED 9-1-2000 */
4390 e->info->var->bufinfo = NULL;
4391
4392 return (e);
4393}
4394
4395static /*@only@*/ uentry
e5081f8c 4396uentry_makeDatatypeBase (/*@only@*/ cstring name, ctype ct, qual abstract,
616915dd 4397 ynm mut, ctype rtype, alkind ak, exkind exp,
4398 sstate defstate, nstate isnull,
4399 /*@only@*/ fileloc loc)
4400{
4401 uentry e = uentry_alloc ();
4402
4403 e->ukind = KDATATYPE;
4404 /* e->shallowCopy = FALSE; */
4405 e->uname = name;
4406 e->utype = ct;
4407 e->storageclass = SCNONE;
4408 e->sref = sRef_makeUnknown ();
28bf4b0b 4409 DPRINTF (("Merge null 1: %s", sRef_unparseFull (e->sref)));
616915dd 4410
4411 /*
4412 ** This is only setting null state. (I think?)
4413 */
4414
4415 if (ctype_isUA (ct))
4416 {
4417 uentry te = usymtab_getTypeEntrySafe (ctype_typeId (ct));
4418
4419 if (uentry_isValid (te))
4420 {
4421 sRef_setStateFromUentry (e->sref, te);
4422 }
4423 else
4424 {
4425 /* problem for recursive type definitions */
4426 }
4427 }
4428
4429 sRef_setAliasKind (e->sref, ak, loc);
4430 sRef_setExKind (e->sref, exp, loc);
4431
4432 sRef_setDefState (e->sref, defstate, loc);
4433
e5081f8c 4434 if (qual_isEitherAbstract (abstract) && ctype_isUnknown (ct) && isnull == NS_UNKNOWN)
616915dd 4435 {
4436 isnull = NS_ABSNULL;
4437 }
4438
28bf4b0b 4439 DPRINTF (("Merge null: %s", sRef_unparseFull (e->sref)));
616915dd 4440 sRef_mergeNullState (e->sref, isnull);
4441
4442 e->whereDefined = fileloc_copy (loc); /*< bogus! (but necessary for lexer) >*/
4443
4444 if (fileloc_isSpec (loc))
4445 {
4446 e->whereSpecified = loc;
4447 e->whereDeclared = fileloc_undefined;
4448 }
4449 else
4450 {
4451 e->whereSpecified = fileloc_undefined;
4452 e->whereDeclared = loc;
4453 }
4454
4455 e->isPrivate = FALSE;
4456 e->hasNameError = FALSE;
b73d1009 4457 e->warn = warnClause_undefined;
616915dd 4458 e->used = FALSE;
4459 e->lset = FALSE;
4460 e->uses = filelocList_new ();
4461
4462 e->info = (uinfo) dmalloc (sizeof (*e->info));
4463 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
28bf4b0b 4464 e->info->datatype->abs = abstract;
616915dd 4465 e->info->datatype->mut = mut;
4466 e->info->datatype->type = rtype;
28bf4b0b 4467
4468 DPRINTF (("About to store: %s", sRef_unparseFull (e->sref)));
616915dd 4469 sRef_storeState (e->sref);
28bf4b0b 4470 DPRINTF (("After store: %s", sRef_unparseFull (e->sref)));
616915dd 4471
4472 return (e);
4473}
4474
616915dd 4475static void uentry_setHasGlobs (uentry ue)
4476{
4477 llassert (uentry_isFunction (ue));
4478
4479 ue->info->fcn->hasGlobs = TRUE;
4480}
4481
4482static void uentry_setHasMods (uentry ue)
4483{
4484 llassert (uentry_isFunction (ue));
4485
4486 ue->info->fcn->hasMods = TRUE;
4487}
616915dd 4488
4489bool uentry_hasGlobs (uentry ue)
4490{
4491 if (uentry_isFunction (ue))
4492 {
4493 return (ue->info->fcn->hasGlobs);
4494 }
4495
4496 return FALSE;
4497}
4498
28bf4b0b 4499bool uentry_hasStateClauseList (uentry ue)
616915dd 4500{
28bf4b0b 4501 return (uentry_isFunction (ue) && stateClauseList_isDefined (ue->info->fcn->specclauses));
616915dd 4502}
4503
ccf0a4a8 4504bool uentry_hasConditions (uentry ue)
4505{
4506 return (uentry_isFunction (ue)
4507 && (functionConstraint_isDefined (ue->info->fcn->preconditions)
4508 || functionConstraint_isDefined (ue->info->fcn->postconditions)));
4509}
4510
28bf4b0b 4511stateClauseList uentry_getStateClauseList (uentry ue)
616915dd 4512{
28bf4b0b 4513 if (!uentry_isFunction (ue))
4514 {
4515 llassert (uentry_isFunction (ue));
4516 return stateClauseList_undefined;
4517 }
4518
4519 DPRINTF (("Get state clause list: %s", uentry_unparse (ue)));
616915dd 4520 return ue->info->fcn->specclauses;
4521}
4522
4523bool uentry_hasMods (uentry ue)
4524{
4525 if (uentry_isFunction (ue))
4526 {
4527 return (ue->info->fcn->hasMods);
4528 }
4529
4530 return FALSE;
4531}
4532
4533static uentry
4534 uentry_makeFunctionBase (/*@only@*/ cstring name, ctype ct,
4535 typeIdSet access,
4536 bool hasGlobs, /*@only@*/ globSet globs,
4537 bool hasMods, /*@only@*/ sRefSet mods,
4538 alkind ak, exkind exp,
4539 sstate defstate, nstate isnull,
4540 exitkind exitCode,
4541 specCode sCode,
4542 qual nullPred,
28bf4b0b 4543 /*@only@*/ stateClauseList specclauses,
4544 /*@only@*/ warnClause warnclause,
616915dd 4545 /*@only@*/ fileloc loc)
4546{
4547 uentry e = uentry_alloc ();
4548 ctype ret;
4549
4550 /* e->shallowCopy = FALSE; */
4551 e->ukind = KFCN;
4552 e->uname = name;
4553 e->utype = ct;
4554 e->storageclass = SCNONE;
4555
4556 if (ctype_isFunction (ct))
4557 {
28bf4b0b 4558 ret = ctype_getReturnType (ct);
616915dd 4559 }
4560 else
4561 {
4562 if (ctype_isKnown (ct))
4563 {
4564 llbug (message ("not function: %s", ctype_unparse (ct)));
4565 }
4566
4567 ret = ctype_unknown;
4568 }
4569
4570 e->sref = sRef_makeType (ret);
4571
4572 if (ctype_isUA (ret))
4573 {
4574 sRef_setStateFromType (e->sref, ret);
4575 }
4576
4577 sRef_setDefined (e->sref, loc);
4578 sRef_setNullState (e->sref, isnull, loc);
4579
4580 sRef_setAliasKind (e->sref, ak, loc);
4581 sRef_setExKind (e->sref, exp, loc);
4582 sRef_setDefState (e->sref, defstate, loc);
4583
4584 e->whereSpecified = loc;
4585 e->whereDefined = fileloc_undefined;
4586
4587 e->isPrivate = FALSE;
4588 e->hasNameError = FALSE;
4589
4590 e->used = FALSE;
4591 e->lset = FALSE;
4592 e->uses = filelocList_new ();
28bf4b0b 4593 e->warn = warnclause;
616915dd 4594
4595 e->info = (uinfo) dmalloc (sizeof (*e->info));
4596 e->info->fcn = (ufinfo) dmalloc (sizeof (*e->info->fcn));
4597
4598 e->info->fcn->exitCode = exitCode;
4599 e->info->fcn->specialCode = sCode;
4600 e->info->fcn->nullPred = nullPred;
4601 e->info->fcn->access = access;
4602
4603 e->info->fcn->specclauses = specclauses;
4604 e->info->fcn->hasGlobs = hasGlobs;
4605 e->info->fcn->globs = globs;
4606
4607 e->info->fcn->hasMods = hasMods;
4608 e->info->fcn->mods = mods;
4609
4610 e->info->fcn->defparams = uentryList_undefined;
4611 e->whereDeclared = fileloc_undefined;
4612
4613 sRef_storeState (e->sref);
4614
4615 /*drl 111 30 2000*/
4616 e->info->fcn->preconditions = NULL;
4617 /* end drl */
4618
4619 /*drl 12 28 2000*/
4620 e->info->fcn->postconditions = NULL;
4621 /* end drl */
4622
4623 return (e);
4624}
4625
4626static /*@only@*/ uentry
4627 uentry_makeTagBase (/*@only@*/ cstring name, ekind tagkind,
4628 ctype ct, ctype rtype, /*@only@*/ fileloc loc)
4629{
4630 uentry e = uentry_alloc ();
4631
4632 if (tagkind != KSTRUCTTAG && tagkind != KUNIONTAG && tagkind != KENUMTAG)
4633 {
4634 llbuglit ("uentry_makeTagBase: not a tag type");
4635 }
4636
4637 /* e->shallowCopy = FALSE; */
4638 e->ukind = tagkind;
4639 e->uname = name;
4640 e->utype = ct;
4641 e->sref = sRef_makeUnknown ();
4642 e->storageclass = SCNONE;
4643
4644 if (fileloc_isSpec (loc))
4645 {
4646 e->whereSpecified = loc;
4647 e->whereDeclared = fileloc_undefined;
4648 }
4649 else
4650 {
4651 e->whereDeclared = loc;
4652 e->whereSpecified = fileloc_undefined;
4653 }
4654
4655 e->whereDefined = fileloc_undefined;
4656
4657 e->isPrivate = FALSE;
4658 e->hasNameError = FALSE;
4659
4660 e->used = FALSE;
4661 e->lset = FALSE;
4662 e->uses = filelocList_new ();
b73d1009 4663 e->warn = warnClause_undefined;
616915dd 4664
4665 e->info = (uinfo) dmalloc (sizeof (*e->info));
4666 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
e5081f8c 4667 e->info->datatype->abs = qual_createUnknown ();
616915dd 4668 e->info->datatype->mut = MAYBE;
4669 e->info->datatype->type = rtype;
4670
4671 sRef_storeState (e->sref);
4672
4673 return (e);
4674}
4675
4676static uentry
4677 uentry_makeIterBase (/*@only@*/ cstring name, typeIdSet access,
4678 ctype ct, /*@only@*/ fileloc loc)
4679{
4680 uentry e = uentry_alloc ();
4681
4682 /* e->shallowCopy = FALSE; */
4683 e->ukind = KITER;
4684 e->uname = name;
4685 e->utype = ct;
4686 e->sref = sRef_makeUnknown ();
4687 e->storageclass = SCNONE;
4688
4689 if (fileloc_isSpec (loc))
4690 {
4691 e->whereSpecified = loc;
4692 e->whereDeclared = fileloc_undefined;
4693 }
4694 else
4695 {
4696 e->whereDeclared = loc;
4697 e->whereSpecified = fileloc_undefined;
4698 }
4699
4700 e->whereDefined = fileloc_undefined;
4701
4702 e->isPrivate = FALSE;
4703 e->hasNameError = FALSE;
4704
4705 e->used = FALSE;
4706 e->lset = FALSE;
4707 e->uses = filelocList_new ();
b73d1009 4708 e->warn = warnClause_undefined;
616915dd 4709
4710 e->info = (uinfo) dmalloc (sizeof (*e->info));
4711 e->info->iter = (uiinfo) dmalloc (sizeof (*e->info->iter));
4712 e->info->iter->access = access;
4713 e->info->iter->mods = sRefSet_undefined;
4714 e->info->iter->globs = globSet_undefined;
4715
4716 sRef_storeState (e->sref);
4717 return (e);
4718}
4719
4720static uentry
4721 uentry_makeEndIterBase (/*@only@*/ cstring name, typeIdSet access,
4722 /*@only@*/ fileloc loc)
4723{
4724 uentry e = uentry_alloc ();
4725
4726 /* e->shallowCopy = FALSE; */
4727 e->ukind = KENDITER;
4728 e->storageclass = SCNONE;
4729 e->uname = name;
4730 e->utype = ctype_unknown;
4731 e->sref = sRef_makeUnknown ();
4732
4733 if (fileloc_isSpec (loc))
4734 {
4735 e->whereSpecified = loc;
4736 e->whereDeclared = fileloc_undefined;
4737 }
4738 else
4739 {
4740 e->whereDeclared = loc;
4741 e->whereSpecified = fileloc_undefined;
4742 }
4743
4744 e->whereDefined = fileloc_undefined;
4745
4746 e->isPrivate = FALSE;
4747 e->hasNameError = FALSE;
4748
4749 e->used = FALSE;
4750 e->lset = FALSE;
4751 e->uses = filelocList_new ();
b73d1009 4752 e->warn = warnClause_undefined;
616915dd 4753
4754 e->info = (uinfo) dmalloc (sizeof (*e->info));
4755 e->info->enditer = (ueinfo) dmalloc (sizeof (*e->info->enditer));
4756 e->info->enditer->access = access;
4757 sRef_storeState (e->sref);
4758
4759 return (e);
4760}
4761
4762void uentry_markFree (/*@unused@*/ /*@owned@*/ uentry u)
4763{
4764 /* should save u */
4765/*@-mustfree@*/
4766}
4767/*@=mustfree@*/
4768
4769/*@only@*/ uentry
4770uentry_undump (ekind kind, fileloc loc, char **s)
4771{
4772 uentry ue;
4773
28bf4b0b 4774 DPRINTF (("Uentry undump: %s", *s));
4775
616915dd 4776 if (**s == '!')
4777 {
28bf4b0b 4778 reader_checkChar (s, '!');
4779 reader_checkChar (s, '.');
616915dd 4780 ue = uentry_makeElipsisMarker ();
4781 }
4782 else
4783 {
4784 ctype ct = ctype_undump (s);
4785 cstring name;
4786
4787 switch (kind)
4788 {
4789 case KVAR:
4790 {
4791 vkind tkind;
4792 sstate defstate;
4793 nstate isnull;
4794 alkind aliased;
4795 exkind exp;
4796 chkind checked;
4797
28bf4b0b 4798 reader_checkChar (s, '|');
616915dd 4799
28bf4b0b 4800 if (reader_optCheckChar (s, '@'))
616915dd 4801 {
28bf4b0b 4802 tkind = vkind_fromInt (reader_getInt (s));
4803 reader_checkChar (s, '|');
616915dd 4804 }
4805 else
4806 {
4807 tkind = VKPARAM;
4808 }
4809
28bf4b0b 4810 if (reader_optCheckChar (s, '$'))
616915dd 4811 {
4812 defstate = SS_UNKNOWN;
4813 isnull = NS_UNKNOWN;
4814 aliased = AK_IMPTEMP;
4815 exp = XO_UNKNOWN;
4816 checked = CH_UNKNOWN;
4817 }
28bf4b0b 4818 else if (reader_optCheckChar (s, '&'))
616915dd 4819 {
4820 defstate = SS_DEFINED;
4821 isnull = NS_UNKNOWN;
4822 aliased = AK_IMPTEMP;
4823 exp = XO_UNKNOWN;
4824 checked = CH_UNKNOWN;
4825 }
28bf4b0b 4826 else if (reader_optCheckChar (s, '^'))
616915dd 4827 {
4828 defstate = SS_UNKNOWN;
4829 isnull = NS_UNKNOWN;
4830 aliased = AK_IMPTEMP;
4831 exp = XO_UNKNOWN;
4832 checked = CH_UNKNOWN;
4833 }
4834 else
4835 {
28bf4b0b 4836 defstate = sstate_fromInt (reader_getInt (s));
4837 advanceField (s); isnull = nstate_fromInt (reader_getInt (s));
4838 advanceField (s); aliased = alkind_fromInt (reader_getInt (s));
616915dd 4839
28bf4b0b 4840 if (reader_optCheckChar (s, '&'))
616915dd 4841 {
4842 exp = XO_UNKNOWN;
4843 checked = CH_UNKNOWN;
4844 }
4845 else
4846 {
28bf4b0b 4847 advanceField (s); exp = exkind_fromInt (reader_getInt (s));
4848 advanceField (s); checked = (chkind) (reader_getInt (s));
616915dd 4849 }
4850 }
4851
4852 advanceName (s);
28bf4b0b 4853 name = reader_getStringWord (s);
616915dd 4854
28bf4b0b 4855 llassert (!cstring_equal (name, GLOBAL_MARKER_NAME));
4856
616915dd 4857 ue = uentry_makeVariableBase (name, ct, tkind, defstate,
4858 isnull, aliased, exp,
4859 checked, fileloc_copy (loc));
4860 }
4861 break;
4862 case KDATATYPE:
4863 {
e5081f8c 4864 qual abstract;
616915dd 4865 ynm mut;
4866 ctype rtype;
4867 sstate defstate;
4868 nstate isnull;
4869 alkind aliased;
4870 exkind exp;
4871
e5081f8c 4872 advanceField (s); abstract = qual_abstractFromCodeChar (reader_loadChar (s));
28bf4b0b 4873 advanceField (s); mut = ynm_fromCodeChar (reader_loadChar (s));
4874 advanceField (s); defstate = sstate_fromInt (reader_getInt (s));
4875 advanceField (s); isnull = nstate_fromInt (reader_getInt (s));
4876 advanceField (s); aliased = alkind_fromInt (reader_getInt (s));
4877 advanceField (s); exp = exkind_fromInt (reader_getInt (s));
616915dd 4878 advanceField (s); rtype = ctype_undump (s);
4879 advanceName (s);
28bf4b0b 4880 name = reader_getStringWord (s);
4881 DPRINTF (("Datatype %s, Exp = %s", name, exkind_unparse (exp)));
4882 ue = uentry_makeDatatypeBase (name, ct, abstract, mut, rtype,
616915dd 4883 aliased, exp, defstate, isnull,
4884 fileloc_copy (loc));
4885 }
4886 break;
4887 case KFCN:
4888 {
4889 alkind ak;
4890 exkind exp;
4891 sstate defstate;
4892 nstate isnull;
4893 exitkind exitCode;
4894 specCode specc;
4895 qual nullPred;
4896 typeIdSet access;
4897 bool hasGlobs;
4898 globSet globs;
4899 bool hasMods;
4900 sRefSet mods;
28bf4b0b 4901 stateClauseList specclauses = stateClauseList_undefined;
4902 warnClause warnclause = warnClause_undefined;
616915dd 4903
28bf4b0b 4904 if (reader_optCheckChar (s, '$'))
616915dd 4905 {
4906 defstate = SS_DEFINED;
4907 isnull = NS_UNKNOWN;
4908 exitCode = XK_UNKNOWN;
4909 specc = SPC_NONE;
28bf4b0b 4910 nullPred = qual_createUnknown ();
616915dd 4911 }
4912 else
4913 {
28bf4b0b 4914 advanceField (s); defstate = sstate_fromInt (reader_getInt (s));
4915 advanceField (s); isnull = nstate_fromInt (reader_getInt (s));
4916 advanceField (s); exitCode = exitkind_fromInt (reader_getInt (s));
4917 advanceField (s); specc = specCode_fromInt (reader_getInt (s));
4918 advanceField (s); nullPred = qual_undump (s);
616915dd 4919 }
4920
28bf4b0b 4921 if (reader_optCheckChar (s, '$'))
616915dd 4922 {
4923 hasGlobs = FALSE;
4924 globs = globSet_undefined;
4925 hasMods = FALSE;
4926 mods = sRefSet_undefined;
4927 }
28bf4b0b 4928 else if (reader_optCheckChar (s, '^'))
616915dd 4929 {
4930 hasGlobs = TRUE;
4931 globs = globSet_undefined;
4932 hasMods = TRUE;
4933 mods = sRefSet_undefined;
4934 }
4935 else
4936 {
28bf4b0b 4937 advanceField (s); hasGlobs = bool_fromInt (reader_getInt (s));
616915dd 4938 advanceField (s); globs = globSet_undump (s);
28bf4b0b 4939 advanceField (s); hasMods = bool_fromInt (reader_getInt (s));
616915dd 4940 advanceField (s); mods = sRefSet_undump (s);
4941 }
4942
28bf4b0b 4943 if (reader_optCheckChar (s, '$'))
616915dd 4944 {
4945 ak = AK_UNKNOWN;
4946 exp = XO_UNKNOWN;
4947 }
4948 else
4949 {
28bf4b0b 4950 advanceField (s); ak = alkind_fromInt (reader_getInt (s));
4951 advanceField (s); exp = exkind_fromInt (reader_getInt (s));
616915dd 4952 }
4953
4954 advanceField (s); access = typeIdSet_undump (s);
4955
28bf4b0b 4956 /*
4957 ** Optional clauses: Start with @<code>:
4958 */
4959
4960 while (reader_optCheckChar (s, '@'))
616915dd 4961 {
28bf4b0b 4962 if (reader_optCheckChar (s, 'W')) /* Warn clause */
4963 {
4964 reader_checkChar (s, ':');
4965 warnclause = warnClause_undump (s);
4966 }
4967 else if (reader_optCheckChar (s, 'S')) /* stateClause List */
4968 {
4969 reader_checkChar (s, ':');
4970 specclauses = stateClauseList_undump (s);
4971 }
4972 else
4973 {
4974 BADBRANCH;
4975 }
616915dd 4976 }
4977
28bf4b0b 4978 advanceName (s); name = reader_getStringWord (s);
616915dd 4979
4980 ue = uentry_makeFunctionBase (name, ct, access,
4981 hasGlobs, globs,
4982 hasMods, mods,
4983 ak, exp, defstate, isnull,
4984 exitCode, specc, nullPred,
4985 specclauses,
28bf4b0b 4986 warnclause,
616915dd 4987 fileloc_copy (loc));
4988 DPRINTF (("Undump: %s", uentry_unparse (ue)));
4989 }
4990 break;
4991 case KITER:
4992 {
4993 typeIdSet access;
4994
4995 advanceField (s); access = typeIdSet_undump (s);
28bf4b0b 4996 advanceName (s); name = reader_getStringWord (s);
616915dd 4997
4998 ue = uentry_makeIterBase (name, access, ct,
4999 fileloc_copy (loc));
5000 }
5001 break;
5002 case KENDITER:
5003 {
5004 typeIdSet access;
5005
5006 advanceField (s); access = typeIdSet_undump (s);
28bf4b0b 5007 advanceName (s); name = reader_getStringWord (s);
616915dd 5008
5009 ue = uentry_makeEndIterBase (name, access, fileloc_copy (loc));
5010 }
5011 break;
5012 case KENUMCONST:
5013 case KCONST:
5014 {
5015 typeIdSet access;
5016 multiVal val;
5017 nstate nullstate;
5018
28bf4b0b 5019 if (reader_optCheckChar (s, '$'))
616915dd 5020 {
5021 val = multiVal_undefined;
5022 access = typeIdSet_undefined;
5023 nullstate = NS_UNKNOWN;
5024 }
5025 else
5026 {
5027 advanceField (s); val = multiVal_undump (s);
5028 advanceField (s); access = typeIdSet_undump (s);
28bf4b0b 5029 advanceField (s); nullstate = nstate_fromInt (reader_getInt (s));
616915dd 5030 }
5031
28bf4b0b 5032 advanceName (s); name = reader_getStringWord (s);
616915dd 5033
5034 ue = uentry_makeConstantBase (name, ct, access,
5035 nullstate, fileloc_copy (loc), val);
5036 break;
5037 }
5038 case KSTRUCTTAG:
5039 case KUNIONTAG:
5040 case KENUMTAG:
5041 {
5042 ctype rtype;
5043
5044 advanceField (s); rtype = ctype_undump (s);
28bf4b0b 5045 advanceName (s); name = reader_getStringWord (s);
616915dd 5046 ue = uentry_makeTagBase (name, kind, ct, rtype, fileloc_copy (loc));
5047 }
5048 break;
5049 case KINVALID:
5050 llcontbuglit ("uentry_undump: invalid");
5051 ue = uentry_undefined;
5052 break;
5053 case KELIPSMARKER:
5054 llcontbuglit ("uentry_undump: elips marker");
5055 ue = uentry_undefined;
5056 break;
5057 }
5058 }
5059
5060 return (ue);
5061}
5062
5063cstring
5064uentry_dump (uentry v)
5065{
5066 return (uentry_dumpAux (v, FALSE));
5067}
5068
5069cstring
5070uentry_dumpParam (uentry v)
5071{
5072 llassertprint (uentry_isVariable (v) || uentry_isElipsisMarker (v),
5073 ("dump: %s", uentry_unparseFull (v)));
5074
5075 return (uentry_dumpAux (v, TRUE));
5076}
5077
5078static cstring
5079uentry_dumpAux (uentry v, bool isParam)
5080{
5081 llassert (uentry_isValid (v));
28bf4b0b 5082 llassert (!uentry_isGlobalMarker (v));
616915dd 5083
28bf4b0b 5084 DPRINTF (("Dump uentry: [%p]", v));
616915dd 5085 DPRINTF (("Dumping entry: %s", uentry_unparseFull (v)));
28bf4b0b 5086
616915dd 5087 switch (v->ukind)
5088 {
5089 case KINVALID:
5090 llcontbuglit ("uentry_dump: invalid entry");
5091 return cstring_undefined;
5092 case KELIPSMARKER:
5093 return (message ("!."));
5094 case KVAR:
5095 {
5096 cstring sdump;
5097 vkind vk = v->info->var->kind;
5098 sstate dss = sRef_getDefState (v->sref);
5099 nstate nst = sRef_getNullState (v->sref);
5100 alkind alk = sRef_getAliasKind (v->sref);
5101 exkind exk = sRef_getExKind (v->sref);
5102 chkind chk = v->info->var->checked;
5103
5104 DPRINTF (("Dumping var"));
5105
5106 if (dss == SS_UNKNOWN
5107 && nst == NS_UNKNOWN
5108 && alk == AK_IMPTEMP
5109 && exk == XO_UNKNOWN
5110 && chk == CH_UNKNOWN)
5111 {
5112 sdump = cstring_makeLiteral ("$");
5113 }
5114 else if (dss == SS_DEFINED
5115 && nst == NS_UNKNOWN
5116 && alk == AK_IMPTEMP
5117 && exk == XO_UNKNOWN
5118 && chk == CH_UNKNOWN)
5119 {
5120 sdump = cstring_makeLiteral ("&");
5121 }
5122 else if (dss == SS_UNKNOWN
5123 && nst == NS_UNKNOWN
5124 && alk == AK_UNKNOWN
5125 && exk == XO_UNKNOWN
5126 && chk == CH_UNKNOWN)
5127 {
5128 sdump = cstring_makeLiteral ("^");
5129 }
5130 else if (exk == XO_UNKNOWN
5131 && chk == CH_UNKNOWN)
5132 {
5133 sdump = message ("%d@%d@%d&",
5134 (int) dss,
5135 (int) nst,
5136 (int) alk);
5137 }
5138 else
5139 {
5140 sdump = message ("%d@%d@%d@%d@%d",
e5081f8c 5141 (int) dss,
616915dd 5142 (int) nst,
5143 (int) alk,
5144 (int) exk,
5145 (int) chk);
5146 }
5147
5148
5149 if (vk != VKPARAM)
5150 {
5151 return (message ("%q|@%d|%q#%s",
5152 ctype_dump (v->utype),
5153 (int) vk,
5154 sdump,
5155 isParam ? cstring_undefined : v->uname));
5156 }
5157 else
5158 {
5159 return (message ("%q|%q#%s",
5160 ctype_dump (v->utype),
5161 sdump,
5162 isParam ? cstring_undefined : v->uname));
5163 }
5164
5165 }
5166 case KDATATYPE:
28bf4b0b 5167 /*
5168 DPRINTF (("Dumping datatype: %s -> %s type: %s [%d]",
5169 uentry_unparse (v),
5170 exkind_unparse (sRef_getExKind (v->sref)),
5171 ctype_unparse (v->utype), (int) v->utype));
5172 */
5173
e5081f8c 5174 return (message ("%q@%c@%s@%d@%d@%d@%d@%q#%s",
616915dd 5175 ctype_dump (v->utype),
e5081f8c 5176 qual_abstractCode (v->info->datatype->abs),
616915dd 5177 ynm_unparseCode (v->info->datatype->mut),
5178 (int) sRef_getDefState (v->sref),
5179 (int) sRef_getNullState (v->sref),
5180 (int) sRef_getAliasKind (v->sref),
5181 (int) sRef_getExKind (v->sref),
5182 ctype_dump (v->info->datatype->type),
5183 v->uname));
5184 case KFCN:
5185 {
28bf4b0b 5186 cstring sdump, gdump, adump, xdump;
616915dd 5187 alkind alk = sRef_getAliasKind (v->sref);
5188 exkind exk = sRef_getExKind (v->sref);
5189
5190 if (sRef_getDefState (v->sref) == SS_DEFINED
5191 && !nstate_isKnown (sRef_getNullState (v->sref))
5192 && !exitkind_isKnown (v->info->fcn->exitCode)
5193 && v->info->fcn->specialCode == SPC_NONE
28bf4b0b 5194 && qual_isUnknown (v->info->fcn->nullPred))
616915dd 5195 {
5196 sdump = cstring_makeLiteral ("$");
5197 }
5198 else
5199 {
28bf4b0b 5200 sdump = message ("@%d@%d@%d@%d@%x",
616915dd 5201 (int) sRef_getDefState (v->sref),
5202 (int) sRef_getNullState (v->sref),
5203 (int) v->info->fcn->exitCode,
5204 (int) v->info->fcn->specialCode,
28bf4b0b 5205 qual_dump (v->info->fcn->nullPred));
616915dd 5206 }
5207
5208 if (!uentry_hasGlobs(v) && !uentry_hasMods (v))
5209 {
5210 gdump = cstring_makeLiteral ("$");
5211 }
5212 else if (uentry_hasGlobs (v) && globSet_isEmpty (uentry_getGlobs (v))
5213 && uentry_hasMods (v) && sRefSet_isEmpty (uentry_getMods (v)))
5214 {
5215 gdump = cstring_makeLiteral ("^");
5216 }
5217 else
5218 {
5219 gdump = message ("@%s@%q@%s@%q",
5220 bool_dump (uentry_hasGlobs (v)),
5221 globSet_dump (uentry_getGlobs (v)),
5222 bool_dump (uentry_hasMods (v)),
5223 sRefSet_dump (uentry_getMods (v)));
5224 }
5225
5226 if (alk == AK_UNKNOWN && exk == XO_UNKNOWN)
5227 {
5228 adump = cstring_makeLiteral ("$");
5229 }
5230 else
5231 {
5232 adump = message ("@%d@%d", (int) alk, (int) exk);
5233 }
5234
28bf4b0b 5235 xdump = cstring_undefined;
5236
5237 if (uentry_hasWarning (v))
616915dd 5238 {
28bf4b0b 5239 xdump = message ("%q@W:%q", xdump, warnClause_dump (v->warn));
616915dd 5240 }
28bf4b0b 5241
5242 if (uentry_hasStateClauseList (v))
616915dd 5243 {
28bf4b0b 5244 xdump = message ("%q@S:%q", xdump, stateClauseList_dump (v->info->fcn->specclauses));
616915dd 5245 }
28bf4b0b 5246
5247 return (message ("%q%q%q%q@%q%q#%s",
5248 ctype_dump (v->utype),
5249 sdump,
5250 gdump,
5251 adump,
5252 typeIdSet_dump (uentry_accessType (v)),
5253 xdump,
5254 v->uname));
616915dd 5255 }
5256 case KITER:
5257 return (message ("%q@%q#%s",
5258 ctype_dump (v->utype),
5259 typeIdSet_dump (v->info->iter->access),
5260 v->uname));
5261 case KENDITER:
5262 return (message ("%q@%q#%s",
5263 ctype_dump (v->utype),
5264 typeIdSet_dump (uentry_accessType (v)),
5265 v->uname));
5266 case KENUMCONST:
5267 case KCONST:
5268 {
5269 cstring sdump;
5270
b9904f57 5271 if (multiVal_isUnknown (uentry_getConstantValue (v))
616915dd 5272 && typeIdSet_isEmpty (uentry_accessType (v))
5273 && (sRef_getNullState (v->sref) == NS_UNKNOWN))
5274 {
5275 sdump = cstring_makeLiteral ("$");
5276 }
5277 else
5278 {
5279 sdump = message ("@%q@%q@%d",
b9904f57 5280 multiVal_dump (uentry_getConstantValue (v)),
616915dd 5281 typeIdSet_dump (uentry_accessType (v)),
5282 (int) sRef_getNullState (v->sref));
5283 }
5284
5285 return (message ("%q%q#%s",
5286 ctype_dump (v->utype),
5287 sdump,
5288 v->uname));
5289 }
5290 case KSTRUCTTAG:
5291 case KUNIONTAG:
5292 case KENUMTAG:
5293 return (message ("%q@%q#%s",
5294 ctype_dump (v->utype),
5295 ctype_dump (v->info->datatype->type), v->uname));
5296 }
5297
5298 BADEXIT;
5299}
5300
5301/*@only@*/ cstring
5302uentry_unparseAbbrev (uentry v)
5303{
5304 if (!uentry_isVariable (v))
5305 {
5306 llcontbuglit ("uentry_unparseAbbrev: not variable");
5307 return uentry_unparse (v);
5308 }
5309
5310 return (message ("%s %q", ctype_unparseDeep (v->utype), uentry_getName (v)));
5311}
5312
5313/*@only@*/ cstring
5314uentry_unparse (uentry v)
5315{
5316 cstring st;
5317
5318 if (uentry_isUndefined (v)) return (cstring_makeLiteral ("<undefined>"));
5319 if (uentry_isElipsisMarker (v)) return (cstring_makeLiteral ("..."));
5320
5321 st = uentry_getName (v);
5322
5323 if (cstring_isDefined (st))
5324 {
5325 return (ctype_unparseDeclaration (v->utype, st));
5326 }
5327 else
5328 {
5329 cstring_free (st);
5330 return (cstring_copy (ctype_unparse (v->utype)));
5331 }
5332}
5333
5334/*@only@*/ cstring
5335uentry_unparseFull (uentry v)
5336{
5337 if (uentry_isUndefined (v))
5338 {
5339 return (cstring_makeLiteral ("<undefined>"));
5340 }
616915dd 5341 else
5342 {
28bf4b0b 5343 cstring res;
5344
e5081f8c 5345 res = message ("[%p] %s %s: %s [spec: %q; decl: %q; def: %q]",
5346 v, ekind_unparse (v->ukind), v->uname,
28bf4b0b 5347 ctype_unparse (v->utype),
5348 fileloc_unparse (uentry_whereSpecified (v)),
5349 fileloc_unparse (uentry_whereDeclared (v)),
5350 fileloc_unparse (uentry_whereDefined (v)));
5351
5352 DPRINTF (("uentry: %s", res));
5353
5354 if (uentry_isDatatype (v))
5355 {
5356 res = message ("%q / type: %s mut: %s abs: %s state: %q",
5357 res,
5358 ctype_unparse
5359 (ctype_isDefined (v->info->datatype->type)
5360 ? v->info->datatype->type : ctype_unknown),
5361 ynm_unparse (v->info->datatype->mut),
e5081f8c 5362 qual_unparse (v->info->datatype->abs),
28bf4b0b 5363 sRef_unparseState (v->sref));
5364 }
5365 else if (uentry_isFunction (v))
5366 {
5367 res = message ("%q / sref: %q / mods: %q / "
ba45e1e4 5368 "globs: %q / clauses: %q / pre: %q / post: %q",
28bf4b0b 5369 res,
5370 sRef_unparseFull (v->sref),
5371 sRefSet_unparse (v->info->fcn->mods),
5372 globSet_unparse (v->info->fcn->globs),
ba45e1e4 5373 stateClauseList_unparse (v->info->fcn->specclauses),
5374 functionConstraint_unparse (v->info->fcn->preconditions),
5375 functionConstraint_unparse (v->info->fcn->postconditions));
28bf4b0b 5376 }
5377 else if (uentry_isIter (v))
5378 {
5379 res = message ("%q / sref: %q",
5380 res,
5381 sRef_unparseFull (v->sref));
5382 }
5383 else if (uentry_isVariable (v))
5384 {
5385 res = message ("%q / sref: %q / kind <%d> isout <%d> null <%d> used <%d>",
5386 res,
5387 sRef_unparseFull (v->sref),
5388 (int) v->info->var->kind,
5389 (int) v->info->var->defstate,
5390 (int) v->info->var->nullstate,
5391 (int) v->used);
5392 DPRINTF (("sref: [%p]", v->sref));
5393 DPRINTF (("sref: %s", sRef_unparseDebug (v->sref)));
5394 /* DPRINTF (("sref: %s", sRef_unparseDeep (v->sref))); */
5395 }
b9904f57 5396 else if (uentry_isConstant (v))
5397 {
02b84d4b 5398 res = message ("%q = %q / %q",
5399 res, multiVal_unparse (uentry_getConstantValue (v)),
5400 sRef_unparseFull (v->sref));
b9904f57 5401 }
28bf4b0b 5402 else
5403 {
5404 res = message ("%q :: %q", res, uentry_unparse (v));
5405 }
5406
5407 return res;
616915dd 5408 }
5409}
5410
5411bool uentry_hasAccessType (uentry e)
5412{
5413 if (uentry_isValid (e))
5414 {
5415 switch (e->ukind)
5416 {
5417 case KITER:
5418 return (!typeIdSet_isEmpty (e->info->iter->access));
5419 case KENDITER:
5420 return (!typeIdSet_isEmpty (e->info->enditer->access));
5421 case KFCN:
5422 return (!typeIdSet_isEmpty (e->info->fcn->access));
5423 case KENUMCONST:
5424 case KCONST:
5425 return (!typeIdSet_isEmpty (e->info->uconst->access));
5426 default:
5427 return FALSE;
5428 }
5429 }
5430
5431 return FALSE;
5432}
5433
5434typeIdSet uentry_accessType (uentry e)
5435{
5436 if (uentry_isValid (e))
5437 {
5438 switch (e->ukind)
5439 {
5440 case KITER:
5441 return (e->info->iter->access);
5442 case KENDITER:
5443 return (e->info->enditer->access);
5444 case KFCN:
5445 return (e->info->fcn->access);
5446 case KENUMCONST:
5447 case KCONST:
5448 return (e->info->uconst->access);
5449 default:
5450 break;
5451 }
5452 }
5453
5454 return typeIdSet_undefined;
5455}
5456
5457bool
5458uentry_isVariable (uentry e)
5459{
5460 return (uentry_isVar (e));
5461}
5462
5463bool
5464uentry_isSpecified (uentry e)
5465{
5466 return (uentry_isValid (e) && !fileloc_isUndefined (e->whereSpecified));
5467}
5468
5469static bool
5470uentry_isReallySpecified (uentry e)
5471{
5472 return (uentry_isValid (e)
5473 && fileloc_isRealSpec (e->whereSpecified));
5474}
5475
5476bool
5477uentry_isVar (uentry e)
5478{
5479 return (!uentry_isUndefined (e) && e->ukind == KVAR);
5480}
5481
5482bool
5483uentry_isFakeTag (uentry e)
5484{
5485 return (uentry_isValid (e) && strchr (cstring_toCharsSafe (e->uname), '!') != 0);
5486}
5487
5488bool
5489uentry_isDatatype (uentry e)
5490{
5491 return (!uentry_isUndefined (e) &&
5492 (e->ukind == KDATATYPE || e->ukind == KSTRUCTTAG ||
5493 e->ukind == KUNIONTAG || e->ukind == KENUMTAG));
5494}
5495
5496void
5497uentry_setAbstract (uentry e)
5498{
5499 typeId oldid;
5500
5501 llassert (uentry_isDatatype (e)
e5081f8c 5502 && (qual_isUnknown (e->info->datatype->abs)));
616915dd 5503
5504 oldid = ctype_typeId (e->info->datatype->type);
e5081f8c 5505 e->info->datatype->abs = qual_createAbstract ();
616915dd 5506 e->info->datatype->type = ctype_createAbstract (oldid);
5507}
5508
5509void
5510uentry_setConcrete (uentry e)
5511{
5512 llassert (uentry_isDatatype (e)
e5081f8c 5513 && (qual_isUnknown (e->info->datatype->abs)
5514 || qual_isConcrete (e->info->datatype->abs)));
616915dd 5515
e5081f8c 5516 e->info->datatype->abs = qual_createConcrete ();
616915dd 5517}
5518
5519bool
5520uentry_isAbstractDatatype (uentry e)
5521{
5522 return (uentry_isDatatype (e)
e5081f8c 5523 && (qual_isEitherAbstract (e->info->datatype->abs)));
616915dd 5524}
5525
5526bool
5527uentry_isMaybeAbstract (uentry e)
5528{
5529 return (uentry_isDatatype (e)
e5081f8c 5530 && (!qual_isConcrete (e->info->datatype->abs)));
616915dd 5531}
5532
5533bool
5534uentry_isMutableDatatype (uentry e)
5535{
b73d1009 5536 if (uentry_isDatatype (e))
5537 {
5538 if (ctype_isNumAbstract (e->info->datatype->type))
5539 {
5540 return FALSE;
5541 }
5542 else
5543 {
5544 return ynm_toBoolRelaxed (e->info->datatype->mut);
5545 }
5546 }
5547
5548 return FALSE;
616915dd 5549}
5550
5551bool
5552uentry_isRefCountedDatatype (uentry e)
5553{
5554 return (uentry_isDatatype (e) && (sRef_isRefCounted (uentry_getSref (e))));
5555}
5556
5557bool
5558uentry_isParam (uentry u)
5559{
5560 return (uentry_isVariable (u) && (u->info->var->kind == VKPARAM
5561 || u->info->var->kind == VKYIELDPARAM));
5562}
5563
5564bool
5565uentry_isExpandedMacro (uentry u)
5566{
5567 return (uentry_isVariable (u) && (u->info->var->kind == VKEXPMACRO));
5568}
5569
5570bool
5571uentry_isSefParam (uentry u)
5572{
5573 return (uentry_isVariable (u)
5574 && (u->info->var->kind == VKSEFPARAM
5575 || u->info->var->kind == VKREFSEFPARAM
5576 || u->info->var->kind == VKSEFRETPARAM
5577 || u->info->var->kind == VKREFSEFRETPARAM));
5578}
5579
5580bool
5581uentry_isRefParam (uentry u)
5582{
5583 return (uentry_isVariable (u)
5584 && (u->info->var->kind == VKREFPARAM
5585 || u->info->var->kind == VKREFYIELDPARAM
5586 || u->info->var->kind == VKREFSEFPARAM
5587 || u->info->var->kind == VKREFSEFRETPARAM));
5588}
5589
5590bool
5591uentry_isAnyParam (uentry u)
5592{
5593 return (uentry_isVariable (u)
5594 && ((u->info->var->kind == VKPARAM)
5595 || (u->info->var->kind == VKSEFPARAM)
5596 || (u->info->var->kind == VKYIELDPARAM)
5597 || (u->info->var->kind == VKRETPARAM)
5598 || (u->info->var->kind == VKSEFRETPARAM)));
5599}
5600
5601sstate
5602uentry_getDefState (uentry u)
5603{
5604 if (uentry_isValid (u))
5605 {
5606 return (sRef_getDefState (u->sref));
5607 }
5608 else
5609 {
5610 return (SS_UNKNOWN);
5611 }
5612}
5613
5614bool
5615uentry_isOut (uentry u)
5616{
5617 return ((uentry_isVariable (u) && (u->info->var->defstate == SS_ALLOCATED))
5618 || (uentry_isDatatype (u) && (sRef_isAllocated (u->sref))));
5619}
5620
5621bool
5622uentry_isPartial (uentry u)
5623{
5624 return ((uentry_isVariable (u) && (u->info->var->defstate == SS_PARTIAL))
5625 || (uentry_isDatatype (u) && (sRef_isAllocated (u->sref))));
5626}
5627
5628bool
5629uentry_isStateSpecial (uentry u)
5630{
5631 return ((uentry_isVariable (u)
5632 && (u->info->var->defstate == SS_SPECIAL))
5633 || (uentry_isValid (u) && sRef_isStateSpecial (u->sref)));
5634}
5635
5636exitkind uentry_getExitCode (uentry ue)
5637{
5638 if (uentry_isFunction (ue))
5639 {
5640 return ue->info->fcn->exitCode;
5641 }
5642 else
5643 {
5644 return XK_UNKNOWN;
5645 }
5646}
5647
28bf4b0b 5648qual uentry_nullPred (uentry u)
616915dd 5649{
5650 llassert (uentry_isRealFunction (u));
5651
5652 if (uentry_isFunction (u))
5653 {
5654 return (u->info->fcn->nullPred);
5655 }
5656 else
5657 {
28bf4b0b 5658 return qual_createUnknown ();
616915dd 5659 }
5660}
5661
28bf4b0b 5662/*
5663** Note for variables, this is checking the declared state, not the current state.
5664*/
5665
616915dd 5666bool
5667uentry_possiblyNull (uentry u)
5668{
5669 return ((uentry_isVariable (u) && (nstate_possiblyNull (u->info->var->nullstate)))
5670 || (uentry_isDatatype (u) && (sRef_possiblyNull (u->sref))));
5671}
5672
5673alkind
5674uentry_getAliasKind (uentry u)
5675{
5676 if (uentry_isValid (u))
5677 {
5678 return (sRef_getAliasKind (uentry_getSref (u)));
5679 }
5680 else
5681 {
5682 return AK_UNKNOWN;
5683 }
5684}
5685
5686exkind
5687uentry_getExpKind (uentry u)
5688{
5689 if (uentry_isValid (u))
5690 {
5691 return (sRef_getExKind (uentry_getSref (u)));
5692 }
5693 else
5694 {
5695 return XO_UNKNOWN;
5696 }
5697}
5698
5699bool
5700uentry_isIter (uentry e)
5701{
5702 return (!uentry_isUndefined (e) && e->ukind == KITER);
5703}
5704
5705bool
5706uentry_isEndIter (uentry e)
5707{
5708 return (!uentry_isUndefined (e) && e->ukind == KENDITER);
5709}
5710
5711bool
5712uentry_isRealFunction (uentry e)
5713{
5714 return (uentry_isFunction (e) ||
5715 (uentry_isVariable (e) && ctype_isFunction (uentry_getType (e))));
5716}
5717
5718bool
5719uentry_hasName (uentry e)
5720{
5721 if (uentry_isValid (e))
5722 {
5723 cstring s = e->uname;
5724
28bf4b0b 5725 return (!(cstring_isEmpty (s) || cstring_equalLit (s, "...")
5726 || uentry_isFakeTag (e)));
616915dd 5727 }
5728 else
5729 {
5730 return FALSE;
5731 }
5732}
5733
28bf4b0b 5734/*
5735** Returns true for fake tags.
5736** This is used for dumping the library
5737*/
5738
616915dd 5739bool uentry_hasRealName (uentry e)
5740{
28bf4b0b 5741 return (uentry_isValid (e)
5742 && cstring_isNonEmpty (e->uname)
5743 && !uentry_isGlobalMarker (e));
616915dd 5744}
5745
5746
5747/*@observer@*/ globSet
5748uentry_getGlobs (uentry l)
5749{
5750 if (uentry_isInvalid (l))
5751 {
5752 return globSet_undefined;
5753 }
5754
6fcd0b1e 5755 if (uentry_isFunction (l))
5756 {
5757 return l->info->fcn->globs;
5758 }
5759 else if (uentry_isIter (l))
616915dd 5760 {
6fcd0b1e 5761 return l->info->iter->globs;
5762 }
5763 else if (uentry_isEndIter (l))
5764 {
5765 return globSet_undefined;
5766 }
5767 else
5768 {
5769 if (l->ukind == KVAR)
616915dd 5770 {
6fcd0b1e 5771 llcontbug (message ("Bad call to uentry_getGlobs (var): %q (%s)",
616915dd 5772 uentry_unparse (l),
5773 ekind_unparse (l->ukind)));
6fcd0b1e 5774 }
5775 else
5776 {
5777 llcontbug (message ("Bad call to uentry_getGlobs: %q (%s)",
616915dd 5778 uentry_unparse (l),
5779 ekind_unparse (l->ukind)));
616915dd 5780 }
6fcd0b1e 5781
616915dd 5782 return globSet_undefined;
5783 }
616915dd 5784}
5785
51bc6ecc 5786# ifdef WIN32
5787/* Make Microsoft VC++ happy */
5788# pragma warning (disable : 4715)
5789# endif
5790
616915dd 5791/*@observer@*/ sRefSet
5792uentry_getMods (uentry l)
5793{
5794 llassert (uentry_isValid (l));
5795
5796 if (l->ukind != KFCN && l->ukind != KITER && l->ukind != KENDITER)
5797 {
5798 llcontbug (message ("Bad call to uentry_getMods: %q", uentry_unparse (l)));
5799 return sRefSet_undefined;
5800 }
5801
6fcd0b1e 5802 if (uentry_isFunction (l))
5803 {
5804 return l->info->fcn->mods;
5805 }
5806 else if (uentry_isIter (l))
5807 {
5808 return l->info->iter->mods;
5809 }
5810 else if (uentry_isEndIter (l))
5811 {
5812 return sRefSet_undefined;
5813 }
5814 else
5815 {
5816 BADBRANCH;
5817 }
616915dd 5818}
5819
5820ekind
5821uentry_getKind (uentry e)
5822{
5823 llassert (uentry_isValid (e));
616915dd 5824 return (e->ukind);
5825}
5826
5827/*@observer@*/ multiVal uentry_getConstantValue (uentry e)
5828{
b9904f57 5829 llassert (uentry_isEitherConstant (e));
5830 return (sRef_getValue (e->sref));
616915dd 5831}
5832
5833/*@observer@*/ uentryList
5834uentry_getParams (uentry l)
5835{
5836 if (uentry_isInvalid (l)) return uentryList_undefined;
5837
5838 switch (l->ukind)
5839 {
5840 case KFCN:
5841 case KITER:
5842 {
5843 ctype ct = l->utype;
5844
5845 if (ctype_isFunction (ct))
5846 {
5847 return (ctype_argsFunction (ct));
5848 }
5849 else
5850 {
5851 return uentryList_undefined;
5852 }
5853 }
5854 case KVAR:
5855 {
5856 ctype ct = l->utype;
5857
39888ce3 5858 /*drl 12/10/2002 changed to fix bug involving multiple redefines of library functions in macros. Bug was reported by Malcolm Parsons
5859
5860 Old code was simplly llassert (ctype_isFunction (ct) );
5861 */
5862
5863 llassert (ctype_isFunction (ct) || context_inMacro() );
5864
616915dd 5865 return (ctype_argsFunction (ct));
5866 }
5867 BADDEFAULT;
5868 }
5869 BADEXIT;
5870}
5871
5872/*@observer@*/ cstring
5873uentry_rawName (uentry e)
5874{
5875 if (uentry_isValid (e))
5876 {
5877 return (e->uname);
5878 }
5879 else
5880 {
5881 return cstring_undefined;
5882 }
5883}
5884
5885static cstring
5886uentry_getOptName (uentry e)
5887{
5888 cstring s = uentry_getName (e);
5889
5890 if (cstring_isDefined (s))
5891 {
5892 s = cstring_appendChar (s, ' ');
5893 }
5894
5895 return s;
5896}
5897
5898/*@only@*/ cstring
5899uentry_getName (uentry e)
5900{
5901 cstring ret = cstring_undefined;
5902
5903 if (uentry_isValid (e))
5904 {
616915dd 5905 if (uentry_isAnyTag (e))
5906 {
28bf4b0b 5907 ret = fixTagName (e->uname);
616915dd 5908 }
5909 else if (uentry_isAnyParam (e))
5910 {
5911 ret = cstring_copy (fixParamName (e->uname));
5912 }
5913 else
5914 {
5915 ret = cstring_copy (e->uname);
5916 }
5917 }
5918
5919 return ret;
5920}
5921
28bf4b0b 5922cstring uentry_observeRealName (uentry e)
5923{
5924 cstring ret = cstring_undefined;
5925
5926 if (uentry_isValid (e))
5927 {
5928 if (uentry_isAnyTag (e))
5929 {
5930 if (isFakeTag (e->uname))
5931 {
5932 ret = cstring_undefined;
5933 }
5934 else
5935 {
5936 ret = plainTagName (e->uname);
5937 }
5938 }
5939 else if (uentry_isAnyParam (e))
5940 {
5941 ret = fixParamName (e->uname);
5942 }
5943 else
5944 {
5945 ret = e->uname;
5946 }
5947 }
5948
5949 return ret;
5950}
5951
616915dd 5952cstring uentry_getRealName (uentry e)
5953{
5954 if (uentry_isValid (e))
5955 {
5956 if (uentry_isAnyTag (e))
5957 {
5958 return (cstring_undefined);
5959 }
5960 else
5961 {
5962 return (e->uname);
5963 }
5964 }
5965 return cstring_undefined;
5966}
5967
5968ctype uentry_getType (uentry e)
5969{
5970 if (uentry_isValid (e))
5971 {
5972 return e->utype;
5973 }
5974 else
5975 {
5976 return ctype_unknown;
5977 }
5978}
5979
5980fileloc uentry_whereLast (uentry e)
5981{
5982 fileloc loc;
5983
5984 if (uentry_isInvalid (e))
5985 {
5986 return fileloc_undefined;
5987 }
5988
5989 loc = e->whereDefined;
5990
5991 if (fileloc_isValid (loc) && !fileloc_isExternal (loc))
5992 {
5993 return loc;
5994 }
5995
5996 loc = uentry_whereDeclared (e);
5997
5998 if (fileloc_isValid (loc) && !fileloc_isExternal (loc))
5999 {
6000 return loc;
6001 }
6002
6003 loc = uentry_whereSpecified (e);
6004 return loc;
6005}
6006
6007fileloc uentry_whereEither (uentry e)
6008{
6009 if (uentry_isInvalid (e)) return fileloc_undefined;
6010
6011 if (fileloc_isDefined (e->whereDefined)
6012 && !fileloc_isExternal (e->whereDefined))
6013 {
6014 return e->whereDefined;
6015 }
6016 else if (fileloc_isDefined (e->whereDeclared))
6017 {
6018 return e->whereDeclared;
6019 }
6020 else
6021 {
6022 return e->whereSpecified;
6023 }
6024}
6025
6026fileloc uentry_whereSpecified (uentry e)
6027{
6028 if (uentry_isInvalid (e)) return fileloc_undefined;
6029
6030 return (e->whereSpecified);
6031}
6032
6033fileloc uentry_whereDefined (uentry e)
6034{
6035 if (uentry_isInvalid (e)) return fileloc_undefined;
6036
6037 return (e->whereDefined);
6038}
6039
6040fileloc uentry_whereDeclared (uentry e)
6041{
6042 if (uentry_isInvalid (e)) return fileloc_undefined;
6043
6044 return (e->whereDeclared);
6045}
6046
6047/*@observer@*/ fileloc
6048uentry_whereEarliest (uentry e)
6049{
6050 if (uentry_isInvalid (e)) return fileloc_undefined;
6051
6052 if (fileloc_isDefined (e->whereSpecified))
6053 {
6054 return (e->whereSpecified);
6055 }
6056 else if (fileloc_isDefined (e->whereDeclared))
6057 {
6058 return (e->whereDeclared);
6059 }
6060 else
6061 {
6062 return e->whereDefined;
6063 }
6064}
6065
6066void
6067uentry_setFunctionDefined (uentry e, fileloc loc)
6068{
6069 if (uentry_isValid (e))
6070 {
6071 llassert (uentry_isFunction (e));
6072
6073 if (fileloc_isUndefined (e->whereDeclared))
6074 {
6075 e->whereDeclared = fileloc_update (e->whereDeclared, loc);
6076 }
6077
6078 if (!fileloc_isDefined (e->whereDefined))
6079 {
6080 e->whereDefined = fileloc_update (e->whereDefined, loc);
6081 }
6082 }
6083}
6084
6085void
6086uentry_setDeclDef (uentry e, fileloc f)
6087{
6088 uentry_setDeclared (e, f);
6089
6090 if (!uentry_isFunction (e)
6091 && !(uentry_isVariable (e) && uentry_isExtern (e)))
6092 {
6093 uentry_setDefined (e, f);
6094 }
6095}
6096
6097void
6098uentry_setDeclaredForce (uentry e, fileloc f)
6099{
6100 llassert (uentry_isValid (e));
6101 e->whereDeclared = fileloc_update (e->whereDeclared, f);
6102}
6103
6104void
6105uentry_setDeclaredForceOnly (uentry e, fileloc f)
6106{
6107 llassert (uentry_isValid (e));
6108 fileloc_free (e->whereDeclared);
6109 e->whereDeclared = f;
6110}
6111
6112void
6113uentry_setDeclaredOnly (uentry e, /*@only@*/ fileloc f)
6114{
6115 fileloc oldloc;
6116
6117 llassert (uentry_isValid (e));
6118 oldloc = e->whereDeclared;
6119
6120 if (fileloc_isDefined (oldloc))
6121 {
6122 if (fileloc_isLib (oldloc) || fileloc_isImport (oldloc))
6123 {
6124 e->whereDeclared = f;
6125 fileloc_free (oldloc);
6126 }
6127 else
6128 {
6129 fileloc_free (f);
6130 }
6131 }
6132 else
6133 {
6134 e->whereDeclared = f;
6135 fileloc_free (oldloc);
6136 }
6137}
6138
6139void
6140uentry_setDeclared (uentry e, fileloc f)
6141{
6142 fileloc oldloc;
6143
6144 llassert (uentry_isValid (e));
6145 oldloc = e->whereDeclared;
6146
6147 if (fileloc_isDefined (oldloc))
6148 {
6149 if (fileloc_isLib (oldloc) || fileloc_isImport (oldloc))
6150 {
6151 e->whereDeclared = fileloc_update (e->whereDeclared, f);
6152 }
6153 else
6154 {
6155 ;
6156 }
6157 }
6158 else
6159 {
6160 e->whereDeclared = fileloc_update (e->whereDeclared, f);
6161 }
6162}
6163
6164void
6165uentry_clearDefined (uentry e)
6166{
6167 if (uentry_isValid (e))
6168 {
6169 e->whereDefined = fileloc_update (e->whereDefined, fileloc_undefined);
6170 }
6171}
6172
6173void
6174uentry_setDefined (uentry e, fileloc f)
6175{
6176 fileloc oldloc;
6177
6178 llassert (uentry_isValid (e));
6179 oldloc = e->whereDefined;
6180
6181 if (fileloc_isDefined (oldloc))
6182 {
6183 if (fileloc_isLib (oldloc)
6184 || fileloc_isImport (oldloc)
6185 || fileloc_isBuiltin (oldloc)
6186 || fileloc_isPreproc (oldloc))
6187 {
6188 e->whereDefined = fileloc_update (e->whereDefined, f);
6189 }
6190 else
6191 {
6192 if (fileloc_equal (oldloc, f) || context_processingMacros ())
6193 {
6194 ; /* okay */
6195 }
6196 else
6197 {
6198 if (optgenerror (FLG_REDEF,
6199 message ("%s %q redefined",
6200 ekind_capName (e->ukind),
6201 uentry_getName (e)),
6202 f))
6203 {
6204 llgenindentmsg (message ("Previous definition of %q",
6205 uentry_getName (e)),
6206 e->whereDefined);
6207 }
6208 }
6209 }
6210 }
6211 else
6212 {
6213 e->whereDefined = fileloc_update (e->whereDefined, f);
6214 }
6215}
6216
6217bool
6218uentry_isCodeDefined (uentry e)
6219{
efd360a3 6220 llassert (uentry_isValid (e));
6221
6222 return (fileloc_isDefined (e->whereDefined));
616915dd 6223}
6224
6225bool
6226uentry_isDeclared (uentry e)
6227{
6228 if (uentry_isValid (e))
6229 {
6230 return (fileloc_isDefined (e->whereDeclared));
6231 }
6232
6233 return FALSE;
6234}
6235
6236sRef uentry_getSref (uentry e)
6237{
6238 /* not true, used for functions too (but shouldn't be? */
6239 /* llassertprint (e->ukind == KVAR, ("uentry_getSref: not variable!")); */
6240
6241 if (uentry_isInvalid (e)) return sRef_undefined;
6242
6243 return (e->sref);
6244}
6245
6246sRef uentry_getOrigSref (uentry e)
6247{
b73d1009 6248 /* evans 2003-04-12 - removed for now */
6249 /* evans 2001-09-09 - need to fix this
b7e84605 6250 if (uentry_isValid (e))
6251 {
6252 if (uentry_isVariable (e))
6253 {
6254 return e->info->var->origsref;
6255 }
6256 else
6257 {
6258 sRef sr = sRef_copy (uentry_getSref (e));
6259
6260 sRef_resetState (sr);
6261 sRef_clearDerived (sr);
6262 return (sr);
6263 }
6264 }
6265 else
6266 {
6267 return sRef_undefined;
6268 }
6269 */
6270
616915dd 6271 if (uentry_isValid (e))
6272 {
6273 sRef sr = sRef_copy (uentry_getSref (e));
6274
6275 sRef_resetState (sr);
6276 sRef_clearDerived (sr);
6277
6278 if (uentry_isVariable (e))
6279 {
6280 sRef_setDefState (sr, e->info->var->defstate, fileloc_undefined);
6281 sRef_setNullState (sr, e->info->var->nullstate, fileloc_undefined);
6282 }
6283
6284 return (sr);
6285 }
6286 else
6287 {
6288 return sRef_undefined;
6289 }
6290}
6291
6292/*
6293** requires: uentry e is not in a hashed symbol table
6294*/
6295
6296void
6297uentry_setName (uentry e, /*@only@*/ cstring n)
6298{
6299 llassert (uentry_isValid (e));
6300
6301 cstring_free (e->uname);
6302 e->uname = n;
6303}
6304
6305void
6306uentry_setType (uentry e, ctype t)
6307{
6308 if (uentry_isValid (e))
6309 {
6310 e->utype = t;
6311 sRef_setType (e->sref, t);
6312 }
6313}
6314
6315void
6316uentry_resetParams (uentry ue, /*@only@*/ uentryList pn)
6317{
6318 ctype rct;
6319 ctype rettype = ctype_unknown;
6320
6321 llassert (uentry_isValid (ue));
6322
efd360a3 6323 uentry_convertVarFunction (ue);
616915dd 6324 llassert (uentry_isFunction (ue));
6325
efd360a3 6326 rct = ctype_realType (ue->utype);
6327
616915dd 6328 if (ctype_isFunction (rct))
6329 {
28bf4b0b 6330 rettype = ctype_getReturnType (rct);
616915dd 6331 }
6332
6333 ue->utype = ctype_makeNFParamsFunction (rettype, pn);
6334}
6335
6336void
6337uentry_setRefParam (uentry e)
6338{
616915dd 6339 if (!uentry_isVar (e))
6340 {
6341 llbug (message ("uentry_setParam: not variable: %q", uentry_unparse (e)));
6342 }
6343 else
6344 {
6345 if (e->info->var->kind == VKSEFPARAM)
6346 {
6347 e->info->var->kind = VKREFSEFPARAM;
6348 }
6349 else if (e->info->var->kind == VKSEFRETPARAM)
6350 {
6351 e->info->var->kind = VKREFSEFRETPARAM;
6352 }
6353 else if (e->info->var->kind == VKYIELDPARAM)
6354 {
6355 e->info->var->kind = VKREFYIELDPARAM;
6356 }
6357 else
6358 {
6359 e->info->var->kind = VKREFPARAM;
6360 }
6361 }
6362}
6363
6364void
6365uentry_setParam (uentry e)
6366{
6367 if (!uentry_isVar (e))
6368 {
6369 if (uentry_isElipsisMarker (e))
6370 {
6371
6372 }
6373 else
6374 {
6375 llbug (message ("uentry_setParam: not variable: %q", uentry_unparse (e)));
6376 }
6377 }
6378 else
6379 {
6380 cstring oldname;
6381
6382 if (e->info->var->kind == VKYIELDPARAM
6383 || e->info->var->kind == VKSEFPARAM
6384 || e->info->var->kind == VKSEFRETPARAM)
6385 {
6386 ;
6387 }
6388 else
6389 {
6390 e->info->var->kind = VKPARAM;
6391 }
6392
6393 oldname = e->uname;
6394 e->uname = makeParam (e->uname);
6395 cstring_free (oldname);
6396 }
6397}
6398
6399void
6400uentry_setSref (uentry e, sRef s)
6401{
6402 if (uentry_isValid (e))
6403 {
6404 if (sRef_isValid (e->sref))
6405 {
6406 sRef_mergeStateQuietReverse (e->sref, s);
6407 }
6408 else
6409 {
6410 e->sref = sRef_saveCopy (s);
6411 }
6412 }
6413}
6414
6415ctype
6416uentry_getAbstractType (uentry e)
6417{
6418 llassert (uentry_isDatatype (e));
6419
6420 /*
6421 ** This assertion removed.
6422 ** Okay to have undefined type, for system types
6423
6424 llassertprintret (!ctype_isUndefined (e->info->datatype->type),
6425 ("uentry_getAbstractType %q: undefined", uentry_unparseFull (e)),
6426 e->utype);
6427
6428 */
6429
6430 if (ctype_isUndefined (e->info->datatype->type))
6431 {
6432 return ctype_unknown;
6433 }
6434
6435 /*
6436 ** Sadly, a kludge...
6437 */
6438
6439 if (ctype_isUserBool (e->info->datatype->type)) {
6440 return ctype_bool;
6441 }
6442
6443 return e->info->datatype->type;
6444}
6445
6446ctype uentry_getRealType (uentry e)
6447{
6448 ctype ct;
b73d1009 6449 typeId uid = typeId_invalid;
616915dd 6450
6451 if (uentry_isInvalid (e))
6452 {
6453 return ctype_unknown;
6454 }
aec3dcdb 6455
6456 if (!uentry_isDatatype (e))
6457 {
6458 /* This shouldn't happen, except when types are redeclared in strange ways */
6459 return ctype_unknown;
6460 }
616915dd 6461
6462 if (uentry_isAnyTag (e))
6463 {
6464 return (e->utype);
6465 }
6466
6467 if (uentry_isAbstractType (e))
6468 {
6469 ct = uentry_getAbstractType (e);
6470
6471 if (ctype_isManifestBool (ct)) {
6472 return ct;
6473 }
6474
6475 llassert (ctype_isUA (ct));
6476
6477 uid = ctype_typeId (ct);
6478
6479 if (!context_hasAccess (uid))
6480 {
6481 return (ct);
6482 }
6483 }
6484
6485 ct = uentry_getType (e);
6486
6487 /* if (ctype_isUserBool (ct)) return ct; */
6488
6489 if (ctype_isManifestBool (ct)) {
6490 return ctype_bool;
6491 }
6492
6493 if (ctype_isUA (ct))
6494 {
b73d1009 6495 typeId iid = ctype_typeId (ct);
616915dd 6496
b73d1009 6497 if (typeId_equal (iid, uid))
616915dd 6498 {
6499 llcontbug (message ("uentry_getRealType: recursive type! %s",
6500 ctype_unparse (ct)));
6501 return ct;
6502 }
6503 else
6504 {
6505 /* evs 2000-07-25: possible infinite recursion ? */
6506 uentry ue2 = usymtab_getTypeEntry (iid);
28bf4b0b 6507
6508 if (ue2 == e)
6509 {
6510 llcontbug (message ("Bad recursion: %q", uentry_unparseFull (e)));
6511 return ctype_unknown;
6512 }
616915dd 6513
6514 return uentry_getRealType (ue2);
6515 }
6516 }
6517 else
6518 {
6519 return ct;
6520 }
6521}
6522
6523ctype uentry_getForceRealType (uentry e)
6524{
6525 ctype ct;
b73d1009 6526 typeId uid = typeId_invalid;
616915dd 6527
6528 if (uentry_isInvalid (e))
6529 {
6530 return ctype_unknown;
6531 }
6532
6533 llassertprint (uentry_isDatatype (e), ("not datatype: %s", uentry_unparse (e)));
6534
6535 if (uentry_isAnyTag (e))
6536 {
6537 return (e->utype);
6538 }
6539
6540 if (uentry_isAbstractType (e))
6541 {
6542 ct = uentry_getAbstractType (e);
6543 llassert (ctype_isUA (ct));
6544
6545 uid = ctype_typeId (ct);
6546 /* no check for access! */
6547 }
6548
6549 ct = uentry_getType (e);
6550
6551 /* evs 2000-07-25 */
6552 /* if (ctype_isUserBool (ct)) return ct; */
6553
6554 if (ctype_isManifestBool (ct)) {
6555 return ctype_bool;
6556 }
6557
6558 if (ctype_isUA (ct))
6559 {
b73d1009 6560 typeId iid = ctype_typeId (ct);
616915dd 6561
b73d1009 6562 if (typeId_equal (iid, uid))
616915dd 6563 {
6564 llcontbug (message ("uentry_getRealType: recursive type! %s",
6565 ctype_unparse (ct)));
6566 return ct;
6567 }
6568 else
6569 {
6570 return uentry_getForceRealType (usymtab_getTypeEntry (iid));
6571 }
6572 }
6573 else
6574 {
6575 return ct;
6576 }
6577}
6578
6579uentry uentry_nameCopy (cstring name, uentry e)
6580{
6581 uentry enew = uentry_alloc ();
6582
6583 llassert (uentry_isValid (e));
6584
6585 /* enew->shallowCopy = FALSE; */
6586 enew->ukind = e->ukind;
6587 enew->uname = name;
6588 enew->utype = e->utype;
6589 enew->whereSpecified = fileloc_copy (e->whereSpecified);
6590 enew->whereDefined = fileloc_copy (e->whereDefined);
6591 enew->whereDeclared = fileloc_copy (e->whereDeclared);
6592 enew->sref = sRef_copy (e->sref);
6593 enew->used = e->used;
6594 enew->lset = FALSE;
6595 enew->isPrivate = e->isPrivate;
6596 enew->hasNameError = FALSE;
6597
6598 enew->uses = filelocList_new ();
28bf4b0b 6599 enew->warn = warnClause_undefined;
616915dd 6600
6601 enew->storageclass = e->storageclass;
6602 enew->info = uinfo_copy (e->info, e->ukind);
6603
6604 return enew;
6605}
6606
6607void
b73d1009 6608uentry_setDatatype (uentry e, typeId uid)
616915dd 6609{
6610 llassert (uentry_isDatatype (e));
6611
6612 if (uentry_isAbstractType (e))
6613 {
e5081f8c 6614 if (qual_isNumAbstract (e->info->datatype->abs))
6615 {
6616 e->info->datatype->type = ctype_createNumAbstract (uid);
6617 }
6618 else
6619 {
6620 llassert (qual_isAbstract (e->info->datatype->abs));
6621 e->info->datatype->type = ctype_createAbstract (uid);
6622 }
616915dd 6623 }
6624 else
6625 {
6626 e->info->datatype->type = ctype_createUser (uid);
6627 }
6628}
6629
6630static void
6631uentry_setSpecDef (/*@special@*/ uentry e, /*@keep@*/ fileloc f)
6632 /*@defines e->whereSpecified, e->whereDeclared, e->whereDefined@*/
6633 /*@modifies e@*/
6634{
6635 llassert (uentry_isValid (e));
6636
6637 if (fileloc_isSpec (f) || fileloc_isImport (f))
6638 {
6639 e->whereSpecified = f;
6640 e->whereDeclared = fileloc_undefined;
6641 e->whereDefined = fileloc_undefined;
6642 }
6643 else
6644 {
6645 e->whereSpecified = fileloc_undefined;
6646 e->whereDeclared = f;
6647 e->whereDefined = fileloc_undefined;
6648 }
7ebcc5bb 6649
6650 llassert (fileloc_storable (f));
616915dd 6651}
6652
6653static void
6654ucinfo_free (/*@only@*/ ucinfo u)
6655{
616915dd 6656 sfree (u);
6657}
6658
6659static void
6660uvinfo_free (/*@only@*/ uvinfo u)
6661{
28bf4b0b 6662 /*drl7x added 6/29/01 */
b072092f 6663 free (u->bufinfo); /* evans - 2001-07-19 fixed this bug */
616915dd 6664 sfree (u);
6665}
6666
6667static void
6668udinfo_free (/*@only@*/ udinfo u)
6669{
6670 sfree (u);
6671}
6672
6673static void
6674ufinfo_free (/*@only@*/ ufinfo u)
6675{
6676 globSet_free (u->globs);
6677 sRefSet_free (u->mods);
28bf4b0b 6678 stateClauseList_free (u->specclauses);
616915dd 6679 sfree (u);
6680}
6681
6682static void
6683uiinfo_free (/*@only@*/ uiinfo u)
6684{
6685 sfree (u);
6686}
6687
6688static void
6689ueinfo_free (/*@only@*/ ueinfo u)
6690{
6691 sfree (u);
6692}
6693
6694static /*@only@*/ ucinfo
6695ucinfo_copy (ucinfo u)
6696{
6697 ucinfo ret = (ucinfo) dmalloc (sizeof (*ret));
616915dd 6698 ret->access = u->access;
3e3ec469 6699 ret->macro = u->macro;
616915dd 6700 return ret;
6701}
6702
6703static /*@only@*/ uvinfo
6704uvinfo_copy (uvinfo u)
6705{
6706 uvinfo ret = (uvinfo) dmalloc (sizeof (*ret));
6707
6708 ret->kind = u->kind;
6709 ret->nullstate = u->nullstate;
6710 ret->defstate = u->defstate;
6711 ret->checked = u->checked;
28bf4b0b 6712
b7e84605 6713
28bf4b0b 6714 /* drl added 07-02-001 */
6715 /* copy null terminated information */
6716
6717 if (u->bufinfo != NULL)
6718 {
6719 ret->bufinfo = (bbufinfo) dmalloc (sizeof( * u->bufinfo ) );
6720 ret->bufinfo->bufstate = u->bufinfo->bufstate;
6721 ret->bufinfo->size = u->bufinfo->size;
6722 ret->bufinfo->len = u->bufinfo->len;
6723 return ret;
6724 }
6725 else
6726 {
6727 ret->bufinfo = NULL;
6728 return ret;
6729 }
6730
616915dd 6731}
6732
6733static /*@only@*/ udinfo
6734udinfo_copy (udinfo u)
6735{
6736 udinfo ret = (udinfo) dmalloc (sizeof (*ret));
6737
6738 ret->abs = u->abs;
6739 ret->mut = u->mut;
6740 ret->type = u->type;
6741
6742 return ret;
6743}
6744
6745static /*@only@*/ ufinfo
6746ufinfo_copy (ufinfo u)
6747{
6748 ufinfo ret = (ufinfo) dmalloc (sizeof (*ret));
6749
6750 ret->hasGlobs = u->hasGlobs;
6751 ret->hasMods = u->hasMods;
6752 ret->exitCode = u->exitCode;
6753 ret->specialCode = u->specialCode;
6754 ret->nullPred = u->nullPred;
6755 ret->access = u->access;
6756 ret->globs = globSet_newCopy (u->globs);
6757 ret->mods = sRefSet_newCopy (u->mods);
6758 ret->defparams = u->defparams;
28bf4b0b 6759 ret->specclauses = stateClauseList_copy (u->specclauses);
616915dd 6760
3814599d 6761 ret->preconditions = functionConstraint_copy (u->preconditions);
6762 ret->postconditions = functionConstraint_copy (u->postconditions);
616915dd 6763
6764 return ret;
6765}
6766
6767static /*@only@*/ uiinfo
6768uiinfo_copy (uiinfo u)
6769{
6770 uiinfo ret = (uiinfo) dmalloc (sizeof (*ret));
6771
6772 ret->access = u->access;
6773 ret->globs = globSet_newCopy (u->globs);
6774 ret->mods = sRefSet_newCopy (u->mods);
6775
6776 return (ret);
6777}
6778
6779static /*@only@*/ ueinfo
6780ueinfo_copy (ueinfo u)
6781{
6782 ueinfo ret = (ueinfo) dmalloc (sizeof (*ret));
6783
6784 ret->access = u->access;
6785 return ret;
6786}
6787
6788static void
6789uinfo_free (uinfo u, ekind kind)
6790{
6791 switch (kind)
6792 {
6793 case KENUMCONST:
6794 case KCONST: ucinfo_free (u->uconst); break;
6795 case KVAR: uvinfo_free (u->var); break;
6796 case KSTRUCTTAG:
6797 case KUNIONTAG:
6798 case KENUMTAG:
6799 case KDATATYPE: udinfo_free (u->datatype); break;
6800 case KFCN: ufinfo_free (u->fcn); break;
6801 case KITER: uiinfo_free (u->iter); break;
6802 case KENDITER: ueinfo_free (u->enditer); break;
6803 case KELIPSMARKER: break;
6804 case KINVALID: break;
6805 }
6806
6807 sfree (u);
6808}
6809
6810static /*@only@*/ /*@null@*/ uinfo
6811uinfo_copy (uinfo u, ekind kind)
6812{
6813 if (kind == KELIPSMARKER || kind == KINVALID)
6814 {
6815 return NULL;
6816 }
6817 else
6818 {
6819 uinfo ret = (uinfo) dmalloc (sizeof (*ret));
6820
6821 switch (kind)
6822 {
6823 case KENUMCONST:
6824 case KCONST: ret->uconst = ucinfo_copy (u->uconst); break;
6825 case KVAR: ret->var = uvinfo_copy (u->var); break;
6826 case KSTRUCTTAG:
6827 case KUNIONTAG:
6828 case KENUMTAG:
6829 case KDATATYPE: ret->datatype = udinfo_copy (u->datatype); break;
6830 case KFCN: ret->fcn = ufinfo_copy (u->fcn); break;
6831 case KITER: ret->iter = uiinfo_copy (u->iter); break;
6832 case KENDITER: ret->enditer = ueinfo_copy (u->enditer); break;
6833 BADDEFAULT;
6834 }
6835 return ret;
6836 }
6837}
6838
6839static void
6840uentry_reallyFree (/*@notnull@*/ /*@only@*/ uentry e)
6841{
6842 filelocList_free (e->uses);
6843 cstring_free (e->uname);
6844
6845 uinfo_free (e->info, e->ukind);
6846
6847 fileloc_free (e->whereSpecified);
6848 fileloc_free (e->whereDefined);
6849 fileloc_free (e->whereDeclared);
6850
28bf4b0b 6851 warnClause_free (e->warn);
6852
616915dd 6853 nuentries--;
6854 sfree (e);
6fcd0b1e 6855}
616915dd 6856
6857extern void uentry_markOwned (/*@owned@*/ uentry u)
6858{
6859 sfreeEventually (u);
6860}
6861
6862void
6863uentry_free (/*@only@*/ uentry e)
6864{
6865 if (uentry_isValid (e) && !uentry_isElipsisMarker (e))
6866 {
6867 uentry_reallyFree (e);
6868 }
6869}
6870
6871/*
6872** For uentry's in the global or file scope
6873*/
6874
6875void
6876uentry_freeComplete (/*@only@*/ uentry e)
6877{
6878 if (uentry_isValid (e) && !uentry_isElipsisMarker (e))
6879 {
28bf4b0b 6880 DPRINTF (("Free complete: %s", sRef_unparseFull (e->sref)));
616915dd 6881 /*@i@*/ sRef_free (e->sref);
6882 e->sref = sRef_undefined;
6883 uentry_reallyFree (e);
6884 }
6885}
6886
6887/*
6888** requires old->kind != new->kind, old->uname = new->uname
6889*/
6890
6891static void
6892KindConformanceError (/*@unique@*/ uentry old, uentry unew, bool mustConform)
6893{
6894 llassert (uentry_isValid (old));
6895 llassert (uentry_isValid (unew));
6896
ce7034f0 6897 if ((uentry_isEitherConstant (unew) || uentry_isDatatype (unew))
616915dd 6898 && (fileloc_isPreproc (uentry_whereDeclared (old))
6899 || ctype_isUnknown (old->utype))
6900 && !uentry_isSpecified (old))
6901 {
6902 ; /* no error */
6903 }
6904 else
6905 {
6906 if (mustConform)
6907 {
6908 if (!uentry_isDeclared (old))
6909 {
6910 if (uentry_isSpecified (old))
6911 {
6912 if (uentry_isSpecified (unew))
6913 {
6914 llbuglit ("Respecification!");
6915 }
6916 else if (uentry_isDeclared (unew))
6917 {
6918 if (optgenerror
6919 (FLG_INCONDEFS,
6920 message ("%s %q inconsistently declared as %s: %t",
6921 ekind_capName (old->ukind),
6922 uentry_getName (unew),
6923 ekind_unparseLong (unew->ukind),
6924 unew->utype),
f2b6724f 6925 uentry_whereLast (unew))) /* evans 2001-12-30: was uentry_whereDeclared */
616915dd 6926 {
f2b6724f 6927 uentry_showWhereLastKind (old);
616915dd 6928 }
6929 }
6930 else
6931 {
6932 BADEXIT;
6933 }
6934 }
6935 else
6936 {
6937 if (optgenerror
6938 (FLG_INCONDEFS,
6939 message ("%s %q inconsistently declared as %s: %t",
6940 ekind_capName (old->ukind),
6941 uentry_getName (unew),
6942 ekind_unparseLong (unew->ukind),
6943 unew->utype),
f2b6724f 6944 uentry_whereLast (unew))) /* evans 2001-12-30: was uentry_whereDeclared */
616915dd 6945 {
f2b6724f 6946 uentry_showWhereLastKind (old);
616915dd 6947 }
6948 }
6949 }
6950 else
6951 {
6952 llassert (uentry_isDeclared (unew));
6953
f2b6724f 6954 DPRINTF (("Old: \n\t%s", uentry_unparseFull (old)));
6955 DPRINTF (("New: \n\t%s", uentry_unparseFull (unew)));
6956
616915dd 6957 if (optgenerror
6958 (FLG_INCONDEFS,
6959 message ("%s %q inconsistently redeclared as %s",
6960 ekind_capName (old->ukind),
6961 uentry_getName (unew),
6962 ekind_unparseLong (unew->ukind)),
f2b6724f 6963 uentry_whereLast (unew))) /* evans 2001-12-30: was uentry_whereDeclared */
616915dd 6964 {
f2b6724f 6965 uentry_showWhereLastKind (old);
616915dd 6966 }
6967 }
6968 }
6969 }
6970
efd360a3 6971 uentry_updateInto (old, unew);
616915dd 6972}
6973
6974/*
6975** def is the definition of spec, modifies spec
6976**
6977** reports any inconsistencies
6978** returns the summary of all available information
6979** if spec and def are inconsistent, def is returned
6980*/
6981
6982void
6983uentry_showWhereLast (uentry spec)
6984{
6985 if (uentry_isValid (spec))
6986 {
6987 if (fileloc_isDefined (spec->whereDefined)
6988 && !fileloc_isLib (spec->whereDefined)
f2b6724f 6989 /*!! && !fileloc_isPreproc (spec->whereDefined) */ )
616915dd 6990 {
6991 llgenindentmsg (message ("Previous definition of %q: %t",
6992 uentry_getName (spec),
6993 uentry_getType (spec)),
6994 uentry_whereDefined (spec));
6995 }
6996 else if (uentry_isDeclared (spec))
6997 {
6998 llgenindentmsg (message ("Previous declaration of %q: %t",
6999 uentry_getName (spec),
7000 uentry_getType (spec)),
7001 uentry_whereDeclared (spec));
7002 }
7003 else if (uentry_isSpecified (spec))
7004 {
7005 if (uentry_hasName (spec))
7006 {
7007 llgenindentmsg (message ("Specification of %q: %t",
7008 uentry_getName (spec),
7009 uentry_getType (spec)),
7010 uentry_whereSpecified (spec));
7011 }
7012 else
7013 {
7014 llgenindentmsg (message ("Specification: %t", uentry_getType (spec)),
7015 uentry_whereSpecified (spec));
7016 }
7017 }
7018 else
7019 {
7020 /* nothing to show */
7021 }
7022 }
7023}
7024
f2b6724f 7025static void
7026uentry_showWhereLastKind (uentry spec)
7027{
7028 if (uentry_isValid (spec))
7029 {
7030 if (fileloc_isDefined (spec->whereDefined)
7031 && !fileloc_isLib (spec->whereDefined)
7032 /*!! && !fileloc_isPreproc (spec->whereDefined) */ )
7033 {
7034 llgenindentmsg (message ("Previous definition of %q as %s: %t",
7035 uentry_getName (spec),
7036 ekind_unparseLong (spec->ukind),
7037 uentry_getType (spec)),
7038 uentry_whereDefined (spec));
7039 }
7040 else if (uentry_isDeclared (spec))
7041 {
7042 llgenindentmsg (message ("Previous declaration of %q as %s: %t",
7043 uentry_getName (spec),
7044 ekind_unparseLong (spec->ukind),
7045 uentry_getType (spec)),
7046 uentry_whereDeclared (spec));
7047 }
7048 else if (uentry_isSpecified (spec))
7049 {
7050 if (uentry_hasName (spec))
7051 {
7052 llgenindentmsg (message ("Specification of %q as %s: %t",
7053 uentry_getName (spec),
7054 ekind_unparseLong (spec->ukind),
7055 uentry_getType (spec)),
7056 uentry_whereSpecified (spec));
7057 }
7058 else
7059 {
7060 llgenindentmsg (message ("Specification as %s: %t",
7061 ekind_unparseLong (spec->ukind),
7062 uentry_getType (spec)),
7063 uentry_whereSpecified (spec));
7064 }
7065 }
7066 else
7067 {
7068 /* nothing to show */
7069 }
7070 }
7071}
7072
616915dd 7073void
7074uentry_showDefSpecInfo (uentry ce, fileloc fwhere)
7075{
7076 fileloc loc = uentry_whereDefined (ce);
7077
7078 if (fileloc_isUser (loc) && !fileloc_equal (loc, fwhere))
7079 {
7080 llgenindentmsg (message ("Definition of %q", uentry_getName (ce)),
7081 loc);
7082 }
7083
7084 loc = uentry_whereSpecified (ce);
7085
7086 if (fileloc_isUser (loc) && !fileloc_equal (loc, fwhere))
7087 {
7088 llgenindentmsg (message ("Specification of %q", uentry_getName (ce)),
7089 loc);
7090 }
7091}
7092
7093void uentry_showWhereLastExtra (uentry spec, cstring extra)
7094{
7095 if (uentry_isDeclared (spec))
7096 {
7097 llgenindentmsg (message ("Previous declaration of %q: %q",
7098 uentry_getName (spec), extra),
7099 uentry_whereDeclared (spec));
7100 }
7101 else if (uentry_isSpecified (spec))
7102 {
7103 llgenindentmsg (message ("Specification of %q: %q",
7104 uentry_getName (spec), extra),
7105 uentry_whereSpecified (spec));
7106 }
7107 else
7108 {
7109 cstring_free (extra);
7110 }
7111}
7112
7113void
7114uentry_showWhereDeclared (uentry spec)
7115{
7116 if (uentry_isDeclared (spec))
7117 {
7118 if (uentry_hasName (spec))
7119 {
7120 llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
7121 uentry_whereDeclared (spec));
7122 }
7123 else
7124 {
7125 llgenindentmsg (cstring_makeLiteral ("Declaration"), uentry_whereDeclared (spec));
7126 }
7127 }
7128 else if (uentry_isSpecified (spec))
7129 {
7130 if (uentry_hasName (spec))
7131 {
7132 llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
7133 uentry_whereSpecified (spec));
7134 }
7135 else
7136 {
7137 llgenindentmsg (cstring_makeLiteral ("Specification"), uentry_whereSpecified (spec));
7138 }
7139 }
7140 else
7141 {
7142 /* nothing to show */
7143 }
7144
7145}
7146
7147void
7148uentry_showWhereAny (uentry spec)
7149{
7150 if (uentry_isDeclared (spec))
7151 {
7152 if (uentry_hasName (spec))
7153 {
7154 llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
7155 uentry_whereDeclared (spec));
7156 }
7157 else
7158 {
7159 llgenindentmsg (cstring_makeLiteral ("Declaration"), uentry_whereDeclared (spec));
7160 }
7161 }
7162 else if (uentry_isSpecified (spec))
7163 {
7164 if (uentry_hasName (spec))
7165 {
7166 llgenindentmsg (message ("Specification of %q",
7167 uentry_getName (spec)),
7168 uentry_whereSpecified (spec));
7169 }
7170 else
7171 {
7172 llgenindentmsg (cstring_makeLiteral ("Specification"),
7173 uentry_whereSpecified (spec));
7174 }
7175 }
7176 else if (fileloc_isDefined (uentry_whereDefined (spec)))
7177 {
7178 if (uentry_hasName (spec))
7179 {
7180 llgenindentmsg (message ("Definition of %q", uentry_getName (spec)),
7181 uentry_whereDefined (spec));
7182 }
7183 else
7184 {
7185 llgenindentmsg (cstring_makeLiteral ("Definition"), uentry_whereDefined (spec));
7186 }
7187 }
7188 else
7189 {
7190 /* nothing to show */
7191 }
7192}
7193
7194void
7195uentry_showWhereDefined (uentry spec)
7196{
7197 if (uentry_isCodeDefined (spec))
7198 {
7199 llgenindentmsg (message ("Previous definition of %q", uentry_getName (spec)),
7200 uentry_whereDefined (spec));
7201 }
7202}
7203
7204void
7205uentry_showWhereLastPlain (uentry spec)
7206{
7207 if (uentry_isDeclared (spec))
7208 {
7209 llgenindentmsg (message ("Previous declaration of %q", uentry_getName (spec)),
7210 uentry_whereDeclared (spec));
7211 }
7212 else if (uentry_isSpecified (spec))
7213 {
7214 llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
7215 uentry_whereSpecified (spec));
7216 }
7217 else
7218 {
7219 }
7220}
7221
7222static void
7223uentry_showWhereLastVal (uentry spec, cstring val)
7224{
7225 if (uentry_isDeclared (spec))
7226 {
7227 llgenindentmsg (message ("Previous declaration of %q: %s",
7228 uentry_getName (spec), val),
7229 uentry_whereDeclared (spec));
7230 }
7231 else if (uentry_isSpecified (spec))
7232 {
7233 llgenindentmsg (message ("Specification of %q: %s",
7234 uentry_getName (spec), val),
7235 uentry_whereSpecified (spec));
7236 }
7237 else
7238 {
7239 }
7240}
7241
7242void
7243uentry_showWhereSpecified (uentry spec)
7244{
7245 if (uentry_isSpecified (spec))
7246 {
7247 if (uentry_hasName (spec))
7248 {
7249 llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
7250 uentry_whereSpecified (spec));
7251 }
7252 else
7253 {
7254 llgenindentmsg (cstring_makeLiteral ("Specification"),
7255 uentry_whereSpecified (spec));
7256 }
7257 }
7258 else if (uentry_isDeclared (spec))
7259 {
7260 llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
7261 uentry_whereDeclared (spec));
7262 }
7263 else
7264 {
7265 /* nothing to show */
7266 }
7267}
7268
7269void
7270uentry_showWhereSpecifiedExtra (uentry spec, cstring s)
7271{
7272 if (uentry_isSpecified (spec))
7273 {
7274 if (uentry_hasName (spec))
7275 {
7276 llgenindentmsg (message ("Specification of %q: %q",
7277 uentry_getName (spec), s),
7278 uentry_whereSpecified (spec));
7279 }
7280 else
7281 {
7282 llgenindentmsg (message ("Specification: %q", s),
7283 uentry_whereSpecified (spec));
7284 }
7285 }
7286 else if (uentry_isDeclared (spec))
7287 {
7288 llgenindentmsg (message ("Declaration of %q: %q",
7289 uentry_getName (spec), s),
7290 uentry_whereDeclared (spec));
7291 }
7292 else
7293 {
7294 llgenindentmsg (message ("Previous: %q", s),
7295 uentry_whereLast (spec));
7296 }
7297}
7298
7299/*
7300**
7301*/
7302
7303static void
7304checkStructConformance (uentry old, uentry unew)
7305{
7306 ctype oldr, newr;
7307 uentryList fold, fnew;
7308
7309 /*
7310 ** requires: types of old and new are structs or unions
7311 */
7312
7313 llassert (uentry_isValid (old));
7314 llassert (uentry_isValid (unew));
7315
7316 oldr = ctype_realType (old->utype);
7317 fold = ctype_getFields (oldr);
7318
7319 newr = ctype_realType (unew->utype);
7320 fnew = ctype_getFields (newr);
7321
7322 if (!uentryList_matchFields (fold, fnew))
7323 {
7324 if (fileloc_equal (uentry_whereLast (old),
7325 uentry_whereLast (unew)))
7326 {
7327 ; /* cheat! */
7328 }
7329 else
7330 {
7331 if (optgenerror
7332 (FLG_MATCHFIELDS,
7333 message ("%q %q %rdeclared with fields { %q }, %s "
7334 "with fields { %q }",
7335 cstring_makeLiteral (ctype_isStruct (newr) ? "Structure": "Union"),
7336 uentry_getName (old),
7337 uentry_isDeclared (old),
7338 uentryList_unparseAbbrev (fnew),
7339 uentry_specOrDefName (old),
7340 uentryList_unparseAbbrev (fold)),
7341 uentry_whereDeclared (unew)))
7342 {
7343 uentry_showWhereLastPlain (old);
7344 uentryList_showFieldDifference (fold, fnew);
7345 }
7346 }
7347
7348 old->utype = unew->utype;
7349 }
7350}
7351
7352static void
7353checkEnumConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
7354{
7355 /*
7356 ** requires old and new are enums
7357 */
7358
7359 ctype rold = ctype_realType (old->utype);
7360 ctype rnew = ctype_realType (unew->utype);
7361 enumNameList eold = ctype_elist (rold);
7362 enumNameList enew = ctype_elist (rnew);
7363
7364 if (!enumNameList_match (eold, enew))
7365 {
7366 if (optgenerror
7367 (FLG_MATCHFIELDS,
7368 message ("Enum %q declared with members { %q } but "
140c27a8 7369 "%s with members { %q }",
616915dd 7370 uentry_getName (old),
7371 enumNameList_unparse (enew),
140c27a8 7372 uentry_specOrDefName (old),
616915dd 7373 enumNameList_unparse (eold)),
7374 uentry_whereDeclared (unew)))
7375 {
7376 uentry_showWhereSpecified (old);
7377 old->utype = unew->utype;
7378 }
7379 }
7380}
7381
7382/*
7383** either oldCurrent or newCurrent may be undefined!
7384*/
7385
7386static void
7387paramTypeError (uentry old, uentry oldCurrent, ctype oldType,
7388 uentry unew, uentry newCurrent, ctype newType,
7389 int paramno)
7390{
7391 bool hasError = FALSE;
7392
7393 if (uentry_isValid (newCurrent) && uentry_isDeclared (newCurrent))
7394 {
7395 if (uentry_hasName (newCurrent))
7396 {
7397 hasError = optgenerror
7398 (FLG_TYPE,
7399 message ("Parameter %d, %q, of function %q has inconsistent type: "
7400 "declared %t, %s %t",
7401 paramno + 1, uentry_getName (newCurrent),
7402 uentry_getName (unew),
7403 newType, uentry_specOrDefName (old), oldType),
7404 uentry_whereDeclared (newCurrent));
7405 }
7406 else
7407 {
7408 hasError = optgenerror
7409 (FLG_TYPE,
7410 message ("Parameter %d of function %q has inconsistent type: "
7411 "declared %t, %s %t",
7412 paramno + 1, uentry_getName (unew),
7413 newType, uentry_specOrDefName (old), oldType),
7414 uentry_whereDeclared (newCurrent));
7415
7416 DPRINTF (("type: %s / %s",
7417 ctype_unparse (newType),
7418 ctype_unparse (ctype_realType (newType))));
7419 }
7420 }
7421 else
7422 {
7423 if (uentry_isDeclared (unew))
7424 {
7425 hasError = optgenerror
7426 (FLG_TYPE,
7427 message ("Parameter %d of function %s has inconsistent type: "
7428 "declared %t, %s %t",
7429 paramno + 1, unew->uname,
7430 newType, uentry_specOrDefName (old), oldType),
7431 uentry_whereDeclared (unew));
7432 }
7433 else
7434 {
7435 hasError = optgenerror
7436 (FLG_TYPE,
7437 message ("Parameter %d of function %s has inconsistent type: "
7438 "declared %t, %s %t",
7439 paramno + 1, unew->uname,
7440 newType, uentry_specOrDefName (old), oldType),
7441 uentry_whereDeclared (unew));
7442 }
7443 }
7444
7445 if (hasError)
7446 {
6970c11b 7447 DPRINTF (("Here: %s / %s",
7448 uentry_unparseFull (oldCurrent),
7449 uentry_unparseFull (newCurrent)));
7450
616915dd 7451 if (!uentry_isUndefined (oldCurrent))
7452 {
7453 if (!uentry_isUndefined (newCurrent)
7454 && cstring_equal (uentry_rawName (newCurrent), uentry_rawName (oldCurrent)))
7455 {
7456 uentry_showWhereLast (oldCurrent);
7457 }
7458 else
7459 {
7460 uentry_showWhereLastPlain (old);
7461 }
7462
7463 uentry_setType (oldCurrent, newType);
7464 }
7465 else
7466 {
7467 uentry_showWhereLastPlain (old);
7468 }
7469 }
7470}
7471
7472static void
7473nargsError (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
7474{
7475 if (optgenerror
7476 (FLG_TYPE,
28bf4b0b 7477 message ("Function %s %rdeclared with %d arg%&, %s with %d",
616915dd 7478 unew->uname,
7479 uentry_isDeclared (old),
7480 uentryList_size (uentry_getParams (unew)),
7481 uentry_specOrDefName (old),
7482 uentryList_size (uentry_getParams (old))),
7483 uentry_whereDeclared (unew)))
7484 {
7485 uentry_showWhereLastPlain (old);
7486 }
7487}
7488
7489static void
7490returnValueError (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
7491{
7492 if (optgenerror
7493 (FLG_INCONDEFS,
7494 message ("Function %s inconsistently %rdeclared to return %t",
7495 unew->uname,
7496 uentry_isDeclared (old),
28bf4b0b 7497 ctype_getReturnType (unew->utype)),
616915dd 7498 uentry_whereDeclared (unew)))
7499 {
28bf4b0b 7500 uentry_showWhereLastVal (old, ctype_unparse (ctype_getReturnType (old->utype)));
616915dd 7501 }
7502}
7503
7504static cstring paramStorageName (uentry ue)
7505{
7506 return (cstring_makeLiteralTemp (uentry_isParam (ue) ? "param" : "storage"));
7507}
7508
7509static cstring fcnErrName (uentry ue)
7510{
7511 return (cstring_makeLiteralTemp (uentry_isFunction (ue) ? "to return" : "as"));
7512}
7513
7514extern /*@observer@*/ cstring uentry_checkedName (uentry ue)
7515{
7516 if (uentry_isVar (ue))
7517 {
7518 return (checkedName (ue->info->var->checked));
7519 }
7520 else
7521 {
7522 return (cstring_makeLiteralTemp ("<checked invalid>"));
7523 }
7524}
7525
7526static cstring checkedName (chkind checked)
7527{
7528 switch (checked)
7529 {
7530 case CH_UNKNOWN: return (cstring_makeLiteralTemp ("unknown"));
7531 case CH_UNCHECKED: return (cstring_makeLiteralTemp ("unchecked"));
7532 case CH_CHECKED: return (cstring_makeLiteralTemp ("checked"));
7533 case CH_CHECKMOD: return (cstring_makeLiteralTemp ("checkmod"));
7534 case CH_CHECKEDSTRICT: return (cstring_makeLiteralTemp ("checkedstrict"));
7535 }
7536 BADEXIT;
7537}
7538
7539static
7540void checkNullState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, bool mustConform, bool completeConform)
7541{
7542 nstate oldState;
7543 nstate newState;
7544
7545 if (uentry_isVar (unew))
7546 {
7547 llassert (uentry_isVar (old));
7548
7549 oldState = old->info->var->nullstate;
7550 newState = unew->info->var->nullstate;
7551 }
7552 else
7553 {
7554 oldState = sRef_getNullState (old->sref);
7555 newState = sRef_getNullState (unew->sref);
7556 }
7557
7558 if (oldState == NS_ABSNULL)
7559 {
7560 if (uentry_isVar (old))
7561 {
7562 old->info->var->nullstate = newState;
7563 }
7564
7565 sRef_mergeNullState (old->sref, newState);
7566 }
7567 else if (newState == NS_UNKNOWN)
7568 {
7569 if (completeConform && newState != oldState
7570 && uentry_isReallySpecified (old))
7571 {
7572 if (optgenerror
7573 (FLG_NEEDSPEC,
7574 message ("%s %q specified as %s, but declared without %s qualifier",
7575 ekind_capName (unew->ukind),
7576 uentry_getName (unew),
7577 nstate_unparse (oldState),
7578 nstate_unparse (oldState)),
7579 uentry_whereDeclared (unew)))
7580 {
7581 uentry_showWhereSpecified (old);
7582 }
7583 }
7584
7585 if (uentry_isVar (unew))
7586 {
7587 unew->info->var->nullstate = oldState;
7588 }
7589
7590 sRef_mergeNullState (unew->sref, oldState);
7591 }
7592 else if (newState == NS_POSNULL)
7593 {
7594 if (oldState == NS_MNOTNULL
7595 && (ctype_isUA (unew->utype)
7596 || (uentry_isFunction (unew)
28bf4b0b 7597 && ctype_isUA (ctype_getReturnType (unew->utype)))))
616915dd 7598 {
7599 if (uentry_isVar (unew))
7600 {
7601 unew->info->var->nullstate = oldState;
7602 }
7603
7604 sRef_mergeNullState (unew->sref, oldState);
7605 }
7606 else
7607 {
7608 if (oldState == NS_NOTNULL || oldState == NS_MNOTNULL
7609 || oldState == NS_UNKNOWN)
7610 {
7611 if (mustConform)
7612 {
7613 if (optgenerror
7614 (FLG_INCONDEFS,
7615 message
7616 ("%s %q inconsistently %rdeclared %s possibly null storage, "
7617 "%s %q qualifier",
7618 uentry_ekindName (unew),
7619 uentry_getName (unew),
7620 uentry_isDeclared (old),
7621 fcnErrName (unew),
7622 uentry_specOrDefName (old),
7623 cstring_makeLiteral (oldState == NS_MNOTNULL ? "with notnull" : "without null")),
7624 uentry_whereDeclared (unew)))
7625 {
7626 uentry_showWhereSpecified (old);
7627 }
7628 }
7629 }
7630
7631 if (uentry_isVar (old))
7632 {
7633 old->info->var->nullstate = newState;
7634 }
7635
7636 sRef_mergeNullState (old->sref, newState);
7637 }
7638 }
7639 else if (newState == NS_MNOTNULL)
7640 {
7641 if (oldState != NS_MNOTNULL)
7642 {
7643 if (mustConform)
7644 {
7645 if (optgenerror
7646 (FLG_INCONDEFS,
7647 message ("%s %q inconsistently %rdeclared %s notnull storage, "
7648 "%s without notnull qualifier",
7649 uentry_ekindName (unew),
7650 uentry_getName (unew),
7651 uentry_isDeclared (old),
7652 fcnErrName (unew),
7653 uentry_specOrDefName (old)),
7654 uentry_whereDeclared (unew)))
7655 {
7656 uentry_showWhereSpecified (old);
7657 }
7658 }
7659
7660 if (uentry_isVar (old))
7661 {
7662 old->info->var->nullstate = newState;
7663 }
7664
7665 sRef_mergeNullState (old->sref, newState);
7666 }
7667 }
7668 else
7669 {
7670 if (uentry_isVar (unew))
7671 {
7672 unew->info->var->nullstate = oldState;
7673 }
7674
7675 sRef_mergeNullState (unew->sref, oldState);
7676 }
7677}
7678
7679static
7680void checkDefState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
7681 bool mustConform, bool completeConform)
7682{
7683 sstate oldState;
7684 sstate newState;
7685 bool vars = FALSE;
7686
7687 if (uentry_isVar (old) && uentry_isVar (unew))
7688 {
7689 oldState = old->info->var->defstate;
7690 newState = unew->info->var->defstate;
7691 vars = TRUE;
7692 }
7693 else
7694 {
7695 oldState = sRef_getDefState (old->sref);
7696 newState = sRef_getDefState (unew->sref);
7697 }
7698
28bf4b0b 7699 if (newState != oldState
7700 && newState != SS_UNKNOWN
7701 && newState != SS_DEFINED)
616915dd 7702 {
7703 if (mustConform)
7704 {
7705 if (optgenerror
7706 (FLG_INCONDEFS,
7707 message ("%s %q inconsistently %rdeclared %s %s %s, "
7708 "%s %s %s %s",
7709 uentry_ekindName (unew),
7710 uentry_getName (unew),
7711 uentry_isDeclared (old),
7712 fcnErrName (unew),
7713 sstate_unparse (newState),
7714 paramStorageName (unew),
7715 uentry_specOrDefName (old),
7716 fcnErrName (unew),
7717 sstate_unparse (oldState),
7718 paramStorageName (unew)),
7719 uentry_whereDeclared (unew)))
7720 {
7721 uentry_showWhereSpecified (old);
7722 }
7723 }
28bf4b0b 7724
616915dd 7725 if (vars) old->info->var->defstate = newState;
7726 sRef_setDefState (old->sref, newState, uentry_whereDeclared (unew));
7727 }
7728 else
7729 {
7730 if (completeConform
7731 && (newState != oldState) && (oldState != SS_DEFINED)
7732 && uentry_isReallySpecified (old))
7733 {
7734 if (optgenerror
7735 (FLG_NEEDSPEC,
7736 message ("%s %q specified as %s, but declared without %s qualifier",
7737 ekind_capName (unew->ukind),
7738 uentry_getName (unew),
7739 sstate_unparse (oldState),
7740 sstate_unparse (oldState)),
7741 uentry_whereDeclared (unew)))
7742 {
7743 uentry_showWhereSpecified (old);
7744 }
7745 }
28bf4b0b 7746
616915dd 7747 if (vars) unew->info->var->defstate = oldState;
7748 sRef_setDefState (unew->sref, oldState, uentry_whereDeclared (unew));
7749 }
7750}
7751
7752static void
7753 checkAliasState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
7754 bool mustConform, bool completeConform)
7755{
7756 alkind newKind;
7757 alkind oldKind;
7758
7759 oldKind = sRef_getAliasKind (old->sref);
7760 newKind = sRef_getAliasKind (unew->sref);
7761
7762 if (alkind_isImplicit (newKind)
7763 || (alkind_isRefCounted (newKind) && !uentry_isDatatype (unew)))
7764 {
7765 if (completeConform && !alkind_equal (newKind, oldKind)
7766 && uentry_isReallySpecified (old))
7767 {
7768 if (optgenerror
7769 (FLG_NEEDSPEC,
7770 message ("%s %q specified as %s, but declared without "
7771 "explicit alias qualifier",
7772 ekind_capName (unew->ukind),
7773 uentry_getName (unew),
7774 alkind_unparse (oldKind)),
7775 uentry_whereDeclared (unew)))
7776 {
7777 uentry_showWhereSpecified (old);
7778 }
7779 }
7780
7781 /*
7782 ** This really shouldn't be necessary, but it is!
7783 ** Function params (?) use new here.
7784 */
7785
7786 sRef_setAliasKind (unew->sref, oldKind, uentry_whereDeclared (unew));
7787 return;
7788 }
7789
7790 if (alkind_isKnown (newKind))
7791 {
7792 if (!alkind_equal (oldKind, newKind))
7793 {
7794 if (alkind_isKnown (oldKind))
7795 {
7796 if (mustConform &&
7797 optgenerror
7798 (FLG_INCONDEFS,
7799 message ("%s %q inconsistently %rdeclared %s %s storage, "
7800 "%s as %s storage",
7801 uentry_ekindName (unew),
7802 uentry_getName (unew),
7803 uentry_isDeclared (old),
7804 fcnErrName (unew),
7805 alkind_unparse (newKind),
7806 uentry_specOrDefName (old),
7807 alkind_unparse (oldKind)),
7808 uentry_whereDeclared (unew)))
7809 {
7810 uentry_showWhereSpecified (old);
7811
28bf4b0b 7812 DPRINTF (("Old: %s", sRef_unparseFull (old->sref)));
7813 DPRINTF (("New: %s", sRef_unparseFull (unew->sref)));
616915dd 7814 sRef_setAliasKind (old->sref, AK_ERROR,
7815 uentry_whereDeclared (unew));
7816 }
7817 else
7818 {
7819 sRef_setAliasKind (old->sref, newKind,
7820 uentry_whereDeclared (unew));
7821 }
7822 }
7823 else
7824 {
7825 if (!(alkind_isImplicit (newKind)))
7826 {
7827 if (mustConform &&
7828 !uentry_isFunction (unew) &&
7829 optgenerror
7830 (FLG_INCONDEFS,
7831 message ("%s %q inconsistently %rdeclared %s %s storage, "
7832 "implicitly %s as temp storage",
7833 uentry_ekindName (unew),
7834 uentry_getName (unew),
7835 uentry_isDeclared (old),
7836 fcnErrName (unew),
7837 alkind_unparse (newKind),
7838 uentry_specOrDefName (old)),
7839 uentry_whereDeclared (unew)))
7840 {
7841 uentry_showWhereSpecified (old);
7842 oldKind = AK_ERROR;
7843 }
7844
7845 sRef_setAliasKind (old->sref, newKind,
7846 uentry_whereDeclared (unew));
7847 }
7848 else /* newKind is temp or refcounted */
7849 {
7850 ;
7851 }
7852 }
7853 }
7854 }
7855 else /* newKind unknown */
7856 {
7857 ;
7858 }
7859}
7860
7861static void
7862 checkExpState(/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
7863 bool mustConform, bool completeConform)
7864{
7865 exkind newKind;
7866 exkind oldKind;
7867
7868 oldKind = sRef_getExKind (old->sref);
7869 newKind = sRef_getExKind (unew->sref);
7870
7871 if (exkind_isKnown (newKind))
7872 {
7873 if (oldKind != newKind)
7874 {
7875 if (exkind_isKnown (oldKind))
7876 {
7877 if (mustConform &&
7878 optgenerror
7879 (FLG_INCONDEFS,
7880 message ("%s %q inconsistently %rdeclared %s %s, %s as %s",
7881 uentry_ekindName (unew),
7882 uentry_getName (unew),
7883 uentry_isDeclared (old),
7884 fcnErrName (unew),
7885 exkind_unparse (newKind),
7886 uentry_specOrDefName (old),
7887 exkind_unparse (oldKind)),
7888 uentry_whereDeclared (unew)))
7889 {
7890 uentry_showWhereSpecified (old);
7891 }
7892
7893 sRef_setExKind (old->sref, newKind, uentry_whereDefined (unew));
7894 }
7895 else
7896 {
7897 if (mustConform &&
7898 optgenerror
7899 (FLG_INCONDEFS,
7900 message ("%s %q inconsistently %rdeclared %s %s, "
7901 "implicitly %s without exposure qualifier",
7902 uentry_ekindName (unew),
7903 uentry_getName (unew),
7904 uentry_isDeclared (old),
7905 fcnErrName (unew),
7906 exkind_unparse (newKind),
7907 uentry_specOrDefName (old)),
7908 uentry_whereDeclared (unew)))
7909 {
7910 uentry_showWhereSpecified (old);
7911 }
7912
7913 sRef_setExKind (old->sref, newKind, uentry_whereDefined (unew));
7914 }
7915 }
7916 }
7917 else
7918 {
7919 if (completeConform && exkind_isKnown (oldKind)
7920 && uentry_isReallySpecified (old))
7921 {
7922 if (optgenerror
7923 (FLG_NEEDSPEC,
7924 message ("%s %q specified as %s, but declared without "
7925 "exposure qualifier",
7926 ekind_capName (unew->ukind),
7927 uentry_getName (unew),
7928 exkind_unparse (oldKind)),
7929 uentry_whereDeclared (unew)))
7930 {
7931 uentry_showWhereSpecified (old);
7932 }
7933 }
7934
7935 /* yes, this is necessary! (if its a param) */
7936 sRef_setExKind (unew->sref, oldKind, fileloc_undefined);
7937 }
7938}
7939
28bf4b0b 7940static void
7941checkMetaState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
7942 bool mustConform, /*@unused@*/ bool completeConform)
7943{
7944 valueTable newvals = sRef_getValueTable (unew->sref);
7945
7946 if (valueTable_isDefined (newvals))
7947 {
7948 DPRINTF (("Check meta state: %s -> %s",
7949 uentry_unparseFull (old),
7950 uentry_unparseFull (unew)));
7951
7952 DPRINTF (("Check meta state refs: %s -> %s",
7953 sRef_unparseFull (old->sref),
7954 sRef_unparseFull (unew->sref)));
7955
7956 DPRINTF (("Value table: %s", valueTable_unparse (newvals)));
7957
7958 /*
7959 ** Copy the new values into the old ref
7960 */
7961
7962 valueTable_elements (newvals, key, newval)
7963 {
7964 metaStateInfo msinfo = context_lookupMetaStateInfo (key);
7965 stateValue oldval = sRef_getMetaStateValue (old->sref, key);
7966
7967 llassert (metaStateInfo_isDefined (msinfo));
7968
7969 if (stateValue_isUndefined (oldval))
7970 {
7971 sRef_setMetaStateValue (old->sref, key, stateValue_getValue (newval), uentry_whereLast (unew));
7972 }
7973 else
7974 {
7975 if (stateValue_isError (oldval))
7976 {
7977 if (!stateValue_isError (newval))
7978 {
7979 sRef_setMetaStateValue (old->sref, key, stateValue_getValue (newval), uentry_whereLast (unew));
7980 }
7981 else
7982 {
7983 ; /* No change necessary. */
7984 }
7985 }
7986 else
7987 {
7988 if (stateValue_getValue (newval) != stateValue_getValue (oldval))
7989 {
7990 if (fileloc_isXHFile (uentry_whereDeclared (unew)))
7991 {
7992 ;
7993 }
7994 else
7995 {
ccf0a4a8 7996 if (!stateValue_isError (newval)
7997 && !stateValue_isImplicit (newval))
28bf4b0b 7998 {
ccf0a4a8 7999 if (uentry_hasName (unew)
8000 || !sRef_isParam (uentry_getSref (unew)))
8001 {
8002 if (mustConform
8003 && optgenerror
8004 (FLG_INCONDEFS,
8005 message ("%s %q inconsistently %rdeclared %s %q, %s as %q",
8006 uentry_ekindName (unew),
8007 uentry_getName (unew),
8008 uentry_isDeclared (old),
8009 fcnErrName (unew),
8010 stateValue_unparseValue (newval, msinfo),
8011 uentry_specOrDefName (old),
8012 stateValue_unparseValue (oldval, msinfo)),
8013 uentry_whereDeclared (unew)))
8014 {
8015 uentry_showWhereSpecified (old);
8016 }
8017 }
8018 else
abb1cb43 8019 {
ccf0a4a8 8020 if (mustConform
8021 && optgenerror
8022 (FLG_INCONDEFS,
8023 message ("%s %d inconsistently %rdeclared %s %q, %s as %q",
8024 uentry_ekindName (unew),
8025 sRef_getParam (uentry_getSref (unew)),
8026 uentry_isDeclared (old),
8027 fcnErrName (unew),
8028 stateValue_unparseValue (newval, msinfo),
8029 uentry_specOrDefName (old),
8030 stateValue_unparseValue (oldval, msinfo)),
8031 uentry_whereDeclared (unew)))
8032 {
8033 uentry_showWhereSpecified (old);
8034 }
abb1cb43 8035 }
28bf4b0b 8036 }
8037 }
8038
8039 DPRINTF (("Updating!"));
8040 sRef_setMetaStateValue (old->sref, key, stateValue_getValue (newval), uentry_whereLast (unew));
8041 }
8042 else
8043 {
8044 DPRINTF (("Values match"));
8045 }
8046 }
8047 }
8048 } end_valueTable_elements ;
8049 }
8050}
8051
616915dd 8052static void
8053uentry_checkStateConformance (/*@notnull@*/ uentry old,
8054 /*@notnull@*/ uentry unew,
8055 bool mustConform, bool completeConform)
8056{
8057 checkDefState (old, unew, mustConform, completeConform);
8058 checkNullState (old, unew, mustConform, completeConform);
8059 checkAliasState (old, unew, mustConform, completeConform);
8060 checkExpState (old, unew, mustConform, completeConform);
28bf4b0b 8061 checkMetaState (old, unew, mustConform, completeConform);
616915dd 8062
8063 sRef_storeState (old->sref);
8064 sRef_storeState (unew->sref);
8065}
8066
8067static void
8068checkVarConformance (uentry old, uentry unew, bool mustConform, bool completeConform)
8069{
8070 if (uentry_isElipsisMarker (old) || uentry_isElipsisMarker (unew))
8071 {
8072 return;
8073 }
8074
8075 llassert (uentry_isVar (old));
8076 llassert (uentry_isVar (unew));
8077
8078 if (cstring_isEmpty (old->uname))
8079 {
8080 cstring_free (old->uname);
8081 old->uname = cstring_copy (unew->uname);
8082 }
8083
8084 if (unew->info->var->kind == VKRETPARAM
8085 || unew->info->var->kind == VKSEFRETPARAM)
8086 {
8087 if (old->info->var->kind != VKRETPARAM
8088 && old->info->var->kind != VKSEFRETPARAM)
8089 {
8090 if (optgenerror
8091 (FLG_INCONDEFS,
8092 message ("Parameter %q inconsistently %rdeclared as "
8093 "returned parameter",
8094 uentry_getName (unew),
8095 uentry_isDeclared (old)),
8096 uentry_whereDeclared (unew)))
8097 {
8098 uentry_showWhereSpecified (old);
8099 old->info->var->kind = unew->info->var->kind;
8100 }
8101 }
8102 }
8103
8104
8105 if (unew->info->var->kind == VKSEFPARAM || unew->info->var->kind == VKSEFRETPARAM)
8106 {
8107 if (old->info->var->kind != VKSEFPARAM
8108 && old->info->var->kind != VKSEFRETPARAM)
8109 {
8110 if (optgenerror
8111 (FLG_INCONDEFS,
8112 message ("Parameter %qinconsistently %rdeclared as "
8113 "sef parameter",
8114 uentry_getOptName (unew),
8115 uentry_isDeclared (old)),
8116 uentry_whereDeclared (unew)))
8117 {
8118 uentry_showWhereSpecified (old);
8119 old->info->var->kind = unew->info->var->kind;
8120 }
8121 }
8122 }
8123
8124 if (old->info->var->kind == VKSPEC)
8125 {
8126 old->info->var->kind = unew->info->var->kind;
8127 }
8128 else
8129 {
8130 unew->info->var->kind = old->info->var->kind;
8131 }
8132
8133 if (unew->info->var->checked != CH_UNKNOWN
8134 && unew->info->var->checked != old->info->var->checked)
8135 {
8136 if (old->info->var->checked == CH_UNKNOWN
8137 && !fileloc_isUser (uentry_whereLast (old)))
8138 {
8139 ; /* no error */
8140 }
8141 else
8142 {
8143 if (optgenerror
8144 (FLG_INCONDEFS,
8145 message ("Variable %q inconsistently %rdeclared as "
8146 "%s parameter (was %s)",
8147 uentry_getName (unew),
8148 uentry_isDeclared (old),
8149 checkedName (unew->info->var->checked),
8150 checkedName (old->info->var->checked)),
8151 uentry_whereDeclared (unew)))
8152 {
8153 uentry_showWhereSpecified (old);
8154 }
8155 }
8156
8157 old->info->var->checked = unew->info->var->checked;
8158 }
8159 else
8160 {
8161 if (completeConform
8162 && (old->info->var->checked != CH_UNKNOWN)
8163 && uentry_isReallySpecified (old))
8164 {
8165 if (optgenerror
8166 (FLG_NEEDSPEC,
8167 message ("%s %q specified as %s, but declared without %s qualifier",
8168 ekind_capName (unew->ukind),
8169 uentry_getName (unew),
8170 checkedName (old->info->var->checked),
8171 checkedName (old->info->var->checked)),
8172 uentry_whereDeclared (unew)))
8173 {
8174 uentry_showWhereSpecified (old);
8175 }
8176 }
8177
8178 unew->info->var->checked = old->info->var->checked;
8179 }
8180
8181 uentry_checkStateConformance (old, unew, mustConform, completeConform);
8182}
8183
8184void uentry_checkMatchParam (uentry u1, uentry u2, int paramno, exprNode e)
8185{
8186 if (uentry_isElipsisMarker (u1) || uentry_isElipsisMarker (u2))
8187 {
8188 return;
8189 }
8190
8191 llassert (uentry_isVar (u1));
8192 llassert (uentry_isVar (u2));
8193
8194 if (u1->info->var->kind != u2->info->var->kind) {
8195 if (u1->info->var->kind == VKSEFRETPARAM) {
8196 if (u2->info->var->kind == VKRETPARAM) {
8197 voptgenerror
8198 (FLG_TYPE,
8199 message ("Function types are inconsistent. Parameter %d is "
8200 "sef parameter, but non-sef parameter in "
8201 "assigned function: %s",
8202 paramno, exprNode_unparse (e)),
8203 exprNode_loc (e));
8204 } else if (u2->info->var->kind == VKSEFPARAM) {
8205 voptgenerror
8206 (FLG_TYPE,
8207 message ("Function types are inconsistent. Parameter %d is "
8208 "returns parameter, but non-returns parameter in "
8209 "assigned function: %s",
8210 paramno, exprNode_unparse (e)),
8211 exprNode_loc (e));
8212 } else {
8213 voptgenerror
8214 (FLG_TYPE,
8215 message ("Function types are inconsistent. Parameter %d is "
8216 "sef returns parameter, but non-sef returns parameter in "
8217 "assigned function: %s",
8218 paramno, exprNode_unparse (e)),
8219 exprNode_loc (e));
8220 }
8221 } else if (u1->info->var->kind == VKRETPARAM) {
8222 voptgenerror
8223 (FLG_TYPE,
8224 message ("Function types are inconsistent. Parameter %d is "
8225 "returns parameter, but non-returns parameter in "
8226 "assigned function: %s",
8227 paramno, exprNode_unparse (e)),
8228 exprNode_loc (e));
8229 } else if (u1->info->var->kind == VKSEFPARAM) {
8230 voptgenerror
8231 (FLG_TYPE,
8232 message ("Function types are inconsistent. Parameter %d is "
8233 "sef parameter, but non-sef parameter in "
8234 "assigned function: %s",
8235 paramno, exprNode_unparse (e)),
8236 exprNode_loc (e));
8237 } else {
8238 if (u2->info->var->kind == VKSEFRETPARAM) {
8239 voptgenerror
8240 (FLG_TYPE,
8241 message ("Function types are inconsistent. Parameter %d is "
8242 "normal parameter, but sef returns parameter in "
8243 "assigned function: %s",
8244 paramno, exprNode_unparse (e)),
8245 exprNode_loc (e));
8246 } else if (u2->info->var->kind == VKSEFPARAM) {
8247 voptgenerror
8248 (FLG_TYPE,
8249 message ("Function types are inconsistent. Parameter %d is "
8250 "normal parameter, but sef parameter in "
8251 "assigned function: %s",
8252 paramno, exprNode_unparse (e)),
8253 exprNode_loc (e));
8254 } else if (u2->info->var->kind == VKRETPARAM) {
8255 voptgenerror
8256 (FLG_TYPE,
8257 message ("Function types are inconsistent. Parameter %d is "
8258 "normal parameter, but returns parameter in "
8259 "assigned function: %s",
8260 paramno, exprNode_unparse (e)),
8261 exprNode_loc (e));
8262 } else {
8263 BADBRANCH;
8264 }
8265 }
8266 }
8267
8268 if (u1->info->var->defstate != u2->info->var->defstate)
8269 {
8270 voptgenerror
8271 (FLG_TYPE,
8272 message ("Function types are inconsistent. Parameter %d is "
8273 "%s, but %s in assigned function: %s",
8274 paramno,
8275 sstate_unparse (u1->info->var->defstate),
8276 sstate_unparse (u2->info->var->defstate),
8277 exprNode_unparse (e)),
8278 exprNode_loc (e));
8279 }
8280
8281 if (u1->info->var->nullstate != u2->info->var->nullstate)
8282 {
8283 voptgenerror
8284 (FLG_TYPE,
8285 message ("Function types are inconsistent. Parameter %d is "
8286 "%s, but %s in assigned function: %s",
8287 paramno,
8288 nstate_unparse (u1->info->var->nullstate),
8289 nstate_unparse (u2->info->var->nullstate),
8290 exprNode_unparse (e)),
8291 exprNode_loc (e));
8292 }
8293
8294 if (sRef_getAliasKind (u1->sref) != sRef_getAliasKind (u2->sref))
8295 {
8296 voptgenerror
8297 (FLG_TYPE,
8298 message ("Function types are inconsistent. Parameter %d is "
8299 "%s, but %s in assigned function: %s",
8300 paramno,
8301 alkind_unparse (sRef_getAliasKind (u1->sref)),
8302 alkind_unparse (sRef_getAliasKind (u2->sref)),
8303 exprNode_unparse (e)),
8304 exprNode_loc (e));
8305 }
8306
8307 if (sRef_getExKind (u1->sref) != sRef_getExKind (u2->sref))
8308 {
8309 voptgenerror
8310 (FLG_TYPE,
8311 message ("Function types are inconsistent. Parameter %d is "
8312 "%s, but %s in assigned function: %s",
8313 paramno,
8314 exkind_unparse (sRef_getExKind (u1->sref)),
8315 exkind_unparse (sRef_getExKind (u2->sref)),
8316 exprNode_unparse (e)),
8317 exprNode_loc (e));
8318 }
8319}
8320
aec3dcdb 8321static void uentry_convertIntoFunction (/*@notnull@*/ uentry old)
8322{
8323 /*
8324 ** Convert old into a function
8325 */
8326
8327 old->ukind = KFCN;
8328 old->utype = ctype_unknown;
8329 old->info->fcn = (ufinfo) dmalloc (sizeof (*old->info->fcn));
8330 old->info->fcn->hasMods = FALSE;
8331 old->info->fcn->hasGlobs = FALSE;
8332 old->info->fcn->exitCode = XK_UNKNOWN;
8333 old->info->fcn->nullPred = qual_createUnknown ();
8334 old->info->fcn->specialCode = SPC_NONE;
8335 old->info->fcn->access = typeIdSet_undefined;
8336 old->info->fcn->globs = globSet_undefined;
8337 old->info->fcn->defparams = uentryList_undefined;
8338 old->info->fcn->mods = sRefSet_undefined;
8339 old->info->fcn->specclauses = NULL;
8340 old->info->fcn->preconditions = NULL;
8341 old->info->fcn->postconditions = NULL;
8342}
8343
616915dd 8344static void
8345checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old,
8346 /*@notnull@*/ uentry unew,
8347 bool mustConform, /*@unused@*/ bool completeConform)
8348{
8349 uentryList oldParams = uentry_getParams (old);
8350 uentryList newParams = uentry_getParams (unew);
8351 ctype newType = unew->utype;
ac35a6ab 8352 ctype oldType = ctype_realType (old->utype);
616915dd 8353 ctype oldRetType = ctype_unknown;
8354 ctype newRetType = ctype_unknown;
8355
28bf4b0b 8356 DPRINTF (("Function conform: %s ==> %s",
8357 uentry_unparseFull (old),
8358 uentry_unparseFull (unew)));
8359
616915dd 8360 if (uentry_isForward (old))
8361 {
8362 mustConform = FALSE;
efd360a3 8363 uentry_updateInto (old, unew);
616915dd 8364 return;
8365 }
8366
8367 /*
8368 ** check return values
8369 */
8370
8371 if (ctype_isKnown (oldType))
8372 {
aec3dcdb 8373 if (ctype_isFunction (oldType))
8374 {
8375 oldRetType = ctype_getReturnType (oldType);
8376 }
8377 else
8378 {
8379 if (optgenerror
8380 (FLG_INCONDEFS,
8381 message ("%s %q declared as function, but previously declared as %s",
8382 ekind_capName (unew->ukind),
8383 uentry_getName (unew),
8384 ekind_unparseLong (old->ukind)),
8385 uentry_whereDeclared (unew)))
8386 {
8387 uentry_showWhereLast (old);
8388 }
8389
8390 uentry_convertIntoFunction (old);
8391 return;
8392 }
616915dd 8393 }
8394
8395 if (ctype_isKnown (newType))
8396 {
8397 llassert (ctype_isFunction (newType));
28bf4b0b 8398 newRetType = ctype_getReturnType (newType);
616915dd 8399 }
8400
8401 if (ctype_isKnown (oldRetType) && ctype_isKnown (newRetType)
8402 && !ctype_matchDef (newRetType, oldRetType))
8403 {
8404 if (mustConform) returnValueError (old, unew);
8405 }
8406 else
8407 {
8408 if (ctype_isConj (newRetType))
8409 {
8410 if (ctype_isConj (oldRetType))
8411 {
8412 if (!ctype_sameAltTypes (newRetType, oldRetType))
8413 {
8414 if (optgenerror
8415 (FLG_INCONDEFS,
8416 message ("Function %q inconsistently %rdeclared to "
8417 "return alternate types %s "
8418 "(types match, but alternates are not identical, "
8419 "so checking may not be correct)",
8420 uentry_getName (unew),
8421 uentry_isDeclared (old),
8422 ctype_unparse (newRetType)),
8423 uentry_whereDeclared (unew)))
8424 {
8425 uentry_showWhereLastVal (old, ctype_unparse (oldRetType));
8426 }
8427 }
8428 }
8429 else
8430 {
8431 old->utype = ctype_makeFunction (oldRetType, uentryList_copy (newParams));
8432 }
8433 }
8434 }
8435
28bf4b0b 8436 DPRINTF (("Before state: %s",
8437 uentry_unparseFull (old)));
616915dd 8438 uentry_checkStateConformance (old, unew, mustConform, completeConform);
28bf4b0b 8439 DPRINTF (("After state: %s",
8440 uentry_unparseFull (old)));
616915dd 8441
8442 if (!exitkind_equal (unew->info->fcn->exitCode, old->info->fcn->exitCode))
8443 {
8444 if (exitkind_isKnown (unew->info->fcn->exitCode))
8445 {
8446 if (optgenerror
8447 (FLG_INCONDEFS,
8448 message ("Function %q inconsistently %rdeclared using %s",
8449 uentry_getName (unew),
8450 uentry_isDeclared (old),
8451 exitkind_unparse (unew->info->fcn->exitCode)),
8452 uentry_whereDeclared (unew)))
8453 {
8454 uentry_showWhereSpecified (old);
8455 }
8456 }
8457 else
8458 {
8459 unew->info->fcn->exitCode = old->info->fcn->exitCode;
8460 }
8461 }
8462
8463 if (!qual_isUnknown (unew->info->fcn->nullPred))
8464 {
28bf4b0b 8465 if (!qual_match (old->info->fcn->nullPred, unew->info->fcn->nullPred))
616915dd 8466 {
8467 if (optgenerror
8468 (FLG_INCONDEFS,
8469 message ("Function %q inconsistently %rdeclared using %s",
8470 uentry_getName (unew),
8471 uentry_isDeclared (old),
8472 qual_unparse (unew->info->fcn->nullPred)),
8473 uentry_whereDeclared (unew)))
8474 {
8475 uentry_showWhereSpecified (old);
8476 }
8477 }
8478 }
8479 else
8480 {
8481 unew->info->fcn->nullPred = old->info->fcn->nullPred;
8482 }
8483
8484 if (unew->info->fcn->specialCode != SPC_NONE)
8485 {
8486 if (old->info->fcn->specialCode != unew->info->fcn->specialCode)
8487 {
8488 if (optgenerror
8489 (FLG_INCONDEFS,
8490 message ("Function %q inconsistently %rdeclared using %s",
8491 uentry_getName (unew),
8492 uentry_isDeclared (old),
8493 specCode_unparse (unew->info->fcn->specialCode)),
8494 uentry_whereDeclared (unew)))
8495 {
8496 uentry_showWhereSpecified (old);
8497 }
8498 }
8499 }
8500 else
8501 {
8502 unew->info->fcn->specialCode = old->info->fcn->specialCode;
8503 }
8504
8505 /*
8506 ** check parameters
8507 */
8508
8509 if (!uentryList_sameObject (oldParams, newParams)
8510 && (!uentryList_isMissingParams (oldParams)))
8511 {
8512 if (!uentryList_isMissingParams (newParams))
8513 {
8514 int paramno = 0;
8515 int nparams = uentryList_size (oldParams);
8516 bool checknames = context_maybeSet (FLG_DECLPARAMMATCH);
8517
8518 if (nparams != uentryList_size (newParams))
8519 {
8520 nargsError (old, unew);
8521 }
8522
8523 if (uentryList_size (newParams) < nparams)
8524 {
8525 nparams = uentryList_size (newParams);
8526 }
8527
8528 while (paramno < nparams)
8529 {
8530 uentry oldCurrent = uentryList_getN (oldParams, paramno);
8531 uentry newCurrent = uentryList_getN (newParams, paramno);
8532 ctype oldCurrentType = uentry_getType (oldCurrent);
8533 ctype newCurrentType = uentry_getType (newCurrent);
8534
8535 llassert (uentry_isValid (oldCurrent)
8536 && uentry_isValid (newCurrent));
8537
8538 if (!uentry_isElipsisMarker (oldCurrent)
8539 && !uentry_isElipsisMarker (newCurrent))
8540 {
8541 checkVarConformance (oldCurrent, newCurrent,
8542 mustConform, completeConform);
8543 }
8544
8545 if (checknames)
8546 {
8547 if (uentry_hasName (oldCurrent)
8548 && uentry_hasName (newCurrent))
8549 {
8550 cstring oldname = uentry_getName (oldCurrent);
8551 cstring pfx = context_getString (FLG_DECLPARAMPREFIX);
8552 cstring oname;
8553 cstring nname = uentry_getName (newCurrent);
8554 cstring nnamefix;
8555
8556 if (cstring_isDefined (pfx)
68de3f33 8557 && cstring_equalPrefix (oldname, pfx))
616915dd 8558 {
8559 oname = cstring_suffix (oldname, cstring_length (pfx));
8560 }
8561 else
8562 {
8563 oname = oldname;
8564 /*@-branchstate@*/ } /*@=branchstate@*/
8565
8566 if (cstring_isDefined (pfx)
68de3f33 8567 && cstring_equalPrefix (nname, pfx))
616915dd 8568 {
8569 nnamefix = cstring_suffix (nname, cstring_length (pfx));
8570 }
8571 else
8572 {
8573 nnamefix = nname;
8574 /*@-branchstate@*/ } /*@=branchstate@*/
8575
8576 if (!cstring_equal (oname, nnamefix))
8577 {
8578 if (optgenerror
8579 (FLG_DECLPARAMMATCH,
8580 message ("Definition parameter name %s does not match "
8581 "name of corresponding parameter in "
8582 "declaration: %s",
8583 nnamefix, oname),
8584 uentry_whereLast (newCurrent)))
8585 {
8586 uentry_showWhereLastPlain (oldCurrent);
8587 }
8588 }
8589
8590 cstring_free (oldname);
8591 cstring_free (nname);
8592 }
8593 }
8594
8595 if (!ctype_match (oldCurrentType, newCurrentType))
8596 {
8597 paramTypeError (old, oldCurrent, oldCurrentType,
8598 unew, newCurrent, newCurrentType, paramno);
8599 }
8600 else
8601 {
8602 if (ctype_isMissingParamsMarker (newCurrentType)
8603 || ctype_isElips (newCurrentType)
8604 || ctype_isMissingParamsMarker (oldCurrentType)
8605 || ctype_isElips (oldCurrentType))
8606 {
8607 ;
8608 }
8609 else
8610 {
8611 if (ctype_isConj (newCurrentType))
8612 {
8613 if (ctype_isConj (oldCurrentType))
8614 {
8615 if (!ctype_sameAltTypes (newCurrentType, oldCurrentType))
8616 {
8617 if (optgenerror
8618 (FLG_INCONDEFS,
8619 message ("Parameter %q inconsistently %rdeclared with "
8620 "alternate types %s "
8621 "(types match, but alternates are not identical, "
8622 "so checking may not be correct)",
8623 uentry_getName (newCurrent),
8624 uentry_isDeclared (oldCurrent),
8625 ctype_unparse (newCurrentType)),
8626 uentry_whereDeclared (unew)))
8627 {
8628 uentry_showWhereLastVal (oldCurrent,
8629 ctype_unparse (oldCurrentType));
8630 }
8631 }
8632 }
8633 else
8634 {
8635 if (optgenerror
8636 (FLG_INCONDEFS,
8637 message ("Parameter %q inconsistently %rdeclared with "
8638 "alternate types %s",
8639 uentry_getName (newCurrent),
8640 uentry_isDeclared (oldCurrent),
8641 ctype_unparse (newCurrentType)),
8642 uentry_whereDeclared (unew)))
8643 {
8644 uentry_showWhereLastVal (oldCurrent,
8645 ctype_unparse (oldCurrentType));
8646
8647 }
8648 }
8649 }
8650 else
8651 {
8652 if (ctype_isConj (oldCurrentType))
8653 {
8654 uentry_setType (newCurrent, oldCurrentType);
8655 }
8656 }
8657 }
8658 }
8659
8660 paramno++;
8661 /*
1b8ae690 8662 ** Forgot this! detected by splint:
616915dd 8663 ** uentry.c:1257,15: Suspected infinite loop
8664 */
8665 }
8666 }
8667 }
8668
8669 if (!uentryList_isMissingParams (newParams))
8670 {
8671 if (ctype_isConj (oldRetType))
8672 {
8673 old->utype = ctype_makeFunction (oldRetType,
8674 uentryList_copy (newParams));
8675 }
8676 else
8677 {
8678 old->utype = unew->utype;
8679 }
8680 }
8681
8682 checkGlobalsConformance (old, unew, mustConform, completeConform);
8683 checkModifiesConformance (old, unew, mustConform, completeConform);
8684
28bf4b0b 8685 DPRINTF (("Before list: %s",
8686 uentry_unparseFull (old)));
8687
8688 if (stateClauseList_isDefined (unew->info->fcn->specclauses))
616915dd 8689 {
28bf4b0b 8690 if (!stateClauseList_isDefined (old->info->fcn->specclauses))
616915dd 8691 {
28bf4b0b 8692 /*
616915dd 8693 if (optgenerror
8694 (FLG_INCONDEFS,
8695 message ("Function %q redeclared using special clauses (can only "
8696 "be used in first declaration)",
8697 uentry_getName (unew)),
8698 uentry_whereDeclared (unew)))
8699 {
8700 uentry_showWhereLast (old);
8701 }
28bf4b0b 8702 */
8703
b73d1009 8704 /* need to add some checking @*/
28bf4b0b 8705 old->info->fcn->specclauses = unew->info->fcn->specclauses;
616915dd 8706 }
8707 else
8708 {
b73d1009 8709 /* should be able to append? */
28bf4b0b 8710
8711 stateClauseList_checkEqual (old, unew);
8712 stateClauseList_free (unew->info->fcn->specclauses);
8713 unew->info->fcn->specclauses = stateClauseList_undefined;
8714 /*@-branchstate@*/
616915dd 8715 }
8716 }
b73d1009 8717 /*@=branchstate@*/ /* shouldn't need this */
616915dd 8718
8719 if (fileloc_isUndefined (old->whereDeclared))
8720 {
8721 old->whereDeclared = fileloc_copy (unew->whereDeclared);
8722 }
8723 else if (fileloc_isUndefined (unew->whereDeclared))
8724 {
8725 unew->whereDeclared = fileloc_copy (old->whereDeclared);
8726 }
8727 else
8728 {
8729 /* no change */
8730 }
b73d1009 8731 /*@-compmempass@*/
8732} /*@=compmempass@*/ /* I think this is a spurious warning */
616915dd 8733
8734void
8735uentry_mergeConstantValue (uentry ue, /*@only@*/ multiVal m)
8736{
8737 multiVal uval;
8738
8739 llassert (uentry_isValid (ue));
8740 llassert (uentry_isEitherConstant (ue));
8741
b9904f57 8742 DPRINTF (("Constant value: %s / %s", uentry_unparse (ue), multiVal_unparse (m)));
8743 uval = uentry_getConstantValue (ue);
616915dd 8744
8745 if (multiVal_isDefined (uval))
8746 {
8747 if (multiVal_isDefined (m))
8748 {
8749 if (!multiVal_equiv (uval, m))
8750 {
8751 if (optgenerror
8752 (FLG_INCONDEFS,
8753 message ("%s %q defined with inconsistent value: %q",
8754 ekind_capName (ue->ukind),
8755 uentry_getName (ue),
8756 multiVal_unparse (m)),
8757 g_currentloc))
8758 {
8759 uentry_showWhereLastExtra (ue, multiVal_unparse (uval));
8760 }
8761 }
8762 }
8763 multiVal_free (m);
8764 }
8765 else
8766 {
b9904f57 8767 uentry_setConstantValue (ue, m);
616915dd 8768 }
8769}
8770
8771static
8772bool checkTypeConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
8773 bool mustConform)
8774{
8775 bool typeError = FALSE;
8776
8777 if (uentry_isStructTag (old) || uentry_isUnionTag (old))
8778 {
8779 if (ctype_isSU (old->utype) && ctype_isSU (unew->utype))
8780 {
8781 if (mustConform)
8782 {
28bf4b0b 8783 DPRINTF (("Check struct conformance: %s / %s",
8784 uentry_unparseFull (old),
8785 uentry_unparseFull (unew)));
616915dd 8786 checkStructConformance (old, unew);
8787 }
8788 }
8789 else
8790 {
8791 if (!(ctype_isBogus (old->utype) || ctype_isBogus (unew->utype)))
8792 {
8793 llbug (message ("struct tags: bad types: %t / %t",
8794 old->utype, unew->utype));
8795 }
8796 }
8797 }
8798 else if (uentry_isEnumTag (old))
8799 {
8800 if (ctype_isEnum (old->utype) && ctype_isEnum (unew->utype))
8801 {
8802 if (mustConform) checkEnumConformance (old, unew);
8803 }
8804 else
8805 {
8806 if (!(ctype_isBogus (old->utype) || ctype_isBogus (unew->utype)))
8807 {
8808 llbug (message ("enum! bad type: %s / %s", ctype_unparse (old->utype),
8809 ctype_unparse (unew->utype)));
8810 }
8811 }
8812 }
8813 else if (!ctype_match (old->utype, unew->utype))
8814 {
28bf4b0b 8815 DPRINTF (("Type mismatch: %s / %s",
8816 ctype_unparse (old->utype),
8817 ctype_unparse (unew->utype)));
8818
616915dd 8819 if (cstring_equal (uentry_rawName (old), context_getBoolName ()))
8820 {
8821 ctype realt = ctype_realType (unew->utype);
8822
8823 if (ctype_isRealInt (realt) || ctype_isChar (realt))
8824 {
8825 unew->utype = ctype_bool;
8826 }
8827 else
8828 {
8829 if (mustConform)
8830 {
8831 typeError = optgenerror
8832 (FLG_INCONDEFS,
8833 message ("%q defined as %s", uentry_getName (old),
8834 ctype_unparse (realt)),
8835 uentry_whereDeclared (unew));
8836 }
8837 }
8838 }
8839 else
8840 {
8841 if (mustConform)
8842 {
8843 ctype oldr = ctype_realType (old->utype);
8844 ctype newr = ctype_realType (unew->utype);
8845
8846 if (ctype_isStruct (oldr) && ctype_isStruct (newr))
8847 {
8848 checkStructConformance (old, unew);
8849 }
8850 else if (ctype_isUnion (oldr) && ctype_isUnion (newr))
8851 {
8852 checkStructConformance (old, unew);
8853 }
8854 else if (ctype_isEnum (oldr) && ctype_isEnum (newr))
8855 {
8856 checkEnumConformance (old, unew);
8857 }
8858 else if (uentry_isConstant (old)
8859 && (ctype_isAbstract (oldr) && ctype_isEnum (newr)))
8860 {
8861 /* okay...for now! (should check the type is reset later... */
8862 }
8863 else
8864 {
8865 DPRINTF (("YABA!"));
8866 if (optgenerror
8867 (FLG_INCONDEFS,
8868 message ("%s %q %rdeclared with inconsistent type: %t",
8869 ekind_capName (unew->ukind),
8870 uentry_getName (unew),
8871 uentry_isDeclared (old),
8872 unew->utype),
8873 uentry_whereDeclared (unew)))
8874 {
8875 uentry_showWhereLast (old);
8876 typeError = TRUE;
8877 }
8878 }
8879 }
8880 }
8881 }
8882 else
8883 {
8884 /* no error */
8885 }
8886
8887 return typeError;
8888}
8889
8890static void
8891uentry_checkDatatypeConformance (/*@notnull@*/ uentry old,
8892 /*@notnull@*/ uentry unew,
8893 bool mustConform, bool completeConform)
8894{
8895 if (ctype_isDefined (unew->info->datatype->type))
8896 {
8897 /*
8898 ** bool is hard coded here, since it is built into LCL.
8899 ** For now, we're stuck with LCL's types.
8900 */
8901
8902 if (ctype_isDirectBool (old->utype) &&
8903 cstring_equalLit (unew->uname, "bool"))
8904 {
8905 /* if (!context_getFlag (FLG_ABSTRACTBOOL))
8906 evs 2000-07-25: removed
8907 */
8908 unew->utype = ctype_bool;
8909 }
8910
8911 if (ctype_isUnknown (old->info->datatype->type))
8912 {
8913 old->info->datatype->type = unew->info->datatype->type;
8914 }
8915 else
8916 {
8917 DPRINTF (("Old: %s / New: %s",
8918 uentry_unparseFull (old),
8919 uentry_unparseFull (unew)));
8920 DPRINTF (("Types: %s / %s",
8921 ctype_unparse (old->info->datatype->type),
8922 ctype_unparse (unew->info->datatype->type)));
8923
8924 if (ctype_matchDef (old->info->datatype->type,
8925 unew->info->datatype->type))
8926 {
8927 ;
8928 }
8929 else
8930 {
8931 if (optgenerror
8932 (FLG_INCONDEFS,
8933 message
8934 ("Type %q %s with inconsistent type: %t",
8935 uentry_getName (unew),
8936 uentry_reDefDecl (old, unew),
8937 unew->info->datatype->type),
8938 uentry_whereDeclared (unew)))
8939 {
8940 uentry_showWhereLastExtra
8941 (old, cstring_copy (ctype_unparse (old->info->datatype->type)));
8942 }
8943
8944 old->info->datatype->type = unew->info->datatype->type;
8945 }
8946 }
8947 }
8948
e5081f8c 8949 if (!qual_isUnknown (unew->info->datatype->abs))
616915dd 8950 {
e5081f8c 8951 if (qual_isConcrete (old->info->datatype->abs)
8952 && qual_isEitherAbstract (unew->info->datatype->abs))
616915dd 8953 {
8954 if (!ctype_isDirectBool (old->utype))
8955 {
8956 if (optgenerror
8957 (FLG_INCONDEFS,
8958 message
8959 ("Datatype %q inconsistently %rdeclared as abstract type",
8960 uentry_getName (unew),
8961 uentry_isDeclared (old)),
8962 uentry_whereDeclared (unew)))
8963 {
8964 uentry_showWhereLastPlain (old);
8965 }
8966 }
8967 }
e5081f8c 8968 else if (qual_isEitherAbstract (old->info->datatype->abs)
8969 && qual_isConcrete (unew->info->datatype->abs))
616915dd 8970 {
8971 if (!ctype_isDirectBool (old->utype))
8972 {
8973 if (optgenerror
8974 (FLG_INCONDEFS,
8975 message
8976 ("Datatype %q inconsistently %rdeclared as concrete type",
8977 uentry_getName (unew),
8978 uentry_isDeclared (old)),
8979 uentry_whereDeclared (unew)))
8980 {
8981 uentry_showWhereLastPlain (old);
8982 }
8983 }
8984 }
8985 else
8986 {
8987 ;
8988 }
8989 }
8990 else
8991 {
e5081f8c 8992 if (qual_isEitherAbstract (old->info->datatype->abs))
616915dd 8993 {
8994 old->sref = unew->sref;
8995 unew->info->datatype->mut = old->info->datatype->mut;
8996
8997 if (completeConform
8998 && uentry_isReallySpecified (old))
8999 {
9000 if (optgenerror
9001 (FLG_NEEDSPEC,
9002 message
9003 ("Datatype %q specified as abstract, "
9004 "but abstract annotation not used in declaration",
9005 uentry_getName (unew)),
9006 uentry_whereDeclared (unew)))
9007 {
9008 uentry_showWhereLastPlain (old);
9009 }
9010 }
9011 }
9012 }
9013
9014 unew->info->datatype->abs = old->info->datatype->abs;
9015
9016 if (ynm_isMaybe (unew->info->datatype->mut))
9017 {
9018 if (completeConform && ynm_isOff (old->info->datatype->mut)
9019 && uentry_isReallySpecified (old))
9020 {
9021 if (optgenerror
9022 (FLG_NEEDSPEC,
9023 message
9024 ("Datatype %q specified as immutable, "
9025 "but immutable annotation not used in declaration",
9026 uentry_getName (unew)),
9027 uentry_whereDeclared (unew)))
9028 {
9029 uentry_showWhereLastPlain (old);
9030 }
9031 }
9032
9033 unew->info->datatype->mut = old->info->datatype->mut;
9034 }
9035 else if (ynm_isMaybe (old->info->datatype->mut))
9036 {
9037 old->info->datatype->mut = unew->info->datatype->mut;
9038 }
9039 else
9040 {
e5081f8c 9041 if (qual_isEitherAbstract (old->info->datatype->abs))
616915dd 9042 {
9043 if (ynm_isOn (old->info->datatype->mut) && ynm_isOff (unew->info->datatype->mut))
9044 {
9045 if (optgenerror
9046 (FLG_INCONDEFS,
9047 message ("Datatype %q inconsistently %rdeclared as immutable",
9048 uentry_getName (unew),
9049 uentry_isDeclared (old)),
9050 uentry_whereDeclared (unew)))
9051 {
9052 uentry_showWhereLastPlain (old);
9053 }
9054 }
9055 else
9056 {
9057 if (ynm_isOff (old->info->datatype->mut)
9058 && ynm_isOn (unew->info->datatype->mut))
9059 {
9060 if (optgenerror
9061 (FLG_INCONDEFS,
9062 message ("Datatype %q inconsistently %rdeclared as mutable",
9063 uentry_getName (unew),
9064 uentry_isDeclared (old)),
9065 uentry_whereDeclared (unew)))
9066 {
9067 uentry_showWhereLastPlain (old);
9068 }
9069 }
9070 }
9071 }
9072 old->info->datatype->mut = unew->info->datatype->mut;
9073 }
9074
9075 uentry_checkStateConformance (old, unew, mustConform, completeConform);
9076}
9077
9078static void
9079uentry_checkConstantConformance (/*@notnull@*/ uentry old,
9080 /*@notnull@*/ uentry unew,
9081 bool mustConform,
9082 /*@unused@*/ bool completeConform)
9083{
b9904f57 9084 multiVal oldval = uentry_getConstantValue (old);
9085 multiVal newval = uentry_getConstantValue (unew);
616915dd 9086
b9904f57 9087 if (multiVal_isDefined (oldval))
616915dd 9088 {
b9904f57 9089 if (multiVal_isDefined (newval))
616915dd 9090 {
b9904f57 9091 if (!multiVal_equiv (oldval, newval))
616915dd 9092 {
9093 if (mustConform
9094 && optgenerror
9095 (FLG_INCONDEFS,
9096 message ("%s %q %rdeclared with inconsistent value: %q",
9097 ekind_capName (unew->ukind),
9098 uentry_getName (unew),
9099 uentry_isDeclared (old),
b9904f57 9100 multiVal_unparse (newval)),
616915dd 9101 uentry_whereDeclared (unew)))
9102 {
b9904f57 9103 uentry_showWhereLastExtra (old, multiVal_unparse (oldval));
616915dd 9104 }
9105 }
9106
b9904f57 9107 uentry_setConstantValue (unew, multiVal_copy (oldval));
616915dd 9108 }
9109 else
9110 {
9111 ;
9112 }
9113 }
9114 else
9115 {
b9904f57 9116 uentry_setConstantValue (old, multiVal_copy (newval));
616915dd 9117 }
9118}
9119
9120static void
9121uentry_checkConformance (/*@unique@*/ /*@notnull@*/ uentry old,
9122 /*@notnull@*/ uentry unew, bool mustConform,
9123 bool completeConform)
9124{
9125 bool typeError = FALSE;
9126 bool fcnConformance = FALSE;
9127
9128 if (!ekind_equal (unew->ukind, old->ukind))
9129 {
9130 /*
9131 ** okay, only if one is a function and the other is
9132 ** a variable of type function.
9133 */
9134
9135 if (unew->ukind == KENUMCONST
9136 && old->ukind == KCONST)
9137 {
9138 old->ukind = KENUMCONST;
9139 goto nokinderror;
9140 }
9141
9142 if (unew->ukind == KFCN
9143 && old->ukind == KCONST
9144 && ctype_isUnknown (old->utype))
9145 {
9146 /*
9147 ** When a function is defined with an unparam macro
9148 */
9149
efd360a3 9150 uentry_updateInto (old, unew);
616915dd 9151 return;
9152 }
9153
9154 if (uentry_isExpandedMacro (old)
9155 && uentry_isEitherConstant (unew))
9156 {
efd360a3 9157 uentry_updateInto (old, unew);
616915dd 9158 return;
9159 }
9160
9161 if (uentry_isEndIter (unew))
9162 {
9163 if (ctype_isUnknown (old->utype))
9164 {
9165 if (!uentry_isSpecified (old)
9166 && uentry_isCodeDefined (unew))
9167 {
9168 if (!fileloc_withinLines (uentry_whereDefined (old),
9169 uentry_whereDeclared (unew), 2))
9170 { /* bogus! will give errors if there is too much whitespace */
9171 voptgenerror
9172 (FLG_SYNTAX,
9173 message
9174 ("Iterator finalized name %q does not match name in "
9175 "previous iter declaration (should be end_%q). This iter "
9176 "is declared at %q",
9177 uentry_getName (unew),
9178 uentry_getName (old),
9179 fileloc_unparse (uentry_whereDefined (old))),
9180 uentry_whereDeclared (old));
9181 }
9182 }
9183
efd360a3 9184 uentry_updateInto (old, unew);
616915dd 9185 return;
9186 }
9187 else
9188 {
9189 KindConformanceError (old, unew, mustConform);
9190 }
9191 }
9192
9193 if (uentry_isFunction (unew))
9194 {
9195 if (uentry_isVariable (old))
9196 {
9197 if (!ctype_isUnknown (old->utype))
9198 {
9199 if (ctype_isFunction (old->utype))
9200 {
9201 uentry_makeVarFunction (old);
9202 checkFunctionConformance (old, unew, mustConform,
9203 completeConform);
9204 fcnConformance = TRUE;
9205 }
9206 else
9207 {
9208 KindConformanceError (old, unew, mustConform);
9209 }
9210 }
9211 else
9212 {
9213 if (uentry_isExpandedMacro (old))
9214 {
9215 if (fileloc_isUndefined (unew->whereDefined))
9216 {
9217 unew->whereDefined = fileloc_update (unew->whereDefined,
9218 old->whereDefined);
9219 }
9220
efd360a3 9221 uentry_updateInto (old, unew);
616915dd 9222 old->used = unew->used = TRUE;
9223 return;
9224 }
9225 else
9226 {
9227 /* undeclared identifier */
9228 old->utype = unew->utype;
9229 uentry_makeVarFunction (old);
9230 checkFunctionConformance (old, unew, FALSE, FALSE);
9231 fcnConformance = TRUE;
9232 }
9233 }
9234 }
9235 else
9236 {
9237 KindConformanceError (old, unew, mustConform);
9238 }
9239 }
9240 else if (uentry_isFunction (old) && uentry_isVariable (unew))
9241 {
9242 if (!ctype_isUnknown (unew->utype))
9243 {
9244 if (ctype_isFunction (unew->utype))
9245 {
9246 uentry_makeVarFunction (unew);
9247 checkFunctionConformance (old, unew, mustConform, completeConform);
9248 fcnConformance = TRUE;
9249 }
9250 else
9251 {
9252 KindConformanceError (old, unew, mustConform);
9253 }
9254 }
9255 else
9256 {
9257 KindConformanceError (old, unew, mustConform);
9258 }
9259 }
9260 else
9261 {
9262 KindConformanceError (old, unew, mustConform);
9263 }
9264 }
9265 else
9266 {
9267 /*
9268 ** check parameter lists for functions
9269 ** (before type errors, to get better messages
9270 */
9271
9272 if (uentry_isFunction (old))
9273 {
9274 checkFunctionConformance (old, unew, mustConform, completeConform);
9275 fcnConformance = TRUE;
9276 }
9277 else
9278 {
9279 if (!ctype_isUndefined (old->utype))
9280 {
9281 typeError = checkTypeConformance (old, unew, mustConform);
9282 }
9283 }
9284 }
9285
9286 nokinderror:
9287
9288 if (uentry_isEitherConstant (old) && uentry_isEitherConstant (unew))
9289 {
9290 uentry_checkConstantConformance (old, unew, mustConform, completeConform);
9291 }
9292
9293 if (uentry_isDatatype (old) && uentry_isDatatype (unew))
9294 {
9295 DPRINTF (("Check datatype: %s / %s",
9296 uentry_unparseFull (old),
9297 uentry_unparseFull (unew)));
9298
9299 uentry_checkDatatypeConformance (old, unew, mustConform, completeConform);
9300 }
9301
9302 if (uentry_isVariable (old) && uentry_isVariable (unew))
9303 {
9304 if (!typeError &&
9305 !ctype_matchDef (old->utype, unew->utype))
9306 {
9307 if (optgenerror
9308 (FLG_INCONDEFS,
9309 message
9310 ("Variable %q %s with inconsistent type (arrays and pointers are "
9311 "not identical in variable declarations): %t",
9312 uentry_getName (unew),
9313 uentry_reDefDecl (old, unew),
9314 unew->utype),
9315 uentry_whereDeclared (unew)))
9316 {
9317 uentry_showWhereLast (old);
9318
9319 /*
9320 ** Avoid repeated errors.
9321 */
9322
9323 if (uentry_isCodeDefined (old) && uentry_isCodeDefined (unew))
9324 {
9325 old->whereDefined = fileloc_update (old->whereDefined,
9326 fileloc_undefined);
9327 }
9328
9329 typeError = TRUE;
9330 }
9331 }
9332
9333 checkVarConformance (old, unew, mustConform, completeConform);
9334 }
9335
9336 if (fcnConformance)
9337 {
9338 /* old->utype = unew->utype; */
9339 }
9340 else
9341 {
9342 if (ctype_isConj (old->utype))
9343 {
9344 if (ctype_isConj (unew->utype))
9345 {
9346 if (!ctype_sameAltTypes (old->utype, unew->utype))
9347 {
9348 if (optgenerror
9349 (FLG_INCONDEFS,
9350 message ("%s %q inconsistently %rdeclared with "
9351 "alternate types %s "
9352 "(types match, but alternates are not identical, "
9353 "so checking may not be correct)",
9354 ekind_capName (uentry_getKind (old)),
9355 uentry_getName (unew),
9356 uentry_isDeclared (old),
9357 ctype_unparse (unew->utype)),
9358 uentry_whereDeclared (unew)))
9359 {
9360 uentry_showWhereLastVal (old, ctype_unparse (old->utype));
9361 }
9362 else
9363 {
9364 old->utype = unew->utype;
9365 }
9366 }
9367 }
9368 }
9369 else
9370 {
9371 if (ctype_isUnknown (old->utype))
9372 {
9373 old->utype = unew->utype;
9374 }
9375 }
9376 }
9377
9378 if (unew->ukind == old->ukind)
9379 {
9380 sfree (unew->info);
9381 unew->info = uinfo_copy (old->info, old->ukind);
9382 }
9383
9384 sRef_storeState (old->sref);
9385 sRef_storeState (unew->sref);
9386}
9387
ba45e1e4 9388static void uentry_mergeConstraints (uentry spec, uentry def)
9389{
9390 if (uentry_isFunction (def))
9391 {
9392 DPRINTF (("Here: %s / %s",
9393 uentry_unparseFull (spec),
9394 uentry_unparseFull (def)));
efd360a3 9395 /* evans 2001-07-21 */
9396 llassert (uentry_isFunction (spec));
ba45e1e4 9397
9398 if (functionConstraint_isDefined (def->info->fcn->preconditions))
9399 {
9400 if (fileloc_isXHFile (uentry_whereLast (def)))
9401 {
9402 llassert (uentry_isFunction (spec));
9403 spec->info->fcn->preconditions = functionConstraint_conjoin (spec->info->fcn->preconditions,
9404 def->info->fcn->preconditions);
ba45e1e4 9405 }
ccf0a4a8 9406 else if (fileloc_equal (uentry_whereLast (spec), uentry_whereLast (def)))
9407 {
9408 ;
9409 }
ba45e1e4 9410 else
9411 {
ccf0a4a8 9412 /* Check if the constraints are identical */
9413
3120b462 9414 if (optgenerror
9415 (FLG_INCONDEFS,
9416 message
9417 ("Preconditions for %q redeclared. Dropping previous precondition: %q",
9418 uentry_getName (spec),
9419 functionConstraint_unparse (spec->info->fcn->preconditions)),
9420 uentry_whereLast (def)))
9421 {
9422 uentry_showWhereSpecified (spec);
9423 }
9424
9425 functionConstraint_free (spec->info->fcn->preconditions);
9426 spec->info->fcn->preconditions = def->info->fcn->preconditions;
ba45e1e4 9427 }
3120b462 9428
9429 def->info->fcn->preconditions = functionConstraint_undefined;
ba45e1e4 9430 }
9431
ba45e1e4 9432 if (functionConstraint_isDefined (def->info->fcn->postconditions))
9433 {
9434 if (fileloc_isXHFile (uentry_whereLast (def)))
9435 {
9436 llassert (uentry_isFunction (spec));
9437 DPRINTF (("Post: %s /++/ %s",
9438 functionConstraint_unparse (spec->info->fcn->postconditions),
9439 functionConstraint_unparse (def->info->fcn->postconditions)));
9440 spec->info->fcn->postconditions = functionConstraint_conjoin (spec->info->fcn->postconditions,
9441 def->info->fcn->postconditions);
9442 def->info->fcn->postconditions = functionConstraint_undefined;
9443 DPRINTF (("Conjoined post: %s", functionConstraint_unparse (spec->info->fcn->postconditions)));
9444 }
9445 else
9446 {
3120b462 9447 if (optgenerror
9448 (FLG_INCONDEFS,
9449 message
9450 ("Postconditions for %q redeclared. Dropping previous postcondition: %q",
9451 uentry_getName (spec),
9452 functionConstraint_unparse (spec->info->fcn->postconditions)),
9453 uentry_whereLast (def)))
9454 {
9455 uentry_showWhereSpecified (spec);
9456 }
9457
9458 functionConstraint_free (spec->info->fcn->postconditions);
9459 spec->info->fcn->postconditions = def->info->fcn->postconditions;
9460 def->info->fcn->postconditions = functionConstraint_undefined;
ba45e1e4 9461 }
9462 }
9463 }
9464}
9465
616915dd 9466/*
9467** modifies spec to reflect def, reports any inconsistencies
9468*/
9469
9470void
9471uentry_mergeEntries (uentry spec, /*@only@*/ uentry def)
9472{
9473 llassert (uentry_isValid (spec));
9474 llassert (uentry_isValid (def));
9475 llassert (cstring_equal (spec->uname, def->uname));
efd360a3 9476
9477 if (uentry_isFunction (def))
9478 {
9479 if (uentry_isConstant (spec))
9480 {
9481 llassert (ctype_isUnknown (spec->utype) || ctype_isFunction (spec->utype));
9482 uentry_makeConstantFunction (spec);
9483 }
9484 else
9485 {
9486 uentry_convertVarFunction (spec);
9487 }
9488
9489 llassert (uentry_isFunction (spec));
9490 }
28bf4b0b 9491
6317f163 9492 DPRINTF (("Merge entries: %s / %s", uentry_unparseFull (spec),
28bf4b0b 9493 uentry_unparseFull (def)));
616915dd 9494
ba45e1e4 9495 uentry_mergeConstraints (spec, def);
9496
616915dd 9497 uentry_checkConformance (spec, def, TRUE,
9498 context_getFlag (FLG_NEEDSPEC));
9499
28bf4b0b 9500 DPRINTF (("Merge entries after conform: %s / %s",
9501 uentry_unparseFull (spec),
9502 uentry_unparseFull (def)));
9503
616915dd 9504 /* was: !(fileloc_isImport (uentry_whereSpecified (spec)))); */
9505
9506 /*
9507 ** okay, declarations conform. Propagate extra information.
9508 */
9509
9510 uentry_setDefined (spec, uentry_whereDefined (def));
9511 uentry_setDeclared (spec, uentry_whereDeclared (def));
9512
9513 if (uentry_isStatic (def))
9514 {
9515 if (optgenerror
9516 (FLG_INCONDEFS,
9517 message ("%s %q specified, but declared as static",
9518 ekind_capName (def->ukind),
9519 uentry_getName (def)),
9520 uentry_whereDeclared (def)))
9521 {
9522 uentry_showWhereSpecified (spec);
9523 }
9524 }
9525 else
9526 {
9527 spec->storageclass = def->storageclass;
9528 }
9529
9530 sRef_storeState (spec->sref);
9531
9532 spec->used = def->used || spec->used;
9533 spec->hasNameError |= def->hasNameError;
9534
9535 uentry_free (def);
9536
9537 if (!spec->hasNameError)
9538 {
9539 uentry_checkName (spec);
9540 }
9541 else
9542 {
9543 ;
9544 }
9545}
9546
9547/*
9548** Can't generate function redeclaration errors when the
9549** entries are merged, since we don't yet know if its the
9550** definition of the function.
9551*/
9552
9553void
9554uentry_clearDecl (void)
9555{
9556 posRedeclared = uentry_undefined;
9557 fileloc_free (posLoc);
9558 posLoc = fileloc_undefined;
9559}
9560
9561void
9562uentry_checkDecl (void)
9563{
f0171cff 9564 if (uentry_isValid (posRedeclared) && !fileloc_isXHFile (posLoc))
616915dd 9565 {
9566 llassert (fileloc_isDefined (posLoc));
9567
9568 if (uentry_isCodeDefined (posRedeclared))
9569 {
9570 if (optgenerror (FLG_REDECL,
9571 message ("%s %q declared after definition",
9572 ekind_capName (posRedeclared->ukind),
9573 uentry_getName (posRedeclared)),
9574 posLoc))
9575 {
9576 llgenindentmsg (message ("Definition of %q",
9577 uentry_getName (posRedeclared)),
9578 posRedeclared->whereDeclared);
9579 }
9580 }
9581 else
9582 {
9583 if (optgenerror (FLG_REDECL,
9584 message ("%s %q declared more than once",
9585 ekind_capName (posRedeclared->ukind),
9586 uentry_getName (posRedeclared)),
9587 posLoc))
9588 {
9589 llgenindentmsg (message ("Previous declaration of %q",
9590 uentry_getName (posRedeclared)),
9591 posRedeclared->whereDeclared);
9592 }
9593 }
9594 }
9595
9596 fileloc_free (posLoc);
9597 posLoc = fileloc_undefined;
9598 posRedeclared = uentry_undefined;
9599}
9600
9601/*
9602** Redefinition of old as unew.
9603** modifies old to reflect unew, reports any inconsistencies
9604*/
9605
9606void
9607uentry_mergeDefinition (uentry old, /*@only@*/ uentry unew)
9608{
d89a0c94 9609 fileloc olddef = uentry_whereDeclared (old);
616915dd 9610 fileloc unewdef = uentry_whereDeclared (unew);
9611 bool mustConform;
9612 bool wasForward;
28bf4b0b 9613
9614 DPRINTF (("uentry merge: %s / %s",
9615 uentry_unparseFull (old),
9616 uentry_unparseFull (unew)));
616915dd 9617
616915dd 9618 wasForward =
9619 fileloc_isUndefined (olddef)
efd360a3 9620 && fileloc_isDefined (uentry_whereDefined (old))
9621 && !uentry_isExpandedMacro (old);
616915dd 9622
9623 if (!context_getFlag (FLG_INCONDEFSLIB)
9624 && (fileloc_isLib (olddef) || fileloc_isImport (olddef)))
9625 {
9626 mustConform = FALSE;
9627 }
9628 else
9629 {
9630 mustConform = TRUE;
9631 }
9632
9633 llassert (uentry_isValid (old));
9634 llassert (uentry_isValid (unew));
9635 llassert (cstring_equal (old->uname, unew->uname));
9636
efd360a3 9637 if (uentry_isFunction (unew) && !uentry_isFunction (old))
9638 {
9639 if (uentry_isConstant (old))
9640 {
9641 llassert (ctype_isUnknown (old->utype) || ctype_isFunction (old->utype));
9642 uentry_makeConstantFunction (old);
9643 }
9644 else
9645 {
9646 uentry_convertVarFunction (old);
9647 }
9648
aec3dcdb 9649 if (!uentry_isFunction (old))
9650 {
9651 if (optgenerror
9652 (FLG_INCONDEFS,
9653 message ("%s %q declared as function, but previously declared as %s",
9654 ekind_capName (unew->ukind),
9655 uentry_getName (unew),
9656 ekind_unparseLong (old->ukind)),
9657 uentry_whereDeclared (unew)))
9658 {
9659 uentry_showWhereLast (old);
9660 }
9661
9662 uentry_convertIntoFunction (old);
9663 return;
9664 }
efd360a3 9665 }
9666
9667 DPRINTF (("uentry merge: %s / %s",
9668 uentry_unparseFull (old),
9669 uentry_unparseFull (unew)));
9670
9671 if (uentry_isExtern (unew))
9672 {
9673 uentry_setUsed (old, unewdef);
9674 }
9675
616915dd 9676 /*
9677 ** should check old one was extern!
9678 */
9679
9680 if (uentry_isStatic (old))
9681 {
9682 if (!(uentry_isStatic (unew)))
9683 {
9684 if (optgenerror
9685 (FLG_SHADOW,
9686 message ("%s %q shadows static declaration",
9687 ekind_capName (unew->ukind),
9688 uentry_getName (unew)),
9689 unewdef))
9690 {
9691 uentry_showWhereLast (old);
9692 }
9693 }
9694 else
9695 {
9696 uentry_setDeclDef (old, unewdef);
9697 }
9698 }
9699 else if (uentry_isStatic (unew))
9700 {
9701 uentry_setDeclDef (old, unewdef);
9702 }
9703 else if (uentry_isExtern (old))
9704 {
9705 uentry_setDeclared (old, unewdef);
9706 }
9707 else
9708 {
d89a0c94 9709 if (!uentry_isExtern (unew)
9710 && !uentry_isForward (old)
616915dd 9711 && !fileloc_equal (olddef, unewdef)
9712 && !fileloc_isUndefined (olddef)
9713 && !fileloc_isUndefined (unewdef)
9714 && !fileloc_isBuiltin (olddef)
9715 && !fileloc_isBuiltin (unewdef)
9716 && !uentry_isYield (old)
9717 && !(fileloc_isLib (olddef) || fileloc_isImport (olddef)))
9718 {
9719 if (uentry_isVariable (old) || uentry_isVariable (unew))
9720 {
9721 ; /* will report redeclaration error later */
9722 }
9723 else
9724 {
9725 if (fileloc_isDefined (uentry_whereDefined (old)))
9726 {
9727 if (optgenerror
9728 (FLG_REDEF,
9729 message ("%s %q defined more than once",
9730 ekind_capName (unew->ukind),
9731 uentry_getName (unew)),
9732 uentry_whereLast (unew)))
9733 {
9734 llgenindentmsg
9735 (message ("Previous definition of %q",
9736 uentry_getName (old)),
9737 uentry_whereLast (old));
9738 }
9739 /*
9740 if (uentry_isDatatype (old) || uentry_isAnyTag (old))
9741 {
efd360a3 9742 uentry_updateInto (old, unew);
616915dd 9743 old->sref = sRef_saveCopy (old->sref);
9744 }
9745 */
9746 }
9747 }
9748 }
9749 else
9750 {
9751 if (fileloc_isLib (olddef)
9752 || fileloc_isUndefined (olddef)
9753 || fileloc_isImport (olddef))
9754 {
9755 if (uentry_isExtern (unew))
9756 {
9757 if (uentry_isExtern (old)
9758 || (fileloc_isDefined (uentry_whereDeclared (old))
9759 && (!fileloc_equal (uentry_whereDeclared (old),
9760 uentry_whereDefined (old)))))
9761 {
9762 if (optgenerror
9763 (FLG_REDECL,
9764 message ("%s %q declared more than once",
9765 ekind_capName (unew->ukind),
9766 uentry_getName (unew)),
9767 unew->whereDeclared))
9768 {
9769 llgenindentmsg
9770 (message ("Previous declaration of %q",
9771 uentry_getName (old)),
9772 old->whereDeclared);
9773 }
9774 }
9775
9776 uentry_setExtern (old);
9777 }
9778 else
9779 {
d89a0c94 9780 uentry_setDeclared (old, unewdef); /* evans 2001-07-23 was setDefined */
616915dd 9781 }
9782 }
9783 }
9784 }
9785
efd360a3 9786 DPRINTF (("uentry merge: %s / %s",
9787 uentry_unparseFull (old),
9788 uentry_unparseFull (unew)));
ba45e1e4 9789
efd360a3 9790 uentry_mergeConstraints (old, unew);
d89a0c94 9791 DPRINTF (("uentry merge: %s / %s",
9792 uentry_unparseFull (old),
9793 uentry_unparseFull (unew)));
9794
616915dd 9795 uentry_checkConformance (old, unew, mustConform, FALSE);
d89a0c94 9796 DPRINTF (("uentry merge: %s / %s",
9797 uentry_unparseFull (old),
9798 uentry_unparseFull (unew)));
616915dd 9799
9800 old->used = old->used || unew->used;
9801 old->uses = filelocList_append (old->uses, unew->uses);
9802 unew->uses = filelocList_undefined;
9803
9804 sRef_storeState (old->sref);
9805 sRef_storeState (unew->sref);
9806
9807 if (wasForward)
9808 {
9809 old->whereDefined = fileloc_update (old->whereDefined,
9810 fileloc_undefined);
9811 }
9812
d89a0c94 9813 DPRINTF (("here: %s", uentry_unparseFull (old)));
9814
616915dd 9815 /*
9816 ** No redeclaration errors for functions here, since we
9817 ** don't know if this is the definition of the function.
9818 */
9819
9820 if (fileloc_isUser (old->whereDeclared)
9821 && fileloc_isUser (unew->whereDeclared)
9822 && !fileloc_equal (old->whereDeclared, unew->whereDeclared)
9823 && !fileloc_isDefined (unew->whereDefined))
9824 {
9825 if (uentry_isFunction (old))
9826 {
9827 /*@-temptrans@*/ posRedeclared = old; /*@=temptrans@*/
9828 posLoc = fileloc_update (posLoc, unew->whereDeclared);
9829 }
9830 else
9831 {
9832 if (optgenerror (FLG_REDECL,
9833 message ("%s %q declared more than once",
9834 ekind_capName (unew->ukind),
9835 uentry_getName (unew)),
9836 unew->whereDeclared))
9837 {
9838 llgenindentmsg (message ("Previous declaration of %q",
9839 uentry_getName (old)),
9840 old->whereDeclared);
9841 }
9842 }
9843 }
9844
9845 if (fileloc_isUndefined (old->whereDefined))
9846 {
9847 old->whereDefined = fileloc_update (old->whereDefined, unew->whereDefined);
9848 }
9849 else
9850 {
9851 if (!context_processingMacros ()
9852 && fileloc_isUser (old->whereDefined)
9853 && fileloc_isUser (unew->whereDefined)
9854 && !fileloc_equal (old->whereDefined, unew->whereDefined))
9855 {
9856 if (uentry_isVariable (unew) || uentry_isFunction (unew))
9857 {
9858 if (uentry_isVariable (unew)
9859 && uentry_isExtern (unew))
9860 {
9861 if (optgenerror (FLG_REDECL,
9862 message ("%s %q declared after definition",
9863 ekind_capName (unew->ukind),
9864 uentry_getName (unew)),
9865 unew->whereDeclared))
9866 {
9867 llgenindentmsg (message ("Definition of %q",
9868 uentry_getName (old)),
9869 old->whereDefined);
9870 }
9871 }
9872 else
9873 {
9874 if (optgenerror (FLG_REDEF,
9875 message ("%s %q redefined",
9876 ekind_capName (unew->ukind),
9877 uentry_getName (unew)),
9878 unew->whereDefined))
9879 {
9880 llgenindentmsg (message ("Previous definition of %q",
9881 uentry_getName (old)),
9882 old->whereDefined);
9883 }
9884 }
9885 }
9886 }
9887 }
9888
9889 if (uentry_isExternal (unew))
9890 {
9891 old->whereDefined = fileloc_createExternal ();
9892 }
9893
9894 if (unew->hasNameError)
9895 {
9896 old->hasNameError = TRUE;
9897 }
9898
9899 uentry_free (unew);
9900
9901 if (!old->hasNameError)
9902 {
9903 uentry_checkName (old);
9904 }
9905
d89a0c94 9906 DPRINTF (("After: %s", uentry_unparseFull (old)));
616915dd 9907 llassert (!ctype_isUndefined (old->utype));
9908}
9909
9910void
9911uentry_copyState (uentry res, uentry other)
9912{
9913 llassert (uentry_isValid (res));
9914 llassert (uentry_isValid (other));
9915
9916 res->used = other->used;
9917
9918 res->info->var->kind = other->info->var->kind;
9919 res->info->var->defstate = other->info->var->defstate;
9920 res->info->var->nullstate = other->info->var->nullstate;
9921 res->info->var->checked = other->info->var->checked;
9922
9923 sRef_copyState (res->sref, other->sref);
9924}
9925
9926bool
9927uentry_sameKind (uentry u1, uentry u2)
9928{
9929 if (uentry_isValid (u1) && uentry_isValid (u2))
9930 {
9931 if (uentry_isVar (u1) && uentry_isVar (u2))
9932 {
9933 ctype c1 = u1->utype;
9934 ctype c2 = u2->utype;
9935
9936 if (ctype_isUnknown (c1) || ctype_isUnknown (c2)) return FALSE;
9937
9938 /*
9939 ** both functions, or both not functions
9940 */
9941
9942 return (bool_equal (ctype_isFunction (c1), ctype_isFunction (c2)));
9943 }
9944 else
9945 {
9946 return ((u1->ukind == u2->ukind));
9947 }
9948 }
9949
9950 return FALSE;
9951}
9952
efd360a3 9953static void uentry_updateInto (/*@unique@*/ uentry unew, uentry old)
616915dd 9954{
abd7f895 9955 ekind okind;
616915dd 9956 llassert (uentry_isValid (unew));
9957 llassert (uentry_isValid (old));
9958
d89a0c94 9959 DPRINTF (("Update into: %s / %s", uentry_unparseFull (unew), uentry_unparseFull (old)));
abd7f895 9960 okind = unew->ukind;
616915dd 9961 unew->ukind = old->ukind;
efd360a3 9962 llassert (cstring_equal (unew->uname, old->uname));
616915dd 9963 unew->utype = old->utype;
9964
efd360a3 9965 if (fileloc_isDefined (unew->whereSpecified)
9966 && !fileloc_isDefined (old->whereSpecified))
9967 {
9968 ; /* Keep the old value */
9969 }
9970 else
9971 {
b73d1009 9972 fileloc_free (unew->whereSpecified);
efd360a3 9973 unew->whereSpecified = fileloc_copy (old->whereSpecified);
9974 }
9975
9976 if (fileloc_isDefined (unew->whereDefined)
9977 && !fileloc_isDefined (old->whereDefined))
9978 {
9979 ; /* Keep the old value */
9980 }
9981 else
9982 {
b73d1009 9983 fileloc_free (unew->whereDefined);
efd360a3 9984 unew->whereDefined = fileloc_copy (old->whereDefined);
9985 }
9986
9987 if (fileloc_isDefined (unew->whereDeclared)
9988 && !fileloc_isDefined (old->whereDeclared))
9989 {
9990 ; /* Keep the old value */
9991 }
9992 else
9993 {
b73d1009 9994 fileloc_free (unew->whereDeclared);
efd360a3 9995 unew->whereDeclared = fileloc_copy (old->whereDeclared);
9996 }
616915dd 9997
d89a0c94 9998 DPRINTF (("Update into: %s / %s", uentry_unparseFull (unew), uentry_unparseFull (old)));
9999
616915dd 10000 unew->sref = sRef_saveCopy (old->sref); /* Memory leak! */
10001 unew->used = old->used;
10002 unew->lset = FALSE;
10003 unew->isPrivate = old->isPrivate;
10004 unew->hasNameError = old->hasNameError;
efd360a3 10005 unew->uses = filelocList_append (unew->uses, old->uses);
10006 old->uses = filelocList_undefined;
616915dd 10007
10008 unew->storageclass = old->storageclass;
efd360a3 10009 uinfo_free (unew->info, okind);
616915dd 10010 unew->info = uinfo_copy (old->info, old->ukind);
10011}
10012
6fcd0b1e 10013static uentry
10014uentry_copyAux (uentry e, bool saveCopy)
616915dd 10015{
6fcd0b1e 10016
616915dd 10017 if (uentry_isValid (e))
10018 {
10019 uentry enew = uentry_alloc ();
10020 DPRINTF (("copy: %s", uentry_unparseFull (e)));
efd360a3 10021 enew->ukind = e->ukind;
10022 enew->uname = cstring_copy (e->uname);
10023 enew->utype = e->utype;
10024
10025 enew->whereSpecified = fileloc_copy (e->whereSpecified);
10026 enew->whereDefined = fileloc_copy (e->whereDefined);
10027 enew->whereDeclared = fileloc_copy (e->whereDeclared);
10028
6fcd0b1e 10029 if (saveCopy)
10030 {
10031 enew->sref = sRef_saveCopy (e->sref); /* Memory leak! */
10032 }
10033 else
10034 {
10035 enew->sref = sRef_copy (e->sref);
10036 }
10037
efd360a3 10038 enew->used = e->used;
10039 enew->lset = FALSE;
10040 enew->isPrivate = e->isPrivate;
10041 enew->hasNameError = e->hasNameError;
10042 enew->uses = filelocList_undefined;
10043
10044 enew->storageclass = e->storageclass;
10045 enew->info = uinfo_copy (e->info, e->ukind);
10046 enew->warn = warnClause_copy (e->warn);
10047
616915dd 10048 DPRINTF (("Here we are..."));
10049 DPRINTF (("original: %s", uentry_unparseFull (e)));
10050 DPRINTF (("copy: %s", uentry_unparse (enew)));
10051 DPRINTF (("copy: %s", uentry_unparseFull (enew)));
10052 return enew;
10053 }
10054 else
10055 {
10056 return uentry_undefined;
10057 }
10058}
10059
6fcd0b1e 10060uentry
10061uentry_copy (uentry e)
10062{
10063 return uentry_copyAux (e, TRUE);
10064}
10065
10066uentry
10067uentry_copyNoSave (uentry e)
10068{
10069 return uentry_copyAux (e, FALSE);
10070}
10071
616915dd 10072void
10073uentry_setState (uentry res, uentry other)
10074{
10075 llassert (uentry_isValid (res));
10076 llassert (uentry_isValid (other));
10077
10078 llassert (res->ukind == other->ukind);
10079 llassert (res->ukind == KVAR);
10080
10081 res->sref = sRef_saveCopy (other->sref);
10082 res->used = other->used;
10083 filelocList_free (res->uses);
10084 res->uses = other->uses;
10085 other->uses = filelocList_undefined;
10086 res->lset = other->lset;
10087}
10088
10089void
10090uentry_mergeUses (uentry res, uentry other)
10091{
10092 llassert (uentry_isValid (res));
10093 llassert (uentry_isValid (other));
10094
10095 res->used = other->used || res->used;
10096 res->lset = other->lset || res->lset;
10097 res->uses = filelocList_append (res->uses, other->uses);
10098 other->uses = filelocList_undefined;
10099}
10100
10101
10102/*
10103** This is a really ugly routine.
10104**
10105** gack...fix this one day.
10106*/
10107
10108/*
10109** flip == TRUE
10110** >> res is the false branch, other is the true branch (or continuation)
10111** flip == FALSE
10112** >> res is the true branch, other is the false branch (or continutation)
10113**
10114** opt == TRUE if,
10115**
10116** <other>
10117** if <res> ;
10118**
10119** References not effected by res are propagated from other.
10120*/
10121
10122static void
b87215ab 10123branchStateError (/*@notnull@*/ uentry res, /*@notnull@*/ uentry other,
10124 bool flip, clause cl, fileloc loc)
616915dd 10125{
10126 if (optgenerror
10127 (FLG_BRANCHSTATE,
10128 message ("%s %q is %s %s, but %s %s.",
10129 ekind_capName (res->ukind), uentry_getName (res),
10130 sRef_stateVerb (res->sref), clause_nameFlip (cl, flip),
10131 sRef_stateAltVerb (res->sref), clause_nameFlip (cl, !flip)),
10132 loc))
10133 {
16c024b5 10134 DPRINTF (("Here: %s / %s", sRef_unparseFull (res->sref), sRef_unparseFull (other->sref)));
10135
616915dd 10136 if (sRef_isDead (res->sref))
10137 {
16c024b5 10138 if (sRef_hasStateInfoLoc (res->sref)) {
10139 llgenindentmsg (message ("%s:", clause_nameFlip (cl, flip)), loc);
10140 sRef_showStateInfo (res->sref);
10141 }
10142
10143 if (sRef_hasStateInfoLoc (other->sref)) {
10144 llgenindentmsg (message ("%s:", clause_nameFlip (cl, !flip)), loc);
10145 sRef_showStateInfo (other->sref);
10146 }
616915dd 10147 }
10148 else if (sRef_isKept (res->sref))
10149 {
16c024b5 10150 if (sRef_hasAliasInfoLoc (res->sref)) {
10151 llgenindentmsg (message ("%s:", clause_nameFlip (cl, flip)), loc);
10152 sRef_showAliasInfo (res->sref);
10153 }
10154
10155 if (sRef_hasAliasInfoLoc (other->sref)) {
10156 llgenindentmsg (message ("%s:", clause_nameFlip (cl, !flip)), loc);
10157 sRef_showAliasInfo (other->sref);
10158 }
616915dd 10159 }
10160 else /* dependent */
10161 {
16c024b5 10162 if (sRef_hasAliasInfoLoc (res->sref)) {
10163 llgenindentmsg (message ("%s:", clause_nameFlip (cl, flip)), loc);
10164 sRef_showAliasInfo (res->sref);
10165 }
10166
10167 if (sRef_hasAliasInfoLoc (other->sref)) {
10168 llgenindentmsg (message ("%s:", clause_nameFlip (cl, !flip)), loc);
10169 sRef_showAliasInfo (other->sref);
10170 }
616915dd 10171 }
10172
10173 sRef_setAliasKind (res->sref, AK_ERROR, fileloc_undefined);
10174 }
10175}
10176
60868d40 10177static bool uentry_incompatibleMemoryStates (sRef rs, sRef os)
616915dd 10178{
10179 alkind rk = sRef_getAliasKind (rs);
10180 alkind ok = sRef_getAliasKind (os);
10181
10182 if (alkind_isError (rk) || alkind_isError (ok))
10183 {
10184 return FALSE;
10185 }
10186 else
10187 {
10188 return ((sRef_isDead (rs)
10189 || (alkind_isKept (rk) && !alkind_isKept (ok))
10190 || (alkind_isDependent (rk)
10191 && !alkind_isDependent (ok) && !alkind_isTemp (ok)))
10192 && (sRef_isAllocated (os) || sRef_isStateDefined (os)));
10193 }
10194}
10195
10196static void
10197 branchStateAltError (/*@notnull@*/ uentry res,
10198 /*@notnull@*/ uentry other, bool flip,
10199 clause cl, fileloc loc)
10200{
10201 if (optgenerror
10202 (FLG_BRANCHSTATE,
10203 message ("%s %q is %s %s, but %s %s.",
10204 ekind_capName (res->ukind), uentry_getName (res),
10205 sRef_stateVerb (other->sref), clause_nameFlip (cl, flip),
10206 sRef_stateAltVerb (other->sref), clause_nameFlip (cl, !flip)),
10207 loc))
10208 {
10209 if (sRef_isDead (other->sref))
10210 {
16c024b5 10211 if (sRef_hasStateInfoLoc (other->sref)) {
10212 llgenindentmsg (message ("%s:", clause_nameFlip (cl, flip)), loc);
10213 sRef_showStateInfo (other->sref);
10214 }
10215
10216 if (sRef_hasStateInfoLoc (res->sref)) {
10217 llgenindentmsg (message ("%s:", clause_nameFlip (cl, !flip)), loc);
10218 sRef_showStateInfo (res->sref);
10219 }
616915dd 10220 }
10221 else /* kept */
10222 {
16c024b5 10223 if (sRef_hasAliasInfoLoc (other->sref)) {
10224 llgenindentmsg (message ("%s:", clause_nameFlip (cl, flip)), loc);
10225 sRef_showAliasInfo (other->sref);
10226 }
10227
10228 if (sRef_hasAliasInfoLoc (res->sref)) {
10229 llgenindentmsg (message ("%s:", clause_nameFlip (cl, !flip)), loc);
10230 sRef_showAliasInfo (res->sref);
10231 }
616915dd 10232 }
10233
10234 sRef_setAliasKind (res->sref, AK_ERROR, fileloc_undefined);
10235 sRef_setDefinedComplete (res->sref, fileloc_undefined);
10236
10237 sRef_setAliasKind (other->sref, AK_ERROR, fileloc_undefined);
10238 sRef_setDefinedComplete (other->sref, fileloc_undefined);
10239 }
10240}
10241
28bf4b0b 10242/*
10243** A reference is relevant for certain checks, only if it
10244** is not definitely null on this path (but not declared
10245** to always be null.)
10246*/
10247
10248static bool uentry_relevantReference (sRef sr, bool flip)
616915dd 10249{
28bf4b0b 10250 if (sRef_isKept (sr) || sRef_isDependent (sr))
10251 {
10252 return FALSE;
10253 }
10254 else
10255 {
10256 if (flip)
10257 {
10258 return !sRef_definitelyNullContext (sr);
10259 }
10260 else
10261 {
10262 return !sRef_definitelyNullAltContext (sr);
10263 }
10264 }
616915dd 10265}
616915dd 10266
28bf4b0b 10267static void
abd7f895 10268uentry_mergeAliasStates (/*@notnull@*/ uentry res, /*@notnull@*/ uentry other,
10269 fileloc loc, bool mustReturn, bool flip, bool opt,
28bf4b0b 10270 clause cl)
10271{
60868d40 10272 sRef rs = res->sref;
10273 sRef os = other->sref;
10274
28bf4b0b 10275 DPRINTF (("Merge alias states: %s / %s",
10276 uentry_unparseFull (res),
10277 uentry_unparseFull (other)));
616915dd 10278
60868d40 10279 if (sRef_isValid (rs))
616915dd 10280 {
10281 if (!mustReturn)
10282 {
60868d40 10283 if (uentry_incompatibleMemoryStates (rs, os))
616915dd 10284 {
60868d40 10285 DPRINTF (("Incompatible: \n\t%s / \n\t%s",
10286 sRef_unparseFull (rs), sRef_unparseFull (os)));
28bf4b0b 10287
60868d40 10288 if (sRef_isThroughArrayFetch (rs)
616915dd 10289 && !context_getFlag (FLG_STRICTBRANCHSTATE))
10290 {
60868d40 10291 if (sRef_isKept (rs) || sRef_isKept (os))
616915dd 10292 {
60868d40 10293 sRef_maybeKill (rs, loc);
616915dd 10294 }
60868d40 10295 else if (sRef_isPossiblyDead (os))
616915dd 10296 {
60868d40 10297 sRef_maybeKill (rs, loc);
616915dd 10298 }
10299 else
10300 {
10301 ;
10302 }
10303 }
10304 else
10305 {
60868d40 10306 if (uentry_relevantReference (os, flip))
616915dd 10307 {
60868d40 10308 if (sRef_isLocalParamVar (rs)
10309 && (sRef_isLocalState (os)
10310 || sRef_isDependent (os)))
616915dd 10311 {
60868d40 10312 if (sRef_isDependent (rs))
616915dd 10313 {
60868d40 10314 sRef_setDependent (os, loc);
616915dd 10315 }
10316 else
10317 {
60868d40 10318 sRef_setDefState (rs, SS_UNUSEABLE, loc);
616915dd 10319 }
10320 }
10321 else
10322 {
16c024b5 10323 branchStateError (res, other, !flip, cl, loc); /* evans 2002-12-15: changed flip to !flip */
616915dd 10324 }
10325 }
10326 }
10327
60868d40 10328 if (sRef_isKept (rs))
616915dd 10329 {
60868d40 10330 DPRINTF (("Setting kept: %s", sRef_unparseFull (os)));
10331 sRef_setKept (os, loc);
616915dd 10332 }
10333 }
10334 else
10335 {
60868d40 10336 if (uentry_incompatibleMemoryStates (os, rs))
616915dd 10337 {
60868d40 10338 if (uentry_relevantReference (rs, !flip))
616915dd 10339 {
60868d40 10340 if (sRef_isLocalParamVar (rs)
10341 && (sRef_isDependent (rs)
10342 || sRef_isLocalState (rs)))
616915dd 10343 {
60868d40 10344 if (sRef_isDependent (os))
616915dd 10345 {
60868d40 10346 sRef_setDependent (rs, loc);
616915dd 10347 }
10348 else
10349 {
60868d40 10350 sRef_setDefState (rs, SS_UNUSEABLE, loc);
616915dd 10351 }
10352 }
10353 else
10354 {
60868d40 10355 if (sRef_isParam (os))
616915dd 10356 {
10357 /*
10358 ** If the local variable associated
10359 ** with the param has the correct state,
10360 ** its okay.
10361 ** (e.g., free (s); s = new(); ...
10362 */
28bf4b0b 10363
616915dd 10364 uentry uvar = usymtab_lookupSafe (other->uname);
28bf4b0b 10365
616915dd 10366 if (uentry_isValid (uvar)
60868d40 10367 && ((sRef_isDead (os)
616915dd 10368 && sRef_isOnly (uvar->sref))
60868d40 10369 || (sRef_isDependent (os)
616915dd 10370 && sRef_isOwned (uvar->sref))))
10371 {
10372 /* no error */
10373 }
10374 else
10375 {
10376 branchStateAltError (res, other,
10377 flip, cl, loc);
10378 }
10379 }
10380 else
10381 {
28bf4b0b 10382 DPRINTF (("Here: %s / %s",
10383 uentry_unparseFull (res),
10384 uentry_unparseFull (other)));
10385
616915dd 10386 branchStateAltError (res, other,
10387 flip, cl, loc);
10388 }
10389 }
10390 }
10391 }
28bf4b0b 10392
60868d40 10393 if (sRef_isKept (os))
616915dd 10394 {
60868d40 10395 sRef_setKept (rs, loc);
616915dd 10396 }
10397 }
10398
10399 if (opt)
10400 {
10401 DPRINTF (("Merge opt..."));
60868d40 10402 sRef_mergeOptState (rs, os, cl, loc);
616915dd 10403 DPRINTF (("Done!"));
10404 }
10405 else
10406 {
60868d40 10407 DPRINTF (("Merging states: \n\t%s / \n\t%s", sRef_unparseFull (rs), sRef_unparseFull (os)));
10408 sRef_mergeState (rs, os, cl, loc);
10409 DPRINTF (("After merging : \n\t%s / \n\t%s", sRef_unparseFull (rs), sRef_unparseFull (os)));
616915dd 10410 }
10411 }
10412 else
10413 {
60868d40 10414 if (sRef_isModified (os))
616915dd 10415 {
60868d40 10416 sRef_setModified (rs);
616915dd 10417 }
10418 }
28bf4b0b 10419 }
60868d40 10420
10421 DPRINTF (("After merge: %s", sRef_unparseFull (res->sref)));
28bf4b0b 10422}
616915dd 10423
28bf4b0b 10424static void
abd7f895 10425uentry_mergeValueStates (/*@notnull@*/ uentry res, /*@notnull@*/ uentry other,
10426 fileloc loc, bool mustReturn, /*@unused@*/ bool flip)
28bf4b0b 10427{
10428 valueTable rvalues;
10429 valueTable ovalues;
10430
10431 DPRINTF (("Merge values: %s / %s", sRef_unparseFull (res->sref), sRef_unparseFull (other->sref)));
10432
b7e84605 10433 if (mustReturn)
10434 {
10435 return;
10436 }
10437 /* flip? */
10438
28bf4b0b 10439 rvalues = sRef_getValueTable (res->sref);
10440 ovalues = sRef_getValueTable (other->sref);
10441
10442 if (valueTable_isUndefined (ovalues))
10443 {
10444 DPRINTF (("No value table: %s", sRef_unparseFull (other->sref)));
10445 ;
10446 }
10447 else if (valueTable_isUndefined (rvalues))
10448 {
10449 /*
10450 ** Copy values from other
10451 */
10452
517a2db3 10453 /* ??? */
28bf4b0b 10454 }
10455 else
10456 {
10457 valueTable_elements (ovalues, fkey, fval) {
10458 stateValue tval;
10459 metaStateInfo minfo;
10460 stateCombinationTable sctable;
10461 cstring msg;
10462 int nval;
10463
10464 tval = valueTable_lookup (rvalues, fkey);
10465
10466 DPRINTF (("Merge value: %s / %s X %s", fkey,
10467 stateValue_unparse (fval), stateValue_unparse (tval)));
10468
10469 minfo = context_lookupMetaStateInfo (fkey);
10470 llassert (stateValue_isDefined (tval));
10471
10472 if (metaStateInfo_isUndefined (minfo) || !stateValue_isDefined (tval))
10473 {
10474 DPRINTF (("Cannot find meta state for: %s", fkey));
10475 BADBRANCH;
10476 }
10477 else
10478 {
10479 llassert (metaStateInfo_isDefined (minfo));
10480
10481 if (stateValue_isError (fval)
10482 || sRef_definitelyNullContext (res->sref))
10483 {
10484 sRef_setMetaStateValueComplete (res->sref,
10485 fkey, stateValue_getValue (fval),
b7e84605 10486 stateValue_getLoc (fval));
28bf4b0b 10487 DPRINTF (("Setting res: %s", sRef_unparseFull (res->sref)));
10488 }
10489 else if (stateValue_isError (tval)
10490 || sRef_definitelyNullAltContext (other->sref))
10491 {
10492 DPRINTF (("Other branch is definitely null!"));
10493 }
b7e84605 10494 else if (sRef_isStateUndefined (res->sref)
10495 || sRef_isDead (res->sref))
10496 {
10497 ; /* Combination state doesn't matter if it is undefined or dead */
10498 }
28bf4b0b 10499 else
10500 {
10501 DPRINTF (("Check: %s / %s / %s / %s", fkey,
10502 metaStateInfo_unparse (minfo),
10503 stateValue_unparse (fval),
10504 stateValue_unparse (tval)));
10505
10506 DPRINTF (("state values: %d / %d",
10507 stateValue_getValue (fval), stateValue_getValue (tval)));
10508
10509 sctable = metaStateInfo_getMergeTable (minfo);
10510
10511 DPRINTF (("Merge table: %s",
10512 stateCombinationTable_unparse (sctable)));
10513
10514 msg = cstring_undefined;
10515
10516 nval = stateCombinationTable_lookup (sctable,
10517 stateValue_getValue (fval),
10518 stateValue_getValue (tval),
10519 &msg);
10520
10521 DPRINTF (("nval: %d / %d / %d", nval,
10522 stateValue_getValue (fval), stateValue_getValue (tval)));
10523
b7e84605 10524 if (nval == stateValue_error)
28bf4b0b 10525 {
28bf4b0b 10526 if (uentry_isGlobalMarker (res))
10527 {
10528 if (optgenerror
10529 (FLG_STATEMERGE,
10530 message
b7e84605 10531 ("Control branches merge with incompatible global states (%s and %s)%q",
28bf4b0b 10532 metaStateInfo_unparseValue (minfo, stateValue_getValue (fval)),
10533 metaStateInfo_unparseValue (minfo, stateValue_getValue (tval)),
b7e84605 10534 cstring_isDefined (msg)
10535 ? message (": %s", msg) : cstring_undefined),
28bf4b0b 10536 loc))
10537 {
10538 sRef_showMetaStateInfo (res->sref, fkey);
10539 sRef_showMetaStateInfo (other->sref, fkey);
10540 }
10541 }
10542 else
10543 {
10544 if (optgenerror
10545 (FLG_STATEMERGE,
10546 message
b7e84605 10547 ("Control branches merge with incompatible states for %q (%s and %s)%q",
28bf4b0b 10548 uentry_getName (res),
10549 metaStateInfo_unparseValue (minfo, stateValue_getValue (fval)),
10550 metaStateInfo_unparseValue (minfo, stateValue_getValue (tval)),
b7e84605 10551 cstring_isDefined (msg)
10552 ? message (": %s", msg) : cstring_undefined),
28bf4b0b 10553 loc))
10554 {
10555 sRef_showMetaStateInfo (res->sref, fkey);
10556 sRef_showMetaStateInfo (other->sref, fkey);
10557 DPRINTF (("Res: %s", sRef_unparseFull (res->sref)));
10558 DPRINTF (("Other: %s", sRef_unparseFull (other->sref)));
10559 DPRINTF (("Null: %s / %s",
10560 bool_unparse (usymtab_isDefinitelyNull (res->sref)),
10561 bool_unparse (usymtab_isDefinitelyNull (other->sref))));
10562
10563 }
10564 }
10565 }
10566
10567 if (nval == stateValue_getValue (fval)
10568 && nval != stateValue_getValue (tval))
10569 {
10570 loc = stateValue_getLoc (fval);
10571 }
10572 else if (nval == stateValue_getValue (tval)
10573 && nval != stateValue_getValue (fval))
10574 {
10575 loc = stateValue_getLoc (tval);
10576 }
10577 else
10578 {
10579 ;
10580 }
10581
10582 if (stateValue_getValue (sRef_getMetaStateValue (res->sref, fkey)) == nval
10583 && nval == stateValue_getValue (fval)
10584 && nval == stateValue_getValue (tval))
10585 {
10586 ;
10587 }
10588 else
10589 {
10590 sRef_setMetaStateValueComplete (res->sref, fkey, nval, loc);
10591 }
10592 }
10593 }
10594 } end_valueTable_elements ;
10595 }
10596}
10597
10598
10599static void
abd7f895 10600uentry_mergeSetStates (/*@notnull@*/ uentry res,
10601 /*@notnull@*/ uentry other, /*@unused@*/ fileloc loc,
28bf4b0b 10602 bool flip, clause cl)
10603{
10604 if (cl == DOWHILECLAUSE)
10605 {
10606 res->used = other->used || res->used;
10607 res->lset = other->lset || res->lset;
10608 res->uses = filelocList_append (res->uses, other->uses);
10609 other->uses = filelocList_undefined;
10610 }
10611 else
10612 {
10613 if (sRef_isMacroParamRef (res->sref)
10614 && !uentry_isSefParam (other)
10615 && !uentry_isSefParam (res))
616915dd 10616 {
28bf4b0b 10617 bool hasError = FALSE;
10618
10619 if (bool_equal (res->used, other->used))
616915dd 10620 {
28bf4b0b 10621 res->used = other->used;
10622 }
10623 else
10624 {
10625 if (other->used && !flip)
616915dd 10626 {
28bf4b0b 10627 hasError =
10628 optgenerror
10629 (FLG_MACROPARAMS,
10630 message ("Macro parameter %q used in true clause, "
10631 "but not in false clause",
10632 uentry_getName (res)),
10633 uentry_whereDeclared (res));
616915dd 10634 }
10635 else
28bf4b0b 10636 {
10637 hasError =
10638 optgenerror
10639 (FLG_MACROPARAMS,
10640 message ("Macro parameter %q used in false clause, "
10641 "but not in true clause",
10642 uentry_getName (res)),
10643 uentry_whereDeclared (res));
10644 }
10645 res->used = TRUE;
10646
10647 if (hasError)
616915dd 10648 {
28bf4b0b 10649 /* make it sef now, prevent more errors */
10650 res->info->var->kind = VKREFSEFPARAM;
616915dd 10651 }
10652 }
28bf4b0b 10653 }
10654 else
10655 {
10656 res->used = other->used || res->used;
10657 res->lset = other->lset || res->lset;
10658 res->uses = filelocList_append (res->uses, other->uses);
10659 other->uses = filelocList_undefined;
616915dd 10660 }
10661 }
10662}
10663
28bf4b0b 10664void
10665uentry_mergeState (uentry res, uentry other, fileloc loc,
10666 bool mustReturn, bool flip, bool opt,
10667 clause cl)
10668{
10669 llassert (uentry_isValid (res));
10670 llassert (uentry_isValid (other));
10671
10672 llassert (res->ukind == other->ukind);
10673 llassert (res->ukind == KVAR);
10674
10675 DPRINTF (("Merge state: %s / %s", uentry_unparseFull (res),
10676 uentry_unparseFull (other)));
10677
10678 uentry_mergeAliasStates (res, other, loc, mustReturn, flip, opt, cl);
b7e84605 10679 uentry_mergeValueStates (res, other, loc, mustReturn, flip);
28bf4b0b 10680 uentry_mergeSetStates (res, other, loc, flip, cl);
3e3ec469 10681
10682 DPRINTF (("Merge ==> %s", uentry_unparseFull (res)));
28bf4b0b 10683}
10684
616915dd 10685void uentry_setUsed (uentry e, fileloc loc)
10686{
10687 static bool firstTime = TRUE;
10688 static bool showUses = FALSE;
10689 static bool exportLocal = FALSE;
10690
28bf4b0b 10691 DPRINTF (("Used: %s / %s", uentry_unparse (e), fileloc_unparse (loc)));
10692
616915dd 10693 if (firstTime)
10694 {
10695 /* need to track uses is FLG_SHOWUSES or FLG_EXPORTLOCAL is true */
10696
10697 showUses = context_getFlag (FLG_SHOWUSES);
10698 exportLocal = context_maybeSet (FLG_EXPORTLOCAL);
10699
10700 firstTime = FALSE;
10701 }
10702
10703 if (uentry_isValid (e))
10704 {
28bf4b0b 10705 if (warnClause_isDefined (e->warn))
10706 {
10707 flagSpec flg = warnClause_getFlag (e->warn);
10708 cstring msg;
10709
10710 if (warnClause_hasMessage (e->warn))
10711 {
10712 msg = cstring_copy (warnClause_getMessage (e->warn));
10713 }
10714 else
10715 {
10716 msg = message ("Use of possibly dangerous %s",
10717 uentry_ekindNameLC (e));
10718 }
10719
10720 vfsgenerror (flg,
10721 message ("%q: %q", msg, uentry_getName (e)),
10722 loc);
10723 }
10724
616915dd 10725 if (sRef_isMacroParamRef (e->sref))
10726 {
10727 if (uentry_isYield (e) || uentry_isSefParam (e))
10728 {
10729 ;
10730 }
10731 else
10732 {
10733 if (context_inConditional ())
10734 {
10735 if (optgenerror
10736 (FLG_MACROPARAMS,
10737 message ("Macro parameter %q used in conditionally "
10738 "executed code (may or may not be "
10739 "evaluated exactly once)",
10740 uentry_getName (e)),
10741 loc))
10742 {
10743 e->info->var->kind = VKREFSEFPARAM;
10744 }
10745 }
10746 else
10747 {
10748 if ((e)->used)
10749 {
10750 if (optgenerror
10751 (FLG_MACROPARAMS,
10752 message ("Macro parameter %q used more than once",
10753 uentry_getName (e)),
10754 uentry_whereDeclared (e)))
10755 {
10756 e->info->var->kind = VKREFSEFPARAM;
10757 }
10758 }
10759 }
10760 }
10761 }
10762
b73d1009 10763 if (usymId_isValid (usymtab_directParamNo (e)))
616915dd 10764 {
b73d1009 10765 uentry_setUsed (usymtab_getParam (usymId_toInt (usymtab_directParamNo (e))), loc);
616915dd 10766 }
10767
10768 e->used = TRUE;
28bf4b0b 10769
616915dd 10770 if (!sRef_isLocalVar (e->sref))
10771 {
10772 if (showUses)
10773 {
10774 e->uses = filelocList_add (e->uses, fileloc_copy (loc));
10775 }
10776 else
10777 {
10778 if (exportLocal)
10779 {
10780 if (context_inMacro ())
10781 {
10782 e->uses = filelocList_addUndefined (e->uses);
10783 }
10784 else
10785 {
10786 e->uses = filelocList_addDifferentFile
10787 (e->uses,
10788 uentry_whereDeclared (e),
10789 loc);
10790 }
10791 }
10792 }
10793 }
10794 }
10795}
10796
10797bool uentry_isReturned (uentry u)
10798{
10799 return (uentry_isValid (u) && uentry_isVar (u)
10800 && (u->info->var->kind == VKRETPARAM
10801 || u->info->var->kind == VKSEFRETPARAM));
10802}
10803
6fcd0b1e 10804/*@exposed@*/ sRef uentry_returnedRef (uentry u, exprNodeList args, fileloc loc)
616915dd 10805{
10806 llassert (uentry_isRealFunction (u));
10807
28bf4b0b 10808 if (ctype_isFunction (u->utype) && sRef_isStateSpecial (uentry_getSref (u)))
616915dd 10809 {
28bf4b0b 10810 stateClauseList clauses = uentry_getStateClauseList (u);
10811 sRef res = sRef_makeNew (ctype_getReturnType (u->utype), u->sref, u->uname);
616915dd 10812
28bf4b0b 10813 DPRINTF (("Returned: %s", sRef_unparseFull (res)));
6fcd0b1e 10814 sRef_setAllocated (res, loc);
616915dd 10815
28bf4b0b 10816 DPRINTF (("ensures clause: %s / %s", uentry_unparse (u),
10817 stateClauseList_unparse (clauses)));
616915dd 10818
ccf0a4a8 10819 /*
10820 ** This should be in exprNode_reflectEnsuresClause
10821 */
10822
28bf4b0b 10823 stateClauseList_postElements (clauses, cl)
10824 {
10825 if (!stateClause_isGlobal (cl))
616915dd 10826 {
28bf4b0b 10827 sRefSet refs = stateClause_getRefs (cl);
10828 sRefMod modf = stateClause_getEffectFunction (cl);
10829
10830 sRefSet_elements (refs, el)
616915dd 10831 {
28bf4b0b 10832 sRef base = sRef_getRootBase (el);
10833
10834 if (sRef_isResult (base))
616915dd 10835 {
28bf4b0b 10836 if (modf != NULL)
10837 {
10838 sRef sr = sRef_fixBase (el, res);
6fcd0b1e 10839 modf (sr, loc);
28bf4b0b 10840 }
616915dd 10841 }
28bf4b0b 10842 else
10843 {
10844 ;
10845 }
10846 } end_sRefSet_elements ;
10847 }
10848 } end_stateClauseList_postElements ;
ccf0a4a8 10849
616915dd 10850 return res;
10851 }
10852 else
10853 {
10854 uentryList params;
10855 alkind ak;
10856 sRefSet prefs = sRefSet_new ();
10857 sRef res = sRef_undefined;
10858 int paramno = 0;
10859
10860 params = uentry_getParams (u);
10861
10862 uentryList_elements (params, current)
10863 {
10864 if (uentry_isReturned (current))
10865 {
10866 if (exprNodeList_size (args) >= paramno)
10867 {
10868 exprNode ecur = exprNodeList_nth (args, paramno);
10869 sRef tref = exprNode_getSref (ecur);
10870
28bf4b0b 10871 DPRINTF (("Returned reference: %s", sRef_unparseFull (tref)));
10872
616915dd 10873 if (sRef_isValid (tref))
10874 {
10875 sRef tcref = sRef_copy (tref);
10876
28bf4b0b 10877 usymtab_addForceMustAlias (tcref, tref); /* evans 2001-05-27 */
10878
6fcd0b1e 10879 if (sRef_isNew (tcref))
10880 {
10881 /* tcref->kind = SK_OBJECT; */ /*!! Not new anymore */
10882 }
10883
616915dd 10884 if (sRef_isDead (tcref))
10885 {
6fcd0b1e 10886 sRef_setDefined (tcref, loc);
10887 sRef_setOnly (tcref, loc);
616915dd 10888 }
10889
10890 if (sRef_isRefCounted (tcref))
10891 {
10892 /* could be a new ref now (but only if its returned) */
6fcd0b1e 10893 sRef_setAliasKindComplete (tcref, AK_ERROR, loc);
616915dd 10894 }
10895
10896 sRef_makeSafe (tcref);
6fcd0b1e 10897 DPRINTF (("Returns tcref / %s", sRef_unparseFull (tcref)));
616915dd 10898 prefs = sRefSet_insert (prefs, tcref);
10899 }
10900 }
10901 }
10902
10903 paramno++;
10904 } end_uentryList_elements ;
10905
10906 if (sRefSet_size (prefs) > 0)
10907 {
10908 nstate n = sRef_getNullState (u->sref);
10909
10910 if (sRefSet_size (prefs) == 1)
10911 {
10912 res = sRefSet_choose (prefs);
10913 }
10914 else
10915 {
b73d1009 10916 /* should this ever happen? */
616915dd 10917 res = sRefSet_mergeIntoOne (prefs);
10918 }
10919
10920 if (nstate_isKnown (n))
10921 {
6fcd0b1e 10922 sRef_setNullState (res, n, loc);
616915dd 10923 }
10924 }
10925 else
10926 {
10927 if (ctype_isFunction (u->utype))
10928 {
28bf4b0b 10929 DPRINTF (("Making new from %s -->", uentry_unparseFull (u)));
10930 res = sRef_makeNew (ctype_getReturnType (u->utype), u->sref, u->uname);
616915dd 10931 }
10932 else
10933 {
10934 res = sRef_makeNew (ctype_unknown, u->sref, u->uname);
10935 }
10936
10937 if (sRef_isRefCounted (res))
10938 {
6fcd0b1e 10939 sRef_setAliasKind (res, AK_NEWREF, loc);
616915dd 10940 }
10941 }
10942
28bf4b0b 10943
616915dd 10944 if (sRef_getNullState (res) == NS_ABSNULL)
10945 {
10946 ctype ct = ctype_realType (u->utype);
10947
10948 if (ctype_isAbstract (ct))
10949 {
6fcd0b1e 10950 sRef_setNotNull (res, loc);
616915dd 10951 }
10952 else
10953 {
10954 if (ctype_isUser (ct))
10955 {
10956 sRef_setStateFromUentry (res, usymtab_getTypeEntry (ctype_typeId (ct)));
10957 }
10958 else
10959 {
6fcd0b1e 10960 sRef_setNotNull (res, loc);
616915dd 10961 }
10962 }
10963 }
10964
10965 if (sRef_isRefCounted (res))
10966 {
6fcd0b1e 10967 sRef_setAliasKind (res, AK_NEWREF, loc);
616915dd 10968 }
10969 else if (sRef_isKillRef (res))
10970 {
6fcd0b1e 10971 sRef_setAliasKind (res, AK_REFCOUNTED, loc);
616915dd 10972 }
10973 else
10974 {
10975 ;
10976 }
10977
10978 ak = sRef_getAliasKind (res);
10979
10980 if (alkind_isImplicit (ak))
10981 {
10982 sRef_setAliasKind (res,
10983 alkind_fixImplicit (ak),
6fcd0b1e 10984 loc);
616915dd 10985 }
10986
10987 sRefSet_free (prefs);
6fcd0b1e 10988
10989 /*
10990 if (sRef_isOnly (res))
10991 {
10992 sRef_setFresh (res, loc);
10993 }
10994 */
10995
28bf4b0b 10996 DPRINTF (("Returns ref: %s", sRef_unparseFull (res)));
616915dd 10997 return res;
10998 }
10999}
11000
11001static bool uentry_isRefCounted (uentry ue)
11002{
11003 ctype ct = uentry_getType (ue);
11004
11005 if (ctype_isFunction (ct))
11006 {
28bf4b0b 11007 return (ctype_isRefCounted (ctype_getReturnType (ct)));
616915dd 11008 }
11009 else
11010 {
11011 return (ctype_isRefCounted (ct));
11012 }
11013}
11014
11015/*
11016** old was declared yield in the specification.
11017** new is declared in the iter implementation.
11018*/
11019
11020void uentry_checkYieldParam (uentry old, uentry unew)
11021{
11022 cstring name;
11023
11024 llassert (uentry_isVariable (old));
11025 llassert (uentry_isVariable (unew));
11026
11027 unew->info->var->kind = VKYIELDPARAM;
11028 (void) checkTypeConformance (old, unew, TRUE);
11029 checkVarConformance (old, unew, TRUE, FALSE);
11030
11031 /* get rid of param marker */
11032
11033 name = uentry_getName (unew);
11034 cstring_free (unew->uname);
11035 unew->uname = name;
11036 unew->info->var->kind = VKREFYIELDPARAM;
11037
11038 uentry_setUsed (old, fileloc_undefined);
11039 uentry_setUsed (unew, fileloc_undefined);
11040}
11041
11042/*@observer@*/ cstring
11043uentry_ekindName (uentry ue)
11044{
11045 if (uentry_isValid (ue))
11046 {
11047 switch (ue->ukind)
11048 {
11049 case KINVALID:
11050 return cstring_makeLiteralTemp ("<Error: invalid uentry>");
11051 case KDATATYPE:
11052 return cstring_makeLiteralTemp ("Datatype");
11053 case KENUMCONST:
11054 return cstring_makeLiteralTemp ("Enum member");
11055 case KCONST:
11056 return cstring_makeLiteralTemp ("Constant");
11057 case KVAR:
11058 if (uentry_isParam (ue))
11059 {
11060 return cstring_makeLiteralTemp ("Parameter");
11061 }
11062 else if (uentry_isExpandedMacro (ue))
11063 {
11064 return cstring_makeLiteralTemp ("Expanded macro");
11065 }
11066 else
11067 {
11068 return cstring_makeLiteralTemp ("Variable");
11069 }
11070 case KFCN:
11071 return cstring_makeLiteralTemp ("Function");
11072 case KITER:
11073 return cstring_makeLiteralTemp ("Iterator");
11074 case KENDITER:
11075 return cstring_makeLiteralTemp ("Iterator finalizer");
11076 case KSTRUCTTAG:
11077 return cstring_makeLiteralTemp ("Struct tag");
11078 case KUNIONTAG:
11079 return cstring_makeLiteralTemp ("Union tag");
11080 case KENUMTAG:
11081 return cstring_makeLiteralTemp ("Enum tag");
11082 case KELIPSMARKER:
11083 return cstring_makeLiteralTemp ("Optional parameters");
11084 }
11085 }
11086 else
11087 {
11088 return cstring_makeLiteralTemp ("<Undefined>");
11089 }
11090
11091 BADEXIT;
11092}
11093
28bf4b0b 11094/*@observer@*/ cstring
11095uentry_ekindNameLC (uentry ue)
11096{
11097 if (uentry_isValid (ue))
11098 {
11099 switch (ue->ukind)
11100 {
11101 case KINVALID:
11102 return cstring_makeLiteralTemp ("<error: invalid uentry>");
11103 case KDATATYPE:
11104 return cstring_makeLiteralTemp ("datatype");
11105 case KENUMCONST:
11106 return cstring_makeLiteralTemp ("enum member");
11107 case KCONST:
11108 return cstring_makeLiteralTemp ("constant");
11109 case KVAR:
11110 if (uentry_isParam (ue))
11111 {
11112 return cstring_makeLiteralTemp ("parameter");
11113 }
11114 else if (uentry_isExpandedMacro (ue))
11115 {
11116 return cstring_makeLiteralTemp ("expanded macro");
11117 }
11118 else
11119 {
11120 return cstring_makeLiteralTemp ("variable");
11121 }
11122 case KFCN:
11123 return cstring_makeLiteralTemp ("function");
11124 case KITER:
11125 return cstring_makeLiteralTemp ("iterator");
11126 case KENDITER:
11127 return cstring_makeLiteralTemp ("iterator finalizer");
11128 case KSTRUCTTAG:
11129 return cstring_makeLiteralTemp ("struct tag");
11130 case KUNIONTAG:
11131 return cstring_makeLiteralTemp ("union tag");
11132 case KENUMTAG:
11133 return cstring_makeLiteralTemp ("enum tag");
11134 case KELIPSMARKER:
11135 return cstring_makeLiteralTemp ("optional parameters");
11136 }
11137 }
11138 else
11139 {
11140 return cstring_makeLiteralTemp ("<Undefined>");
11141 }
11142
11143 BADEXIT;
11144}
11145
616915dd 11146void uentry_setHasNameError (uentry ue)
11147{
11148 llassert (uentry_isValid (ue));
11149
11150 ue->hasNameError = TRUE;
11151}
11152
11153void uentry_checkName (uentry ue)
11154{
28bf4b0b 11155 DPRINTF (("Checking name: %s / %s / %s", uentry_unparse (ue),
11156 uentry_observeRealName (ue),
11157 bool_unparse (uentry_isVisibleExternally (ue))));
11158
616915dd 11159 if (uentry_isValid (ue)
28bf4b0b 11160 && !context_inXHFile ()
11161 && uentry_hasName (ue)
616915dd 11162 && !uentry_isElipsisMarker (ue)
11163 && context_getFlag (FLG_NAMECHECKS)
11164 && !ue->hasNameError
11165 && !uentry_isEndIter (ue)
11166 && !fileloc_isBuiltin (uentry_whereLast (ue))
11167 && (uentry_isExpandedMacro (ue) || !uentry_isForward (ue)))
28bf4b0b 11168 {
11169 DPRINTF (("Here..."));
11170
616915dd 11171 if (uentry_isPriv (ue))
11172 {
11173 ; /* any checks here? */
11174 }
11175 else if (fileloc_isExternal (uentry_whereDefined (ue)))
11176 {
11177 ; /* no errors for externals */
11178 }
11179 else
11180 {
11181 int scope;
11182
11183 if (uentry_isExpandedMacro (ue))
11184 {
11185 scope = globScope;
11186 }
11187 else
11188 {
11189 if (uentry_isExpandedMacro (ue))
11190 {
11191 scope = fileScope;
11192 }
11193 else if (uentry_isVariable (ue))
11194 {
11195 sRef sr = uentry_getSref (ue);
11196
11197 if (sRef_isValid (sr))
11198 {
11199 scope = sRef_getScope (sr);
11200 }
11201 else
11202 {
11203 scope = fileScope;
11204 }
11205 }
11206 else if (uentry_isFunction (ue)
11207 || uentry_isIter (ue)
11208 || uentry_isEndIter (ue)
11209 || uentry_isConstant (ue))
11210 {
11211 scope = uentry_isStatic (ue) ? fileScope : globScope;
11212 }
11213 else /* datatypes, etc. must be global */
11214 {
11215 scope = globScope;
11216 }
11217
11218 usymtab_checkDistinctName (ue, scope);
11219 }
28bf4b0b 11220
616915dd 11221 if (context_getFlag (FLG_CPPNAMES))
11222 {
28bf4b0b 11223 checkCppName (ue);
616915dd 11224 }
11225
11226 if (scope == globScope)
11227 {
28bf4b0b 11228 checkExternalName (ue);
616915dd 11229 }
28bf4b0b 11230 else if (scope == fileScope)
11231 {
11232 checkFileScopeName (ue);
11233 }
11234 else
616915dd 11235 {
11236 checkLocalName (ue);
616915dd 11237 }
11238
616915dd 11239 checkPrefix (ue);
28bf4b0b 11240 checkAnsiName (ue);
616915dd 11241 }
11242 }
11243}
11244
7ebcc5bb 11245/*@exposed@*/ uentry uentry_makeUnrecognized (cstring c, /*@only@*/ fileloc loc)
616915dd 11246{
11247 uentry ue;
11248 fileloc tloc;
11249
11250 /*
7ebcc5bb 11251 ** Can't but unrecognized ids in macros in global scope, because srefs will break!
11252 */
11253
616915dd 11254 if (!context_inMacro ())
11255 {
11256 sRef_setGlobalScopeSafe ();
11257 }
11258
11259 ue = uentry_makeVariable (c, ctype_unknown, loc, FALSE);
11260 uentry_setUsed (ue, loc);
11261
11262 tloc = fileloc_createExternal ();
11263 uentry_setDefined (ue, tloc);
11264 fileloc_free (tloc);
11265 uentry_setHasNameError (ue);
11266
c3be2604 11267 if (context_getFlag (FLG_REPEATUNRECOG) || (context_inOldStyleScope()))
616915dd 11268 {
11269 uentry_markOwned (ue);
11270 }
11271 else
11272 {
11273 ue = usymtab_supReturnFileEntry (ue);
11274 }
11275
11276 if (!context_inMacro ())
11277 {
11278 sRef_clearGlobalScopeSafe ();
11279 }
11280
11281 return ue;
11282}
11283
28bf4b0b 11284uentry uentry_makeGlobalMarker ()
11285{
11286 uentry ue;
11287 fileloc tloc;
11288
11289 llassert (sRef_inGlobalScope ());
11290
11291 ue = uentry_makeVariableAux
11292 (GLOBAL_MARKER_NAME, ctype_unknown, fileloc_undefined,
11293 sRef_makeGlobalMarker (),
11294 FALSE, VKNORMAL);
11295
11296 tloc = fileloc_createExternal ();
11297 uentry_setUsed (ue, tloc);
11298 uentry_setDefined (ue, tloc);
11299 fileloc_free (tloc);
11300 uentry_setHasNameError (ue);
11301
11302 return ue;
11303}
11304
11305
11306bool uentry_isGlobalMarker (uentry ue)
11307{
11308 return (uentry_isValid (ue)
11309 && (cstring_equal (uentry_rawName (ue), GLOBAL_MARKER_NAME)));
11310}
11311
616915dd 11312/* new start modifications */
28bf4b0b 11313
616915dd 11314/* start modifications */
11315/*
11316requires: p_e is defined, is a ptr/array variable
11317modifies: p_e
11318effects: sets the state of the variable
11319*/
11320
28bf4b0b 11321
abd7f895 11322void uentry_setPossiblyNullTerminatedState (uentry p_e)
11323{
11324 llassert (uentry_isValid (p_e));
616915dd 11325
abd7f895 11326 if (p_e->info != NULL)
11327 {
11328 if (p_e->info->var != NULL)
11329 {
11330 llassert (p_e->info->var->bufinfo != NULL);
11331 p_e->info->var->bufinfo->bufstate = BB_POSSIBLYNULLTERMINATED;
11332 sRef_setPossiblyNullTerminatedState (p_e->sref);
11333 }
11334 }
616915dd 11335}
11336
11337/*
11338requires: p_e is defined, is a ptr/array variable
11339modifies: p_e
11340effects: sets the size of the buffer
11341*/
11342
11343void uentry_setNullTerminatedState (uentry p_e) {
abd7f895 11344 llassert (uentry_isValid (p_e));
616915dd 11345
abd7f895 11346 if (p_e->info != NULL)
11347 {
11348 if (p_e->info->var != NULL)
11349 {
11350 llassert (p_e->info->var->bufinfo != NULL);
11351 p_e->info->var->bufinfo->bufstate = BB_NULLTERMINATED;
11352 sRef_setNullTerminatedState (p_e->sref);
11353 }
11354 }
616915dd 11355}
11356
616915dd 11357/*
11358requires: p_e is defined, is a ptr/array variable
11359modifies: p_e
11360effects: sets the size of the buffer
11361*/
11362
abd7f895 11363void uentry_setSize (uentry p_e, int size)
11364{
11365 if (uentry_isValid (p_e))
11366 {
11367 if (p_e->info != NULL)
11368 {
11369 if (p_e->info->var != NULL)
11370 {
11371 llassert (p_e->info->var->bufinfo != NULL);
11372 p_e->info->var->bufinfo->size = size;
11373 sRef_setSize (p_e->sref, size);
11374 }
11375 }
b7b694d6 11376 }
616915dd 11377}
11378
616915dd 11379/*
11380requires: p_e is defined, is a ptr/array variable
11381modifies: p_e
11382effects: sets the length of the buffer
11383*/
11384
abd7f895 11385void uentry_setLen (uentry p_e, int len)
11386{
11387 if (uentry_isValid (p_e))
11388 {
11389 if (p_e->info != NULL
11390 && p_e->info->var != NULL)
11391 {
11392 llassert (p_e->info->var->bufinfo != NULL);
11393 p_e->info->var->bufinfo->len = len;
11394 sRef_setLen (p_e->sref, len);
11395 }
b7b694d6 11396 }
616915dd 11397}
b7b694d6 11398
616915dd 11399/*@=type*/
ba45e1e4 11400
11401bool uentry_hasMetaStateEnsures (uentry e)
11402{
11403 if (uentry_isValid (e) && uentry_isFunction (e))
11404 {
11405 return functionConstraint_hasMetaStateConstraint (e->info->fcn->postconditions);
11406 }
11407 else
11408 {
11409 return FALSE;
11410 }
11411}
11412
ccf0a4a8 11413metaStateConstraintList uentry_getMetaStateEnsures (uentry e)
ba45e1e4 11414{
ccf0a4a8 11415 llassert (uentry_isValid (e) && uentry_isFunction (e));
11416 return functionConstraint_getMetaStateConstraints (e->info->fcn->postconditions);
ba45e1e4 11417}
6483a926 11418
b73d1009 11419
11420bool uentry_hasBufStateInfo (uentry ue)
11421{
11422 llassert (uentry_isValid (ue));
11423 return (ue->info->var->bufinfo != NULL);
11424}
11425
11426bool uentry_isNullTerminated (uentry ue)
11427{
11428 llassert (uentry_hasBufStateInfo (ue));
11429 llassert (ue->info->var->bufinfo != NULL);
11430 return ue->info->var->bufinfo->bufstate == BB_NULLTERMINATED;
11431}
11432
11433bool uentry_isPossiblyNullTerminated (uentry ue)
11434{
11435 llassert (uentry_hasBufStateInfo (ue));
11436 llassert (ue->info->var->bufinfo != NULL);
11437 return (ue->info->var->bufinfo->bufstate == BB_POSSIBLYNULLTERMINATED);
11438}
11439
11440bool uentry_isNotNullTerminated (uentry ue)
11441{
11442 llassert (uentry_hasBufStateInfo (ue));
11443 llassert (ue->info->var->bufinfo != NULL);
11444 return (ue->info->var->bufinfo->bufstate == BB_NOTNULLTERMINATED);
11445}
11446
6483a926 11447# ifdef DEBUGSPLINT
11448
11449/*
11450** For debugging only
11451*/
11452
11453void uentry_checkValid (uentry ue)
11454{
11455 if (uentry_isValid (ue))
11456 {
02b84d4b 11457 sRef_checkCompletelyReasonable (ue->sref);
6483a926 11458 }
11459}
11460
11461# endif
This page took 1.920317 seconds and 5 git commands to generate.