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