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