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