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