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