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