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