]> 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
6970c11b 2328 ret = sRef_makeGlobal (uid, ctype_unknown, stateInfo_currentLoc ());
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':
6970c11b 2370 return (sRef_makeGlobal (usymId_fromInt (reader_getInt (c)), ctype_unknown, stateInfo_currentLoc ()));
616915dd 2371 case 'p':
6970c11b 2372 return (sRef_makeParam (reader_getInt (c), ctype_unknown, stateInfo_makeLoc (g_currentloc)));
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
6970c11b 3109 sRef_makeCvarAux (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
616915dd 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));
6970c11b 3150 s->state = context_createValueTable (s, stinfo);
616915dd 3151 return s;
3152}
3153
6970c11b 3154/*@dependent@*/ sRef sRef_makeCvar (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
616915dd 3155{
6970c11b 3156 return (sRef_makeCvarAux (level, index, ct, stinfo));
616915dd 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
6970c11b 3178sRef_makeGlobal (usymId l, ctype ct, /*@only@*/ stateInfo stinfo)
616915dd 3179{
6970c11b 3180 return (sRef_makeCvar (globScope, l, ct, stinfo));
616915dd 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
6970c11b 3192sRef_makeParam (int l, ctype ct, stateInfo stinfo)
616915dd 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));
6970c11b 3206 s->state = context_createValueTable (s, stinfo);
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));
6970c11b 3294 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
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));
6970c11b 3467 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
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));
6970c11b 3486 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
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));
6970c11b 3502 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
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 {
616915dd 4175 if (sRef_isKept (el))
4176 {
4177 sRef_showAliasInfo (el);
4178 }
4179 else
4180 {
4181 sRef_showStateInfo (el);
4182 }
4183
4184 /* prevent further errors */
4185 el->defstate = SS_UNKNOWN;
4186 sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);
4187
4188 return FALSE;
4189 }
4190 }
4191
4192 return TRUE;
4193}
4194
4195static void
4196checkDerivDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4197{
4198
4199 if (checkDeadState (el, tbranch, loc))
4200 {
4201 sRefSet_allElements (el->deriv, t)
4202 {
4203 if (sRef_isValid (t))
4204 {
4205 checkDerivDeadState (t, tbranch, loc);
4206 }
4207 } end_sRefSet_allElements;
4208 }
4209}
4210
4211static sRefSet
4212 sRef_mergePdefinedDerivs (sRefSet res, sRefSet other, bool opt,
4213 clause cl, fileloc loc)
4214{
4215 sRefSet ret = sRefSet_new ();
4216
4217 sRefSet_allElements (res, el)
4218 {
4219 if (sRef_isValid (el))
4220 {
4221 sRef e2 = sRefSet_lookupMember (other, el);
4222
4223 if (sRef_isValid (e2))
4224 {
4225 if (sRef_isAllocated (el) && !sRef_isAllocated (e2))
4226 {
4227 ;
4228 }
4229 else if (sRef_isAllocated (e2) && !sRef_isAllocated (el))
4230 {
28bf4b0b 4231 el->deriv = sRefSet_copyInto (el->deriv, e2->deriv);
616915dd 4232 }
4233 else
4234 {
4235 el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv,
4236 opt, cl, loc);
4237 }
4238
4239 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4240
4241 ret = sRefSet_insert (ret, el);
4242 (void) sRefSet_delete (other, e2);
4243 }
4244 else
4245 {
4246 if (!opt)
4247 {
4248 checkDerivDeadState (el, (cl == FALSECLAUSE), loc);
4249 }
4250
4251 ret = sRefSet_insert (ret, el);
4252 }
4253 }
4254 } end_sRefSet_allElements;
4255
4256 sRefSet_allElements (other, el)
4257 {
4258 if (sRef_isValid (el))
4259 {
4260 if (!sRefSet_member (ret, el))
4261 {
4262 /* was cl == FALSECLAUSE */
4263 checkDerivDeadState (el, FALSE, loc);
4264 ret = sRefSet_insert (ret, el);
4265 }
4266 else
4267 {
4268 /*
4269 ** it's okay --- member is a different equality test
4270 */
4271 }
4272 }
4273 } end_sRefSet_allElements;
4274
4275 sRefSet_free (res);
4276 return (ret);
4277}
4278
4279sRef sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a, /*@exposed@*/ sRef b)
4280{
4281 llassert (sRef_isValid (a));
4282 llassert (sRef_isValid (b));
4283
4284 if (!sRef_equivalent (a, b))
4285 {
28bf4b0b 4286 sRef s = sRef_newRef ();
616915dd 4287
4288 s->kind = SK_CONJ;
4289 s->info = (sinfo) dmalloc (sizeof (*s->info));
4290 s->info->conj = (cjinfo) dmalloc (sizeof (*s->info->conj));
28bf4b0b 4291 s->info->conj->a = a; /* sRef_copy (a) */ /*@i32*/ ;
4292 s->info->conj->b = b; /* sRef_copy (b);*/ /*@i32@*/ ;
616915dd 4293
4294 if (ctype_equal (a->type, b->type)) s->type = a->type;
4295 else s->type = ctype_makeConj (a->type, b->type);
4296
4297 if (a->defstate == b->defstate)
4298 {
4299 s->defstate = a->defstate;
4300 }
4301 else
4302 {
4303 s->defstate = SS_UNKNOWN;
4304 }
4305
28bf4b0b 4306 sRef_setNullStateN (s, NS_UNKNOWN);
616915dd 4307
4308 s->safe = a->safe && b->safe;
4309 s->aliaskind = alkind_resolve (a->aliaskind, b->aliaskind);
4310
28bf4b0b 4311 llassert (valueTable_isUndefined (s->state));
6970c11b 4312 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
616915dd 4313 return s;
4314 }
4315 else
4316 {
4317 /*@-exposetrans@*/ return a; /*@=exposetrans@*/
4318 }
4319}
4320
28bf4b0b 4321/*@dependent@*/ sRef
616915dd 4322sRef_makeUnknown ()
4323{
4324 sRef s = sRef_new ();
4325
4326 s->kind = SK_UNKNOWN;
4327 return s;
4328}
4329
28bf4b0b 4330static /*@owned@*/ sRef
616915dd 4331sRef_makeSpecial (speckind sk) /*@*/
4332{
4333 sRef s = sRef_new ();
4334
4335 s->kind = SK_SPECIAL;
4336 s->info = (sinfo) dmalloc (sizeof (*s->info));
4337 s->info->spec = sk;
28bf4b0b 4338 /*@-dependenttrans@*/
616915dd 4339 return s;
28bf4b0b 4340 /*@=dependenttrans@*/
616915dd 4341}
4342
28bf4b0b 4343static /*@owned@*/ sRef srnothing = sRef_undefined;
4344static /*@owned@*/ sRef srinternal = sRef_undefined;
4345static /*@owned@*/ sRef srsystem = sRef_undefined;
4346static /*@owned@*/ sRef srspec = sRef_undefined;
616915dd 4347
28bf4b0b 4348/*@dependent@*/ sRef
616915dd 4349sRef_makeNothing (void)
4350{
4351 if (sRef_isInvalid (srnothing))
4352 {
4353 srnothing = sRef_makeSpecial (SR_NOTHING);
4354 }
4355
616915dd 4356 return srnothing;
616915dd 4357}
4358
4359sRef
4360sRef_makeInternalState (void)
4361{
4362 if (sRef_isInvalid (srinternal))
4363 {
4364 srinternal = sRef_makeSpecial (SR_INTERNAL);
4365 }
4366
616915dd 4367 return srinternal;
616915dd 4368}
4369
4370sRef
4371sRef_makeSpecState (void)
4372{
4373 if (sRef_isInvalid (srspec))
4374 {
4375 srspec = sRef_makeSpecial (SR_SPECSTATE);
4376 }
4377
616915dd 4378 return srspec;
616915dd 4379}
4380
4381sRef
4382sRef_makeSystemState (void)
4383{
4384 if (sRef_isInvalid (srsystem))
4385 {
4386 srsystem = sRef_makeSpecial (SR_SYSTEM);
4387 }
4388
28bf4b0b 4389 return srsystem;
4390}
4391
4392sRef
4393sRef_makeGlobalMarker (void)
4394{
4395 sRef s = sRef_makeSpecial (SR_GLOBALMARKER);
4396 llassert (valueTable_isUndefined (s->state));
6970c11b 4397 s->state = context_createGlobalMarkerValueTable (stateInfo_undefined);
28bf4b0b 4398 return s;
616915dd 4399}
4400
616915dd 4401sRef
b072092f 4402sRef_makeResult (ctype c)
616915dd 4403{
28bf4b0b 4404 sRef s = sRef_newRef ();
616915dd 4405
4406 s->kind = SK_RESULT;
b072092f 4407 s->type = c;
616915dd 4408 s->defstate = SS_UNKNOWN;
4409 s->aliaskind = AK_UNKNOWN;
28bf4b0b 4410 sRef_setNullStateN (s, NS_UNKNOWN);
4411 llassert (valueTable_isUndefined (s->state));
6970c11b 4412 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
28bf4b0b 4413
4414 DPRINTF (("Result: [%p] %s", s, sRef_unparseFull (s)));
616915dd 4415 return s;
4416}
4417
4418
4419bool
4420sRef_isNothing (sRef s)
4421{
4422 return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4423}
4424
4425bool
4426sRef_isInternalState (sRef s)
4427{
4428 return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4429}
4430
4431bool
4432sRef_isSpecInternalState (sRef s)
4433{
4434 return (sRef_isKindSpecial (s)
4435 && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4436}
4437
4438bool
4439sRef_isSpecState (sRef s)
4440{
4441 return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4442}
4443
4444bool
4445sRef_isResult (sRef s)
4446{
4447 return (sRef_isValid (s) && s->kind == SK_RESULT);
4448}
4449
4450bool
4451sRef_isSystemState (sRef s)
4452{
4453 return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4454}
4455
28bf4b0b 4456bool
4457sRef_isGlobalMarker (sRef s)
4458{
4459 return (sRef_isKindSpecial (s) && s->info->spec == SR_GLOBALMARKER);
4460}
4461
616915dd 4462usymId
4463sRef_getScopeIndex (sRef s)
4464{
4465 llassert (sRef_isValid (s));
4466 llassert (sRef_isCvar (s));
4467
4468 return (s->info->cvar->index);
4469}
4470
4471void
4472sRef_makeSafe (sRef s)
4473{
4474 if (sRef_isValid (s))
4475 {
4476 s->safe = TRUE;
4477 }
4478}
4479
4480void
4481sRef_makeUnsafe (sRef s)
4482{
4483 if (sRef_isValid (s))
4484 {
4485 s->safe = FALSE;
4486 }
4487}
4488
4489/*
4490** memory state operations
4491*/
4492
4493/*@only@*/ cstring sRef_unparseFull (sRef s)
4494{
4495 if (sRef_isInvalid (s)) return (cstring_undefined);
4496
28bf4b0b 4497 return (message ("[%d] %q - %q [%s] { %q } < %q >",
616915dd 4498 (int) s,
4499 sRef_unparseDebug (s),
4500 sRef_unparseState (s),
4501 exkind_unparse (s->oexpkind),
28bf4b0b 4502 sRefSet_unparseDebug (s->deriv),
4503 valueTable_unparse (s->state)));
616915dd 4504}
4505
4506/*@unused@*/ cstring sRef_unparseDeep (sRef s)
4507{
4508 cstring st = cstring_undefined;
4509
4510 st = message ("%q:", sRef_unparseFull (s));
4511
4512 if (sRef_isValid (s))
4513 {
4514 sRefSet_allElements (s->deriv, el)
4515 {
4516 st = message("%q\n%q", st, sRef_unparseDeep (el));
4517 } end_sRefSet_allElements ;
4518 }
4519
4520 return st;
4521}
4522
4523/*@only@*/ cstring sRef_unparseState (sRef s)
4524{
4525 if (sRef_isConj (s))
4526 {
4527 return (message ("%q | %q",
4528 sRef_unparseState (s->info->conj->a),
4529 sRef_unparseState (s->info->conj->b)));
4530 }
4531
4532 if (sRef_isInvalid (s))
4533 {
4534 return (cstring_makeLiteral ("<invalid>"));
4535 }
4536
4537 return (message ("%s.%s.%s.%s",
4538 alkind_unparse (s->aliaskind),
28bf4b0b 4539 nstate_unparse (sRef_getNullState (s)),
616915dd 4540 exkind_unparse (s->expkind),
4541 sstate_unparse (s->defstate)));
4542}
4543
4544bool sRef_isNotUndefined (sRef s)
4545{
4546 return (sRef_isInvalid (s)
4547 || (s->defstate != SS_UNDEFINED
4548 && s->defstate != SS_UNUSEABLE
4549 && s->defstate != SS_DEAD));
4550}
4551
4552ynm sRef_isWriteable (sRef s)
4553{
4554 if (sRef_isInvalid (s)) return MAYBE;
4555
4556 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4557 {
4558 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s))))
4559 {
4560 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4561 {
4562 return YES;
4563 }
4564 return MAYBE;
4565 }
4566 else
4567 {
4568 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4569 {
4570 return MAYBE;
4571 }
4572 return NO;
4573 }
4574 }
4575
4576 return (ynm_fromBool (s->defstate != SS_UNUSEABLE));
4577}
4578
4579bool sRef_hasNoStorage (sRef s)
4580{
4581 return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
4582}
4583
4584bool sRef_isStrictReadable (sRef s)
4585{
4586 return (ynm_toBoolStrict (sRef_isReadable (s)));
4587}
4588
4589ynm sRef_isReadable (sRef s)
4590{
4591 sstate ss;
4592
4593 if (sRef_isInvalid (s)) return YES;
4594
4595 ss = s->defstate;
4596
4597 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4598 {
4599 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjA (s))))
4600 {
4601 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4602 {
4603 return YES;
4604 }
4605 return MAYBE;
4606 }
4607 else
4608 {
4609 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4610 {
4611 return MAYBE;
4612 }
4613 return NO;
4614 }
4615 }
4616 else if (ss == SS_HOFFA)
4617 {
4618 if (context_getFlag (FLG_STRICTUSERELEASED))
4619 {
4620 return MAYBE;
4621 }
4622 else
4623 {
4624 return YES;
4625 }
4626 }
4627 else
4628 {
4629 return (ynm_fromBool (ss == SS_DEFINED
4630 || ss == SS_FIXED
4631 || ss == SS_RELDEF
4632 || ss == SS_PDEFINED
4633 || ss == SS_PARTIAL
4634 || ss == SS_SPECIAL
4635 || ss == SS_ALLOCATED
28bf4b0b 4636 || ss == SS_KILLED /* evans 2001-05-26: added this for killed globals */
616915dd 4637 || ss == SS_UNKNOWN));
4638 }
4639}
4640
4641static /*@exposed@*/ sRef whatUndefined (/*@exposed@*/ sRef fref, int depth)
4642{
4643 ctype ct;
4644
4645
4646 if (depth > MAXDEPTH)
4647 {
4648 llgenmsg (message
4649 ("Warning: check definition limit exceeded, checking %q. "
4650 "This either means there is a variable with at least "
4651 "%d indirections apparent in the program text, or "
4652 "there is a bug in LCLint.",
4653 sRef_unparse (fref),
4654 MAXDEPTH),
4655 g_currentloc);
4656
4657 return sRef_undefined;
4658 }
4659
4660 if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
4661 {
4662 return sRef_undefined;
4663 }
4664
4665 if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
4666 {
4667 return fref;
4668 }
4669
4670 ct = ctype_realType (sRef_getType (fref));
4671
4672 if (ctype_isUnknown (ct))
4673 {
4674 return sRef_undefined;
4675 }
4676 else if (ctype_isPointer (ct) || ctype_isArray (ct))
4677 {
4678 if (sRef_isStateUnknown (fref))
4679 {
4680 return sRef_undefined;
4681 }
4682 else
4683 {
4684 sRef fptr = sRef_constructDeref (fref);
4685
4686 return (whatUndefined (fptr, depth + 1));
4687 }
4688 }
4689 else if (ctype_isStruct (ct))
4690 {
4691 bool hasOneDefined = FALSE;
4692
4693 if (sRef_isStateUnknown (fref))
4694 {
4695 return fref;
4696 }
4697
4698 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
4699 {
4700 sRefSet_realElements (sRef_derivedFields (fref), sr)
4701 {
4702 hasOneDefined = TRUE;
4703
4704 if (sRef_isField (sr))
4705 {
4706 cstring fieldname = sRef_getField (sr);
4707 sRef fldref = sRef_makeField (fref, fieldname);
4708 bool shouldCheck = !sRef_isRecursiveField (fldref);
4709
4710 if (shouldCheck)
4711 {
4712 sRef wdef = whatUndefined (fldref, depth + 1);
4713
4714 if (sRef_isValid (wdef))
4715 {
4716 return wdef;
4717 }
4718 }
4719 }
4720 } end_sRefSet_realElements;
4721 }
4722 else if (sRef_isAllocated (fref))
4723 {
4724 /*
4725 ** for structures, each field must be completely defined
4726 */
4727
4728 uentryList fields = ctype_getFields (ct);
4729
4730 uentryList_elements (fields, ue)
4731 {
4732 cstring name = uentry_getRealName (ue);
4733 sRef ffield = sRef_makeField (fref, name);
4734 bool shouldCheck = !sRef_isRecursiveField (ffield);
4735
4736 if (sRef_isRelDef (uentry_getSref (ue)))
4737 {
4738 ; /* no error */
4739 }
4740 else
4741 {
4742 if (shouldCheck)
4743 {
4744 sRef wdef = whatUndefined (ffield, depth + 1);
4745
4746 if (sRef_isInvalid (wdef))
4747 {
4748 return wdef;
4749 }
4750 }
4751 }
4752 } end_uentryList_elements;
4753 }
4754 else
4755 {
4756 ;
4757 }
4758 }
4759 else if (ctype_isUnion (ct))
4760 {
4761 ;
4762 }
4763 else
4764 {
4765 ;
4766 }
4767
4768 return sRef_undefined;
4769}
4770
28bf4b0b 4771static bool checkDefined (/*@temp@*/ sRef sr)
616915dd 4772{
28bf4b0b 4773 /*@-temptrans@*/ /* the result from whatUndefined is lost */
616915dd 4774 return (sRef_isInvalid (whatUndefined (sr, 0)));
28bf4b0b 4775 /*@=temptrans@*/
616915dd 4776}
4777
4778bool sRef_isReallyDefined (sRef s)
4779{
4780 if (sRef_isValid (s))
4781 {
4782 if (sRef_isAnyDefined (s))
4783 {
4784 return TRUE;
4785 }
4786 else
4787 {
4788 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4789 {
4790 return checkDefined (s);
4791 }
4792 else
4793 {
4794 return FALSE;
4795 }
4796 }
4797 }
4798 else
4799 {
4800 return TRUE;
4801 }
4802}
4803
4804void sRef_showNotReallyDefined (sRef s)
4805{
4806 if (sRef_isValid (s))
4807 {
4808 if (sRef_isAnyDefined (s))
4809 {
4810 BADBRANCH;
4811 }
4812 else
4813 {
4814 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4815 {
28bf4b0b 4816 /*@-temptrans@*/ /* the result of whatUndefined is lost */
616915dd 4817 sRef ref = whatUndefined (s, 0);
4818
4819 llassert (sRef_isValid (ref));
4820
4821 if (ref != s)
4822 {
4823 llgenindentmsgnoloc
4824 (message ("This sub-reference is %s: %q",
4825 sstate_unparse (sRef_getDefState (ref)),
4826 sRef_unparse (ref)));
4827 }
4828 }
4829 else
4830 {
4831 ;
4832 }
4833 }
4834 }
4835 else
4836 {
4837 BADBRANCH;
4838 }
4839}
4840
4841sstate sRef_getDefState (sRef s)
4842{
4843 if (sRef_isInvalid (s)) return (SS_UNKNOWN);
4844 return (s->defstate);
4845}
4846
4847void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
4848{
28bf4b0b 4849 sRef_checkMutable (s);
616915dd 4850 sRef_setStateAux (s, defstate, loc);
4851}
4852
4853static void sRef_clearAliasStateAux (sRef s, fileloc loc)
4854{
28bf4b0b 4855 sRef_checkMutable (s);
616915dd 4856 sRef_setAliasKind (s, AK_ERROR, loc);
4857}
4858
4859void sRef_clearAliasState (sRef s, fileloc loc)
4860{
28bf4b0b 4861 sRef_checkMutable (s);
616915dd 4862 sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
4863}
4864
4865void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
4866{
28bf4b0b 4867 sRef_checkMutable (s);
616915dd 4868 sRef_aliasSetCompleteParam (sRef_setAliasKind, s, kind, loc);
4869}
4870
4871void sRef_setAliasKind (sRef s, alkind kind, fileloc loc)
4872{
28bf4b0b 4873 sRef_checkMutable (s);
4874
616915dd 4875 if (sRef_isValid (s))
4876 {
4877 sRef_clearDerived (s);
4878
4879 if ((kind != s->aliaskind && kind != s->oaliaskind)
4880 && fileloc_isDefined (loc))
4881 {
28bf4b0b 4882 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
616915dd 4883 }
4884
4885 s->aliaskind = kind;
4886 }
4887}
4888
4889void sRef_setOrigAliasKind (sRef s, alkind kind)
4890{
28bf4b0b 4891 sRef_checkMutable (s);
4892
616915dd 4893 if (sRef_isValid (s))
4894 {
4895 s->oaliaskind = kind;
4896 }
4897}
4898
4899exkind sRef_getExKind (sRef s)
4900{
4901 if (sRef_isValid (s))
4902 {
4903 return (s->expkind);
4904 }
4905 else
4906 {
4907 return XO_UNKNOWN;
4908 }
4909}
4910
4911exkind sRef_getOrigExKind (sRef s)
4912{
4913 if (sRef_isValid (s))
4914 {
4915 return (s->oexpkind);
4916 }
4917 else
4918 {
4919 return XO_UNKNOWN;
4920 }
4921}
4922
4923static void sRef_clearExKindAux (sRef s, fileloc loc)
4924{
28bf4b0b 4925 sRef_checkMutable (s);
616915dd 4926 sRef_setExKind (s, XO_UNKNOWN, loc);
4927}
4928
4929void sRef_setObserver (sRef s, fileloc loc)
4930{
28bf4b0b 4931 sRef_checkMutable (s);
616915dd 4932 sRef_setExKind (s, XO_OBSERVER, loc);
4933}
4934
4935void sRef_setExposed (sRef s, fileloc loc)
4936{
28bf4b0b 4937 sRef_checkMutable (s);
616915dd 4938 sRef_setExKind (s, XO_EXPOSED, loc);
4939}
4940
4941void sRef_clearExKindComplete (sRef s, fileloc loc)
4942{
4943 (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
4944}
4945
4946void sRef_setExKind (sRef s, exkind exp, fileloc loc)
4947{
28bf4b0b 4948 sRef_checkMutable (s);
4949
616915dd 4950 if (sRef_isValid (s))
4951 {
4952 if (s->expkind != exp)
4953 {
28bf4b0b 4954 s->expinfo = stateInfo_updateLoc (s->expinfo, loc);
616915dd 4955 }
4956
4957 s->expkind = exp;
4958 }
4959}
4960
4961/*
4962** s1->derived = s2->derived
4963*/
4964
4965static void sRef_copyRealDerived (sRef s1, sRef s2)
4966{
28bf4b0b 4967 DPRINTF (("Copy real: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
4968 sRef_checkMutable (s1);
4969
616915dd 4970 if (sRef_isValid (s1) && sRef_isValid (s2))
4971 {
4972 sRef sb = sRef_getRootBase (s1);
4973
4974 sRefSet_clear (s1->deriv);
4975
4976 sRefSet_allElements (s2->deriv, el)
4977 {
4978 if (sRef_isValid (el))
4979 {
4980 sRef rb = sRef_getRootBase (el);
4981
4982 if (!sRef_same (rb, sb))
4983 {
4984 sRef fb = sRef_fixDirectBase (el, s1);
4985
4986 if (sRef_isValid (fb))
4987 {
4988 sRef_copyRealDerived (fb, el);
4989 sRef_addDeriv (s1, fb);
4990 }
4991 }
4992 else
4993 {
4994 sRef_addDeriv (s1, el);
4995 }
4996 }
4997 } end_sRefSet_allElements ;
4998 }
4999
5000 }
5001
5002void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
5003{
5004 sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
5005}
5006
5007void sRef_setUndefined (sRef s, fileloc loc)
5008{
28bf4b0b 5009 sRef_checkMutable (s);
5010
616915dd 5011 if (sRef_isValid (s))
5012 {
5013 s->defstate = SS_UNDEFINED;
5014
5015 if (fileloc_isDefined (loc))
5016 {
28bf4b0b 5017 s->definfo = stateInfo_updateLoc (s->definfo, loc);
616915dd 5018 }
5019
5020 sRef_clearDerived (s);
5021 }
5022}
5023
5024static void sRef_setDefinedAux (sRef s, fileloc loc, bool clear)
5025{
28bf4b0b 5026 sRef_checkMutable (s);
616915dd 5027 if (sRef_isInvalid (s)) return;
5028
3120b462 5029 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5030
616915dd 5031 if (s->defstate != SS_DEFINED && fileloc_isDefined (loc))
5032 {
28bf4b0b 5033 s->definfo = stateInfo_updateLoc (s->definfo, loc);
616915dd 5034 }
5035
5036 s->defstate = SS_DEFINED;
5037
cd7d9b17 5038 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5039
616915dd 5040 /* e.g., if x is allocated, *x = 3 defines x */
5041
5042 if (s->kind == SK_PTR)
5043 {
5044 sRef p = s->info->ref;
3120b462 5045 sRef arr;
5046
5047 if (p->defstate == SS_ALLOCATED
5048 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
616915dd 5049 {
5050 sRef_setDefinedAux (p, loc, clear);
5051 }
3120b462 5052
5053 /*
5054 ** Defines a[0] also:
5055 */
5056
5057 arr = sRef_findDerivedArrayFetch (p, FALSE, 0, FALSE);
5058
5059 if (sRef_isValid (arr))
5060 {
5061 sRef_setDefinedAux (arr, loc, clear);
5062 }
616915dd 5063 }
5064 else if (s->kind == SK_ARRAYFETCH)
5065 {
5066 if (!s->info->arrayfetch->indknown
5067 || (s->info->arrayfetch->ind == 0))
5068 {
5069 sRef p = s->info->arrayfetch->arr;
5070 sRef ptr = sRef_constructPointer (p);
3120b462 5071
616915dd 5072 if (sRef_isValid (ptr))
5073 {
5074 if (ptr->defstate == SS_ALLOCATED
3120b462 5075 || ptr->defstate == SS_UNDEFINED
5076 || ptr->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
616915dd 5077 {
5078 sRef_setDefinedAux (ptr, loc, clear);
5079 }
5080 }
5081
5082 if (p->defstate == SS_RELDEF)
5083 {
5084 ;
5085 }
3120b462 5086 else if (p->defstate == SS_ALLOCATED || p->defstate == SS_PDEFINED
5087 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
616915dd 5088 {
5089 p->defstate = SS_DEFINED;
5090 }
5091 else
5092 {
5093 }
5094 }
5095 }
5096 else if (s->kind == SK_FIELD)
5097 {
5098 sRef parent = s->info->field->rec;
5099
5100 if (sRef_isValid (parent))
5101 {
5102 if (ctype_isUnion (ctype_realType (parent->type)))
5103 {
5104 /*
5105 ** Should not clear derived from here.
5106 */
5107
5108 sRef_setDefinedNoClear (parent, loc);
5109 }
5110 else
5111 {
5112 ; /* Nothing to do for structures. */
5113 }
5114 }
5115
5116 }
5117 else
5118 {
5119 ;
5120 }
5121
5122 if (clear)
5123 {
5124 sRef_clearDerived (s);
cd7d9b17 5125 }
5126 else
5127 {
5128 /* evans 2001-07-12: need to define the derived references */
5129 sRefSet_elements (s->deriv, el)
5130 {
5131 el->defstate = SS_DEFINED;
5132 } end_sRefSet_elements ;
5133 }
5134
5135 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
616915dd 5136}
5137
5138static void sRef_setPartialDefined (sRef s, fileloc loc)
5139{
28bf4b0b 5140 sRef_checkMutable (s);
5141
616915dd 5142 if (!sRef_isPartial (s))
5143 {
5144 sRef_setDefined (s, loc);
5145 }
5146}
5147
5148void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
5149{
5150 sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
5151}
5152
5153void sRef_setDefinedComplete (sRef s, fileloc loc)
5154{
3120b462 5155 DPRINTF (("Set defined complete: %s", sRef_unparseFull (s)));
616915dd 5156 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5157}
5158
5159void sRef_setDefined (sRef s, fileloc loc)
5160{
28bf4b0b 5161 sRef_checkMutable (s);
616915dd 5162 sRef_setDefinedAux (s, loc, TRUE);
5163}
5164
5165static void sRef_setDefinedNoClear (sRef s, fileloc loc)
5166{
28bf4b0b 5167 sRef_checkMutable (s);
616915dd 5168 DPRINTF (("Defining: %s", sRef_unparseFull (s)));
5169 sRef_setDefinedAux (s, loc, FALSE);
5170 DPRINTF (("==> %s", sRef_unparseFull (s)));
5171}
5172
5173void sRef_setDefinedNCComplete (sRef s, fileloc loc)
5174{
28bf4b0b 5175 sRef_checkMutable (s);
616915dd 5176 DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s)));
5177 sRef_innerAliasSetComplete (sRef_setDefinedNoClear, s, loc);
5178 DPRINTF (("==> %s", sRef_unparseFull (s)));
5179}
5180
5181static bool sRef_isDeepUnionField (sRef s)
5182{
5183 return (sRef_deepPred (sRef_isUnionField, s));
5184}
5185
5186bool sRef_isUnionField (sRef s)
5187{
5188 if (sRef_isValid (s) && s->kind == SK_FIELD)
5189 {
5190 /*
5191 ** defining one field of a union defines the union
5192 */
5193
5194 sRef base = s->info->field->rec;
5195
5196 if (sRef_isValid (base))
5197 {
5198 return (ctype_isUnion (ctype_realType (base->type)));
5199 }
5200 }
5201
5202 return FALSE;
5203}
5204
5205void sRef_setPdefined (sRef s, fileloc loc)
5206{
28bf4b0b 5207 sRef_checkMutable (s);
616915dd 5208 if (sRef_isValid (s) && !sRef_isPartial (s))
5209 {
5210 sRef base = sRef_getBaseSafe (s);
5211
5212 if (s->defstate == SS_ALLOCATED)
5213 {
5214 return;
5215 }
5216
5217 if (s->defstate != SS_PDEFINED && fileloc_isDefined (loc))
5218 {
28bf4b0b 5219 s->definfo = stateInfo_updateLoc (s->definfo, loc);
616915dd 5220 }
5221
28bf4b0b 5222 DPRINTF (("set pdefined: %s", sRef_unparseFull (s)));
616915dd 5223 s->defstate = SS_PDEFINED;
5224
5225 /* e.g., if x is allocated, *x = 3 defines x */
5226
5227 while (sRef_isValid (base) && sRef_isKnown (base))
5228 {
5229 if (base->defstate == SS_DEFINED)
5230 {
5231 sRef nb;
28bf4b0b 5232
5233 base->defstate = SS_PDEFINED;
616915dd 5234 nb = sRef_getBaseSafe (base);
5235 base = nb;
5236 }
5237 else
5238 {
5239 break;
5240 }
5241 }
5242 }
5243}
5244
5245static void sRef_setStateAux (sRef s, sstate ss, fileloc loc)
5246{
28bf4b0b 5247 sRef_checkMutable (s);
5248
616915dd 5249 if (sRef_isValid (s))
5250 {
5251 /* if (s->defstate == SS_RELDEF) return; */
5252
5253 if (s->defstate != ss && fileloc_isDefined (loc))
5254 {
28bf4b0b 5255 s->definfo = stateInfo_updateLoc (s->definfo, loc);
616915dd 5256 }
5257
5258 s->defstate = ss;
5259 sRef_clearDerived (s);
5260
5261 if (ss == SS_ALLOCATED)
5262 {
5263 sRef base = sRef_getBaseSafe (s);
5264
5265 while (sRef_isValid (base) && sRef_isKnown (base))
5266 {
5267 if (base->defstate == SS_DEFINED)
5268 {
5269 sRef nb;
5270
5271 base->defstate = SS_PDEFINED;
5272
5273 nb = sRef_getBaseSafe (base);
5274 base = nb;
5275 }
5276 else
5277 {
5278 break;
5279 }
5280 }
5281 }
5282
5283 }
5284}
5285
5286void sRef_setAllocatedComplete (sRef s, fileloc loc)
5287{
5288 sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
5289}
5290
5291static void sRef_setAllocatedShallow (sRef s, fileloc loc)
5292{
28bf4b0b 5293 sRef_checkMutable (s);
5294
616915dd 5295 if (sRef_isValid (s))
5296 {
5297 if (s->defstate == SS_DEAD || s->defstate == SS_UNDEFINED)
5298 {
5299 s->defstate = SS_ALLOCATED;
5300
5301 if (fileloc_isDefined (loc))
5302 {
28bf4b0b 5303 s->definfo = stateInfo_updateLoc (s->definfo, loc);
616915dd 5304 }
5305 }
5306 }
5307}
5308
5309void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
5310{
5311 sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
5312}
5313
5314void sRef_setAllocated (sRef s, fileloc loc)
5315{
28bf4b0b 5316 sRef_checkMutable (s);
616915dd 5317 sRef_setStateAux (s, SS_ALLOCATED, loc);
28bf4b0b 5318}
616915dd 5319
5320void sRef_setPartial (sRef s, fileloc loc)
5321{
28bf4b0b 5322 sRef_checkMutable (s);
616915dd 5323 sRef_setStateAux (s, SS_PARTIAL, loc);
28bf4b0b 5324}
616915dd 5325
5326void sRef_setShared (sRef s, fileloc loc)
5327{
28bf4b0b 5328 sRef_checkMutable (s);
5329
616915dd 5330 if (sRef_isValid (s))
5331 {
5332 if (s->aliaskind != AK_SHARED && fileloc_isDefined (loc))
5333 {
28bf4b0b 5334 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
616915dd 5335 }
5336
5337 s->aliaskind = AK_SHARED;
5338 /* don't! sRef_clearDerived (s); */
5339 }
5340}
5341
28bf4b0b 5342void sRef_setLastReference (sRef s, /*@exposed@*/ sRef ref, fileloc loc)
616915dd 5343{
28bf4b0b 5344 sRef_checkMutable (s);
5345
616915dd 5346 if (sRef_isValid (s))
5347 {
5348 s->aliaskind = sRef_getAliasKind (ref);
28bf4b0b 5349 s->aliasinfo = stateInfo_updateRefLoc (s->aliasinfo, ref, loc);
616915dd 5350 }
5351}
5352
5353static
5354void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
5355{
28bf4b0b 5356 DPRINTF (("Set null state: %s / %s", sRef_unparse (s), nstate_unparse (ns)));
5357 sRef_checkMutable (s);
5358 s->nullstate = ns;
5359
5360 if (fileloc_isDefined (loc))
5361 {
5362 s->nullinfo = stateInfo_updateLoc (s->nullinfo, loc);
5363 }
616915dd 5364}
5365
5366void sRef_setNotNull (sRef s, fileloc loc)
5367{
5368 if (sRef_isValid (s))
5369 {
5370 sRef_setNullStateAux (s, NS_NOTNULL, loc);
5371 }
5372}
5373
28bf4b0b 5374void sRef_setNullStateN (sRef s, nstate n)
5375{
5376 sRef_checkMutable (s);
5377 s->nullstate = n;
5378}
5379
616915dd 5380void sRef_setNullState (sRef s, nstate n, fileloc loc)
5381{
5382 if (sRef_isValid (s))
5383 {
5384 sRef_setNullStateAux (s, n, loc);
5385 }
5386}
5387
28bf4b0b 5388void sRef_setNullTerminatedStateInnerComplete (sRef s, struct s_bbufinfo b, /*@unused@*/ fileloc loc) {
616915dd 5389
5390 switch (b.bufstate) {
5391 case BB_NULLTERMINATED:
5392 sRef_setNullTerminatedState (s);
5393 sRef_setLen (s, b.len);
5394 break;
5395 case BB_POSSIBLYNULLTERMINATED:
5396 sRef_setPossiblyNullTerminatedState(s);
5397 break;
5398 case BB_NOTNULLTERMINATED:
5399 sRef_setNotNullTerminatedState (s);
5400 break;
5401 }
5402 sRef_setSize (s, b.size);
5403
5404 /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5405 * setNullStateInnerComplete.
5406 */
5407}
5408
5409void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5410{
28bf4b0b 5411 DPRINTF (("Set null state: %s", nstate_unparse (n)));
5412
616915dd 5413 sRef_setNullState (s, n, loc);
28bf4b0b 5414
616915dd 5415 switch (n)
5416 {
5417 case NS_POSNULL:
5418 sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5419 break;
5420 case NS_DEFNULL:
5421 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5422 break;
5423 case NS_UNKNOWN:
5424 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5425 break;
5426 case NS_NOTNULL:
5427 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5428 break;
5429 case NS_MNOTNULL:
5430 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5431 break;
5432 case NS_RELNULL:
5433 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5434 break;
5435 case NS_CONSTNULL:
5436 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5437 break;
5438 case NS_ABSNULL:
5439 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5440 break;
5441 case NS_ERROR:
5442 sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5443 break;
5444 }
5445}
5446
5447void sRef_setPosNull (sRef s, fileloc loc)
5448{
5449 if (sRef_isValid (s))
5450 {
5451 sRef_setNullStateAux (s, NS_POSNULL, loc);
5452 }
5453}
5454
5455void sRef_setDefNull (sRef s, fileloc loc)
5456{
5457 if (sRef_isValid (s))
5458 {
5459 sRef_setNullStateAux (s, NS_DEFNULL, loc);
5460 }
5461}
5462
5463void sRef_setNullUnknown (sRef s, fileloc loc)
5464{
5465 if (sRef_isValid (s))
5466 {
5467 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5468 }
5469}
5470
5471void sRef_setNullError (sRef s)
5472{
5473 if (sRef_isValid (s))
5474 {
5475 sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5476 }
5477}
5478
5479void sRef_setNullErrorLoc (sRef s, /*@unused@*/ fileloc loc)
5480{
5481 sRef_setNullError (s);
5482}
5483
5484void sRef_setOnly (sRef s, fileloc loc)
5485{
28bf4b0b 5486 sRef_checkMutable (s);
5487
616915dd 5488 if (sRef_isValid (s) && s->aliaskind != AK_ONLY)
5489 {
5490 s->aliaskind = AK_ONLY;
28bf4b0b 5491 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
616915dd 5492 }
5493}
5494
5495void sRef_setDependent (sRef s, fileloc loc)
5496{
28bf4b0b 5497 sRef_checkMutable (s);
5498
616915dd 5499 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5500 {
28bf4b0b 5501 DPRINTF (("Setting dependent: %s", sRef_unparseFull (s)));
616915dd 5502 s->aliaskind = AK_DEPENDENT;
28bf4b0b 5503 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5504 }
616915dd 5505}
5506
5507void sRef_setOwned (sRef s, fileloc loc)
5508{
28bf4b0b 5509 sRef_checkMutable (s);
5510
616915dd 5511 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5512 {
5513 s->aliaskind = AK_OWNED;
28bf4b0b 5514 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5515 }
616915dd 5516}
5517
5518void sRef_setKept (sRef s, fileloc loc)
5519{
28bf4b0b 5520 sRef_checkMutable (s);
5521
616915dd 5522 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5523 {
5524 sRef base = sRef_getBaseSafe (s);
5525
5526 while (sRef_isValid (base) && sRef_isKnown (base))
5527 {
5528 if (base->defstate == SS_DEFINED)
5529 {
5530 base->defstate = SS_PDEFINED;
5531 base = sRef_getBaseSafe (base);
5532 }
5533 else
5534 {
5535 break;
5536 }
5537
5538 }
5539
5540 s->aliaskind = AK_KEPT;
28bf4b0b 5541 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5542 }
616915dd 5543}
5544
5545static void sRef_setKeptAux (sRef s, fileloc loc)
5546{
5547 if (!sRef_isShared (s))
5548 {
5549 sRef_setKept (s, loc);
5550 }
5551}
5552
5553static void sRef_setDependentAux (sRef s, fileloc loc)
5554{
5555 if (!sRef_isShared (s))
5556 {
5557 sRef_setDependent (s, loc);
5558 }
5559}
5560
5561void sRef_setKeptComplete (sRef s, fileloc loc)
5562{
5563 sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5564}
5565
5566void sRef_setDependentComplete (sRef s, fileloc loc)
5567{
5568 sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5569}
5570
5571void sRef_setFresh (sRef s, fileloc loc)
5572{
28bf4b0b 5573 sRef_checkMutable (s);
5574
616915dd 5575 if (sRef_isValid (s))
5576 {
5577 s->aliaskind = AK_FRESH;
28bf4b0b 5578 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
616915dd 5579 }
5580}
5581
5582void sRef_kill (sRef s, fileloc loc)
5583{
5584 DPRINTF (("Kill: %s", sRef_unparseFull (s)));
28bf4b0b 5585 sRef_checkMutable (s);
616915dd 5586
5587 if (sRef_isValid (s) && !sRef_isShared (s) && !sRef_isConst (s))
5588 {
5589 sRef base = sRef_getBaseSafe (s);
5590
5591 while (sRef_isValid (base) && sRef_isKnown (base))
5592 {
5593 if (base->defstate == SS_DEFINED)
5594 {
5595 base->defstate = SS_PDEFINED;
5596 base = sRef_getBaseSafe (base);
5597 }
5598 else
5599 {
5600 break;
5601 }
616915dd 5602 }
5603
5604 s->aliaskind = s->oaliaskind;
5605 s->defstate = SS_DEAD;
28bf4b0b 5606 s->definfo = stateInfo_updateLoc (s->definfo, loc);
616915dd 5607
5608 sRef_clearDerived (s);
5609 }
5610}
5611
5612void sRef_maybeKill (sRef s, fileloc loc)
5613{
28bf4b0b 5614 sRef_checkMutable (s);
5615
616915dd 5616 if (sRef_isValid (s))
5617 {
5618 sRef base = sRef_getBaseSafe (s);
5619
5620
5621 while (sRef_isValid (base) && sRef_isKnown (base))
5622 {
5623 if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5624 {
5625 base->defstate = SS_PDEFINED;
28bf4b0b 5626 base = sRef_getBaseSafe (base);
616915dd 5627 }
5628 else
5629 {
28bf4b0b 5630 break;
616915dd 5631 }
5632
5633 }
5634
5635 s->aliaskind = s->oaliaskind;
5636 s->defstate = SS_HOFFA;
28bf4b0b 5637 s->definfo = stateInfo_updateLoc (s->definfo, loc);
616915dd 5638 sRef_clearDerived (s);
5639 }
5640
5641 }
5642
5643/*
5644** just for type checking...
5645*/
5646
5647static void sRef_killAux (sRef s, fileloc loc)
5648{
5649 if (sRef_isValid (s) && !sRef_isShared (s))
5650 {
5651 if (sRef_isUnknownArrayFetch (s))
5652 {
5653 sRef_maybeKill (s, loc);
5654 }
5655 else
5656 {
28bf4b0b 5657 sRef_kill (s, loc);
5658 }
616915dd 5659 }
5660}
5661
5662/*
5663** kills s and all aliases to s
5664*/
5665
5666void sRef_killComplete (sRef s, fileloc loc)
5667{
5668 DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5669 sRef_aliasSetComplete (sRef_killAux, s, loc);
5670}
5671
5672static bool sRef_equivalent (sRef s1, sRef s2)
5673{
5674 return (sRef_compare (s1, s2) == 0);
5675}
5676
5677/*
5678** returns an sRef that will not be free'd on function exit.
5679*/
5680
5681/*@only@*/ sRef sRef_saveCopy (sRef s)
5682{
5683 sRef ret;
5684
5685 if (sRef_isValid (s))
5686 {
5687 bool old = inFunction;
5688
5689 /*
5690 ** Exit the function scope, so this sRef is not
5691 ** stored in the deallocation table.
5692 */
5693
5694 inFunction = FALSE;
5695 DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5696 ret = sRef_copy (s);
5697 DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5698 inFunction = old;
5699 }
5700 else
5701 {
5702 ret = sRef_undefined;
5703 }
5704
5705 /*@-dependenttrans@*/
5706 return ret;
5707 /*@=dependenttrans@*/
5708}
5709
5710sRef sRef_copy (sRef s)
5711{
28bf4b0b 5712 if (sRef_isKindSpecial (s) && !sRef_isGlobalMarker (s))
616915dd 5713 {
5714 /*@-retalias@*/
28bf4b0b 5715 return s; /* don't copy specials (except for global markers) */
616915dd 5716 /*@=retalias@*/
5717 }
28bf4b0b 5718
616915dd 5719 if (sRef_isValid (s))
5720 {
5721 sRef t = sRef_alloc ();
5722
28bf4b0b 5723 DPRINTF (("Copying: [%p] %s", s, sRef_unparse (s)));
5724 DPRINTF (("Full: %s", sRef_unparseFull (s)));
5725
616915dd 5726 t->kind = s->kind;
5727 t->safe = s->safe;
5728 t->modified = s->modified;
28bf4b0b 5729 t->immut = FALSE; /* Note mutability is not copied. */
616915dd 5730 t->type = s->type;
b9904f57 5731 t->val = multiVal_copy (s->val);
616915dd 5732
28bf4b0b 5733 t->info = sinfo_copy (s);
616915dd 5734 t->defstate = s->defstate;
616915dd 5735 t->nullstate = s->nullstate;
5736
5737 /* start modifications */
5738 t->bufinfo.bufstate = s->bufinfo.bufstate;
5739 t->bufinfo.len = s->bufinfo.len;
5740 t->bufinfo.size = s->bufinfo.size;
5741 /* end modifications */
5742
5743 t->aliaskind = s->aliaskind;
5744 t->oaliaskind = s->oaliaskind;
5745
5746 t->expkind = s->expkind;
5747 t->oexpkind = s->oexpkind;
5748
28bf4b0b 5749 t->nullinfo = stateInfo_copy (s->nullinfo);
5750 t->aliasinfo = stateInfo_copy (s->aliasinfo);
5751 t->definfo = stateInfo_copy (s->definfo);
5752 t->expinfo = stateInfo_copy (s->expinfo);
616915dd 5753
5754 t->deriv = sRefSet_newDeepCopy (s->deriv);
28bf4b0b 5755 t->state = valueTable_copy (s->state);
5756
5757 DPRINTF (("Made copy: [%p] %s", t, sRef_unparse (t)));
616915dd 5758 return t;
5759 }
5760 else
5761 {
5762 return sRef_undefined;
5763 }
5764}
5765
5766/*@notfunction@*/
5767# define PREDTEST(func,s) \
5768 do { if (sRef_isInvalid (s)) { return FALSE; } \
5769 else { if (sRef_isConj (s)) \
5770 { return (func (sRef_getConjA (s)) \
5771 || func (sRef_getConjB (s))); }}} while (FALSE);
5772
5773bool sRef_isAddress (sRef s)
5774{
5775 PREDTEST (sRef_isAddress, s);
5776 return (s->kind == SK_ADR);
5777}
5778
5779/*
5780** pretty weak... maybe a flag should control this.
5781*/
5782
5783bool sRef_isThroughArrayFetch (sRef s)
5784{
5785 if (sRef_isValid (s))
5786 {
5787 sRef tref = s;
5788
5789 do
5790 {
5791 sRef lt;
5792
5793 if (sRef_isArrayFetch (tref))
5794 {
28bf4b0b 5795 return TRUE;
616915dd 5796 }
5797
5798 lt = sRef_getBase (tref);
5799 tref = lt;
5800 } while (sRef_isValid (tref));
5801 }
5802
5803 return FALSE;
5804}
5805
5806bool sRef_isArrayFetch (sRef s)
5807{
5808 PREDTEST (sRef_isArrayFetch, s);
5809 return (s->kind == SK_ARRAYFETCH);
5810}
5811
5812bool sRef_isMacroParamRef (sRef s)
5813{
5814 if (context_inMacro () && sRef_isCvar (s))
5815 {
5816 uentry ue = sRef_getUentry (s);
5817 cstring pname = makeParam (uentry_rawName (ue));
5818 uentry mac = usymtab_lookupSafe (pname);
5819
5820 cstring_free (pname);
5821 return (uentry_isValid (mac));
5822 }
5823
5824 return FALSE;
5825}
5826
5827bool sRef_isCvar (sRef s)
5828{
5829 PREDTEST (sRef_isCvar, s);
5830 return (s->kind == SK_CVAR);
5831}
5832
5833bool sRef_isConst (sRef s)
5834{
5835 PREDTEST (sRef_isConst, s);
5836 return (s->kind == SK_CONST);
5837}
5838
5839bool sRef_isObject (sRef s)
5840{
5841 PREDTEST (sRef_isObject, s);
5842 return (s->kind == SK_OBJECT);
5843}
5844
5845bool sRef_isExternal (sRef s)
5846{
5847 PREDTEST (sRef_isExternal, s);
5848 return (s->kind == SK_EXTERNAL);
5849}
5850
5851static bool sRef_isDerived (sRef s)
5852{
5853 PREDTEST (sRef_isDerived, s);
5854 return (s->kind == SK_DERIVED);
5855}
5856
5857bool sRef_isField (sRef s)
5858{
5859 PREDTEST (sRef_isField, s);
5860 return (s->kind == SK_FIELD);
5861}
5862
5863static bool sRef_isIndex (sRef s)
5864{
5865 PREDTEST (sRef_isIndex, s);
5866 return (s->kind == SK_ARRAYFETCH);
5867}
5868
5869bool sRef_isAnyParam (sRef s)
5870{
5871 PREDTEST (sRef_isAnyParam, s);
5872 return (s->kind == SK_PARAM);
5873}
5874
5875bool sRef_isParam (sRef s)
5876{
5877 PREDTEST (sRef_isParam, s);
5878 return (s->kind == SK_PARAM);
5879}
5880
5881bool sRef_isDirectParam (sRef s)
5882{
5883 PREDTEST (sRef_isDirectParam, s);
5884
5885 return ((s->kind == SK_CVAR) &&
5886 (s->info->cvar->lexlevel == functionScope) &&
5887 (context_inFunction () &&
5888 (s->info->cvar->index <= uentryList_size (context_getParams ()))));
5889}
5890
5891bool sRef_isPointer (sRef s)
5892{
5893 PREDTEST (sRef_isPointer, s);
5894 return (s->kind == SK_PTR);
5895}
5896
5897/*
5898** returns true if storage referenced by s is visible
5899*/
5900
5901bool sRef_isReference (sRef s)
5902{
5903 PREDTEST (sRef_isReference, s);
5904
28bf4b0b 5905 return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isFileOrGlobalScope (s)
616915dd 5906 || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
5907}
5908
5909bool sRef_isIReference (sRef s)
5910{
5911 return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
5912 || sRef_isField (s) || sRef_isArrayFetch (s));
5913}
5914
28bf4b0b 5915bool sRef_isFileOrGlobalScope (sRef s)
616915dd 5916{
5917 return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
5918}
5919
5920bool sRef_isRealGlobal (sRef s)
5921{
5922 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
5923}
5924
5925bool sRef_isFileStatic (sRef s)
5926{
5927 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
5928}
5929
5930bool sRef_isAliasCheckedGlobal (sRef s)
5931{
28bf4b0b 5932 if (sRef_isFileOrGlobalScope (s))
616915dd 5933 {
5934 uentry ue = sRef_getUentry (s);
5935
5936 return context_checkAliasGlob (ue);
5937 }
5938 else
5939 {
5940 return FALSE;
5941 }
5942}
5943
5944void sRef_free (/*@only@*/ sRef s)
5945{
5946 if (s != sRef_undefined && s->kind != SK_SPECIAL)
5947 {
28bf4b0b 5948 DPRINTF (("Free sref: [%p]", s));
5949
5950 sRef_checkValid (s);
5951
5952 stateInfo_free (s->expinfo);
5953 stateInfo_free (s->aliasinfo);
5954 stateInfo_free (s->definfo);
5955 stateInfo_free (s->nullinfo);
5956
616915dd 5957 sRefSet_free (s->deriv);
5958 s->deriv = sRefSet_undefined;
28bf4b0b 5959
5960 /*@i43@*/ /* valueTable_free (s->state); */
616915dd 5961 sinfo_free (s);
5962
795e7f34 5963
5964 /* drl added to help locate use after release*/
5965 s->expinfo = stateInfo_undefined;
5966 s->aliasinfo = stateInfo_undefined;
5967 s->definfo = stateInfo_undefined;
5968 s->nullinfo = stateInfo_undefined;
5969
5970 /*@i32@*/ sfree (s);
616915dd 5971 }
5972}
5973
5974void sRef_setType (sRef s, ctype t)
5975{
28bf4b0b 5976 sRef_checkMutable (s);
5977
616915dd 5978 if (sRef_isValid (s))
5979 {
5980 s->type = t;
5981 }
5982}
5983
5984void sRef_setTypeFull (sRef s, ctype t)
5985{
28bf4b0b 5986 sRef_checkMutable (s);
5987
616915dd 5988 if (sRef_isValid (s))
5989 {
5990 s->type = t;
5991
5992 sRefSet_allElements (s->deriv, current)
5993 {
5994 sRef_setTypeFull (current, ctype_unknown);
5995 } end_sRefSet_allElements ;
5996 }
5997}
5998
5999/*@exposed@*/ sRef
28bf4b0b 6000 sRef_buildField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
616915dd 6001{
6002 return (sRef_buildNCField (rec, f));
6003}
6004
6005static /*@exposed@*/ sRef
6006sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
6007{
6008 sRefSet_allElements (rec->deriv, sr)
6009 {
6010 if (sRef_isValid (sr))
6011 {
28bf4b0b 6012 if (sr->info != NULL)
616915dd 6013 {
28bf4b0b 6014 if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
6015 {
6016 return sr;
6017 }
616915dd 6018 }
6019 }
6020 } end_sRefSet_allElements;
6021
6022 return sRef_undefined;
6023}
6024
28bf4b0b 6025/*@dependent@*/ /*@observer@*/ sRefSet sRef_derivedFields (/*@temp@*/ sRef rec)
616915dd 6026{
6027 if (sRef_isValid (rec))
6028 {
6029 sRefSet ret;
6030 ret = rec->deriv;
6031 return (ret);
6032 }
6033 else
6034 {
6035 return (sRefSet_undefined);
6036 }
6037}
6038
6039static /*@exposed@*/ sRef
6040 sRef_findDerivedPointer (sRef s)
6041{
6042 if (sRef_isValid (s))
6043 {
6044 sRefSet_realElements (s->deriv, sr)
6045 {
6046 if (sRef_isValid (sr) && sr->kind == SK_PTR)
6047 {
6048 return sr;
6049 }
6050 } end_sRefSet_realElements;
6051 }
6052
6053 return sRef_undefined;
6054}
6055
6056bool
6057sRef_isUnknownArrayFetch (sRef s)
6058{
6059 return (sRef_isValid (s)
6060 && s->kind == SK_ARRAYFETCH
6061 && !s->info->arrayfetch->indknown);
6062}
6063
6064static /*@exposed@*/ sRef
6065sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
6066{
6067
6068 if (isknown)
6069 {
6070 sRefSet_realElements (s->deriv, sr)
6071 {
6072 if (sRef_isValid (sr)
6073 && sr->kind == SK_ARRAYFETCH
6074 && sr->info->arrayfetch->indknown
6075 && (sr->info->arrayfetch->ind == idx))
6076 {
6077 return sr;
6078 }
6079 } end_sRefSet_realElements;
6080 }
6081 else
6082 {
6083 sRefSet_realElements (s->deriv, sr)
6084 {
6085 if (sRef_isValid (sr)
6086 && sr->kind == SK_ARRAYFETCH
6087 && (!sr->info->arrayfetch->indknown
6088 || (sr->info->arrayfetch->indknown &&
6089 sr->info->arrayfetch->ind == 0)))
6090 {
6091 if (sRef_isDead (sr) || sRef_isKept (sr))
6092 {
6093 if (dead || context_getFlag (FLG_STRICTUSERELEASED))
6094 {
6095 return sr;
6096 }
6097 }
6098 else
6099 {
6100 return sr;
6101 }
6102 }
6103 } end_sRefSet_realElements;
6104 }
6105
6106 return sRef_undefined;
6107}
6108
6109static /*@exposed@*/ sRef
6110sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
6111{
6112 sRef s;
6113
28bf4b0b 6114 DPRINTF (("Build nc field: %s / %s",
6115 sRef_unparseFull (rec), f));
6116
616915dd 6117 if (sRef_isInvalid (rec))
6118 {
6119 return sRef_undefined;
6120 }
6121
6122 /*
6123 ** check if the field already has been referenced
6124 */
6125
6126 s = sRef_findDerivedField (rec, f);
6127
6128 if (sRef_isValid (s))
6129 {
28bf4b0b 6130 return s;
616915dd 6131 }
6132 else
6133 {
6134 ctype ct = ctype_realType (rec->type);
6135
28bf4b0b 6136 DPRINTF (("Field of: %s", sRef_unparse (rec)));
6137
6138 s = sRef_newRef ();
616915dd 6139 s->kind = SK_FIELD;
6140 s->info = (sinfo) dmalloc (sizeof (*s->info));
6141 s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
28bf4b0b 6142 s->info->field->rec = rec; /* sRef_copy (rec); */ /*@i32@*/
616915dd 6143 s->info->field->field = f; /* doesn't copy f */
6144
616915dd 6145 if (ctype_isKnown (ct) && ctype_isSU (ct))
6146 {
6147 uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
6148
6149 if (!uentry_isUndefined (ue))
6150 {
28bf4b0b 6151 DPRINTF (("lookup: %s for %s", uentry_unparseFull (ue),
6152 ctype_unparse (ct)));
6153
616915dd 6154 s->type = uentry_getType (ue);
6155
6156 if (ctype_isMutable (s->type)
6157 && rec->aliaskind != AK_STACK
6158 && !alkind_isStatic (rec->aliaskind))
6159 {
6160 s->aliaskind = rec->aliaskind;
6161 }
6162 else
6163 {
6164 s->aliaskind = AK_UNKNOWN;
6165 }
6166
6167 if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec)
6168 || sRef_isPdefined (rec))
6169 {
28bf4b0b 6170 sRef_setStateFromUentry (s, ue);
6171 }
616915dd 6172 else
6173 {
6174 sRef_setPartsFromUentry (s, ue);
28bf4b0b 6175 }
6176
616915dd 6177 s->oaliaskind = s->aliaskind;
6178 s->oexpkind = s->expkind;
28bf4b0b 6179
6180 DPRINTF (("sref: %s", sRef_unparseFull (s)));
616915dd 6181 }
6182 else
6183 {
6184 /*
6185 Never report this as an error. It can happen whenever there
6186 is casting involved.
6187
6188 if (report)
6189 {
6190 llcontbug (message ("buildNCField --- no field %s: %q / %s",
6191 f, sRef_unparse (s), ctype_unparse (ct)));
6192 }
6193 */
6194
6195 return sRef_undefined;
6196 }
6197 }
6198
6199 if (rec->defstate == SS_DEFINED
6200 && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
6201 {
6202 s->defstate = SS_DEFINED;
6203 }
6204 else if (rec->defstate == SS_PARTIAL)
6205 {
6206 s->defstate = SS_PARTIAL;
6207 }
6208 else if (rec->defstate == SS_ALLOCATED)
6209 {
6210 if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
6211 {
6212 s->defstate = SS_ALLOCATED;
6213 }
6214 else
6215 {
6216 s->defstate = SS_UNDEFINED;
6217 }
6218 }
6219 else if (s->defstate == SS_UNKNOWN)
6220 {
6221 s->defstate = rec->defstate;
6222 }
6223 else
6224 {
6225 ; /* no change */
6226 }
6227
6228 if (s->defstate == SS_UNDEFINED)
6229 {
6230 ctype rt = ctype_realType (s->type);
6231
6232 if (ctype_isArray (rt) || ctype_isSU (rt))
6233 {
28bf4b0b 6234 s->defstate = SS_ALLOCATED;
616915dd 6235 }
6236 }
6237
6238 sRef_addDeriv (rec, s);
28bf4b0b 6239 DPRINTF (("Add deriv: %s", sRef_unparseFull (rec)));
616915dd 6240
6241 if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
6242 {
6243 s->aliaskind = AK_REFS;
6244 s->oaliaskind = AK_REFS;
6245 }
6246
28bf4b0b 6247 DPRINTF (("Build field ==> %s", sRef_unparseFull (s)));
6248 return s;
616915dd 6249 }
6250}
6251
6252bool
6253sRef_isStackAllocated (sRef s)
6254{
6255 return (sRef_isValid(s)
6256 && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
6257}
6258
6259static
6260void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s,
6261 /*@notnull@*/ /*@exposed@*/ sRef arr)
6262{
28bf4b0b 6263 sRef_checkMutable (s);
6264
616915dd 6265 if (ctype_isRealAP (arr->type))
6266 {
6267 s->type = ctype_baseArrayPtr (arr->type);
6268 }
6269
6270 /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
6271 if (sRef_isAddress (arr))
6272 {
6273 sRef t = arr->info->ref;
6274
6275 if (sRef_isArrayFetch (t))
6276 {
6277 s->info->arrayfetch->arr = t->info->arrayfetch->arr;
6278 }
6279 }
6280 else if (ctype_isRealPointer (arr->type))
6281 {
6282 sRef sp = sRef_findDerivedPointer (arr);
616915dd 6283
6284 if (sRef_isValid (sp))
6285 {
6286
6287 if (ctype_isMutable (s->type))
6288 {
6289 sRef_setExKind (s, sRef_getExKind (sp), fileloc_undefined);
616915dd 6290
6291 s->aliaskind = sp->aliaskind;
6292 }
6293
6294 s->defstate = sp->defstate;
6295
6296 if (s->defstate == SS_DEFINED)
6297 {
6298 if (!context_getFlag (FLG_STRICTDESTROY))
6299 {
6300 s->defstate = SS_PARTIAL;
6301 }
6302 }
6303
28bf4b0b 6304 sRef_setNullStateN (s, sRef_getNullState (sp));
616915dd 6305 }
6306 else
6307 {
6308 if (arr->defstate == SS_UNDEFINED)
6309 {
6310 s->defstate = SS_UNUSEABLE;
6311 }
6312 else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
6313 {
6314 s->defstate = SS_UNDEFINED;
6315 }
6316 else
6317 {
6318 if (!context_getFlag (FLG_STRICTDESTROY))
6319 {
6320 s->defstate = SS_PARTIAL;
6321 }
6322 else
6323 {
6324 s->defstate = SS_DEFINED;
6325 }
6326
6327 /*
6328 ** Very weak checking for array elements.
6329 ** Was:
6330 ** s->defstate = arr->defstate;
6331 */
6332 }
6333
6334 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6335
6336 if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
6337 {
6338 s->aliaskind = AK_LOCAL;
6339 }
6340 else
6341 {
6342 s->aliaskind = AK_UNKNOWN;
6343 }
6344
6345 sRef_setTypeState (s);
6346 }
6347 }
6348 else
6349 {
6350 if (arr->defstate == SS_DEFINED)
6351 {
6352 /*
6353 ** Very weak checking for array elements.
6354 ** Was:
6355 ** s->defstate = arr->defstate;
6356 */
6357
6358 if (context_getFlag (FLG_STRICTDESTROY))
6359 {
6360 s->defstate = SS_DEFINED;
6361 }
6362 else
6363 {
6364 s->defstate = SS_PARTIAL;
6365 }
6366 }
6367 else if (arr->defstate == SS_ALLOCATED)
6368 {
6369 if (ctype_isRealArray (s->type))
6370 {
6371 s->defstate = SS_ALLOCATED;
6372 }
6373 else
6374 {
6375 if (!s->info->arrayfetch->indknown)
6376 {
6377 /*
6378 ** is index is unknown, elements is defined or
6379 ** allocated is any element is!
6380 */
6381
6382 s->defstate = SS_UNDEFINED;
6383
6384 sRefSet_allElements (arr->deriv, sr)
6385 {
6386 if (sRef_isValid (sr))
6387 {
6388 if (sr->defstate == SS_ALLOCATED)
6389 {
6390 s->defstate = SS_ALLOCATED;
6391 }
6392 else
6393 {
6394 if (sr->defstate == SS_DEFINED)
6395 {
6396 if (context_getFlag (FLG_STRICTDESTROY))
6397 {
6398 s->defstate = SS_DEFINED;
6399 }
6400 else
6401 {
6402 s->defstate = SS_PARTIAL;
6403 }
6404
6405 break;
6406 }
6407 }
6408 }
6409 } end_sRefSet_allElements;
6410
6411 }
6412 else
6413 {
6414 s->defstate = SS_UNDEFINED;
6415 }
6416 }
6417 }
6418 else
6419 {
6420 s->defstate = arr->defstate;
6421 }
6422
6423
6424 /*
6425 ** kludgey way to guess where aliaskind applies
6426 */
6427
6428 if (ctype_isMutable (s->type)
6429 && !ctype_isPointer (arr->type)
6430 && !alkind_isStatic (arr->aliaskind)
6431 && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6432 {
6433 s->aliaskind = arr->aliaskind;
6434 }
6435 else
6436 {
6437 s->aliaskind = AK_UNKNOWN;
6438 }
6439
6440 sRef_setTypeState (s);
6441 }
6442
6443 if (sRef_isObserver (arr))
6444 {
6445 s->expkind = XO_OBSERVER;
6446 }
6447}
6448
6449/*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6450{
6451 sRef s;
6452
6453 if (!sRef_isValid (arr)) {
6454 /*@-nullret@*/ return arr /*@=nullret@*/;
6455 }
6456
6457 if (ctype_isRealPointer (arr->type))
6458 {
6459 (void) sRef_buildPointer (arr); /* do this to define arr! */
6460 }
6461
6462 s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6463
6464 if (sRef_isValid (s))
6465 {
3120b462 6466 /* evans 2001-07-12: this is bogus, clean-up hack */
6467 if (s->info->arrayfetch->arr != arr)
6468 {
6469 sRef res;
6470 check (sRefSet_delete (arr->deriv, s));
6471 res = sRef_buildArrayFetch (arr);
6472 sRef_copyState (res, s);
6473 return res;
6474 }
6475
616915dd 6476 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6477 return s;
6478 }
6479 else
6480 {
28bf4b0b 6481 s = sRef_newRef ();
616915dd 6482
6483 s->kind = SK_ARRAYFETCH;
6484 s->info = (sinfo) dmalloc (sizeof (*s->info));
6485 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6486 s->info->arrayfetch->indknown = FALSE;
6487 s->info->arrayfetch->ind = 0;
28bf4b0b 6488 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
616915dd 6489 sRef_setArrayFetchState (s, arr);
6490 s->oaliaskind = s->aliaskind;
6491 s->oexpkind = s->expkind;
6492
6493 if (!context_inProtectVars ())
6494 {
6495 sRef_addDeriv (arr, s);
6496 }
6497
ccf0a4a8 6498 if (valueTable_isUndefined (s->state))
6499 {
6970c11b 6500 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
ccf0a4a8 6501 }
28bf4b0b 6502
616915dd 6503 return (s);
6504 }
6505}
6506
6507/*@exposed@*/ sRef
6508 sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6509{
6510 sRef s;
6511
6512 if (!sRef_isValid (arr)) {
6513 /*@-nullret@*/ return arr /*@=nullret@*/;
6514 }
6515
6516 if (ctype_isRealPointer (arr->type))
6517 {
6518 (void) sRef_buildPointer (arr); /* do this to define arr! */
6519 }
6520
6521 s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6522
6523 if (sRef_isValid (s))
6524 {
3120b462 6525 /* evans 2001-07-12: this is bogus, clean-up hack */
6526 if (s->info->arrayfetch->arr != arr)
6527 {
6528 sRef res;
6529 check (sRefSet_delete (arr->deriv, s));
6530 res = sRef_buildArrayFetchKnown (arr, i);
6531 sRef_copyState (res, s);
6532 return res;
6533 }
6534
616915dd 6535 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
3120b462 6536
6537 llassert (s->info->arrayfetch->arr == arr);
616915dd 6538 return s;
6539 }
6540 else
6541 {
28bf4b0b 6542 s = sRef_newRef ();
616915dd 6543
6544 s->kind = SK_ARRAYFETCH;
6545 s->info = (sinfo) dmalloc (sizeof (*s->info));
6546 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
28bf4b0b 6547 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
616915dd 6548 s->info->arrayfetch->indknown = TRUE;
6549 s->info->arrayfetch->ind = i;
6550
6551 sRef_setArrayFetchState (s, arr);
6552
6553 s->oaliaskind = s->aliaskind;
6554 s->oexpkind = s->expkind;
6555 sRef_addDeriv (arr, s);
6556
28bf4b0b 6557 llassert (valueTable_isUndefined (s->state));
6970c11b 6558 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
28bf4b0b 6559
616915dd 6560 return (s);
6561 }
6562}
6563
6564/*
6565** sets everything except for defstate
6566*/
6567
6568static void
6569sRef_setPartsFromUentry (sRef s, uentry ue)
28bf4b0b 6570{
6571 sRef uref = uentry_getSref (ue);
6572
616915dd 6573 llassert (sRef_isValid (s));
6574
6575 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6576 s->oaliaskind = s->aliaskind;
6577
6578 if (s->expkind == XO_UNKNOWN)
6579 {
6580 s->expkind = uentry_getExpKind (ue);
6581 }
28bf4b0b 6582
616915dd 6583 s->oexpkind = s->expkind;
28bf4b0b 6584
6585 if (sRef_getNullState (s) == NS_UNKNOWN)
6586 {
6587 DPRINTF (("Setting null state!"));
6588 sRef_setNullStateN (s, sRef_getNullState (uentry_getSref (ue)));
6589 }
6590 else
616915dd 6591 {
28bf4b0b 6592 DPRINTF (("Skipping null null state!"));
616915dd 6593 }
6594
28bf4b0b 6595 if (s->aliaskind == AK_IMPONLY && (sRef_isExposed (s) || sRef_isObserver (s)))
616915dd 6596 {
6597 s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
28bf4b0b 6598 }
616915dd 6599
28bf4b0b 6600 if (sRef_isValid (uref))
6601 {
6602 valueTable utable = uref->state;
6603 valueTable_free (s->state);
6604 s->state = valueTable_copy (utable);
6605 }
616915dd 6606}
6607
6608static void
6609sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6610{
6611 llassert (sRef_isValid (s));
28bf4b0b 6612 sRef_checkMutable (s);
6613
616915dd 6614 sRef_setPartsFromUentry (s, ue);
6615
6616 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6617 s->oaliaskind = s->aliaskind;
6618
6619 if (s->expkind == XO_UNKNOWN)
6620 {
6621 s->expkind = uentry_getExpKind (ue);
6622 }
6623
6624 s->oexpkind = s->expkind;
6625}
6626
6627void
6628sRef_setStateFromUentry (sRef s, uentry ue)
6629{
6630 sstate defstate;
6631
28bf4b0b 6632 sRef_checkMutable (s);
616915dd 6633 llassert (sRef_isValid (s));
6634
6635 sRef_setPartsFromUentry (s, ue);
6636
6637 defstate = uentry_getDefState (ue);
6638
6639 if (sstate_isKnown (defstate))
6640 {
6641 s->defstate = defstate;
6642 }
6643 else
6644 {
6645 ;
6646 }
6647}
6648
6649/*@exposed@*/ sRef
6650 sRef_buildPointer (/*@exposed@*/ sRef t)
6651{
6652 DPRINTF (("build pointer: %s", sRef_unparse (t)));
6653
6654 if (sRef_isInvalid (t)) return sRef_undefined;
6655
6656 if (sRef_isAddress (t))
6657 {
6658 DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6659 return (t->info->ref);
6660 }
6661 else
6662 {
6663 sRef s = sRef_findDerivedPointer (t);
6664
6665 DPRINTF (("find derived: %s", sRef_unparse (s)));
6666
6667 if (sRef_isValid (s))
6668 {
6669
6670 sRef_setExKind (s, sRef_getExKind (t), g_currentloc);
6671 s->oaliaskind = s->aliaskind;
6672 s->oexpkind = s->expkind;
6673
6674 return s;
6675 }
6676 else
6677 {
6678 s = sRef_constructPointerAux (t);
6679
6680 DPRINTF (("construct: %s", sRef_unparse (s)));
6681
6682 if (sRef_isValid (s))
6683 {
6684 sRef_addDeriv (t, s);
6685
6686 s->oaliaskind = s->aliaskind;
6687 s->oexpkind = s->expkind;
6688 }
6689
6690 return s;
6691 }
6692 }
6693}
6694
6695/*@exposed@*/ sRef
28bf4b0b 6696sRef_constructPointer (/*@exposed@*/ sRef t)
616915dd 6697 /*@modifies t@*/
6698{
6699 return sRef_buildPointer (t);
6700}
6701
6702static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6703{
6704 if (sRef_isValid (t))
6705 {
6706 sRef s;
6707
6708 /*
6709 ** if there is a derived t[?], return that. Otherwise, *t.
6710 */
6711
616915dd 6712 s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6713
6714 if (sRef_isValid (s))
6715 {
3120b462 6716 DPRINTF (("Found array fetch: %s", sRef_unparseFull (s)));
28bf4b0b 6717 return s;
616915dd 6718 }
6719 else
6720 {
6721 sRef ret = sRef_constructPointer (t);
6722
3120b462 6723 DPRINTF (("Constructed pointer: %s", sRef_unparseFull (ret)));
616915dd 6724
3120b462 6725 return ret;
616915dd 6726 }
6727 }
6728 else
6729 {
6730 return sRef_undefined;
6731 }
6732}
6733
6734sRef sRef_constructDeref (sRef t)
6735{
6736 return sRef_constructDerefAux (t, FALSE);
6737}
6738
6739sRef sRef_constructDeadDeref (sRef t)
6740{
6741 return sRef_constructDerefAux (t, TRUE);
6742}
6743
6744static sRef
6745sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6746{
28bf4b0b 6747 sRef s = sRef_newRef ();
616915dd 6748 ctype rt = t->type;
6749 ctype st;
6750
ccf0a4a8 6751 llassert (valueTable_isUndefined (s->state));
6752
616915dd 6753 s->kind = SK_PTR;
6754 s->info = (sinfo) dmalloc (sizeof (*s->info));
28bf4b0b 6755 s->info->ref = t; /* sRef_copy (t); */ /*@i32*/
616915dd 6756
6757 if (ctype_isRealAP (rt))
6758 {
6759 s->type = ctype_baseArrayPtr (rt);
6760 }
6761
28bf4b0b 6762 st = ctype_realType (s->type);
ccf0a4a8 6763
616915dd 6764 if (t->defstate == SS_UNDEFINED)
6765 {
6766 s->defstate = SS_UNUSEABLE;
6767 }
6768 else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6769 {
6770 s->defstate = SS_UNDEFINED;
6771 }
6772 else
6773 {
6774 s->defstate = t->defstate;
6775 }
6776
6777 if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6778 {
6779 s->aliaskind = AK_LOCAL;
6780 }
6781 else
6782 {
6783 s->aliaskind = AK_UNKNOWN;
6784 }
ccf0a4a8 6785
616915dd 6786 sRef_setExKind (s, sRef_getExKind (t), fileloc_undefined);
6787 sRef_setTypeState (s);
ccf0a4a8 6788
616915dd 6789 s->oaliaskind = s->aliaskind;
6790 s->oexpkind = s->expkind;
6791
ccf0a4a8 6792 if (valueTable_isUndefined (s->state))
6793 {
6970c11b 6794 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
ccf0a4a8 6795 }
6796
616915dd 6797 return s;
6798}
6799
6800bool sRef_hasDerived (sRef s)
6801{
6802 return (sRef_isValid (s) && !sRefSet_isEmpty (s->deriv));
6803}
6804
6805void
6806sRef_clearDerived (sRef s)
6807{
6808 if (sRef_isValid (s))
6809 {
28bf4b0b 6810 sRefSet_clear (s->deriv);
616915dd 6811 }
6812}
6813
6814void
6815sRef_clearDerivedComplete (sRef s)
6816{
6817
6818 if (sRef_isValid (s))
6819 {
6820 sRef base = sRef_getBaseSafe (s);
6821
6822 while (sRef_isValid (base))
6823 {
6824 sRefSet_clear (base->deriv);
6825 base = sRef_getBaseSafe (base);
6826 }
6827
6828 sRefSet_clear (s->deriv);
6829 }
6830}
6831
28bf4b0b 6832/*@exposed@*/ sRef sRef_makePointer (/*@exposed@*/ sRef s)
6833 /*@modifies s@*/
616915dd 6834{
6835 sRef res = sRef_buildPointer (s);
6836
6837 DPRINTF (("Res: %s", sRef_unparse (res)));
6838 return res;
6839}
6840
6841/*
6842** &a[] => a (this is for out params)
6843*/
6844
6845/*@exposed@*/ sRef
6846sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
6847{
6848
6849 if (sRef_isAddress (arr))
6850 {
28bf4b0b 6851 return (arr->info->ref);
616915dd 6852 }
6853 else
6854 {
6855 return (sRef_buildArrayFetch (arr));
6856 }
6857}
6858
6859/*@exposed@*/ sRef
28bf4b0b 6860sRef_makeArrayFetch (/*@exposed@*/ sRef arr)
616915dd 6861{
6862 return (sRef_buildArrayFetch (arr));
6863}
6864
6865/*@exposed@*/ sRef
28bf4b0b 6866sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
616915dd 6867{
6868 return (sRef_buildArrayFetchKnown (arr, i));
6869}
6870
6871/*@exposed@*/ sRef
6872sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
6873{
6874 sRef ret;
6875 ret = sRef_buildField (rec, f);
6876 return ret;
6877}
6878
6879/*@exposed@*/ sRef
28bf4b0b 6880sRef_makeNCField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
616915dd 6881{
28bf4b0b 6882 return (sRef_buildNCField (rec, f));
616915dd 6883}
6884
6885/*@only@*/ cstring
6886sRef_unparseKindName (sRef s)
6887{
6888 cstring result;
6889
6890 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6891
6892 s = sRef_fixConj (s);
6893
6894 switch (s->kind)
6895 {
6896 case SK_CVAR:
6897 if (sRef_isLocalVar (s))
6898 {
6899 result = cstring_makeLiteral ("Variable");
6900 }
6901 else
6902 {
6903 result = cstring_makeLiteral ("Undef global");
6904 }
6905 break;
6906 case SK_PARAM:
6907 result = cstring_makeLiteral ("Out parameter");
6908 break;
6909 case SK_ARRAYFETCH:
6910 if (sRef_isAnyParam (s->info->arrayfetch->arr))
6911 {
6912 result = cstring_makeLiteral ("Out parameter");
6913 }
6914 else if (sRef_isIndexKnown (s))
6915 {
6916 result = cstring_makeLiteral ("Array element");
6917 }
6918 else
6919 {
6920 result = cstring_makeLiteral ("Value");
6921 }
6922 break;
6923 case SK_PTR:
6924 if (sRef_isAnyParam (s->info->ref))
6925 {
6926 result = cstring_makeLiteral ("Out parameter");
6927 }
6928 else
6929 {
6930 result = cstring_makeLiteral ("Value");
6931 }
6932 break;
6933 case SK_ADR:
6934 result = cstring_makeLiteral ("Value");
6935 break;
6936 case SK_FIELD:
6937 result = cstring_makeLiteral ("Field");
6938 break;
6939 case SK_OBJECT:
6940 result = cstring_makeLiteral ("Object");
6941 break;
6942 case SK_UNCONSTRAINED:
6943 result = cstring_makeLiteral ("<anything>");
6944 break;
6945 case SK_RESULT:
6946 case SK_SPECIAL:
6947 case SK_UNKNOWN:
6948 case SK_EXTERNAL:
6949 case SK_DERIVED:
6950 case SK_CONST:
6951 case SK_TYPE:
6952 result = cstring_makeLiteral ("<unknown>");
6953 break;
6954 case SK_CONJ:
6955 result = cstring_makeLiteral ("<conj>");
6956 break;
6957 case SK_NEW:
6958 result = cstring_makeLiteral ("Storage");
6959 break;
6960 }
6961
6962 return result;
6963}
6964
6965/*@only@*/ cstring
6966sRef_unparseKindNamePlain (sRef s)
6967{
6968 cstring result;
6969
6970 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6971
6972 s = sRef_fixConj (s);
6973
6974 switch (s->kind)
6975 {
6976 case SK_CVAR:
6977 if (sRef_isLocalVar (s))
6978 {
6979 result = cstring_makeLiteral ("Variable");
6980 }
6981 else
6982 {
6983 result = cstring_makeLiteral ("Global");
6984 }
6985 break;
6986 case SK_PARAM:
6987 result = cstring_makeLiteral ("Parameter");
6988 break;
6989 case SK_ARRAYFETCH:
6990 if (sRef_isAnyParam (s->info->arrayfetch->arr))
6991 {
6992 result = cstring_makeLiteral ("Parameter");
6993 }
6994 else if (sRef_isIndexKnown (s))
6995 {
6996 result = cstring_makeLiteral ("Array element");
6997 }
6998 else
6999 {
7000 result = cstring_makeLiteral ("Value");
7001 }
7002 break;
7003 case SK_PTR:
7004 if (sRef_isAnyParam (s->info->ref))
7005 {
7006 result = cstring_makeLiteral ("Parameter");
7007 }
7008 else
7009 {
7010 result = cstring_makeLiteral ("Value");
7011 }
7012 break;
7013 case SK_ADR:
7014 result = cstring_makeLiteral ("Value");
7015 break;
7016 case SK_FIELD:
7017 result = cstring_makeLiteral ("Field");
7018 break;
7019 case SK_OBJECT:
7020 result = cstring_makeLiteral ("Object");
7021 break;
7022 case SK_NEW:
7023 result = cstring_makeLiteral ("Storage");
7024 break;
7025 case SK_UNCONSTRAINED:
7026 result = cstring_makeLiteral ("<anything>");
7027 break;
7028 case SK_RESULT:
7029 case SK_TYPE:
7030 case SK_CONST:
7031 case SK_EXTERNAL:
7032 case SK_DERIVED:
7033 case SK_UNKNOWN:
7034 case SK_SPECIAL:
7035 result = cstring_makeLiteral ("<unknown>");
7036 break;
7037 case SK_CONJ:
7038 result = cstring_makeLiteral ("<conj>");
7039 break;
7040 }
7041
7042 return result;
7043}
7044
7045/*
7046** s1 <- s2
7047*/
7048
7049void
7050sRef_copyState (sRef s1, sRef s2)
7051{
7052 if (sRef_isValid (s1) && sRef_isValid (s2))
7053 {
7054 s1->defstate = s2->defstate;
7055
616915dd 7056 /* start modifications */
7057 s1->bufinfo.bufstate = s2->bufinfo.bufstate;
7058 s1->bufinfo.len = s2->bufinfo.len;
7059 s1->bufinfo.size = s2->bufinfo.size;
7060 /* end modifications */
7061
7062 s1->aliaskind = s2->aliaskind;
28bf4b0b 7063 s1->aliasinfo = stateInfo_update (s1->aliasinfo, s2->aliasinfo);
616915dd 7064
7065 s1->expkind = s2->expkind;
28bf4b0b 7066 s1->expinfo = stateInfo_update (s1->expinfo, s2->expinfo);
7067
7068 s1->nullstate = s2->nullstate;
7069 s1->nullinfo = stateInfo_update (s1->nullinfo, s2->nullinfo);
616915dd 7070
28bf4b0b 7071 /*@-mustfree@*/
7072 /*@i834 don't free it: valueTable_free (s1->state); */
7073 /*@i32@*/ s1->state = valueTable_copy (s2->state);
7074 /*@=mustfree@*/
616915dd 7075 s1->safe = s2->safe;
28bf4b0b 7076 }
616915dd 7077}
7078
7079sRef
7080sRef_makeNew (ctype ct, sRef t, cstring name)
7081{
28bf4b0b 7082 sRef s = sRef_newRef ();
616915dd 7083
7084 s->kind = SK_NEW;
7085 s->type = ct;
7086
7087 llassert (sRef_isValid (t));
7088 s->defstate = t->defstate;
7089
7090 s->aliaskind = t->aliaskind;
7091 s->oaliaskind = s->aliaskind;
616915dd 7092 s->nullstate = t->nullstate;
28bf4b0b 7093
616915dd 7094 s->expkind = t->expkind;
7095 s->oexpkind = s->expkind;
28bf4b0b 7096
616915dd 7097 s->info = (sinfo) dmalloc (sizeof (*s->info));
7098 s->info->fname = name;
7099
7100 /* start modifications */
7101 s->bufinfo.bufstate = t->bufinfo.bufstate;
7102 /* end modifications */
28bf4b0b 7103
7104 llassert (valueTable_isUndefined (s->state));
7105 s->state = valueTable_copy (t->state);
616915dd 7106
28bf4b0b 7107 DPRINTF (("==> Copying state: %s", valueTable_unparse (s->state)));
7108 DPRINTF (("==> new: %s", sRef_unparseFull (s)));
7109 return s;
616915dd 7110}
7111
7112sRef
7113sRef_makeType (ctype ct)
7114{
28bf4b0b 7115 sRef s = sRef_newRef ();
7116
7117 sRef_checkMutable (s);
7118
616915dd 7119 s->kind = SK_TYPE;
7120 s->type = ct;
7121
7122 s->defstate = SS_UNKNOWN;
7123 s->aliaskind = AK_UNKNOWN;
28bf4b0b 7124 sRef_setNullStateN (s, NS_UNKNOWN);
7125
616915dd 7126 /* start modification */
7127 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
7128 /* end modification */
7129
7130
7131 if (ctype_isUA (ct))
7132 {
7133 typeId uid = ctype_typeId (ct);
7134 uentry ue = usymtab_getTypeEntrySafe (uid);
7135
7136 if (uentry_isValid (ue))
7137 {
7138 sRef_mergeStateQuiet (s, uentry_getSref (ue));
7139 }
7140 }
28bf4b0b 7141
7142 s->oaliaskind = s->aliaskind;
616915dd 7143 s->oexpkind = s->expkind;
28bf4b0b 7144 llassert (valueTable_isUndefined (s->state));
6970c11b 7145 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
616915dd 7146
28bf4b0b 7147 DPRINTF (("Create: %s", sRef_unparseFull (s)));
616915dd 7148 return s;
7149}
7150
7151sRef
7152sRef_makeConst (ctype ct)
7153{
28bf4b0b 7154 sRef s = sRef_newRef ();
616915dd 7155
7156 s->kind = SK_CONST;
7157 s->type = ct;
7158
7159 s->defstate = SS_UNKNOWN;
7160 s->aliaskind = AK_UNKNOWN;
28bf4b0b 7161 sRef_setNullStateN (s, NS_UNKNOWN);
7162
616915dd 7163 /* start modification */
7164 s->bufinfo.bufstate = BB_NULLTERMINATED;
7165 /* end modification */
616915dd 7166 if (ctype_isUA (ct))
7167 {
7168 typeId uid = ctype_typeId (ct);
7169 uentry te = usymtab_getTypeEntrySafe (uid);
7170
7171 if (uentry_isValid (te))
7172 {
7173 sRef_mergeStateQuiet (s, uentry_getSref (te));
7174 }
7175 }
28bf4b0b 7176
616915dd 7177
7178 s->oaliaskind = s->aliaskind;
7179 s->oexpkind = s->expkind;
7180
28bf4b0b 7181 llassert (valueTable_isUndefined (s->state));
6970c11b 7182 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
28bf4b0b 7183
616915dd 7184 return s;
7185}
7186
7187bool sRef_hasName (sRef s)
7188{
7189 if (sRef_isInvalid (s))
7190 {
7191 return (FALSE);
7192 }
7193
7194 switch (s->kind)
7195 {
7196 case SK_CVAR:
7197 {
7198 uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
7199 s->info->cvar->index);
7200 return (uentry_hasName (u));
7201 }
7202 case SK_PARAM:
7203 {
28bf4b0b 7204 if (s->info->paramno >= 0)
7205 {
7206 uentry u = uentryList_getN (context_getParams (),
7207 s->info->paramno);
7208
7209 return (uentry_hasName (u));
7210 }
7211 else
7212 {
7213 llassert (s->info->paramno == PARAMUNKNOWN);
7214 return FALSE;
7215 }
616915dd 7216 }
7217 default:
7218 return TRUE;
7219 }
7220}
7221
616915dd 7222bool
7223sRef_sameName (sRef s1, sRef s2)
7224{
7225 if (sRef_isInvalid (s1))
7226 {
7227 return sRef_isInvalid (s2);
7228 }
7229
7230 if (sRef_isInvalid (s2))
7231 {
7232 return (FALSE);
7233 }
7234
7235 switch (s1->kind)
7236 {
7237 case SK_CVAR:
7238 if (s2->kind == SK_CVAR)
7239 {
7240 return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
7241 && s1->info->cvar->index == s2->info->cvar->index);
7242 }
7243 else if (s2->kind == SK_PARAM)
7244 {
7245 if (context_inFunctionLike ())
7246 {
28bf4b0b 7247 if (s2->info->paramno != PARAMUNKNOWN)
7248 {
7249 uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
7250 s1->info->cvar->index);
7251 uentry u2 = uentryList_getN (context_getParams (),
7252 s2->info->paramno);
7253
7254 return (cstring_equalFree (uentry_getName (u1),
7255 uentry_getName (u2)));
7256 }
7257 else
7258 {
7259 return s1->info->paramno == PARAMUNKNOWN;
7260 }
616915dd 7261 }
7262 else
7263 {
7264 return FALSE;
7265 }
7266 }
7267 else
7268 {
7269 return FALSE;
7270 }
7271 case SK_PARAM:
7272 {
7273 if (s2->kind == SK_PARAM)
7274 {
7275 return (s1->info->paramno == s2->info->paramno);
7276 }
7277 else if (s2->kind == SK_CVAR)
7278 {
7279 if (context_inFunctionLike ())
7280 {
28bf4b0b 7281 if (s1->info->paramno == PARAMUNKNOWN)
7282 {
7283 return FALSE;
7284 }
7285 else
7286 {
7287 uentry u1 = uentryList_getN (context_getParams (),
7288 s1->info->paramno);
7289 uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
7290 s2->info->cvar->index);
7291
7292
7293 return (cstring_equalFree (uentry_getName (u1),
7294 uentry_getName (u2)));
7295 }
616915dd 7296 }
7297 else
7298 {
7299 return FALSE;
7300 }
7301 }
7302 else
7303 {
7304 return FALSE;
7305 }
7306 }
7307
7308 case SK_UNCONSTRAINED:
7309 return FALSE;
7310
7311 case SK_ARRAYFETCH:
7312 if (s2->kind == SK_ARRAYFETCH)
7313 {
7314 if (bool_equal (s1->info->arrayfetch->indknown,
7315 s2->info->arrayfetch->indknown))
7316 {
7317 if (!s1->info->arrayfetch->indknown
7318 || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
7319 {
7320 return sRef_sameName (s1->info->arrayfetch->arr,
7321 s2->info->arrayfetch->arr);
7322 }
7323 }
7324 }
7325
7326 return FALSE;
7327 case SK_FIELD:
7328 if (s2->kind == SK_FIELD)
7329 {
7330 if (cstring_equal (s1->info->field->field,
7331 s2->info->field->field))
7332 {
7333 return sRef_sameName (s1->info->field->rec,
7334 s2->info->field->rec);
7335 }
7336
7337 }
7338 return FALSE;
7339 case SK_PTR:
7340 case SK_ADR:
7341 case SK_DERIVED:
7342 case SK_EXTERNAL:
7343 if (s2->kind == s1->kind)
7344 {
7345 return sRef_sameName (s1->info->ref,
7346 s2->info->ref);
7347 }
7348
7349 return FALSE;
7350 case SK_OBJECT:
7351 return FALSE;
7352 case SK_CONJ:
7353 return sRef_sameName (sRef_getConjA (s1), s2);
7354 case SK_NEW:
7355 return FALSE;
7356 case SK_UNKNOWN:
7357 return (s2->kind == SK_UNKNOWN);
7358 case SK_TYPE:
7359 case SK_CONST:
7360 if (s2->kind == s1->kind)
7361 {
7362 return (ctype_equal (s1->type, s2->type));
7363 }
7364
7365 return FALSE;
7366 case SK_SPECIAL:
7367 if (s2->kind == SK_SPECIAL)
7368 {
7369 return (s1->info->spec == s2->info->spec);
7370 }
7371 return FALSE;
7372 case SK_RESULT:
7373 return (s2->kind == SK_RESULT);
7374 default:
7375 return FALSE;
7376 }
7377 BADEXIT;
7378}
7379
7380sRef
7381sRef_fixOuterRef (/*@returned@*/ sRef s)
7382{
7383 sRef root = sRef_getRootBase (s);
7384
7385 if (sRef_isCvar (root))
7386 {
7387 uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel,
7388 root->info->cvar->index);
7389
7390 if (uentry_isValid (ue))
7391 {
7392 sRef uref = uentry_getSref (ue);
7393 sRef sr = sRef_fixBase (s, uref);
7394
7395 return (sr);
7396 }
7397 else
7398 {
7399 llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
7400 return (s);
7401 }
7402 }
7403
7404 return (s);
7405}
7406
7407void
7408sRef_storeState (sRef s)
7409{
7410 if (sRef_isInvalid (s)) return;
7411
28bf4b0b 7412 sRef_checkMutable (s);
616915dd 7413 s->oaliaskind = s->aliaskind;
7414 s->oexpkind = s->expkind;
7415}
7416
7417static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
7418{
7419 sRef_resetState (s);
7420}
7421
7422void
7423sRef_resetState (sRef s)
7424{
7425 bool changed = FALSE;
7426 if (sRef_isInvalid (s)) return;
7427
7428
7429 if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
7430 {
7431 /*
7432 ** killref is used in a kludgey way, to save having to add
7433 ** another alias kind (see usymtab_handleParams)
7434 */
7435
7436 if (s->expkind != s->oexpkind)
7437 {
7438 changed = TRUE;
7439 s->expkind = s->oexpkind;
7440 }
7441 }
7442 else
7443 {
7444 if (s->expkind != s->oexpkind)
7445 {
7446 changed = TRUE;
7447 s->expkind = s->oexpkind;
7448 }
7449
7450 if (s->aliaskind != s->oaliaskind
7451 && s->aliaskind != AK_REFCOUNTED
7452 && s->aliaskind != AK_REFS)
7453 {
7454 changed = TRUE;
7455 s->aliaskind = s->oaliaskind;
28bf4b0b 7456 }
616915dd 7457 }
7458
7459 if (changed)
7460 {
7461 sRef_clearDerived (s);
7462 }
7463
7464 }
7465
7466void
7467sRef_resetStateComplete (sRef s)
7468{
7469 sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7470}
7471
7472/*@exposed@*/ sRef
7473sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7474{
7475 sRef tmp = sRef_undefined;
7476 sRef ret;
7477
7478 if (sRef_isInvalid (s)) return s;
7479 if (sRef_isInvalid (base)) return base;
7480
7481 switch (s->kind)
7482 {
7483 case SK_RESULT:
7484 case SK_PARAM:
7485 case SK_CVAR:
7486 ret = base;
7487 break;
7488 case SK_ARRAYFETCH:
7489 tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7490
7491 if (s->info->arrayfetch->indknown)
7492 {
7493 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7494 }
7495 else
7496 {
7497 ret = sRef_makeArrayFetch (tmp);
7498 }
7499 break;
7500 case SK_FIELD:
7501 tmp = sRef_fixBase (s->info->field->rec, base);
7502 ret = sRef_buildNCField (tmp, s->info->field->field);
7503 break;
7504 case SK_PTR:
7505 tmp = sRef_fixBase (s->info->ref, base);
7506 ret = sRef_makePointer (tmp);
7507 break;
7508 case SK_ADR:
7509 tmp = sRef_fixBase (s->info->ref, base);
7510 ret = sRef_makeAddress (tmp);
7511 break;
7512 case SK_CONJ:
7513 {
7514 sRef tmpb;
7515
7516 tmp = sRef_fixBase (s->info->conj->a, base);
7517 tmpb = sRef_fixBase (s->info->conj->b, base);
7518
7519 ret = sRef_makeConj (tmp, tmpb);
7520 break;
7521 }
7522 BADDEFAULT;
7523 }
7524
7525 return ret;
7526}
7527
7528static /*@exposed@*/ sRef
7529sRef_fixDirectBase (sRef s, sRef base)
7530{
7531 sRef ret;
7532
7533
7534 if (sRef_isInvalid (s))
7535 {
28bf4b0b 7536 return sRef_undefined;
616915dd 7537 }
28bf4b0b 7538
616915dd 7539 switch (s->kind)
7540 {
7541 case SK_ARRAYFETCH:
7542 if (s->info->arrayfetch->indknown)
7543 {
7544 ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7545 }
7546 else
7547 {
7548 ret = sRef_makeArrayFetch (base);
7549 }
7550 break;
7551 case SK_FIELD:
7552 ret = sRef_buildNCField (base, s->info->field->field);
7553 break;
7554 case SK_PTR:
7555 ret = sRef_makePointer (base);
7556 break;
7557 case SK_ADR:
7558 ret = sRef_makeAddress (base);
7559 break;
7560 case SK_CONJ:
7561 {
7562 sRef tmpa, tmpb;
7563
7564 tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7565 tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7566
7567 ret = sRef_makeConj (tmpa, tmpb);
7568 break;
7569 }
7570 BADDEFAULT;
7571 }
7572
7573 sRef_copyState (ret, s);
7574 return ret;
7575}
7576
7577bool
7578sRef_isAllocIndexRef (sRef s)
7579{
7580 return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown)
7581 && sRef_isAllocated (s->info->arrayfetch->arr));
7582}
7583
7584void
7585sRef_showRefLost (sRef s)
7586{
7587 if (sRef_hasAliasInfoLoc (s))
7588 {
7589 llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
28bf4b0b 7590 sRef_getAliasInfoLoc (s));
616915dd 7591 }
7592}
7593
7594void
7595sRef_showRefKilled (sRef s)
7596{
7597 if (sRef_hasStateInfoLoc (s))
7598 {
7599 llgenindentmsg (message ("Storage %q released",
7600 sRef_unparse (s)), sRef_getStateInfoLoc (s));
7601 }
7602}
7603
7604void
7605sRef_showStateInconsistent (sRef s)
7606{
7607 if (sRef_hasStateInfoLoc (s))
7608 {
7609 llgenindentmsg
7610 (message ("Storage %qbecomes inconsistent (released on one branch)",
7611 sRef_unparseOpt (s)),
7612 sRef_getStateInfoLoc (s));
7613 }
7614}
7615
7616void
7617sRef_showStateInfo (sRef s)
7618{
7619 if (sRef_hasStateInfoLoc (s))
7620 {
7621 if (s->defstate == SS_DEAD)
7622 {
7623 llgenindentmsg
7624 (message ("Storage %qis released", sRef_unparseOpt (s)),
7625 sRef_getStateInfoLoc (s));
7626 }
7627 else if (s->defstate == SS_ALLOCATED || s->defstate == SS_DEFINED)
7628 {
7629 llgenindentmsg
7630 (message ("Storage %qis %s", sRef_unparseOpt (s),
7631 sstate_unparse (s->defstate)),
7632 sRef_getStateInfoLoc (s));
7633 }
7634 else if (s->defstate == SS_UNUSEABLE)
7635 {
7636 llgenindentmsg
7637 (message ("Storage %qbecomes inconsistent (clauses merge with"
7638 "%qreleased on one branch)",
7639 sRef_unparseOpt (s),
7640 sRef_unparseOpt (s)),
7641 sRef_getStateInfoLoc (s));
7642 }
7643 else
7644 {
7645 llgenindentmsg (message ("Storage %qbecomes %s",
7646 sRef_unparseOpt (s),
7647 sstate_unparse (s->defstate)),
7648 sRef_getStateInfoLoc (s));
7649 }
7650 }
7651}
7652
7653void
7654sRef_showExpInfo (sRef s)
7655{
7656 if (sRef_hasExpInfoLoc (s))
7657 {
7658 llgenindentmsg (message ("Storage %qbecomes %s", sRef_unparseOpt (s),
7659 exkind_unparse (s->expkind)),
7660 sRef_getExpInfoLoc (s));
7661 }
7662}
7663
28bf4b0b 7664void
7665sRef_showMetaStateInfo (sRef s, cstring key)
7666{
7667 stateValue val;
7668 metaStateInfo minfo = context_lookupMetaStateInfo (key);
7669
7670 llassert (sRef_isValid (s));
7671 llassert (valueTable_isDefined (s->state));
7672 llassert (metaStateInfo_isDefined (minfo));
7673
7674 val = valueTable_lookup (s->state, key);
7675
7676 if (stateValue_hasLoc (val))
7677 {
7678 llgenindentmsg
0bf5022d 7679 (message ("%qbecomes %q", sRef_unparseOpt (s),
2c88d156 7680 stateValue_unparseValue (val, minfo)),
28bf4b0b 7681 stateValue_getLoc (val));
7682 }
7683}
7684
616915dd 7685void
7686sRef_showNullInfo (sRef s)
7687{
28bf4b0b 7688 DPRINTF (("Show null info: %s", sRef_unparseFull (s)));
7689
616915dd 7690 if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7691 {
28bf4b0b 7692 DPRINTF (("has null info: %s",
7693 fileloc_unparse (sRef_getNullInfoLoc (s))));
7694
7695 switch (sRef_getNullState (s))
616915dd 7696 {
7697 case NS_CONSTNULL:
7698 {
7699 fileloc loc = sRef_getNullInfoLoc (s);
7700
7701 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7702 {
7703 llgenindentmsg
7704 (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7705 loc);
7706 }
7707 break;
7708 }
7709 case NS_DEFNULL:
7710 {
7711 fileloc loc = sRef_getNullInfoLoc (s);
7712
7713 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7714 {
7715 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7716 loc);
7717 }
7718 break;
7719 }
7720 case NS_ABSNULL:
7721 case NS_POSNULL:
7722 llgenindentmsg
7723 (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7724 sRef_getNullInfoLoc (s));
7725 break;
7726 case NS_NOTNULL:
7727 case NS_MNOTNULL:
7728 llgenindentmsg
7729 (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7730 sRef_getNullInfoLoc (s));
7731 break;
7732 case NS_UNKNOWN:
7733 llgenindentmsg
7734 (message ("Storage %qnull state becomes unknown",
7735 sRef_unparseOpt (s)),
7736 sRef_getNullInfoLoc (s));
7737 break;
7738
7739 case NS_ERROR:
7740 BADBRANCHCONT;
7741 break;
7742
7743 default:
7744 llgenindentmsg
7745 (message ("<error case> Storage %q becomes %s",
7746 sRef_unparse (s),
28bf4b0b 7747 nstate_unparse (sRef_getNullState (s))),
616915dd 7748 sRef_getNullInfoLoc (s));
7749
7750 break;
7751 }
7752 }
7753}
7754
7755void
7756sRef_showAliasInfo (sRef s)
7757{
7758 if (sRef_hasAliasInfoLoc (s))
7759 {
7760 if (sRef_isFresh (s))
7761 {
7762 llgenindentmsg
7763 (message ("Fresh storage %qallocated", sRef_unparseOpt (s)),
7764 sRef_getAliasInfoLoc (s));
7765 }
7766 else
7767 {
7768 if (!sRef_isRefCounted (s))
7769 {
7770 llgenindentmsg
7771 (message ("Storage %qbecomes %s",
7772 sRef_unparseOpt (s),
7773 alkind_unparse (sRef_getAliasKind (s))),
7774 sRef_getAliasInfoLoc (s));
7775 }
7776 }
7777 }
7778}
7779
7780void
7781sRef_mergeNullState (sRef s, nstate n)
7782{
7783 if (sRef_isValid (s))
7784 {
7785 nstate old;
7786
28bf4b0b 7787 old = sRef_getNullState (s);
616915dd 7788
7789 if (n != old && n != NS_UNKNOWN)
28bf4b0b 7790 {
7791 sRef_setNullState (s, n, g_currentloc);
616915dd 7792 }
7793 }
7794 else
7795 {
7796 llbuglit ("sRef_mergeNullState: invalid");
7797 }
7798}
7799
7800bool
7801sRef_possiblyNull (sRef s)
7802{
7803 if (sRef_isValid (s))
28bf4b0b 7804 {
7805 if (sRef_getNullState (s) == NS_ABSNULL)
616915dd 7806 {
7807 ctype rct = ctype_realType (s->type);
7808
7809 if (ctype_isAbstract (rct))
7810 {
7811 return FALSE;
7812 }
7813 else
7814 {
7815 if (ctype_isUser (rct))
7816 {
7817 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7818
7819 return (nstate_possiblyNull
7820 (sRef_getNullState (uentry_getSref (ue))));
7821 }
7822 else
7823 {
7824 return FALSE;
7825 }
7826 }
7827 }
7828 else
7829 {
28bf4b0b 7830 return nstate_possiblyNull (sRef_getNullState (s));
616915dd 7831 }
7832 }
7833
7834 return FALSE;
7835}
7836
7837cstring
7838sRef_getScopeName (sRef s)
7839{
7840 sRef base = sRef_getRootBase (s);
7841
7842 if (sRef_isRealGlobal (base))
7843 {
7844 return (cstring_makeLiteralTemp ("Global"));
7845 }
7846 else if (sRef_isFileStatic (base))
7847 {
7848 return (cstring_makeLiteralTemp ("Static"));
7849 }
7850 else
7851 {
7852 return (cstring_makeLiteralTemp ("Local"));
7853 }
7854}
7855
7856cstring
7857sRef_unparseScope (sRef s)
7858{
7859 sRef base = sRef_getRootBase (s);
7860
7861 if (sRef_isRealGlobal (base))
7862 {
7863 return (cstring_makeLiteralTemp ("global"));
7864 }
7865 else if (sRef_isFileStatic (base))
7866 {
7867 return (cstring_makeLiteralTemp ("file static"));
7868 }
7869 else
7870 {
7871 BADEXIT;
7872 }
7873}
7874
7875int
7876sRef_getScope (sRef s)
7877{
7878 llassert (sRef_isValid (s));
7879
7880 if (sRef_isCvar (s))
7881 {
7882 return s->info->cvar->lexlevel;
7883 }
7884 else if (sRef_isParam (s))
7885 {
7886 return paramsScope;
7887 }
7888 else
7889 {
7890 return fileScope;
7891 }
7892}
7893
7894bool
7895sRef_isDead (sRef s)
7896{
7897 return (sRef_isValid (s) && (s)->defstate == SS_DEAD);
7898}
7899
7900bool
7901sRef_isDeadStorage (sRef s)
7902{
7903 if (sRef_isValid (s))
7904 {
7905 if (s->defstate == SS_DEAD
7906 || s->defstate == SS_UNUSEABLE
7907 || s->defstate == SS_UNDEFINED
7908 || s->defstate == SS_UNKNOWN)
7909 {
7910 return TRUE;
7911 }
7912 else
7913 {
7914 return (sRef_isDefinitelyNull (s));
7915 }
7916 }
7917 else
7918 {
7919 return FALSE;
7920 }
7921}
7922
7923bool
7924sRef_isPossiblyDead (sRef s)
7925{
7926 return (sRef_isValid (s) && s->defstate == SS_HOFFA);
7927}
7928
7929bool sRef_isStateLive (sRef s)
7930{
7931 if (sRef_isValid (s))
7932 {
7933 sstate ds = s->defstate;
7934
7935 return (!(ds == SS_UNDEFINED
7936 || ds == SS_DEAD
7937 || ds == SS_UNUSEABLE
7938 || ds == SS_HOFFA));
7939 }
7940 else
7941 {
7942 return FALSE;
7943 }
7944}
7945
7946
7947bool sRef_isStateUndefined (sRef s)
7948{
7949 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNDEFINED));
7950}
7951
7952bool sRef_isJustAllocated (sRef s)
7953{
7954 if (sRef_isAllocated (s))
7955 {
7956 sRefSet_allElements (s->deriv, el)
7957 {
7958 if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
7959 {
7960 return FALSE;
7961 }
7962 } end_sRefSet_allElements ;
7963
7964 return TRUE;
7965 }
7966
7967 return FALSE;
7968}
7969
7970static bool
7971sRef_isAllocatedStorage (sRef s)
7972{
7973 if (sRef_isValid (s) && ynm_toBoolStrict (sRef_isReadable (s)))
7974 {
7975 return (ctype_isVisiblySharable (sRef_getType (s)));
7976 }
7977 else
7978 {
7979 return FALSE;
7980 }
7981}
7982
7983bool
7984sRef_isUnuseable (sRef s)
7985{
7986 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
7987}
7988
7989bool
7990sRef_perhapsNull (sRef s)
7991{
7992 if (sRef_isValid (s))
7993 {
28bf4b0b 7994 if (sRef_getNullState (s) == NS_ABSNULL)
616915dd 7995 {
7996 ctype rct = ctype_realType (s->type);
7997
7998 if (ctype_isAbstract (rct))
7999 {
8000 return FALSE;
8001 }
8002 else
8003 {
8004 if (ctype_isUser (rct))
8005 {
8006 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
8007
8008 return (nstate_perhapsNull
8009 (sRef_getNullState (uentry_getSref (ue))));
8010 }
8011 else
8012 {
8013 return FALSE;
8014 }
8015 }
8016 }
8017 else
8018 {
28bf4b0b 8019 return nstate_perhapsNull (sRef_getNullState (s));
616915dd 8020 }
8021 }
8022
8023 return FALSE;
8024}
8025
8026/*
8027** definitelyNull --- called when TRUE is good
8028*/
8029
8030bool
8031sRef_definitelyNull (sRef s)
8032{
8033 return (sRef_isValid (s)
28bf4b0b 8034 && (sRef_getNullState (s) == NS_DEFNULL || sRef_getNullState (s) == NS_CONSTNULL));
616915dd 8035}
8036
8037/*
8038** based on sRef_similar
8039*/
8040
8041void
8042sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
8043{
8044 if (sRef_isValid (set))
8045 {
8046 sRef deriv = sRef_getDeriv (set, guide);
8047
8048 if (sRef_isValid (deriv))
8049 {
28bf4b0b 8050 sRef_setNullStateN (deriv, ns);
616915dd 8051 }
8052 }
8053}
8054
8055static /*@exposed@*/ sRef
8056sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
8057{
8058 llassert (sRef_isValid (set));
8059 llassert (sRef_isValid (guide));
8060
8061 switch (guide->kind)
8062 {
8063 case SK_CVAR:
8064 llassert (set->kind == SK_CVAR);
8065
8066 return set;
8067
8068 case SK_PARAM:
8069 llassert (set->kind == guide->kind);
8070 llassert (set->info->paramno == guide->info->paramno);
8071
8072 return set;
8073
8074 case SK_ARRAYFETCH:
8075
8076 if (set->kind == SK_ARRAYFETCH
8077 && (sRef_similar (set->info->arrayfetch->arr,
8078 guide->info->arrayfetch->arr)))
8079 {
8080 return set;
8081 }
8082 else
8083 {
8084 return (sRef_makeAnyArrayFetch
8085 (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
8086 }
8087
8088 case SK_PTR:
8089
8090 if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
8091 {
8092 return set;
8093 }
8094 else
8095 {
8096 return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
8097 }
8098
8099 case SK_FIELD:
8100
8101 if ((set->kind == SK_FIELD &&
8102 (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
8103 cstring_equal (set->info->field->field, guide->info->field->field))))
8104 {
8105 return set;
8106 }
8107 else
8108 {
8109 return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
8110 guide->info->field->field));
8111 }
8112 case SK_ADR:
8113
8114 if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
8115 {
8116 return set;
8117 }
8118 else
8119 {
8120 return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
8121 }
8122
8123 case SK_CONJ:
8124
8125 return sRef_undefined;
8126
8127 case SK_RESULT:
8128 case SK_SPECIAL:
8129 case SK_UNCONSTRAINED:
8130 case SK_TYPE:
8131 case SK_CONST:
8132 case SK_NEW:
8133 case SK_UNKNOWN:
8134 case SK_OBJECT:
8135 case SK_DERIVED:
8136 case SK_EXTERNAL:
8137 return sRef_undefined;
8138 }
8139
8140 BADEXIT;
8141}
8142
8143/*
8144** sRef_aliasCheckPred
8145**
8146** A confusing but spiffy function:
8147**
8148** Calls predf (s, e, text, <alias>) on s and all of s's aliases
8149** (unless checkAliases (s) is FALSE).
8150**
8151** For alias calls, calls as
8152** predf (alias, e, text, s)
8153*/
8154
8155void
8156sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
8157 /*@null@*/ bool (checkAliases) (sRef),
8158 sRef s, exprNode e, exprNode err)
8159{
8160 bool error = (*predf)(s, e, sRef_undefined, err);
8161
8162
8163 if (checkAliases != NULL && !(checkAliases (s)))
8164 {
8165 /* don't check aliases */
8166 }
8167 else
8168 {
8169 sRefSet aliases = usymtab_allAliases (s);
8170
8171
8172 sRefSet_realElements (aliases, current)
8173 {
8174 if (sRef_isValid (current))
8175 {
8176 if (!sRef_similar (current, s)
8177 || (error && sRef_sameName (current, s)))
8178 {
8179 (void) (*predf)(current, e, s, err);
8180 }
8181 }
8182 } end_sRefSet_realElements;
8183
8184 sRefSet_free (aliases);
8185 }
8186}
8187
8188/*
8189** return TRUE iff predf (s) is true for s or any alias of s
8190*/
8191
8192bool
8193sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
8194{
8195
8196 if ((*predf)(s))
8197 {
8198 return TRUE;
8199 }
8200 else
8201 {
8202 sRefSet aliases;
8203
8204 aliases = usymtab_allAliases (s);
8205
8206 sRefSet_realElements (aliases, current)
8207 {
8208 if (sRef_isValid (current))
8209 {
8210 sRef cref = sRef_updateSref (current);
8211
8212 /* Whoa! a very kludgey way to make sure the right sref is used
8213 ** where there is a conditional symbol table. I am beginning
8214 ** to think that having a conditional symbol table wasn't such
8215 ** a great idea. ;(
8216 */
8217
616915dd 8218 if ((*predf)(cref))
8219 {
28bf4b0b 8220 DPRINTF (("Checking alias: %s", sRef_unparseFull (cref)));
616915dd 8221 sRefSet_free (aliases);
8222 return TRUE;
8223 }
8224 }
8225 } end_sRefSet_realElements;
8226
8227 sRefSet_free (aliases);
8228 }
8229 return FALSE;
8230}
8231
8232bool
8233sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
8234{
8235 sRefSet aliases;
8236 bool result = FALSE;
8237
8238
8239 aliases = usymtab_allAliases (s);
8240
8241 if ((*predf)(s)) result = TRUE;
8242
8243
8244 sRefSet_realElements (aliases, current)
8245 {
8246 if (sRef_isValid (current))
8247 {
28bf4b0b 8248 current = sRef_updateSref (current);
8249 if ((*predf)(current)) result = TRUE;
616915dd 8250 }
8251 } end_sRefSet_realElements;
8252
8253 sRefSet_free (aliases);
8254 return result;
8255}
8256
8257static void
8258sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8259{
8260 sRefSet aliases;
8261
8262 aliases = usymtab_allAliases (s);
8263
28bf4b0b 8264 DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
8265
616915dd 8266 (*predf)(s, loc);
8267
8268 sRefSet_realElements (aliases, current)
8269 {
8270 if (sRef_isValid (current))
8271 {
8272 current = sRef_updateSref (current);
28bf4b0b 8273 ((*predf)(current, loc));
616915dd 8274 }
8275 } end_sRefSet_realElements;
8276
8277 sRefSet_free (aliases);
8278}
8279
8280static void
8281sRef_aliasSetCompleteParam (void (predf) (sRef, alkind, fileloc), sRef s,
8282 alkind kind, fileloc loc)
8283{
8284 sRefSet aliases;
8285
8286
8287 if (sRef_isDeep (s))
8288 {
8289 aliases = usymtab_allAliases (s);
8290 }
8291 else
8292 {
8293 aliases = usymtab_aliasedBy (s);
8294 }
8295
8296 (*predf)(s, kind, loc);
8297
8298 sRefSet_realElements (aliases, current)
8299 {
8300 if (sRef_isValid (current))
8301 {
8302 current = sRef_updateSref (current);
28bf4b0b 8303 ((*predf)(current, kind, loc));
616915dd 8304 }
8305 } end_sRefSet_realElements;
8306
8307 sRefSet_free (aliases);
8308}
8309
8310static void
8311sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8312{
8313 sRef inner;
8314 sRefSet aliases;
8315 ctype ct;
8316
8317 if (!sRef_isValid (s)) return;
8318
8319
8320 /*
8321 ** Type equivalence checking is necessary --- there might be casting.
8322 */
8323
8324 (*predf)(s, loc);
8325
8326 switch (s->kind)
8327 {
8328 case SK_UNCONSTRAINED:
8329 case SK_CVAR:
8330 case SK_PARAM:
8331 break;
8332 case SK_PTR:
8333 inner = s->info->ref;
8334 aliases = usymtab_allAliases (inner);
8335 ct = sRef_getType (inner);
616915dd 8336
8337 sRefSet_realElements (aliases, current)
8338 {
8339 if (sRef_isValid (current))
8340 {
8341 current = sRef_updateSref (current);
8342
8343 if (ctype_equal (ct, sRef_getType (current)))
8344 {
8345 sRef ptr = sRef_makePointer (current);
616915dd 8346 ((*predf)(ptr, loc));
8347 }
8348 }
8349 } end_sRefSet_realElements;
8350
8351 sRefSet_free (aliases);
8352 break;
8353 case SK_ARRAYFETCH:
8354 inner = s->info->arrayfetch->arr;
8355 aliases = usymtab_allAliases (inner);
8356 ct = sRef_getType (inner);
8357
3120b462 8358 DPRINTF (("Array fetch: %s", sRefSet_unparse (aliases)));
8359
616915dd 8360 sRefSet_realElements (aliases, current)
8361 {
8362 if (sRef_isValid (current))
8363 {
8364 current = sRef_updateSref (current);
3120b462 8365 DPRINTF (("Current: %s", sRef_unparseFull (current)));
8366
616915dd 8367 if (ctype_equal (ct, sRef_getType (current)))
8368 {
616915dd 8369 if (s->info->arrayfetch->indknown)
8370 {
8371 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
3120b462 8372 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8373 llassert (af->info->arrayfetch->arr == current);
616915dd 8374 ((*predf)(af, loc));
8375 }
8376 else
8377 {
8378 sRef af = sRef_makeArrayFetch (current);
3120b462 8379 llassert (af->info->arrayfetch->arr == current);
8380 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
616915dd 8381 ((*predf)(af, loc));
8382 }
8383 }
3120b462 8384 else
8385 {
8386 DPRINTF (("Type mismatch: %s / %s",
8387 ctype_unparse (ct),
8388 ctype_unparse (sRef_getType (current))));
8389 }
616915dd 8390 }
8391 } end_sRefSet_realElements;
8392
8393 sRefSet_free (aliases);
8394 break;
8395 case SK_FIELD:
8396 inner = s->info->field->rec;
8397 aliases = usymtab_allAliases (inner);
8398 ct = sRef_getType (inner);
8399
8400
8401 sRefSet_realElements (aliases, current)
8402 {
8403 if (sRef_isValid (current))
8404 {
8405 current = sRef_updateSref (current);
8406
8407 if (ctype_equal (ct, sRef_getType (current)))
8408 {
8409 sRef f = sRef_makeField (current, s->info->field->field);
8410
8411 ((*predf)(f, loc));
8412 }
8413 }
8414 } end_sRefSet_realElements;
8415
8416 sRefSet_free (aliases);
8417 break;
8418 case SK_CONJ:
8419 sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
8420 sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
8421 break;
8422 case SK_SPECIAL:
8423 case SK_ADR:
8424 case SK_TYPE:
8425 case SK_CONST:
8426 case SK_NEW:
8427 case SK_UNKNOWN:
8428 case SK_OBJECT:
8429 case SK_DERIVED:
8430 case SK_EXTERNAL:
8431 case SK_RESULT:
8432 break;
8433 }
8434}
8435
8436static void
8437sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
8438{
8439 sRef inner;
8440 sRefSet aliases;
8441 ctype ct;
8442
8443 if (!sRef_isValid (s)) return;
8444
8445
8446 /*
8447 ** Type equivalence checking is necessary --- there might be casting.
8448 */
8449
8450 (*predf)(s, t);
8451
8452 switch (s->kind)
8453 {
8454 case SK_UNCONSTRAINED:
8455 case SK_CVAR:
8456 case SK_PARAM:
8457 break;
8458 case SK_PTR:
8459 inner = s->info->ref;
8460 aliases = usymtab_allAliases (inner);
8461 ct = sRef_getType (inner);
8462
8463
8464 sRefSet_realElements (aliases, current)
8465 {
8466 if (sRef_isValid (current))
8467 {
8468 current = sRef_updateSref (current);
8469
8470 if (ctype_equal (ct, sRef_getType (current)))
8471 {
8472 sRef ptr = sRef_makePointer (current);
8473
8474 ((*predf)(ptr, t));
8475 }
8476 }
8477 } end_sRefSet_realElements;
8478
8479 sRefSet_free (aliases);
8480 break;
8481 case SK_ARRAYFETCH:
8482 inner = s->info->arrayfetch->arr;
8483 aliases = usymtab_allAliases (inner);
8484 ct = sRef_getType (inner);
8485
8486 sRefSet_realElements (aliases, current)
8487 {
8488 if (sRef_isValid (current))
8489 {
8490 current = sRef_updateSref (current);
8491
8492 if (ctype_equal (ct, sRef_getType (current)))
8493 {
8494
8495 if (s->info->arrayfetch->indknown)
8496 {
8497 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8498
8499 ((*predf)(af, t));
8500 }
8501 else
8502 {
8503 sRef af = sRef_makeArrayFetch (current);
8504
8505 ((*predf)(af, t));
8506 }
8507 }
8508 }
8509 } end_sRefSet_realElements;
8510
8511 sRefSet_free (aliases);
8512 break;
8513 case SK_FIELD:
8514 inner = s->info->field->rec;
8515 aliases = usymtab_allAliases (inner);
8516 ct = sRef_getType (inner);
8517
8518
8519 sRefSet_realElements (aliases, current)
8520 {
8521 if (sRef_isValid (current))
8522 {
8523 current = sRef_updateSref (current);
8524
8525 if (ctype_equal (ct, sRef_getType (current)))
8526 {
8527 sRef f = sRef_makeField (current, s->info->field->field);
8528
8529 ((*predf)(f, t));
8530 }
8531 }
8532 } end_sRefSet_realElements;
8533
8534 sRefSet_free (aliases);
8535 break;
8536 case SK_CONJ:
8537 sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8538 sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8539 break;
8540 case SK_SPECIAL:
8541 case SK_ADR:
8542 case SK_TYPE:
8543 case SK_CONST:
8544 case SK_NEW:
8545 case SK_UNKNOWN:
8546 case SK_OBJECT:
8547 case SK_DERIVED:
8548 case SK_EXTERNAL:
8549 case SK_RESULT:
8550 break;
8551 }
8552}
8553
8554static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8555{
8556 exkind a1 = sRef_getExKind (res);
8557 exkind a2 = sRef_getExKind (other);
8558
8559 if (a1 == a2 || a2 == XO_UNKNOWN)
8560 {
8561 ;
8562 }
8563 else if (a1 == XO_UNKNOWN)
8564 {
28bf4b0b 8565 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
616915dd 8566 res->expkind = a2;
8567 }
8568 else
8569 {
8570 res->expkind = XO_OBSERVER;
8571 }
8572}
8573
8574/*
8575** Currently, this is a very ad hoc implementation, with lots of fixes to
8576** make real code work okay. I need to come up with some more general
8577** rules or principles here.
8578*/
8579
8580static void
8581 sRef_combineAliasKindsError (/*@notnull@*/ sRef res,
8582 /*@notnull@*/ sRef other,
8583 clause cl, fileloc loc)
8584{
8585 bool hasError = FALSE;
8586 alkind ares = sRef_getAliasKind (res);
8587 alkind aother = sRef_getAliasKind (other);
8588
28bf4b0b 8589 sRef_checkMutable (res);
8590
616915dd 8591 if (alkind_isDependent (ares))
8592 {
8593 if (aother == AK_KEPT)
8594 {
28bf4b0b 8595 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 8596 res->aliaskind = AK_KEPT;
8597 }
8598 else
8599 {
8600 if (aother == AK_LOCAL || aother == AK_STATIC
8601 || alkind_isTemp (aother))
8602 {
28bf4b0b 8603 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
616915dd 8604 res->aliaskind = AK_DEPENDENT;
8605 }
8606 }
8607 }
8608 else if (alkind_isDependent (aother))
8609 {
8610 if (ares == AK_KEPT)
8611 {
8612 res->aliaskind = AK_KEPT;
8613 }
8614 else
8615 {
8616 if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8617 {
28bf4b0b 8618 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8619 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 8620 res->aliaskind = AK_DEPENDENT;
8621 }
8622 }
8623 }
8624 else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8625 || ares == AK_STATIC || alkind_isTemp (ares))
8626 && sRef_isFresh (other))
8627 {
8628 /*
8629 ** cases like: if (s == NULL) s = malloc...;
8630 ** don't generate errors
8631 */
8632
28bf4b0b 8633 if (usymtab_isAltDefinitelyNullDeep (res))
616915dd 8634 {
8635 res->aliaskind = ares;
8636 }
8637 else
8638 {
8639 hasError = TRUE;
8640 }
8641 }
8642 else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8643 || aother == AK_STATIC || alkind_isTemp (aother))
8644 && sRef_isFresh (res))
8645 {
8646 /*
8647 ** cases like: if (s == NULL) s = malloc...;
8648 ** don't generate errors
8649 */
8650
28bf4b0b 8651 if (usymtab_isDefinitelyNullDeep (other))
616915dd 8652 {
28bf4b0b 8653 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 8654 res->aliaskind = aother;
8655 }
8656 else
8657 {
8658 hasError = TRUE;
8659 }
8660 }
8661 else if (ares == AK_NEWREF && aother == AK_REFCOUNTED
8662 && sRef_isConst (other))
8663 {
8664 res->aliaskind = AK_NEWREF;
8665 }
8666 else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8667 && sRef_isConst (res))
8668 {
28bf4b0b 8669 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 8670 res->aliaskind = AK_NEWREF;
8671 }
8672 else if (sRef_isLocalVar (res)
8673 && ((ares == AK_KEPT && aother == AK_LOCAL)
8674 || (aother == AK_KEPT && ares == AK_LOCAL)))
8675 {
8676 res->aliaskind = AK_KEPT;
8677 }
8678 else
8679 {
8680 hasError = TRUE;
8681 }
8682
8683 if (hasError)
8684 {
8685 if (sRef_isThroughArrayFetch (res))
8686 {
8687 if (optgenerror2
8688 (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8689 message
8690 ("Clauses exit with %q possibly referencing %s storage %s, "
8691 "%s storage %s",
8692 sRef_unparse (res),
8693 alkind_unparse (aother),
8694 clause_nameTaken (cl),
8695 alkind_unparse (ares),
8696 clause_nameAlternate (cl)),
8697 loc))
8698 {
8699 sRef_showAliasInfo (res);
8700 sRef_showAliasInfo (other);
8701 res->aliaskind = AK_ERROR;
8702 }
8703 else
8704 {
8705 if (ares == AK_KEPT || aother == AK_KEPT)
8706 {
8707 sRef_maybeKill (res, loc);
28bf4b0b 8708 }
616915dd 8709 }
8710 }
8711 else
8712 {
8713 if (optgenerror
8714 (FLG_BRANCHSTATE,
8715 message ("Clauses exit with %q referencing %s storage %s, "
8716 "%s storage %s",
8717 sRef_unparse (res),
8718 alkind_unparse (aother),
8719 clause_nameTaken (cl),
8720 alkind_unparse (ares),
8721 clause_nameAlternate (cl)),
8722 loc))
8723 {
8724 sRef_showAliasInfo (res);
8725 sRef_showAliasInfo (other);
8726
8727 res->aliaskind = AK_ERROR;
8728 }
8729 }
8730
8731 res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8732 }
8733}
8734
8735static void
8736 sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
8737 clause cl, fileloc loc)
8738{
8739 alkind ares = sRef_getAliasKind (res);
8740 alkind aother = sRef_getAliasKind (other);
8741
28bf4b0b 8742 sRef_checkMutable (res);
8743
616915dd 8744 if (alkind_equal (ares, aother)
8745 || aother == AK_UNKNOWN
8746 || aother == AK_ERROR)
8747 {
8748 ; /* keep current state */
8749 }
8750 else if (sRef_isDead (res) || sRef_isDead (other))
8751 {
8752 /* dead error reported (or storage is dead) */
8753 res ->aliaskind = AK_ERROR;
8754 }
8755 else if (ares == AK_UNKNOWN || ares == AK_ERROR
8756 || sRef_isStateUndefined (res))
8757 {
28bf4b0b 8758 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 8759 res->aliaskind = aother;
8760 }
8761 else if (sRef_isStateUndefined (other))
8762 {
8763 ;
8764 }
8765 else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8766 && aother == AK_LOCAL)
8767 || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8768 && ares == AK_LOCAL))
8769 {
8770 if (ares != AK_LOCAL)
8771 {
28bf4b0b 8772 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 8773 }
8774
8775 res->aliaskind = AK_LOCAL;
8776 }
8777 else if ((ares == AK_OWNED && aother == AK_FRESH)
8778 || (aother == AK_OWNED && ares == AK_FRESH))
8779 {
8780 if (ares != AK_FRESH)
8781 {
28bf4b0b 8782 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 8783 }
8784
8785 res->aliaskind = AK_FRESH;
8786 }
8787 else if ((ares == AK_KEEP && aother == AK_FRESH) ||
8788 (aother == AK_KEEP && ares == AK_FRESH))
8789 {
8790 if (ares != AK_KEEP)
8791 {
28bf4b0b 8792 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 8793 }
8794
8795 res->aliaskind = AK_KEEP;
8796 }
8797 else if ((ares == AK_LOCAL && aother == AK_STACK) ||
8798 (aother == AK_LOCAL && ares == AK_STACK))
8799 {
8800 if (ares != AK_STACK)
8801 {
28bf4b0b 8802 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 8803 }
8804
8805 res->aliaskind = AK_STACK;
8806 }
8807 else if ((ares == AK_LOCAL
8808 && (aother == AK_OWNED && sRef_isLocalVar (other)))
8809 || (aother == AK_LOCAL
8810 && (ares == AK_OWNED && sRef_isLocalVar (res))))
8811 {
8812 if (ares != AK_LOCAL)
8813 {
28bf4b0b 8814 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 8815 }
8816
8817 res->aliaskind = AK_LOCAL;
8818 }
8819 else if ((ares == AK_FRESH && alkind_isOnly (aother))
8820 || (aother == AK_FRESH && alkind_isOnly (ares)))
8821 {
8822 res->aliaskind = AK_FRESH;
8823 }
8824 else if ((aother == AK_FRESH && sRef_definitelyNull (res))
8825 || (ares == AK_FRESH && sRef_definitelyNull (other)))
8826 {
8827 if (ares != AK_FRESH)
8828 {
28bf4b0b 8829 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 8830 res->aliaskind = AK_FRESH;
8831 }
8832 }
8833 else if ((sRef_isFresh (res) && sRef_isConst (other))
8834 || (sRef_isFresh (other) && sRef_isConst (res)))
8835 {
8836 /*
8837 ** for NULL constantants
8838 ** this is bogus!
8839 */
8840
8841 if (!sRef_isFresh (res))
8842 {
28bf4b0b 8843 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 8844 }
8845
8846 res->aliaskind = AK_FRESH;
8847 }
8848 else if ((alkind_isStatic (aother) && sRef_isConst (res))
8849 || (alkind_isStatic (ares) && sRef_isConst (other)))
8850 {
8851 if (!alkind_isStatic (ares))
8852 {
28bf4b0b 8853 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
616915dd 8854 res->aliaskind = AK_STATIC;
8855 }
8856 }
8857 else
8858 {
8859 sRef_combineAliasKindsError (res, other, cl, loc);
8860 }
8861}
8862
8863static void sRef_combineDefState (/*@notnull@*/ sRef res,
8864 /*@notnull@*/ sRef other)
8865{
8866 sstate s1 = res->defstate;
8867 sstate s2 = other->defstate;
8868 bool flip = FALSE;
8869
28bf4b0b 8870 sRef_checkMutable (res);
8871
616915dd 8872 if (s1 == s2 || s2 == SS_UNKNOWN)
8873 {
8874 ;
8875 }
8876 else if (s1 == SS_UNKNOWN)
8877 {
8878 flip = TRUE;
8879 }
8880 else
8881 {
8882 switch (s1)
8883 {
8884 case SS_FIXED:
8885 if (s2 == SS_DEFINED)
8886 {
8887 break;
8888 }
8889 else
8890 {
8891 llcontbuglit ("ssfixed: not implemented");
8892 flip = TRUE;
8893 }
8894 break;
8895 case SS_DEFINED:
8896 flip = TRUE;
8897 break;
8898 case SS_PDEFINED:
8899 case SS_ALLOCATED:
8900 flip = (s2 != SS_DEFINED);
8901 break;
8902 case SS_HOFFA:
8903 case SS_RELDEF:
8904 case SS_UNUSEABLE:
8905 case SS_UNDEFINED:
8906 case SS_PARTIAL:
8907 case SS_UNDEFGLOB:
8908 case SS_KILLED:
8909 case SS_DEAD:
8910 case SS_SPECIAL:
8911 break;
8912 BADDEFAULT;
8913 }
8914 }
8915
8916 if (flip)
8917 {
28bf4b0b 8918 res->definfo = stateInfo_update (res->definfo, other->definfo);
616915dd 8919 res->defstate = s2;
8920 }
8921}
8922
8923extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
8924{
8925 sRef ret;
8926 llassert (sRef_isConj (s));
8927
8928 ret = s->info->conj->a;
8929 llassert (ret != NULL);
8930 return ret;
8931}
8932
8933extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
8934{
8935 sRef ret;
8936 llassert (sRef_isConj (s));
8937
8938 ret = s->info->conj->b;
8939 llassert (ret != NULL);
8940 return ret;
8941}
8942
8943extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
8944{
8945 sRef p;
8946 sRef ret;
28bf4b0b 8947
8948 p = sRef_makePointer (s);
616915dd 8949 ret = sRef_makeField (p, f);
28bf4b0b 8950 return ret;
616915dd 8951}
8952
8953extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
8954{
8955 sRef p;
8956 sRef ret;
8957
8958 p = sRef_buildPointer (s);
8959 ret = sRef_buildField (p, f);
8960
8961 return ret;
8962}
8963
8964static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
8965{
8966 sinfo ret;
8967
8968 switch (s->kind)
8969 {
8970 case SK_CVAR:
8971 ret = (sinfo) dmalloc (sizeof (*ret));
8972 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
8973 ret->cvar->lexlevel = s->info->cvar->lexlevel;
8974 ret->cvar->index = s->info->cvar->index;
8975 break;
8976
8977 case SK_PARAM:
8978 ret = (sinfo) dmalloc (sizeof (*ret));
8979 ret->paramno = s->info->paramno;
28bf4b0b 8980 llassert (ret->paramno >= -1);
616915dd 8981 break;
8982
8983 case SK_ARRAYFETCH:
8984 ret = (sinfo) dmalloc (sizeof (*ret));
8985 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
8986 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
8987 ret->arrayfetch->ind = s->info->arrayfetch->ind;
28bf4b0b 8988 ret->arrayfetch->arr = s->info->arrayfetch->arr; /* sRef_copy (s->info->arrayfetch->arr); */ /*@i32@*/
616915dd 8989 break;
8990
8991 case SK_FIELD:
8992 ret = (sinfo) dmalloc (sizeof (*ret));
8993 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
28bf4b0b 8994 ret->field->rec = s->info->field->rec; /* sRef_copy (s->info->field->rec); */ /*@i32@*/
616915dd 8995 ret->field->field = s->info->field->field;
8996 break;
8997
8998 case SK_OBJECT:
8999 ret = (sinfo) dmalloc (sizeof (*ret));
9000 ret->object = s->info->object;
9001 break;
9002
9003 case SK_PTR:
9004 case SK_ADR:
9005 case SK_DERIVED:
9006 case SK_EXTERNAL:
9007 ret = (sinfo) dmalloc (sizeof (*ret));
28bf4b0b 9008 ret->ref = s->info->ref; /* Ref_copy (s->info->ref); */
616915dd 9009 break;
9010
9011 case SK_CONJ:
9012 ret = (sinfo) dmalloc (sizeof (*ret));
9013 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
28bf4b0b 9014 ret->conj->a = s->info->conj->a; /* sRef_copy (s->info->conj->a); */
9015 ret->conj->b = s->info->conj->b; /* sRef_copy (s->info->conj->b);*/
616915dd 9016 break;
9017 case SK_SPECIAL:
9018 ret = (sinfo) dmalloc (sizeof (*ret));
9019 ret->spec = s->info->spec;
9020 break;
9021 case SK_UNCONSTRAINED:
9022 case SK_NEW:
9023 ret = (sinfo) dmalloc (sizeof (*ret));
9024 ret->fname = s->info->fname;
9025 break;
9026 case SK_RESULT:
9027 case SK_CONST:
9028 case SK_TYPE:
9029 case SK_UNKNOWN:
9030 llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
9031 ret = NULL;
9032 break;
9033 }
9034
9035 return ret;
9036}
9037
9038static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
9039{
9040 sinfo ret;
9041
9042 /*
9043 ** Since its a full copy, only storage is assigned
9044 ** to dependent fields.
9045 */
9046 /*@-onlytrans@*/
9047
9048 switch (s->kind)
9049 {
9050 case SK_CVAR:
9051 ret = (sinfo) dmalloc (sizeof (*ret));
9052 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9053 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9054 ret->cvar->index = s->info->cvar->index;
9055 break;
9056
9057 case SK_PARAM:
9058 ret = (sinfo) dmalloc (sizeof (*ret));
9059 ret->paramno = s->info->paramno;
28bf4b0b 9060 llassert (ret->paramno >= -1);
616915dd 9061 break;
9062
9063 case SK_ARRAYFETCH:
9064 ret = (sinfo) dmalloc (sizeof (*ret));
9065 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9066 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9067 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9068 ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
9069 break;
9070
9071 case SK_FIELD:
9072 ret = (sinfo) dmalloc (sizeof (*ret));
9073 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9074 ret->field->rec = sRef_saveCopy (s->info->field->rec);
9075 ret->field->field = s->info->field->field;
9076 break;
9077
9078 case SK_OBJECT:
9079 ret = (sinfo) dmalloc (sizeof (*ret));
9080 ret->object = s->info->object;
9081 break;
9082
9083 case SK_PTR:
9084 case SK_ADR:
9085 case SK_DERIVED:
9086 case SK_EXTERNAL:
9087 ret = (sinfo) dmalloc (sizeof (*ret));
9088 ret->ref = sRef_saveCopy (s->info->ref);
9089 break;
9090
9091 case SK_CONJ:
9092 ret = (sinfo) dmalloc (sizeof (*ret));
9093 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9094 ret->conj->a = sRef_saveCopy (s->info->conj->a);
9095 ret->conj->b = sRef_saveCopy (s->info->conj->b);
9096 break;
9097 case SK_SPECIAL:
9098 ret = (sinfo) dmalloc (sizeof (*ret));
9099 ret->spec = s->info->spec;
9100 break;
9101 case SK_NEW:
9102 case SK_UNCONSTRAINED:
9103 ret = (sinfo) dmalloc (sizeof (*ret));
9104 ret->fname = s->info->fname;
9105 break;
9106 case SK_CONST:
9107 case SK_TYPE:
9108 case SK_RESULT:
9109 case SK_UNKNOWN:
9110 llassert (s->info == NULL);
9111 ret = NULL;
9112 break;
9113 }
9114 /*@=onlytrans@*/
9115 return ret;
9116}
9117
9118
9119static void
9120 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res,
9121 /*@notnull@*/ /*@exposed@*/ sRef other)
9122{
9123 llassert (res->kind == other->kind);
9124
9125 switch (res->kind)
9126 {
9127 case SK_CVAR:
9128 res->info->cvar->lexlevel = other->info->cvar->lexlevel;
9129 res->info->cvar->index = other->info->cvar->index;
9130 break;
9131
9132 case SK_PARAM:
9133 res->info->paramno = other->info->paramno;
28bf4b0b 9134 llassert (res->info->paramno >= -1);
616915dd 9135 break;
9136
9137 case SK_ARRAYFETCH:
9138 res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
9139 res->info->arrayfetch->ind = other->info->arrayfetch->ind;
9140 res->info->arrayfetch->arr = other->info->arrayfetch->arr;
9141 break;
9142
9143 case SK_FIELD:
9144 res->info->field->rec = other->info->field->rec;
9145 res->info->field->field = other->info->field->field;
9146 break;
9147
9148 case SK_OBJECT:
9149 res->info->object = other->info->object;
9150 break;
9151
9152 case SK_PTR:
9153 case SK_ADR:
9154 case SK_DERIVED:
9155 case SK_EXTERNAL:
9156 res->info->ref = other->info->ref;
9157 break;
9158
9159 case SK_CONJ:
9160 res->info->conj->a = other->info->conj->a;
9161 res->info->conj->b = other->info->conj->b;
9162 break;
9163
9164 case SK_SPECIAL:
9165 res->info->spec = other->info->spec;
9166 break;
9167
9168 case SK_NEW:
9169 case SK_UNCONSTRAINED:
9170 res->info->fname = other->info->fname;
9171 break;
9172
9173 case SK_CONST:
9174 case SK_TYPE:
9175 case SK_UNKNOWN:
9176 case SK_RESULT:
9177 llassert (res->info == NULL);
9178 break;
9179 }
9180}
9181
9182static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
9183 /*@uses s->kind, s->info@*/
9184 /*@releases s->info@*/
9185{
9186 switch (s->kind)
9187 {
9188 case SK_CVAR:
28bf4b0b 9189 DPRINTF (("Free sinfo: [%p]", s->info->cvar));
616915dd 9190 sfree (s->info->cvar);
9191 break;
9192
9193 case SK_PARAM:
9194 break;
9195
9196 case SK_ARRAYFETCH:
28bf4b0b 9197 DPRINTF (("Free sinfo: [%p]", s->info->arrayfetch));
616915dd 9198 sfree (s->info->arrayfetch);
9199 break;
9200
9201 case SK_FIELD:
28bf4b0b 9202 DPRINTF (("Free sinfo: [%p]", s->info->field));
616915dd 9203 sfree (s->info->field);
9204 break;
9205
9206 case SK_OBJECT:
9207 break;
9208
9209 case SK_PTR:
9210 case SK_ADR:
9211 case SK_DERIVED:
28bf4b0b 9212 case SK_EXTERNAL: /*@i32 is copy now! */
616915dd 9213 break;
9214
9215 case SK_CONJ:
28bf4b0b 9216 DPRINTF (("Free sinfo: [%p]", s->info->conj));
616915dd 9217 sfree (s->info->conj);
9218 break;
9219
9220 case SK_UNCONSTRAINED:
9221 case SK_SPECIAL:
9222 case SK_CONST:
9223 case SK_NEW:
9224 case SK_TYPE:
9225 case SK_UNKNOWN:
9226 case SK_RESULT:
9227 break;
9228 }
9229
28bf4b0b 9230 if (s->info != NULL) {
9231 DPRINTF (("Free sinfo: [%p]", s->info));
9232 }
9233
616915dd 9234 sfree (s->info);
9235}
9236
9237bool sRef_isNSLocalVar (sRef s)
9238{
9239 if (sRef_isLocalVar (s))
9240 {
9241 uentry ue = sRef_getUentry (s);
9242
9243 return (!uentry_isStatic (ue));
9244 }
9245 else
9246 {
9247 return FALSE;
9248 }
9249}
9250
9251bool sRef_isLocalVar (sRef s)
9252{
9253 if (sRef_isValid(s))
9254 {
9255 return (s->kind == SK_CVAR
9256 && (s->info->cvar->lexlevel > fileScope));
9257 }
9258
9259 return FALSE;
9260}
9261
9262bool sRef_isRealLocalVar (sRef s)
9263{
9264 if (sRef_isValid(s))
9265 {
9266 if (s->kind == SK_CVAR)
9267 {
9268 if (s->info->cvar->lexlevel == functionScope)
9269 {
9270 uentry ue = sRef_getUentry (s);
9271
9272 if (uentry_isAnyParam (ue)
9273 || uentry_isRefParam (ue))
9274 {
9275 return FALSE;
9276 }
9277 else
9278 {
9279 return TRUE;
9280 }
9281 }
9282 else
9283 {
9284 return (s->info->cvar->lexlevel > functionScope);
9285 }
9286 }
9287 }
9288
9289 return FALSE;
9290}
9291
9292bool sRef_isLocalParamVar (sRef s)
9293{
9294 if (sRef_isValid(s))
9295 {
9296 return (s->kind == SK_PARAM
9297 || (s->kind == SK_CVAR
9298 && (s->info->cvar->lexlevel > fileScope)));
9299 }
9300
9301 return FALSE;
9302}
9303
9304static speckind speckind_fromInt (int i)
9305{
9306 /*@+enumint@*/
9307 llassert (i >= SR_NOTHING && i <= SR_SYSTEM);
9308 /*@=enumint@*/
9309
9310 return ((speckind) i);
9311}
9312
28bf4b0b 9313
9314static void sRef_updateNullState (sRef res, sRef other)
9315 /*@modifies res@*/
9316{
9317 res->nullstate = other->nullstate;
9318 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9319}
9320
616915dd 9321void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9322{
28bf4b0b 9323 nstate n1 = sRef_getNullState (res);
9324 nstate n2 = sRef_getNullState (other);
616915dd 9325 bool flip = FALSE;
9326 nstate nn = n1;
9327
9328 if (n1 == n2 || n2 == NS_UNKNOWN)
9329 {
9330 ;
9331 }
9332 else
9333 {
9334 /* note: n2 is not unknown or defnull */
9335
9336 switch (n1)
9337 {
9338 case NS_ERROR: nn = NS_ERROR; break;
9339 case NS_UNKNOWN: flip = TRUE; nn = n2; break;
9340 case NS_POSNULL: break;
9341 case NS_DEFNULL: nn = NS_POSNULL; break;
9342 case NS_RELNULL: break;
9343 case NS_NOTNULL:
9344 if (n2 == NS_MNOTNULL)
9345 {
9346 ;
9347 }
9348 else
9349 {
9350 flip = TRUE;
9351 nn = NS_POSNULL;
9352 }
9353 break;
9354 case NS_MNOTNULL:
9355 if (n2 == NS_NOTNULL)
9356 {
9357 nn = NS_NOTNULL;
9358 }
9359 else
9360 {
9361 flip = TRUE;
9362 nn = NS_POSNULL;
9363 }
9364 break;
9365 case NS_CONSTNULL:
9366 case NS_ABSNULL:
9367 flip = TRUE;
9368 nn = n2;
9369 }
9370 }
9371
9372 if (flip)
9373 {
28bf4b0b 9374 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
616915dd 9375 }
9376
9377 res->nullstate = nn;
9378}
9379
9380cstring sRef_nullMessage (sRef s)
9381{
9382 llassert (sRef_isValid (s));
9383
28bf4b0b 9384 switch (sRef_getNullState (s))
616915dd 9385 {
9386 case NS_DEFNULL:
9387 case NS_CONSTNULL:
9388 return (cstring_makeLiteralTemp ("null"));
9389 default:
9390 return (cstring_makeLiteralTemp ("possibly null"));
9391 }
9392 BADEXIT;
9393}
9394
9395/*@observer@*/ cstring sRef_ntMessage (sRef s)
9396{
9397 llassert (sRef_isValid (s));
9398
9399 switch (s->nullstate)
9400 {
9401 case NS_DEFNULL:
9402 case NS_CONSTNULL:
9403 return (cstring_makeLiteralTemp ("not nullterminated"));
9404 default:
9405 return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
9406 }
9407 BADEXIT;
9408}
9409
9410
9411
9412sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
9413{
9414 sRef tmp = sRef_undefined;
9415 sRef ret;
9416
9417 llassert (sRef_isValid (s));
9418
9419 switch (s->kind)
9420 {
9421 case SK_RESULT:
9422 s->type = typ;
9423 ret = s;
9424 break;
9425 case SK_ARRAYFETCH:
9426 {
9427 ctype ct;
9428 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9429
9430 ct = ctype_realType (sRef_getType (tmp));
9431
9432
9433 if (ctype_isKnown (ct))
9434 {
9435 if (ctype_isAP (ct))
9436 {
9437 ;
9438 }
9439 else
9440 {
9441 voptgenerror
9442 (FLG_TYPE,
9443 message
9444 ("Special clause indexes non-array (%t): *%q",
9445 ct, sRef_unparse (s->info->arrayfetch->arr)),
9446 uentry_whereLast (ue));
9447 }
9448 }
9449
9450 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9451
9452 if (s->info->arrayfetch->indknown)
9453 {
9454 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
9455 }
9456 else
9457 {
9458 ret = sRef_makeArrayFetch (tmp);
9459 }
9460 }
9461 break;
9462 case SK_FIELD:
9463 {
9464 sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
9465 ctype ct = ctype_realType (sRef_getType (rec));
9466
9467 if (ctype_isKnown (ct))
9468 {
9469 if (ctype_isSU (ct))
9470 {
9471 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct),
9472 s->info->field->field)))
9473 {
9474 ;
9475 }
9476 else
9477 {
9478 voptgenerror
9479 (FLG_TYPE,
9480 message
9481 ("Special clause accesses non-existent field of result: %q.%s",
9482 sRef_unparse (rec), s->info->field->field),
9483 uentry_whereLast (ue));
9484 }
9485 }
9486 else
9487 {
9488 voptgenerror
9489 (FLG_TYPE,
9490 message
9491 ("Special clause accesses field of non-struct or union result (%t): %q.%s",
9492 ct, sRef_unparse (rec), s->info->field->field),
9493 uentry_whereLast (ue));
9494 }
9495 }
9496
9497 ret = sRef_makeField (tmp, s->info->field->field);
9498 break;
9499 }
9500 case SK_PTR:
9501 {
9502 ctype ct;
9503 tmp = sRef_fixResultType (s->info->ref, typ, ue);
9504
9505 ct = ctype_realType (sRef_getType (tmp));
9506
9507 if (ctype_isKnown (ct))
9508 {
9509 if (ctype_isAP (ct))
9510 {
9511 ;
9512 }
9513 else
9514 {
9515 voptgenerror
9516 (FLG_TYPE,
9517 message
9518 ("Special clause dereferences non-pointer (%t): *%q",
9519 ct, sRef_unparse (s->info->ref)),
9520 uentry_whereLast (ue));
9521 }
9522 }
9523
9524 ret = sRef_makePointer (tmp);
9525 break;
9526 }
9527 case SK_ADR:
9528 voptgenerror
9529 (FLG_TYPE,
9530 message
9531 ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9532 uentry_whereLast (ue));
9533 ret = s;
9534 break;
9535 BADDEFAULT;
9536 }
9537
9538 return ret;
9539}
9540
9541bool sRef_isOnly (sRef s)
9542{
9543 return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9544}
9545
9546bool sRef_isDependent (sRef s)
9547{
9548 return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9549}
9550
9551bool sRef_isOwned (sRef s)
9552{
9553 return (sRef_isValid (s) && (s->aliaskind == AK_OWNED));
9554}
9555
9556bool sRef_isKeep (sRef s)
9557{
9558 return (sRef_isValid (s) && (s->aliaskind == AK_KEEP));
9559}
9560
9561bool sRef_isTemp (sRef s)
9562{
9563 return (sRef_isValid (s) && alkind_isTemp (s->aliaskind));
9564}
9565
9566bool sRef_isLocalState (sRef s)
9567{
9568 return (sRef_isValid (s) && (s->aliaskind == AK_LOCAL));
9569}
9570
9571bool sRef_isUnique (sRef s)
9572{
9573 return (sRef_isValid (s) && (s->aliaskind == AK_UNIQUE));
9574}
9575
9576bool sRef_isShared (sRef s)
9577{
9578 return (sRef_isValid (s) && (s->aliaskind == AK_SHARED));
9579}
9580
9581bool sRef_isExposed (sRef s)
9582{
9583 return (sRef_isValid (s) && (s->expkind == XO_EXPOSED));
9584}
9585
9586bool sRef_isObserver (sRef s)
9587{
9588 return (sRef_isValid (s) && (s->expkind == XO_OBSERVER));
9589}
9590
9591bool sRef_isFresh (sRef s)
9592{
9593 return (sRef_isValid (s) && (s->aliaskind == AK_FRESH));
9594}
9595
9596bool sRef_isDefinitelyNull (sRef s)
9597{
28bf4b0b 9598 return (sRef_isValid (s) && (sRef_getNullState (s) == NS_DEFNULL
9599 || sRef_getNullState (s) == NS_CONSTNULL));
616915dd 9600}
9601
9602bool sRef_isAllocated (sRef s)
9603{
9604 return (sRef_isValid (s) && (s->defstate == SS_ALLOCATED));
9605}
9606
9607bool sRef_isStack (sRef s)
9608{
9609 return (sRef_isValid (s) && (s->aliaskind == AK_STACK));
9610}
9611
28bf4b0b 9612bool sRef_isNotNull (sRef s)
9613{
9614 return (sRef_isValid(s) && (sRef_getNullState (s) == NS_MNOTNULL
9615 || sRef_getNullState (s) == NS_NOTNULL));
9616}
9617
9618alkind sRef_getAliasKind (sRef s)
9619{
9620 if (sRef_isValid(s)) {
9621 llassert (alkind_isValid (s->aliaskind));
9622 return s->aliaskind;
9623 }
9624
9625 return AK_ERROR;
9626}
9627
9628nstate sRef_getNullState (sRef s)
9629{
9630 if (sRef_isValid (s)) {
9631 llassert (nstate_isValid (s->nullstate));
9632 return s->nullstate;
9633 }
9634
9635 return NS_UNKNOWN;
9636}
9637
9638void sRef_reflectAnnotation (sRef s, annotationInfo a, fileloc loc)
9639{
9640 if (sRef_isValid (s))
9641 {
9642 if (!valueTable_isDefined (s->state))
9643 {
9644 s->state = valueTable_create (1);
9645 valueTable_insert (s->state,
9646 cstring_copy (metaStateInfo_getName (annotationInfo_getState (a))),
9647 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9648 }
9649 else
9650 {
9651 DPRINTF (("reflect loc: %s", fileloc_unparse (loc)));
9652 valueTable_update
9653 (s->state,
9654 metaStateInfo_getName (annotationInfo_getState (a)),
9655 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9656 DPRINTF (("state info: %s", stateInfo_unparse (stateInfo_makeLoc (loc))));
9657 DPRINTF (("sref: %s", sRef_unparse (s)));
9658 DPRINTF (("sref: %s", sRef_unparseFull (s)));
9659 }
9660 }
9661}
9662
9663void sRef_setMetaStateValueComplete (sRef s, cstring key, int value, fileloc loc)
9664{
9665 sRefSet aliases = usymtab_allAliases (s);
9666
9667 sRef_setMetaStateValue (s, key, value, loc);
9668
9669 sRefSet_realElements (aliases, current)
9670 {
9671 if (sRef_isValid (current))
9672 {
9673 current = sRef_updateSref (current);
9674 sRef_setMetaStateValue (current, key, value, loc);
9675 }
9676 } end_sRefSet_realElements ;
9677
9678 sRefSet_free (aliases);
9679}
9680
9681void sRef_setMetaStateValue (sRef s, cstring key, int value, fileloc loc)
9682{
9683 sRef_checkMutable (s);
9684
9685 if (sRef_isValid (s))
9686 {
9687 if (!valueTable_isDefined (s->state))
9688 {
9689 DPRINTF (("inserting state: %s: %s %d", sRef_unparse (s), key, value));
9690 s->state = valueTable_create (1);
9691 valueTable_insert (s->state, cstring_copy (key),
9692 stateValue_create (value, stateInfo_makeLoc (loc)));
9693 }
9694 else
9695 {
9696 DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s), key, value,
9697 fileloc_unparse (loc)));
2c88d156 9698 if (valueTable_contains (s->state, key))
9699 {
9700 valueTable_update
9701 (s->state, key, stateValue_create (value, stateInfo_makeLoc (loc)));
9702 }
9703 else
9704 {
9705 valueTable_insert
9706 (s->state, cstring_copy (key), stateValue_create (value, stateInfo_makeLoc (loc)));
9707 }
9708
28bf4b0b 9709 DPRINTF (("After: %s", sRef_unparseFull (s)));
9710 }
9711 }
9712}
9713
9714bool sRef_checkMetaStateValue (sRef s, cstring key, int value)
9715{
9716 if (sRef_isValid (s))
9717 {
9718 if (valueTable_isDefined (s->state))
9719 {
9720 stateValue val;
9721
9722 DPRINTF (("check state: %s: %s %d", sRef_unparse (s), key, value));
9723
9724 val = valueTable_lookup (s->state, key);
9725 llassert (stateValue_isDefined (val));
9726 return (stateValue_isError (val)
9727 || stateValue_getValue (val) == value);
9728 }
9729 else
9730 {
9731 return TRUE;
9732 }
9733 }
9734 else
9735 {
9736 return TRUE;
9737 }
9738}
9739
9740/*@observer@*/ stateValue sRef_getMetaStateValue (sRef s, cstring key)
9741{
9742 if (sRef_isValid (s))
9743 {
9744 if (valueTable_isDefined (s->state))
9745 {
9746 stateValue val;
9747
9748 val = valueTable_lookup (s->state, key);
2c88d156 9749 /* Okay if its not defined, just returns stateValue_undefined */
28bf4b0b 9750 return val;
9751 }
9752 else
9753 {
9754 return stateValue_undefined;
9755 }
9756 }
9757 else
9758 {
9759 return stateValue_undefined;
9760 }
9761}
9762
9763/*@observer@*/ valueTable sRef_getValueTable (sRef s)
9764{
9765 DPRINTF (("Get value table: %s", sRef_unparse (s)));
9766
9767 if (sRef_isValid (s))
9768 {
9769 llassert (sRef_isValid (s));
9770 DPRINTF (("Value table: %s", valueTable_unparse (s->state)));
9771 return s->state;
9772 }
9773 else
9774 {
9775 DPRINTF (("No value table!"));
9776 return valueTable_undefined;
9777 }
9778}
9779
9780bool sRef_makeStateSpecial (sRef s)
9781{
9782 /*
9783 ** Default defined state can be made special.
9784 */
9785
9786 llassert (sRef_isValid (s)); /*@i523 why doesn't null-checking work!??? */
9787
9788 if (s->defstate == SS_UNKNOWN || s->defstate == SS_DEFINED || s->defstate == SS_SPECIAL)
9789 {
ccf0a4a8 9790 /* s->aliaskind = AK_IMPTEMP; */ /* evans 2001-07-23 shouldn't effect alias state */
28bf4b0b 9791 s->defstate = SS_SPECIAL;
9792 DPRINTF (("Made special: %s", sRef_unparseFull (s)));
9793 return TRUE;
9794 }
9795 else
9796 {
ccf0a4a8 9797 /* s->aliaskind = AK_IMPTEMP; */
28bf4b0b 9798 s->defstate = SS_SPECIAL;
9799 return FALSE;
9800 }
9801}
9802
9803void sRef_markImmutable (sRef s)
616915dd 9804{
28bf4b0b 9805 if (sRef_isValid (s))
9806 {
9807 DPRINTF (("Mark immutable: %s", sRef_unparseFull (s)));
9808 s->immut = TRUE;
9809 }
9810}
9811
9812bool sRef_definitelyNullContext (sRef s)
9813{
9814 return (sRef_definitelyNull (s)
9815 || usymtab_isDefinitelyNullDeep (s));
9816}
9817
9818bool sRef_definitelyNullAltContext (sRef s)
9819{
9820 return (sRef_definitelyNull (s)
9821 || usymtab_isAltDefinitelyNullDeep (s));
616915dd 9822}
9823
28bf4b0b 9824
616915dd 9825/* start modifications */
28bf4b0b 9826struct s_bbufinfo sRef_getNullTerminatedState (sRef p_s) {
9827 struct s_bbufinfo BUFSTATE_UNKNOWN;
616915dd 9828 BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
9829 BUFSTATE_UNKNOWN.size = 0;
9830 BUFSTATE_UNKNOWN.len = 0;
9831
9832 if (sRef_isValid(p_s))
9833 return p_s->bufinfo;
9834 return BUFSTATE_UNKNOWN;
9835}
9836
9837void sRef_setNullTerminatedState(sRef p_s) {
9838 if(sRef_isValid (p_s)) {
9839 p_s->bufinfo.bufstate = BB_NULLTERMINATED;
9840 } else {
9841 llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
9842 }
9843}
9844
9845
9846void sRef_setPossiblyNullTerminatedState(sRef p_s) {
9847 if( sRef_isValid (p_s)) {
9848 p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
9849 } else {
9850 llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
9851 }
9852}
9853
9854void sRef_setNotNullTerminatedState(sRef p_s) {
9855 if( sRef_isValid (p_s)) {
9856 p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
9857 } else {
9858 llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
9859 }
9860}
9861
9862void sRef_setLen(sRef p_s, int len) {
9863 if( sRef_isValid (p_s) && sRef_isNullTerminated(p_s)) {
9864 p_s->bufinfo.len = len;
9865 } else {
9866 llfatalbug( message("sRef_setLen passed a invalid sRef\n"));
9867 }
9868}
9869
9870
9871void sRef_setSize(sRef p_s, int size) {
9872 if( sRef_isValid(p_s)) {
9873 p_s->bufinfo.size = size;
9874 } else {
9875 llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
9876 }
9877}
9878
9879void sRef_resetLen(sRef p_s) {
9880 if (sRef_isValid (p_s)) {
9881 p_s->bufinfo.len = 0;
9882 } else {
9883 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
9884 }
9885}
9886
9887/*drl7x 11/28/2000 */
9888
dc92450f 9889bool sRef_isFixedArray (sRef p_s) /*@*/ {
616915dd 9890 ctype c;
9891 c = sRef_getType (p_s);
9892 return ( ctype_isFixedArray (c) );
9893}
9894
dc92450f 9895long int sRef_getArraySize (sRef p_s) /*@*/ {
616915dd 9896 ctype c;
9897 llassert (sRef_isFixedArray(p_s) );
470b7798 9898 DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) ) ));
9899
616915dd 9900 c = sRef_getType (p_s);
9901
9902 return (ctype_getArraySize (c) );
9903}
9904
b9904f57 9905void sRef_setValue (sRef s, multiVal val)
9906{
9907 llassert (sRef_isValid (s));
9908 multiVal_free (s->val);
9909 s->val = val;
9910}
9911
9912bool sRef_hasValue (sRef s)
9913{
9914 return (sRef_isValid (s)
9915 && multiVal_isDefined (s->val));
9916}
9917
9918multiVal sRef_getValue (sRef s)
9919{
9920 if (sRef_isValid (s))
9921 {
9922 return s->val;
9923 }
9924
9925 return multiVal_undefined;
9926}
This page took 1.491364 seconds and 5 git commands to generate.