]> andersk Git - splint.git/blame - src/sRef.c
Fixed problem with NULL being changed.
[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;
210066f9 5519 DPRINTF (("Set null state ==> %s", sRef_unparseFull (s)));
abd7f895 5520 sRef_resetAliasKind (s);
5521 }
28bf4b0b 5522}
5523
616915dd 5524void sRef_setNullState (sRef s, nstate n, fileloc loc)
5525{
6483a926 5526 if (sRef_isReasonable (s))
616915dd 5527 {
5528 sRef_setNullStateAux (s, n, loc);
5529 }
5530}
5531
2e127cb8 5532void sRef_setNullTerminatedStateInnerComplete (sRef s, struct s_bbufinfo b, /*@unused@*/ fileloc loc)
5533{
616915dd 5534 switch (b.bufstate) {
abd7f895 5535 case BB_NULLTERMINATED:
5536 sRef_setNullTerminatedState (s);
5537 sRef_setLen (s, b.len);
5538 break;
5539 case BB_POSSIBLYNULLTERMINATED:
5540 sRef_setPossiblyNullTerminatedState(s);
5541 break;
5542 case BB_NOTNULLTERMINATED:
5543 sRef_setNotNullTerminatedState (s);
5544 break;
616915dd 5545 }
616915dd 5546
abd7f895 5547 sRef_setSize (s, b.size);
5548
616915dd 5549 /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5550 * setNullStateInnerComplete.
5551 */
5552}
5553
5554void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5555{
28bf4b0b 5556 DPRINTF (("Set null state: %s", nstate_unparse (n)));
5557
616915dd 5558 sRef_setNullState (s, n, loc);
28bf4b0b 5559
616915dd 5560 switch (n)
5561 {
5562 case NS_POSNULL:
5563 sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5564 break;
5565 case NS_DEFNULL:
5566 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5567 break;
5568 case NS_UNKNOWN:
5569 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5570 break;
5571 case NS_NOTNULL:
5572 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5573 break;
5574 case NS_MNOTNULL:
5575 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5576 break;
5577 case NS_RELNULL:
5578 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5579 break;
5580 case NS_CONSTNULL:
5581 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5582 break;
5583 case NS_ABSNULL:
5584 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5585 break;
5586 case NS_ERROR:
5587 sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5588 break;
5589 }
5590}
5591
5592void sRef_setPosNull (sRef s, fileloc loc)
5593{
6483a926 5594 if (sRef_isReasonable (s))
616915dd 5595 {
5596 sRef_setNullStateAux (s, NS_POSNULL, loc);
5597 }
5598}
5599
5600void sRef_setDefNull (sRef s, fileloc loc)
5601{
6483a926 5602 if (sRef_isReasonable (s))
616915dd 5603 {
5604 sRef_setNullStateAux (s, NS_DEFNULL, loc);
5605 }
5606}
5607
5608void sRef_setNullUnknown (sRef s, fileloc loc)
5609{
6483a926 5610 if (sRef_isReasonable (s))
616915dd 5611 {
5612 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5613 }
5614}
5615
5616void sRef_setNullError (sRef s)
5617{
02b84d4b 5618 if (sRef_isReasonable (s) && !sRef_isConst (s))
616915dd 5619 {
5620 sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5621 }
5622}
5623
02b84d4b 5624void sRef_setNullErrorLoc (sRef s, fileloc loc)
616915dd 5625{
02b84d4b 5626 if (sRef_isReasonable (s) && !sRef_isConst (s))
5627 {
5628 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5629 }
616915dd 5630}
5631
5632void sRef_setOnly (sRef s, fileloc loc)
5633{
6483a926 5634 if (sRef_isReasonable (s) && s->aliaskind != AK_ONLY)
616915dd 5635 {
02b84d4b 5636 sRef_checkMutable (s);
616915dd 5637 s->aliaskind = AK_ONLY;
16c024b5 5638 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_ONLY, loc);
02b84d4b 5639 }
616915dd 5640}
5641
5642void sRef_setDependent (sRef s, fileloc loc)
5643{
6483a926 5644 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
616915dd 5645 {
02b84d4b 5646 sRef_checkMutable (s);
28bf4b0b 5647 DPRINTF (("Setting dependent: %s", sRef_unparseFull (s)));
616915dd 5648 s->aliaskind = AK_DEPENDENT;
16c024b5 5649 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_DEPENDENT, loc);
28bf4b0b 5650 }
616915dd 5651}
5652
5653void sRef_setOwned (sRef s, fileloc loc)
5654{
6483a926 5655 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
616915dd 5656 {
02b84d4b 5657 sRef_checkMutable (s);
616915dd 5658 s->aliaskind = AK_OWNED;
16c024b5 5659 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_OWNED, loc);
28bf4b0b 5660 }
616915dd 5661}
5662
5663void sRef_setKept (sRef s, fileloc loc)
5664{
6483a926 5665 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
616915dd 5666 {
5667 sRef base = sRef_getBaseSafe (s);
02b84d4b 5668
6483a926 5669 while (sRef_isReasonable (base) && sRef_isKnown (base))
616915dd 5670 {
5671 if (base->defstate == SS_DEFINED)
5672 {
02b84d4b 5673 sRef_checkMutable (base);
616915dd 5674 base->defstate = SS_PDEFINED;
27c9e640 5675 base = sRef_getBaseSafe (base);
616915dd 5676 }
5677 else
5678 {
5679 break;
5680 }
616915dd 5681 }
5682
02b84d4b 5683 sRef_checkMutable (s);
616915dd 5684 s->aliaskind = AK_KEPT;
16c024b5 5685 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_KEPT, loc);
28bf4b0b 5686 }
616915dd 5687}
5688
5689static void sRef_setKeptAux (sRef s, fileloc loc)
5690{
5691 if (!sRef_isShared (s))
5692 {
5693 sRef_setKept (s, loc);
5694 }
5695}
5696
5697static void sRef_setDependentAux (sRef s, fileloc loc)
5698{
5699 if (!sRef_isShared (s))
5700 {
5701 sRef_setDependent (s, loc);
5702 }
5703}
5704
5705void sRef_setKeptComplete (sRef s, fileloc loc)
5706{
5707 sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5708}
5709
5710void sRef_setDependentComplete (sRef s, fileloc loc)
5711{
5712 sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5713}
5714
5715void sRef_setFresh (sRef s, fileloc loc)
5716{
02b84d4b 5717 if (sRef_isReasonable (s) && !sRef_isConst (s))
616915dd 5718 {
02b84d4b 5719 sRef_checkMutable (s);
616915dd 5720 s->aliaskind = AK_FRESH;
16c024b5 5721 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_CREATED, loc);
6fcd0b1e 5722 DPRINTF (("SetFresh: %s", sRef_unparseFull (s)));
616915dd 5723 }
5724}
5725
5726void sRef_kill (sRef s, fileloc loc)
5727{
5728 DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5729
6483a926 5730 if (sRef_isReasonable (s) && !sRef_isShared (s) && !sRef_isConst (s))
616915dd 5731 {
5732 sRef base = sRef_getBaseSafe (s);
02b84d4b 5733 sRef_checkMutable (s);
5734
6483a926 5735 while (sRef_isReasonable (base) && sRef_isKnown (base))
616915dd 5736 {
5737 if (base->defstate == SS_DEFINED)
5738 {
02b84d4b 5739 sRef_checkMutable (base);
616915dd 5740 base->defstate = SS_PDEFINED;
5741 base = sRef_getBaseSafe (base);
5742 }
5743 else
5744 {
5745 break;
5746 }
616915dd 5747 }
5748
5749 s->aliaskind = s->oaliaskind;
5750 s->defstate = SS_DEAD;
16c024b5 5751 s->definfo = stateInfo_updateLoc (s->definfo, SA_KILLED, loc);
5752 DPRINTF (("State info: %s", stateInfo_unparse (s->definfo)));
616915dd 5753 sRef_clearDerived (s);
5754 }
5755}
5756
5757void sRef_maybeKill (sRef s, fileloc loc)
5758{
6483a926 5759 if (sRef_isReasonable (s))
616915dd 5760 {
5761 sRef base = sRef_getBaseSafe (s);
02b84d4b 5762 sRef_checkMutable (s);
616915dd 5763
6483a926 5764 while (sRef_isReasonable (base) && sRef_isKnown (base))
616915dd 5765 {
5766 if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5767 {
02b84d4b 5768 sRef_checkMutable (base);
616915dd 5769 base->defstate = SS_PDEFINED;
28bf4b0b 5770 base = sRef_getBaseSafe (base);
616915dd 5771 }
5772 else
5773 {
28bf4b0b 5774 break;
616915dd 5775 }
5776
5777 }
5778
5779 s->aliaskind = s->oaliaskind;
5780 s->defstate = SS_HOFFA;
16c024b5 5781 s->definfo = stateInfo_updateLoc (s->definfo, SA_PKILLED, loc);
5782 DPRINTF (("State info: %s / %s", sRef_unparse (s),
5783 stateInfo_unparse (s->definfo)));
616915dd 5784 sRef_clearDerived (s);
5785 }
5786
5787 }
5788
5789/*
5790** just for type checking...
5791*/
5792
5793static void sRef_killAux (sRef s, fileloc loc)
5794{
6483a926 5795 if (sRef_isReasonable (s) && !sRef_isShared (s))
616915dd 5796 {
5797 if (sRef_isUnknownArrayFetch (s))
5798 {
5799 sRef_maybeKill (s, loc);
5800 }
5801 else
5802 {
28bf4b0b 5803 sRef_kill (s, loc);
5804 }
616915dd 5805 }
5806}
5807
5808/*
5809** kills s and all aliases to s
5810*/
5811
5812void sRef_killComplete (sRef s, fileloc loc)
5813{
5814 DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5815 sRef_aliasSetComplete (sRef_killAux, s, loc);
5816}
5817
5818static bool sRef_equivalent (sRef s1, sRef s2)
5819{
5820 return (sRef_compare (s1, s2) == 0);
5821}
5822
5823/*
5824** returns an sRef that will not be free'd on function exit.
5825*/
5826
5827/*@only@*/ sRef sRef_saveCopy (sRef s)
5828{
5829 sRef ret;
5830
6483a926 5831 if (sRef_isReasonable (s))
616915dd 5832 {
5833 bool old = inFunction;
5834
5835 /*
5836 ** Exit the function scope, so this sRef is not
5837 ** stored in the deallocation table.
5838 */
5839
5840 inFunction = FALSE;
5841 DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5842 ret = sRef_copy (s);
5843 DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5844 inFunction = old;
5845 }
5846 else
5847 {
5848 ret = sRef_undefined;
5849 }
5850
5851 /*@-dependenttrans@*/
5852 return ret;
5853 /*@=dependenttrans@*/
5854}
5855
5856sRef sRef_copy (sRef s)
5857{
28bf4b0b 5858 if (sRef_isKindSpecial (s) && !sRef_isGlobalMarker (s))
616915dd 5859 {
5860 /*@-retalias@*/
28bf4b0b 5861 return s; /* don't copy specials (except for global markers) */
616915dd 5862 /*@=retalias@*/
5863 }
28bf4b0b 5864
6483a926 5865 if (sRef_isReasonable (s))
616915dd 5866 {
5867 sRef t = sRef_alloc ();
5868
28bf4b0b 5869 DPRINTF (("Copying: [%p] %s", s, sRef_unparse (s)));
5870 DPRINTF (("Full: %s", sRef_unparseFull (s)));
5871
616915dd 5872 t->kind = s->kind;
5873 t->safe = s->safe;
5874 t->modified = s->modified;
28bf4b0b 5875 t->immut = FALSE; /* Note mutability is not copied. */
616915dd 5876 t->type = s->type;
b9904f57 5877 t->val = multiVal_copy (s->val);
616915dd 5878
28bf4b0b 5879 t->info = sinfo_copy (s);
616915dd 5880 t->defstate = s->defstate;
616915dd 5881 t->nullstate = s->nullstate;
210066f9 5882 DPRINTF (("Set null state==> %s", sRef_unparseFull (t)));
5883
616915dd 5884
5885 /* start modifications */
5886 t->bufinfo.bufstate = s->bufinfo.bufstate;
5887 t->bufinfo.len = s->bufinfo.len;
5888 t->bufinfo.size = s->bufinfo.size;
5889 /* end modifications */
5890
5891 t->aliaskind = s->aliaskind;
5892 t->oaliaskind = s->oaliaskind;
5893
5894 t->expkind = s->expkind;
5895 t->oexpkind = s->oexpkind;
5896
28bf4b0b 5897 t->nullinfo = stateInfo_copy (s->nullinfo);
5898 t->aliasinfo = stateInfo_copy (s->aliasinfo);
5899 t->definfo = stateInfo_copy (s->definfo);
5900 t->expinfo = stateInfo_copy (s->expinfo);
616915dd 5901
5902 t->deriv = sRefSet_newDeepCopy (s->deriv);
28bf4b0b 5903 t->state = valueTable_copy (s->state);
16c024b5 5904
393e573f 5905 DPRINTF (("Made copy: %s => %s", sRef_unparseFull (s), sRef_unparseFull (t)));
616915dd 5906 return t;
5907 }
5908 else
5909 {
5910 return sRef_undefined;
5911 }
5912}
5913
5914/*@notfunction@*/
5915# define PREDTEST(func,s) \
5916 do { if (sRef_isInvalid (s)) { return FALSE; } \
5917 else { if (sRef_isConj (s)) \
5918 { return (func (sRef_getConjA (s)) \
5919 || func (sRef_getConjB (s))); }}} while (FALSE);
5920
5921bool sRef_isAddress (sRef s)
5922{
5923 PREDTEST (sRef_isAddress, s);
5924 return (s->kind == SK_ADR);
5925}
5926
5927/*
5928** pretty weak... maybe a flag should control this.
5929*/
5930
5931bool sRef_isThroughArrayFetch (sRef s)
5932{
6483a926 5933 if (sRef_isReasonable (s))
616915dd 5934 {
5935 sRef tref = s;
5936
5937 do
5938 {
5939 sRef lt;
5940
5941 if (sRef_isArrayFetch (tref))
5942 {
28bf4b0b 5943 return TRUE;
616915dd 5944 }
5945
5946 lt = sRef_getBase (tref);
5947 tref = lt;
6483a926 5948 } while (sRef_isReasonable (tref));
616915dd 5949 }
5950
5951 return FALSE;
5952}
5953
5954bool sRef_isArrayFetch (sRef s)
5955{
5956 PREDTEST (sRef_isArrayFetch, s);
5957 return (s->kind == SK_ARRAYFETCH);
5958}
5959
5960bool sRef_isMacroParamRef (sRef s)
5961{
5962 if (context_inMacro () && sRef_isCvar (s))
5963 {
5964 uentry ue = sRef_getUentry (s);
5965 cstring pname = makeParam (uentry_rawName (ue));
5966 uentry mac = usymtab_lookupSafe (pname);
5967
5968 cstring_free (pname);
5969 return (uentry_isValid (mac));
5970 }
5971
5972 return FALSE;
5973}
5974
5975bool sRef_isCvar (sRef s)
5976{
5977 PREDTEST (sRef_isCvar, s);
5978 return (s->kind == SK_CVAR);
5979}
5980
5981bool sRef_isConst (sRef s)
5982{
5983 PREDTEST (sRef_isConst, s);
5984 return (s->kind == SK_CONST);
5985}
5986
5987bool sRef_isObject (sRef s)
5988{
5989 PREDTEST (sRef_isObject, s);
5990 return (s->kind == SK_OBJECT);
5991}
5992
5993bool sRef_isExternal (sRef s)
5994{
5995 PREDTEST (sRef_isExternal, s);
5996 return (s->kind == SK_EXTERNAL);
5997}
5998
5999static bool sRef_isDerived (sRef s)
6000{
6001 PREDTEST (sRef_isDerived, s);
6002 return (s->kind == SK_DERIVED);
6003}
6004
6005bool sRef_isField (sRef s)
6006{
6007 PREDTEST (sRef_isField, s);
6008 return (s->kind == SK_FIELD);
6009}
6010
6011static bool sRef_isIndex (sRef s)
6012{
6013 PREDTEST (sRef_isIndex, s);
6014 return (s->kind == SK_ARRAYFETCH);
6015}
6016
6017bool sRef_isAnyParam (sRef s)
6018{
6019 PREDTEST (sRef_isAnyParam, s);
6020 return (s->kind == SK_PARAM);
6021}
6022
6023bool sRef_isParam (sRef s)
6024{
6025 PREDTEST (sRef_isParam, s);
6026 return (s->kind == SK_PARAM);
6027}
6028
6029bool sRef_isDirectParam (sRef s)
6030{
6031 PREDTEST (sRef_isDirectParam, s);
6032
6033 return ((s->kind == SK_CVAR) &&
6034 (s->info->cvar->lexlevel == functionScope) &&
6035 (context_inFunction () &&
b73d1009 6036 (s->info->cvar->index <= usymId_fromInt (uentryList_size (context_getParams ())))));
616915dd 6037}
6038
6039bool sRef_isPointer (sRef s)
6040{
6041 PREDTEST (sRef_isPointer, s);
6042 return (s->kind == SK_PTR);
6043}
6044
6045/*
6046** returns true if storage referenced by s is visible
6047*/
6048
6049bool sRef_isReference (sRef s)
6050{
6051 PREDTEST (sRef_isReference, s);
6052
28bf4b0b 6053 return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isFileOrGlobalScope (s)
616915dd 6054 || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
6055}
6056
6057bool sRef_isIReference (sRef s)
6058{
6059 return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
6060 || sRef_isField (s) || sRef_isArrayFetch (s));
6061}
6062
28bf4b0b 6063bool sRef_isFileOrGlobalScope (sRef s)
616915dd 6064{
6065 return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
6066}
6067
6068bool sRef_isRealGlobal (sRef s)
6069{
6070 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
6071}
6072
6073bool sRef_isFileStatic (sRef s)
6074{
6075 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
6076}
6077
6078bool sRef_isAliasCheckedGlobal (sRef s)
6079{
28bf4b0b 6080 if (sRef_isFileOrGlobalScope (s))
616915dd 6081 {
6082 uentry ue = sRef_getUentry (s);
6083
6084 return context_checkAliasGlob (ue);
6085 }
6086 else
6087 {
6088 return FALSE;
6089 }
6090}
6091
6092void sRef_free (/*@only@*/ sRef s)
6093{
6094 if (s != sRef_undefined && s->kind != SK_SPECIAL)
6095 {
28bf4b0b 6096 DPRINTF (("Free sref: [%p]", s));
6097
6098 sRef_checkValid (s);
6fcd0b1e 6099
6100 multiVal_free (s->val); /* evans 2002-07-12 */
28bf4b0b 6101
6102 stateInfo_free (s->expinfo);
6103 stateInfo_free (s->aliasinfo);
6104 stateInfo_free (s->definfo);
6105 stateInfo_free (s->nullinfo);
6106
616915dd 6107 sRefSet_free (s->deriv);
6108 s->deriv = sRefSet_undefined;
28bf4b0b 6109
6fcd0b1e 6110 valueTable_free (s->state);
616915dd 6111 sinfo_free (s);
6112
795e7f34 6113
6114 /* drl added to help locate use after release*/
6115 s->expinfo = stateInfo_undefined;
6116 s->aliasinfo = stateInfo_undefined;
6117 s->definfo = stateInfo_undefined;
6118 s->nullinfo = stateInfo_undefined;
6119
b73d1009 6120 sfree (s);
616915dd 6121 }
6122}
6123
6124void sRef_setType (sRef s, ctype t)
6125{
6483a926 6126 if (sRef_isReasonable (s))
616915dd 6127 {
02b84d4b 6128 sRef_checkMutable (s);
616915dd 6129 s->type = t;
6130 }
6131}
6132
6133void sRef_setTypeFull (sRef s, ctype t)
6134{
6483a926 6135 if (sRef_isReasonable (s))
616915dd 6136 {
02b84d4b 6137 sRef_checkMutable (s);
616915dd 6138 s->type = t;
6139
6140 sRefSet_allElements (s->deriv, current)
6141 {
6142 sRef_setTypeFull (current, ctype_unknown);
6143 } end_sRefSet_allElements ;
6144 }
6145}
6146
6147/*@exposed@*/ sRef
28bf4b0b 6148 sRef_buildField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
616915dd 6149{
6150 return (sRef_buildNCField (rec, f));
6151}
6152
6153static /*@exposed@*/ sRef
6154sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
6155{
6483a926 6156 sRefSet_allElements (sRef_derivedFields (rec), sr)
616915dd 6157 {
6483a926 6158 if (sRef_isReasonable (sr))
616915dd 6159 {
6483a926 6160 if (sRef_isReasonable (sr))
616915dd 6161 {
6483a926 6162 if (sr->info != NULL)
28bf4b0b 6163 {
6483a926 6164 if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
6165 {
6166 return sr;
6167 }
28bf4b0b 6168 }
616915dd 6169 }
6483a926 6170 else
6171 {
6172 llcontbug (message ("Invalid sRef as derived field of %s", sRef_unparse (rec)));
6173 }
616915dd 6174 }
6175 } end_sRefSet_allElements;
6176
6177 return sRef_undefined;
6178}
6179
28bf4b0b 6180/*@dependent@*/ /*@observer@*/ sRefSet sRef_derivedFields (/*@temp@*/ sRef rec)
616915dd 6181{
6483a926 6182 if (sRef_isReasonable (rec))
616915dd 6183 {
6184 sRefSet ret;
6185 ret = rec->deriv;
6186 return (ret);
6187 }
6188 else
6189 {
6190 return (sRefSet_undefined);
6191 }
6192}
6193
6194static /*@exposed@*/ sRef
6195 sRef_findDerivedPointer (sRef s)
6196{
6483a926 6197 if (sRef_isReasonable (s))
616915dd 6198 {
6199 sRefSet_realElements (s->deriv, sr)
6200 {
6483a926 6201 if (sRef_isReasonable (sr) && sr->kind == SK_PTR)
616915dd 6202 {
6203 return sr;
6204 }
6205 } end_sRefSet_realElements;
6206 }
6207
6208 return sRef_undefined;
6209}
6210
6211bool
6212sRef_isUnknownArrayFetch (sRef s)
6213{
6483a926 6214 return (sRef_isReasonable (s)
616915dd 6215 && s->kind == SK_ARRAYFETCH
6216 && !s->info->arrayfetch->indknown);
6217}
6218
6219static /*@exposed@*/ sRef
6220sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
6221{
6222
6223 if (isknown)
6224 {
6225 sRefSet_realElements (s->deriv, sr)
6226 {
6483a926 6227 if (sRef_isReasonable (sr)
616915dd 6228 && sr->kind == SK_ARRAYFETCH
6229 && sr->info->arrayfetch->indknown
6230 && (sr->info->arrayfetch->ind == idx))
6231 {
6232 return sr;
6233 }
6234 } end_sRefSet_realElements;
6235 }
6236 else
6237 {
6238 sRefSet_realElements (s->deriv, sr)
6239 {
6483a926 6240 if (sRef_isReasonable (sr)
616915dd 6241 && sr->kind == SK_ARRAYFETCH
6242 && (!sr->info->arrayfetch->indknown
6243 || (sr->info->arrayfetch->indknown &&
6244 sr->info->arrayfetch->ind == 0)))
6245 {
6246 if (sRef_isDead (sr) || sRef_isKept (sr))
6247 {
6248 if (dead || context_getFlag (FLG_STRICTUSERELEASED))
6249 {
6250 return sr;
6251 }
6252 }
6253 else
6254 {
6255 return sr;
6256 }
6257 }
6258 } end_sRefSet_realElements;
6259 }
6260
6261 return sRef_undefined;
6262}
6263
6264static /*@exposed@*/ sRef
6265sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
6266{
6267 sRef s;
6268
28bf4b0b 6269 DPRINTF (("Build nc field: %s / %s",
6270 sRef_unparseFull (rec), f));
6271
616915dd 6272 if (sRef_isInvalid (rec))
6273 {
6274 return sRef_undefined;
6275 }
6276
6277 /*
6278 ** check if the field already has been referenced
6279 */
6280
6281 s = sRef_findDerivedField (rec, f);
6282
6483a926 6283 if (sRef_isReasonable (s))
616915dd 6284 {
28bf4b0b 6285 return s;
616915dd 6286 }
6287 else
6288 {
6289 ctype ct = ctype_realType (rec->type);
27c9e640 6290
28bf4b0b 6291 DPRINTF (("Field of: %s", sRef_unparse (rec)));
6292
6293 s = sRef_newRef ();
616915dd 6294 s->kind = SK_FIELD;
6295 s->info = (sinfo) dmalloc (sizeof (*s->info));
6296 s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
b73d1009 6297 s->info->field->rec = rec;
616915dd 6298 s->info->field->field = f; /* doesn't copy f */
6299
616915dd 6300 if (ctype_isKnown (ct) && ctype_isSU (ct))
6301 {
6302 uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
6303
6304 if (!uentry_isUndefined (ue))
6305 {
28bf4b0b 6306 DPRINTF (("lookup: %s for %s", uentry_unparseFull (ue),
6307 ctype_unparse (ct)));
6308
616915dd 6309 s->type = uentry_getType (ue);
6310
6311 if (ctype_isMutable (s->type)
6312 && rec->aliaskind != AK_STACK
6313 && !alkind_isStatic (rec->aliaskind))
6314 {
6315 s->aliaskind = rec->aliaskind;
6316 }
6317 else
6318 {
6319 s->aliaskind = AK_UNKNOWN;
6320 }
6321
6322 if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec)
6323 || sRef_isPdefined (rec))
6324 {
28bf4b0b 6325 sRef_setStateFromUentry (s, ue);
6326 }
616915dd 6327 else
6328 {
6329 sRef_setPartsFromUentry (s, ue);
28bf4b0b 6330 }
6331
616915dd 6332 s->oaliaskind = s->aliaskind;
6333 s->oexpkind = s->expkind;
16c024b5 6334
28bf4b0b 6335 DPRINTF (("sref: %s", sRef_unparseFull (s)));
616915dd 6336 }
6337 else
6338 {
6339 /*
6340 Never report this as an error. It can happen whenever there
6341 is casting involved.
6342
6343 if (report)
6344 {
6345 llcontbug (message ("buildNCField --- no field %s: %q / %s",
6346 f, sRef_unparse (s), ctype_unparse (ct)));
6347 }
6348 */
6349
6350 return sRef_undefined;
6351 }
6352 }
6353
6354 if (rec->defstate == SS_DEFINED
6355 && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
6356 {
6357 s->defstate = SS_DEFINED;
6358 }
6359 else if (rec->defstate == SS_PARTIAL)
6360 {
6361 s->defstate = SS_PARTIAL;
6362 }
6363 else if (rec->defstate == SS_ALLOCATED)
6364 {
6365 if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
6366 {
6367 s->defstate = SS_ALLOCATED;
6368 }
6369 else
6370 {
6371 s->defstate = SS_UNDEFINED;
6372 }
6373 }
6374 else if (s->defstate == SS_UNKNOWN)
6375 {
6376 s->defstate = rec->defstate;
6377 }
6378 else
6379 {
6380 ; /* no change */
6381 }
6382
6383 if (s->defstate == SS_UNDEFINED)
6384 {
6385 ctype rt = ctype_realType (s->type);
6386
6387 if (ctype_isArray (rt) || ctype_isSU (rt))
6388 {
28bf4b0b 6389 s->defstate = SS_ALLOCATED;
616915dd 6390 }
6391 }
6392
6393 sRef_addDeriv (rec, s);
28bf4b0b 6394 DPRINTF (("Add deriv: %s", sRef_unparseFull (rec)));
616915dd 6395
6396 if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
6397 {
6398 s->aliaskind = AK_REFS;
6399 s->oaliaskind = AK_REFS;
6400 }
6401
28bf4b0b 6402 DPRINTF (("Build field ==> %s", sRef_unparseFull (s)));
6403 return s;
616915dd 6404 }
6405}
6406
6407bool
6408sRef_isStackAllocated (sRef s)
6409{
6483a926 6410 return (sRef_isReasonable(s)
616915dd 6411 && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
6412}
6413
6414static
6415void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s,
6416 /*@notnull@*/ /*@exposed@*/ sRef arr)
6417{
28bf4b0b 6418 sRef_checkMutable (s);
6419
616915dd 6420 if (ctype_isRealAP (arr->type))
6421 {
6422 s->type = ctype_baseArrayPtr (arr->type);
6423 }
6424
6425 /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
1d239d69 6426 /* evans - 2001-08-27: not sure where this was necessary - it
6427 ** causes an assertion in in aliasCheckPred to fail.
6428 */
6429
616915dd 6430 if (sRef_isAddress (arr))
6431 {
6432 sRef t = arr->info->ref;
6433
6434 if (sRef_isArrayFetch (t))
6435 {
6436 s->info->arrayfetch->arr = t->info->arrayfetch->arr;
6437 }
6438 }
6439 else if (ctype_isRealPointer (arr->type))
6440 {
6441 sRef sp = sRef_findDerivedPointer (arr);
616915dd 6442
6483a926 6443 if (sRef_isReasonable (sp))
616915dd 6444 {
6445
6446 if (ctype_isMutable (s->type))
6447 {
16c024b5 6448 s->expkind = sRef_getExKind (sp);
6449 s->expinfo = stateInfo_copy (sp->expinfo);
6450
616915dd 6451 s->aliaskind = sp->aliaskind;
16c024b5 6452 s->aliasinfo = stateInfo_copy (sp->aliasinfo);
616915dd 6453 }
6454
6455 s->defstate = sp->defstate;
6456
6457 if (s->defstate == SS_DEFINED)
6458 {
6459 if (!context_getFlag (FLG_STRICTDESTROY))
6460 {
6461 s->defstate = SS_PARTIAL;
6462 }
6463 }
6464
393e573f 6465 DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), sRef_unparseFull (sp)));
28bf4b0b 6466 sRef_setNullStateN (s, sRef_getNullState (sp));
616915dd 6467 }
6468 else
6469 {
6470 if (arr->defstate == SS_UNDEFINED)
6471 {
6472 s->defstate = SS_UNUSEABLE;
6473 }
6474 else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
6475 {
6476 s->defstate = SS_UNDEFINED;
6477 }
6478 else
6479 {
6480 if (!context_getFlag (FLG_STRICTDESTROY))
6481 {
6482 s->defstate = SS_PARTIAL;
6483 }
6484 else
6485 {
6486 s->defstate = SS_DEFINED;
6487 }
6488
6489 /*
6490 ** Very weak checking for array elements.
6491 ** Was:
6492 ** s->defstate = arr->defstate;
6493 */
6494 }
6495
16c024b5 6496 s->expkind = sRef_getExKind (arr);
6497 s->expinfo = stateInfo_copy (arr->expinfo);
6498
616915dd 6499 if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
6500 {
6501 s->aliaskind = AK_LOCAL;
6502 }
6503 else
6504 {
6505 s->aliaskind = AK_UNKNOWN;
6506 }
6507
6508 sRef_setTypeState (s);
6509 }
6510 }
6511 else
6512 {
6513 if (arr->defstate == SS_DEFINED)
6514 {
6515 /*
6516 ** Very weak checking for array elements.
6517 ** Was:
6518 ** s->defstate = arr->defstate;
6519 */
6520
6521 if (context_getFlag (FLG_STRICTDESTROY))
6522 {
6523 s->defstate = SS_DEFINED;
6524 }
6525 else
6526 {
6527 s->defstate = SS_PARTIAL;
6528 }
6529 }
6530 else if (arr->defstate == SS_ALLOCATED)
6531 {
6532 if (ctype_isRealArray (s->type))
6533 {
6534 s->defstate = SS_ALLOCATED;
6535 }
6536 else
6537 {
6538 if (!s->info->arrayfetch->indknown)
6539 {
6540 /*
6541 ** is index is unknown, elements is defined or
6542 ** allocated is any element is!
6543 */
6544
6545 s->defstate = SS_UNDEFINED;
6546
6547 sRefSet_allElements (arr->deriv, sr)
6548 {
6483a926 6549 if (sRef_isReasonable (sr))
616915dd 6550 {
6483a926 6551 if (sRef_isReasonable (sr))
616915dd 6552 {
6483a926 6553 if (sr->defstate == SS_ALLOCATED)
616915dd 6554 {
6483a926 6555 s->defstate = SS_ALLOCATED;
6556 }
6557 else
6558 {
6559 if (sr->defstate == SS_DEFINED)
616915dd 6560 {
6483a926 6561 if (context_getFlag (FLG_STRICTDESTROY))
6562 {
6563 s->defstate = SS_DEFINED;
6564 }
6565 else
6566 {
6567 s->defstate = SS_PARTIAL;
6568 }
6569
6570 break;
616915dd 6571 }
616915dd 6572 }
6573 }
6483a926 6574 else
6575 {
6576 llcontbug (message ("Invalid sRef as derived element of %s", sRef_unparse (arr)));
6577 }
616915dd 6578 }
6579 } end_sRefSet_allElements;
6483a926 6580 }
616915dd 6581 else
6582 {
6583 s->defstate = SS_UNDEFINED;
6584 }
6585 }
6586 }
6587 else
6588 {
6589 s->defstate = arr->defstate;
6590 }
6591
6592
6593 /*
6594 ** kludgey way to guess where aliaskind applies
6595 */
6596
6597 if (ctype_isMutable (s->type)
6598 && !ctype_isPointer (arr->type)
6599 && !alkind_isStatic (arr->aliaskind)
6600 && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6601 {
6602 s->aliaskind = arr->aliaskind;
6603 }
6604 else
6605 {
6606 s->aliaskind = AK_UNKNOWN;
6607 }
6608
6609 sRef_setTypeState (s);
6610 }
6611
6612 if (sRef_isObserver (arr))
6613 {
6614 s->expkind = XO_OBSERVER;
16c024b5 6615 s->expinfo = stateInfo_copy (arr->expinfo);
616915dd 6616 }
6617}
6618
6619/*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6620{
6621 sRef s;
6622
6483a926 6623 if (!sRef_isReasonable (arr)) {
616915dd 6624 /*@-nullret@*/ return arr /*@=nullret@*/;
6625 }
6626
6627 if (ctype_isRealPointer (arr->type))
6628 {
6629 (void) sRef_buildPointer (arr); /* do this to define arr! */
6630 }
6631
6632 s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6633
6483a926 6634 if (sRef_isReasonable (s))
616915dd 6635 {
3120b462 6636 /* evans 2001-07-12: this is bogus, clean-up hack */
6637 if (s->info->arrayfetch->arr != arr)
6638 {
6639 sRef res;
6640 check (sRefSet_delete (arr->deriv, s));
6641 res = sRef_buildArrayFetch (arr);
6642 sRef_copyState (res, s);
1d239d69 6643 llassert (res->info->arrayfetch->arr == arr);
3120b462 6644 return res;
6645 }
6646
16c024b5 6647 s->expkind = sRef_getExKind (arr);
6648 s->expinfo = stateInfo_copy (arr->expinfo);
6649
616915dd 6650 return s;
6651 }
6652 else
6653 {
28bf4b0b 6654 s = sRef_newRef ();
616915dd 6655
6656 s->kind = SK_ARRAYFETCH;
6657 s->info = (sinfo) dmalloc (sizeof (*s->info));
6658 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6659 s->info->arrayfetch->indknown = FALSE;
6660 s->info->arrayfetch->ind = 0;
b73d1009 6661 s->info->arrayfetch->arr = arr;
393e573f 6662
616915dd 6663 sRef_setArrayFetchState (s, arr);
393e573f 6664
616915dd 6665 s->oaliaskind = s->aliaskind;
6666 s->oexpkind = s->expkind;
6667
6668 if (!context_inProtectVars ())
6669 {
6670 sRef_addDeriv (arr, s);
6671 }
6672
ccf0a4a8 6673 if (valueTable_isUndefined (s->state))
6674 {
16c024b5 6675 s->state = context_createValueTable
6676 (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
ccf0a4a8 6677 }
393e573f 6678
616915dd 6679 return (s);
6680 }
6681}
6682
6683/*@exposed@*/ sRef
6684 sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6685{
6686 sRef s;
6687
6483a926 6688 if (!sRef_isReasonable (arr)) {
616915dd 6689 /*@-nullret@*/ return arr /*@=nullret@*/;
6690 }
6691
6692 if (ctype_isRealPointer (arr->type))
6693 {
1d239d69 6694 (void) sRef_buildPointer (arr); /* do this to define arr! */
616915dd 6695 }
6696
6697 s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
1d239d69 6698
6483a926 6699 if (sRef_isReasonable (s))
616915dd 6700 {
3120b462 6701 /* evans 2001-07-12: this is bogus, clean-up hack */
6702 if (s->info->arrayfetch->arr != arr)
6703 {
6704 sRef res;
1d239d69 6705
3120b462 6706 check (sRefSet_delete (arr->deriv, s));
6707 res = sRef_buildArrayFetchKnown (arr, i);
1d239d69 6708
6709 llassert (res->info->arrayfetch->arr == arr);
3120b462 6710 sRef_copyState (res, s);
1d239d69 6711 llassert (res->info->arrayfetch->arr == arr);
3120b462 6712 return res;
6713 }
6714
16c024b5 6715 s->expkind = sRef_getExKind (arr);
6716 s->expinfo = stateInfo_copy (arr->expinfo);
6717
3120b462 6718 llassert (s->info->arrayfetch->arr == arr);
616915dd 6719 return s;
6720 }
6721 else
6722 {
28bf4b0b 6723 s = sRef_newRef ();
616915dd 6724
6725 s->kind = SK_ARRAYFETCH;
6726 s->info = (sinfo) dmalloc (sizeof (*s->info));
6727 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
b73d1009 6728 s->info->arrayfetch->arr = arr;
616915dd 6729 s->info->arrayfetch->indknown = TRUE;
6730 s->info->arrayfetch->ind = i;
1d239d69 6731
616915dd 6732 sRef_setArrayFetchState (s, arr);
1d239d69 6733 /* evans 2001-08-27 no: can change this - llassert (s->info->arrayfetch->arr == arr); */
6734
616915dd 6735 s->oaliaskind = s->aliaskind;
6736 s->oexpkind = s->expkind;
6737 sRef_addDeriv (arr, s);
6738
28bf4b0b 6739 llassert (valueTable_isUndefined (s->state));
16c024b5 6740 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
616915dd 6741 return (s);
6742 }
6743}
6744
6745/*
6746** sets everything except for defstate
6747*/
6748
6749static void
6750sRef_setPartsFromUentry (sRef s, uentry ue)
28bf4b0b 6751{
6752 sRef uref = uentry_getSref (ue);
6753
6483a926 6754 llassert (sRef_isReasonable (s));
616915dd 6755
6756 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6757 s->oaliaskind = s->aliaskind;
6758
6759 if (s->expkind == XO_UNKNOWN)
6760 {
6761 s->expkind = uentry_getExpKind (ue);
6762 }
28bf4b0b 6763
616915dd 6764 s->oexpkind = s->expkind;
28bf4b0b 6765
6766 if (sRef_getNullState (s) == NS_UNKNOWN)
6767 {
393e573f 6768 DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), uentry_unparseFull (ue)));
28bf4b0b 6769 sRef_setNullStateN (s, sRef_getNullState (uentry_getSref (ue)));
6770 }
6771 else
616915dd 6772 {
28bf4b0b 6773 DPRINTF (("Skipping null null state!"));
616915dd 6774 }
6775
28bf4b0b 6776 if (s->aliaskind == AK_IMPONLY && (sRef_isExposed (s) || sRef_isObserver (s)))
616915dd 6777 {
6778 s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
28bf4b0b 6779 }
616915dd 6780
6483a926 6781 if (sRef_isReasonable (uref))
28bf4b0b 6782 {
6783 valueTable utable = uref->state;
6784 valueTable_free (s->state);
6785 s->state = valueTable_copy (utable);
6786 }
616915dd 6787}
6788
6789static void
6790sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6791{
6483a926 6792 llassert (sRef_isReasonable (s));
28bf4b0b 6793 sRef_checkMutable (s);
6794
616915dd 6795 sRef_setPartsFromUentry (s, ue);
6796
6797 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6798 s->oaliaskind = s->aliaskind;
6799
6800 if (s->expkind == XO_UNKNOWN)
6801 {
6802 s->expkind = uentry_getExpKind (ue);
6803 }
6804
6805 s->oexpkind = s->expkind;
6806}
6807
6808void
6809sRef_setStateFromUentry (sRef s, uentry ue)
6810{
6811 sstate defstate;
6812
28bf4b0b 6813 sRef_checkMutable (s);
6483a926 6814 llassert (sRef_isReasonable (s));
616915dd 6815
6816 sRef_setPartsFromUentry (s, ue);
6817
6818 defstate = uentry_getDefState (ue);
6819
6820 if (sstate_isKnown (defstate))
6821 {
6822 s->defstate = defstate;
6823 }
6824 else
6825 {
6826 ;
6827 }
6828}
6829
6830/*@exposed@*/ sRef
6831 sRef_buildPointer (/*@exposed@*/ sRef t)
6832{
6833 DPRINTF (("build pointer: %s", sRef_unparse (t)));
6834
6835 if (sRef_isInvalid (t)) return sRef_undefined;
6836
6837 if (sRef_isAddress (t))
6838 {
6839 DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6840 return (t->info->ref);
6841 }
6842 else
6843 {
6844 sRef s = sRef_findDerivedPointer (t);
6845
6846 DPRINTF (("find derived: %s", sRef_unparse (s)));
6847
6483a926 6848 if (sRef_isReasonable (s))
616915dd 6849 {
16c024b5 6850 s->expkind = sRef_getExKind (t);
6851 s->expinfo = stateInfo_copy (t->expinfo);
6852
616915dd 6853 s->oaliaskind = s->aliaskind;
6854 s->oexpkind = s->expkind;
6855
6856 return s;
6857 }
6858 else
6859 {
6860 s = sRef_constructPointerAux (t);
6861
6862 DPRINTF (("construct: %s", sRef_unparse (s)));
6863
6483a926 6864 if (sRef_isReasonable (s))
616915dd 6865 {
6866 sRef_addDeriv (t, s);
6867
6868 s->oaliaskind = s->aliaskind;
6869 s->oexpkind = s->expkind;
6870 }
6871
6872 return s;
6873 }
6874 }
6875}
6876
6877/*@exposed@*/ sRef
28bf4b0b 6878sRef_constructPointer (/*@exposed@*/ sRef t)
616915dd 6879 /*@modifies t@*/
6880{
6881 return sRef_buildPointer (t);
6882}
6883
6884static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6885{
6483a926 6886 if (sRef_isReasonable (t))
616915dd 6887 {
6888 sRef s;
6889
6890 /*
6891 ** if there is a derived t[?], return that. Otherwise, *t.
6892 */
6893
616915dd 6894 s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6895
6483a926 6896 if (sRef_isReasonable (s))
616915dd 6897 {
3120b462 6898 DPRINTF (("Found array fetch: %s", sRef_unparseFull (s)));
28bf4b0b 6899 return s;
616915dd 6900 }
6901 else
6902 {
6903 sRef ret = sRef_constructPointer (t);
6904
3120b462 6905 DPRINTF (("Constructed pointer: %s", sRef_unparseFull (ret)));
616915dd 6906
3120b462 6907 return ret;
616915dd 6908 }
6909 }
6910 else
6911 {
6912 return sRef_undefined;
6913 }
6914}
6915
6916sRef sRef_constructDeref (sRef t)
6917{
6918 return sRef_constructDerefAux (t, FALSE);
6919}
6920
6921sRef sRef_constructDeadDeref (sRef t)
6922{
6923 return sRef_constructDerefAux (t, TRUE);
6924}
6925
6926static sRef
6927sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6928{
28bf4b0b 6929 sRef s = sRef_newRef ();
616915dd 6930 ctype rt = t->type;
6931 ctype st;
6932
ccf0a4a8 6933 llassert (valueTable_isUndefined (s->state));
6934
616915dd 6935 s->kind = SK_PTR;
6936 s->info = (sinfo) dmalloc (sizeof (*s->info));
b73d1009 6937 s->info->ref = t;
616915dd 6938
6939 if (ctype_isRealAP (rt))
6940 {
6941 s->type = ctype_baseArrayPtr (rt);
6942 }
6943
28bf4b0b 6944 st = ctype_realType (s->type);
ccf0a4a8 6945
616915dd 6946 if (t->defstate == SS_UNDEFINED)
6947 {
6948 s->defstate = SS_UNUSEABLE;
16c024b5 6949 s->definfo = stateInfo_copy (t->definfo);
616915dd 6950 }
6951 else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6952 {
6953 s->defstate = SS_UNDEFINED;
16c024b5 6954 s->definfo = stateInfo_copy (t->definfo);
616915dd 6955 }
6956 else
6957 {
6958 s->defstate = t->defstate;
16c024b5 6959 s->definfo = stateInfo_copy (t->definfo);
616915dd 6960 }
6961
6962 if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6963 {
6964 s->aliaskind = AK_LOCAL;
6965 }
6966 else
6967 {
6968 s->aliaskind = AK_UNKNOWN;
6969 }
ccf0a4a8 6970
16c024b5 6971 s->expkind = sRef_getExKind (t);
6972 s->expinfo = stateInfo_copy (t->expinfo);
6973
616915dd 6974 sRef_setTypeState (s);
ccf0a4a8 6975
616915dd 6976 s->oaliaskind = s->aliaskind;
6977 s->oexpkind = s->expkind;
6978
ccf0a4a8 6979 if (valueTable_isUndefined (s->state))
6980 {
16c024b5 6981 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
ccf0a4a8 6982 }
6983
16c024b5 6984 DPRINTF (("pointer: %s", sRef_unparseFull (s)));
616915dd 6985 return s;
6986}
6987
6988bool sRef_hasDerived (sRef s)
6989{
6483a926 6990 return (sRef_isReasonable (s) && !sRefSet_isEmpty (s->deriv));
616915dd 6991}
6992
6993void
6994sRef_clearDerived (sRef s)
6995{
6483a926 6996 if (sRef_isReasonable (s))
616915dd 6997 {
6483a926 6998 DPRINTF (("Clear derived: [%p] %s", s, sRef_unparseDebug (s)));
28bf4b0b 6999 sRefSet_clear (s->deriv);
616915dd 7000 }
7001}
7002
7003void
7004sRef_clearDerivedComplete (sRef s)
7005{
6483a926 7006 if (sRef_isReasonable (s))
616915dd 7007 {
7008 sRef base = sRef_getBaseSafe (s);
6483a926 7009
7010 while (sRef_isReasonable (base))
616915dd 7011 {
6483a926 7012 DPRINTF (("Clear derived: [%p] %s", base, sRef_unparse (base)));
616915dd 7013 sRefSet_clear (base->deriv);
7014 base = sRef_getBaseSafe (base);
7015 }
7016
6483a926 7017 DPRINTF (("Clear derived: [%p] %s", s, sRef_unparse (s)));
616915dd 7018 sRefSet_clear (s->deriv);
7019 }
7020}
7021
28bf4b0b 7022/*@exposed@*/ sRef sRef_makePointer (/*@exposed@*/ sRef s)
7023 /*@modifies s@*/
616915dd 7024{
7025 sRef res = sRef_buildPointer (s);
7026
16c024b5 7027 DPRINTF (("Res: %s", sRef_unparseFull (res)));
616915dd 7028 return res;
7029}
7030
7031/*
7032** &a[] => a (this is for out params)
7033*/
7034
7035/*@exposed@*/ sRef
7036sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
393e573f 7037{
616915dd 7038 if (sRef_isAddress (arr))
7039 {
28bf4b0b 7040 return (arr->info->ref);
616915dd 7041 }
7042 else
7043 {
7044 return (sRef_buildArrayFetch (arr));
7045 }
7046}
7047
7048/*@exposed@*/ sRef
28bf4b0b 7049sRef_makeArrayFetch (/*@exposed@*/ sRef arr)
616915dd 7050{
7051 return (sRef_buildArrayFetch (arr));
7052}
7053
7054/*@exposed@*/ sRef
28bf4b0b 7055sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
616915dd 7056{
7057 return (sRef_buildArrayFetchKnown (arr, i));
7058}
7059
7060/*@exposed@*/ sRef
7061sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
7062{
7063 sRef ret;
7064 ret = sRef_buildField (rec, f);
7065 return ret;
7066}
7067
7068/*@exposed@*/ sRef
28bf4b0b 7069sRef_makeNCField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
616915dd 7070{
28bf4b0b 7071 return (sRef_buildNCField (rec, f));
616915dd 7072}
7073
7074/*@only@*/ cstring
7075sRef_unparseKindName (sRef s)
7076{
7077 cstring result;
7078
7079 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7080
7081 s = sRef_fixConj (s);
7082
7083 switch (s->kind)
7084 {
7085 case SK_CVAR:
7086 if (sRef_isLocalVar (s))
7087 {
7088 result = cstring_makeLiteral ("Variable");
7089 }
7090 else
7091 {
7092 result = cstring_makeLiteral ("Undef global");
7093 }
7094 break;
7095 case SK_PARAM:
7096 result = cstring_makeLiteral ("Out parameter");
7097 break;
7098 case SK_ARRAYFETCH:
7099 if (sRef_isAnyParam (s->info->arrayfetch->arr))
7100 {
7101 result = cstring_makeLiteral ("Out parameter");
7102 }
7103 else if (sRef_isIndexKnown (s))
7104 {
7105 result = cstring_makeLiteral ("Array element");
7106 }
7107 else
7108 {
7109 result = cstring_makeLiteral ("Value");
7110 }
7111 break;
7112 case SK_PTR:
7113 if (sRef_isAnyParam (s->info->ref))
7114 {
7115 result = cstring_makeLiteral ("Out parameter");
7116 }
7117 else
7118 {
7119 result = cstring_makeLiteral ("Value");
7120 }
7121 break;
7122 case SK_ADR:
7123 result = cstring_makeLiteral ("Value");
7124 break;
7125 case SK_FIELD:
7126 result = cstring_makeLiteral ("Field");
7127 break;
7128 case SK_OBJECT:
7129 result = cstring_makeLiteral ("Object");
7130 break;
7131 case SK_UNCONSTRAINED:
7132 result = cstring_makeLiteral ("<anything>");
7133 break;
7134 case SK_RESULT:
7135 case SK_SPECIAL:
7136 case SK_UNKNOWN:
7137 case SK_EXTERNAL:
7138 case SK_DERIVED:
7139 case SK_CONST:
7140 case SK_TYPE:
7141 result = cstring_makeLiteral ("<unknown>");
7142 break;
7143 case SK_CONJ:
7144 result = cstring_makeLiteral ("<conj>");
7145 break;
7146 case SK_NEW:
7147 result = cstring_makeLiteral ("Storage");
7148 break;
7149 }
7150
7151 return result;
7152}
7153
7154/*@only@*/ cstring
7155sRef_unparseKindNamePlain (sRef s)
7156{
7157 cstring result;
7158
7159 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7160
7161 s = sRef_fixConj (s);
7162
7163 switch (s->kind)
7164 {
7165 case SK_CVAR:
7166 if (sRef_isLocalVar (s))
7167 {
7168 result = cstring_makeLiteral ("Variable");
7169 }
7170 else
7171 {
7172 result = cstring_makeLiteral ("Global");
7173 }
7174 break;
7175 case SK_PARAM:
7176 result = cstring_makeLiteral ("Parameter");
7177 break;
7178 case SK_ARRAYFETCH:
7179 if (sRef_isAnyParam (s->info->arrayfetch->arr))
7180 {
7181 result = cstring_makeLiteral ("Parameter");
7182 }
7183 else if (sRef_isIndexKnown (s))
7184 {
7185 result = cstring_makeLiteral ("Array element");
7186 }
7187 else
7188 {
7189 result = cstring_makeLiteral ("Value");
7190 }
7191 break;
7192 case SK_PTR:
7193 if (sRef_isAnyParam (s->info->ref))
7194 {
7195 result = cstring_makeLiteral ("Parameter");
7196 }
7197 else
7198 {
7199 result = cstring_makeLiteral ("Value");
7200 }
7201 break;
7202 case SK_ADR:
7203 result = cstring_makeLiteral ("Value");
7204 break;
7205 case SK_FIELD:
7206 result = cstring_makeLiteral ("Field");
7207 break;
7208 case SK_OBJECT:
7209 result = cstring_makeLiteral ("Object");
7210 break;
7211 case SK_NEW:
7212 result = cstring_makeLiteral ("Storage");
7213 break;
7214 case SK_UNCONSTRAINED:
7215 result = cstring_makeLiteral ("<anything>");
7216 break;
7217 case SK_RESULT:
7218 case SK_TYPE:
7219 case SK_CONST:
7220 case SK_EXTERNAL:
7221 case SK_DERIVED:
7222 case SK_UNKNOWN:
7223 case SK_SPECIAL:
7224 result = cstring_makeLiteral ("<unknown>");
7225 break;
7226 case SK_CONJ:
7227 result = cstring_makeLiteral ("<conj>");
7228 break;
7229 }
7230
7231 return result;
7232}
7233
7234/*
7235** s1 <- s2
7236*/
7237
7238void
7239sRef_copyState (sRef s1, sRef s2)
7240{
6483a926 7241 if (sRef_isReasonable (s1) && sRef_isReasonable (s2))
616915dd 7242 {
7243 s1->defstate = s2->defstate;
7244
616915dd 7245 /* start modifications */
7246 s1->bufinfo.bufstate = s2->bufinfo.bufstate;
7247 s1->bufinfo.len = s2->bufinfo.len;
7248 s1->bufinfo.size = s2->bufinfo.size;
7249 /* end modifications */
7250
7251 s1->aliaskind = s2->aliaskind;
28bf4b0b 7252 s1->aliasinfo = stateInfo_update (s1->aliasinfo, s2->aliasinfo);
616915dd 7253
7254 s1->expkind = s2->expkind;
28bf4b0b 7255 s1->expinfo = stateInfo_update (s1->expinfo, s2->expinfo);
393e573f 7256
28bf4b0b 7257 s1->nullstate = s2->nullstate;
210066f9 7258 DPRINTF (("Set null state==> %s", sRef_unparseFull (s1)));
28bf4b0b 7259 s1->nullinfo = stateInfo_update (s1->nullinfo, s2->nullinfo);
616915dd 7260
b73d1009 7261 valueTable_free (s1->state);
7262 s1->state = valueTable_copy (s2->state);
616915dd 7263 s1->safe = s2->safe;
28bf4b0b 7264 }
616915dd 7265}
7266
7267sRef
7268sRef_makeNew (ctype ct, sRef t, cstring name)
7269{
28bf4b0b 7270 sRef s = sRef_newRef ();
616915dd 7271
7272 s->kind = SK_NEW;
7273 s->type = ct;
7274
6483a926 7275 llassert (sRef_isReasonable (t));
616915dd 7276 s->defstate = t->defstate;
7277
7278 s->aliaskind = t->aliaskind;
7279 s->oaliaskind = s->aliaskind;
616915dd 7280 s->nullstate = t->nullstate;
28bf4b0b 7281
616915dd 7282 s->expkind = t->expkind;
7283 s->oexpkind = s->expkind;
28bf4b0b 7284
616915dd 7285 s->info = (sinfo) dmalloc (sizeof (*s->info));
7286 s->info->fname = name;
7287
7288 /* start modifications */
7289 s->bufinfo.bufstate = t->bufinfo.bufstate;
7290 /* end modifications */
28bf4b0b 7291
7292 llassert (valueTable_isUndefined (s->state));
7293 s->state = valueTable_copy (t->state);
616915dd 7294
28bf4b0b 7295 DPRINTF (("==> Copying state: %s", valueTable_unparse (s->state)));
7296 DPRINTF (("==> new: %s", sRef_unparseFull (s)));
7297 return s;
616915dd 7298}
7299
7300sRef
7301sRef_makeType (ctype ct)
7302{
28bf4b0b 7303 sRef s = sRef_newRef ();
7304
7305 sRef_checkMutable (s);
7306
616915dd 7307 s->kind = SK_TYPE;
7308 s->type = ct;
7309
7310 s->defstate = SS_UNKNOWN;
7311 s->aliaskind = AK_UNKNOWN;
28bf4b0b 7312 sRef_setNullStateN (s, NS_UNKNOWN);
7313
616915dd 7314 /* start modification */
7315 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
7316 /* end modification */
7317
7318
7319 if (ctype_isUA (ct))
7320 {
7321 typeId uid = ctype_typeId (ct);
7322 uentry ue = usymtab_getTypeEntrySafe (uid);
7323
7324 if (uentry_isValid (ue))
7325 {
7326 sRef_mergeStateQuiet (s, uentry_getSref (ue));
7327 }
7328 }
28bf4b0b 7329
7330 s->oaliaskind = s->aliaskind;
616915dd 7331 s->oexpkind = s->expkind;
28bf4b0b 7332 llassert (valueTable_isUndefined (s->state));
16c024b5 7333 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
616915dd 7334
28bf4b0b 7335 DPRINTF (("Create: %s", sRef_unparseFull (s)));
616915dd 7336 return s;
7337}
7338
7339sRef
7340sRef_makeConst (ctype ct)
7341{
28bf4b0b 7342 sRef s = sRef_newRef ();
616915dd 7343
7344 s->kind = SK_CONST;
7345 s->type = ct;
7346
7347 s->defstate = SS_UNKNOWN;
7348 s->aliaskind = AK_UNKNOWN;
28bf4b0b 7349 sRef_setNullStateN (s, NS_UNKNOWN);
7350
616915dd 7351 /* start modification */
7352 s->bufinfo.bufstate = BB_NULLTERMINATED;
7353 /* end modification */
2cecdaff 7354
7355 /* evans 2002-04-22: added isManifestBool to avoid errors for -boolfalse initializations */
7356 if (!ctype_isManifestBool (ct) && ctype_isUA (ct))
616915dd 7357 {
7358 typeId uid = ctype_typeId (ct);
7359 uentry te = usymtab_getTypeEntrySafe (uid);
7360
7361 if (uentry_isValid (te))
7362 {
7363 sRef_mergeStateQuiet (s, uentry_getSref (te));
7364 }
7365 }
28bf4b0b 7366
616915dd 7367 s->oaliaskind = s->aliaskind;
7368 s->oexpkind = s->expkind;
7369
28bf4b0b 7370 llassert (valueTable_isUndefined (s->state));
16c024b5 7371 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
28bf4b0b 7372
616915dd 7373 return s;
7374}
7375
7376bool sRef_hasName (sRef s)
7377{
7378 if (sRef_isInvalid (s))
7379 {
7380 return (FALSE);
7381 }
7382
7383 switch (s->kind)
7384 {
7385 case SK_CVAR:
7386 {
7387 uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
7388 s->info->cvar->index);
7389 return (uentry_hasName (u));
7390 }
7391 case SK_PARAM:
7392 {
28bf4b0b 7393 if (s->info->paramno >= 0)
7394 {
7395 uentry u = uentryList_getN (context_getParams (),
7396 s->info->paramno);
7397
7398 return (uentry_hasName (u));
7399 }
7400 else
7401 {
7402 llassert (s->info->paramno == PARAMUNKNOWN);
7403 return FALSE;
7404 }
616915dd 7405 }
7406 default:
7407 return TRUE;
7408 }
7409}
7410
616915dd 7411bool
7412sRef_sameName (sRef s1, sRef s2)
7413{
7414 if (sRef_isInvalid (s1))
7415 {
7416 return sRef_isInvalid (s2);
7417 }
7418
7419 if (sRef_isInvalid (s2))
7420 {
7421 return (FALSE);
7422 }
7423
7424 switch (s1->kind)
7425 {
7426 case SK_CVAR:
7427 if (s2->kind == SK_CVAR)
7428 {
7429 return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
7430 && s1->info->cvar->index == s2->info->cvar->index);
7431 }
7432 else if (s2->kind == SK_PARAM)
7433 {
7434 if (context_inFunctionLike ())
7435 {
28bf4b0b 7436 if (s2->info->paramno != PARAMUNKNOWN)
7437 {
7438 uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
7439 s1->info->cvar->index);
7440 uentry u2 = uentryList_getN (context_getParams (),
7441 s2->info->paramno);
7442
7443 return (cstring_equalFree (uentry_getName (u1),
7444 uentry_getName (u2)));
7445 }
7446 else
7447 {
7448 return s1->info->paramno == PARAMUNKNOWN;
7449 }
616915dd 7450 }
7451 else
7452 {
7453 return FALSE;
7454 }
7455 }
7456 else
7457 {
7458 return FALSE;
7459 }
7460 case SK_PARAM:
7461 {
7462 if (s2->kind == SK_PARAM)
7463 {
7464 return (s1->info->paramno == s2->info->paramno);
7465 }
7466 else if (s2->kind == SK_CVAR)
7467 {
7468 if (context_inFunctionLike ())
7469 {
28bf4b0b 7470 if (s1->info->paramno == PARAMUNKNOWN)
7471 {
7472 return FALSE;
7473 }
7474 else
7475 {
7476 uentry u1 = uentryList_getN (context_getParams (),
7477 s1->info->paramno);
7478 uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
7479 s2->info->cvar->index);
7480
7481
7482 return (cstring_equalFree (uentry_getName (u1),
7483 uentry_getName (u2)));
7484 }
616915dd 7485 }
7486 else
7487 {
7488 return FALSE;
7489 }
7490 }
7491 else
7492 {
7493 return FALSE;
7494 }
7495 }
7496
7497 case SK_UNCONSTRAINED:
7498 return FALSE;
7499
7500 case SK_ARRAYFETCH:
7501 if (s2->kind == SK_ARRAYFETCH)
7502 {
7503 if (bool_equal (s1->info->arrayfetch->indknown,
7504 s2->info->arrayfetch->indknown))
7505 {
7506 if (!s1->info->arrayfetch->indknown
7507 || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
7508 {
7509 return sRef_sameName (s1->info->arrayfetch->arr,
7510 s2->info->arrayfetch->arr);
7511 }
7512 }
7513 }
7514
7515 return FALSE;
7516 case SK_FIELD:
7517 if (s2->kind == SK_FIELD)
7518 {
7519 if (cstring_equal (s1->info->field->field,
7520 s2->info->field->field))
7521 {
7522 return sRef_sameName (s1->info->field->rec,
7523 s2->info->field->rec);
7524 }
7525
7526 }
7527 return FALSE;
7528 case SK_PTR:
7529 case SK_ADR:
7530 case SK_DERIVED:
7531 case SK_EXTERNAL:
7532 if (s2->kind == s1->kind)
7533 {
7534 return sRef_sameName (s1->info->ref,
7535 s2->info->ref);
7536 }
7537
7538 return FALSE;
7539 case SK_OBJECT:
7540 return FALSE;
7541 case SK_CONJ:
7542 return sRef_sameName (sRef_getConjA (s1), s2);
7543 case SK_NEW:
7544 return FALSE;
7545 case SK_UNKNOWN:
7546 return (s2->kind == SK_UNKNOWN);
7547 case SK_TYPE:
7548 case SK_CONST:
7549 if (s2->kind == s1->kind)
7550 {
7551 return (ctype_equal (s1->type, s2->type));
7552 }
7553
7554 return FALSE;
7555 case SK_SPECIAL:
7556 if (s2->kind == SK_SPECIAL)
7557 {
7558 return (s1->info->spec == s2->info->spec);
7559 }
7560 return FALSE;
7561 case SK_RESULT:
7562 return (s2->kind == SK_RESULT);
7563 default:
7564 return FALSE;
7565 }
7566 BADEXIT;
7567}
7568
7569sRef
7570sRef_fixOuterRef (/*@returned@*/ sRef s)
7571{
7572 sRef root = sRef_getRootBase (s);
7573
7574 if (sRef_isCvar (root))
7575 {
7576 uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel,
7577 root->info->cvar->index);
7578
7579 if (uentry_isValid (ue))
7580 {
7581 sRef uref = uentry_getSref (ue);
7582 sRef sr = sRef_fixBase (s, uref);
7583
7584 return (sr);
7585 }
7586 else
7587 {
7588 llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
7589 return (s);
7590 }
7591 }
7592
7593 return (s);
7594}
7595
7596void
7597sRef_storeState (sRef s)
7598{
7599 if (sRef_isInvalid (s)) return;
7600
28bf4b0b 7601 sRef_checkMutable (s);
616915dd 7602 s->oaliaskind = s->aliaskind;
7603 s->oexpkind = s->expkind;
7604}
7605
7606static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
7607{
7608 sRef_resetState (s);
7609}
7610
7611void
7612sRef_resetState (sRef s)
7613{
7614 bool changed = FALSE;
7615 if (sRef_isInvalid (s)) return;
7616
7617
7618 if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
7619 {
7620 /*
7621 ** killref is used in a kludgey way, to save having to add
7622 ** another alias kind (see usymtab_handleParams)
7623 */
7624
7625 if (s->expkind != s->oexpkind)
7626 {
7627 changed = TRUE;
7628 s->expkind = s->oexpkind;
7629 }
7630 }
7631 else
7632 {
7633 if (s->expkind != s->oexpkind)
7634 {
7635 changed = TRUE;
7636 s->expkind = s->oexpkind;
7637 }
7638
7639 if (s->aliaskind != s->oaliaskind
7640 && s->aliaskind != AK_REFCOUNTED
7641 && s->aliaskind != AK_REFS)
7642 {
7643 changed = TRUE;
7644 s->aliaskind = s->oaliaskind;
28bf4b0b 7645 }
616915dd 7646 }
7647
7648 if (changed)
7649 {
7650 sRef_clearDerived (s);
7651 }
7652
7653 }
7654
7655void
7656sRef_resetStateComplete (sRef s)
7657{
7658 sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7659}
7660
7661/*@exposed@*/ sRef
7662sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7663{
7664 sRef tmp = sRef_undefined;
7665 sRef ret;
7666
7667 if (sRef_isInvalid (s)) return s;
7668 if (sRef_isInvalid (base)) return base;
7669
7670 switch (s->kind)
7671 {
7672 case SK_RESULT:
7673 case SK_PARAM:
7674 case SK_CVAR:
7675 ret = base;
7676 break;
7677 case SK_ARRAYFETCH:
7678 tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7679
7680 if (s->info->arrayfetch->indknown)
7681 {
7682 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7683 }
7684 else
7685 {
7686 ret = sRef_makeArrayFetch (tmp);
7687 }
7688 break;
7689 case SK_FIELD:
7690 tmp = sRef_fixBase (s->info->field->rec, base);
7691 ret = sRef_buildNCField (tmp, s->info->field->field);
7692 break;
7693 case SK_PTR:
7694 tmp = sRef_fixBase (s->info->ref, base);
7695 ret = sRef_makePointer (tmp);
7696 break;
7697 case SK_ADR:
7698 tmp = sRef_fixBase (s->info->ref, base);
7699 ret = sRef_makeAddress (tmp);
7700 break;
7701 case SK_CONJ:
7702 {
7703 sRef tmpb;
7704
7705 tmp = sRef_fixBase (s->info->conj->a, base);
7706 tmpb = sRef_fixBase (s->info->conj->b, base);
7707
7708 ret = sRef_makeConj (tmp, tmpb);
7709 break;
7710 }
7711 BADDEFAULT;
7712 }
7713
7714 return ret;
7715}
7716
7717static /*@exposed@*/ sRef
7718sRef_fixDirectBase (sRef s, sRef base)
7719{
7720 sRef ret;
7721
7722
7723 if (sRef_isInvalid (s))
7724 {
28bf4b0b 7725 return sRef_undefined;
616915dd 7726 }
28bf4b0b 7727
616915dd 7728 switch (s->kind)
7729 {
7730 case SK_ARRAYFETCH:
7731 if (s->info->arrayfetch->indknown)
7732 {
7733 ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7734 }
7735 else
7736 {
7737 ret = sRef_makeArrayFetch (base);
7738 }
7739 break;
7740 case SK_FIELD:
7741 ret = sRef_buildNCField (base, s->info->field->field);
7742 break;
7743 case SK_PTR:
7744 ret = sRef_makePointer (base);
7745 break;
7746 case SK_ADR:
7747 ret = sRef_makeAddress (base);
7748 break;
7749 case SK_CONJ:
7750 {
7751 sRef tmpa, tmpb;
7752
7753 tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7754 tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7755
7756 ret = sRef_makeConj (tmpa, tmpb);
7757 break;
7758 }
7759 BADDEFAULT;
7760 }
7761
7762 sRef_copyState (ret, s);
7763 return ret;
7764}
7765
7766bool
7767sRef_isAllocIndexRef (sRef s)
7768{
7769 return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown)
7770 && sRef_isAllocated (s->info->arrayfetch->arr));
7771}
7772
7773void
7774sRef_showRefLost (sRef s)
7775{
7776 if (sRef_hasAliasInfoLoc (s))
7777 {
7778 llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
28bf4b0b 7779 sRef_getAliasInfoLoc (s));
616915dd 7780 }
7781}
7782
7783void
7784sRef_showRefKilled (sRef s)
7785{
16c024b5 7786 if (sRef_isValid (s))
616915dd 7787 {
16c024b5 7788 DPRINTF (("Killed: %s", sRef_unparseFull (s)));
7789 if (context_getLocIndentSpaces () == 0) {
7790 stateInfo_display (s->definfo, message (" Storage %q", sRef_unparseOpt (s)));
7791 } else {
7792 stateInfo_display (s->definfo, message ("Storage %q", sRef_unparseOpt (s)));
7793 }
616915dd 7794 }
7795}
7796
7797void
7798sRef_showStateInconsistent (sRef s)
7799{
7800 if (sRef_hasStateInfoLoc (s))
7801 {
7802 llgenindentmsg
7803 (message ("Storage %qbecomes inconsistent (released on one branch)",
7804 sRef_unparseOpt (s)),
7805 sRef_getStateInfoLoc (s));
7806 }
7807}
7808
7809void
7810sRef_showStateInfo (sRef s)
7811{
16c024b5 7812 if (sRef_isValid (s)) {
7813 if (context_getLocIndentSpaces () == 0) {
7814 stateInfo_display (s->definfo, message (" Storage %q", sRef_unparseOpt (s)));
7815 } else {
7816 stateInfo_display (s->definfo, message ("Storage %q", sRef_unparseOpt (s)));
616915dd 7817 }
16c024b5 7818 }
616915dd 7819}
7820
7821void
7822sRef_showExpInfo (sRef s)
7823{
16c024b5 7824 if (sRef_isValid (s)) {
7825 if (context_getLocIndentSpaces () == 0) {
7826 stateInfo_display (s->expinfo, message (" Storage %q", sRef_unparseOpt (s)));
7827 } else {
7828 stateInfo_display (s->expinfo, message ("Storage %q", sRef_unparseOpt (s)));
616915dd 7829 }
16c024b5 7830 }
616915dd 7831}
7832
28bf4b0b 7833void
7834sRef_showMetaStateInfo (sRef s, cstring key)
7835{
7836 stateValue val;
7837 metaStateInfo minfo = context_lookupMetaStateInfo (key);
7838
6483a926 7839 llassert (sRef_isReasonable (s));
28bf4b0b 7840 llassert (valueTable_isDefined (s->state));
7841 llassert (metaStateInfo_isDefined (minfo));
7842
7843 val = valueTable_lookup (s->state, key);
7844
7845 if (stateValue_hasLoc (val))
7846 {
7847 llgenindentmsg
0bf5022d 7848 (message ("%qbecomes %q", sRef_unparseOpt (s),
2c88d156 7849 stateValue_unparseValue (val, minfo)),
28bf4b0b 7850 stateValue_getLoc (val));
7851 }
7852}
7853
616915dd 7854void
7855sRef_showNullInfo (sRef s)
7856{
28bf4b0b 7857 DPRINTF (("Show null info: %s", sRef_unparseFull (s)));
7858
616915dd 7859 if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7860 {
28bf4b0b 7861 DPRINTF (("has null info: %s",
7862 fileloc_unparse (sRef_getNullInfoLoc (s))));
7863
7864 switch (sRef_getNullState (s))
616915dd 7865 {
7866 case NS_CONSTNULL:
7867 {
7868 fileloc loc = sRef_getNullInfoLoc (s);
7869
7870 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7871 {
7872 llgenindentmsg
7873 (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7874 loc);
7875 }
7876 break;
7877 }
7878 case NS_DEFNULL:
7879 {
7880 fileloc loc = sRef_getNullInfoLoc (s);
7881
7882 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7883 {
7884 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7885 loc);
7886 }
7887 break;
7888 }
7889 case NS_ABSNULL:
7890 case NS_POSNULL:
7891 llgenindentmsg
7892 (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7893 sRef_getNullInfoLoc (s));
7894 break;
7895 case NS_NOTNULL:
7896 case NS_MNOTNULL:
7897 llgenindentmsg
7898 (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7899 sRef_getNullInfoLoc (s));
7900 break;
7901 case NS_UNKNOWN:
7902 llgenindentmsg
7903 (message ("Storage %qnull state becomes unknown",
7904 sRef_unparseOpt (s)),
7905 sRef_getNullInfoLoc (s));
7906 break;
7907
7908 case NS_ERROR:
7909 BADBRANCHCONT;
7910 break;
7911
7912 default:
7913 llgenindentmsg
7914 (message ("<error case> Storage %q becomes %s",
7915 sRef_unparse (s),
28bf4b0b 7916 nstate_unparse (sRef_getNullState (s))),
616915dd 7917 sRef_getNullInfoLoc (s));
7918
7919 break;
7920 }
7921 }
7922}
7923
7924void
7925sRef_showAliasInfo (sRef s)
7926{
16c024b5 7927 if (sRef_isValid (s))
616915dd 7928 {
7929 if (sRef_isFresh (s))
7930 {
16c024b5 7931 if (context_getLocIndentSpaces () == 0) {
7932 stateInfo_display (s->aliasinfo, message (" Fresh storage %q", sRef_unparseOpt (s)));
7933 } else {
7934 stateInfo_display (s->aliasinfo, message ("Fresh storage %q", sRef_unparseOpt (s)));
7935 }
616915dd 7936 }
16c024b5 7937 else
616915dd 7938 {
16c024b5 7939 if (context_getLocIndentSpaces () == 0) {
7940 stateInfo_display (s->aliasinfo, message (" Storage %q", sRef_unparseOpt (s)));
7941 } else {
7942 stateInfo_display (s->aliasinfo, message ("Storage %q", sRef_unparseOpt (s)));
7943 }
616915dd 7944 }
7945 }
7946}
7947
7948void
7949sRef_mergeNullState (sRef s, nstate n)
7950{
6483a926 7951 if (sRef_isReasonable (s))
616915dd 7952 {
7953 nstate old;
7954
28bf4b0b 7955 old = sRef_getNullState (s);
616915dd 7956
7957 if (n != old && n != NS_UNKNOWN)
28bf4b0b 7958 {
b87215ab 7959 sRef_setNullState (s, n, g_currentloc);
616915dd 7960 }
7961 }
7962 else
7963 {
7964 llbuglit ("sRef_mergeNullState: invalid");
7965 }
7966}
7967
7968bool
7969sRef_possiblyNull (sRef s)
7970{
6483a926 7971 if (sRef_isReasonable (s))
b87215ab 7972 {
7973 if (sRef_getNullState (s) == NS_ABSNULL)
616915dd 7974 {
7975 ctype rct = ctype_realType (s->type);
b87215ab 7976
616915dd 7977 if (ctype_isAbstract (rct))
7978 {
7979 return FALSE;
7980 }
7981 else
7982 {
7983 if (ctype_isUser (rct))
7984 {
7985 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7986
7987 return (nstate_possiblyNull
7988 (sRef_getNullState (uentry_getSref (ue))));
7989 }
7990 else
7991 {
7992 return FALSE;
7993 }
7994 }
7995 }
7996 else
7997 {
28bf4b0b 7998 return nstate_possiblyNull (sRef_getNullState (s));
616915dd 7999 }
8000 }
b87215ab 8001
616915dd 8002 return FALSE;
8003}
8004
8005cstring
8006sRef_getScopeName (sRef s)
8007{
8008 sRef base = sRef_getRootBase (s);
8009
8010 if (sRef_isRealGlobal (base))
8011 {
8012 return (cstring_makeLiteralTemp ("Global"));
8013 }
8014 else if (sRef_isFileStatic (base))
8015 {
8016 return (cstring_makeLiteralTemp ("Static"));
8017 }
8018 else
8019 {
8020 return (cstring_makeLiteralTemp ("Local"));
8021 }
8022}
8023
8024cstring
8025sRef_unparseScope (sRef s)
8026{
8027 sRef base = sRef_getRootBase (s);
8028
8029 if (sRef_isRealGlobal (base))
8030 {
8031 return (cstring_makeLiteralTemp ("global"));
8032 }
8033 else if (sRef_isFileStatic (base))
8034 {
8035 return (cstring_makeLiteralTemp ("file static"));
8036 }
8037 else
8038 {
8039 BADEXIT;
8040 }
8041}
8042
8043int
8044sRef_getScope (sRef s)
8045{
6483a926 8046 llassert (sRef_isReasonable (s));
616915dd 8047
8048 if (sRef_isCvar (s))
8049 {
8050 return s->info->cvar->lexlevel;
8051 }
8052 else if (sRef_isParam (s))
8053 {
8054 return paramsScope;
8055 }
8056 else
8057 {
8058 return fileScope;
8059 }
8060}
8061
8062bool
8063sRef_isDead (sRef s)
8064{
6483a926 8065 return (sRef_isReasonable (s) && (s)->defstate == SS_DEAD);
616915dd 8066}
8067
8068bool
8069sRef_isDeadStorage (sRef s)
8070{
6483a926 8071 if (sRef_isReasonable (s))
616915dd 8072 {
8073 if (s->defstate == SS_DEAD
8074 || s->defstate == SS_UNUSEABLE
8075 || s->defstate == SS_UNDEFINED
8076 || s->defstate == SS_UNKNOWN)
8077 {
8078 return TRUE;
8079 }
8080 else
8081 {
8082 return (sRef_isDefinitelyNull (s));
8083 }
8084 }
8085 else
8086 {
8087 return FALSE;
8088 }
8089}
8090
8091bool
8092sRef_isPossiblyDead (sRef s)
8093{
6483a926 8094 return (sRef_isReasonable (s) && s->defstate == SS_HOFFA);
616915dd 8095}
8096
8097bool sRef_isStateLive (sRef s)
8098{
6483a926 8099 if (sRef_isReasonable (s))
616915dd 8100 {
8101 sstate ds = s->defstate;
8102
8103 return (!(ds == SS_UNDEFINED
8104 || ds == SS_DEAD
8105 || ds == SS_UNUSEABLE
8106 || ds == SS_HOFFA));
8107 }
8108 else
8109 {
8110 return FALSE;
8111 }
8112}
8113
8114
8115bool sRef_isStateUndefined (sRef s)
8116{
6483a926 8117 return ((sRef_isReasonable(s)) && ((s)->defstate == SS_UNDEFINED));
616915dd 8118}
8119
8120bool sRef_isJustAllocated (sRef s)
8121{
8122 if (sRef_isAllocated (s))
8123 {
8124 sRefSet_allElements (s->deriv, el)
8125 {
8126 if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
8127 {
8128 return FALSE;
8129 }
8130 } end_sRefSet_allElements ;
8131
8132 return TRUE;
8133 }
8134
8135 return FALSE;
8136}
8137
8138static bool
8139sRef_isAllocatedStorage (sRef s)
8140{
6483a926 8141 if (sRef_isReasonable (s) && ynm_toBoolStrict (sRef_isValidLvalue (s)))
616915dd 8142 {
8143 return (ctype_isVisiblySharable (sRef_getType (s)));
8144 }
8145 else
8146 {
8147 return FALSE;
8148 }
8149}
8150
8151bool
8152sRef_isUnuseable (sRef s)
8153{
8154 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
8155}
8156
8157bool
8158sRef_perhapsNull (sRef s)
8159{
6483a926 8160 if (sRef_isReasonable (s))
616915dd 8161 {
28bf4b0b 8162 if (sRef_getNullState (s) == NS_ABSNULL)
616915dd 8163 {
8164 ctype rct = ctype_realType (s->type);
8165
8166 if (ctype_isAbstract (rct))
8167 {
8168 return FALSE;
8169 }
8170 else
8171 {
8172 if (ctype_isUser (rct))
8173 {
8174 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
8175
8176 return (nstate_perhapsNull
8177 (sRef_getNullState (uentry_getSref (ue))));
8178 }
8179 else
8180 {
8181 return FALSE;
8182 }
8183 }
8184 }
8185 else
8186 {
28bf4b0b 8187 return nstate_perhapsNull (sRef_getNullState (s));
616915dd 8188 }
8189 }
8190
8191 return FALSE;
8192}
8193
8194/*
8195** definitelyNull --- called when TRUE is good
8196*/
8197
8198bool
8199sRef_definitelyNull (sRef s)
8200{
6483a926 8201 return (sRef_isReasonable (s)
28bf4b0b 8202 && (sRef_getNullState (s) == NS_DEFNULL || sRef_getNullState (s) == NS_CONSTNULL));
616915dd 8203}
8204
8205/*
8206** based on sRef_similar
8207*/
8208
8209void
8210sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
8211{
6483a926 8212 if (sRef_isReasonable (set))
616915dd 8213 {
8214 sRef deriv = sRef_getDeriv (set, guide);
8215
6483a926 8216 if (sRef_isReasonable (deriv))
616915dd 8217 {
28bf4b0b 8218 sRef_setNullStateN (deriv, ns);
616915dd 8219 }
8220 }
8221}
8222
8223static /*@exposed@*/ sRef
8224sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
8225{
6483a926 8226 llassert (sRef_isReasonable (set));
8227 llassert (sRef_isReasonable (guide));
616915dd 8228
8229 switch (guide->kind)
8230 {
8231 case SK_CVAR:
6483a926 8232 llassert (set->kind == SK_CVAR);
616915dd 8233 return set;
8234
8235 case SK_PARAM:
8236 llassert (set->kind == guide->kind);
8237 llassert (set->info->paramno == guide->info->paramno);
616915dd 8238 return set;
8239
8240 case SK_ARRAYFETCH:
8241
8242 if (set->kind == SK_ARRAYFETCH
8243 && (sRef_similar (set->info->arrayfetch->arr,
8244 guide->info->arrayfetch->arr)))
8245 {
8246 return set;
8247 }
8248 else
8249 {
8250 return (sRef_makeAnyArrayFetch
8251 (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
8252 }
8253
8254 case SK_PTR:
8255
8256 if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
8257 {
8258 return set;
8259 }
8260 else
8261 {
8262 return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
8263 }
8264
8265 case SK_FIELD:
8266
8267 if ((set->kind == SK_FIELD &&
8268 (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
8269 cstring_equal (set->info->field->field, guide->info->field->field))))
8270 {
8271 return set;
8272 }
8273 else
8274 {
8275 return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
8276 guide->info->field->field));
8277 }
8278 case SK_ADR:
8279
8280 if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
8281 {
8282 return set;
8283 }
8284 else
8285 {
8286 return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
8287 }
8288
8289 case SK_CONJ:
8290
8291 return sRef_undefined;
8292
8293 case SK_RESULT:
8294 case SK_SPECIAL:
8295 case SK_UNCONSTRAINED:
8296 case SK_TYPE:
8297 case SK_CONST:
8298 case SK_NEW:
8299 case SK_UNKNOWN:
8300 case SK_OBJECT:
8301 case SK_DERIVED:
8302 case SK_EXTERNAL:
8303 return sRef_undefined;
8304 }
8305
8306 BADEXIT;
8307}
8308
8309/*
8310** sRef_aliasCheckPred
8311**
8312** A confusing but spiffy function:
8313**
8314** Calls predf (s, e, text, <alias>) on s and all of s's aliases
8315** (unless checkAliases (s) is FALSE).
8316**
8317** For alias calls, calls as
8318** predf (alias, e, text, s)
8319*/
8320
8321void
8322sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
8323 /*@null@*/ bool (checkAliases) (sRef),
8324 sRef s, exprNode e, exprNode err)
8325{
8326 bool error = (*predf)(s, e, sRef_undefined, err);
8327
8328
8329 if (checkAliases != NULL && !(checkAliases (s)))
8330 {
8331 /* don't check aliases */
8332 }
8333 else
8334 {
8335 sRefSet aliases = usymtab_allAliases (s);
616915dd 8336
8337 sRefSet_realElements (aliases, current)
8338 {
6483a926 8339 if (sRef_isReasonable (current))
616915dd 8340 {
6483a926 8341 if (sRef_isReasonable (current))
616915dd 8342 {
6483a926 8343 if (!sRef_similar (current, s)
8344 || (error && sRef_sameName (current, s)))
8345 {
8346 (void) (*predf)(current, e, s, err);
8347 }
616915dd 8348 }
6483a926 8349 else
8350 {
8351 llcontbug (message ("Invalid sRef as alias field of %s", sRef_unparse (s)));
8352 }
8353 }
616915dd 8354 } end_sRefSet_realElements;
8355
8356 sRefSet_free (aliases);
8357 }
8358}
8359
8360/*
8361** return TRUE iff predf (s) is true for s or any alias of s
8362*/
8363
8364bool
8365sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
8366{
8367
8368 if ((*predf)(s))
8369 {
8370 return TRUE;
8371 }
8372 else
8373 {
8374 sRefSet aliases;
8375
8376 aliases = usymtab_allAliases (s);
8377
8378 sRefSet_realElements (aliases, current)
8379 {
6483a926 8380 if (sRef_isReasonable (current))
616915dd 8381 {
8382 sRef cref = sRef_updateSref (current);
8383
8384 /* Whoa! a very kludgey way to make sure the right sref is used
8385 ** where there is a conditional symbol table. I am beginning
8386 ** to think that having a conditional symbol table wasn't such
8387 ** a great idea. ;(
8388 */
8389
616915dd 8390 if ((*predf)(cref))
8391 {
28bf4b0b 8392 DPRINTF (("Checking alias: %s", sRef_unparseFull (cref)));
616915dd 8393 sRefSet_free (aliases);
8394 return TRUE;
8395 }
8396 }
8397 } end_sRefSet_realElements;
8398
8399 sRefSet_free (aliases);
8400 }
8401 return FALSE;
8402}
8403
8404bool
8405sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
8406{
8407 sRefSet aliases;
8408 bool result = FALSE;
8409
8410
8411 aliases = usymtab_allAliases (s);
8412
8413 if ((*predf)(s)) result = TRUE;
8414
8415
8416 sRefSet_realElements (aliases, current)
8417 {
6483a926 8418 if (sRef_isReasonable (current))
616915dd 8419 {
28bf4b0b 8420 current = sRef_updateSref (current);
8421 if ((*predf)(current)) result = TRUE;
616915dd 8422 }
8423 } end_sRefSet_realElements;
8424
8425 sRefSet_free (aliases);
8426 return result;
8427}
8428
1d239d69 8429void
616915dd 8430sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8431{
8432 sRefSet aliases;
8433
8434 aliases = usymtab_allAliases (s);
8435
909cf5eb 8436 DPRINTF (("All aliases: %s --> %s", sRef_unparseFull (s), sRefSet_unparseFull (aliases)));
28bf4b0b 8437
616915dd 8438 (*predf)(s, loc);
8439
8440 sRefSet_realElements (aliases, current)
8441 {
6483a926 8442 if (sRef_isReasonable (current))
616915dd 8443 {
909cf5eb 8444 DPRINTF (("Update: %s", sRef_unparseFull (current)));
616915dd 8445 current = sRef_updateSref (current);
909cf5eb 8446 DPRINTF (("Updated ==> %s", sRef_unparseFull (current)));
28bf4b0b 8447 ((*predf)(current, loc));
393e573f 8448 DPRINTF (("Killed: %s", sRef_unparseFull (current)));
616915dd 8449 }
8450 } end_sRefSet_realElements;
8451
8452 sRefSet_free (aliases);
8453}
8454
1d239d69 8455void
8456sRef_aliasSetCompleteParam (void (predf) (sRef, int, fileloc), sRef s,
8457 int kind, fileloc loc)
616915dd 8458{
8459 sRefSet aliases;
68de3f33 8460
8461 if (sRef_isDeep (s))
8462 {
8463 aliases = usymtab_allAliases (s);
8464 }
8465 else
8466 {
8467 aliases = usymtab_aliasedBy (s);
8468 }
616915dd 8469
68de3f33 8470 (*predf)(s, kind, loc);
8471
8472 sRefSet_realElements (aliases, current)
8473 {
6483a926 8474 if (sRef_isReasonable (current))
68de3f33 8475 {
8476 current = sRef_updateSref (current);
8477 ((*predf)(current, kind, loc));
8478 }
8479 } end_sRefSet_realElements;
8480
8481 sRefSet_free (aliases);
8482}
8483
8484/*
8485** Version of aliasSetCompleteParam for alkind parameters
8486*/
8487
8488void
8489sRef_aliasSetCompleteAlkParam (void (predf) (sRef, alkind, fileloc), sRef s,
8490 alkind kind, fileloc loc)
8491{
8492 sRefSet aliases;
616915dd 8493
8494 if (sRef_isDeep (s))
8495 {
8496 aliases = usymtab_allAliases (s);
8497 }
8498 else
8499 {
8500 aliases = usymtab_aliasedBy (s);
8501 }
8502
8503 (*predf)(s, kind, loc);
8504
8505 sRefSet_realElements (aliases, current)
8506 {
6483a926 8507 if (sRef_isReasonable (current))
616915dd 8508 {
8509 current = sRef_updateSref (current);
28bf4b0b 8510 ((*predf)(current, kind, loc));
616915dd 8511 }
8512 } end_sRefSet_realElements;
8513
8514 sRefSet_free (aliases);
8515}
8516
8517static void
8518sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8519{
8520 sRef inner;
8521 sRefSet aliases;
8522 ctype ct;
8523
6483a926 8524 if (!sRef_isReasonable (s)) return;
616915dd 8525
616915dd 8526 /*
8527 ** Type equivalence checking is necessary --- there might be casting.
8528 */
8529
8530 (*predf)(s, loc);
8531
8532 switch (s->kind)
8533 {
8534 case SK_UNCONSTRAINED:
8535 case SK_CVAR:
8536 case SK_PARAM:
8537 break;
8538 case SK_PTR:
8539 inner = s->info->ref;
8540 aliases = usymtab_allAliases (inner);
8541 ct = sRef_getType (inner);
616915dd 8542
8543 sRefSet_realElements (aliases, current)
8544 {
6483a926 8545 if (sRef_isReasonable (current))
616915dd 8546 {
8547 current = sRef_updateSref (current);
8548
8549 if (ctype_equal (ct, sRef_getType (current)))
8550 {
8551 sRef ptr = sRef_makePointer (current);
616915dd 8552 ((*predf)(ptr, loc));
8553 }
8554 }
8555 } end_sRefSet_realElements;
8556
8557 sRefSet_free (aliases);
8558 break;
8559 case SK_ARRAYFETCH:
8560 inner = s->info->arrayfetch->arr;
8561 aliases = usymtab_allAliases (inner);
8562 ct = sRef_getType (inner);
8563
3120b462 8564 DPRINTF (("Array fetch: %s", sRefSet_unparse (aliases)));
8565
616915dd 8566 sRefSet_realElements (aliases, current)
8567 {
6483a926 8568 if (sRef_isReasonable (current))
616915dd 8569 {
8570 current = sRef_updateSref (current);
3120b462 8571 DPRINTF (("Current: %s", sRef_unparseFull (current)));
8572
616915dd 8573 if (ctype_equal (ct, sRef_getType (current)))
8574 {
616915dd 8575 if (s->info->arrayfetch->indknown)
8576 {
8577 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
3120b462 8578 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
1d239d69 8579 /* evans 2001-08-27 This isn't true:
8580 llassert (af->info->arrayfetch->arr == current);
8581 see comments in buildArrayFetchKnown
8582 */
616915dd 8583 ((*predf)(af, loc));
8584 }
8585 else
8586 {
8587 sRef af = sRef_makeArrayFetch (current);
1d239d69 8588 /* evans 2001-08-27 This isn't true:
8589 llassert (af->info->arrayfetch->arr == current);
8590 see comments in buildArrayFetch
8591 */
3120b462 8592 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
616915dd 8593 ((*predf)(af, loc));
8594 }
8595 }
3120b462 8596 else
8597 {
8598 DPRINTF (("Type mismatch: %s / %s",
8599 ctype_unparse (ct),
8600 ctype_unparse (sRef_getType (current))));
8601 }
616915dd 8602 }
8603 } end_sRefSet_realElements;
8604
8605 sRefSet_free (aliases);
8606 break;
8607 case SK_FIELD:
8608 inner = s->info->field->rec;
8609 aliases = usymtab_allAliases (inner);
8610 ct = sRef_getType (inner);
616915dd 8611
8612 sRefSet_realElements (aliases, current)
8613 {
6483a926 8614 if (sRef_isReasonable (current))
616915dd 8615 {
8616 current = sRef_updateSref (current);
8617
8618 if (ctype_equal (ct, sRef_getType (current)))
8619 {
8620 sRef f = sRef_makeField (current, s->info->field->field);
8621
8622 ((*predf)(f, loc));
8623 }
8624 }
8625 } end_sRefSet_realElements;
8626
8627 sRefSet_free (aliases);
8628 break;
8629 case SK_CONJ:
8630 sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
8631 sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
8632 break;
8633 case SK_SPECIAL:
8634 case SK_ADR:
8635 case SK_TYPE:
8636 case SK_CONST:
8637 case SK_NEW:
8638 case SK_UNKNOWN:
8639 case SK_OBJECT:
8640 case SK_DERIVED:
8641 case SK_EXTERNAL:
8642 case SK_RESULT:
8643 break;
8644 }
8645}
8646
8647static void
8648sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
8649{
8650 sRef inner;
8651 sRefSet aliases;
8652 ctype ct;
8653
6483a926 8654 if (!sRef_isReasonable (s)) return;
616915dd 8655
616915dd 8656 /*
8657 ** Type equivalence checking is necessary --- there might be casting.
8658 */
8659
8660 (*predf)(s, t);
8661
8662 switch (s->kind)
8663 {
8664 case SK_UNCONSTRAINED:
8665 case SK_CVAR:
8666 case SK_PARAM:
8667 break;
8668 case SK_PTR:
8669 inner = s->info->ref;
8670 aliases = usymtab_allAliases (inner);
8671 ct = sRef_getType (inner);
2e127cb8 8672
616915dd 8673 sRefSet_realElements (aliases, current)
8674 {
6483a926 8675 if (sRef_isReasonable (current))
616915dd 8676 {
8677 current = sRef_updateSref (current);
8678
8679 if (ctype_equal (ct, sRef_getType (current)))
8680 {
8681 sRef ptr = sRef_makePointer (current);
8682
8683 ((*predf)(ptr, t));
8684 }
8685 }
8686 } end_sRefSet_realElements;
8687
8688 sRefSet_free (aliases);
8689 break;
8690 case SK_ARRAYFETCH:
8691 inner = s->info->arrayfetch->arr;
8692 aliases = usymtab_allAliases (inner);
8693 ct = sRef_getType (inner);
8694
8695 sRefSet_realElements (aliases, current)
8696 {
6483a926 8697 if (sRef_isReasonable (current))
616915dd 8698 {
8699 current = sRef_updateSref (current);
8700
8701 if (ctype_equal (ct, sRef_getType (current)))
8702 {
8703
8704 if (s->info->arrayfetch->indknown)
8705 {
8706 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8707
8708 ((*predf)(af, t));
8709 }
8710 else
8711 {
8712 sRef af = sRef_makeArrayFetch (current);
8713
8714 ((*predf)(af, t));
8715 }
8716 }
8717 }
8718 } end_sRefSet_realElements;
8719
8720 sRefSet_free (aliases);
8721 break;
8722 case SK_FIELD:
8723 inner = s->info->field->rec;
8724 aliases = usymtab_allAliases (inner);
8725 ct = sRef_getType (inner);
8726
8727
8728 sRefSet_realElements (aliases, current)
8729 {
6483a926 8730 if (sRef_isReasonable (current))
616915dd 8731 {
8732 current = sRef_updateSref (current);
8733
8734 if (ctype_equal (ct, sRef_getType (current)))
8735 {
8736 sRef f = sRef_makeField (current, s->info->field->field);
8737
8738 ((*predf)(f, t));
8739 }
8740 }
8741 } end_sRefSet_realElements;
8742
8743 sRefSet_free (aliases);
8744 break;
8745 case SK_CONJ:
8746 sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8747 sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8748 break;
8749 case SK_SPECIAL:
8750 case SK_ADR:
8751 case SK_TYPE:
8752 case SK_CONST:
8753 case SK_NEW:
8754 case SK_UNKNOWN:
8755 case SK_OBJECT:
8756 case SK_DERIVED:
8757 case SK_EXTERNAL:
8758 case SK_RESULT:
8759 break;
8760 }
8761}
8762
8763static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8764{
8765 exkind a1 = sRef_getExKind (res);
8766 exkind a2 = sRef_getExKind (other);
8767
8768 if (a1 == a2 || a2 == XO_UNKNOWN)
8769 {
8770 ;
8771 }
8772 else if (a1 == XO_UNKNOWN)
8773 {
28bf4b0b 8774 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
616915dd 8775 res->expkind = a2;
8776 }
8777 else
8778 {
8779 res->expkind = XO_OBSERVER;
8780 }
8781}
8782
8783/*
8784** Currently, this is a very ad hoc implementation, with lots of fixes to
8785** make real code work okay. I need to come up with some more general
8786** rules or principles here.
8787*/
8788
8789static void
8790 sRef_combineAliasKindsError (/*@notnull@*/ sRef res,
8791 /*@notnull@*/ sRef other,
8792 clause cl, fileloc loc)
8793{
8794 bool hasError = FALSE;
8795 alkind ares = sRef_getAliasKind (res);
8796 alkind aother = sRef_getAliasKind (other);
8797
28bf4b0b 8798 sRef_checkMutable (res);
8799
616915dd 8800 if (alkind_isDependent (ares))
8801 {
8802 if (aother == AK_KEPT)
8803 {
28bf4b0b 8804 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 8805 res->aliaskind = AK_KEPT;
8806 }
8807 else
8808 {
8809 if (aother == AK_LOCAL || aother == AK_STATIC
8810 || alkind_isTemp (aother))
8811 {
28bf4b0b 8812 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
616915dd 8813 res->aliaskind = AK_DEPENDENT;
8814 }
8815 }
8816 }
8817 else if (alkind_isDependent (aother))
8818 {
8819 if (ares == AK_KEPT)
8820 {
8821 res->aliaskind = AK_KEPT;
8822 }
8823 else
8824 {
8825 if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8826 {
28bf4b0b 8827 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8828 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 8829 res->aliaskind = AK_DEPENDENT;
8830 }
8831 }
8832 }
8833 else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8834 || ares == AK_STATIC || alkind_isTemp (ares))
8835 && sRef_isFresh (other))
8836 {
8837 /*
8838 ** cases like: if (s == NULL) s = malloc...;
8839 ** don't generate errors
8840 */
8841
28bf4b0b 8842 if (usymtab_isAltDefinitelyNullDeep (res))
616915dd 8843 {
8844 res->aliaskind = ares;
8845 }
8846 else
8847 {
8848 hasError = TRUE;
8849 }
8850 }
8851 else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8852 || aother == AK_STATIC || alkind_isTemp (aother))
8853 && sRef_isFresh (res))
8854 {
8855 /*
8856 ** cases like: if (s == NULL) s = malloc...;
8857 ** don't generate errors
8858 */
8859
28bf4b0b 8860 if (usymtab_isDefinitelyNullDeep (other))
616915dd 8861 {
28bf4b0b 8862 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 8863 res->aliaskind = aother;
8864 }
8865 else
8866 {
8867 hasError = TRUE;
8868 }
8869 }
8870 else if (ares == AK_NEWREF && aother == AK_REFCOUNTED
8871 && sRef_isConst (other))
8872 {
8873 res->aliaskind = AK_NEWREF;
8874 }
8875 else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8876 && sRef_isConst (res))
8877 {
28bf4b0b 8878 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 8879 res->aliaskind = AK_NEWREF;
8880 }
8881 else if (sRef_isLocalVar (res)
8882 && ((ares == AK_KEPT && aother == AK_LOCAL)
8883 || (aother == AK_KEPT && ares == AK_LOCAL)))
8884 {
8885 res->aliaskind = AK_KEPT;
8886 }
6fcd0b1e 8887 else if ((ares == AK_OWNED && aother == AK_ONLY)
8888 || (aother == AK_OWNED && ares == AK_ONLY))
8889 {
8890 res->aliaskind = AK_OWNED;
8891
8892 if (aother == AK_OWNED)
8893 {
8894 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8895 }
8896 }
616915dd 8897 else
8898 {
8899 hasError = TRUE;
8900 }
8901
8902 if (hasError)
8903 {
8904 if (sRef_isThroughArrayFetch (res))
8905 {
8906 if (optgenerror2
8907 (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8908 message
8909 ("Clauses exit with %q possibly referencing %s storage %s, "
8910 "%s storage %s",
8911 sRef_unparse (res),
8912 alkind_unparse (aother),
8913 clause_nameTaken (cl),
8914 alkind_unparse (ares),
8915 clause_nameAlternate (cl)),
8916 loc))
8917 {
8918 sRef_showAliasInfo (res);
8919 sRef_showAliasInfo (other);
8920 res->aliaskind = AK_ERROR;
8921 }
8922 else
8923 {
8924 if (ares == AK_KEPT || aother == AK_KEPT)
8925 {
8926 sRef_maybeKill (res, loc);
28bf4b0b 8927 }
616915dd 8928 }
8929 }
8930 else
8931 {
8932 if (optgenerror
8933 (FLG_BRANCHSTATE,
8934 message ("Clauses exit with %q referencing %s storage %s, "
8935 "%s storage %s",
8936 sRef_unparse (res),
8937 alkind_unparse (aother),
8938 clause_nameTaken (cl),
8939 alkind_unparse (ares),
8940 clause_nameAlternate (cl)),
8941 loc))
8942 {
8943 sRef_showAliasInfo (res);
8944 sRef_showAliasInfo (other);
8945
8946 res->aliaskind = AK_ERROR;
8947 }
8948 }
8949
8950 res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8951 }
8952}
8953
8954static void
8955 sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
8956 clause cl, fileloc loc)
8957{
8958 alkind ares = sRef_getAliasKind (res);
8959 alkind aother = sRef_getAliasKind (other);
8960
28bf4b0b 8961 sRef_checkMutable (res);
8962
60868d40 8963 DPRINTF (("Combine alias kinds: \n\t%s / \n\t%s",
8964 sRef_unparseFull (res), sRef_unparseFull (other)));
616915dd 8965 if (alkind_equal (ares, aother)
8966 || aother == AK_UNKNOWN
8967 || aother == AK_ERROR)
8968 {
8969 ; /* keep current state */
8970 }
8971 else if (sRef_isDead (res) || sRef_isDead (other))
8972 {
8973 /* dead error reported (or storage is dead) */
8974 res ->aliaskind = AK_ERROR;
8975 }
8976 else if (ares == AK_UNKNOWN || ares == AK_ERROR
60868d40 8977 || sRef_isStateUndefined (res)
8978 || sRef_isDefinitelyNull (res))
616915dd 8979 {
28bf4b0b 8980 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 8981 res->aliaskind = aother;
8982 }
60868d40 8983 else if (sRef_isStateUndefined (other)
8984 || sRef_isDefinitelyNull (other))
616915dd 8985 {
8986 ;
8987 }
8988 else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8989 && aother == AK_LOCAL)
8990 || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8991 && ares == AK_LOCAL))
8992 {
8993 if (ares != AK_LOCAL)
8994 {
28bf4b0b 8995 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 8996 }
8997
8998 res->aliaskind = AK_LOCAL;
8999 }
9000 else if ((ares == AK_OWNED && aother == AK_FRESH)
9001 || (aother == AK_OWNED && ares == AK_FRESH))
9002 {
9003 if (ares != AK_FRESH)
9004 {
28bf4b0b 9005 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 9006 }
9007
9008 res->aliaskind = AK_FRESH;
9009 }
9010 else if ((ares == AK_KEEP && aother == AK_FRESH) ||
9011 (aother == AK_KEEP && ares == AK_FRESH))
9012 {
9013 if (ares != AK_KEEP)
9014 {
28bf4b0b 9015 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 9016 }
9017
9018 res->aliaskind = AK_KEEP;
9019 }
9020 else if ((ares == AK_LOCAL && aother == AK_STACK) ||
9021 (aother == AK_LOCAL && ares == AK_STACK))
9022 {
9023 if (ares != AK_STACK)
9024 {
28bf4b0b 9025 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 9026 }
9027
9028 res->aliaskind = AK_STACK;
9029 }
9030 else if ((ares == AK_LOCAL
9031 && (aother == AK_OWNED && sRef_isLocalVar (other)))
9032 || (aother == AK_LOCAL
9033 && (ares == AK_OWNED && sRef_isLocalVar (res))))
9034 {
9035 if (ares != AK_LOCAL)
9036 {
28bf4b0b 9037 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 9038 }
9039
9040 res->aliaskind = AK_LOCAL;
9041 }
9042 else if ((ares == AK_FRESH && alkind_isOnly (aother))
9043 || (aother == AK_FRESH && alkind_isOnly (ares)))
9044 {
9045 res->aliaskind = AK_FRESH;
9046 }
9047 else if ((aother == AK_FRESH && sRef_definitelyNull (res))
9048 || (ares == AK_FRESH && sRef_definitelyNull (other)))
9049 {
9050 if (ares != AK_FRESH)
9051 {
28bf4b0b 9052 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 9053 res->aliaskind = AK_FRESH;
9054 }
9055 }
9056 else if ((sRef_isFresh (res) && sRef_isConst (other))
9057 || (sRef_isFresh (other) && sRef_isConst (res)))
9058 {
9059 /*
9060 ** for NULL constantants
9061 ** this is bogus!
9062 */
9063
9064 if (!sRef_isFresh (res))
9065 {
28bf4b0b 9066 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 9067 }
9068
9069 res->aliaskind = AK_FRESH;
9070 }
9071 else if ((alkind_isStatic (aother) && sRef_isConst (res))
9072 || (alkind_isStatic (ares) && sRef_isConst (other)))
9073 {
9074 if (!alkind_isStatic (ares))
9075 {
28bf4b0b 9076 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 9077 res->aliaskind = AK_STATIC;
9078 }
9079 }
9080 else
9081 {
9082 sRef_combineAliasKindsError (res, other, cl, loc);
9083 }
9084}
9085
9086static void sRef_combineDefState (/*@notnull@*/ sRef res,
9087 /*@notnull@*/ sRef other)
9088{
9089 sstate s1 = res->defstate;
9090 sstate s2 = other->defstate;
9091 bool flip = FALSE;
9092
28bf4b0b 9093 sRef_checkMutable (res);
9094
616915dd 9095 if (s1 == s2 || s2 == SS_UNKNOWN)
9096 {
9097 ;
9098 }
9099 else if (s1 == SS_UNKNOWN)
9100 {
9101 flip = TRUE;
9102 }
9103 else
9104 {
9105 switch (s1)
9106 {
9107 case SS_FIXED:
9108 if (s2 == SS_DEFINED)
9109 {
9110 break;
9111 }
9112 else
9113 {
9114 llcontbuglit ("ssfixed: not implemented");
9115 flip = TRUE;
9116 }
9117 break;
9118 case SS_DEFINED:
9119 flip = TRUE;
9120 break;
9121 case SS_PDEFINED:
9122 case SS_ALLOCATED:
9123 flip = (s2 != SS_DEFINED);
9124 break;
9125 case SS_HOFFA:
9126 case SS_RELDEF:
9127 case SS_UNUSEABLE:
9128 case SS_UNDEFINED:
9129 case SS_PARTIAL:
9130 case SS_UNDEFGLOB:
9131 case SS_KILLED:
9132 case SS_DEAD:
9133 case SS_SPECIAL:
9134 break;
9135 BADDEFAULT;
9136 }
9137 }
9138
9139 if (flip)
9140 {
28bf4b0b 9141 res->definfo = stateInfo_update (res->definfo, other->definfo);
616915dd 9142 res->defstate = s2;
9143 }
9144}
9145
9146extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
9147{
9148 sRef ret;
9149 llassert (sRef_isConj (s));
9150
9151 ret = s->info->conj->a;
9152 llassert (ret != NULL);
9153 return ret;
9154}
9155
9156extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
9157{
9158 sRef ret;
9159 llassert (sRef_isConj (s));
9160
9161 ret = s->info->conj->b;
9162 llassert (ret != NULL);
9163 return ret;
9164}
9165
9166extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
9167{
9168 sRef p;
9169 sRef ret;
28bf4b0b 9170
9171 p = sRef_makePointer (s);
616915dd 9172 ret = sRef_makeField (p, f);
68de3f33 9173 DPRINTF (("Arrow: %s => %s",
9174 sRef_unparseFull (s), sRef_unparseFull (ret)));
28bf4b0b 9175 return ret;
616915dd 9176}
9177
9178extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
9179{
9180 sRef p;
9181 sRef ret;
9182
9183 p = sRef_buildPointer (s);
9184 ret = sRef_buildField (p, f);
9185
9186 return ret;
9187}
9188
9189static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
9190{
9191 sinfo ret;
9192
9193 switch (s->kind)
9194 {
9195 case SK_CVAR:
9196 ret = (sinfo) dmalloc (sizeof (*ret));
9197 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9198 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9199 ret->cvar->index = s->info->cvar->index;
9200 break;
9201
9202 case SK_PARAM:
9203 ret = (sinfo) dmalloc (sizeof (*ret));
9204 ret->paramno = s->info->paramno;
28bf4b0b 9205 llassert (ret->paramno >= -1);
616915dd 9206 break;
9207
9208 case SK_ARRAYFETCH:
9209 ret = (sinfo) dmalloc (sizeof (*ret));
9210 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9211 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9212 ret->arrayfetch->ind = s->info->arrayfetch->ind;
b73d1009 9213 ret->arrayfetch->arr = s->info->arrayfetch->arr;
616915dd 9214 break;
9215
9216 case SK_FIELD:
9217 ret = (sinfo) dmalloc (sizeof (*ret));
9218 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
b73d1009 9219 ret->field->rec = s->info->field->rec;
616915dd 9220 ret->field->field = s->info->field->field;
9221 break;
9222
9223 case SK_OBJECT:
9224 ret = (sinfo) dmalloc (sizeof (*ret));
9225 ret->object = s->info->object;
9226 break;
9227
9228 case SK_PTR:
9229 case SK_ADR:
9230 case SK_DERIVED:
9231 case SK_EXTERNAL:
9232 ret = (sinfo) dmalloc (sizeof (*ret));
28bf4b0b 9233 ret->ref = s->info->ref; /* Ref_copy (s->info->ref); */
616915dd 9234 break;
9235
9236 case SK_CONJ:
9237 ret = (sinfo) dmalloc (sizeof (*ret));
9238 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
28bf4b0b 9239 ret->conj->a = s->info->conj->a; /* sRef_copy (s->info->conj->a); */
9240 ret->conj->b = s->info->conj->b; /* sRef_copy (s->info->conj->b);*/
616915dd 9241 break;
9242 case SK_SPECIAL:
9243 ret = (sinfo) dmalloc (sizeof (*ret));
9244 ret->spec = s->info->spec;
9245 break;
6fcd0b1e 9246
616915dd 9247 case SK_UNCONSTRAINED:
9248 case SK_NEW:
9249 ret = (sinfo) dmalloc (sizeof (*ret));
9250 ret->fname = s->info->fname;
9251 break;
6fcd0b1e 9252
616915dd 9253 case SK_RESULT:
9254 case SK_CONST:
9255 case SK_TYPE:
9256 case SK_UNKNOWN:
9257 llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
9258 ret = NULL;
9259 break;
9260 }
9261
9262 return ret;
9263}
9264
9265static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
9266{
9267 sinfo ret;
9268
9269 /*
9270 ** Since its a full copy, only storage is assigned
9271 ** to dependent fields.
9272 */
9273 /*@-onlytrans@*/
9274
9275 switch (s->kind)
9276 {
9277 case SK_CVAR:
9278 ret = (sinfo) dmalloc (sizeof (*ret));
9279 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9280 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9281 ret->cvar->index = s->info->cvar->index;
9282 break;
9283
9284 case SK_PARAM:
9285 ret = (sinfo) dmalloc (sizeof (*ret));
9286 ret->paramno = s->info->paramno;
28bf4b0b 9287 llassert (ret->paramno >= -1);
616915dd 9288 break;
9289
9290 case SK_ARRAYFETCH:
9291 ret = (sinfo) dmalloc (sizeof (*ret));
9292 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9293 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9294 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9295 ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
9296 break;
9297
9298 case SK_FIELD:
9299 ret = (sinfo) dmalloc (sizeof (*ret));
9300 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9301 ret->field->rec = sRef_saveCopy (s->info->field->rec);
9302 ret->field->field = s->info->field->field;
9303 break;
9304
9305 case SK_OBJECT:
9306 ret = (sinfo) dmalloc (sizeof (*ret));
9307 ret->object = s->info->object;
9308 break;
9309
9310 case SK_PTR:
9311 case SK_ADR:
9312 case SK_DERIVED:
9313 case SK_EXTERNAL:
9314 ret = (sinfo) dmalloc (sizeof (*ret));
9315 ret->ref = sRef_saveCopy (s->info->ref);
9316 break;
9317
9318 case SK_CONJ:
9319 ret = (sinfo) dmalloc (sizeof (*ret));
9320 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9321 ret->conj->a = sRef_saveCopy (s->info->conj->a);
9322 ret->conj->b = sRef_saveCopy (s->info->conj->b);
9323 break;
9324 case SK_SPECIAL:
9325 ret = (sinfo) dmalloc (sizeof (*ret));
9326 ret->spec = s->info->spec;
9327 break;
9328 case SK_NEW:
9329 case SK_UNCONSTRAINED:
9330 ret = (sinfo) dmalloc (sizeof (*ret));
9331 ret->fname = s->info->fname;
9332 break;
9333 case SK_CONST:
9334 case SK_TYPE:
9335 case SK_RESULT:
9336 case SK_UNKNOWN:
9337 llassert (s->info == NULL);
9338 ret = NULL;
9339 break;
9340 }
9341 /*@=onlytrans@*/
9342 return ret;
9343}
9344
9345
9346static void
9347 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res,
9348 /*@notnull@*/ /*@exposed@*/ sRef other)
9349{
9350 llassert (res->kind == other->kind);
9351
9352 switch (res->kind)
9353 {
9354 case SK_CVAR:
9355 res->info->cvar->lexlevel = other->info->cvar->lexlevel;
9356 res->info->cvar->index = other->info->cvar->index;
9357 break;
9358
9359 case SK_PARAM:
9360 res->info->paramno = other->info->paramno;
28bf4b0b 9361 llassert (res->info->paramno >= -1);
616915dd 9362 break;
9363
9364 case SK_ARRAYFETCH:
9365 res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
9366 res->info->arrayfetch->ind = other->info->arrayfetch->ind;
9367 res->info->arrayfetch->arr = other->info->arrayfetch->arr;
9368 break;
9369
9370 case SK_FIELD:
9371 res->info->field->rec = other->info->field->rec;
9372 res->info->field->field = other->info->field->field;
9373 break;
9374
9375 case SK_OBJECT:
9376 res->info->object = other->info->object;
9377 break;
9378
9379 case SK_PTR:
9380 case SK_ADR:
9381 case SK_DERIVED:
9382 case SK_EXTERNAL:
9383 res->info->ref = other->info->ref;
9384 break;
9385
9386 case SK_CONJ:
9387 res->info->conj->a = other->info->conj->a;
9388 res->info->conj->b = other->info->conj->b;
9389 break;
9390
9391 case SK_SPECIAL:
9392 res->info->spec = other->info->spec;
9393 break;
9394
9395 case SK_NEW:
9396 case SK_UNCONSTRAINED:
9397 res->info->fname = other->info->fname;
9398 break;
9399
9400 case SK_CONST:
9401 case SK_TYPE:
9402 case SK_UNKNOWN:
9403 case SK_RESULT:
9404 llassert (res->info == NULL);
9405 break;
9406 }
9407}
9408
9409static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
9410 /*@uses s->kind, s->info@*/
9411 /*@releases s->info@*/
9412{
9413 switch (s->kind)
9414 {
9415 case SK_CVAR:
28bf4b0b 9416 DPRINTF (("Free sinfo: [%p]", s->info->cvar));
616915dd 9417 sfree (s->info->cvar);
9418 break;
9419
9420 case SK_PARAM:
9421 break;
9422
9423 case SK_ARRAYFETCH:
28bf4b0b 9424 DPRINTF (("Free sinfo: [%p]", s->info->arrayfetch));
616915dd 9425 sfree (s->info->arrayfetch);
9426 break;
9427
9428 case SK_FIELD:
28bf4b0b 9429 DPRINTF (("Free sinfo: [%p]", s->info->field));
616915dd 9430 sfree (s->info->field);
9431 break;
9432
9433 case SK_OBJECT:
9434 break;
9435
9436 case SK_PTR:
9437 case SK_ADR:
9438 case SK_DERIVED:
b73d1009 9439 case SK_EXTERNAL: /* is copy now! */
616915dd 9440 break;
9441
9442 case SK_CONJ:
28bf4b0b 9443 DPRINTF (("Free sinfo: [%p]", s->info->conj));
616915dd 9444 sfree (s->info->conj);
9445 break;
9446
9447 case SK_UNCONSTRAINED:
9448 case SK_SPECIAL:
9449 case SK_CONST:
9450 case SK_NEW:
9451 case SK_TYPE:
9452 case SK_UNKNOWN:
9453 case SK_RESULT:
9454 break;
9455 }
9456
28bf4b0b 9457 if (s->info != NULL) {
9458 DPRINTF (("Free sinfo: [%p]", s->info));
9459 }
9460
616915dd 9461 sfree (s->info);
9462}
9463
9464bool sRef_isNSLocalVar (sRef s)
9465{
9466 if (sRef_isLocalVar (s))
9467 {
9468 uentry ue = sRef_getUentry (s);
9469
9470 return (!uentry_isStatic (ue));
9471 }
9472 else
9473 {
9474 return FALSE;
9475 }
9476}
9477
9478bool sRef_isLocalVar (sRef s)
9479{
9480 if (sRef_isValid(s))
9481 {
9482 return (s->kind == SK_CVAR
9483 && (s->info->cvar->lexlevel > fileScope));
9484 }
9485
9486 return FALSE;
9487}
9488
9489bool sRef_isRealLocalVar (sRef s)
9490{
9491 if (sRef_isValid(s))
9492 {
9493 if (s->kind == SK_CVAR)
9494 {
9495 if (s->info->cvar->lexlevel == functionScope)
9496 {
9497 uentry ue = sRef_getUentry (s);
9498
9499 if (uentry_isAnyParam (ue)
9500 || uentry_isRefParam (ue))
9501 {
9502 return FALSE;
9503 }
9504 else
9505 {
9506 return TRUE;
9507 }
9508 }
9509 else
9510 {
9511 return (s->info->cvar->lexlevel > functionScope);
9512 }
9513 }
9514 }
9515
9516 return FALSE;
9517}
9518
9519bool sRef_isLocalParamVar (sRef s)
9520{
9521 if (sRef_isValid(s))
9522 {
9523 return (s->kind == SK_PARAM
9524 || (s->kind == SK_CVAR
9525 && (s->info->cvar->lexlevel > fileScope)));
9526 }
9527
9528 return FALSE;
9529}
9530
9531static speckind speckind_fromInt (int i)
9532{
9533 /*@+enumint@*/
9534 llassert (i >= SR_NOTHING && i <= SR_SYSTEM);
9535 /*@=enumint@*/
9536
9537 return ((speckind) i);
9538}
9539
28bf4b0b 9540
abd7f895 9541static void sRef_updateNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
28bf4b0b 9542 /*@modifies res@*/
9543{
9544 res->nullstate = other->nullstate;
210066f9 9545 DPRINTF (("update null state==> %s", sRef_unparseFull (res)));
28bf4b0b 9546 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
60868d40 9547 sRef_resetAliasKind (res);
28bf4b0b 9548}
9549
616915dd 9550void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9551{
28bf4b0b 9552 nstate n1 = sRef_getNullState (res);
9553 nstate n2 = sRef_getNullState (other);
616915dd 9554 bool flip = FALSE;
9555 nstate nn = n1;
9556
9557 if (n1 == n2 || n2 == NS_UNKNOWN)
9558 {
9559 ;
9560 }
9561 else
9562 {
9563 /* note: n2 is not unknown or defnull */
9564
9565 switch (n1)
9566 {
9567 case NS_ERROR: nn = NS_ERROR; break;
9568 case NS_UNKNOWN: flip = TRUE; nn = n2; break;
9569 case NS_POSNULL: break;
9570 case NS_DEFNULL: nn = NS_POSNULL; break;
9571 case NS_RELNULL: break;
9572 case NS_NOTNULL:
9573 if (n2 == NS_MNOTNULL)
9574 {
9575 ;
9576 }
9577 else
9578 {
9579 flip = TRUE;
9580 nn = NS_POSNULL;
9581 }
9582 break;
9583 case NS_MNOTNULL:
9584 if (n2 == NS_NOTNULL)
9585 {
9586 nn = NS_NOTNULL;
9587 }
9588 else
9589 {
9590 flip = TRUE;
9591 nn = NS_POSNULL;
9592 }
9593 break;
9594 case NS_CONSTNULL:
9595 case NS_ABSNULL:
9596 flip = TRUE;
9597 nn = n2;
9598 }
9599 }
9600
9601 if (flip)
9602 {
28bf4b0b 9603 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
616915dd 9604 }
9605
9606 res->nullstate = nn;
210066f9 9607 DPRINTF (("update null state==> %s", sRef_unparseFull (res)));
60868d40 9608 sRef_resetAliasKind (res);
616915dd 9609}
9610
9611cstring sRef_nullMessage (sRef s)
9612{
6483a926 9613 llassert (sRef_isReasonable (s));
616915dd 9614
28bf4b0b 9615 switch (sRef_getNullState (s))
616915dd 9616 {
9617 case NS_DEFNULL:
9618 case NS_CONSTNULL:
9619 return (cstring_makeLiteralTemp ("null"));
9620 default:
9621 return (cstring_makeLiteralTemp ("possibly null"));
9622 }
9623 BADEXIT;
9624}
9625
9626/*@observer@*/ cstring sRef_ntMessage (sRef s)
9627{
6483a926 9628 llassert (sRef_isReasonable (s));
616915dd 9629
9630 switch (s->nullstate)
9631 {
9632 case NS_DEFNULL:
9633 case NS_CONSTNULL:
9634 return (cstring_makeLiteralTemp ("not nullterminated"));
9635 default:
9636 return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
9637 }
9638 BADEXIT;
9639}
9640
9641
9642
9643sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
9644{
9645 sRef tmp = sRef_undefined;
9646 sRef ret;
9647
6483a926 9648 llassert (sRef_isReasonable (s));
616915dd 9649
9650 switch (s->kind)
9651 {
9652 case SK_RESULT:
9653 s->type = typ;
9654 ret = s;
9655 break;
9656 case SK_ARRAYFETCH:
9657 {
9658 ctype ct;
9659 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9660
9661 ct = ctype_realType (sRef_getType (tmp));
9662
9663
9664 if (ctype_isKnown (ct))
9665 {
9666 if (ctype_isAP (ct))
9667 {
9668 ;
9669 }
9670 else
9671 {
9672 voptgenerror
9673 (FLG_TYPE,
9674 message
9675 ("Special clause indexes non-array (%t): *%q",
9676 ct, sRef_unparse (s->info->arrayfetch->arr)),
9677 uentry_whereLast (ue));
9678 }
9679 }
9680
9681 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9682
9683 if (s->info->arrayfetch->indknown)
9684 {
9685 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
9686 }
9687 else
9688 {
9689 ret = sRef_makeArrayFetch (tmp);
9690 }
9691 }
9692 break;
9693 case SK_FIELD:
9694 {
9695 sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
9696 ctype ct = ctype_realType (sRef_getType (rec));
9697
9698 if (ctype_isKnown (ct))
9699 {
9700 if (ctype_isSU (ct))
9701 {
9702 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct),
9703 s->info->field->field)))
9704 {
9705 ;
9706 }
9707 else
9708 {
9709 voptgenerror
9710 (FLG_TYPE,
9711 message
9712 ("Special clause accesses non-existent field of result: %q.%s",
9713 sRef_unparse (rec), s->info->field->field),
9714 uentry_whereLast (ue));
9715 }
9716 }
9717 else
9718 {
9719 voptgenerror
9720 (FLG_TYPE,
9721 message
9722 ("Special clause accesses field of non-struct or union result (%t): %q.%s",
9723 ct, sRef_unparse (rec), s->info->field->field),
9724 uentry_whereLast (ue));
9725 }
9726 }
9727
9728 ret = sRef_makeField (tmp, s->info->field->field);
9729 break;
9730 }
9731 case SK_PTR:
9732 {
9733 ctype ct;
9734 tmp = sRef_fixResultType (s->info->ref, typ, ue);
9735
9736 ct = ctype_realType (sRef_getType (tmp));
9737
9738 if (ctype_isKnown (ct))
9739 {
9740 if (ctype_isAP (ct))
9741 {
9742 ;
9743 }
9744 else
9745 {
9746 voptgenerror
9747 (FLG_TYPE,
9748 message
9749 ("Special clause dereferences non-pointer (%t): *%q",
9750 ct, sRef_unparse (s->info->ref)),
9751 uentry_whereLast (ue));
9752 }
9753 }
9754
9755 ret = sRef_makePointer (tmp);
9756 break;
9757 }
9758 case SK_ADR:
9759 voptgenerror
9760 (FLG_TYPE,
9761 message
9762 ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9763 uentry_whereLast (ue));
9764 ret = s;
9765 break;
9766 BADDEFAULT;
9767 }
9768
9769 return ret;
9770}
9771
9772bool sRef_isOnly (sRef s)
9773{
9774 return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9775}
9776
9777bool sRef_isDependent (sRef s)
9778{
9779 return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9780}
9781
9782bool sRef_isOwned (sRef s)
9783{
6483a926 9784 return (sRef_isReasonable (s) && (s->aliaskind == AK_OWNED));
616915dd 9785}
9786
9787bool sRef_isKeep (sRef s)
9788{
6483a926 9789 return (sRef_isReasonable (s) && (s->aliaskind == AK_KEEP));
616915dd 9790}
9791
9792bool sRef_isTemp (sRef s)
9793{
6483a926 9794 return (sRef_isReasonable (s) && alkind_isTemp (s->aliaskind));
616915dd 9795}
9796
9797bool sRef_isLocalState (sRef s)
9798{
6483a926 9799 return (sRef_isReasonable (s) && (s->aliaskind == AK_LOCAL));
616915dd 9800}
9801
9802bool sRef_isUnique (sRef s)
9803{
6483a926 9804 return (sRef_isReasonable (s) && (s->aliaskind == AK_UNIQUE));
616915dd 9805}
9806
9807bool sRef_isShared (sRef s)
9808{
6483a926 9809 return (sRef_isReasonable (s) && (s->aliaskind == AK_SHARED));
616915dd 9810}
9811
9812bool sRef_isExposed (sRef s)
9813{
6483a926 9814 return (sRef_isReasonable (s) && (s->expkind == XO_EXPOSED));
616915dd 9815}
9816
9817bool sRef_isObserver (sRef s)
9818{
6483a926 9819 return (sRef_isReasonable (s) && (s->expkind == XO_OBSERVER));
616915dd 9820}
9821
9822bool sRef_isFresh (sRef s)
9823{
6483a926 9824 return (sRef_isReasonable (s) && (s->aliaskind == AK_FRESH));
616915dd 9825}
9826
9827bool sRef_isDefinitelyNull (sRef s)
9828{
6483a926 9829 return (sRef_isReasonable (s) && (sRef_getNullState (s) == NS_DEFNULL
28bf4b0b 9830 || sRef_getNullState (s) == NS_CONSTNULL));
616915dd 9831}
9832
9833bool sRef_isAllocated (sRef s)
9834{
6483a926 9835 return (sRef_isReasonable (s) && (s->defstate == SS_ALLOCATED));
616915dd 9836}
9837
9838bool sRef_isStack (sRef s)
9839{
6483a926 9840 return (sRef_isReasonable (s) && (s->aliaskind == AK_STACK));
616915dd 9841}
9842
28bf4b0b 9843bool sRef_isNotNull (sRef s)
9844{
9845 return (sRef_isValid(s) && (sRef_getNullState (s) == NS_MNOTNULL
9846 || sRef_getNullState (s) == NS_NOTNULL));
9847}
9848
9849alkind sRef_getAliasKind (sRef s)
9850{
9851 if (sRef_isValid(s)) {
9852 llassert (alkind_isValid (s->aliaskind));
9853 return s->aliaskind;
9854 }
9855
9856 return AK_ERROR;
9857}
9858
9859nstate sRef_getNullState (sRef s)
9860{
6483a926 9861 if (sRef_isReasonable (s)) {
28bf4b0b 9862 llassert (nstate_isValid (s->nullstate));
9863 return s->nullstate;
9864 }
9865
9866 return NS_UNKNOWN;
9867}
9868
9869void sRef_reflectAnnotation (sRef s, annotationInfo a, fileloc loc)
9870{
6483a926 9871 if (sRef_isReasonable (s))
28bf4b0b 9872 {
9873 if (!valueTable_isDefined (s->state))
9874 {
9875 s->state = valueTable_create (1);
16c024b5 9876 valueTable_insert
9877 (s->state,
9878 cstring_copy (metaStateInfo_getName (annotationInfo_getState (a))),
9879 stateValue_create (annotationInfo_getValue (a),
9880 stateInfo_makeLoc (loc, SA_DECLARED)));
28bf4b0b 9881 }
9882 else
9883 {
9884 DPRINTF (("reflect loc: %s", fileloc_unparse (loc)));
9885 valueTable_update
9886 (s->state,
9887 metaStateInfo_getName (annotationInfo_getState (a)),
16c024b5 9888 stateValue_create (annotationInfo_getValue (a),
9889 stateInfo_makeLoc (loc, SA_DECLARED)));
9890
28bf4b0b 9891 DPRINTF (("sref: %s", sRef_unparse (s)));
9892 DPRINTF (("sref: %s", sRef_unparseFull (s)));
9893 }
9894 }
9895}
9896
9897void sRef_setMetaStateValueComplete (sRef s, cstring key, int value, fileloc loc)
9898{
9899 sRefSet aliases = usymtab_allAliases (s);
9900
9901 sRef_setMetaStateValue (s, key, value, loc);
9902
9903 sRefSet_realElements (aliases, current)
9904 {
6483a926 9905 if (sRef_isReasonable (current))
28bf4b0b 9906 {
9907 current = sRef_updateSref (current);
9908 sRef_setMetaStateValue (current, key, value, loc);
9909 }
9910 } end_sRefSet_realElements ;
9911
9912 sRefSet_free (aliases);
9913}
9914
9915void sRef_setMetaStateValue (sRef s, cstring key, int value, fileloc loc)
9916{
9917 sRef_checkMutable (s);
9918
6483a926 9919 if (sRef_isReasonable (s))
28bf4b0b 9920 {
9921 if (!valueTable_isDefined (s->state))
9922 {
9923 DPRINTF (("inserting state: %s: %s %d", sRef_unparse (s), key, value));
9924 s->state = valueTable_create (1);
9925 valueTable_insert (s->state, cstring_copy (key),
16c024b5 9926 stateValue_create (value,
9927 stateInfo_makeLoc (loc, SA_CHANGED)));
28bf4b0b 9928 }
9929 else
9930 {
9931 DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s), key, value,
9932 fileloc_unparse (loc)));
2c88d156 9933 if (valueTable_contains (s->state, key))
9934 {
9935 valueTable_update
16c024b5 9936 (s->state, key, stateValue_create (value,
9937 stateInfo_makeLoc (loc, SA_CHANGED)));
2c88d156 9938 }
9939 else
9940 {
9941 valueTable_insert
16c024b5 9942 (s->state, cstring_copy (key),
9943 stateValue_create (value, stateInfo_makeLoc (loc, SA_CHANGED)));
2c88d156 9944 }
9945
28bf4b0b 9946 DPRINTF (("After: %s", sRef_unparseFull (s)));
9947 }
9948 }
9949}
9950
9951bool sRef_checkMetaStateValue (sRef s, cstring key, int value)
9952{
6483a926 9953 if (sRef_isReasonable (s))
28bf4b0b 9954 {
9955 if (valueTable_isDefined (s->state))
9956 {
9957 stateValue val;
9958
9959 DPRINTF (("check state: %s: %s %d", sRef_unparse (s), key, value));
9960
9961 val = valueTable_lookup (s->state, key);
9962 llassert (stateValue_isDefined (val));
9963 return (stateValue_isError (val)
9964 || stateValue_getValue (val) == value);
9965 }
9966 else
9967 {
9968 return TRUE;
9969 }
9970 }
9971 else
9972 {
9973 return TRUE;
9974 }
9975}
9976
9977/*@observer@*/ stateValue sRef_getMetaStateValue (sRef s, cstring key)
9978{
6483a926 9979 if (sRef_isReasonable (s))
28bf4b0b 9980 {
9981 if (valueTable_isDefined (s->state))
9982 {
9983 stateValue val;
9984
9985 val = valueTable_lookup (s->state, key);
2c88d156 9986 /* Okay if its not defined, just returns stateValue_undefined */
28bf4b0b 9987 return val;
9988 }
9989 else
9990 {
9991 return stateValue_undefined;
9992 }
9993 }
9994 else
9995 {
9996 return stateValue_undefined;
9997 }
9998}
9999
10000/*@observer@*/ valueTable sRef_getValueTable (sRef s)
10001{
10002 DPRINTF (("Get value table: %s", sRef_unparse (s)));
10003
6483a926 10004 if (sRef_isReasonable (s))
28bf4b0b 10005 {
6483a926 10006 llassert (sRef_isReasonable (s));
28bf4b0b 10007 DPRINTF (("Value table: %s", valueTable_unparse (s->state)));
10008 return s->state;
10009 }
10010 else
10011 {
10012 DPRINTF (("No value table!"));
10013 return valueTable_undefined;
10014 }
10015}
10016
10017bool sRef_makeStateSpecial (sRef s)
10018{
10019 /*
10020 ** Default defined state can be made special.
10021 */
10022
b73d1009 10023 llassert (sRef_isReasonable (s));
28bf4b0b 10024
10025 if (s->defstate == SS_UNKNOWN || s->defstate == SS_DEFINED || s->defstate == SS_SPECIAL)
10026 {
ccf0a4a8 10027 /* s->aliaskind = AK_IMPTEMP; */ /* evans 2001-07-23 shouldn't effect alias state */
28bf4b0b 10028 s->defstate = SS_SPECIAL;
10029 DPRINTF (("Made special: %s", sRef_unparseFull (s)));
10030 return TRUE;
10031 }
10032 else
10033 {
ccf0a4a8 10034 /* s->aliaskind = AK_IMPTEMP; */
28bf4b0b 10035 s->defstate = SS_SPECIAL;
10036 return FALSE;
10037 }
10038}
10039
10040void sRef_markImmutable (sRef s)
616915dd 10041{
6483a926 10042 if (sRef_isReasonable (s))
28bf4b0b 10043 {
10044 DPRINTF (("Mark immutable: %s", sRef_unparseFull (s)));
10045 s->immut = TRUE;
10046 }
10047}
10048
10049bool sRef_definitelyNullContext (sRef s)
10050{
10051 return (sRef_definitelyNull (s)
10052 || usymtab_isDefinitelyNullDeep (s));
10053}
10054
10055bool sRef_definitelyNullAltContext (sRef s)
10056{
10057 return (sRef_definitelyNull (s)
10058 || usymtab_isAltDefinitelyNullDeep (s));
616915dd 10059}
10060
28bf4b0b 10061
616915dd 10062/* start modifications */
28bf4b0b 10063struct s_bbufinfo sRef_getNullTerminatedState (sRef p_s) {
10064 struct s_bbufinfo BUFSTATE_UNKNOWN;
616915dd 10065 BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
10066 BUFSTATE_UNKNOWN.size = 0;
10067 BUFSTATE_UNKNOWN.len = 0;
10068
10069 if (sRef_isValid(p_s))
10070 return p_s->bufinfo;
10071 return BUFSTATE_UNKNOWN;
10072}
10073
10074void sRef_setNullTerminatedState(sRef p_s) {
6483a926 10075 if(sRef_isReasonable (p_s)) {
616915dd 10076 p_s->bufinfo.bufstate = BB_NULLTERMINATED;
10077 } else {
10078 llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
10079 }
10080}
10081
10082
10083void sRef_setPossiblyNullTerminatedState(sRef p_s) {
6483a926 10084 if( sRef_isReasonable (p_s)) {
616915dd 10085 p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
10086 } else {
10087 llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
10088 }
10089}
10090
10091void sRef_setNotNullTerminatedState(sRef p_s) {
6483a926 10092 if( sRef_isReasonable (p_s)) {
616915dd 10093 p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
10094 } else {
10095 llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
10096 }
10097}
10098
10099void sRef_setLen(sRef p_s, int len) {
02b84d4b 10100 if (sRef_isReasonable (p_s) && sRef_isNullTerminated(p_s))
10101 {
10102 p_s->bufinfo.len = len;
10103 }
10104 else
10105 {
10106 llfatalbug( message("sRef_setLen passed an invalid sRef\n"));
10107 }
616915dd 10108}
10109
10110
10111void sRef_setSize(sRef p_s, int size) {
02b84d4b 10112 if( sRef_isValid(p_s))
10113 {
616915dd 10114 p_s->bufinfo.size = size;
02b84d4b 10115 }
10116 else
10117 {
10118 llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
10119 }
616915dd 10120}
10121
10122void sRef_resetLen(sRef p_s) {
02b84d4b 10123 if (sRef_isReasonable (p_s))
10124 {
10125 p_s->bufinfo.len = 0;
10126 }
10127 else
10128 {
10129 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
10130 }
616915dd 10131}
10132
10133/*drl7x 11/28/2000 */
10134
dc92450f 10135bool sRef_isFixedArray (sRef p_s) /*@*/ {
616915dd 10136 ctype c;
10137 c = sRef_getType (p_s);
10138 return ( ctype_isFixedArray (c) );
10139}
10140
37ae0b5e 10141size_t sRef_getArraySize (sRef p_s) /*@*/
10142{
616915dd 10143 ctype c;
10144 llassert (sRef_isFixedArray(p_s) );
470b7798 10145 DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) ) ));
10146
616915dd 10147 c = sRef_getType (p_s);
37ae0b5e 10148 return (ctype_getArraySize (c));
616915dd 10149}
10150
b9904f57 10151void sRef_setValue (sRef s, multiVal val)
10152{
b87215ab 10153 if (!sRef_isReasonable (s))
10154 {
10155 llcontbuglit ("Unreasonable sRef");
10156 llcontbug (message ("sRef: %s", sRef_unparse (s)));
10157 return;
10158 }
10159
b9904f57 10160 multiVal_free (s->val);
10161 s->val = val;
10162}
10163
10164bool sRef_hasValue (sRef s)
10165{
6483a926 10166 return (sRef_isReasonable (s)
b9904f57 10167 && multiVal_isDefined (s->val));
10168}
10169
10170multiVal sRef_getValue (sRef s)
10171{
6483a926 10172 if (sRef_isReasonable (s))
b9904f57 10173 {
10174 return s->val;
10175 }
10176
10177 return multiVal_undefined;
10178}
This page took 1.780857 seconds and 5 git commands to generate.