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