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