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