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