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