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