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