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