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