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