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
28 # include "splintMacros.nf"
31 static bool mtContextNode_matchesType (mtContextNode
, ctype
) /*@*/ ;
33 static /*@observer@*/ cstring
mtContextKind_unparse (mtContextKind ck
)
37 case MTC_ANY
: return cstring_makeLiteralTemp ("any");
38 case MTC_PARAM
: return cstring_makeLiteralTemp ("parameter");
39 case MTC_RESULT
: return cstring_makeLiteralTemp ("result");
40 case MTC_REFERENCE
: return cstring_makeLiteralTemp ("reference");
41 case MTC_CLAUSE
: return cstring_makeLiteralTemp ("clause");
42 case MTC_LITERAL
: return cstring_makeLiteralTemp ("literal");
43 case MTC_NULL
: return cstring_makeLiteralTemp ("null");
46 BADBRANCHRET (cstring_undefined
);
49 static mtContextNode
mtContextNode_create (mtContextKind context
, ctype ct
)
51 mtContextNode res
= (mtContextNode
) dmalloc (sizeof (*res
));
52 res
->context
= context
;
54 DPRINTF (("Create: %s", mtContextNode_unparse (res
)));
58 extern mtContextNode
mtContextNode_createAny (void)
60 return mtContextNode_create (MTC_ANY
, ctype_unknown
);
63 extern mtContextNode
mtContextNode_createParameter (ctype ct
)
65 return mtContextNode_create (MTC_PARAM
, ct
);
68 extern mtContextNode
mtContextNode_createResult (ctype ct
)
70 return mtContextNode_create (MTC_RESULT
, ct
);
73 extern mtContextNode
mtContextNode_createReference (ctype ct
)
75 return mtContextNode_create (MTC_REFERENCE
, ct
);
78 extern mtContextNode
mtContextNode_createClause (ctype ct
)
80 return mtContextNode_create (MTC_CLAUSE
, ct
);
83 extern mtContextNode
mtContextNode_createLiteral (ctype ct
)
85 return mtContextNode_create (MTC_LITERAL
, ct
);
88 extern mtContextNode
mtContextNode_createNull (ctype ct
)
90 return mtContextNode_create (MTC_NULL
, ct
);
93 extern void mtContextNode_free (/*@only@*/ mtContextNode node
)
98 bool mtContextNode_matchesEntry (mtContextNode context
, uentry ue
)
102 llassert (mtContextNode_isDefined (context
));
104 DPRINTF (("Matches context: %s / %s",
105 mtContextNode_unparse (context
), uentry_unparse (ue
)));
107 switch (context
->context
)
109 case MTC_ANY
: break; /* everything matches */
111 if (!uentry_isFunction (ue
))
117 if (!uentry_isAnyParam (ue
))
119 DPRINTF (("not param: %s", uentry_unparseFull (ue
)));
132 if (uentry_isFunction (ue
))
134 ct
= ctype_getReturnType (uentry_getType (ue
));
138 ct
= uentry_getType (ue
);
141 return mtContextNode_matchesType (context
, ct
);
144 bool mtContextNode_matchesRef (mtContextNode context
, sRef sr
)
148 llassert (mtContextNode_isDefined (context
));
150 DPRINTF (("Matches context: %s / %s",
151 mtContextNode_unparse (context
), sRef_unparse (sr
)));
153 switch (context
->context
)
155 case MTC_ANY
: break; /* everything matches */
157 DPRINTF (("Result? %s / %s",
158 sRef_unparseFull (sr
),
159 bool_unparse (sRef_isResult (sr
))));
160 return sRef_isResult (sr
);
162 if (!sRef_isParam (sr
))
168 DPRINTF (("Literal: %s", sRef_unparse (sr
)));
169 if (!sRef_isConst (sr
))
181 ct
= sRef_getType (sr
);
182 return mtContextNode_matchesType (context
, ct
);
185 bool mtContextNode_matchesRefStrict (mtContextNode context
, sRef s
)
187 if (mtContextNode_isDefined (context
)
188 && mtContextNode_matchesRef (context
, s
))
190 if (ctype_isKnown (context
->type
)
191 && (ctype_isUnknown (sRef_getType (s
))
192 || ctype_isVoidPointer (sRef_getType (s
))))
205 bool mtContextNode_matchesType (mtContextNode context
, ctype ct
)
207 DPRINTF (("Context type..."));
208 llassert (mtContextNode_isDefined (context
));
210 if (!ctype_match (context
->type
, ct
))
212 DPRINTF (("Type mismatch: %s / %s",
213 ctype_unparse (context
->type
),
214 ctype_unparse (ct
)));
219 /* evans 2001-08-21 - don't match if only one type is unknown */
220 if (ctype_isUnknown (ct
) && !ctype_isUnknown (context
->type
))
225 DPRINTF (("Type okay: %s / %s",
226 ctype_unparse (context
->type
),
227 ctype_unparse (ct
)));
233 cstring
mtContextNode_unparse (mtContextNode node
)
235 llassert (mtContextNode_isDefined (node
));
237 if (ctype_isKnown (node
->type
))
239 return message ("%s %s", mtContextKind_unparse (node
->context
),
240 ctype_unparse (node
->type
));
244 return message ("%s", mtContextKind_unparse (node
->context
));
249 bool mtContextNode_isClause (mtContextNode n
)
251 llassert (mtContextNode_isDefined (n
));
252 return (n
->context
== MTC_CLAUSE
);
254 # endif /* DEADCODE */
256 bool mtContextNode_isParameter (mtContextNode n
)
258 llassert (mtContextNode_isDefined (n
));
259 return (n
->context
== MTC_PARAM
);
262 bool mtContextNode_isReference (mtContextNode n
)
264 llassert (mtContextNode_isDefined (n
));
265 return (n
->context
== MTC_REFERENCE
);
268 bool mtContextNode_isResult (mtContextNode n
)
270 llassert (mtContextNode_isDefined (n
));
271 return (n
->context
== MTC_RESULT
);
274 bool mtContextNode_isLiteral (mtContextNode n
)
276 llassert (mtContextNode_isDefined (n
));
277 return (n
->context
== MTC_LITERAL
);
280 bool mtContextNode_isNull (mtContextNode n
)
282 llassert (mtContextNode_isDefined (n
));
283 return (n
->context
== MTC_NULL
);
287 void mtContextNode_showRefError (mtContextNode context
, sRef sr
)
291 llassert (mtContextNode_isDefined (context
));
292 llassert (!mtContextNode_matchesRef (context
, sr
));
294 DPRINTF (("Matches context: %s / %s",
295 mtContextNode_unparse (context
), sRef_unparse (sr
)));
297 switch (context
->context
)
299 case MTC_ANY
: break; /* everything matches */
301 if (!sRef_isResult (sr
))
304 (message ("Context is result, doesn't match %q", sRef_unparse (sr
)));
309 if (!sRef_isResult (sr
))
312 (message ("Context is parameter, doesn't match %q", sRef_unparse (sr
)));
317 DPRINTF (("Literal: %s", sRef_unparse (sr
)));
318 if (!sRef_isConst (sr
))
321 (message ("Context is literal, doesn't match %q", sRef_unparse (sr
)));
332 ct
= sRef_getType (sr
);
334 if (!mtContextNode_matchesType (context
, ct
))
337 (message ("Context type is %s, doesn't match type %s",
338 ctype_unparse (context
->type
),
339 ctype_unparse (ct
)));
346 # endif /* DEADCODE */