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