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