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