]> andersk Git - splint.git/blame - src/uentry.c
*** empty log message ***
[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));
a0a162cd 1144 llassert (!specialClauses_isDefined (ue->info->fcn->specclauses));
885824d3 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 }
a0a162cd 2502
885824d3 2503 if (ctype_isIncompleteArray (base)) {
2504 base = ctype_baseArrayPtr (base);
2505
2506 if (ctype_isArray (base)) {
a0a162cd 2507 if (!uentry_hasName (ue)) {
2508 (void) optgenerror (FLG_INCOMPLETETYPE,
2509 message ("Unnamed function parameter %d is incomplete type (inner array must have bounds): %s",
2510 i + 1,
2511 ctype_unparse (ct)),
2512 uentry_whereLast (ue));
2513 } else {
2514 (void) optgenerror (FLG_INCOMPLETETYPE,
2515 message ("Function parameter %q is incomplete type (inner array must have bounds): %s",
2516 uentry_getName (ue),
2517 ctype_unparse (ct)),
2518 uentry_whereLast (ue));
2519 }
885824d3 2520 }
2521 }
2522
2523 return ue;
2524}
2525
2526/*@only@*/ /*@notnull@*/ uentry uentry_makeIdVariable (idDecl t)
2527{
2528 ctype ct = idDecl_getCtype (t);
2529
2530 if (ctype_isFunction (ct))
2531 {
2532 return (uentry_makeIdFunction (t));
2533 }
2534 else
2535 {
2536 fileloc loc = setLocation ();
2537 uentry ue = uentry_makeVariable (idDecl_observeId (t), ct, loc, FALSE);
2538
2539 uentry_reflectQualifiers (ue, idDecl_getQuals (t));
2540
2541 if (!uentry_isExtern (ue))
2542 {
2543 uentry_setDefined (ue, loc);
2544 }
2545
2546 return ue;
2547 }
2548}
2549
2550# ifndef NOLCL
2551/*@notnull@*/ uentry uentry_makeVariableParam (cstring n, ctype t)
2552{
2553 return (uentry_makeVariableParamAux (n, t, sRef_makeType (t), SS_DEFINED));
2554}
2555# endif
2556
2557/*
2558** constants
2559*/
2560
2561/*@only@*/ /*@notnull@*/
2562uentry uentry_makeConstantAux (cstring n, ctype t,
2563 /*@keep@*/ fileloc f, bool priv,
2564 /*@only@*/ multiVal m)
2565{
2566 uentry e = uentry_alloc ();
2567
2568 e->ukind = KCONST;
2569 e->uname = cstring_copy (n);
2570 e->utype = t;
2571 e->storageclass = SCNONE;
2572
2573 e->sref = sRef_makeConst (t);
2574
2575 e->lset = FALSE;
2576 e->used = FALSE;
2577
2578 e->uses = filelocList_new ();
2579 e->isPrivate = priv;
2580 e->hasNameError = FALSE;
2581
2582 e->info = (uinfo) dmalloc (sizeof (*e->info));
2583 e->info->uconst = (ucinfo) dmalloc (sizeof (*e->info->uconst));
2584 e->info->uconst->val = m;
2585 e->info->uconst->access = typeIdSet_undefined;
2586
2587 uentry_setSpecDef (e, f);
2588
2589 if (multiVal_isInt (m) && (multiVal_forceInt (m) == 0))
2590 {
2591 sRef_setDefNull (e->sref, uentry_whereDeclared (e));
2592 }
2593
2594 return (e);
2595}
2596
2597/*@notnull@*/ uentry uentry_makeConstant (cstring n, ctype t, fileloc f)
2598{
2599 return (uentry_makeConstantAux (n, t, f, FALSE, multiVal_unknown ()));
2600}
2601
2602/*@notnull@*/ uentry uentry_makeIdConstant (idDecl t)
2603{
2604 uentry ue = uentry_makeConstant (idDecl_observeId (t),
2605 idDecl_getCtype (t),
2606 fileloc_undefined);
2607
2608 llassert (fileloc_isUndefined (ue->whereDeclared));
2609 ue->whereDeclared = setLocation ();
2610
2611 uentry_reflectQualifiers (ue, idDecl_getQuals (t));
2612
2613 return ue;
2614}
2615
2616/*
2617** variables
2618*/
2619
2620void uentry_setDefState (uentry ue, sstate defstate)
2621{
2622 if (uentry_isValid (ue))
2623 {
2624 sRef_setDefState (ue->sref, defstate, fileloc_undefined);
2625
2626 if (uentry_isVariable (ue))
2627 {
2628 ue->info->var->defstate = defstate; /* evs 2000-05-17: fixed bug, was SS_DEFINED! */
2629 }
2630 }
2631}
2632
2633bool uentry_isCheckedUnknown (uentry ue)
2634{
2635 return (uentry_isVar (ue)
2636 && (ue->info->var->checked == CH_UNKNOWN));
2637}
2638
2639bool uentry_isCheckMod (uentry ue)
2640{
2641 return (uentry_isVar (ue)
2642 && (ue->info->var->checked == CH_CHECKMOD));
2643}
2644
2645bool uentry_isUnchecked (uentry ue)
2646{
2647 return (uentry_isVar (ue)
2648 && (ue->info->var->checked == CH_UNCHECKED));
2649}
2650
2651bool uentry_isChecked (uentry ue)
2652{
2653 return (uentry_isVar (ue)
2654 && (ue->info->var->checked == CH_CHECKED));
2655}
2656
2657bool uentry_isCheckedModify (uentry ue)
2658{
2659 return (uentry_isVar (ue)
2660 && (ue->info->var->checked == CH_CHECKED
2661 || ue->info->var->checked == CH_CHECKMOD
2662 || ue->info->var->checked == CH_CHECKEDSTRICT));
2663}
2664
2665bool uentry_isCheckedStrict (uentry ue)
2666{
2667 return (uentry_isVar (ue)
2668 && (ue->info->var->checked == CH_CHECKEDSTRICT));
2669}
2670
2671void uentry_setUnchecked (uentry ue)
2672{
2673 llassert (uentry_isVar (ue));
2674
2675 ue->info->var->checked = CH_UNCHECKED;
2676}
2677
2678void uentry_setChecked (uentry ue)
2679{
2680 llassert (uentry_isVar (ue));
2681
2682 ue->info->var->checked = CH_CHECKED;
2683}
2684
2685void uentry_setCheckMod (uentry ue)
2686{
2687 llassert (uentry_isVar (ue));
2688
2689 ue->info->var->checked = CH_CHECKMOD;
2690}
2691
2692void uentry_setCheckedStrict (uentry ue)
2693{
2694 llassert (uentry_isVar (ue));
2695
2696 ue->info->var->checked = CH_CHECKEDSTRICT;
2697}
2698
2699static /*@only@*/ /*@notnull@*/
2700 uentry uentry_makeVariableAux (cstring n, ctype t,
2701 fileloc f,
2702 /*@exposed@*/ sRef s,
2703 bool priv, vkind kind)
2704{
2705 uentry e = uentry_alloc ();
2706 ctype rt = t;
2707
2708 DPRINTF (("Make variable: %s %s %s", n, ctype_unparse (t), sRef_unparse (s)));
2709
2710 e->ukind = KVAR;
2711 e->uname = cstring_copy (n);
2712 e->utype = t;
2713
2714 e->storageclass = SCNONE;
2715
2716 e->sref = s;
2717
2718 e->used = FALSE;
2719 e->lset = FALSE;
2720
2721 e->uses = filelocList_new ();
2722 e->isPrivate = priv;
2723 e->hasNameError = FALSE;
2724
2725 e->info = (uinfo) dmalloc (sizeof (*e->info));
2726 e->info->var = (uvinfo) dmalloc (sizeof (*e->info->var));
2727 e->info->var->kind = kind;
2728
2729 e->info->var->checked = CH_UNKNOWN;
2730
2731 uentry_setSpecDef (e, f);
2732
2733 if (ctype_isFunction (rt))
2734 {
2735 rt = ctype_returnValue (rt);
2736 }
2737
2738 if (ctype_isUA (rt))
2739 {
2740 sRef_setStateFromType (e->sref, rt);
2741 }
2742
2743 e->info->var->defstate = sRef_getDefState (e->sref);
2744 e->info->var->nullstate = sRef_getNullState (e->sref);
2745
1ac6313d 2746/* start modifications */
2747/* This function sets the uentry for a pointer or array variable declaration,
2748 it allocates memory and sets the fields. We check if the type of the variable
2749 is a pointer or array and allocate a `bbufinfo' struct accordingly */
2750
2751 if( ctype_isArray (t) || ctype_isPointer(t)) {
2752 e->info->var->bufinfo = dmalloc( sizeof(*e->info->var->bufinfo) );
2753 e->info->var->bufinfo->bufstate = BB_NOTNULLTERMINATED;
2754 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
2755 } else {
2756 e->info->var->bufinfo = NULL;
2757 }/* end else */
2758/* end modification */
2759
885824d3 2760 return (e);
2761}
2762
2763bool
2764uentry_isYield (uentry ue)
2765{
2766 return (uentry_isVariable (ue)
2767 && (ue->info->var->kind == VKYIELDPARAM
2768 || ue->info->var->kind == VKREFYIELDPARAM));
2769}
2770
2771static bool
2772uentry_isRefsField (uentry ue)
2773{
2774 return (uentry_isVariable (ue) && sRef_isRefsField (ue->sref));
2775}
2776
2777/*@only@*/ /*@notnull@*/
2778uentry uentry_makeVariable (cstring n, ctype t, fileloc f, bool isPriv)
2779{
2780 return (uentry_makeVariableAux (n, t, f, sRef_makeType (t), isPriv,
2781 fileloc_isSpec (f) ? VKSPEC : VKNORMAL));
2782}
2783
2784/*
2785** functions
2786*/
2787
2788void uentry_makeVarFunction (uentry ue)
2789{
2790 alkind ak;
2791 exkind ek;
2792 uvinfo oldInfo;
2793 fileloc loc;
2794
2795 llassert (uentry_isValid (ue));
2796 llassert (!sRef_modInFunction ());
2797
2798 ak = sRef_getOrigAliasKind (ue->sref);
2799 ek = sRef_getOrigExKind (ue->sref);
2800
2801 oldInfo = ue->info->var;
2802
2803 llassert (ctype_isUnknown (ue->utype) || ctype_isFunction (ue->utype));
2804
2805 /*
2806 ** expanded macro is marked used (until I write a pre-processor)
2807 */
2808
2809 ue->used |= (oldInfo->kind == VKEXPMACRO);
2810
2811 ue->ukind = KFCN;
2812 ue->info->fcn = (ufinfo) dmalloc (sizeof (*ue->info->fcn));
2813 ue->info->fcn->exitCode = XK_UNKNOWN;
2814 ue->info->fcn->nullPred = QU_UNKNOWN;
2815 ue->info->fcn->specialCode = SPC_NONE;
2816 ue->info->fcn->access = typeIdSet_undefined;
2817 ue->info->fcn->hasGlobs = FALSE;
2818 ue->info->fcn->globs = globSet_undefined;
2819 ue->info->fcn->hasMods = FALSE;
2820 ue->info->fcn->mods = sRefSet_undefined;
2821 ue->info->fcn->specclauses = NULL;
2822 ue->info->fcn->defparams = uentryList_undefined;
2823
2824 if (ctype_isFunction (ue->utype))
2825 {
2826 ue->sref = sRef_makeType (ctype_returnValue (ue->utype));
2827 }
2828 else
2829 {
2830 ue->sref = sRef_makeType (ctype_unknown);
2831 }
2832
2833 if (sRef_isRefCounted (ue->sref))
2834 {
2835 ak = AK_NEWREF;
2836 }
2837 else
2838 {
2839 if (alkind_isUnknown (ak))
2840 {
2841 if (exkind_isKnown (ek))
2842 {
2843 ak = AK_IMPDEPENDENT;
2844 }
2845 else
2846 {
2847 if (context_getFlag (FLG_RETIMPONLY))
2848 {
2849 if (ctype_isFunction (ue->utype)
2850 && ctype_isVisiblySharable
2851 (ctype_realType (ctype_returnValue (ue->utype))))
2852 {
2853 if (uentryList_hasReturned (uentry_getParams (ue)))
2854 {
2855 ;
2856 }
2857 else
2858 {
2859 ak = AK_IMPONLY;
2860 }
2861 }
2862 }
2863 }
2864 }
2865 }
2866
2867 loc = ue->whereDeclared;
2868
2869 sRef_setAliasKind (ue->sref, ak, loc);
2870 sRef_setNullState (ue->sref, oldInfo->nullstate, loc);
2871 sRef_setDefState (ue->sref, oldInfo->defstate, loc);
2872 sRef_setExKind (ue->sref, ek, loc);
2873
2874 if (oldInfo->kind == VKEXPMACRO)
2875 {
2876 fileloc_free (loc);
2877 ue->whereDeclared = fileloc_undefined;
2878 }
2879 else
2880 {
2881 fileloc_free (ue->whereDefined);
2882 ue->whereDefined = fileloc_undefined;
2883 }
2884
2885 uvinfo_free (oldInfo);
2886}
2887
2888void
2889uentry_setGlobals (uentry ue, /*@owned@*/ globSet globs)
2890{
2891 llassert (uentry_isValid (ue));
2892
2893 if (uentry_isIter (ue))
2894 {
2895 llassert (globSet_isUndefined (ue->info->iter->globs));
2896 ue->info->iter->globs = globs;
2897 }
2898 else
2899 {
2900 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
2901 {
2902 uentry_makeVarFunction (ue);
2903 }
2904
2905 llassert (uentry_isFunction (ue));
2906 llassert (!ue->info->fcn->hasGlobs
2907 && globSet_isUndefined (ue->info->fcn->globs));
2908
2909 ue->info->fcn->hasGlobs = TRUE;
2910 /*@-mustfree@*/ ue->info->fcn->globs = globs;
2911 /*@=mustfree@*/
2912 }
2913
2914 if (globSet_hasStatic (globs))
2915 {
2916 context_recordFileGlobals (globs);
2917 }
2918
2919 if (context_getFlag (FLG_GLOBALSIMPMODIFIESNOTHING))
2920 {
2921 ue->info->fcn->hasMods = TRUE;
2922 }
2923}
2924
2925void uentry_addAccessType (uentry ue, typeId tid)
2926{
2927 if (uentry_isFunction (ue))
2928 {
2929 ue->info->fcn->access = typeIdSet_insert (ue->info->fcn->access, tid);
2930 }
2931 else if (uentry_isEitherConstant (ue))
2932 {
2933 ue->info->uconst->access = typeIdSet_insert (ue->info->uconst->access, tid);
2934 }
2935 else if (uentry_isIter (ue))
2936 {
2937 ue->info->iter->access = typeIdSet_insert (ue->info->iter->access, tid);
2938 }
2939 else if (uentry_isEndIter (ue))
2940 {
2941 ue->info->enditer->access = typeIdSet_insert (ue->info->enditer->access, tid);
2942 }
2943 else
2944 {
2945 llbug (message ("no access for: %q", uentry_unparse (ue)));
2946 }
2947}
2948
2949/*@only@*/ /*@notnull@*/ uentry
2950 uentry_makeFunction (cstring n, ctype t,
2951 typeId access,
2952 /*@only@*/ globSet globs, /*@only@*/ sRefSet mods,
2953 fileloc f)
2954{
2955 return (uentry_makeFunctionAux (n, t,
2956 ((typeId_isInvalid (access)) ? typeIdSet_emptySet ()
2957 : typeIdSet_single (access)),
2958 globs, mods, f,
2959 FALSE, FALSE));
2960}
2961
2962# ifndef NOLCL
2963/*@notnull@*/ uentry
2964 uentry_makePrivFunction2 (cstring n, ctype t,
2965 typeIdSet access,
2966 globSet globs, sRefSet mods,
2967 fileloc f)
2968{
2969 return (uentry_makeFunctionAux (n, t, access, globs, mods, f, TRUE, FALSE));
2970}
2971
2972
2973/*@notnull@*/ uentry
2974 uentry_makeSpecFunction (cstring n, ctype t,
2975 typeIdSet access,
2976 /*@only@*/ globSet globs,
2977 /*@only@*/ sRefSet mods,
2978 fileloc f)
2979{
2980 uentry ue = uentry_makeFunctionAux (n, t, access,
2981 globs, mods, f,
2982 FALSE, FALSE);
2983
2984 uentry_setHasGlobs (ue);
2985 uentry_setHasMods (ue);
2986
2987 reflectImplicitFunctionQualifiers (ue, TRUE);
2988 return (ue);
2989}
2990# endif
2991
2992uentry uentry_makeExpandedMacro (cstring s, fileloc f)
2993{
2994 uentry ue = uentry_makeVariableAux (s, ctype_unknown, fileloc_undefined,
2995 sRef_undefined, FALSE, VKEXPMACRO);
2996
2997 uentry_setDefined (ue, f);
2998 return ue;
2999}
3000
3001/*@notnull@*/ /*@notnull@*/ uentry
3002 uentry_makeForwardFunction (cstring n, typeId access, fileloc f)
3003{
3004 uentry ue = uentry_makeFunctionAux (n, ctype_unknown,
3005 typeIdSet_singleOpt (access),
3006 globSet_undefined, sRefSet_undefined,
3007 fileloc_undefined,
3008 FALSE, TRUE);
3009
3010 ue->whereDeclared = fileloc_update (ue->whereDeclared, f);
3011 return ue;
3012}
3013
3014bool uentry_isForward (uentry e)
3015{
3016 if (uentry_isValid (e))
3017 {
3018 ctype ct = uentry_getType (e);
3019
3020 return (ctype_isUnknown (ct)
3021 || (ctype_isFunction (ct)
3022 && ctype_isUnknown (ctype_returnValue (ct))));
3023 }
3024
3025 return FALSE;
3026}
3027
3028# ifndef NOLCL
3029/*@notnull@*/ uentry
3030uentry_makeTypeListFunction (cstring n, typeIdSet access, fileloc f)
3031{
3032 return (uentry_makeFunctionAux (n, ctype_unknown, access,
3033 globSet_new (),
3034 sRefSet_new (), f,
3035 FALSE, TRUE));
3036}
3037
3038/*@notnull@*/ uentry
3039uentry_makeUnspecFunction (cstring n, ctype t,
3040 typeIdSet access,
3041 fileloc f)
3042{
3043 uentry ue = uentry_makeFunctionAux (n, t, access, globSet_new (),
3044 sRefSet_new (), f, FALSE, TRUE);
3045
3046 reflectImplicitFunctionQualifiers (ue, TRUE);
3047 return ue;
3048}
3049# endif
3050
3051/*
3052** datatypes
3053*/
3054
3055/* is exported for use by usymtab_interface */
3056
3057/*@notnull@*/ uentry
3058 uentry_makeDatatypeAux (cstring n, ctype t, ynm mut, ynm abs,
3059 fileloc f, bool priv)
3060{
3061 uentry e = uentry_alloc ();
3062
a0a162cd 3063 DPRINTF (("Make datatype: %s / %s",
3064 n, ctype_unparse (t)));
3065
885824d3 3066 /* e->shallowCopy = FALSE; */
3067 e->ukind = KDATATYPE;
3068 e->uname = cstring_copy (n);
3069 e->utype = t;
3070 e->storageclass = SCNONE;
3071 e->sref = sRef_makeUnknown ();
3072
3073 if (ctype_isUA (t))
3074 {
3075 sRef_setStateFromType (e->sref, t);
3076 }
3077
3078 uentry_setSpecDef (e, f);
3079
3080 e->uses = filelocList_new ();
3081 e->isPrivate = priv;
3082 e->hasNameError = FALSE;
3083
3084 e->used = FALSE;
3085 e->lset = FALSE;
3086
3087 e->info = (uinfo) dmalloc (sizeof (*e->info));
3088 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
3089 e->info->datatype->abs = abs;
3090 e->info->datatype->mut = mut;
3091 e->info->datatype->type = ctype_undefined;
3092
3093 if (uentry_isDeclared (e))
3094 {
3095 uentry_setDefined (e, f);
3096 }
3097
3098 if (ynm_isOn (abs) && !(uentry_isCodeDefined (e)))
3099 {
3100 sRef_setNullState (e->sref, NS_ABSNULL, uentry_whereDeclared (e));
3101 }
3102
3103 return (e);
3104}
3105
3106/*@notnull@*/ uentry
3107 uentry_makeDatatype (cstring n, ctype t, ynm mut, ynm abs,
3108 fileloc f)
3109{
3110 return (uentry_makeDatatypeAux (n, t, mut, abs, f, FALSE));
3111}
3112
3113/*@notnull@*/ uentry uentry_makeBoolDatatype (ynm abs)
3114{
3115 uentry ret = uentry_makeDatatypeAux (context_getBoolName (),
3116 ctype_bool, NO, abs,
3117 fileloc_getBuiltin (),
3118 FALSE);
3119
3120 ret->info->datatype->type = ctype_bool;
3121 return ret;
3122}
3123
3124/*
3125** iters
3126*/
3127
3128static /*@only@*/ /*@notnull@*/ uentry
3129 uentry_makeIterAux (cstring n, typeIdSet access, ctype ct,
3130 /*@only@*/ fileloc f)
3131{
3132 uentry e = uentry_alloc ();
3133
3134 e->ukind = KITER;
3135 e->uname = cstring_copy (n);
3136 e->utype = ct;
3137 e->sref = sRef_makeUnknown ();
3138 e->storageclass = SCNONE;
3139 e->used = FALSE;
3140 e->lset = FALSE;
3141
3142 uentry_setSpecDef (e, f);
3143
3144 e->uses = filelocList_new ();
3145 e->isPrivate = FALSE;
3146 e->hasNameError = FALSE;
3147
3148 e->info = (uinfo) dmalloc (sizeof (*e->info));
3149 e->info->iter = (uiinfo) dmalloc (sizeof (*e->info->iter));
3150 e->info->iter->access = access;
3151 e->info->iter->mods = sRefSet_undefined;
3152 e->info->iter->globs = globSet_undefined;
3153
3154 uentry_checkIterArgs (e);
3155 return (e);
3156}
3157
3158/*@notnull@*/ uentry uentry_makeIter (cstring n, ctype ct, fileloc f)
3159{
3160 return (uentry_makeIterAux (n, context_fileAccessTypes (), ct, f));
3161}
3162
3163static /*@notnull@*/ uentry
3164uentry_makeEndIterAux (cstring n, typeIdSet access, /*@only@*/ fileloc f)
3165{
3166 uentry e = uentry_alloc ();
3167
3168 /* e->shallowCopy = FALSE; */
3169 e->ukind = KENDITER;
3170 e->storageclass = SCNONE;
3171 e->uname = message ("end_%s", n);
3172 e->utype = ctype_unknown;
3173 e->sref = sRef_makeUnknown ();
3174
3175 uentry_setSpecDef (e, f);
3176
3177 e->used = FALSE;
3178 e->lset = FALSE;
3179
3180 e->uses = filelocList_new ();
3181 e->isPrivate = FALSE;
3182 e->hasNameError = FALSE;
3183
3184 e->info = (uinfo) dmalloc (sizeof (*e->info));
3185 e->info->enditer = (ueinfo) dmalloc (sizeof (*e->info->enditer));
3186
3187 e->info->enditer->access = access;
3188
3189 return (e);
3190}
3191
3192/*@notnull@*/ /*@only@*/ uentry uentry_makeEndIter (cstring n, fileloc f)
3193{
3194 return (uentry_makeEndIterAux (n, context_fileAccessTypes (), f));
3195}
3196
3197/*
3198** tags
3199*/
3200
3201static /*@only@*/ /*@notnull@*/ uentry
3202 uentry_makeTagAux (cstring n, ctype t,
3203 /*@only@*/ fileloc fl,
3204 bool priv, ekind kind)
3205{
3206 uentry e = uentry_alloc ();
3207
3208 if (kind != KSTRUCTTAG && kind != KUNIONTAG && kind != KENUMTAG)
3209 {
3210 llbuglit ("uentry_makeTagAux: not a tag type");
3211 }
3212
3213 e->ukind = kind;
3214 /* e->shallowCopy = FALSE; */
3215 e->uname = cstring_copy (n);
3216
3217 e->utype = t;
3218 e->sref = sRef_makeUnknown ();
3219 e->storageclass = SCNONE;
3220
3221 uentry_setSpecDef (e, fl);
3222
3223 e->used = FALSE;
3224 e->lset = FALSE;
3225
3226 e->uses = filelocList_new ();
3227 e->isPrivate = priv;
3228 e->hasNameError = FALSE;
3229
3230 e->info = (uinfo) dmalloc (sizeof (*e->info));
3231 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
3232 e->info->datatype->abs = NO;
3233 e->info->datatype->mut = (kind == KENUMTAG) ? NO : MAYBE;
3234 e->info->datatype->type = t;
3235
3236 if (uentry_isDeclared (e))
3237 {
3238 uentry_setDefined (e, fl);
3239 }
3240
a0a162cd 3241 DPRINTF (("Make tag: %s / %s [%d]", uentry_unparseFull (e),
3242 ctype_unparse (t), t));
885824d3 3243 return (e);
3244}
3245
3246uentry uentry_makeStructTagLoc (cstring n, ctype t)
3247{
3248 cstring sname = makeStruct (n);
3249 uentry ret = uentry_makeTagAux (sname, t, setLocation (), FALSE, KSTRUCTTAG);
3250
3251 cstring_free (sname);
3252 return (ret);
3253}
3254
3255/*@only@*/ uentry
3256uentry_makeStructTag (cstring n, ctype t, fileloc loc)
3257{
3258 cstring sname = makeStruct (n);
3259 uentry ret = uentry_makeTagAux (sname, t, loc, FALSE, KSTRUCTTAG);
3260
3261 cstring_free (sname);
3262 return ret;
3263}
3264
3265/*@only@*/ uentry
3266uentry_makeUnionTag (cstring n, ctype t, fileloc loc)
3267{
3268 cstring uname = makeUnion (n);
3269 uentry ret = uentry_makeTagAux (uname, t, loc, FALSE, KUNIONTAG);
3270
3271 cstring_free (uname);
3272 return (ret);
3273}
3274
3275# ifndef NOLCL
3276uentry
3277uentry_makeEnumTag (cstring n, ctype t, fileloc loc)
3278{
3279 cstring ename = makeEnum (n);
3280 uentry ret = uentry_makeTagAux (ename, t, loc, FALSE, KENUMTAG);
3281
3282 cstring_free (ename);
3283 return ret;
3284}
3285# endif
3286
3287uentry
3288uentry_makeUnionTagLoc (cstring n, ctype t)
3289{
3290 cstring uname = makeUnion (n);
3291 uentry ret = uentry_makeTagAux (uname, t, setLocation (), FALSE, KUNIONTAG);
3292
3293 cstring_free (uname);
3294 return ret;
3295}
3296
3297uentry
3298uentry_makeEnumTagLoc (cstring n, ctype t)
3299{
3300 cstring ename = makeEnum (n);
3301 uentry ret = uentry_makeTagAux (ename, t, setLocation (), FALSE, KENUMTAG);
3302
3303 cstring_free (ename);
3304 return ret;
3305}
3306
3307bool
3308uentry_isStructTag (uentry ue)
3309{
3310 return (uentry_isValid (ue) && ue->ukind == KSTRUCTTAG);
3311}
3312
3313bool
3314uentry_isUnionTag (uentry ue)
3315{
3316 return (uentry_isValid (ue) && ue->ukind == KUNIONTAG);
3317}
3318
3319bool
3320uentry_isEnumTag (uentry ue)
3321{
3322 return (uentry_isValid (ue) && ue->ukind == KENUMTAG);
3323}
3324
3325bool
3326uentry_isAnyTag (uentry ue)
3327{
3328 return (uentry_isStructTag (ue)
3329 || uentry_isUnionTag (ue)
3330 || uentry_isEnumTag (ue));
3331}
3332
3333static /*@unchecked@*/ /*@only@*/ uentry emarker = NULL;
3334
3335extern void uentry_destroyMod (void)
3336 /*@globals killed emarker@*/ /*@modifies emarker@*/
3337{
3338 static bool wasDestroyed = FALSE;
3339
3340 llassert (!wasDestroyed);
3341
3342 if (emarker != NULL)
3343 {
3344 uentry_reallyFree (emarker);
3345 }
3346
3347 wasDestroyed = TRUE;
3348}
3349
3350uentry
3351uentry_makeElipsisMarker (void)
3352{
3353 if (emarker == NULL)
3354 {
3355 emarker = uentry_alloc ();
3356
3357 emarker->ukind = KELIPSMARKER;
3358 emarker->uname = cstring_makeLiteral ("...");
3359 emarker->utype = ctype_elipsMarker;
3360 emarker->sref = sRef_undefined;
3361 emarker->storageclass = SCNONE;
3362 emarker->used = FALSE;
3363 emarker->lset = FALSE;
3364 emarker->info = NULL;
3365
3366 uentry_setSpecDef (emarker, fileloc_undefined);
3367 emarker->uses = filelocList_new ();
3368 emarker->isPrivate = FALSE;
3369 emarker->hasNameError = FALSE;
3370 }
3371
3372 /*@ignore@*/ return (emarker); /*@end@*/
3373}
3374
3375/*
3376** comparisons
3377*/
3378
3379bool
3380uentry_equiv (uentry p1, uentry p2)
3381{
3382 if (uentry_compare (p1, p2) != 0)
3383 {
3384 return FALSE;
3385 }
3386 else
3387 {
3388 return TRUE;
3389 }
3390}
3391
3392int
3393uentry_xcomparealpha (uentry *p1, uentry *p2)
3394{
3395 int res;
3396
3397 if ((res = uentry_compare (*p1, *p2)) == 0) {
3398 if ((*p1 != NULL) && (*p2 != NULL)) {
3399 res = cstring_compare ((*p1)->uname,
3400 (*p2)->uname);
3401 }
3402 }
3403
3404 return res;
3405}
3406
3407int
3408uentry_xcompareuses (uentry *p1, uentry *p2)
3409{
3410 uentry u1 = *p1;
3411 uentry u2 = *p2;
3412
3413 if (uentry_isValid (u1))
3414 {
3415 if (uentry_isValid (u2))
3416 {
3417 return (-1 * int_compare (filelocList_size (u1->uses),
3418 filelocList_size (u2->uses)));
3419 }
3420 else
3421 {
3422 return 1;
3423 }
3424 }
3425 else
3426 {
3427 if (uentry_isValid (u2))
3428 {
3429 return -1;
3430 }
3431 else
3432 {
3433 return 0;
3434 }
3435 }
3436}
3437
3438int
3439uentry_compareStrict (uentry v1, uentry v2)
3440{
3441 COMPARERETURN (uentry_compare (v1, v2));
3442
3443 if (v1 != v2 && uentry_isValid (v1) && uentry_isValid (v2))
3444 {
3445 COMPARERETURN (fileloc_compare (v1->whereDeclared, v2->whereDeclared));
3446 COMPARERETURN (fileloc_compare (v1->whereDefined, v2->whereDefined));
3447 COMPARERETURN (fileloc_compare (v1->whereSpecified, v2->whereSpecified));
3448 }
3449
3450 return 0;
3451}
3452
3453int
3454uentry_compare (uentry u1, uentry u2)
3455{
3456 if (u1 == u2) return 0;
3457
3458 if (uentry_isInvalid (u1)) return -1;
3459 if (uentry_isInvalid (u2)) return 1;
3460
3461 INTCOMPARERETURN (u1->ukind, u2->ukind);
3462 COMPARERETURN (ctype_compare (u1->utype, u2->utype));
3463 COMPARERETURN (bool_compare (uentry_isPriv (u1), uentry_isPriv (u2)));
3464
3465 COMPARERETURN (sRef_compare (u1->sref, u2->sref));
3466
3467 switch (u1->ukind)
3468 {
3469 case KINVALID:
3470 case KELIPSMARKER:
3471 /* bug detected by lclint:
3472 ** uentry.c:753,14: Return value type bool does not match declared type int: TRUE
3473 */
3474 return 0;
3475 case KENUMCONST:
3476 case KCONST:
3477 return (multiVal_compare (u1->info->uconst->val,
3478 u2->info->uconst->val));
3479 case KSTRUCTTAG:
3480 case KUNIONTAG:
3481 case KENUMTAG:
3482 return (ctype_compare (u1->info->datatype->type, u2->info->datatype->type));
3483 case KITER:
3484 COMPARERETURN (typeIdSet_compare (uentry_accessType (u1),
3485 uentry_accessType (u2)));
3486 return (uentryList_compareParams (uentry_getParams (u1),
3487 uentry_getParams (u2)));
3488 case KENDITER:
3489 return (typeIdSet_compare (uentry_accessType (u1),
3490 uentry_accessType (u2)));
3491 case KFCN:
3492 COMPARERETURN (typeIdSet_compare (uentry_accessType (u1),
3493 uentry_accessType (u2)));
3494 COMPARERETURN (globSet_compare (uentry_getGlobs (u1),
3495 uentry_getGlobs (u2)));
3496 COMPARERETURN (uentryList_compareParams (uentry_getParams (u1),
3497 uentry_getParams (u2)));
3498 COMPARERETURN (generic_compare (u1->info->fcn->specialCode,
3499 u2->info->fcn->specialCode));
3500 COMPARERETURN (generic_compare (u1->info->fcn->nullPred,
3501 u2->info->fcn->nullPred));
3502
3503 return (sRefSet_compare (uentry_getMods (u1), uentry_getMods (u2)));
3504 case KVAR:
3505 COMPARERETURN (generic_compare (u1->info->var->kind, u2->info->var->kind));
3506 COMPARERETURN (generic_compare (sRef_getOrigAliasKind (u1->sref),
3507 sRef_getOrigAliasKind (u2->sref)));
3508 COMPARERETURN (generic_compare (sRef_getOrigExKind (u1->sref),
3509 sRef_getOrigExKind (u2->sref)));
3510 COMPARERETURN (generic_compare (u1->info->var->checked,
3511 u2->info->var->checked));
3512 COMPARERETURN (generic_compare (u1->info->var->defstate,
3513 u2->info->var->defstate));
3514 return (generic_compare (u1->info->var->nullstate,
3515 u2->info->var->nullstate));
3516 case KDATATYPE:
3517 COMPARERETURN (ctype_compare (u1->info->datatype->type,
3518 u2->info->datatype->type));
3519 COMPARERETURN (ynm_compare (u1->info->datatype->mut,
3520 u2->info->datatype->mut));
3521 return (ynm_compare (u1->info->datatype->abs, u2->info->datatype->abs));
3522 }
3523
3524 BADEXIT;
3525}
3526
3527/*
3528** library format:
3529**
3530** all entries are: <type>[@<info>]*#<name>
3531**
3532** info depends on kind:
3533*/
3534
3535static void
3536advanceField (char **s)
3537{
3538 checkChar (s, '@');
3539}
3540
3541static void
3542advanceName (char **s)
3543{
3544 checkChar (s, '#');
3545}
3546
3547static vkind
3548vkind_fromInt (int i)
3549{
3550 if /*@+enumint@*/ (i < VKFIRST || i > VKLAST) /*@=enumint@*/
3551 {
3552 llbuglit ("vkind_fromInt: out of range");
3553 }
3554
3555 return (vkind)i;
3556}
3557
3558static uentry
3559 uentry_makeConstantBase (/*@only@*/ cstring name, ctype ct,
3560 typeIdSet access, nstate nullstate,
3561 /*@keep@*/ fileloc loc, /*@only@*/ multiVal m)
3562{
3563 uentry e = uentry_alloc ();
3564
3565 e->ukind = KCONST;
3566 e->uname = name;
3567 e->utype = ct;
3568 e->sref = sRef_makeConst (ct);
3569
3570 sRef_setNullState (e->sref, nullstate, loc);
3571 e->storageclass = SCNONE;
3572
3573 if (fileloc_isSpec (loc))
3574 {
3575 e->whereSpecified = loc;
3576 e->whereDeclared = fileloc_undefined;
3577 }
3578 else
3579 {
3580 e->whereSpecified = fileloc_undefined;
3581 e->whereDeclared = loc;
3582 }
3583
3584 e->whereDefined = fileloc_undefined;
3585 e->uses = filelocList_new ();
3586 e->isPrivate = FALSE;
3587 e->hasNameError = FALSE;
3588
3589 e->used = FALSE;
3590 e->lset = FALSE;
3591
3592 e->info = (uinfo) dmalloc (sizeof (*e->info));
3593 e->info->uconst = (ucinfo) dmalloc (sizeof (*e->info->uconst));
3594 e->info->uconst->val = m;
3595 e->info->uconst->access = access;
3596
3597 sRef_storeState (e->sref);
3598
3599 return (e);
3600}
3601
3602static /*@only@*/ uentry
3603 uentry_makeVariableBase (/*@only@*/ cstring name, ctype ct, vkind kind,
3604 sstate defstate, nstate isnull, alkind aliased,
3605 exkind exp, chkind checked,
3606 /*@only@*/ fileloc loc)
3607{
3608 uentry e = uentry_alloc ();
3609
3610 e->ukind = KVAR;
3611 e->uname = name;
3612 e->utype = ct;
3613 e->storageclass = SCNONE;
3614
3615 e->sref = sRef_makeType (ct);
3616 sRef_setNullState (e->sref, isnull, loc);
3617
3618 e->whereDefined = fileloc_undefined;
3619
3620 if (fileloc_isSpec (loc))
3621 {
3622 e->whereSpecified = loc;
3623 e->whereDeclared = fileloc_undefined;
3624 }
3625 else
3626 {
3627 e->whereSpecified = fileloc_undefined;
3628 e->whereDeclared = loc;
3629 }
3630
3631 e->isPrivate = FALSE;
3632 e->hasNameError = FALSE;
3633
3634 e->used = FALSE;
3635 e->lset = FALSE;
3636
3637 e->uses = filelocList_new ();
3638
3639 e->info = (uinfo) dmalloc (sizeof (*e->info));
3640 e->info->var = (uvinfo) dmalloc (sizeof (*e->info->var));
3641 e->info->var->kind = kind;
3642 e->info->var->checked = checked;
3643 e->info->var->defstate = defstate;
3644
3645 sRef_setDefState (e->sref, defstate, loc);
3646
3647 e->info->var->nullstate = sRef_getNullState (e->sref);
3648
3649 sRef_setExKind (e->sref, exp, loc);
3650 sRef_setAliasKind (e->sref, aliased, loc);
3651
3652 sRef_storeState (e->sref);
3653 return (e);
3654}
3655
3656static /*@only@*/ uentry
3657uentry_makeDatatypeBase (/*@only@*/ cstring name, ctype ct, ynm abs,
3658 ynm mut, ctype rtype, alkind ak, exkind exp,
3659 sstate defstate, nstate isnull,
3660 /*@only@*/ fileloc loc)
3661{
3662 uentry e = uentry_alloc ();
3663
3664 e->ukind = KDATATYPE;
3665 /* e->shallowCopy = FALSE; */
3666 e->uname = name;
3667 e->utype = ct;
3668 e->storageclass = SCNONE;
3669 e->sref = sRef_makeUnknown ();
3670
3671 /*
3672 ** This is only setting null state. (I think?)
3673 */
3674
3675 if (ctype_isUA (ct))
3676 {
3677 uentry te = usymtab_getTypeEntrySafe (ctype_typeId (ct));
3678
3679 if (uentry_isValid (te))
3680 {
3681 sRef_setStateFromUentry (e->sref, te);
3682 }
3683 else
3684 {
3685 /* problem for recursive type definitions */
3686 }
3687 }
3688
3689 sRef_setAliasKind (e->sref, ak, loc);
3690 sRef_setExKind (e->sref, exp, loc);
3691
3692 sRef_setDefState (e->sref, defstate, loc);
3693
3694 if (ynm_isOn (abs) && ctype_isUnknown (ct) && isnull == NS_UNKNOWN)
3695 {
3696 isnull = NS_ABSNULL;
3697 }
3698
3699 sRef_mergeNullState (e->sref, isnull);
3700
3701 e->whereDefined = fileloc_copy (loc); /*< bogus! (but necessary for lexer) >*/
3702
3703 if (fileloc_isSpec (loc))
3704 {
3705 e->whereSpecified = loc;
3706 e->whereDeclared = fileloc_undefined;
3707 }
3708 else
3709 {
3710 e->whereSpecified = fileloc_undefined;
3711 e->whereDeclared = loc;
3712 }
3713
3714 e->isPrivate = FALSE;
3715 e->hasNameError = FALSE;
3716
3717 e->used = FALSE;
3718 e->lset = FALSE;
3719 e->uses = filelocList_new ();
3720
3721 e->info = (uinfo) dmalloc (sizeof (*e->info));
3722 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
3723 e->info->datatype->abs = abs;
3724 e->info->datatype->mut = mut;
3725 e->info->datatype->type = rtype;
3726
3727 sRef_storeState (e->sref);
3728
3729 return (e);
3730}
3731
3732# ifndef NOLCL
3733static void uentry_setHasGlobs (uentry ue)
3734{
3735 llassert (uentry_isFunction (ue));
3736
3737 ue->info->fcn->hasGlobs = TRUE;
3738}
3739
3740static void uentry_setHasMods (uentry ue)
3741{
3742 llassert (uentry_isFunction (ue));
3743
3744 ue->info->fcn->hasMods = TRUE;
3745}
3746# endif
3747
3748bool uentry_hasGlobs (uentry ue)
3749{
3750 if (uentry_isFunction (ue))
3751 {
3752 return (ue->info->fcn->hasGlobs);
3753 }
3754
3755 return FALSE;
3756}
3757
3758bool uentry_hasSpecialClauses (uentry ue)
3759{
a0a162cd 3760 return (uentry_isFunction (ue) && specialClauses_isDefined (ue->info->fcn->specclauses));
885824d3 3761}
3762
3763specialClauses uentry_getSpecialClauses (uentry ue)
3764{
3765 llassert (uentry_isFunction (ue));
3766 return ue->info->fcn->specclauses;
3767}
3768
3769bool uentry_hasMods (uentry ue)
3770{
3771 if (uentry_isFunction (ue))
3772 {
3773 return (ue->info->fcn->hasMods);
3774 }
3775
3776 return FALSE;
3777}
3778
3779static uentry
3780 uentry_makeFunctionBase (/*@only@*/ cstring name, ctype ct,
3781 typeIdSet access,
3782 bool hasGlobs, /*@only@*/ globSet globs,
3783 bool hasMods, /*@only@*/ sRefSet mods,
3784 alkind ak, exkind exp,
3785 sstate defstate, nstate isnull,
3786 exitkind exitCode,
3787 specCode sCode,
3788 qual nullPred,
3789 /*@only@*/ specialClauses specclauses,
3790 /*@only@*/ fileloc loc)
3791{
3792 uentry e = uentry_alloc ();
3793 ctype ret;
3794
3795 /* e->shallowCopy = FALSE; */
3796 e->ukind = KFCN;
3797 e->uname = name;
3798 e->utype = ct;
3799 e->storageclass = SCNONE;
3800
3801 if (ctype_isFunction (ct))
3802 {
3803 ret = ctype_returnValue (ct);
3804 }
3805 else
3806 {
3807 if (ctype_isKnown (ct))
3808 {
3809 llbug (message ("not function: %s", ctype_unparse (ct)));
3810 }
3811
3812 ret = ctype_unknown;
3813 }
3814
3815 e->sref = sRef_makeType (ret);
3816
3817 if (ctype_isUA (ret))
3818 {
3819 sRef_setStateFromType (e->sref, ret);
3820 }
3821
3822 sRef_setDefined (e->sref, loc);
3823 sRef_setNullState (e->sref, isnull, loc);
3824
3825 sRef_setAliasKind (e->sref, ak, loc);
3826 sRef_setExKind (e->sref, exp, loc);
3827 sRef_setDefState (e->sref, defstate, loc);
3828
3829 e->whereSpecified = loc;
3830 e->whereDefined = fileloc_undefined;
3831
3832 e->isPrivate = FALSE;
3833 e->hasNameError = FALSE;
3834
3835 e->used = FALSE;
3836 e->lset = FALSE;
3837 e->uses = filelocList_new ();
3838
3839 e->info = (uinfo) dmalloc (sizeof (*e->info));
3840 e->info->fcn = (ufinfo) dmalloc (sizeof (*e->info->fcn));
3841
3842 e->info->fcn->exitCode = exitCode;
3843 e->info->fcn->specialCode = sCode;
3844 e->info->fcn->nullPred = nullPred;
3845 e->info->fcn->access = access;
3846
3847 e->info->fcn->specclauses = specclauses;
3848 e->info->fcn->hasGlobs = hasGlobs;
3849 e->info->fcn->globs = globs;
3850
3851 e->info->fcn->hasMods = hasMods;
3852 e->info->fcn->mods = mods;
3853
3854 e->info->fcn->defparams = uentryList_undefined;
3855 e->whereDeclared = fileloc_undefined;
3856
3857 sRef_storeState (e->sref);
3858
3859 return (e);
3860}
3861
3862static /*@only@*/ uentry
3863 uentry_makeTagBase (/*@only@*/ cstring name, ekind tagkind,
3864 ctype ct, ctype rtype, /*@only@*/ fileloc loc)
3865{
3866 uentry e = uentry_alloc ();
3867
3868 if (tagkind != KSTRUCTTAG && tagkind != KUNIONTAG && tagkind != KENUMTAG)
3869 {
3870 llbuglit ("uentry_makeTagBase: not a tag type");
3871 }
3872
3873 /* e->shallowCopy = FALSE; */
3874 e->ukind = tagkind;
3875 e->uname = name;
3876 e->utype = ct;
3877 e->sref = sRef_makeUnknown ();
3878 e->storageclass = SCNONE;
3879
3880 if (fileloc_isSpec (loc))
3881 {
3882 e->whereSpecified = loc;
3883 e->whereDeclared = fileloc_undefined;
3884 }
3885 else
3886 {
3887 e->whereDeclared = loc;
3888 e->whereSpecified = fileloc_undefined;
3889 }
3890
3891 e->whereDefined = fileloc_undefined;
3892
3893 e->isPrivate = FALSE;
3894 e->hasNameError = FALSE;
3895
3896 e->used = FALSE;
3897 e->lset = FALSE;
3898 e->uses = filelocList_new ();
3899
3900 e->info = (uinfo) dmalloc (sizeof (*e->info));
3901 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
3902 e->info->datatype->abs = NO;
3903 e->info->datatype->mut = MAYBE;
3904 e->info->datatype->type = rtype;
3905
3906 sRef_storeState (e->sref);
3907
3908 return (e);
3909}
3910
3911static uentry
3912 uentry_makeIterBase (/*@only@*/ cstring name, typeIdSet access,
3913 ctype ct, /*@only@*/ fileloc loc)
3914{
3915 uentry e = uentry_alloc ();
3916
3917 /* e->shallowCopy = FALSE; */
3918 e->ukind = KITER;
3919 e->uname = name;
3920 e->utype = ct;
3921 e->sref = sRef_makeUnknown ();
3922 e->storageclass = SCNONE;
3923
3924 if (fileloc_isSpec (loc))
3925 {
3926 e->whereSpecified = loc;
3927 e->whereDeclared = fileloc_undefined;
3928 }
3929 else
3930 {
3931 e->whereDeclared = loc;
3932 e->whereSpecified = fileloc_undefined;
3933 }
3934
3935 e->whereDefined = fileloc_undefined;
3936
3937 e->isPrivate = FALSE;
3938 e->hasNameError = FALSE;
3939
3940 e->used = FALSE;
3941 e->lset = FALSE;
3942 e->uses = filelocList_new ();
3943
3944 e->info = (uinfo) dmalloc (sizeof (*e->info));
3945 e->info->iter = (uiinfo) dmalloc (sizeof (*e->info->iter));
3946 e->info->iter->access = access;
3947 e->info->iter->mods = sRefSet_undefined;
3948 e->info->iter->globs = globSet_undefined;
3949
3950 sRef_storeState (e->sref);
3951 return (e);
3952}
3953
3954static uentry
3955 uentry_makeEndIterBase (/*@only@*/ cstring name, typeIdSet access,
3956 /*@only@*/ fileloc loc)
3957{
3958 uentry e = uentry_alloc ();
3959
3960 /* e->shallowCopy = FALSE; */
3961 e->ukind = KENDITER;
3962 e->storageclass = SCNONE;
3963 e->uname = name;
3964 e->utype = ctype_unknown;
3965 e->sref = sRef_makeUnknown ();
3966
3967 if (fileloc_isSpec (loc))
3968 {
3969 e->whereSpecified = loc;
3970 e->whereDeclared = fileloc_undefined;
3971 }
3972 else
3973 {
3974 e->whereDeclared = loc;
3975 e->whereSpecified = fileloc_undefined;
3976 }
3977
3978 e->whereDefined = fileloc_undefined;
3979
3980 e->isPrivate = FALSE;
3981 e->hasNameError = FALSE;
3982
3983 e->used = FALSE;
3984 e->lset = FALSE;
3985 e->uses = filelocList_new ();
3986
3987 e->info = (uinfo) dmalloc (sizeof (*e->info));
3988 e->info->enditer = (ueinfo) dmalloc (sizeof (*e->info->enditer));
3989 e->info->enditer->access = access;
3990 sRef_storeState (e->sref);
3991
3992 return (e);
3993}
3994
3995void uentry_markFree (/*@unused@*/ /*@owned@*/ uentry u)
3996{
3997 /* should save u */
3998/*@-mustfree@*/
3999}
4000/*@=mustfree@*/
4001
4002/*@only@*/ uentry
4003uentry_undump (ekind kind, fileloc loc, char **s)
4004{
4005 uentry ue;
4006
4007 if (**s == '!')
4008 {
4009 checkChar (s, '!');
4010 checkChar (s, '.');
4011 ue = uentry_makeElipsisMarker ();
4012 }
4013 else
4014 {
4015 ctype ct = ctype_undump (s);
4016 cstring name;
4017
4018 switch (kind)
4019 {
4020 case KVAR:
4021 {
4022 vkind tkind;
4023 sstate defstate;
4024 nstate isnull;
4025 alkind aliased;
4026 exkind exp;
4027 chkind checked;
4028
4029 checkChar (s, '|');
4030
4031 if (optCheckChar (s, '@'))
4032 {
4033 tkind = vkind_fromInt (getInt (s));
4034 checkChar (s, '|');
4035 }
4036 else
4037 {
4038 tkind = VKPARAM;
4039 }
4040
4041 if (optCheckChar (s, '$'))
4042 {
4043 defstate = SS_UNKNOWN;
4044 isnull = NS_UNKNOWN;
4045 aliased = AK_IMPTEMP;
4046 exp = XO_UNKNOWN;
4047 checked = CH_UNKNOWN;
4048 }
4049 else if (optCheckChar (s, '&'))
4050 {
4051 defstate = SS_DEFINED;
4052 isnull = NS_UNKNOWN;
4053 aliased = AK_IMPTEMP;
4054 exp = XO_UNKNOWN;
4055 checked = CH_UNKNOWN;
4056 }
4057 else if (optCheckChar (s, '^'))
4058 {
4059 defstate = SS_UNKNOWN;
4060 isnull = NS_UNKNOWN;
4061 aliased = AK_IMPTEMP;
4062 exp = XO_UNKNOWN;
4063 checked = CH_UNKNOWN;
4064 }
4065 else
4066 {
4067 defstate = sstate_fromInt (getInt (s));
4068 advanceField (s); isnull = nstate_fromInt (getInt (s));
4069 advanceField (s); aliased = alkind_fromInt (getInt (s));
4070
4071 if (optCheckChar (s, '&'))
4072 {
4073 exp = XO_UNKNOWN;
4074 checked = CH_UNKNOWN;
4075 }
4076 else
4077 {
4078 advanceField (s); exp = exkind_fromInt (getInt (s));
4079 advanceField (s); checked = (chkind) (getInt (s));
4080 }
4081 }
4082
4083 advanceName (s);
4084 name = getStringWord (s);
4085
4086 ue = uentry_makeVariableBase (name, ct, tkind, defstate,
4087 isnull, aliased, exp,
4088 checked, fileloc_copy (loc));
4089 }
4090 break;
4091 case KDATATYPE:
4092 {
4093 ynm abs;
4094 ynm mut;
4095 ctype rtype;
4096 sstate defstate;
4097 nstate isnull;
4098 alkind aliased;
4099 exkind exp;
4100
4101 advanceField (s); abs = ynm_fromCodeChar (loadChar (s));
4102 advanceField (s); mut = ynm_fromCodeChar (loadChar (s));
4103 advanceField (s); defstate = sstate_fromInt (getInt (s));
4104 advanceField (s); isnull = nstate_fromInt (getInt (s));
4105 advanceField (s); aliased = alkind_fromInt (getInt (s));
4106 advanceField (s); exp = exkind_fromInt (getInt (s));
4107 advanceField (s); rtype = ctype_undump (s);
4108 advanceName (s);
4109 name = getStringWord (s);
4110
4111 ue = uentry_makeDatatypeBase (name, ct, abs, mut, rtype,
4112 aliased, exp, defstate, isnull,
4113 fileloc_copy (loc));
4114 }
4115 break;
4116 case KFCN:
4117 {
4118 alkind ak;
4119 exkind exp;
4120 sstate defstate;
4121 nstate isnull;
4122 exitkind exitCode;
4123 specCode specc;
4124 qual nullPred;
4125 typeIdSet access;
4126 bool hasGlobs;
4127 globSet globs;
4128 bool hasMods;
4129 sRefSet mods;
4130 specialClauses specclauses;
4131
4132 if (optCheckChar (s, '$'))
4133 {
4134 defstate = SS_DEFINED;
4135 isnull = NS_UNKNOWN;
4136 exitCode = XK_UNKNOWN;
4137 specc = SPC_NONE;
4138 nullPred = QU_UNKNOWN;
4139 }
4140 else
4141 {
4142 advanceField (s); defstate = sstate_fromInt (getInt (s));
4143 advanceField (s); isnull = nstate_fromInt (getInt (s));
4144 advanceField (s); exitCode = exitkind_fromInt (getInt (s));
4145 advanceField (s); specc = specCode_fromInt (getInt (s));
4146 advanceField (s); nullPred = qual_fromInt (getInt (s));
4147 }
4148
4149 if (optCheckChar (s, '$'))
4150 {
4151 hasGlobs = FALSE;
4152 globs = globSet_undefined;
4153 hasMods = FALSE;
4154 mods = sRefSet_undefined;
4155 }
4156 else if (optCheckChar (s, '^'))
4157 {
4158 hasGlobs = TRUE;
4159 globs = globSet_undefined;
4160 hasMods = TRUE;
4161 mods = sRefSet_undefined;
4162 }
4163 else
4164 {
4165 advanceField (s); hasGlobs = bool_fromInt (getInt (s));
4166 advanceField (s); globs = globSet_undump (s);
4167 advanceField (s); hasMods = bool_fromInt (getInt (s));
4168 advanceField (s); mods = sRefSet_undump (s);
4169 }
4170
4171 if (optCheckChar (s, '$'))
4172 {
4173 ak = AK_UNKNOWN;
4174 exp = XO_UNKNOWN;
4175 }
4176 else
4177 {
4178 advanceField (s); ak = alkind_fromInt (getInt (s));
4179 advanceField (s); exp = exkind_fromInt (getInt (s));
4180 }
4181
4182 advanceField (s); access = typeIdSet_undump (s);
4183
4184 if (optCheckChar (s, '@'))
4185 {
4186 specclauses = specialClauses_undump (s);
4187 }
4188 else
4189 {
4190 specclauses = specialClauses_undefined;
4191 }
4192
4193 advanceName (s); name = getStringWord (s);
4194
4195 ue = uentry_makeFunctionBase (name, ct, access,
4196 hasGlobs, globs,
4197 hasMods, mods,
4198 ak, exp, defstate, isnull,
4199 exitCode, specc, nullPred,
4200 specclauses,
4201 fileloc_copy (loc));
4202 DPRINTF (("Undump: %s", uentry_unparse (ue)));
4203 }
4204 break;
4205 case KITER:
4206 {
4207 typeIdSet access;
4208
4209 advanceField (s); access = typeIdSet_undump (s);
4210 advanceName (s); name = getStringWord (s);
4211
4212 ue = uentry_makeIterBase (name, access, ct,
4213 fileloc_copy (loc));
4214 }
4215 break;
4216 case KENDITER:
4217 {
4218 typeIdSet access;
4219
4220 advanceField (s); access = typeIdSet_undump (s);
4221 advanceName (s); name = getStringWord (s);
4222
4223 ue = uentry_makeEndIterBase (name, access, fileloc_copy (loc));
4224 }
4225 break;
4226 case KENUMCONST:
4227 case KCONST:
4228 {
4229 typeIdSet access;
4230 multiVal val;
4231 nstate nullstate;
4232
4233 if (optCheckChar (s, '$'))
4234 {
4235 val = multiVal_undefined;
4236 access = typeIdSet_undefined;
4237 nullstate = NS_UNKNOWN;
4238 }
4239 else
4240 {
4241 advanceField (s); val = multiVal_undump (s);
4242 advanceField (s); access = typeIdSet_undump (s);
4243 advanceField (s); nullstate = nstate_fromInt (getInt (s));
4244 }
4245
4246 advanceName (s); name = getStringWord (s);
4247
4248 ue = uentry_makeConstantBase (name, ct, access,
4249 nullstate, fileloc_copy (loc), val);
4250 break;
4251 }
4252 case KSTRUCTTAG:
4253 case KUNIONTAG:
4254 case KENUMTAG:
4255 {
4256 ctype rtype;
4257
4258 advanceField (s); rtype = ctype_undump (s);
4259 advanceName (s); name = getStringWord (s);
4260 ue = uentry_makeTagBase (name, kind, ct, rtype, fileloc_copy (loc));
4261 }
4262 break;
4263 case KINVALID:
4264 llcontbuglit ("uentry_undump: invalid");
4265 ue = uentry_undefined;
4266 break;
4267 case KELIPSMARKER:
4268 llcontbuglit ("uentry_undump: elips marker");
4269 ue = uentry_undefined;
4270 break;
4271 }
4272 }
4273
4274 return (ue);
4275}
4276
4277cstring
4278uentry_dump (uentry v)
4279{
4280 return (uentry_dumpAux (v, FALSE));
4281}
4282
4283cstring
4284uentry_dumpParam (uentry v)
4285{
4286 llassertprint (uentry_isVariable (v) || uentry_isElipsisMarker (v),
4287 ("dump: %s", uentry_unparseFull (v)));
4288
4289 return (uentry_dumpAux (v, TRUE));
4290}
4291
4292static cstring
4293uentry_dumpAux (uentry v, bool isParam)
4294{
4295 llassert (uentry_isValid (v));
4296
a0a162cd 4297 DPRINTF (("Dumping entry: %s", uentry_unparseFull (v)));
4298
885824d3 4299 switch (v->ukind)
4300 {
4301 case KINVALID:
4302 llcontbuglit ("uentry_dump: invalid entry");
4303 return cstring_undefined;
4304 case KELIPSMARKER:
4305 return (message ("!."));
4306 case KVAR:
4307 {
4308 cstring sdump;
4309 vkind vk = v->info->var->kind;
4310 sstate dss = sRef_getDefState (v->sref);
4311 nstate nst = sRef_getNullState (v->sref);
4312 alkind alk = sRef_getAliasKind (v->sref);
4313 exkind exk = sRef_getExKind (v->sref);
4314 chkind chk = v->info->var->checked;
4315
a0a162cd 4316 DPRINTF (("Dumping var"));
4317
885824d3 4318 if (dss == SS_UNKNOWN
4319 && nst == NS_UNKNOWN
4320 && alk == AK_IMPTEMP
4321 && exk == XO_UNKNOWN
4322 && chk == CH_UNKNOWN)
4323 {
4324 sdump = cstring_makeLiteral ("$");
4325 }
4326 else if (dss == SS_DEFINED
4327 && nst == NS_UNKNOWN
4328 && alk == AK_IMPTEMP
4329 && exk == XO_UNKNOWN
4330 && chk == CH_UNKNOWN)
4331 {
4332 sdump = cstring_makeLiteral ("&");
4333 }
4334 else if (dss == SS_UNKNOWN
4335 && nst == NS_UNKNOWN
4336 && alk == AK_UNKNOWN
4337 && exk == XO_UNKNOWN
4338 && chk == CH_UNKNOWN)
4339 {
4340 sdump = cstring_makeLiteral ("^");
4341 }
4342 else if (exk == XO_UNKNOWN
4343 && chk == CH_UNKNOWN)
4344 {
4345 sdump = message ("%d@%d@%d&",
4346 (int) dss,
4347 (int) nst,
4348 (int) alk);
4349 }
4350 else
4351 {
4352 sdump = message ("%d@%d@%d@%d@%d",
4353 (int) dss,
4354 (int) nst,
4355 (int) alk,
4356 (int) exk,
4357 (int) chk);
4358 }
4359
4360
4361 if (vk != VKPARAM)
4362 {
4363 return (message ("%q|@%d|%q#%s",
4364 ctype_dump (v->utype),
4365 (int) vk,
4366 sdump,
4367 isParam ? cstring_undefined : v->uname));
4368 }
4369 else
4370 {
4371 return (message ("%q|%q#%s",
4372 ctype_dump (v->utype),
4373 sdump,
4374 isParam ? cstring_undefined : v->uname));
4375 }
4376
4377 }
4378 case KDATATYPE:
4379 return (message ("%q@%s@%s@%d@%d@%d@%d@%q#%s",
4380 ctype_dump (v->utype),
4381 ynm_unparseCode (v->info->datatype->abs),
4382 ynm_unparseCode (v->info->datatype->mut),
4383 (int) sRef_getDefState (v->sref),
4384 (int) sRef_getNullState (v->sref),
4385 (int) sRef_getAliasKind (v->sref),
4386 (int) sRef_getExKind (v->sref),
4387 ctype_dump (v->info->datatype->type),
4388 v->uname));
4389 case KFCN:
4390 {
4391 cstring sdump, gdump, adump;
4392 alkind alk = sRef_getAliasKind (v->sref);
4393 exkind exk = sRef_getExKind (v->sref);
4394
4395 if (sRef_getDefState (v->sref) == SS_DEFINED
4396 && !nstate_isKnown (sRef_getNullState (v->sref))
4397 && !exitkind_isKnown (v->info->fcn->exitCode)
4398 && v->info->fcn->specialCode == SPC_NONE
4399 && v->info->fcn->nullPred == QU_UNKNOWN)
4400 {
4401 sdump = cstring_makeLiteral ("$");
4402 }
4403 else
4404 {
4405 sdump = message ("@%d@%d@%d@%d@%d",
4406 (int) sRef_getDefState (v->sref),
4407 (int) sRef_getNullState (v->sref),
4408 (int) v->info->fcn->exitCode,
4409 (int) v->info->fcn->specialCode,
4410 (int) v->info->fcn->nullPred);
4411 }
4412
4413 if (!uentry_hasGlobs(v) && !uentry_hasMods (v))
4414 {
4415 gdump = cstring_makeLiteral ("$");
4416 }
4417 else if (uentry_hasGlobs (v) && globSet_isEmpty (uentry_getGlobs (v))
4418 && uentry_hasMods (v) && sRefSet_isEmpty (uentry_getMods (v)))
4419 {
4420 gdump = cstring_makeLiteral ("^");
4421 }
4422 else
4423 {
4424 gdump = message ("@%s@%q@%s@%q",
4425 bool_dump (uentry_hasGlobs (v)),
4426 globSet_dump (uentry_getGlobs (v)),
4427 bool_dump (uentry_hasMods (v)),
4428 sRefSet_dump (uentry_getMods (v)));
4429 }
4430
4431 if (alk == AK_UNKNOWN && exk == XO_UNKNOWN)
4432 {
4433 adump = cstring_makeLiteral ("$");
4434 }
4435 else
4436 {
4437 adump = message ("@%d@%d", (int) alk, (int) exk);
4438 }
4439
4440 if (uentry_hasSpecialClauses (v))
4441 {
4442 return (message ("%q%q%q%q@%q@%q#%s",
4443 ctype_dump (v->utype),
4444 sdump,
4445 gdump,
4446 adump,
4447 typeIdSet_dump (uentry_accessType (v)),
4448 specialClauses_dump (v->info->fcn->specclauses),
4449 v->uname));
4450 }
4451 else
4452 {
4453 return (message ("%q%q%q%q@%q#%s",
4454 ctype_dump (v->utype),
4455 sdump,
4456 gdump,
4457 adump,
4458 typeIdSet_dump (uentry_accessType (v)),
4459 v->uname));
4460 }
4461 }
4462 case KITER:
4463 return (message ("%q@%q#%s",
4464 ctype_dump (v->utype),
4465 typeIdSet_dump (v->info->iter->access),
4466 v->uname));
4467 case KENDITER:
4468 return (message ("%q@%q#%s",
4469 ctype_dump (v->utype),
4470 typeIdSet_dump (uentry_accessType (v)),
4471 v->uname));
4472 case KENUMCONST:
4473 case KCONST:
4474 {
4475 cstring sdump;
4476
4477 if (multiVal_isUnknown (v->info->uconst->val)
4478 && typeIdSet_isEmpty (uentry_accessType (v))
4479 && (sRef_getNullState (v->sref) == NS_UNKNOWN))
4480 {
4481 sdump = cstring_makeLiteral ("$");
4482 }
4483 else
4484 {
4485 sdump = message ("@%q@%q@%d",
4486 multiVal_dump (v->info->uconst->val),
4487 typeIdSet_dump (uentry_accessType (v)),
4488 (int) sRef_getNullState (v->sref));
4489 }
4490
4491 return (message ("%q%q#%s",
4492 ctype_dump (v->utype),
4493 sdump,
4494 v->uname));
4495 }
4496 case KSTRUCTTAG:
4497 case KUNIONTAG:
4498 case KENUMTAG:
4499 return (message ("%q@%q#%s",
4500 ctype_dump (v->utype),
4501 ctype_dump (v->info->datatype->type), v->uname));
4502 }
4503
4504 BADEXIT;
4505}
4506
4507/*@only@*/ cstring
4508uentry_unparseAbbrev (uentry v)
4509{
4510 if (!uentry_isVariable (v))
4511 {
4512 llcontbuglit ("uentry_unparseAbbrev: not variable");
4513 return uentry_unparse (v);
4514 }
4515
4516 return (message ("%s %q", ctype_unparseDeep (v->utype), uentry_getName (v)));
4517}
4518
4519/*@only@*/ cstring
4520uentry_unparse (uentry v)
4521{
4522 cstring st;
4523
4524 if (uentry_isUndefined (v)) return (cstring_makeLiteral ("<undefined>"));
4525 if (uentry_isElipsisMarker (v)) return (cstring_makeLiteral ("..."));
4526
4527 st = uentry_getName (v);
4528
4529 if (cstring_isDefined (st))
4530 {
4531 return (ctype_unparseDeclaration (v->utype, st));
4532 }
4533 else
4534 {
4535 cstring_free (st);
4536 return (cstring_copy (ctype_unparse (v->utype)));
4537 }
4538}
4539
4540/*@only@*/ cstring
4541uentry_unparseFull (uentry v)
4542{
4543 if (uentry_isUndefined (v))
4544 {
4545 return (cstring_makeLiteral ("<undefined>"));
4546 }
4547 else if (uentry_isDatatype (v))
4548 {
4549 return (message ("[%d] [%s] %s %q : %t [%t] %s %s // %q [s: %q; d: %q]",
4550 (int) v,
4551 ekind_unparse (v->ukind),
4552 v->uname,
4553 uentry_getName (v),
4554 v->utype,
4555 ctype_isDefined (v->info->datatype->type)
4556 ? v->info->datatype->type : ctype_unknown,
4557 ynm_unparse (v->info->datatype->mut),
4558 ynm_unparse (v->info->datatype->abs),
4559 sRef_unparseState (v->sref),
4560 fileloc_unparse (v->whereSpecified),
4561 fileloc_unparse (v->whereDefined)));
4562 }
4563 else if (uentry_isFunction (v))
4564 {
4565 return (message ("[%w] = [%s] %q : %t / sref: %q / mods: %q / "
4566 "globs: %q / [s: %q; decl: %q; def: %q]",
4567 (long unsigned) v,
4568 ekind_unparse (v->ukind),
4569 uentry_getName (v),
4570 v->utype,
4571 sRef_unparseFull (v->sref),
4572 sRefSet_unparse (v->info->fcn->mods),
4573 globSet_unparse (v->info->fcn->globs),
4574 fileloc_unparse (v->whereSpecified),
4575 fileloc_unparse (v->whereDeclared),
4576 fileloc_unparse (v->whereDefined)));
4577 }
4578 else if (uentry_isIter (v))
4579 {
4580 return (message ("[%s] %q: %t / %q [s: %q; d: %q]",
4581 ekind_unparse (v->ukind),
4582 uentry_getName (v),
4583 v->utype,
4584 sRef_unparseFull (v->sref),
4585 fileloc_unparse (v->whereSpecified),
4586 fileloc_unparse (v->whereDefined)));
4587 }
4588 else if (uentry_isVariable (v))
4589 {
4590 return
4591 (message ("[check: %s] / [%w] = [%s] %s : %t %q [s: %q; def: %q; dec: %q] "
4592 "kind <%d> isout <%d> used <%d>",
4593 checkedName (v->info->var->checked),
4594 (long unsigned) v,
4595 ekind_unparse (v->ukind),
4596 v->uname,
4597 v->utype,
4598 sRef_unparseDeep (v->sref),
4599 fileloc_unparse (v->whereSpecified),
4600 fileloc_unparse (v->whereDefined),
4601 fileloc_unparse (v->whereDeclared),
4602 (int) v->info->var->kind,
4603 (int) v->info->var->defstate,
4604 (int) v->used));
4605 }
4606 else
4607 {
4608 return (message ("[%s] %s : %t %q at [s: %q; d: %q]",
4609 ekind_unparse (v->ukind),
4610 v->uname,
4611 v->utype,
4612 sRef_unparseFull (v->sref),
4613 fileloc_unparse (v->whereSpecified),
4614 fileloc_unparse (v->whereDefined)));
4615
4616 }
4617}
4618
4619bool uentry_hasAccessType (uentry e)
4620{
4621 if (uentry_isValid (e))
4622 {
4623 switch (e->ukind)
4624 {
4625 case KITER:
4626 return (!typeIdSet_isEmpty (e->info->iter->access));
4627 case KENDITER:
4628 return (!typeIdSet_isEmpty (e->info->enditer->access));
4629 case KFCN:
4630 return (!typeIdSet_isEmpty (e->info->fcn->access));
4631 case KENUMCONST:
4632 case KCONST:
4633 return (!typeIdSet_isEmpty (e->info->uconst->access));
4634 default:
4635 return FALSE;
4636 }
4637 }
4638
4639 return FALSE;
4640}
4641
4642typeIdSet uentry_accessType (uentry e)
4643{
4644 if (uentry_isValid (e))
4645 {
4646 switch (e->ukind)
4647 {
4648 case KITER:
4649 return (e->info->iter->access);
4650 case KENDITER:
4651 return (e->info->enditer->access);
4652 case KFCN:
4653 return (e->info->fcn->access);
4654 case KENUMCONST:
4655 case KCONST:
4656 return (e->info->uconst->access);
4657 default:
4658 break;
4659 }
4660 }
4661
4662 return typeIdSet_undefined;
4663}
4664
4665bool
4666uentry_isVariable (uentry e)
4667{
4668 return (uentry_isVar (e));
4669}
4670
4671bool
4672uentry_isSpecified (uentry e)
4673{
4674 return (uentry_isValid (e) && !fileloc_isUndefined (e->whereSpecified));
4675}
4676
4677static bool
4678uentry_isReallySpecified (uentry e)
4679{
4680 return (uentry_isValid (e)
4681 && fileloc_isRealSpec (e->whereSpecified));
4682}
4683
4684bool
4685uentry_isVar (uentry e)
4686{
4687 return (!uentry_isUndefined (e) && e->ukind == KVAR);
4688}
4689
4690bool
4691uentry_isFakeTag (uentry e)
4692{
4693 return (uentry_isValid (e) && strchr (cstring_toCharsSafe (e->uname), '!') != 0);
4694}
4695
4696bool
4697uentry_isDatatype (uentry e)
4698{
4699 return (!uentry_isUndefined (e) &&
4700 (e->ukind == KDATATYPE || e->ukind == KSTRUCTTAG ||
4701 e->ukind == KUNIONTAG || e->ukind == KENUMTAG));
4702}
4703
4704void
4705uentry_setAbstract (uentry e)
4706{
4707 typeId oldid;
4708
4709 llassert (uentry_isDatatype (e)
4710 && (ynm_isMaybe (e->info->datatype->abs)));
4711
4712 oldid = ctype_typeId (e->info->datatype->type);
4713 e->info->datatype->abs = YES;
4714 e->info->datatype->type = ctype_createAbstract (oldid);
4715}
4716
4717void
4718uentry_setConcrete (uentry e)
4719{
4720 llassert (uentry_isDatatype (e)
4721 && (ynm_isMaybe (e->info->datatype->abs)));
4722
4723 e->info->datatype->abs = NO;
4724}
4725
4726bool
4727uentry_isAbstractDatatype (uentry e)
4728{
4729 return (uentry_isDatatype (e)
4730 && (ynm_isOn (e->info->datatype->abs)));
4731}
4732
4733bool
4734uentry_isMaybeAbstract (uentry e)
4735{
4736 return (uentry_isDatatype (e)
4737 && (ynm_isMaybe (e->info->datatype->abs)));
4738}
4739
4740bool
4741uentry_isMutableDatatype (uentry e)
4742{
4743 bool res = uentry_isDatatype (e)
4744 && (ynm_toBoolRelaxed (e->info->datatype->mut));
4745
4746 return res;
4747}
4748
4749bool
4750uentry_isRefCountedDatatype (uentry e)
4751{
4752 return (uentry_isDatatype (e) && (sRef_isRefCounted (uentry_getSref (e))));
4753}
4754
4755bool
4756uentry_isParam (uentry u)
4757{
4758 return (uentry_isVariable (u) && (u->info->var->kind == VKPARAM
4759 || u->info->var->kind == VKYIELDPARAM));
4760}
4761
4762bool
4763uentry_isExpandedMacro (uentry u)
4764{
4765 return (uentry_isVariable (u) && (u->info->var->kind == VKEXPMACRO));
4766}
4767
4768bool
4769uentry_isSefParam (uentry u)
4770{
4771 return (uentry_isVariable (u)
4772 && (u->info->var->kind == VKSEFPARAM
4773 || u->info->var->kind == VKREFSEFPARAM
4774 || u->info->var->kind == VKSEFRETPARAM
4775 || u->info->var->kind == VKREFSEFRETPARAM));
4776}
4777
4778bool
4779uentry_isRefParam (uentry u)
4780{
4781 return (uentry_isVariable (u)
4782 && (u->info->var->kind == VKREFPARAM
4783 || u->info->var->kind == VKREFYIELDPARAM
4784 || u->info->var->kind == VKREFSEFPARAM
4785 || u->info->var->kind == VKREFSEFRETPARAM));
4786}
4787
4788bool
4789uentry_isAnyParam (uentry u)
4790{
4791 return (uentry_isVariable (u)
4792 && ((u->info->var->kind == VKPARAM)
4793 || (u->info->var->kind == VKSEFPARAM)
4794 || (u->info->var->kind == VKYIELDPARAM)
4795 || (u->info->var->kind == VKRETPARAM)
4796 || (u->info->var->kind == VKSEFRETPARAM)));
4797}
4798
4799sstate
4800uentry_getDefState (uentry u)
4801{
4802 if (uentry_isValid (u))
4803 {
4804 return (sRef_getDefState (u->sref));
4805 }
4806 else
4807 {
4808 return (SS_UNKNOWN);
4809 }
4810}
4811
4812bool
4813uentry_isOut (uentry u)
4814{
4815 return ((uentry_isVariable (u) && (u->info->var->defstate == SS_ALLOCATED))
4816 || (uentry_isDatatype (u) && (sRef_isAllocated (u->sref))));
4817}
4818
4819bool
4820uentry_isPartial (uentry u)
4821{
4822 return ((uentry_isVariable (u) && (u->info->var->defstate == SS_PARTIAL))
4823 || (uentry_isDatatype (u) && (sRef_isAllocated (u->sref))));
4824}
4825
4826bool
4827uentry_isStateSpecial (uentry u)
4828{
4829 return ((uentry_isVariable (u)
4830 && (u->info->var->defstate == SS_SPECIAL))
4831 || (uentry_isValid (u) && sRef_isStateSpecial (u->sref)));
4832}
4833
4834exitkind uentry_getExitCode (uentry ue)
4835{
4836 if (uentry_isFunction (ue))
4837 {
4838 return ue->info->fcn->exitCode;
4839 }
4840 else
4841 {
4842 return XK_UNKNOWN;
4843 }
4844}
4845
4846qual
4847uentry_nullPred (uentry u)
4848{
4849 llassert (uentry_isRealFunction (u));
4850
4851 if (uentry_isFunction (u))
4852 {
4853 return (u->info->fcn->nullPred);
4854 }
4855 else
4856 {
4857 return QU_UNKNOWN;
4858 }
4859}
4860
4861bool
4862uentry_possiblyNull (uentry u)
4863{
4864 return ((uentry_isVariable (u) && (nstate_possiblyNull (u->info->var->nullstate)))
4865 || (uentry_isDatatype (u) && (sRef_possiblyNull (u->sref))));
4866}
4867
4868alkind
4869uentry_getAliasKind (uentry u)
4870{
4871 if (uentry_isValid (u))
4872 {
4873 return (sRef_getAliasKind (uentry_getSref (u)));
4874 }
4875 else
4876 {
4877 return AK_UNKNOWN;
4878 }
4879}
4880
4881exkind
4882uentry_getExpKind (uentry u)
4883{
4884 if (uentry_isValid (u))
4885 {
4886 return (sRef_getExKind (uentry_getSref (u)));
4887 }
4888 else
4889 {
4890 return XO_UNKNOWN;
4891 }
4892}
4893
4894bool
4895uentry_isIter (uentry e)
4896{
4897 return (!uentry_isUndefined (e) && e->ukind == KITER);
4898}
4899
4900bool
4901uentry_isEndIter (uentry e)
4902{
4903 return (!uentry_isUndefined (e) && e->ukind == KENDITER);
4904}
4905
4906bool
4907uentry_isRealFunction (uentry e)
4908{
4909 return (uentry_isFunction (e) ||
4910 (uentry_isVariable (e) && ctype_isFunction (uentry_getType (e))));
4911}
4912
4913bool
4914uentry_hasName (uentry e)
4915{
4916 if (uentry_isValid (e))
4917 {
4918 cstring s = e->uname;
4919
4920 return (!(cstring_isEmpty (s) || cstring_equalLit (s, "...")));
4921 }
4922 else
4923 {
4924 return FALSE;
4925 }
4926}
4927
4928bool uentry_hasRealName (uentry e)
4929{
4930 return (uentry_isValid (e) && cstring_isNonEmpty (e->uname));
4931}
4932
4933
4934/*@observer@*/ globSet
4935uentry_getGlobs (uentry l)
4936{
4937 if (uentry_isInvalid (l))
4938 {
4939 return globSet_undefined;
4940 }
4941
4942 if (l->ukind != KFCN)
4943 {
4944 if (l->ukind != KITER && l->ukind != KENDITER)
4945 {
4946 if (l->ukind == KVAR)
4947 {
4948 llbug (message ("Bad call to uentry_getGlobs (var): %q (%s)",
4949 uentry_unparse (l),
4950 ekind_unparse (l->ukind)));
4951 }
4952 else
4953 {
4954 llbug (message ("Bad call to uentry_getGlobs: %q (%s)",
4955 uentry_unparse (l),
4956 ekind_unparse (l->ukind)));
4957 }
4958 }
4959 return globSet_undefined;
4960 }
4961
4962 return l->info->fcn->globs;
4963}
4964
4965/*@observer@*/ sRefSet
4966uentry_getMods (uentry l)
4967{
4968 llassert (uentry_isValid (l));
4969
4970 if (l->ukind != KFCN && l->ukind != KITER && l->ukind != KENDITER)
4971 {
4972 llcontbug (message ("Bad call to uentry_getMods: %q", uentry_unparse (l)));
4973 return sRefSet_undefined;
4974 }
4975
4976 return l->info->fcn->mods;
4977}
4978
4979ekind
4980uentry_getKind (uentry e)
4981{
4982 llassert (uentry_isValid (e));
4983
4984 return (e->ukind);
4985}
4986
4987/*@observer@*/ multiVal uentry_getConstantValue (uentry e)
4988{
4989 llassert (uentry_isEitherConstant (e));
4990
4991 return (e->info->uconst->val);
4992}
4993
4994/*@observer@*/ uentryList
4995uentry_getParams (uentry l)
4996{
4997 if (uentry_isInvalid (l)) return uentryList_undefined;
4998
4999 switch (l->ukind)
5000 {
5001 case KFCN:
5002 case KITER:
5003 {
5004 ctype ct = l->utype;
5005
5006 if (ctype_isFunction (ct))
5007 {
5008 return (ctype_argsFunction (ct));
5009 }
5010 else
5011 {
5012 return uentryList_undefined;
5013 }
5014 }
5015 case KVAR:
5016 {
5017 ctype ct = l->utype;
5018
5019 llassert (ctype_isFunction (ct));
5020 return (ctype_argsFunction (ct));
5021 }
5022 BADDEFAULT;
5023 }
5024 BADEXIT;
5025}
5026
5027/*@observer@*/ cstring
5028uentry_rawName (uentry e)
5029{
5030 if (uentry_isValid (e))
5031 {
5032 return (e->uname);
5033 }
5034 else
5035 {
5036 return cstring_undefined;
5037 }
5038}
5039
5040static cstring
5041uentry_getOptName (uentry e)
5042{
5043 cstring s = uentry_getName (e);
5044
5045 if (cstring_isDefined (s))
5046 {
5047 s = cstring_appendChar (s, ' ');
5048 }
5049
5050 return s;
5051}
5052
5053/*@only@*/ cstring
5054uentry_getName (uentry e)
5055{
5056 cstring ret = cstring_undefined;
5057
5058 if (uentry_isValid (e))
5059 {
5060
5061 if (uentry_isAnyTag (e))
5062 {
5063 ret = fixTagName (e->uname);
5064 }
5065 else if (uentry_isAnyParam (e))
5066 {
5067 ret = cstring_copy (fixParamName (e->uname));
5068 }
5069 else
5070 {
5071 ret = cstring_copy (e->uname);
5072 }
5073 }
5074
5075 return ret;
5076}
5077
5078cstring uentry_getRealName (uentry e)
5079{
5080 if (uentry_isValid (e))
5081 {
5082 if (uentry_isAnyTag (e))
5083 {
5084 return (cstring_undefined);
5085 }
5086 else
5087 {
5088 return (e->uname);
5089 }
5090 }
5091 return cstring_undefined;
5092}
5093
5094ctype uentry_getType (uentry e)
5095{
5096 if (uentry_isValid (e))
5097 {
5098 return e->utype;
5099 }
5100 else
5101 {
5102 return ctype_unknown;
5103 }
5104}
5105
5106fileloc uentry_whereLast (uentry e)
5107{
5108 fileloc loc;
5109
5110 if (uentry_isInvalid (e))
5111 {
5112 return fileloc_undefined;
5113 }
5114
5115 loc = e->whereDefined;
5116
5117 if (fileloc_isValid (loc) && !fileloc_isExternal (loc))
5118 {
5119 return loc;
5120 }
5121
5122 loc = uentry_whereDeclared (e);
5123
5124 if (fileloc_isValid (loc) && !fileloc_isExternal (loc))
5125 {
5126 return loc;
5127 }
5128
5129 loc = uentry_whereSpecified (e);
5130 return loc;
5131}
5132
5133fileloc uentry_whereEither (uentry e)
5134{
5135 if (uentry_isInvalid (e)) return fileloc_undefined;
5136
5137 if (fileloc_isDefined (e->whereDefined)
5138 && !fileloc_isExternal (e->whereDefined))
5139 {
5140 return e->whereDefined;
5141 }
5142 else if (fileloc_isDefined (e->whereDeclared))
5143 {
5144 return e->whereDeclared;
5145 }
5146 else
5147 {
5148 return e->whereSpecified;
5149 }
5150}
5151
5152fileloc uentry_whereSpecified (uentry e)
5153{
5154 if (uentry_isInvalid (e)) return fileloc_undefined;
5155
5156 return (e->whereSpecified);
5157}
5158
5159fileloc uentry_whereDefined (uentry e)
5160{
5161 if (uentry_isInvalid (e)) return fileloc_undefined;
5162
5163 return (e->whereDefined);
5164}
5165
5166fileloc uentry_whereDeclared (uentry e)
5167{
5168 if (uentry_isInvalid (e)) return fileloc_undefined;
5169
5170 return (e->whereDeclared);
5171}
5172
5173/*@observer@*/ fileloc
5174uentry_whereEarliest (uentry e)
5175{
5176 if (uentry_isInvalid (e)) return fileloc_undefined;
5177
5178 if (fileloc_isDefined (e->whereSpecified))
5179 {
5180 return (e->whereSpecified);
5181 }
5182 else if (fileloc_isDefined (e->whereDeclared))
5183 {
5184 return (e->whereDeclared);
5185 }
5186 else
5187 {
5188 return e->whereDefined;
5189 }
5190}
5191
5192void
5193uentry_setFunctionDefined (uentry e, fileloc loc)
5194{
5195 if (uentry_isValid (e))
5196 {
5197 llassert (uentry_isFunction (e));
5198
5199 if (fileloc_isUndefined (e->whereDeclared))
5200 {
5201 e->whereDeclared = fileloc_update (e->whereDeclared, loc);
5202 }
5203
5204 if (!fileloc_isDefined (e->whereDefined))
5205 {
5206 e->whereDefined = fileloc_update (e->whereDefined, loc);
5207 }
5208 }
5209}
5210
5211void
5212uentry_setDeclDef (uentry e, fileloc f)
5213{
5214 uentry_setDeclared (e, f);
5215
5216 if (!uentry_isFunction (e)
5217 && !(uentry_isVariable (e) && uentry_isExtern (e)))
5218 {
5219 uentry_setDefined (e, f);
5220 }
5221}
5222
5223void
5224uentry_setDeclaredForce (uentry e, fileloc f)
5225{
5226 llassert (uentry_isValid (e));
5227 e->whereDeclared = fileloc_update (e->whereDeclared, f);
5228}
5229
5230void
5231uentry_setDeclaredForceOnly (uentry e, fileloc f)
5232{
5233 llassert (uentry_isValid (e));
5234 fileloc_free (e->whereDeclared);
5235 e->whereDeclared = f;
5236}
5237
5238void
5239uentry_setDeclaredOnly (uentry e, /*@only@*/ fileloc f)
5240{
5241 fileloc oldloc;
5242
5243 llassert (uentry_isValid (e));
5244 oldloc = e->whereDeclared;
5245
5246 if (fileloc_isDefined (oldloc))
5247 {
5248 if (fileloc_isLib (oldloc) || fileloc_isImport (oldloc))
5249 {
5250 e->whereDeclared = f;
5251 fileloc_free (oldloc);
5252 }
5253 else
5254 {
5255 fileloc_free (f);
5256 }
5257 }
5258 else
5259 {
5260 e->whereDeclared = f;
5261 fileloc_free (oldloc);
5262 }
5263}
5264
5265void
5266uentry_setDeclared (uentry e, fileloc f)
5267{
5268 fileloc oldloc;
5269
5270 llassert (uentry_isValid (e));
5271 oldloc = e->whereDeclared;
5272
5273 if (fileloc_isDefined (oldloc))
5274 {
5275 if (fileloc_isLib (oldloc) || fileloc_isImport (oldloc))
5276 {
5277 e->whereDeclared = fileloc_update (e->whereDeclared, f);
5278 }
5279 else
5280 {
5281 ;
5282 }
5283 }
5284 else
5285 {
5286 e->whereDeclared = fileloc_update (e->whereDeclared, f);
5287 }
5288}
5289
5290void
5291uentry_clearDefined (uentry e)
5292{
5293 if (uentry_isValid (e))
5294 {
5295 e->whereDefined = fileloc_update (e->whereDefined, fileloc_undefined);
5296 }
5297}
5298
5299void
5300uentry_setDefined (uentry e, fileloc f)
5301{
5302 fileloc oldloc;
5303
5304 llassert (uentry_isValid (e));
5305 oldloc = e->whereDefined;
5306
5307 if (fileloc_isDefined (oldloc))
5308 {
5309 if (fileloc_isLib (oldloc)
5310 || fileloc_isImport (oldloc)
5311 || fileloc_isBuiltin (oldloc)
5312 || fileloc_isPreproc (oldloc))
5313 {
5314 e->whereDefined = fileloc_update (e->whereDefined, f);
5315 }
5316 else
5317 {
5318 if (fileloc_equal (oldloc, f) || context_processingMacros ())
5319 {
5320 ; /* okay */
5321 }
5322 else
5323 {
5324 if (optgenerror (FLG_REDEF,
5325 message ("%s %q redefined",
5326 ekind_capName (e->ukind),
5327 uentry_getName (e)),
5328 f))
5329 {
5330 llgenindentmsg (message ("Previous definition of %q",
5331 uentry_getName (e)),
5332 e->whereDefined);
5333 }
5334 }
5335 }
5336 }
5337 else
5338 {
5339 e->whereDefined = fileloc_update (e->whereDefined, f);
5340 }
5341}
5342
5343bool
5344uentry_isCodeDefined (uentry e)
5345{
5346 return (uentry_isValid (e) && fileloc_isDefined (e->whereDefined));
5347}
5348
5349bool
5350uentry_isDeclared (uentry e)
5351{
5352 if (uentry_isValid (e))
5353 {
5354 return (fileloc_isDefined (e->whereDeclared));
5355 }
5356
5357 return FALSE;
5358}
5359
5360sRef uentry_getSref (uentry e)
5361{
5362 /* not true, used for functions too (but shouldn't be? */
5363 /* llassertprint (e->ukind == KVAR, ("uentry_getSref: not variable!")); */
5364
5365 if (uentry_isInvalid (e)) return sRef_undefined;
5366
5367 return (e->sref);
5368}
5369
5370sRef uentry_getOrigSref (uentry e)
5371{
5372 if (uentry_isValid (e))
5373 {
5374 sRef sr = sRef_copy (uentry_getSref (e));
5375
5376 sRef_resetState (sr);
5377 sRef_clearDerived (sr);
5378
5379 if (uentry_isVariable (e))
5380 {
5381 sRef_setDefState (sr, e->info->var->defstate, fileloc_undefined);
5382 sRef_setNullState (sr, e->info->var->nullstate, fileloc_undefined);
5383 }
5384
5385 return (sr);
5386 }
5387 else
5388 {
5389 return sRef_undefined;
5390 }
5391}
5392
5393/*
5394** requires: uentry e is not in a hashed symbol table
5395*/
5396
5397void
5398uentry_setName (uentry e, /*@only@*/ cstring n)
5399{
5400 llassert (uentry_isValid (e));
5401
5402 cstring_free (e->uname);
5403 e->uname = n;
5404}
5405
5406void
5407uentry_setType (uentry e, ctype t)
5408{
5409 if (uentry_isValid (e))
5410 {
5411 e->utype = t;
5412 sRef_setType (e->sref, t);
5413 }
5414}
5415
5416void
5417uentry_resetParams (uentry ue, /*@only@*/ uentryList pn)
5418{
5419 ctype rct;
5420 ctype rettype = ctype_unknown;
5421
5422 llassert (uentry_isValid (ue));
5423
5424 rct = ctype_realType (ue->utype);
5425
5426 if (uentry_isVariable (ue) && (ctype_isFunction (rct) || ctype_isUnknown (rct)))
5427 {
5428 uentry_makeVarFunction (ue);
5429 }
5430
5431 llassert (uentry_isFunction (ue));
5432
5433 if (ctype_isFunction (rct))
5434 {
5435 rettype = ctype_returnValue (rct);
5436 }
5437
5438 ue->utype = ctype_makeNFParamsFunction (rettype, pn);
5439}
5440
5441void
5442uentry_setRefParam (uentry e)
5443{
5444
5445 if (!uentry_isVar (e))
5446 {
5447 llbug (message ("uentry_setParam: not variable: %q", uentry_unparse (e)));
5448 }
5449 else
5450 {
5451 if (e->info->var->kind == VKSEFPARAM)
5452 {
5453 e->info->var->kind = VKREFSEFPARAM;
5454 }
5455 else if (e->info->var->kind == VKSEFRETPARAM)
5456 {
5457 e->info->var->kind = VKREFSEFRETPARAM;
5458 }
5459 else if (e->info->var->kind == VKYIELDPARAM)
5460 {
5461 e->info->var->kind = VKREFYIELDPARAM;
5462 }
5463 else
5464 {
5465 e->info->var->kind = VKREFPARAM;
5466 }
5467 }
5468}
5469
5470void
5471uentry_setParam (uentry e)
5472{
5473 if (!uentry_isVar (e))
5474 {
5475 if (uentry_isElipsisMarker (e))
5476 {
5477
5478 }
5479 else
5480 {
5481 llbug (message ("uentry_setParam: not variable: %q", uentry_unparse (e)));
5482 }
5483 }
5484 else
5485 {
5486 cstring oldname;
5487
5488 if (e->info->var->kind == VKYIELDPARAM
5489 || e->info->var->kind == VKSEFPARAM
5490 || e->info->var->kind == VKSEFRETPARAM)
5491 {
5492 ;
5493 }
5494 else
5495 {
5496 e->info->var->kind = VKPARAM;
5497 }
5498
5499 oldname = e->uname;
5500 e->uname = makeParam (e->uname);
5501 cstring_free (oldname);
5502 }
5503}
5504
5505void
5506uentry_setSref (uentry e, sRef s)
5507{
5508 if (uentry_isValid (e))
5509 {
5510 if (sRef_isValid (e->sref))
5511 {
5512 sRef_mergeStateQuietReverse (e->sref, s);
5513 }
5514 else
5515 {
5516 e->sref = sRef_saveCopy (s);
5517 }
5518 }
5519}
5520
5521ctype
5522uentry_getAbstractType (uentry e)
5523{
5524 llassert (uentry_isDatatype (e));
5525
5526 /*
5527 ** This assertion removed.
5528 ** Okay to have undefined type, for system types
5529
5530 llassertprintret (!ctype_isUndefined (e->info->datatype->type),
5531 ("uentry_getAbstractType %q: undefined", uentry_unparseFull (e)),
5532 e->utype);
5533
5534 */
5535
5536 if (ctype_isUndefined (e->info->datatype->type))
5537 {
5538 return ctype_unknown;
5539 }
5540
a0a162cd 5541 /*
5542 ** Sadly, a kludge...
5543 */
5544
5545 if (ctype_isUserBool (e->info->datatype->type)) {
5546 return ctype_bool;
5547 }
5548
885824d3 5549 return e->info->datatype->type;
5550}
5551
5552ctype uentry_getRealType (uentry e)
5553{
a0a162cd 5554 ctype ct;
885824d3 5555 typeId uid = USYMIDINVALID;
5556
5557 if (uentry_isInvalid (e))
5558 {
5559 return ctype_unknown;
5560 }
5561
5562 llassertprint (uentry_isDatatype (e), ("not datatype: %s", uentry_unparse (e)));
5563
5564 if (uentry_isAnyTag (e))
5565 {
5566 return (e->utype);
5567 }
5568
5569 if (uentry_isAbstractType (e))
5570 {
5571 ct = uentry_getAbstractType (e);
a0a162cd 5572
5573 if (ctype_isManifestBool (ct)) {
5574 return ct;
5575 }
5576
885824d3 5577 llassert (ctype_isUA (ct));
5578
5579 uid = ctype_typeId (ct);
5580
5581 if (!context_hasAccess (uid))
5582 {
5583 return (ct);
5584 }
5585 }
5586
5587 ct = uentry_getType (e);
5588
a0a162cd 5589 /* if (ctype_isUserBool (ct)) return ct; */
5590
5591 if (ctype_isManifestBool (ct)) {
5592 return ctype_bool;
5593 }
885824d3 5594
5595 if (ctype_isUA (ct))
5596 {
5597 usymId iid = ctype_typeId (ct);
5598
5599 if /*@access usymId@*/ (iid == uid) /*@noaccess usymId@*/
5600 {
5601 llcontbug (message ("uentry_getRealType: recursive type! %s",
5602 ctype_unparse (ct)));
5603 return ct;
5604 }
5605 else
5606 {
a0a162cd 5607 /* evs 2000-07-25: possible infinite recursion ? */
5608 uentry ue2 = usymtab_getTypeEntry (iid);
5609 llassertprint (ue2 != e, ("Bad recursion: %s", uentry_unparseFull (e)));
5610
5611 return uentry_getRealType (ue2);
885824d3 5612 }
5613 }
5614 else
5615 {
5616 return ct;
5617 }
5618}
5619
5620ctype uentry_getForceRealType (uentry e)
5621{
5622 ctype ct;
5623 typeId uid = USYMIDINVALID;
5624
5625 if (uentry_isInvalid (e))
5626 {
5627 return ctype_unknown;
5628 }
5629
5630 llassertprint (uentry_isDatatype (e), ("not datatype: %s", uentry_unparse (e)));
5631
5632 if (uentry_isAnyTag (e))
5633 {
5634 return (e->utype);
5635 }
5636
5637 if (uentry_isAbstractType (e))
5638 {
5639 ct = uentry_getAbstractType (e);
5640 llassert (ctype_isUA (ct));
5641
5642 uid = ctype_typeId (ct);
5643 /* no check for access! */
5644 }
5645
5646 ct = uentry_getType (e);
a0a162cd 5647
5648 /* evs 2000-07-25 */
5649 /* if (ctype_isUserBool (ct)) return ct; */
5650
5651 if (ctype_isManifestBool (ct)) {
5652 return ctype_bool;
5653 }
885824d3 5654
5655 if (ctype_isUA (ct))
5656 {
5657 usymId iid = ctype_typeId (ct);
5658
5659 if /*@access usymId@*/ (iid == uid) /*@noaccess usymId@*/
5660 {
5661 llcontbug (message ("uentry_getRealType: recursive type! %s",
5662 ctype_unparse (ct)));
5663 return ct;
5664 }
5665 else
5666 {
5667 return uentry_getForceRealType (usymtab_getTypeEntry (iid));
5668 }
5669 }
5670 else
5671 {
5672 return ct;
5673 }
5674}
5675
5676uentry uentry_nameCopy (cstring name, uentry e)
5677{
5678 uentry enew = uentry_alloc ();
5679
5680 llassert (uentry_isValid (e));
5681
5682 /* enew->shallowCopy = FALSE; */
5683 enew->ukind = e->ukind;
5684 enew->uname = name;
5685 enew->utype = e->utype;
5686 enew->whereSpecified = fileloc_copy (e->whereSpecified);
5687 enew->whereDefined = fileloc_copy (e->whereDefined);
5688 enew->whereDeclared = fileloc_copy (e->whereDeclared);
5689 enew->sref = sRef_copy (e->sref);
5690 enew->used = e->used;
5691 enew->lset = FALSE;
5692 enew->isPrivate = e->isPrivate;
5693 enew->hasNameError = FALSE;
5694
5695 enew->uses = filelocList_new ();
5696
5697 enew->storageclass = e->storageclass;
5698 enew->info = uinfo_copy (e->info, e->ukind);
5699
5700 return enew;
5701}
5702
5703void
5704uentry_setDatatype (uentry e, usymId uid)
5705{
5706 llassert (uentry_isDatatype (e));
5707
5708 if (uentry_isAbstractType (e))
5709 {
5710 e->info->datatype->type = ctype_createAbstract (uid);
5711 }
5712 else
5713 {
5714 e->info->datatype->type = ctype_createUser (uid);
5715 }
5716}
5717
5718static void
5719uentry_setSpecDef (/*@special@*/ uentry e, /*@keep@*/ fileloc f)
5720 /*@defines e->whereSpecified, e->whereDeclared, e->whereDefined@*/
5721 /*@modifies e@*/
5722{
5723 llassert (uentry_isValid (e));
5724
5725 if (fileloc_isSpec (f) || fileloc_isImport (f))
5726 {
5727 e->whereSpecified = f;
5728 e->whereDeclared = fileloc_undefined;
5729 e->whereDefined = fileloc_undefined;
5730 }
5731 else
5732 {
5733 e->whereSpecified = fileloc_undefined;
5734 e->whereDeclared = f;
5735 e->whereDefined = fileloc_undefined;
5736 }
5737}
5738
5739static void
5740ucinfo_free (/*@only@*/ ucinfo u)
5741{
5742 multiVal_free (u->val);
5743 sfree (u);
5744}
5745
5746static void
5747uvinfo_free (/*@only@*/ uvinfo u)
5748{
5749 sfree (u);
5750}
5751
5752static void
5753udinfo_free (/*@only@*/ udinfo u)
5754{
5755 sfree (u);
5756}
5757
5758static void
5759ufinfo_free (/*@only@*/ ufinfo u)
5760{
5761 globSet_free (u->globs);
5762 sRefSet_free (u->mods);
5763 specialClauses_free (u->specclauses);
5764
5765 sfree (u);
5766}
5767
5768static void
5769uiinfo_free (/*@only@*/ uiinfo u)
5770{
5771 sfree (u);
5772}
5773
5774static void
5775ueinfo_free (/*@only@*/ ueinfo u)
5776{
5777 sfree (u);
5778}
5779
5780static /*@only@*/ ucinfo
5781ucinfo_copy (ucinfo u)
5782{
5783 ucinfo ret = (ucinfo) dmalloc (sizeof (*ret));
5784
5785 ret->val = multiVal_copy (u->val);
5786 ret->access = u->access;
5787
5788 return ret;
5789}
5790
5791static /*@only@*/ uvinfo
5792uvinfo_copy (uvinfo u)
5793{
5794 uvinfo ret = (uvinfo) dmalloc (sizeof (*ret));
5795
5796 ret->kind = u->kind;
5797 ret->nullstate = u->nullstate;
5798 ret->defstate = u->defstate;
5799 ret->checked = u->checked;
5800
5801 return ret;
5802}
5803
5804static /*@only@*/ udinfo
5805udinfo_copy (udinfo u)
5806{
5807 udinfo ret = (udinfo) dmalloc (sizeof (*ret));
5808
5809 ret->abs = u->abs;
5810 ret->mut = u->mut;
5811 ret->type = u->type;
5812
5813 return ret;
5814}
5815
5816static /*@only@*/ ufinfo
5817ufinfo_copy (ufinfo u)
5818{
5819 ufinfo ret = (ufinfo) dmalloc (sizeof (*ret));
5820
5821 ret->hasGlobs = u->hasGlobs;
5822 ret->hasMods = u->hasMods;
5823 ret->exitCode = u->exitCode;
5824 ret->specialCode = u->specialCode;
5825 ret->nullPred = u->nullPred;
5826 ret->access = u->access;
5827 ret->globs = globSet_newCopy (u->globs);
5828 ret->mods = sRefSet_newCopy (u->mods);
5829 ret->defparams = u->defparams;
5830 ret->specclauses = specialClauses_copy (u->specclauses);
5831
5832 return ret;
5833}
5834
5835static /*@only@*/ uiinfo
5836uiinfo_copy (uiinfo u)
5837{
5838 uiinfo ret = (uiinfo) dmalloc (sizeof (*ret));
5839
5840 ret->access = u->access;
5841 ret->globs = globSet_newCopy (u->globs);
5842 ret->mods = sRefSet_newCopy (u->mods);
5843
5844 return (ret);
5845}
5846
5847static /*@only@*/ ueinfo
5848ueinfo_copy (ueinfo u)
5849{
5850 ueinfo ret = (ueinfo) dmalloc (sizeof (*ret));
5851
5852 ret->access = u->access;
5853 return ret;
5854}
5855
5856static void
5857uinfo_free (uinfo u, ekind kind)
5858{
5859 switch (kind)
5860 {
5861 case KENUMCONST:
5862 case KCONST: ucinfo_free (u->uconst); break;
5863 case KVAR: uvinfo_free (u->var); break;
5864 case KSTRUCTTAG:
5865 case KUNIONTAG:
5866 case KENUMTAG:
5867 case KDATATYPE: udinfo_free (u->datatype); break;
5868 case KFCN: ufinfo_free (u->fcn); break;
5869 case KITER: uiinfo_free (u->iter); break;
5870 case KENDITER: ueinfo_free (u->enditer); break;
5871 case KELIPSMARKER: break;
5872 case KINVALID: break;
5873 }
5874
5875 sfree (u);
5876}
5877
5878static /*@only@*/ /*@null@*/ uinfo
5879uinfo_copy (uinfo u, ekind kind)
5880{
5881 if (kind == KELIPSMARKER || kind == KINVALID)
5882 {
5883 return NULL;
5884 }
5885 else
5886 {
5887 uinfo ret = (uinfo) dmalloc (sizeof (*ret));
5888
5889 switch (kind)
5890 {
5891 case KENUMCONST:
5892 case KCONST: ret->uconst = ucinfo_copy (u->uconst); break;
5893 case KVAR: ret->var = uvinfo_copy (u->var); break;
5894 case KSTRUCTTAG:
5895 case KUNIONTAG:
5896 case KENUMTAG:
5897 case KDATATYPE: ret->datatype = udinfo_copy (u->datatype); break;
5898 case KFCN: ret->fcn = ufinfo_copy (u->fcn); break;
5899 case KITER: ret->iter = uiinfo_copy (u->iter); break;
5900 case KENDITER: ret->enditer = ueinfo_copy (u->enditer); break;
5901 BADDEFAULT;
5902 }
5903 return ret;
5904 }
5905}
5906
5907static void
5908uentry_reallyFree (/*@notnull@*/ /*@only@*/ uentry e)
5909{
5910 filelocList_free (e->uses);
5911 cstring_free (e->uname);
5912
5913 uinfo_free (e->info, e->ukind);
5914
5915 fileloc_free (e->whereSpecified);
5916 fileloc_free (e->whereDefined);
5917 fileloc_free (e->whereDeclared);
5918
5919 nuentries--;
5920 sfree (e);
5921 }
5922
5923extern void uentry_markOwned (/*@owned@*/ uentry u)
5924{
5925 sfreeEventually (u);
5926}
5927
5928void
5929uentry_free (/*@only@*/ uentry e)
5930{
5931 if (uentry_isValid (e) && !uentry_isElipsisMarker (e))
5932 {
5933 uentry_reallyFree (e);
5934 }
5935}
5936
5937/*
5938** For uentry's in the global or file scope
5939*/
5940
5941void
5942uentry_freeComplete (/*@only@*/ uentry e)
5943{
5944 if (uentry_isValid (e) && !uentry_isElipsisMarker (e))
5945 {
5946 /*@i@*/ sRef_free (e->sref);
5947 e->sref = sRef_undefined;
5948 uentry_reallyFree (e);
5949 }
5950}
5951
5952/*
5953** requires old->kind != new->kind, old->uname = new->uname
5954*/
5955
5956static void
5957KindConformanceError (/*@unique@*/ uentry old, uentry unew, bool mustConform)
5958{
5959 llassert (uentry_isValid (old));
5960 llassert (uentry_isValid (unew));
5961
5962 if (uentry_isEitherConstant (unew)
5963 && (fileloc_isPreproc (uentry_whereDeclared (old))
5964 || ctype_isUnknown (old->utype))
5965 && !uentry_isSpecified (old))
5966 {
5967 ; /* no error */
5968 }
5969 else
5970 {
5971 if (mustConform)
5972 {
5973 if (!uentry_isDeclared (old))
5974 {
5975 if (uentry_isSpecified (old))
5976 {
5977 if (uentry_isSpecified (unew))
5978 {
5979 llbuglit ("Respecification!");
5980 }
5981 else if (uentry_isDeclared (unew))
5982 {
5983 if (optgenerror
5984 (FLG_INCONDEFS,
5985 message ("%s %q inconsistently declared as %s: %t",
5986 ekind_capName (old->ukind),
5987 uentry_getName (unew),
5988 ekind_unparseLong (unew->ukind),
5989 unew->utype),
5990 uentry_whereDeclared (unew)))
5991 {
5992 uentry_showWhereLast (old);
5993 }
5994 }
5995 else
5996 {
5997 BADEXIT;
5998 }
5999 }
6000 else
6001 {
6002 if (optgenerror
6003 (FLG_INCONDEFS,
6004 message ("%s %q inconsistently declared as %s: %t",
6005 ekind_capName (old->ukind),
6006 uentry_getName (unew),
6007 ekind_unparseLong (unew->ukind),
6008 unew->utype),
6009 uentry_whereDeclared (unew)))
6010 {
6011 uentry_showWhereLast (old);
6012 }
6013 }
6014 }
6015 else
6016 {
6017 llassert (uentry_isDeclared (unew));
6018
6019 if (optgenerror
6020 (FLG_INCONDEFS,
6021 message ("%s %q inconsistently redeclared as %s",
6022 ekind_capName (old->ukind),
6023 uentry_getName (unew),
6024 ekind_unparseLong (unew->ukind)),
6025 uentry_whereDeclared (unew)))
6026 {
6027 uentry_showWhereLast (old);
6028 }
6029 }
6030 }
6031 }
6032
6033 uentry_copyInto (old, unew);
6034}
6035
6036/*
6037** def is the definition of spec, modifies spec
6038**
6039** reports any inconsistencies
6040** returns the summary of all available information
6041** if spec and def are inconsistent, def is returned
6042*/
6043
6044void
6045uentry_showWhereLast (uentry spec)
6046{
6047 if (uentry_isValid (spec))
6048 {
6049 if (fileloc_isDefined (spec->whereDefined)
6050 && !fileloc_isLib (spec->whereDefined)
6051 && !fileloc_isPreproc (spec->whereDefined))
6052 {
6053 llgenindentmsg (message ("Previous definition of %q: %t",
6054 uentry_getName (spec),
6055 uentry_getType (spec)),
6056 uentry_whereDefined (spec));
6057 }
6058 else if (uentry_isDeclared (spec))
6059 {
6060 llgenindentmsg (message ("Previous declaration of %q: %t",
6061 uentry_getName (spec),
6062 uentry_getType (spec)),
6063 uentry_whereDeclared (spec));
6064 }
6065 else if (uentry_isSpecified (spec))
6066 {
6067 if (uentry_hasName (spec))
6068 {
6069 llgenindentmsg (message ("Specification of %q: %t",
6070 uentry_getName (spec),
6071 uentry_getType (spec)),
6072 uentry_whereSpecified (spec));
6073 }
6074 else
6075 {
6076 llgenindentmsg (message ("Specification: %t", uentry_getType (spec)),
6077 uentry_whereSpecified (spec));
6078 }
6079 }
6080 else
6081 {
6082 /* nothing to show */
6083 }
6084 }
6085}
6086
6087void
6088uentry_showDefSpecInfo (uentry ce, fileloc fwhere)
6089{
6090 fileloc loc = uentry_whereDefined (ce);
6091
6092 if (fileloc_isUser (loc) && !fileloc_equal (loc, fwhere))
6093 {
6094 llgenindentmsg (message ("Definition of %q", uentry_getName (ce)),
6095 loc);
6096 }
6097
6098 loc = uentry_whereSpecified (ce);
6099
6100 if (fileloc_isUser (loc) && !fileloc_equal (loc, fwhere))
6101 {
6102 llgenindentmsg (message ("Specification of %q", uentry_getName (ce)),
6103 loc);
6104 }
6105}
6106
6107void uentry_showWhereLastExtra (uentry spec, cstring extra)
6108{
6109 if (uentry_isDeclared (spec))
6110 {
6111 llgenindentmsg (message ("Previous declaration of %q: %q",
6112 uentry_getName (spec), extra),
6113 uentry_whereDeclared (spec));
6114 }
6115 else if (uentry_isSpecified (spec))
6116 {
6117 llgenindentmsg (message ("Specification of %q: %q",
6118 uentry_getName (spec), extra),
6119 uentry_whereSpecified (spec));
6120 }
6121 else
6122 {
6123 cstring_free (extra);
6124 }
6125}
6126
6127void
6128uentry_showWhereDeclared (uentry spec)
6129{
6130 if (uentry_isDeclared (spec))
6131 {
6132 if (uentry_hasName (spec))
6133 {
6134 llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
6135 uentry_whereDeclared (spec));
6136 }
6137 else
6138 {
6139 llgenindentmsg (cstring_makeLiteral ("Declaration"), uentry_whereDeclared (spec));
6140 }
6141 }
6142 else if (uentry_isSpecified (spec))
6143 {
6144 if (uentry_hasName (spec))
6145 {
6146 llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
6147 uentry_whereSpecified (spec));
6148 }
6149 else
6150 {
6151 llgenindentmsg (cstring_makeLiteral ("Specification"), uentry_whereSpecified (spec));
6152 }
6153 }
6154 else
6155 {
6156 /* nothing to show */
6157 }
6158
6159}
6160
6161void
6162uentry_showWhereAny (uentry spec)
6163{
6164 if (uentry_isDeclared (spec))
6165 {
6166 if (uentry_hasName (spec))
6167 {
6168 llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
6169 uentry_whereDeclared (spec));
6170 }
6171 else
6172 {
6173 llgenindentmsg (cstring_makeLiteral ("Declaration"), uentry_whereDeclared (spec));
6174 }
6175 }
6176 else if (uentry_isSpecified (spec))
6177 {
6178 if (uentry_hasName (spec))
6179 {
6180 llgenindentmsg (message ("Specification of %q",
6181 uentry_getName (spec)),
6182 uentry_whereSpecified (spec));
6183 }
6184 else
6185 {
6186 llgenindentmsg (cstring_makeLiteral ("Specification"),
6187 uentry_whereSpecified (spec));
6188 }
6189 }
6190 else if (fileloc_isDefined (uentry_whereDefined (spec)))
6191 {
6192 if (uentry_hasName (spec))
6193 {
6194 llgenindentmsg (message ("Definition of %q", uentry_getName (spec)),
6195 uentry_whereDefined (spec));
6196 }
6197 else
6198 {
6199 llgenindentmsg (cstring_makeLiteral ("Definition"), uentry_whereDefined (spec));
6200 }
6201 }
6202 else
6203 {
6204 /* nothing to show */
6205 }
6206}
6207
6208void
6209uentry_showWhereDefined (uentry spec)
6210{
6211 if (uentry_isCodeDefined (spec))
6212 {
6213 llgenindentmsg (message ("Previous definition of %q", uentry_getName (spec)),
6214 uentry_whereDefined (spec));
6215 }
6216}
6217
6218void
6219uentry_showWhereLastPlain (uentry spec)
6220{
6221 if (uentry_isDeclared (spec))
6222 {
6223 llgenindentmsg (message ("Previous declaration of %q", uentry_getName (spec)),
6224 uentry_whereDeclared (spec));
6225 }
6226 else if (uentry_isSpecified (spec))
6227 {
6228 llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
6229 uentry_whereSpecified (spec));
6230 }
6231 else
6232 {
6233 }
6234}
6235
6236static void
6237uentry_showWhereLastVal (uentry spec, cstring val)
6238{
6239 if (uentry_isDeclared (spec))
6240 {
6241 llgenindentmsg (message ("Previous declaration of %q: %s",
6242 uentry_getName (spec), val),
6243 uentry_whereDeclared (spec));
6244 }
6245 else if (uentry_isSpecified (spec))
6246 {
6247 llgenindentmsg (message ("Specification of %q: %s",
6248 uentry_getName (spec), val),
6249 uentry_whereSpecified (spec));
6250 }
6251 else
6252 {
6253 }
6254}
6255
6256void
6257uentry_showWhereSpecified (uentry spec)
6258{
6259 if (uentry_isSpecified (spec))
6260 {
6261 if (uentry_hasName (spec))
6262 {
6263 llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
6264 uentry_whereSpecified (spec));
6265 }
6266 else
6267 {
6268 llgenindentmsg (cstring_makeLiteral ("Specification"),
6269 uentry_whereSpecified (spec));
6270 }
6271 }
6272 else if (uentry_isDeclared (spec))
6273 {
6274 llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
6275 uentry_whereDeclared (spec));
6276 }
6277 else
6278 {
6279 /* nothing to show */
6280 }
6281}
6282
6283void
6284uentry_showWhereSpecifiedExtra (uentry spec, cstring s)
6285{
6286 if (uentry_isSpecified (spec))
6287 {
6288 if (uentry_hasName (spec))
6289 {
6290 llgenindentmsg (message ("Specification of %q: %q",
6291 uentry_getName (spec), s),
6292 uentry_whereSpecified (spec));
6293 }
6294 else
6295 {
6296 llgenindentmsg (message ("Specification: %q", s),
6297 uentry_whereSpecified (spec));
6298 }
6299 }
6300 else if (uentry_isDeclared (spec))
6301 {
6302 llgenindentmsg (message ("Declaration of %q: %q",
6303 uentry_getName (spec), s),
6304 uentry_whereDeclared (spec));
6305 }
6306 else
6307 {
6308 llgenindentmsg (message ("Previous: %q", s),
6309 uentry_whereLast (spec));
6310 }
6311}
6312
6313/*
6314**
6315*/
6316
6317static void
6318checkStructConformance (uentry old, uentry unew)
6319{
6320 ctype oldr, newr;
6321 uentryList fold, fnew;
6322
6323 /*
6324 ** requires: types of old and new are structs or unions
6325 */
6326
6327 llassert (uentry_isValid (old));
6328 llassert (uentry_isValid (unew));
6329
6330 oldr = ctype_realType (old->utype);
6331 fold = ctype_getFields (oldr);
6332
6333 newr = ctype_realType (unew->utype);
6334 fnew = ctype_getFields (newr);
6335
6336 if (!uentryList_matchFields (fold, fnew))
6337 {
6338 if (fileloc_equal (uentry_whereLast (old),
6339 uentry_whereLast (unew)))
6340 {
6341 ; /* cheat! */
6342 }
6343 else
6344 {
6345 if (optgenerror
6346 (FLG_MATCHFIELDS,
6347 message ("%q %q %rdeclared with fields { %q }, %s "
6348 "with fields { %q }",
6349 cstring_makeLiteral (ctype_isStruct (newr) ? "Structure": "Union"),
6350 uentry_getName (old),
6351 uentry_isDeclared (old),
6352 uentryList_unparseAbbrev (fnew),
6353 uentry_specOrDefName (old),
6354 uentryList_unparseAbbrev (fold)),
6355 uentry_whereDeclared (unew)))
6356 {
6357 uentry_showWhereLastPlain (old);
6358 uentryList_showFieldDifference (fold, fnew);
6359 }
6360 }
6361
6362 old->utype = unew->utype;
6363 }
6364}
6365
6366static void
6367checkEnumConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
6368{
6369 /*
6370 ** requires old and new are enums
6371 */
6372
6373 ctype rold = ctype_realType (old->utype);
6374 ctype rnew = ctype_realType (unew->utype);
6375 enumNameList eold = ctype_elist (rold);
6376 enumNameList enew = ctype_elist (rnew);
6377
6378 if (!enumNameList_match (eold, enew))
6379 {
6380 if (optgenerror
6381 (FLG_MATCHFIELDS,
6382 message ("Enum %q declared with members { %q } but "
6383 "specified with members { %q }",
6384 uentry_getName (old),
6385 enumNameList_unparse (enew),
6386 enumNameList_unparse (eold)),
6387 uentry_whereDeclared (unew)))
6388 {
6389 uentry_showWhereSpecified (old);
6390 old->utype = unew->utype;
6391 }
6392 }
6393}
6394
6395/*
6396** either oldCurrent or newCurrent may be undefined!
6397*/
6398
6399static void
6400paramTypeError (uentry old, uentry oldCurrent, ctype oldType,
6401 uentry unew, uentry newCurrent, ctype newType,
6402 int paramno)
6403{
6404 bool hasError = FALSE;
6405
6406 if (uentry_isValid (newCurrent) && uentry_isDeclared (newCurrent))
6407 {
6408 if (uentry_hasName (newCurrent))
6409 {
6410 hasError = optgenerror
6411 (FLG_TYPE,
6412 message ("Parameter %d, %q, of function %q has inconsistent type: "
6413 "declared %t, %s %t",
6414 paramno + 1, uentry_getName (newCurrent),
6415 uentry_getName (unew),
6416 newType, uentry_specOrDefName (old), oldType),
6417 uentry_whereDeclared (newCurrent));
6418 }
6419 else
6420 {
6421 hasError = optgenerror
6422 (FLG_TYPE,
6423 message ("Parameter %d of function %q has inconsistent type: "
6424 "declared %t, %s %t",
6425 paramno + 1, uentry_getName (unew),
6426 newType, uentry_specOrDefName (old), oldType),
6427 uentry_whereDeclared (newCurrent));
6428
6429 DPRINTF (("type: %s / %s",
6430 ctype_unparse (newType),
6431 ctype_unparse (ctype_realType (newType))));
6432 }
6433 }
6434 else
6435 {
6436 if (uentry_isDeclared (unew))
6437 {
6438 hasError = optgenerror
6439 (FLG_TYPE,
6440 message ("Parameter %d of function %s has inconsistent type: "
6441 "declared %t, %s %t",
6442 paramno + 1, unew->uname,
6443 newType, uentry_specOrDefName (old), oldType),
6444 uentry_whereDeclared (unew));
6445 }
6446 else
6447 {
6448 hasError = optgenerror
6449 (FLG_TYPE,
6450 message ("Parameter %d of function %s has inconsistent type: "
6451 "declared %t, %s %t",
6452 paramno + 1, unew->uname,
6453 newType, uentry_specOrDefName (old), oldType),
6454 uentry_whereDeclared (unew));
6455 }
6456 }
6457
6458 if (hasError)
6459 {
6460 if (!uentry_isUndefined (oldCurrent))
6461 {
6462 if (!uentry_isUndefined (newCurrent)
6463 && cstring_equal (uentry_rawName (newCurrent), uentry_rawName (oldCurrent)))
6464 {
6465 uentry_showWhereLast (oldCurrent);
6466 }
6467 else
6468 {
6469 uentry_showWhereLastPlain (old);
6470 }
6471
6472 uentry_setType (oldCurrent, newType);
6473 }
6474 else
6475 {
6476 uentry_showWhereLastPlain (old);
6477 }
6478 }
6479}
6480
6481static void
6482nargsError (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
6483{
6484 if (optgenerror
6485 (FLG_TYPE,
6486 message ("Function %s %rdeclared with %d arg%p, %s with %d",
6487 unew->uname,
6488 uentry_isDeclared (old),
6489 uentryList_size (uentry_getParams (unew)),
6490 uentry_specOrDefName (old),
6491 uentryList_size (uentry_getParams (old))),
6492 uentry_whereDeclared (unew)))
6493 {
6494 uentry_showWhereLastPlain (old);
6495 }
6496}
6497
6498static void
6499returnValueError (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
6500{
6501 if (optgenerror
6502 (FLG_INCONDEFS,
6503 message ("Function %s inconsistently %rdeclared to return %t",
6504 unew->uname,
6505 uentry_isDeclared (old),
6506 ctype_returnValue (unew->utype)),
6507 uentry_whereDeclared (unew)))
6508 {
6509 uentry_showWhereLastVal (old, ctype_unparse (ctype_returnValue (old->utype)));
6510 }
6511}
6512
6513static cstring paramStorageName (uentry ue)
6514{
6515 return (cstring_makeLiteralTemp (uentry_isParam (ue) ? "param" : "storage"));
6516}
6517
6518static cstring fcnErrName (uentry ue)
6519{
6520 return (cstring_makeLiteralTemp (uentry_isFunction (ue) ? "to return" : "as"));
6521}
6522
6523extern /*@observer@*/ cstring uentry_checkedName (uentry ue)
6524{
6525 if (uentry_isVar (ue))
6526 {
6527 return (checkedName (ue->info->var->checked));
6528 }
6529 else
6530 {
6531 return (cstring_makeLiteralTemp ("<checked invalid>"));
6532 }
6533}
6534
6535static cstring checkedName (chkind checked)
6536{
6537 switch (checked)
6538 {
6539 case CH_UNKNOWN: return (cstring_makeLiteralTemp ("unknown"));
6540 case CH_UNCHECKED: return (cstring_makeLiteralTemp ("unchecked"));
6541 case CH_CHECKED: return (cstring_makeLiteralTemp ("checked"));
6542 case CH_CHECKMOD: return (cstring_makeLiteralTemp ("checkmod"));
6543 case CH_CHECKEDSTRICT: return (cstring_makeLiteralTemp ("checkedstrict"));
6544 }
6545 BADEXIT;
6546}
6547
6548static
6549void checkNullState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, bool mustConform, bool completeConform)
6550{
6551 nstate oldState;
6552 nstate newState;
6553
6554 if (uentry_isVar (unew))
6555 {
6556 llassert (uentry_isVar (old));
6557
6558 oldState = old->info->var->nullstate;
6559 newState = unew->info->var->nullstate;
6560 }
6561 else
6562 {
6563 oldState = sRef_getNullState (old->sref);
6564 newState = sRef_getNullState (unew->sref);
6565 }
6566
6567 if (oldState == NS_ABSNULL)
6568 {
6569 if (uentry_isVar (old))
6570 {
6571 old->info->var->nullstate = newState;
6572 }
6573
6574 sRef_mergeNullState (old->sref, newState);
6575 }
6576 else if (newState == NS_UNKNOWN)
6577 {
6578 if (completeConform && newState != oldState
6579 && uentry_isReallySpecified (old))
6580 {
6581 if (optgenerror
6582 (FLG_NEEDSPEC,
6583 message ("%s %q specified as %s, but declared without %s qualifier",
6584 ekind_capName (unew->ukind),
6585 uentry_getName (unew),
6586 nstate_unparse (oldState),
6587 nstate_unparse (oldState)),
6588 uentry_whereDeclared (unew)))
6589 {
6590 uentry_showWhereSpecified (old);
6591 }
6592 }
6593
6594 if (uentry_isVar (unew))
6595 {
6596 unew->info->var->nullstate = oldState;
6597 }
6598
6599 sRef_mergeNullState (unew->sref, oldState);
6600 }
6601 else if (newState == NS_POSNULL)
6602 {
6603 if (oldState == NS_MNOTNULL
6604 && (ctype_isUA (unew->utype)
6605 || (uentry_isFunction (unew)
6606 && ctype_isUA (ctype_returnValue (unew->utype)))))
6607 {
6608 if (uentry_isVar (unew))
6609 {
6610 unew->info->var->nullstate = oldState;
6611 }
6612
6613 sRef_mergeNullState (unew->sref, oldState);
6614 }
6615 else
6616 {
6617 if (oldState == NS_NOTNULL || oldState == NS_MNOTNULL
6618 || oldState == NS_UNKNOWN)
6619 {
6620 if (mustConform)
6621 {
6622 if (optgenerror
6623 (FLG_INCONDEFS,
6624 message
6625 ("%s %q inconsistently %rdeclared %s possibly null storage, "
6626 "%s %q qualifier",
6627 uentry_ekindName (unew),
6628 uentry_getName (unew),
6629 uentry_isDeclared (old),
6630 fcnErrName (unew),
6631 uentry_specOrDefName (old),
6632 cstring_makeLiteral (oldState == NS_MNOTNULL ? "with notnull" : "without null")),
6633 uentry_whereDeclared (unew)))
6634 {
6635 uentry_showWhereSpecified (old);
6636 }
6637 }
6638 }
6639
6640 if (uentry_isVar (old))
6641 {
6642 old->info->var->nullstate = newState;
6643 }
6644
6645 sRef_mergeNullState (old->sref, newState);
6646 }
6647 }
6648 else if (newState == NS_MNOTNULL)
6649 {
6650 if (oldState != NS_MNOTNULL)
6651 {
6652 if (mustConform)
6653 {
6654 if (optgenerror
6655 (FLG_INCONDEFS,
6656 message ("%s %q inconsistently %rdeclared %s notnull storage, "
6657 "%s without notnull qualifier",
6658 uentry_ekindName (unew),
6659 uentry_getName (unew),
6660 uentry_isDeclared (old),
6661 fcnErrName (unew),
6662 uentry_specOrDefName (old)),
6663 uentry_whereDeclared (unew)))
6664 {
6665 uentry_showWhereSpecified (old);
6666 }
6667 }
6668
6669 if (uentry_isVar (old))
6670 {
6671 old->info->var->nullstate = newState;
6672 }
6673
6674 sRef_mergeNullState (old->sref, newState);
6675 }
6676 }
6677 else
6678 {
6679 if (uentry_isVar (unew))
6680 {
6681 unew->info->var->nullstate = oldState;
6682 }
6683
6684 sRef_mergeNullState (unew->sref, oldState);
6685 }
6686}
6687
6688static
6689void checkDefState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
6690 bool mustConform, bool completeConform)
6691{
6692 sstate oldState;
6693 sstate newState;
6694 bool vars = FALSE;
6695
6696 if (uentry_isVar (old) && uentry_isVar (unew))
6697 {
6698 oldState = old->info->var->defstate;
6699 newState = unew->info->var->defstate;
6700 vars = TRUE;
6701 }
6702 else
6703 {
6704 oldState = sRef_getDefState (old->sref);
6705 newState = sRef_getDefState (unew->sref);
6706 }
6707
6708 if (newState != oldState && newState != SS_UNKNOWN && newState != SS_DEFINED)
6709 {
6710 if (mustConform)
6711 {
6712 if (optgenerror
6713 (FLG_INCONDEFS,
6714 message ("%s %q inconsistently %rdeclared %s %s %s, "
6715 "%s %s %s %s",
6716 uentry_ekindName (unew),
6717 uentry_getName (unew),
6718 uentry_isDeclared (old),
6719 fcnErrName (unew),
6720 sstate_unparse (newState),
6721 paramStorageName (unew),
6722 uentry_specOrDefName (old),
6723 fcnErrName (unew),
6724 sstate_unparse (oldState),
6725 paramStorageName (unew)),
6726 uentry_whereDeclared (unew)))
6727 {
6728 uentry_showWhereSpecified (old);
6729 }
6730 }
6731
6732 if (vars) old->info->var->defstate = newState;
6733 sRef_setDefState (old->sref, newState, uentry_whereDeclared (unew));
6734 }
6735 else
6736 {
6737 if (completeConform
6738 && (newState != oldState) && (oldState != SS_DEFINED)
6739 && uentry_isReallySpecified (old))
6740 {
6741 if (optgenerror
6742 (FLG_NEEDSPEC,
6743 message ("%s %q specified as %s, but declared without %s qualifier",
6744 ekind_capName (unew->ukind),
6745 uentry_getName (unew),
6746 sstate_unparse (oldState),
6747 sstate_unparse (oldState)),
6748 uentry_whereDeclared (unew)))
6749 {
6750 uentry_showWhereSpecified (old);
6751 }
6752 }
6753
6754 if (vars) unew->info->var->defstate = oldState;
6755 sRef_setDefState (unew->sref, oldState, uentry_whereDeclared (unew));
6756 }
6757}
6758
6759static void
6760 checkAliasState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
6761 bool mustConform, bool completeConform)
6762{
6763 alkind newKind;
6764 alkind oldKind;
6765
6766 oldKind = sRef_getAliasKind (old->sref);
6767 newKind = sRef_getAliasKind (unew->sref);
6768
6769 if (alkind_isImplicit (newKind)
6770 || (alkind_isRefCounted (newKind) && !uentry_isDatatype (unew)))
6771 {
6772 if (completeConform && !alkind_equal (newKind, oldKind)
6773 && uentry_isReallySpecified (old))
6774 {
6775 if (optgenerror
6776 (FLG_NEEDSPEC,
6777 message ("%s %q specified as %s, but declared without "
6778 "explicit alias qualifier",
6779 ekind_capName (unew->ukind),
6780 uentry_getName (unew),
6781 alkind_unparse (oldKind)),
6782 uentry_whereDeclared (unew)))
6783 {
6784 uentry_showWhereSpecified (old);
6785 }
6786 }
6787
6788 /*
6789 ** This really shouldn't be necessary, but it is!
6790 ** Function params (?) use new here.
6791 */
6792
6793 sRef_setAliasKind (unew->sref, oldKind, uentry_whereDeclared (unew));
6794 return;
6795 }
6796
6797 if (alkind_isKnown (newKind))
6798 {
6799 if (!alkind_equal (oldKind, newKind))
6800 {
6801 if (alkind_isKnown (oldKind))
6802 {
6803 if (mustConform &&
6804 optgenerror
6805 (FLG_INCONDEFS,
6806 message ("%s %q inconsistently %rdeclared %s %s storage, "
6807 "%s as %s storage",
6808 uentry_ekindName (unew),
6809 uentry_getName (unew),
6810 uentry_isDeclared (old),
6811 fcnErrName (unew),
6812 alkind_unparse (newKind),
6813 uentry_specOrDefName (old),
6814 alkind_unparse (oldKind)),
6815 uentry_whereDeclared (unew)))
6816 {
6817 uentry_showWhereSpecified (old);
6818
6819 sRef_setAliasKind (old->sref, AK_ERROR,
6820 uentry_whereDeclared (unew));
6821 }
6822 else
6823 {
6824 sRef_setAliasKind (old->sref, newKind,
6825 uentry_whereDeclared (unew));
6826 }
6827 }
6828 else
6829 {
6830 if (!(alkind_isImplicit (newKind)))
6831 {
6832 if (mustConform &&
6833 !uentry_isFunction (unew) &&
6834 optgenerror
6835 (FLG_INCONDEFS,
6836 message ("%s %q inconsistently %rdeclared %s %s storage, "
6837 "implicitly %s as temp storage",
6838 uentry_ekindName (unew),
6839 uentry_getName (unew),
6840 uentry_isDeclared (old),
6841 fcnErrName (unew),
6842 alkind_unparse (newKind),
6843 uentry_specOrDefName (old)),
6844 uentry_whereDeclared (unew)))
6845 {
6846 uentry_showWhereSpecified (old);
6847 oldKind = AK_ERROR;
6848 }
6849
6850 sRef_setAliasKind (old->sref, newKind,
6851 uentry_whereDeclared (unew));
6852 }
6853 else /* newKind is temp or refcounted */
6854 {
6855 ;
6856 }
6857 }
6858 }
6859 }
6860 else /* newKind unknown */
6861 {
6862 ;
6863 }
6864}
6865
6866static void
6867 checkExpState(/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
6868 bool mustConform, bool completeConform)
6869{
6870 exkind newKind;
6871 exkind oldKind;
6872
6873 oldKind = sRef_getExKind (old->sref);
6874 newKind = sRef_getExKind (unew->sref);
6875
6876 if (exkind_isKnown (newKind))
6877 {
6878 if (oldKind != newKind)
6879 {
6880 if (exkind_isKnown (oldKind))
6881 {
6882 if (mustConform &&
6883 optgenerror
6884 (FLG_INCONDEFS,
6885 message ("%s %q inconsistently %rdeclared %s %s, %s as %s",
6886 uentry_ekindName (unew),
6887 uentry_getName (unew),
6888 uentry_isDeclared (old),
6889 fcnErrName (unew),
6890 exkind_unparse (newKind),
6891 uentry_specOrDefName (old),
6892 exkind_unparse (oldKind)),
6893 uentry_whereDeclared (unew)))
6894 {
6895 uentry_showWhereSpecified (old);
6896 }
6897
6898 sRef_setExKind (old->sref, newKind, uentry_whereDefined (unew));
6899 }
6900 else
6901 {
6902 if (mustConform &&
6903 optgenerror
6904 (FLG_INCONDEFS,
6905 message ("%s %q inconsistently %rdeclared %s %s, "
6906 "implicitly %s without exposure qualifier",
6907 uentry_ekindName (unew),
6908 uentry_getName (unew),
6909 uentry_isDeclared (old),
6910 fcnErrName (unew),
6911 exkind_unparse (newKind),
6912 uentry_specOrDefName (old)),
6913 uentry_whereDeclared (unew)))
6914 {
6915 uentry_showWhereSpecified (old);
6916 }
6917
6918 sRef_setExKind (old->sref, newKind, uentry_whereDefined (unew));
6919 }
6920 }
6921 }
6922 else
6923 {
6924 if (completeConform && exkind_isKnown (oldKind)
6925 && uentry_isReallySpecified (old))
6926 {
6927 if (optgenerror
6928 (FLG_NEEDSPEC,
6929 message ("%s %q specified as %s, but declared without "
6930 "exposure qualifier",
6931 ekind_capName (unew->ukind),
6932 uentry_getName (unew),
6933 exkind_unparse (oldKind)),
6934 uentry_whereDeclared (unew)))
6935 {
6936 uentry_showWhereSpecified (old);
6937 }
6938 }
6939
6940 /* yes, this is necessary! (if its a param) */
6941 sRef_setExKind (unew->sref, oldKind, fileloc_undefined);
6942 }
6943}
6944
6945static void
6946uentry_checkStateConformance (/*@notnull@*/ uentry old,
6947 /*@notnull@*/ uentry unew,
6948 bool mustConform, bool completeConform)
6949{
6950 checkDefState (old, unew, mustConform, completeConform);
6951 checkNullState (old, unew, mustConform, completeConform);
6952 checkAliasState (old, unew, mustConform, completeConform);
6953 checkExpState (old, unew, mustConform, completeConform);
6954
6955 sRef_storeState (old->sref);
6956 sRef_storeState (unew->sref);
6957}
6958
6959static void
6960checkVarConformance (uentry old, uentry unew, bool mustConform, bool completeConform)
6961{
6962 if (uentry_isElipsisMarker (old) || uentry_isElipsisMarker (unew))
6963 {
6964 return;
6965 }
6966
6967 llassert (uentry_isVar (old));
6968 llassert (uentry_isVar (unew));
6969
6970 if (cstring_isEmpty (old->uname))
6971 {
6972 cstring_free (old->uname);
6973 old->uname = cstring_copy (unew->uname);
6974 }
6975
6976 if (unew->info->var->kind == VKRETPARAM
6977 || unew->info->var->kind == VKSEFRETPARAM)
6978 {
6979 if (old->info->var->kind != VKRETPARAM
6980 && old->info->var->kind != VKSEFRETPARAM)
6981 {
6982 if (optgenerror
6983 (FLG_INCONDEFS,
6984 message ("Parameter %q inconsistently %rdeclared as "
6985 "returned parameter",
6986 uentry_getName (unew),
6987 uentry_isDeclared (old)),
6988 uentry_whereDeclared (unew)))
6989 {
6990 uentry_showWhereSpecified (old);
6991 old->info->var->kind = unew->info->var->kind;
6992 }
6993 }
6994 }
6995
6996
6997 if (unew->info->var->kind == VKSEFPARAM || unew->info->var->kind == VKSEFRETPARAM)
6998 {
6999 if (old->info->var->kind != VKSEFPARAM
7000 && old->info->var->kind != VKSEFRETPARAM)
7001 {
7002 if (optgenerror
7003 (FLG_INCONDEFS,
7004 message ("Parameter %qinconsistently %rdeclared as "
7005 "sef parameter",
7006 uentry_getOptName (unew),
7007 uentry_isDeclared (old)),
7008 uentry_whereDeclared (unew)))
7009 {
7010 uentry_showWhereSpecified (old);
7011 old->info->var->kind = unew->info->var->kind;
7012 }
7013 }
7014 }
7015
7016 if (old->info->var->kind == VKSPEC)
7017 {
7018 old->info->var->kind = unew->info->var->kind;
7019 }
7020 else
7021 {
7022 unew->info->var->kind = old->info->var->kind;
7023 }
7024
7025 if (unew->info->var->checked != CH_UNKNOWN
7026 && unew->info->var->checked != old->info->var->checked)
7027 {
7028 if (old->info->var->checked == CH_UNKNOWN
7029 && !fileloc_isUser (uentry_whereLast (old)))
7030 {
7031 ; /* no error */
7032 }
7033 else
7034 {
7035 if (optgenerror
7036 (FLG_INCONDEFS,
7037 message ("Variable %q inconsistently %rdeclared as "
7038 "%s parameter (was %s)",
7039 uentry_getName (unew),
7040 uentry_isDeclared (old),
7041 checkedName (unew->info->var->checked),
7042 checkedName (old->info->var->checked)),
7043 uentry_whereDeclared (unew)))
7044 {
7045 uentry_showWhereSpecified (old);
7046 }
7047 }
7048
7049 old->info->var->checked = unew->info->var->checked;
7050 }
7051 else
7052 {
7053 if (completeConform
7054 && (old->info->var->checked != CH_UNKNOWN)
7055 && uentry_isReallySpecified (old))
7056 {
7057 if (optgenerror
7058 (FLG_NEEDSPEC,
7059 message ("%s %q specified as %s, but declared without %s qualifier",
7060 ekind_capName (unew->ukind),
7061 uentry_getName (unew),
7062 checkedName (old->info->var->checked),
7063 checkedName (old->info->var->checked)),
7064 uentry_whereDeclared (unew)))
7065 {
7066 uentry_showWhereSpecified (old);
7067 }
7068 }
7069
7070 unew->info->var->checked = old->info->var->checked;
7071 }
7072
7073 uentry_checkStateConformance (old, unew, mustConform, completeConform);
7074}
7075
7076void uentry_checkMatchParam (uentry u1, uentry u2, int paramno, exprNode e)
7077{
7078 if (uentry_isElipsisMarker (u1) || uentry_isElipsisMarker (u2))
7079 {
7080 return;
7081 }
7082
7083 llassert (uentry_isVar (u1));
7084 llassert (uentry_isVar (u2));
7085
7086 if (u1->info->var->kind != u2->info->var->kind) {
7087 if (u1->info->var->kind == VKSEFRETPARAM) {
7088 if (u2->info->var->kind == VKRETPARAM) {
7089 voptgenerror
7090 (FLG_TYPE,
7091 message ("Function types are inconsistent. Parameter %d is "
7092 "sef parameter, but non-sef parameter in "
7093 "assigned function: %s",
7094 paramno, exprNode_unparse (e)),
7095 exprNode_loc (e));
7096 } else if (u2->info->var->kind == VKSEFPARAM) {
7097 voptgenerror
7098 (FLG_TYPE,
7099 message ("Function types are inconsistent. Parameter %d is "
7100 "returns parameter, but non-returns parameter in "
7101 "assigned function: %s",
7102 paramno, exprNode_unparse (e)),
7103 exprNode_loc (e));
7104 } else {
7105 voptgenerror
7106 (FLG_TYPE,
7107 message ("Function types are inconsistent. Parameter %d is "
7108 "sef returns parameter, but non-sef returns parameter in "
7109 "assigned function: %s",
7110 paramno, exprNode_unparse (e)),
7111 exprNode_loc (e));
7112 }
7113 } else if (u1->info->var->kind == VKRETPARAM) {
7114 voptgenerror
7115 (FLG_TYPE,
7116 message ("Function types are inconsistent. Parameter %d is "
7117 "returns parameter, but non-returns parameter in "
7118 "assigned function: %s",
7119 paramno, exprNode_unparse (e)),
7120 exprNode_loc (e));
7121 } else if (u1->info->var->kind == VKSEFPARAM) {
7122 voptgenerror
7123 (FLG_TYPE,
7124 message ("Function types are inconsistent. Parameter %d is "
7125 "sef parameter, but non-sef parameter in "
7126 "assigned function: %s",
7127 paramno, exprNode_unparse (e)),
7128 exprNode_loc (e));
7129 } else {
7130 if (u2->info->var->kind == VKSEFRETPARAM) {
7131 voptgenerror
7132 (FLG_TYPE,
7133 message ("Function types are inconsistent. Parameter %d is "
7134 "normal parameter, but sef returns parameter in "
7135 "assigned function: %s",
7136 paramno, exprNode_unparse (e)),
7137 exprNode_loc (e));
7138 } else if (u2->info->var->kind == VKSEFPARAM) {
7139 voptgenerror
7140 (FLG_TYPE,
7141 message ("Function types are inconsistent. Parameter %d is "
7142 "normal parameter, but sef parameter in "
7143 "assigned function: %s",
7144 paramno, exprNode_unparse (e)),
7145 exprNode_loc (e));
7146 } else if (u2->info->var->kind == VKRETPARAM) {
7147 voptgenerror
7148 (FLG_TYPE,
7149 message ("Function types are inconsistent. Parameter %d is "
7150 "normal parameter, but returns parameter in "
7151 "assigned function: %s",
7152 paramno, exprNode_unparse (e)),
7153 exprNode_loc (e));
7154 } else {
7155 BADBRANCH;
7156 }
7157 }
7158 }
7159
7160 if (u1->info->var->defstate != u2->info->var->defstate)
7161 {
7162 voptgenerror
7163 (FLG_TYPE,
7164 message ("Function types are inconsistent. Parameter %d is "
7165 "%s, but %s in assigned function: %s",
7166 paramno,
7167 sstate_unparse (u1->info->var->defstate),
7168 sstate_unparse (u2->info->var->defstate),
7169 exprNode_unparse (e)),
7170 exprNode_loc (e));
7171 }
7172
7173 if (u1->info->var->nullstate != u2->info->var->nullstate)
7174 {
7175 voptgenerror
7176 (FLG_TYPE,
7177 message ("Function types are inconsistent. Parameter %d is "
7178 "%s, but %s in assigned function: %s",
7179 paramno,
7180 nstate_unparse (u1->info->var->nullstate),
7181 nstate_unparse (u2->info->var->nullstate),
7182 exprNode_unparse (e)),
7183 exprNode_loc (e));
7184 }
7185
7186 if (sRef_getAliasKind (u1->sref) != sRef_getAliasKind (u2->sref))
7187 {
7188 voptgenerror
7189 (FLG_TYPE,
7190 message ("Function types are inconsistent. Parameter %d is "
7191 "%s, but %s in assigned function: %s",
7192 paramno,
7193 alkind_unparse (sRef_getAliasKind (u1->sref)),
7194 alkind_unparse (sRef_getAliasKind (u2->sref)),
7195 exprNode_unparse (e)),
7196 exprNode_loc (e));
7197 }
7198
7199 if (sRef_getExKind (u1->sref) != sRef_getExKind (u2->sref))
7200 {
7201 voptgenerror
7202 (FLG_TYPE,
7203 message ("Function types are inconsistent. Parameter %d is "
7204 "%s, but %s in assigned function: %s",
7205 paramno,
7206 exkind_unparse (sRef_getExKind (u1->sref)),
7207 exkind_unparse (sRef_getExKind (u2->sref)),
7208 exprNode_unparse (e)),
7209 exprNode_loc (e));
7210 }
7211}
7212
7213static void
7214checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old,
7215 /*@notnull@*/ uentry unew,
7216 bool mustConform, /*@unused@*/ bool completeConform)
7217{
7218 uentryList oldParams = uentry_getParams (old);
7219 uentryList newParams = uentry_getParams (unew);
7220 ctype newType = unew->utype;
7221 ctype oldType = old->utype;
7222 ctype oldRetType = ctype_unknown;
7223 ctype newRetType = ctype_unknown;
7224
7225 if (uentry_isForward (old))
7226 {
7227 mustConform = FALSE;
7228 uentry_copyInto (old, unew);
7229 return;
7230 }
7231
7232 /*
7233 ** check return values
7234 */
7235
7236 if (ctype_isKnown (oldType))
7237 {
7238 llassert (ctype_isFunction (oldType));
7239
7240 oldRetType = ctype_returnValue (oldType);
7241 }
7242
7243 if (ctype_isKnown (newType))
7244 {
7245 llassert (ctype_isFunction (newType));
7246
7247 newRetType = ctype_returnValue (newType);
7248 }
7249
7250 if (ctype_isKnown (oldRetType) && ctype_isKnown (newRetType)
7251 && !ctype_matchDef (newRetType, oldRetType))
7252 {
7253 if (mustConform) returnValueError (old, unew);
7254 }
7255 else
7256 {
7257 if (ctype_isConj (newRetType))
7258 {
7259 if (ctype_isConj (oldRetType))
7260 {
7261 if (!ctype_sameAltTypes (newRetType, oldRetType))
7262 {
7263 if (optgenerror
7264 (FLG_INCONDEFS,
7265 message ("Function %q inconsistently %rdeclared to "
7266 "return alternate types %s "
7267 "(types match, but alternates are not identical, "
7268 "so checking may not be correct)",
7269 uentry_getName (unew),
7270 uentry_isDeclared (old),
7271 ctype_unparse (newRetType)),
7272 uentry_whereDeclared (unew)))
7273 {
7274 uentry_showWhereLastVal (old, ctype_unparse (oldRetType));
7275 }
7276 }
7277 }
7278 else
7279 {
7280 old->utype = ctype_makeFunction (oldRetType, uentryList_copy (newParams));
7281 }
7282 }
7283 }
7284
7285 uentry_checkStateConformance (old, unew, mustConform, completeConform);
7286
7287 if (!exitkind_equal (unew->info->fcn->exitCode, old->info->fcn->exitCode))
7288 {
7289 if (exitkind_isKnown (unew->info->fcn->exitCode))
7290 {
7291 if (optgenerror
7292 (FLG_INCONDEFS,
7293 message ("Function %q inconsistently %rdeclared using %s",
7294 uentry_getName (unew),
7295 uentry_isDeclared (old),
7296 exitkind_unparse (unew->info->fcn->exitCode)),
7297 uentry_whereDeclared (unew)))
7298 {
7299 uentry_showWhereSpecified (old);
7300 }
7301 }
7302 else
7303 {
7304 unew->info->fcn->exitCode = old->info->fcn->exitCode;
7305 }
7306 }
7307
7308 if (!qual_isUnknown (unew->info->fcn->nullPred))
7309 {
7310 if (!qual_equal (old->info->fcn->nullPred, unew->info->fcn->nullPred))
7311 {
7312 if (optgenerror
7313 (FLG_INCONDEFS,
7314 message ("Function %q inconsistently %rdeclared using %s",
7315 uentry_getName (unew),
7316 uentry_isDeclared (old),
7317 qual_unparse (unew->info->fcn->nullPred)),
7318 uentry_whereDeclared (unew)))
7319 {
7320 uentry_showWhereSpecified (old);
7321 }
7322 }
7323 }
7324 else
7325 {
7326 unew->info->fcn->nullPred = old->info->fcn->nullPred;
7327 }
7328
7329 if (unew->info->fcn->specialCode != SPC_NONE)
7330 {
7331 if (old->info->fcn->specialCode != unew->info->fcn->specialCode)
7332 {
7333 if (optgenerror
7334 (FLG_INCONDEFS,
7335 message ("Function %q inconsistently %rdeclared using %s",
7336 uentry_getName (unew),
7337 uentry_isDeclared (old),
7338 specCode_unparse (unew->info->fcn->specialCode)),
7339 uentry_whereDeclared (unew)))
7340 {
7341 uentry_showWhereSpecified (old);
7342 }
7343 }
7344 }
7345 else
7346 {
7347 unew->info->fcn->specialCode = old->info->fcn->specialCode;
7348 }
7349
7350 /*
7351 ** check parameters
7352 */
7353
7354 if (!uentryList_sameObject (oldParams, newParams)
7355 && (!uentryList_isMissingParams (oldParams)))
7356 {
7357 if (!uentryList_isMissingParams (newParams))
7358 {
7359 int paramno = 0;
7360 int nparams = uentryList_size (oldParams);
7361 bool checknames = context_maybeSet (FLG_DECLPARAMMATCH);
7362
7363 if (nparams != uentryList_size (newParams))
7364 {
7365 nargsError (old, unew);
7366 }
7367
7368 if (uentryList_size (newParams) < nparams)
7369 {
7370 nparams = uentryList_size (newParams);
7371 }
7372
7373 while (paramno < nparams)
7374 {
7375 uentry oldCurrent = uentryList_getN (oldParams, paramno);
7376 uentry newCurrent = uentryList_getN (newParams, paramno);
7377 ctype oldCurrentType = uentry_getType (oldCurrent);
7378 ctype newCurrentType = uentry_getType (newCurrent);
7379
7380 llassert (uentry_isValid (oldCurrent)
7381 && uentry_isValid (newCurrent));
7382
7383 if (!uentry_isElipsisMarker (oldCurrent)
7384 && !uentry_isElipsisMarker (newCurrent))
7385 {
7386 checkVarConformance (oldCurrent, newCurrent,
7387 mustConform, completeConform);
7388 }
7389
7390 if (checknames)
7391 {
7392 if (uentry_hasName (oldCurrent)
7393 && uentry_hasName (newCurrent))
7394 {
7395 cstring oldname = uentry_getName (oldCurrent);
7396 cstring pfx = context_getString (FLG_DECLPARAMPREFIX);
7397 cstring oname;
7398 cstring nname = uentry_getName (newCurrent);
7399 cstring nnamefix;
7400
7401 if (cstring_isDefined (pfx)
7402 && cstring_equalPrefix (oldname, cstring_toCharsSafe (pfx)))
7403 {
7404 oname = cstring_suffix (oldname, cstring_length (pfx));
7405 }
7406 else
7407 {
7408 oname = oldname;
7409 /*@-branchstate@*/ } /*@=branchstate@*/
7410
7411 if (cstring_isDefined (pfx)
7412 && cstring_equalPrefix (nname, cstring_toCharsSafe (pfx)))
7413 {
7414 nnamefix = cstring_suffix (nname, cstring_length (pfx));
7415 }
7416 else
7417 {
7418 nnamefix = nname;
7419 /*@-branchstate@*/ } /*@=branchstate@*/
7420
7421 if (!cstring_equal (oname, nnamefix))
7422 {
7423 if (optgenerror
7424 (FLG_DECLPARAMMATCH,
7425 message ("Definition parameter name %s does not match "
7426 "name of corresponding parameter in "
7427 "declaration: %s",
7428 nnamefix, oname),
7429 uentry_whereLast (newCurrent)))
7430 {
7431 uentry_showWhereLastPlain (oldCurrent);
7432 }
7433 }
7434
7435 cstring_free (oldname);
7436 cstring_free (nname);
7437 }
7438 }
7439
7440 if (!ctype_match (oldCurrentType, newCurrentType))
7441 {
7442 paramTypeError (old, oldCurrent, oldCurrentType,
7443 unew, newCurrent, newCurrentType, paramno);
7444 }
7445 else
7446 {
7447 if (ctype_isMissingParamsMarker (newCurrentType)
7448 || ctype_isElips (newCurrentType)
7449 || ctype_isMissingParamsMarker (oldCurrentType)
7450 || ctype_isElips (oldCurrentType))
7451 {
7452 ;
7453 }
7454 else
7455 {
7456 if (ctype_isConj (newCurrentType))
7457 {
7458 if (ctype_isConj (oldCurrentType))
7459 {
7460 if (!ctype_sameAltTypes (newCurrentType, oldCurrentType))
7461 {
7462 if (optgenerror
7463 (FLG_INCONDEFS,
7464 message ("Parameter %q inconsistently %rdeclared with "
7465 "alternate types %s "
7466 "(types match, but alternates are not identical, "
7467 "so checking may not be correct)",
7468 uentry_getName (newCurrent),
7469 uentry_isDeclared (oldCurrent),
7470 ctype_unparse (newCurrentType)),
7471 uentry_whereDeclared (unew)))
7472 {
7473 uentry_showWhereLastVal (oldCurrent,
7474 ctype_unparse (oldCurrentType));
7475 }
7476 }
7477 }
7478 else
7479 {
7480 if (optgenerror
7481 (FLG_INCONDEFS,
7482 message ("Parameter %q inconsistently %rdeclared with "
7483 "alternate types %s",
7484 uentry_getName (newCurrent),
7485 uentry_isDeclared (oldCurrent),
7486 ctype_unparse (newCurrentType)),
7487 uentry_whereDeclared (unew)))
7488 {
7489 uentry_showWhereLastVal (oldCurrent,
7490 ctype_unparse (oldCurrentType));
7491
7492 }
7493 }
7494 }
7495 else
7496 {
7497 if (ctype_isConj (oldCurrentType))
7498 {
7499 uentry_setType (newCurrent, oldCurrentType);
7500 }
7501 }
7502 }
7503 }
7504
7505 paramno++;
7506 /*
7507 ** Forgot this! detected by lclint:
7508 ** uentry.c:1257,15: Suspected infinite loop
7509 */
7510 }
7511 }
7512 }
7513
7514 if (!uentryList_isMissingParams (newParams))
7515 {
7516 if (ctype_isConj (oldRetType))
7517 {
7518 old->utype = ctype_makeFunction (oldRetType,
7519 uentryList_copy (newParams));
7520 }
7521 else
7522 {
7523 old->utype = unew->utype;
7524 }
7525 }
7526
7527 checkGlobalsConformance (old, unew, mustConform, completeConform);
7528 checkModifiesConformance (old, unew, mustConform, completeConform);
7529
a0a162cd 7530 if (specialClauses_isDefined (unew->info->fcn->specclauses))
885824d3 7531 {
a0a162cd 7532 if (!specialClauses_isDefined (old->info->fcn->specclauses))
885824d3 7533 {
7534 if (optgenerror
7535 (FLG_INCONDEFS,
7536 message ("Function %q redeclared using special clauses (can only "
7537 "be used in first declaration)",
7538 uentry_getName (unew)),
7539 uentry_whereDeclared (unew)))
7540 {
7541 uentry_showWhereLast (old);
7542 }
7543 }
7544 else
7545 {
7546 specialClauses_checkEqual (old, unew);
7547 }
7548 }
7549
7550 if (fileloc_isUndefined (old->whereDeclared))
7551 {
7552 old->whereDeclared = fileloc_copy (unew->whereDeclared);
7553 }
7554 else if (fileloc_isUndefined (unew->whereDeclared))
7555 {
7556 unew->whereDeclared = fileloc_copy (old->whereDeclared);
7557 }
7558 else
7559 {
7560 /* no change */
7561 }
7562}
7563
7564void
7565uentry_mergeConstantValue (uentry ue, /*@only@*/ multiVal m)
7566{
7567 multiVal uval;
7568
7569 llassert (uentry_isValid (ue));
7570 llassert (uentry_isEitherConstant (ue));
7571
7572 uval = ue->info->uconst->val;
7573
7574 if (multiVal_isDefined (uval))
7575 {
7576 if (multiVal_isDefined (m))
7577 {
7578 if (!multiVal_equiv (uval, m))
7579 {
7580 if (optgenerror
7581 (FLG_INCONDEFS,
7582 message ("%s %q defined with inconsistent value: %q",
7583 ekind_capName (ue->ukind),
7584 uentry_getName (ue),
7585 multiVal_unparse (m)),
7586 g_currentloc))
7587 {
7588 uentry_showWhereLastExtra (ue, multiVal_unparse (uval));
7589 }
7590 }
7591 }
7592 multiVal_free (m);
7593 }
7594 else
7595 {
7596 ue->info->uconst->val = m;
7597 multiVal_free (uval);
7598 }
7599}
7600
7601static
7602bool checkTypeConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
7603 bool mustConform)
7604{
7605 bool typeError = FALSE;
7606
7607 if (uentry_isStructTag (old) || uentry_isUnionTag (old))
7608 {
7609 if (ctype_isSU (old->utype) && ctype_isSU (unew->utype))
7610 {
7611 if (mustConform)
7612 {
7613 checkStructConformance (old, unew);
7614 }
7615 }
7616 else
7617 {
7618 if (!(ctype_isBogus (old->utype) || ctype_isBogus (unew->utype)))
7619 {
7620 llbug (message ("struct tags: bad types: %t / %t",
7621 old->utype, unew->utype));
7622 }
7623 }
7624 }
7625 else if (uentry_isEnumTag (old))
7626 {
7627 if (ctype_isEnum (old->utype) && ctype_isEnum (unew->utype))
7628 {
7629 if (mustConform) checkEnumConformance (old, unew);
7630 }
7631 else
7632 {
7633 if (!(ctype_isBogus (old->utype) || ctype_isBogus (unew->utype)))
7634 {
7635 llbug (message ("enum! bad type: %s / %s", ctype_unparse (old->utype),
7636 ctype_unparse (unew->utype)));
7637 }
7638 }
7639 }
7640 else if (!ctype_match (old->utype, unew->utype))
7641 {
7642 if (cstring_equal (uentry_rawName (old), context_getBoolName ()))
7643 {
7644 ctype realt = ctype_realType (unew->utype);
7645
7646 if (ctype_isRealInt (realt) || ctype_isChar (realt))
7647 {
7648 unew->utype = ctype_bool;
7649 }
7650 else
7651 {
7652 if (mustConform)
7653 {
7654 typeError = optgenerror
7655 (FLG_INCONDEFS,
7656 message ("%q defined as %s", uentry_getName (old),
7657 ctype_unparse (realt)),
7658 uentry_whereDeclared (unew));
7659 }
7660 }
7661 }
7662 else
7663 {
7664 if (mustConform)
7665 {
7666 ctype oldr = ctype_realType (old->utype);
7667 ctype newr = ctype_realType (unew->utype);
7668
7669 if (ctype_isStruct (oldr) && ctype_isStruct (newr))
7670 {
7671 checkStructConformance (old, unew);
7672 }
7673 else if (ctype_isUnion (oldr) && ctype_isUnion (newr))
7674 {
7675 checkStructConformance (old, unew);
7676 }
7677 else if (ctype_isEnum (oldr) && ctype_isEnum (newr))
7678 {
7679 checkEnumConformance (old, unew);
7680 }
7681 else if (uentry_isConstant (old)
7682 && (ctype_isAbstract (oldr) && ctype_isEnum (newr)))
7683 {
7684 /* okay...for now! (should check the type is reset later... */
7685 }
7686 else
7687 {
a0a162cd 7688 DPRINTF (("YABA!"));
885824d3 7689 if (optgenerror
7690 (FLG_INCONDEFS,
7691 message ("%s %q %rdeclared with inconsistent type: %t",
7692 ekind_capName (unew->ukind),
7693 uentry_getName (unew),
7694 uentry_isDeclared (old),
7695 unew->utype),
7696 uentry_whereDeclared (unew)))
7697 {
7698 uentry_showWhereLast (old);
7699 typeError = TRUE;
7700 }
7701 }
7702 }
7703 }
7704 }
7705 else
7706 {
7707 /* no error */
7708 }
7709
7710 return typeError;
7711}
7712
7713static void
7714uentry_checkDatatypeConformance (/*@notnull@*/ uentry old,
7715 /*@notnull@*/ uentry unew,
7716 bool mustConform, bool completeConform)
7717{
7718 if (ctype_isDefined (unew->info->datatype->type))
7719 {
a0a162cd 7720 /*
7721 ** bool is hard coded here, since it is built into LCL.
7722 ** For now, we're stuck with LCL's types.
7723 */
7724
885824d3 7725 if (ctype_isDirectBool (old->utype) &&
7726 cstring_equalLit (unew->uname, "bool"))
7727 {
a0a162cd 7728 /* if (!context_getFlag (FLG_ABSTRACTBOOL))
7729 evs 2000-07-25: removed
7730 */
885824d3 7731 unew->utype = ctype_bool;
885824d3 7732 }
7733
7734 if (ctype_isUnknown (old->info->datatype->type))
7735 {
7736 old->info->datatype->type = unew->info->datatype->type;
7737 }
7738 else
7739 {
a0a162cd 7740 DPRINTF (("Old: %s / New: %s",
7741 uentry_unparseFull (old),
7742 uentry_unparseFull (unew)));
7743 DPRINTF (("Types: %s / %s",
7744 ctype_unparse (old->info->datatype->type),
7745 ctype_unparse (unew->info->datatype->type)));
7746
885824d3 7747 if (ctype_matchDef (old->info->datatype->type,
a0a162cd 7748 unew->info->datatype->type))
885824d3 7749 {
7750 ;
7751 }
7752 else
7753 {
7754 if (optgenerror
7755 (FLG_INCONDEFS,
7756 message
7757 ("Type %q %s with inconsistent type: %t",
7758 uentry_getName (unew),
7759 uentry_reDefDecl (old, unew),
7760 unew->info->datatype->type),
7761 uentry_whereDeclared (unew)))
7762 {
7763 uentry_showWhereLastExtra
7764 (old, cstring_copy (ctype_unparse (old->info->datatype->type)));
7765 }
7766
7767 old->info->datatype->type = unew->info->datatype->type;
7768 }
7769 }
7770 }
7771
7772 if (unew->info->datatype->abs != MAYBE)
7773 {
7774 if (ynm_isOff (old->info->datatype->abs)
7775 && ynm_isOn (unew->info->datatype->abs))
7776 {
7777 if (!ctype_isDirectBool (old->utype))
7778 {
7779 if (optgenerror
7780 (FLG_INCONDEFS,
7781 message
7782 ("Datatype %q inconsistently %rdeclared as abstract type",
7783 uentry_getName (unew),
7784 uentry_isDeclared (old)),
7785 uentry_whereDeclared (unew)))
7786 {
7787 uentry_showWhereLastPlain (old);
7788 }
7789 }
7790 }
7791 else if (ynm_isOn (old->info->datatype->abs)
7792 && ynm_isOff (unew->info->datatype->abs))
7793 {
7794 if (!ctype_isDirectBool (old->utype))
7795 {
7796 if (optgenerror
7797 (FLG_INCONDEFS,
7798 message
7799 ("Datatype %q inconsistently %rdeclared as concrete type",
7800 uentry_getName (unew),
7801 uentry_isDeclared (old)),
7802 uentry_whereDeclared (unew)))
7803 {
7804 uentry_showWhereLastPlain (old);
7805 }
7806 }
7807 }
7808 else
7809 {
7810 ;
7811 }
7812 }
7813 else
7814 {
7815 if (ynm_isOn (old->info->datatype->abs))
7816 {
7817 old->sref = unew->sref;
7818 unew->info->datatype->mut = old->info->datatype->mut;
7819
7820 if (completeConform
7821 && uentry_isReallySpecified (old))
7822 {
7823 if (optgenerror
7824 (FLG_NEEDSPEC,
7825 message
7826 ("Datatype %q specified as abstract, "
7827 "but abstract annotation not used in declaration",
7828 uentry_getName (unew)),
7829 uentry_whereDeclared (unew)))
7830 {
7831 uentry_showWhereLastPlain (old);
7832 }
7833 }
7834 }
7835 }
7836
7837 unew->info->datatype->abs = old->info->datatype->abs;
7838
7839 if (ynm_isMaybe (unew->info->datatype->mut))
7840 {
7841 if (completeConform && ynm_isOff (old->info->datatype->mut)
7842 && uentry_isReallySpecified (old))
7843 {
7844 if (optgenerror
7845 (FLG_NEEDSPEC,
7846 message
7847 ("Datatype %q specified as immutable, "
7848 "but immutable annotation not used in declaration",
7849 uentry_getName (unew)),
7850 uentry_whereDeclared (unew)))
7851 {
7852 uentry_showWhereLastPlain (old);
7853 }
7854 }
7855
7856 unew->info->datatype->mut = old->info->datatype->mut;
7857 }
7858 else if (ynm_isMaybe (old->info->datatype->mut))
7859 {
7860 old->info->datatype->mut = unew->info->datatype->mut;
7861 }
7862 else
7863 {
7864 if (ynm_isOn (old->info->datatype->abs))
7865 {
7866 if (ynm_isOn (old->info->datatype->mut) && ynm_isOff (unew->info->datatype->mut))
7867 {
7868 if (optgenerror
7869 (FLG_INCONDEFS,
7870 message ("Datatype %q inconsistently %rdeclared as immutable",
7871 uentry_getName (unew),
7872 uentry_isDeclared (old)),
7873 uentry_whereDeclared (unew)))
7874 {
7875 uentry_showWhereLastPlain (old);
7876 }
7877 }
7878 else
7879 {
7880 if (ynm_isOff (old->info->datatype->mut)
7881 && ynm_isOn (unew->info->datatype->mut))
7882 {
7883 if (optgenerror
7884 (FLG_INCONDEFS,
7885 message ("Datatype %q inconsistently %rdeclared as mutable",
7886 uentry_getName (unew),
7887 uentry_isDeclared (old)),
7888 uentry_whereDeclared (unew)))
7889 {
7890 uentry_showWhereLastPlain (old);
7891 }
7892 }
7893 }
7894 }
7895 old->info->datatype->mut = unew->info->datatype->mut;
7896 }
7897
7898 uentry_checkStateConformance (old, unew, mustConform, completeConform);
7899}
7900
7901static void
7902uentry_checkConstantConformance (/*@notnull@*/ uentry old,
7903 /*@notnull@*/ uentry unew,
7904 bool mustConform,
7905 /*@unused@*/ bool completeConform)
7906{
7907 multiVal oldVal = old->info->uconst->val;
7908 multiVal newVal = unew->info->uconst->val;
7909
7910 if (multiVal_isDefined (oldVal))
7911 {
7912 if (multiVal_isDefined (newVal))
7913 {
7914 if (!multiVal_equiv (oldVal, newVal))
7915 {
7916 if (mustConform
7917 && optgenerror
7918 (FLG_INCONDEFS,
7919 message ("%s %q %rdeclared with inconsistent value: %q",
7920 ekind_capName (unew->ukind),
7921 uentry_getName (unew),
7922 uentry_isDeclared (old),
7923 multiVal_unparse (newVal)),
7924 uentry_whereDeclared (unew)))
7925 {
7926 uentry_showWhereLastExtra (old, multiVal_unparse (oldVal));
7927 }
7928 }
7929
7930 unew->info->uconst->val = multiVal_copy (oldVal);
7931 multiVal_free (newVal);
7932 }
7933 else
7934 {
7935 ;
7936 }
7937 }
7938 else
7939 {
7940 old->info->uconst->val = multiVal_copy (newVal);
7941 }
7942}
7943
7944static void
7945uentry_checkConformance (/*@unique@*/ /*@notnull@*/ uentry old,
7946 /*@notnull@*/ uentry unew, bool mustConform,
7947 bool completeConform)
7948{
7949 bool typeError = FALSE;
7950 bool fcnConformance = FALSE;
7951
7952 if (!ekind_equal (unew->ukind, old->ukind))
7953 {
7954 /*
7955 ** okay, only if one is a function and the other is
7956 ** a variable of type function.
7957 */
7958
7959 if (unew->ukind == KENUMCONST
7960 && old->ukind == KCONST)
7961 {
7962 old->ukind = KENUMCONST;
7963 goto nokinderror;
7964 }
7965
7966 if (unew->ukind == KFCN
7967 && old->ukind == KCONST
7968 && ctype_isUnknown (old->utype))
7969 {
7970 /*
7971 ** When a function is defined with an unparam macro
7972 */
7973
7974 uentry_copyInto (old, unew);
7975 return;
7976 }
7977
7978 if (uentry_isExpandedMacro (old)
7979 && uentry_isEitherConstant (unew))
7980 {
7981 uentry_copyInto (old, unew);
7982 return;
7983 }
7984
7985 if (uentry_isEndIter (unew))
7986 {
7987 if (ctype_isUnknown (old->utype))
7988 {
7989 if (!uentry_isSpecified (old)
7990 && uentry_isCodeDefined (unew))
7991 {
7992 if (!fileloc_withinLines (uentry_whereDefined (old),
7993 uentry_whereDeclared (unew), 2))
7994 { /* bogus! will give errors if there is too much whitespace */
7995 voptgenerror
7996 (FLG_SYNTAX,
7997 message
7998 ("Iterator finalized name %q does not match name in "
7999 "previous iter declaration (should be end_%q). This iter "
8000 "is declared at %q",
8001 uentry_getName (unew),
8002 uentry_getName (old),
8003 fileloc_unparse (uentry_whereDefined (old))),
8004 uentry_whereDeclared (old));
8005 }
8006 }
8007
8008 uentry_copyInto (old, unew);
8009 return;
8010 }
8011 else
8012 {
8013 KindConformanceError (old, unew, mustConform);
8014 }
8015 }
8016
8017 if (uentry_isFunction (unew))
8018 {
8019 if (uentry_isVariable (old))
8020 {
8021 if (!ctype_isUnknown (old->utype))
8022 {
8023 if (ctype_isFunction (old->utype))
8024 {
8025 uentry_makeVarFunction (old);
8026 checkFunctionConformance (old, unew, mustConform,
8027 completeConform);
8028 fcnConformance = TRUE;
8029 }
8030 else
8031 {
8032 KindConformanceError (old, unew, mustConform);
8033 }
8034 }
8035 else
8036 {
8037 if (uentry_isExpandedMacro (old))
8038 {
8039 if (fileloc_isUndefined (unew->whereDefined))
8040 {
8041 unew->whereDefined = fileloc_update (unew->whereDefined,
8042 old->whereDefined);
8043 }
8044
8045 uentry_copyInto (old, unew);
8046 old->used = unew->used = TRUE;
8047 return;
8048 }
8049 else
8050 {
8051 /* undeclared identifier */
8052 old->utype = unew->utype;
8053 uentry_makeVarFunction (old);
8054 checkFunctionConformance (old, unew, FALSE, FALSE);
8055 fcnConformance = TRUE;
8056 }
8057 }
8058 }
8059 else
8060 {
8061 KindConformanceError (old, unew, mustConform);
8062 }
8063 }
8064 else if (uentry_isFunction (old) && uentry_isVariable (unew))
8065 {
8066 if (!ctype_isUnknown (unew->utype))
8067 {
8068 if (ctype_isFunction (unew->utype))
8069 {
8070 uentry_makeVarFunction (unew);
8071 checkFunctionConformance (old, unew, mustConform, completeConform);
8072 fcnConformance = TRUE;
8073 }
8074 else
8075 {
8076 KindConformanceError (old, unew, mustConform);
8077 }
8078 }
8079 else
8080 {
8081 KindConformanceError (old, unew, mustConform);
8082 }
8083 }
8084 else
8085 {
8086 KindConformanceError (old, unew, mustConform);
8087 }
8088 }
8089 else
8090 {
8091 /*
8092 ** check parameter lists for functions
8093 ** (before type errors, to get better messages
8094 */
8095
8096 if (uentry_isFunction (old))
8097 {
8098 checkFunctionConformance (old, unew, mustConform, completeConform);
8099 fcnConformance = TRUE;
8100 }
8101 else
8102 {
8103 if (!ctype_isUndefined (old->utype))
8104 {
8105 typeError = checkTypeConformance (old, unew, mustConform);
8106 }
8107 }
8108 }
8109
8110 nokinderror:
8111
8112 if (uentry_isEitherConstant (old) && uentry_isEitherConstant (unew))
8113 {
8114 uentry_checkConstantConformance (old, unew, mustConform, completeConform);
8115 }
8116
8117 if (uentry_isDatatype (old) && uentry_isDatatype (unew))
8118 {
a0a162cd 8119 DPRINTF (("Check datatype: %s / %s",
8120 uentry_unparseFull (old),
8121 uentry_unparseFull (unew)));
8122
885824d3 8123 uentry_checkDatatypeConformance (old, unew, mustConform, completeConform);
8124 }
8125
8126 if (uentry_isVariable (old) && uentry_isVariable (unew))
8127 {
8128 if (!typeError &&
8129 !ctype_matchDef (old->utype, unew->utype))
8130 {
8131 if (optgenerror
8132 (FLG_INCONDEFS,
8133 message
8134 ("Variable %q %s with inconsistent type (arrays and pointers are "
8135 "not identical in variable declarations): %t",
8136 uentry_getName (unew),
8137 uentry_reDefDecl (old, unew),
8138 unew->utype),
8139 uentry_whereDeclared (unew)))
8140 {
8141 uentry_showWhereLast (old);
8142
8143 /*
8144 ** Avoid repeated errors.
8145 */
8146
8147 if (uentry_isCodeDefined (old) && uentry_isCodeDefined (unew))
8148 {
8149 old->whereDefined = fileloc_update (old->whereDefined,
8150 fileloc_undefined);
8151 }
8152
8153 typeError = TRUE;
8154 }
8155 }
8156
8157 checkVarConformance (old, unew, mustConform, completeConform);
8158 }
8159
8160 if (fcnConformance)
8161 {
8162 /* old->utype = unew->utype; */
8163 }
8164 else
8165 {
8166 if (ctype_isConj (old->utype))
8167 {
8168 if (ctype_isConj (unew->utype))
8169 {
8170 if (!ctype_sameAltTypes (old->utype, unew->utype))
8171 {
8172 if (optgenerror
8173 (FLG_INCONDEFS,
8174 message ("%s %q inconsistently %rdeclared with "
8175 "alternate types %s "
8176 "(types match, but alternates are not identical, "
8177 "so checking may not be correct)",
8178 ekind_capName (uentry_getKind (old)),
8179 uentry_getName (unew),
8180 uentry_isDeclared (old),
8181 ctype_unparse (unew->utype)),
8182 uentry_whereDeclared (unew)))
8183 {
8184 uentry_showWhereLastVal (old, ctype_unparse (old->utype));
8185 }
8186 else
8187 {
8188 old->utype = unew->utype;
8189 }
8190 }
8191 }
8192 }
8193 else
8194 {
8195 if (ctype_isUnknown (old->utype))
8196 {
8197 old->utype = unew->utype;
8198 }
8199 }
8200 }
8201
8202 if (unew->ukind == old->ukind)
8203 {
8204 sfree (unew->info);
8205 unew->info = uinfo_copy (old->info, old->ukind);
8206 }
8207
8208 sRef_storeState (old->sref);
8209 sRef_storeState (unew->sref);
8210}
8211
8212/*
8213** modifies spec to reflect def, reports any inconsistencies
8214*/
8215
8216void
8217uentry_mergeEntries (uentry spec, /*@only@*/ uentry def)
8218{
8219 llassert (uentry_isValid (spec));
8220 llassert (uentry_isValid (def));
8221 llassert (cstring_equal (spec->uname, def->uname));
8222
8223 uentry_checkConformance (spec, def, TRUE,
8224 context_getFlag (FLG_NEEDSPEC));
8225
8226 /* was: !(fileloc_isImport (uentry_whereSpecified (spec)))); */
8227
8228 /*
8229 ** okay, declarations conform. Propagate extra information.
8230 */
8231
8232 uentry_setDefined (spec, uentry_whereDefined (def));
8233 uentry_setDeclared (spec, uentry_whereDeclared (def));
8234
8235 if (uentry_isStatic (def))
8236 {
8237 if (optgenerror
8238 (FLG_INCONDEFS,
8239 message ("%s %q specified, but declared as static",
8240 ekind_capName (def->ukind),
8241 uentry_getName (def)),
8242 uentry_whereDeclared (def)))
8243 {
8244 uentry_showWhereSpecified (spec);
8245 }
8246 }
8247 else
8248 {
8249 spec->storageclass = def->storageclass;
8250 }
8251
8252 sRef_storeState (spec->sref);
8253
8254 spec->used = def->used || spec->used;
8255 spec->hasNameError |= def->hasNameError;
8256
8257 uentry_free (def);
8258
8259 if (!spec->hasNameError)
8260 {
8261 uentry_checkName (spec);
8262 }
8263 else
8264 {
8265 ;
8266 }
8267}
8268
8269/*
8270** Can't generate function redeclaration errors when the
8271** entries are merged, since we don't yet know if its the
8272** definition of the function.
8273*/
8274
8275void
8276uentry_clearDecl (void)
8277{
8278 posRedeclared = uentry_undefined;
8279 fileloc_free (posLoc);
8280 posLoc = fileloc_undefined;
8281}
8282
8283void
8284uentry_checkDecl (void)
8285{
8286 if (uentry_isValid (posRedeclared))
8287 {
8288 llassert (fileloc_isDefined (posLoc));
8289
8290 if (uentry_isCodeDefined (posRedeclared))
8291 {
8292 if (optgenerror (FLG_REDECL,
8293 message ("%s %q declared after definition",
8294 ekind_capName (posRedeclared->ukind),
8295 uentry_getName (posRedeclared)),
8296 posLoc))
8297 {
8298 llgenindentmsg (message ("Definition of %q",
8299 uentry_getName (posRedeclared)),
8300 posRedeclared->whereDeclared);
8301 }
8302 }
8303 else
8304 {
8305 if (optgenerror (FLG_REDECL,
8306 message ("%s %q declared more than once",
8307 ekind_capName (posRedeclared->ukind),
8308 uentry_getName (posRedeclared)),
8309 posLoc))
8310 {
8311 llgenindentmsg (message ("Previous declaration of %q",
8312 uentry_getName (posRedeclared)),
8313 posRedeclared->whereDeclared);
8314 }
8315 }
8316 }
8317
8318 fileloc_free (posLoc);
8319 posLoc = fileloc_undefined;
8320 posRedeclared = uentry_undefined;
8321}
8322
8323/*
8324** Redefinition of old as unew.
8325** modifies old to reflect unew, reports any inconsistencies
8326*/
8327
8328void
8329uentry_mergeDefinition (uentry old, /*@only@*/ uentry unew)
8330{
8331 fileloc olddef = uentry_whereDeclared (old);
8332 fileloc unewdef = uentry_whereDeclared (unew);
8333 bool mustConform;
8334 bool wasForward;
8335
8336 if (uentry_isExtern (unew))
8337 {
8338 uentry_setUsed (old, unewdef);
8339 }
8340
8341 wasForward =
8342 fileloc_isUndefined (olddef)
8343 && fileloc_isDefined (uentry_whereDefined (old))
8344 && !uentry_isExpandedMacro (old);
8345
8346 if (!context_getFlag (FLG_INCONDEFSLIB)
8347 && (fileloc_isLib (olddef) || fileloc_isImport (olddef)))
8348 {
8349 mustConform = FALSE;
8350 }
8351 else
8352 {
8353 mustConform = TRUE;
8354 }
8355
8356 llassert (uentry_isValid (old));
8357 llassert (uentry_isValid (unew));
8358 llassert (cstring_equal (old->uname, unew->uname));
8359
8360 /*
8361 ** should check old one was extern!
8362 */
8363
8364 if (uentry_isStatic (old))
8365 {
8366 if (!(uentry_isStatic (unew)))
8367 {
8368 if (optgenerror
8369 (FLG_SHADOW,
8370 message ("%s %q shadows static declaration",
8371 ekind_capName (unew->ukind),
8372 uentry_getName (unew)),
8373 unewdef))
8374 {
8375 uentry_showWhereLast (old);
8376 }
8377 }
8378 else
8379 {
8380 uentry_setDeclDef (old, unewdef);
8381 }
8382 }
8383 else if (uentry_isStatic (unew))
8384 {
8385 uentry_setDeclDef (old, unewdef);
8386 }
8387 else if (uentry_isExtern (old))
8388 {
8389 uentry_setDeclared (old, unewdef);
8390 }
8391 else
8392 {
8393 if (!uentry_isExtern (unew) && !uentry_isForward (old)
8394 && !fileloc_equal (olddef, unewdef)
8395 && !fileloc_isUndefined (olddef)
8396 && !fileloc_isUndefined (unewdef)
8397 && !fileloc_isBuiltin (olddef)
8398 && !fileloc_isBuiltin (unewdef)
8399 && !uentry_isYield (old)
8400 && !(fileloc_isLib (olddef) || fileloc_isImport (olddef)))
8401 {
8402 if (uentry_isVariable (old) || uentry_isVariable (unew))
8403 {
8404 ; /* will report redeclaration error later */
8405 }
8406 else
8407 {
8408 if (fileloc_isDefined (uentry_whereDefined (old)))
8409 {
8410 if (optgenerror
8411 (FLG_REDEF,
8412 message ("%s %q defined more than once",
8413 ekind_capName (unew->ukind),
8414 uentry_getName (unew)),
8415 uentry_whereLast (unew)))
8416 {
8417 llgenindentmsg
8418 (message ("Previous definition of %q",
8419 uentry_getName (old)),
8420 uentry_whereLast (old));
8421 }
8422 /*
8423 if (uentry_isDatatype (old) || uentry_isAnyTag (old))
8424 {
8425 uentry_copyInto (old, unew);
8426 old->sref = sRef_saveCopy (old->sref);
8427 }
8428 */
8429 }
8430 }
8431 }
8432 else
8433 {
8434 if (fileloc_isLib (olddef)
8435 || fileloc_isUndefined (olddef)
8436 || fileloc_isImport (olddef))
8437 {
8438 if (uentry_isExtern (unew))
8439 {
8440 if (uentry_isExtern (old)
8441 || (fileloc_isDefined (uentry_whereDeclared (old))
8442 && (!fileloc_equal (uentry_whereDeclared (old),
8443 uentry_whereDefined (old)))))
8444 {
8445 if (optgenerror
8446 (FLG_REDECL,
8447 message ("%s %q declared more than once",
8448 ekind_capName (unew->ukind),
8449 uentry_getName (unew)),
8450 unew->whereDeclared))
8451 {
8452 llgenindentmsg
8453 (message ("Previous declaration of %q",
8454 uentry_getName (old)),
8455 old->whereDeclared);
8456 }
8457 }
8458
8459 uentry_setExtern (old);
8460 }
8461 else
8462 {
8463 uentry_setDefined (old, unewdef);
8464 }
8465 }
8466 }
8467 }
8468
8469 uentry_checkConformance (old, unew, mustConform, FALSE);
8470
8471 old->used = old->used || unew->used;
8472 old->uses = filelocList_append (old->uses, unew->uses);
8473 unew->uses = filelocList_undefined;
8474
8475 sRef_storeState (old->sref);
8476 sRef_storeState (unew->sref);
8477
8478 if (wasForward)
8479 {
8480 old->whereDefined = fileloc_update (old->whereDefined,
8481 fileloc_undefined);
8482 }
8483
8484 /*
8485 ** No redeclaration errors for functions here, since we
8486 ** don't know if this is the definition of the function.
8487 */
8488
8489 if (fileloc_isUser (old->whereDeclared)
8490 && fileloc_isUser (unew->whereDeclared)
8491 && !fileloc_equal (old->whereDeclared, unew->whereDeclared)
8492 && !fileloc_isDefined (unew->whereDefined))
8493 {
8494 if (uentry_isFunction (old))
8495 {
8496 /*@-temptrans@*/ posRedeclared = old; /*@=temptrans@*/
8497 posLoc = fileloc_update (posLoc, unew->whereDeclared);
8498 }
8499 else
8500 {
8501 if (optgenerror (FLG_REDECL,
8502 message ("%s %q declared more than once",
8503 ekind_capName (unew->ukind),
8504 uentry_getName (unew)),
8505 unew->whereDeclared))
8506 {
8507 llgenindentmsg (message ("Previous declaration of %q",
8508 uentry_getName (old)),
8509 old->whereDeclared);
8510 }
8511 }
8512 }
8513
8514 if (fileloc_isUndefined (old->whereDefined))
8515 {
8516 old->whereDefined = fileloc_update (old->whereDefined, unew->whereDefined);
8517 }
8518 else
8519 {
8520 if (!context_processingMacros ()
8521 && fileloc_isUser (old->whereDefined)
8522 && fileloc_isUser (unew->whereDefined)
8523 && !fileloc_equal (old->whereDefined, unew->whereDefined))
8524 {
8525 if (uentry_isVariable (unew) || uentry_isFunction (unew))
8526 {
8527 if (uentry_isVariable (unew)
8528 && uentry_isExtern (unew))
8529 {
8530 if (optgenerror (FLG_REDECL,
8531 message ("%s %q declared after definition",
8532 ekind_capName (unew->ukind),
8533 uentry_getName (unew)),
8534 unew->whereDeclared))
8535 {
8536 llgenindentmsg (message ("Definition of %q",
8537 uentry_getName (old)),
8538 old->whereDefined);
8539 }
8540 }
8541 else
8542 {
8543 if (optgenerror (FLG_REDEF,
8544 message ("%s %q redefined",
8545 ekind_capName (unew->ukind),
8546 uentry_getName (unew)),
8547 unew->whereDefined))
8548 {
8549 llgenindentmsg (message ("Previous definition of %q",
8550 uentry_getName (old)),
8551 old->whereDefined);
8552 }
8553 }
8554 }
8555 }
8556 }
8557
8558 if (uentry_isExternal (unew))
8559 {
8560 old->whereDefined = fileloc_createExternal ();
8561 }
8562
8563 if (unew->hasNameError)
8564 {
8565 old->hasNameError = TRUE;
8566 }
8567
8568 uentry_free (unew);
8569
8570 if (!old->hasNameError)
8571 {
8572 uentry_checkName (old);
8573 }
8574
8575 llassert (!ctype_isUndefined (old->utype));
8576}
8577
8578void
8579uentry_copyState (uentry res, uentry other)
8580{
8581 llassert (uentry_isValid (res));
8582 llassert (uentry_isValid (other));
8583
8584 res->used = other->used;
8585
8586 res->info->var->kind = other->info->var->kind;
8587 res->info->var->defstate = other->info->var->defstate;
8588 res->info->var->nullstate = other->info->var->nullstate;
8589 res->info->var->checked = other->info->var->checked;
8590
8591 sRef_copyState (res->sref, other->sref);
8592}
8593
8594bool
8595uentry_sameKind (uentry u1, uentry u2)
8596{
8597 if (uentry_isValid (u1) && uentry_isValid (u2))
8598 {
8599 if (uentry_isVar (u1) && uentry_isVar (u2))
8600 {
8601 ctype c1 = u1->utype;
8602 ctype c2 = u2->utype;
8603
8604 if (ctype_isUnknown (c1) || ctype_isUnknown (c2)) return FALSE;
8605
8606 /*
8607 ** both functions, or both not functions
8608 */
8609
8610 return (bool_equal (ctype_isFunction (c1), ctype_isFunction (c2)));
8611 }
8612 else
8613 {
8614 return ((u1->ukind == u2->ukind));
8615 }
8616 }
8617
8618 return FALSE;
8619}
8620
8621static void uentry_copyInto (/*@unique@*/ uentry unew, uentry old)
8622{
8623 llassert (uentry_isValid (unew));
8624 llassert (uentry_isValid (old));
8625
8626 unew->ukind = old->ukind;
8627 unew->uname = cstring_copy (old->uname);
8628 unew->utype = old->utype;
8629
8630 unew->whereSpecified = fileloc_copy (old->whereSpecified);
8631 unew->whereDefined = fileloc_copy (old->whereDefined);
8632 unew->whereDeclared = fileloc_copy (old->whereDeclared);
8633
8634 unew->sref = sRef_saveCopy (old->sref); /* Memory leak! */
8635 unew->used = old->used;
8636 unew->lset = FALSE;
8637 unew->isPrivate = old->isPrivate;
8638 unew->hasNameError = old->hasNameError;
8639 unew->uses = filelocList_undefined;
8640
8641 unew->storageclass = old->storageclass;
8642 unew->info = uinfo_copy (old->info, old->ukind);
8643}
8644
8645
8646uentry
8647uentry_copy (uentry e)
8648{
8649 if (uentry_isValid (e))
8650 {
8651 uentry enew = uentry_alloc ();
8652 DPRINTF (("copy: %s", uentry_unparseFull (e)));
8653 uentry_copyInto (enew, e);
8654 DPRINTF (("Here we are..."));
8655 DPRINTF (("original: %s", uentry_unparseFull (e)));
8656 DPRINTF (("copy: %s", uentry_unparse (enew)));
8657 DPRINTF (("copy: %s", uentry_unparseFull (enew)));
8658 return enew;
8659 }
8660 else
8661 {
8662 return uentry_undefined;
8663 }
8664}
8665
8666void
8667uentry_setState (uentry res, uentry other)
8668{
8669 llassert (uentry_isValid (res));
8670 llassert (uentry_isValid (other));
8671
8672 llassert (res->ukind == other->ukind);
8673 llassert (res->ukind == KVAR);
8674
8675 res->sref = sRef_saveCopy (other->sref);
8676 res->used = other->used;
8677 filelocList_free (res->uses);
8678 res->uses = other->uses;
8679 other->uses = filelocList_undefined;
8680 res->lset = other->lset;
8681}
8682
8683void
8684uentry_mergeUses (uentry res, uentry other)
8685{
8686 llassert (uentry_isValid (res));
8687 llassert (uentry_isValid (other));
8688
8689 res->used = other->used || res->used;
8690 res->lset = other->lset || res->lset;
8691 res->uses = filelocList_append (res->uses, other->uses);
8692 other->uses = filelocList_undefined;
8693}
8694
8695
8696/*
8697** This is a really ugly routine.
8698**
8699** gack...fix this one day.
8700*/
8701
8702/*
8703** flip == TRUE
8704** >> res is the false branch, other is the true branch (or continuation)
8705** flip == FALSE
8706** >> res is the true branch, other is the false branch (or continutation)
8707**
8708** opt == TRUE if,
8709**
8710** <other>
8711** if <res> ;
8712**
8713** References not effected by res are propagated from other.
8714*/
8715
8716static void
8717 branchStateError (/*@notnull@*/ uentry res, /*@notnull@*/ uentry other,
8718 bool flip, clause cl, fileloc loc)
8719{
8720 if (optgenerror
8721 (FLG_BRANCHSTATE,
8722 message ("%s %q is %s %s, but %s %s.",
8723 ekind_capName (res->ukind), uentry_getName (res),
8724 sRef_stateVerb (res->sref), clause_nameFlip (cl, flip),
8725 sRef_stateAltVerb (res->sref), clause_nameFlip (cl, !flip)),
8726 loc))
8727 {
8728 if (sRef_isDead (res->sref))
8729 {
8730 sRef_showStateInfo (res->sref);
8731 }
8732 else if (sRef_isKept (res->sref))
8733 {
8734 sRef_showAliasInfo (res->sref);
8735 }
8736 else /* dependent */
8737 {
8738 sRef_showAliasInfo (res->sref);
8739 sRef_showAliasInfo (other->sref);
8740 }
8741
8742 sRef_setAliasKind (res->sref, AK_ERROR, fileloc_undefined);
8743 }
8744}
8745
8746static bool incompatibleStates (sRef rs, sRef os)
8747{
8748 alkind rk = sRef_getAliasKind (rs);
8749 alkind ok = sRef_getAliasKind (os);
8750
8751 if (alkind_isError (rk) || alkind_isError (ok))
8752 {
8753 return FALSE;
8754 }
8755 else
8756 {
8757 return ((sRef_isDead (rs)
8758 || (alkind_isKept (rk) && !alkind_isKept (ok))
8759 || (alkind_isDependent (rk)
8760 && !alkind_isDependent (ok) && !alkind_isTemp (ok)))
8761 && (sRef_isAllocated (os) || sRef_isStateDefined (os)));
8762 }
8763}
8764
8765static void
8766 branchStateAltError (/*@notnull@*/ uentry res,
8767 /*@notnull@*/ uentry other, bool flip,
8768 clause cl, fileloc loc)
8769{
8770 if (optgenerror
8771 (FLG_BRANCHSTATE,
8772 message ("%s %q is %s %s, but %s %s.",
8773 ekind_capName (res->ukind), uentry_getName (res),
8774 sRef_stateVerb (other->sref), clause_nameFlip (cl, flip),
8775 sRef_stateAltVerb (other->sref), clause_nameFlip (cl, !flip)),
8776 loc))
8777 {
8778 if (sRef_isDead (other->sref))
8779 {
8780 sRef_showStateInfo (other->sref);
8781 }
8782 else /* kept */
8783 {
8784 sRef_showAliasInfo (other->sref);
8785 }
8786
8787 sRef_setAliasKind (res->sref, AK_ERROR, fileloc_undefined);
8788 sRef_setDefinedComplete (res->sref, fileloc_undefined);
8789
8790 sRef_setAliasKind (other->sref, AK_ERROR, fileloc_undefined);
8791 sRef_setDefinedComplete (other->sref, fileloc_undefined);
8792 }
8793}
8794
8795static bool notNull (sRef sr, bool flip)
8796{
8797 return (!sRef_definitelyNull (sr)
8798 && !(sRef_isKept (sr))
8799 && !(sRef_isDependent (sr))
8800 && !(flip ? usymtab_isProbableDeepNull (sr)
8801 : usymtab_isAltProbablyDeepNull (sr)));
8802}
8803
8804void
8805uentry_mergeState (uentry res, uentry other, fileloc loc,
8806 bool mustReturn, bool flip, bool opt,
8807 clause cl)
8808{
8809 llassert (uentry_isValid (res));
8810 llassert (uentry_isValid (other));
8811
8812 llassert (res->ukind == other->ukind);
8813 llassert (res->ukind == KVAR);
8814
8815 DPRINTF (("Merge state: %s / %s",
8816 uentry_unparse (res),
8817 uentry_unparse (other)));
8818
8819 if (sRef_isValid (res->sref))
8820 {
8821 if (!mustReturn)
8822 {
8823 if (incompatibleStates (res->sref, other->sref))
8824 {
8825 if (sRef_isThroughArrayFetch (res->sref)
8826 && !context_getFlag (FLG_STRICTBRANCHSTATE))
8827 {
8828 if (sRef_isKept (res->sref) || sRef_isKept (other->sref))
8829 {
8830 sRef_maybeKill (res->sref, loc);
8831 }
8832 else if (sRef_isPossiblyDead (other->sref))
8833 {
8834 sRef_maybeKill (res->sref, loc);
8835 }
8836 else
8837 {
8838 ;
8839 }
8840 }
8841 else
8842 {
8843 if (notNull (other->sref, flip))
8844 {
8845 if (sRef_isLocalParamVar (res->sref)
8846 && (sRef_isLocalState (other->sref)
8847 || sRef_isDependent (other->sref)))
8848 {
8849 if (sRef_isDependent (res->sref))
8850 {
8851 sRef_setDependent (other->sref, loc);
8852 }
8853 else
8854 {
8855 sRef_setDefState (res->sref, SS_UNUSEABLE, loc);
8856 }
8857 }
8858 else
8859 {
8860 branchStateError (res, other, flip, cl, loc);
8861 }
8862 }
8863 }
8864
8865 if (sRef_isKept (res->sref))
8866 {
8867 sRef_setKept (other->sref, loc);
8868 }
8869 }
8870 else
8871 {
8872 if (incompatibleStates (other->sref, res->sref))
8873 {
8874 if (notNull (res->sref, !flip))
8875 {
8876 if (sRef_isLocalParamVar (res->sref)
8877 && (sRef_isDependent (res->sref)
8878 || sRef_isLocalState (res->sref)))
8879 {
8880 if (sRef_isDependent (other->sref))
8881 {
8882 sRef_setDependent (res->sref, loc);
8883 }
8884 else
8885 {
8886 sRef_setDefState (res->sref, SS_UNUSEABLE, loc);
8887 }
8888 }
8889 else
8890 {
8891 if (sRef_isParam (other->sref))
8892 {
8893 /*
8894 ** If the local variable associated
8895 ** with the param has the correct state,
8896 ** its okay.
8897 ** (e.g., free (s); s = new(); ...
8898 */
8899
8900 uentry uvar = usymtab_lookupSafe (other->uname);
8901
8902 if (uentry_isValid (uvar)
8903 && ((sRef_isDead (other->sref)
8904 && sRef_isOnly (uvar->sref))
8905 || (sRef_isDependent (other->sref)
8906 && sRef_isOwned (uvar->sref))))
8907 {
8908 /* no error */
8909 }
8910 else
8911 {
8912 branchStateAltError (res, other,
8913 flip, cl, loc);
8914 }
8915 }
8916 else
8917 {
8918 branchStateAltError (res, other,
8919 flip, cl, loc);
8920 }
8921 }
8922 }
8923 }
8924
8925 if (sRef_isKept (other->sref))
8926 {
8927 sRef_setKept (res->sref, loc);
8928 }
8929 }
8930
8931 if (opt)
8932 {
8933 DPRINTF (("Merge opt..."));
8934 sRef_mergeOptState (res->sref, other->sref, cl, loc);
8935 DPRINTF (("Done!"));
8936 }
8937 else
8938 {
8939 sRef_mergeState (res->sref, other->sref, cl, loc);
8940 }
8941 }
8942 else
8943 {
8944 if (sRef_isModified (other->sref))
8945 {
8946 sRef_setModified (res->sref);
8947 }
8948 }
8949
8950 if (cl == DOWHILECLAUSE)
8951 {
8952 res->used = other->used || res->used;
8953 res->lset = other->lset || res->lset;
8954 res->uses = filelocList_append (res->uses, other->uses);
8955 other->uses = filelocList_undefined;
8956 }
8957 else
8958 {
8959 if (sRef_isMacroParamRef (res->sref)
8960 && !uentry_isSefParam (other)
8961 && !uentry_isSefParam (res))
8962 {
8963 bool hasError = FALSE;
8964
8965 if (bool_equal (res->used, other->used))
8966 {
8967 res->used = other->used;
8968 }
8969 else
8970 {
8971 if (other->used && !flip)
8972 {
8973 hasError =
8974 optgenerror
8975 (FLG_MACROPARAMS,
8976 message ("Macro parameter %q used in true clause, "
8977 "but not in false clause",
8978 uentry_getName (res)),
8979 uentry_whereDeclared (res));
8980 }
8981 else
8982 {
8983 hasError =
8984 optgenerror
8985 (FLG_MACROPARAMS,
8986 message ("Macro parameter %q used in false clause, "
8987 "but not in true clause",
8988 uentry_getName (res)),
8989 uentry_whereDeclared (res));
8990 }
8991 res->used = TRUE;
8992
8993 if (hasError)
8994 {
8995 /* make it sef now, prevent more errors */
8996 res->info->var->kind = VKREFSEFPARAM;
8997 }
8998 }
8999 }
9000 else
9001 {
9002 res->used = other->used || res->used;
9003 res->lset = other->lset || res->lset;
9004 res->uses = filelocList_append (res->uses, other->uses);
9005 other->uses = filelocList_undefined;
9006 }
9007 }
9008 }
9009}
9010
9011void uentry_setUsed (uentry e, fileloc loc)
9012{
9013 static bool firstTime = TRUE;
9014 static bool showUses = FALSE;
9015 static bool exportLocal = FALSE;
9016
9017 if (firstTime)
9018 {
9019 /* need to track uses is FLG_SHOWUSES or FLG_EXPORTLOCAL is true */
9020
9021 showUses = context_getFlag (FLG_SHOWUSES);
9022 exportLocal = context_maybeSet (FLG_EXPORTLOCAL);
9023
9024 firstTime = FALSE;
9025 }
9026
9027 if (uentry_isValid (e))
9028 {
9029 int dp;
9030
9031 if (sRef_isMacroParamRef (e->sref))
9032 {
9033 if (uentry_isYield (e) || uentry_isSefParam (e))
9034 {
9035 ;
9036 }
9037 else
9038 {
9039 if (context_inConditional ())
9040 {
9041 if (optgenerror
9042 (FLG_MACROPARAMS,
9043 message ("Macro parameter %q used in conditionally "
9044 "executed code (may or may not be "
9045 "evaluated exactly once)",
9046 uentry_getName (e)),
9047 loc))
9048 {
9049 e->info->var->kind = VKREFSEFPARAM;
9050 }
9051 }
9052 else
9053 {
9054 if ((e)->used)
9055 {
9056 if (optgenerror
9057 (FLG_MACROPARAMS,
9058 message ("Macro parameter %q used more than once",
9059 uentry_getName (e)),
9060 uentry_whereDeclared (e)))
9061 {
9062 e->info->var->kind = VKREFSEFPARAM;
9063 }
9064 }
9065 }
9066 }
9067 }
9068
9069 if ((dp = uentry_directParamNo (e)) >= 0)
9070 {
9071 uentry_setUsed (usymtab_getParam (dp), loc);
9072 }
9073
9074 e->used = TRUE;
9075
9076 if (!sRef_isLocalVar (e->sref))
9077 {
9078 if (showUses)
9079 {
9080 e->uses = filelocList_add (e->uses, fileloc_copy (loc));
9081 }
9082 else
9083 {
9084 if (exportLocal)
9085 {
9086 if (context_inMacro ())
9087 {
9088 e->uses = filelocList_addUndefined (e->uses);
9089 }
9090 else
9091 {
9092 e->uses = filelocList_addDifferentFile
9093 (e->uses,
9094 uentry_whereDeclared (e),
9095 loc);
9096 }
9097 }
9098 }
9099 }
9100 }
9101}
9102
9103bool uentry_isReturned (uentry u)
9104{
9105 return (uentry_isValid (u) && uentry_isVar (u)
9106 && (u->info->var->kind == VKRETPARAM
9107 || u->info->var->kind == VKSEFRETPARAM));
9108}
9109
9110/*@exposed@*/ sRef uentry_returnedRef (uentry u, exprNodeList args)
9111{
9112 llassert (uentry_isRealFunction (u));
9113
9114 if (ctype_isFunction (u->utype)
9115 && sRef_isStateSpecial (uentry_getSref (u)))
9116 {
9117 specialClauses clauses = uentry_getSpecialClauses (u);
9118 sRef res = sRef_makeNew (ctype_returnValue (u->utype), u->sref, u->uname);
9119
9120 sRef_setAllocated (res, g_currentloc);
9121
9122 specialClauses_postElements (clauses, cl)
9123 {
9124 sRefSet refs = specialClause_getRefs (cl);
9125 sRefMod modf = specialClause_getEffectFunction (cl);
9126
9127 sRefSet_elements (refs, el)
9128 {
9129 sRef base = sRef_getRootBase (el);
9130
9131 if (sRef_isResult (base))
9132 {
9133 if (modf != NULL)
9134 {
9135 sRef sr = sRef_fixBase (el, res);
9136 modf (sr, g_currentloc);
9137 }
9138 }
9139 else
9140 {
9141 ;
9142 }
9143 } end_sRefSet_elements ;
9144
9145 } end_specialClauses_postElements ;
9146
9147 return res;
9148 }
9149 else
9150 {
9151 uentryList params;
9152 alkind ak;
9153 sRefSet prefs = sRefSet_new ();
9154 sRef res = sRef_undefined;
9155 int paramno = 0;
9156
9157 params = uentry_getParams (u);
9158
9159 uentryList_elements (params, current)
9160 {
9161 if (uentry_isReturned (current))
9162 {
9163 if (exprNodeList_size (args) >= paramno)
9164 {
9165 exprNode ecur = exprNodeList_nth (args, paramno);
9166 sRef tref = exprNode_getSref (ecur);
9167
9168 if (sRef_isValid (tref))
9169 {
9170 sRef tcref = sRef_copy (tref);
9171
9172 if (sRef_isDead (tcref))
9173 {
9174 sRef_setDefined (tcref, g_currentloc);
9175 sRef_setOnly (tcref, g_currentloc);
9176 }
9177
9178 if (sRef_isRefCounted (tcref))
9179 {
9180 /* could be a new ref now (but only if its returned) */
9181 sRef_setAliasKindComplete (tcref, AK_ERROR, g_currentloc);
9182 }
9183
9184 sRef_makeSafe (tcref);
9185
9186 prefs = sRefSet_insert (prefs, tcref);
9187 }
9188 }
9189 }
9190
9191 paramno++;
9192 } end_uentryList_elements ;
9193
9194 if (sRefSet_size (prefs) > 0)
9195 {
9196 nstate n = sRef_getNullState (u->sref);
9197
9198 if (sRefSet_size (prefs) == 1)
9199 {
9200 res = sRefSet_choose (prefs);
9201 }
9202 else
9203 {
9204 res = sRefSet_mergeIntoOne (prefs);
9205 }
9206
9207 if (nstate_isKnown (n))
9208 {
9209 sRef_setNullState (res, n, g_currentloc);
9210 }
9211 }
9212 else
9213 {
9214 if (ctype_isFunction (u->utype))
9215 {
9216 res = sRef_makeNew (ctype_returnValue (u->utype), u->sref, u->uname);
9217 }
9218 else
9219 {
9220 res = sRef_makeNew (ctype_unknown, u->sref, u->uname);
9221 }
9222
9223 if (sRef_isRefCounted (res))
9224 {
9225 sRef_setAliasKind (res, AK_NEWREF, g_currentloc);
9226 }
9227 }
9228
9229 if (sRef_getNullState (res) == NS_ABSNULL)
9230 {
9231 ctype ct = ctype_realType (u->utype);
9232
9233 if (ctype_isAbstract (ct))
9234 {
9235 sRef_setNotNull (res, g_currentloc);
9236 }
9237 else
9238 {
9239 if (ctype_isUser (ct))
9240 {
9241 sRef_setStateFromUentry (res, usymtab_getTypeEntry (ctype_typeId (ct)));
9242 }
9243 else
9244 {
9245 sRef_setNotNull (res, g_currentloc);
9246 }
9247 }
9248 }
9249
9250 if (sRef_isRefCounted (res))
9251 {
9252 sRef_setAliasKind (res, AK_NEWREF, g_currentloc);
9253 }
9254 else if (sRef_isKillRef (res))
9255 {
9256 sRef_setAliasKind (res, AK_REFCOUNTED, g_currentloc);
9257 }
9258 else
9259 {
9260 ;
9261 }
9262
9263 ak = sRef_getAliasKind (res);
9264
9265 if (alkind_isImplicit (ak))
9266 {
9267 sRef_setAliasKind (res,
9268 alkind_fixImplicit (ak),
9269 g_currentloc);
9270 }
9271
9272 sRefSet_free (prefs);
9273
9274 return res;
9275 }
9276}
9277
9278static bool uentry_isRefCounted (uentry ue)
9279{
9280 ctype ct = uentry_getType (ue);
9281
9282 if (ctype_isFunction (ct))
9283 {
9284 return (ctype_isRefCounted (ctype_returnValue (ct)));
9285 }
9286 else
9287 {
9288 return (ctype_isRefCounted (ct));
9289 }
9290}
9291
9292/*
9293** old was declared yield in the specification.
9294** new is declared in the iter implementation.
9295*/
9296
9297void uentry_checkYieldParam (uentry old, uentry unew)
9298{
9299 cstring name;
9300
9301 llassert (uentry_isVariable (old));
9302 llassert (uentry_isVariable (unew));
9303
9304 unew->info->var->kind = VKYIELDPARAM;
9305 (void) checkTypeConformance (old, unew, TRUE);
9306 checkVarConformance (old, unew, TRUE, FALSE);
9307
9308 /* get rid of param marker */
9309
9310 name = uentry_getName (unew);
9311 cstring_free (unew->uname);
9312 unew->uname = name;
9313 unew->info->var->kind = VKREFYIELDPARAM;
9314
9315 uentry_setUsed (old, fileloc_undefined);
9316 uentry_setUsed (unew, fileloc_undefined);
9317}
9318
9319/*@observer@*/ cstring
9320uentry_ekindName (uentry ue)
9321{
9322 if (uentry_isValid (ue))
9323 {
9324 switch (ue->ukind)
9325 {
9326 case KINVALID:
9327 return cstring_makeLiteralTemp ("<Error: invalid uentry>");
9328 case KDATATYPE:
9329 return cstring_makeLiteralTemp ("Datatype");
9330 case KENUMCONST:
9331 return cstring_makeLiteralTemp ("Enum member");
9332 case KCONST:
9333 return cstring_makeLiteralTemp ("Constant");
9334 case KVAR:
9335 if (uentry_isParam (ue))
9336 {
9337 return cstring_makeLiteralTemp ("Parameter");
9338 }
9339 else if (uentry_isExpandedMacro (ue))
9340 {
9341 return cstring_makeLiteralTemp ("Expanded macro");
9342 }
9343 else
9344 {
9345 return cstring_makeLiteralTemp ("Variable");
9346 }
9347 case KFCN:
9348 return cstring_makeLiteralTemp ("Function");
9349 case KITER:
9350 return cstring_makeLiteralTemp ("Iterator");
9351 case KENDITER:
9352 return cstring_makeLiteralTemp ("Iterator finalizer");
9353 case KSTRUCTTAG:
9354 return cstring_makeLiteralTemp ("Struct tag");
9355 case KUNIONTAG:
9356 return cstring_makeLiteralTemp ("Union tag");
9357 case KENUMTAG:
9358 return cstring_makeLiteralTemp ("Enum tag");
9359 case KELIPSMARKER:
9360 return cstring_makeLiteralTemp ("Optional parameters");
9361 }
9362 }
9363 else
9364 {
9365 return cstring_makeLiteralTemp ("<Undefined>");
9366 }
9367
9368 BADEXIT;
9369}
9370
9371void uentry_setHasNameError (uentry ue)
9372{
9373 llassert (uentry_isValid (ue));
9374
9375 ue->hasNameError = TRUE;
9376}
9377
9378void uentry_checkName (uentry ue)
9379{
9380 if (uentry_isValid (ue)
9381 && !uentry_isElipsisMarker (ue)
9382 && context_getFlag (FLG_NAMECHECKS)
9383 && !ue->hasNameError
9384 && !uentry_isEndIter (ue)
9385 && !fileloc_isBuiltin (uentry_whereLast (ue))
9386 && (uentry_isExpandedMacro (ue) || !uentry_isForward (ue)))
9387 {
9388
9389 if (uentry_isPriv (ue))
9390 {
9391 ; /* any checks here? */
9392 }
9393 else if (fileloc_isExternal (uentry_whereDefined (ue)))
9394 {
9395 ; /* no errors for externals */
9396 }
9397 else
9398 {
9399 int scope;
9400
9401 if (uentry_isExpandedMacro (ue))
9402 {
9403 scope = globScope;
9404 }
9405 else
9406 {
9407 if (uentry_isExpandedMacro (ue))
9408 {
9409 scope = fileScope;
9410 }
9411 else if (uentry_isVariable (ue))
9412 {
9413 sRef sr = uentry_getSref (ue);
9414
9415 if (sRef_isValid (sr))
9416 {
9417 scope = sRef_getScope (sr);
9418 }
9419 else
9420 {
9421 scope = fileScope;
9422 }
9423 }
9424 else if (uentry_isFunction (ue)
9425 || uentry_isIter (ue)
9426 || uentry_isEndIter (ue)
9427 || uentry_isConstant (ue))
9428 {
9429 scope = uentry_isStatic (ue) ? fileScope : globScope;
9430 }
9431 else /* datatypes, etc. must be global */
9432 {
9433 scope = globScope;
9434 }
9435
9436 usymtab_checkDistinctName (ue, scope);
9437 }
9438
9439 if (context_getFlag (FLG_CPPNAMES))
9440 {
9441 if (checkCppName (uentry_rawName (ue), uentry_whereLast (ue)))
9442 {
9443 uentry_setHasNameError (ue);
9444 }
9445 }
9446
9447 if (scope == globScope)
9448 {
9449 checkGlobalName (ue);
9450
9451 if (context_getFlag (FLG_ANSIRESERVED))
9452 {
9453 if (uentry_hasName (ue)
9454 && !uentry_isAnyTag (ue))
9455 {
9456 if (checkAnsiName (uentry_rawName (ue),
9457 uentry_whereLast (ue)))
9458 {
9459 uentry_setHasNameError (ue);
9460 }
9461 }
9462 }
9463 }
9464 else
9465 {
9466 checkLocalName (ue);
9467
9468 if (context_getFlag (FLG_ANSIRESERVEDLOCAL))
9469 {
9470 if (uentry_hasName (ue)
9471 && !uentry_isAnyTag (ue))
9472 {
9473 if (checkAnsiName (uentry_rawName (ue),
9474 uentry_whereLast (ue)))
9475 {
9476 uentry_setHasNameError (ue);
9477 }
9478 }
9479 }
9480 }
9481
9482 DPRINTF (("Check prefix: %s", uentry_unparse (ue)));
9483 checkPrefix (ue);
9484 }
9485 }
9486}
9487
9488/*@exposed@*/ uentry uentry_makeUnrecognized (cstring c, /*@keep@*/ fileloc loc)
9489{
9490 uentry ue;
9491 fileloc tloc;
9492
9493 /*
9494 ** Can't but unrecognized ids in macros in global scope, because srefs will break! */
9495 if (!context_inMacro ())
9496 {
9497 sRef_setGlobalScopeSafe ();
9498 }
9499
9500 ue = uentry_makeVariable (c, ctype_unknown, loc, FALSE);
9501 uentry_setUsed (ue, loc);
9502
9503 tloc = fileloc_createExternal ();
9504 uentry_setDefined (ue, tloc);
9505 fileloc_free (tloc);
9506 uentry_setHasNameError (ue);
9507
9508 if (context_getFlag (FLG_REPEATUNRECOG))
9509 {
9510 uentry_markOwned (ue);
9511 }
9512 else
9513 {
9514 ue = usymtab_supReturnFileEntry (ue);
9515 }
9516
9517 if (!context_inMacro ())
9518 {
9519 sRef_clearGlobalScopeSafe ();
9520 }
9521
9522 return ue;
9523}
9524
11ed4f45 9525/* new start modifications */
9526
a0a162cd 9527void uentry_testInRange (uentry p_e, uentry cconstant) {
9528 if( uentry_isValid(p_e) ) {
9529 if( p_e->sref != NULL) {
9530 int index = atoi(exprNode_unparse(cconstant) );
9531 usymtab_testInRange (p_e->sref, index);
9532 }//end if
9533 }//endif
9534}
9535
11ed4f45 9536void uentry_setStringLength (uentry p_e, uentry cconstant) {
9537if( uentry_isValid(p_e) ) {
9538 if( p_e->info != NULL) {
9539 if( p_e->info->var != NULL) {
9540 int length = atoi(exprNode_unparse(cconstant) );
9541 p_e->info->var->bufinfo->len = length;
9542 p_e->sref->bufinfo.len = length;
9543 printf("Set string length of buff to %d \n", p_e->sref->bufinfo.size);
9544 }//end if
9545 }//endif
9546}//end if
9547}
9548
9549
9550void uentry_setBufferSize (uentry p_e, exprNode cconstant) {
9551if( uentry_isValid(p_e) ) {
9552 if( p_e->info != NULL) {
9553 if( p_e->info->var != NULL) {
9554 int size = atoi(exprNode_unparse(cconstant) );
9555 p_e->info->var->bufinfo->size = size;
9556 p_e->sref->bufinfo.size = size;
9557 printf("Set buffer size to %d \n", p_e->sref->bufinfo.size);
9558 // fprintf(stderr, "For %s and %s\n", uentry_unparse(p_e) );
9559 // fprintf(stderr, "and %d\n", size );
9560
9561 }//end if
9562 }//endif
9563}//end if
9564}
885824d3 9565
11ed4f45 9566
1ac6313d 9567/* start modifications */
9568/*
9569requires: p_e is defined, is a ptr/array variable
9570modifies: p_e
9571effects: sets the state of the variable
9572*/
9573
9574void uentry_setPossiblyNullTerminatedState (uentry p_e) {
9575 if( uentry_isValid(p_e) ) {
9576 if( p_e->info != NULL) {
9577 if( p_e->info->var != NULL) {
9578 p_e->info->var->bufinfo->bufstate = BB_POSSIBLYNULLTERMINATED;
9579 p_e->sref->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
9580 return;
9581 }/* End if */
9582 }/* End if */
9583 }/* End if */
9584
9585 fprintf(stderr, "uentry:Error in setPossiblyNullTerminatedState\n");
9586}
9587
9588/*
9589requires: p_e is defined, is a ptr/array variable
9590modifies: p_e
9591effects: sets the size of the buffer
9592*/
9593
9594void uentry_setNullTerminatedState (uentry p_e) {
9595 if( uentry_isValid(p_e) ) {
9596 if( p_e->info != NULL) {
9597 if( p_e->info->var != NULL) {
9598 p_e->info->var->bufinfo->bufstate = BB_NULLTERMINATED;
9599 p_e->sref->bufinfo.bufstate = BB_NULLTERMINATED;
9600 return;
9601 }//End if
9602 }//End if
9603 }//End if
9604
9605 fprintf(stderr, "uentry:Error in setNullTerminatedState\n");
9606}
9607
9608
9609/*
9610requires: p_e is defined, is a ptr/array variable
9611modifies: p_e
9612effects: sets the state of the variable
9613*/
9614
9615void uentry_setNotNullTerminatedState (uentry p_e) {
9616 if( uentry_isValid(p_e) ) {
9617 if( p_e->info != NULL) {
9618 if( p_e->info->var != NULL) {
9619 p_e->info->var->bufinfo->bufstate = BB_NOTNULLTERMINATED;
9620 p_e->sref->bufinfo.bufstate = BB_NOTNULLTERMINATED;
9621 return;
9622 }//End if
9623 }//End if
9624 }//End if
9625
9626 fprintf(stderr, "uentry:Error in setNotNullTerminatedState\n");
9627}
9628
9629
9630/*
9631requires: p_e is defined, is a ptr/array variable
9632modifies: p_e
9633effects: sets the size of the buffer
9634*/
9635
9636void uentry_setSize (uentry p_e, int size) {
9637 if( uentry_isValid(p_e) ) {
9638 if( p_e->info != NULL) {
9639 if( p_e->info->var != NULL) {
9640 p_e->info->var->bufinfo->size = size;
9641 p_e->sref->bufinfo.size = size;
9642 return;
9643 }//End if
9644 }//End if
9645 }//End if
9646
9647 fprintf(stderr, "uentry:Error in setSize\n");
9648}
9649
9650
9651/*
9652requires: p_e is defined, is a ptr/array variable
9653modifies: p_e
9654effects: sets the length of the buffer
9655*/
9656
9657void uentry_setLen (uentry p_e, int len) {
9658 if( uentry_isValid(p_e) ) {
9659 if( p_e->info != NULL) {
9660 if( p_e->info->var != NULL) {
9661 p_e->info->var->bufinfo->len = len;
9662 p_e->sref->bufinfo.len = len;
9663 return;
9664 }//End if
9665 }//End if
9666 }//End if
9667
9668 fprintf(stderr, "uentry:Error in setLen\n");
9669}
885824d3 9670
9671
This page took 1.359712 seconds and 5 git commands to generate.