2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
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.
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.
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.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
25 # include "splintMacros.nf"
28 static /*@observer@*/ cstring
stateAction_unparse (stateAction p_sa
) /*@*/ ;
29 static /*@only@*/ /*@notnull@*/ stateInfo
stateInfo_makeRefLoc (
30 /*@exposed@*/ sRef p_ref
, fileloc p_loc
, stateAction p_action
) /*@*/ ;
33 void stateInfo_free (/*@only@*/ stateInfo a
)
37 fileloc_free (a
->loc
);
38 /* shouldn't we free a->previous? most likely memory leak */
43 /*@only@*/ stateInfo
stateInfo_update (/*@only@*/ stateInfo old
, stateInfo newinfo
)
45 ** returns an stateInfo with the same value as new. May reuse the
46 ** storage of old. (i.e., same effect as copy, but more
52 DPRINTF (("Update state ==> %s", stateInfo_unparse (newinfo
)));
53 return stateInfo_copy (newinfo
);
55 else if (newinfo
== NULL
)
62 if (fileloc_equal (old
->loc
, newinfo
->loc
)
63 && old
->action
== newinfo
->action
64 /*@-abstractcompare@*/ && old
->ref
== newinfo
->ref
/*@=abstractcompare@*/)
67 ** Duplicate (change through alias most likely)
68 ** don't add this info
75 stateInfo snew
= stateInfo_makeRefLoc (newinfo
->ref
,
76 newinfo
->loc
, newinfo
->action
);
77 llassert (snew
->previous
== NULL
);
79 DPRINTF (("Update state ==> %s", stateInfo_unparse (snew
)));
85 static /*@observer@*/ stateInfo
stateInfo_sort (/*@temp@*/ stateInfo stinfo
)
86 /* Sorts in reverse location order */
88 DPRINTF (("Sorting: %s", stateInfo_unparse (stinfo
)));
90 if (stinfo
== NULL
|| stinfo
->previous
== NULL
)
96 stateInfo snext
= stateInfo_sort (stinfo
->previous
);
97 stateInfo sfirst
= snext
;
99 DPRINTF (("stinfo/sext: %s // %s", stateInfo_unparse (stinfo
), stateInfo_unparse (snext
)));
100 llassert (snext
!= NULL
);
102 if (!fileloc_lessthan (stinfo
->loc
, snext
->loc
))
104 /*@i2@*/ stinfo
->previous
= sfirst
; /* spurious? */
105 DPRINTF (("Sorted ==> %s", stateInfo_unparse (stinfo
)));
106 /*@i2@*/ return stinfo
; /* spurious? */
110 while (snext
!= NULL
&& fileloc_lessthan (stinfo
->loc
, snext
->loc
))
115 fileloc tloc
= snext
->loc
;
116 stateAction taction
= snext
->action
;
117 sRef tref
= snext
->ref
;
119 DPRINTF (("in while: stinfo/sext: %s // %s", stateInfo_unparse (stinfo
), stateInfo_unparse (snext
)));
121 snext
->loc
= stinfo
->loc
;
122 snext
->action
= stinfo
->action
;
124 snext
->ref
= stinfo
->ref
; /* Doesn't actually modifie sfirst */
128 stinfo
->action
= taction
;
131 stinfo
->previous
= snext
->previous
;
133 snext
= snext
->previous
;
134 DPRINTF (("in while: stinfo/sext: %s // %s", stateInfo_unparse (stinfo
), stateInfo_unparse (snext
)));
137 DPRINTF (("Sorted ==> %s", stateInfo_unparse (sfirst
)));
146 stateInfo_updateLoc (/*@only@*/ stateInfo old
, stateAction action
, fileloc loc
)
148 if (fileloc_isUndefined (loc
)) {
149 loc
= fileloc_copy (g_currentloc
);
152 if (old
!= NULL
&& fileloc_equal (old
->loc
, loc
) && old
->action
== action
)
155 ** Duplicate (change through alias most likely)
156 ** don't add this info
163 stateInfo snew
= stateInfo_makeLoc (loc
, action
);
164 llassert (snew
->previous
== NULL
);
165 snew
->previous
= old
;
166 DPRINTF (("Update state ==> %s", stateInfo_unparse (snew
)));
172 stateInfo_updateRefLoc (/*@only@*/ stateInfo old
, /*@exposed@*/ sRef ref
,
173 stateAction action
, fileloc loc
)
175 if (fileloc_isUndefined (loc
)) {
176 loc
= fileloc_copy (g_currentloc
);
179 if (old
!= NULL
&& fileloc_equal (old
->loc
, loc
)
180 && old
->action
== action
181 /*@-abstractcompare*/ && old
->ref
== ref
/*@=abstractcompare@*/)
184 ** Duplicate (change through alias most likely)
185 ** don't add this info
192 stateInfo snew
= stateInfo_makeRefLoc (ref
, loc
, action
);
193 llassert (snew
->previous
== NULL
);
194 snew
->previous
= old
;
195 DPRINTF (("Update state ==> %s", stateInfo_unparse (snew
)));
200 /*@only@*/ stateInfo
stateInfo_copy (stateInfo a
)
208 stateInfo ret
= (stateInfo
) dmalloc (sizeof (*ret
));
210 ret
->loc
= fileloc_copy (a
->loc
); /*< should report bug without copy! >*/
212 ret
->action
= a
->action
;
213 ret
->previous
= stateInfo_copy (a
->previous
);
219 /*@only@*/ /*@notnull@*/ stateInfo
220 stateInfo_currentLoc (void)
222 return stateInfo_makeLoc (g_currentloc
, SA_DECLARED
);
225 /*@only@*/ /*@notnull@*/ stateInfo
226 stateInfo_makeLoc (fileloc loc
, stateAction action
)
228 return stateInfo_makeRefLoc (sRef_undefined
, loc
, action
);
231 static /*@only@*/ /*@notnull@*/ stateInfo
232 stateInfo_makeRefLoc (/*@exposed@*/ sRef ref
, fileloc loc
, stateAction action
)
233 /*@post:isnull result->previous@*/
235 stateInfo ret
= (stateInfo
) dmalloc (sizeof (*ret
));
237 if (fileloc_isUndefined (loc
)) {
238 ret
->loc
= fileloc_copy (g_currentloc
);
240 ret
->loc
= fileloc_copy (loc
);
244 ret
->action
= action
;
245 ret
->previous
= stateInfo_undefined
;
247 DPRINTF (("Make loc ==> %s", stateInfo_unparse (ret
)));
252 stateInfo_unparse (stateInfo s
)
254 cstring res
= cstring_makeLiteral ("");
256 while (stateInfo_isDefined (s
)) {
257 res
= message ("%q%q: ", res
, fileloc_unparse (s
->loc
));
258 if (sRef_isValid (s
->ref
)) {
259 res
= message ("%q through alias %q ", res
, sRef_unparse (s
->ref
));
262 res
= message ("%q%s; ", res
, stateAction_unparse (s
->action
));
269 fileloc
stateInfo_getLoc (stateInfo info
)
271 if (stateInfo_isDefined (info
))
276 return fileloc_undefined
;
279 stateAction
stateAction_fromNState (nstate ns
)
289 return SA_BECOMESNONNULL
;
294 return SA_BECOMESPOSSIBLYNULL
;
296 return SA_BECOMESNULL
;
298 return SA_BECOMESPOSSIBLYNULL
;
302 stateAction
stateAction_fromExkind (exkind ex
)
316 /*@notreached@*/ return SA_UNKNOWN
;
319 stateAction
stateAction_fromAlkind (alkind ak
)
348 return SA_REFCOUNTED
;
359 case AK_IMPDEPENDENT
:
360 return SA_IMPDEPENDENT
;
368 /*@notreached@*/ return SA_UNKNOWN
;
371 stateAction
stateAction_fromSState (sstate ss
)
375 case SS_UNKNOWN
: return SA_DECLARED
;
376 case SS_UNUSEABLE
: return SA_KILLED
;
377 case SS_UNDEFINED
: return SA_UNDEFINED
;
378 case SS_MUNDEFINED
: return SA_MUNDEFINED
;
379 case SS_ALLOCATED
: return SA_ALLOCATED
;
380 case SS_PDEFINED
: return SA_PDEFINED
;
381 case SS_DEFINED
: return SA_DEFINED
;
382 case SS_PARTIAL
: return SA_PDEFINED
;
383 case SS_DEAD
: return SA_RELEASED
;
384 case SS_HOFFA
: return SA_PKILLED
;
385 case SS_SPECIAL
: return SA_DECLARED
;
386 case SS_RELDEF
: return SA_DECLARED
;
388 llbug (message ("Unexpected sstate: %s", sstate_unparse (ss
)));
389 /*@notreached@*/ return SA_UNKNOWN
;
393 static /*@observer@*/ cstring
stateAction_unparse (stateAction sa
)
397 case SA_UNKNOWN
: return cstring_makeLiteralTemp ("changed <unknown modification>");
398 case SA_CHANGED
: return cstring_makeLiteralTemp ("changed");
400 case SA_CREATED
: return cstring_makeLiteralTemp ("created");
401 case SA_DECLARED
: return cstring_makeLiteralTemp ("declared");
402 case SA_DEFINED
: return cstring_makeLiteralTemp ("defined");
403 case SA_PDEFINED
: return cstring_makeLiteralTemp ("partially defined");
404 case SA_RELEASED
: return cstring_makeLiteralTemp ("released");
405 case SA_ALLOCATED
: return cstring_makeLiteralTemp ("allocated");
406 case SA_KILLED
: return cstring_makeLiteralTemp ("released");
407 case SA_PKILLED
: return cstring_makeLiteralTemp ("possibly released");
408 case SA_MERGED
: return cstring_makeLiteralTemp ("merged");
409 case SA_UNDEFINED
: return cstring_makeLiteralTemp ("becomes undefined");
410 case SA_MUNDEFINED
: return cstring_makeLiteralTemp ("possibly undefined");
412 case SA_SHARED
: return cstring_makeLiteralTemp ("becomes shared");
413 case SA_ONLY
: return cstring_makeLiteralTemp ("becomes only");
414 case SA_IMPONLY
: return cstring_makeLiteralTemp ("becomes implicitly only");
415 case SA_OWNED
: return cstring_makeLiteralTemp ("becomes owned");
416 case SA_DEPENDENT
: return cstring_makeLiteralTemp ("becomes dependent");
417 case SA_IMPDEPENDENT
: return cstring_makeLiteralTemp ("becomes implicitly dependent");
418 case SA_KEPT
: return cstring_makeLiteralTemp ("becomes kept");
419 case SA_KEEP
: return cstring_makeLiteralTemp ("becomes keep");
420 case SA_FRESH
: return cstring_makeLiteralTemp ("becomes fresh");
421 case SA_TEMP
: return cstring_makeLiteralTemp ("becomes temp");
422 case SA_IMPTEMP
: return cstring_makeLiteralTemp ("becomes implicitly temp");
423 case SA_XSTACK
: return cstring_makeLiteralTemp ("becomes stack-allocated storage");
424 case SA_STATIC
: return cstring_makeLiteralTemp ("becomes static");
425 case SA_LOCAL
: return cstring_makeLiteralTemp ("becomes local");
427 case SA_REFCOUNTED
: return cstring_makeLiteralTemp ("becomes refcounted");
428 case SA_REFS
: return cstring_makeLiteralTemp ("becomes refs");
429 case SA_NEWREF
: return cstring_makeLiteralTemp ("becomes newref");
430 case SA_KILLREF
: return cstring_makeLiteralTemp ("becomes killref");
432 case SA_OBSERVER
: return cstring_makeLiteralTemp ("becomes observer");
433 case SA_EXPOSED
: return cstring_makeLiteralTemp ("becomes exposed");
435 case SA_BECOMESNULL
: return cstring_makeLiteralTemp ("becomes null");
436 case SA_BECOMESNONNULL
: return cstring_makeLiteralTemp ("becomes non-null");
437 case SA_BECOMESPOSSIBLYNULL
: return cstring_makeLiteralTemp ("becomes possibly null");
438 default: BADBRANCHRET (cstring_undefined
);
442 void stateInfo_display (stateInfo s
, cstring sname
)
444 bool showdeep
= context_flagOn (FLG_SHOWDEEPHISTORY
, g_currentloc
);
446 s
= stateInfo_sort (s
);
448 while (stateInfo_isDefined (s
))
450 cstring msg
= message ("%s%s", sname
, stateAction_unparse (s
->action
));
452 if (sRef_isValid (s
->ref
)) {
453 msg
= message ("%q (through alias %q)", msg
, sRef_unparse (s
->ref
));
456 llgenindentmsg (msg
, s
->loc
);
465 cstring_free (sname
);