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