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