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