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