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