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