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