2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 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 cprim_isReal (cprim c)
33 return (cprim_isAnyReal (c));
36 static bool cprim_isNumeric (cprim c)
38 return (cprim_isReal (c) || cprim_isInt (c));
44 if (i < CTX_UNKNOWN || i > CTX_LAST)
46 llcontbug (message ("cprim_fromInt: out of range: %d", i));
54 ** not symmetric: c1 := c2 or c2 is passed as c1
55 ** (if RELAXQUALS, c1 must be "bigger" than c2)
58 static bool cprim_closeEnoughAux (cprim p_c1, cprim p_c2, bool p_deep);
61 cprim_closeEnoughDeep (cprim c1, cprim c2)
64 ** If * c2 is passed as * c1
65 ** Comparison is slightly different since it is safe to pass int as long,
66 ** but not to pass int * as long *!
68 ** For deep comparisons, +relaxquals does not permit the long/int break.
71 return cprim_closeEnoughAux (c1, c2, TRUE);
75 cprim_closeEnough (cprim c1, cprim c2)
77 return cprim_closeEnoughAux (c1, c2, FALSE);
81 cprim_closeEnoughAux (cprim c1, cprim c2, bool deep)
83 if (c1 == c2) return TRUE;
85 if (c1 == CTX_ANYINTEGRAL)
87 if (context_getFlag (FLG_MATCHANYINTEGRAL)
88 || context_getFlag (FLG_IGNOREQUALS))
90 return (cprim_isAnyInt (c2)
91 || (cprim_isAnyChar (c2) && context_msgCharInt ()));
93 else if (context_getFlag (FLG_LONGINTEGRAL))
95 return (cprim_closeEnough (CTX_LINT, c2));
97 else if (context_getFlag (FLG_LONGUNSIGNEDINTEGRAL))
99 return (cprim_closeEnough (CTX_ULINT, c2));
107 if (c1 == CTX_UNSIGNEDINTEGRAL)
109 if (context_getFlag (FLG_MATCHANYINTEGRAL)
110 || context_getFlag (FLG_IGNOREQUALS))
112 if (context_getFlag (FLG_IGNORESIGNS))
114 return (cprim_isAnyUnsignedInt (c2)
115 || (cprim_isUnsignedChar (c2) && context_msgCharInt ()));
119 return (cprim_isAnyInt (c2)
120 || (cprim_isAnyChar (c2) && context_msgCharInt ()));
123 else if (context_getFlag (FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL))
125 return (cprim_closeEnough (CTX_ULINT, c2));
133 if (c1 == CTX_SIGNEDINTEGRAL)
135 if (context_getFlag (FLG_MATCHANYINTEGRAL)
136 || context_getFlag (FLG_IGNOREQUALS))
138 return (cprim_isAnyInt (c2)
139 || (cprim_isAnyChar (c2) && context_msgCharInt ()));
141 else if (context_getFlag (FLG_LONGSIGNEDINTEGRAL))
143 return (cprim_closeEnough (CTX_LINT, c2));
151 if (c2 == CTX_ANYINTEGRAL)
153 if (context_getFlag (FLG_MATCHANYINTEGRAL))
155 return (cprim_isAnyInt (c1)
156 || (cprim_isAnyChar (c1) && context_msgCharInt ()));
158 else if (context_getFlag (FLG_LONGINTEGRAL))
160 return (cprim_closeEnough (c1, CTX_LINT));
162 else if (context_getFlag (FLG_LONGUNSIGNEDINTEGRAL))
164 return (cprim_closeEnough (c1, CTX_ULINT));
172 if (c2 == CTX_UNSIGNEDINTEGRAL)
174 if (context_getFlag (FLG_MATCHANYINTEGRAL))
176 return (cprim_isAnyInt (c1)
177 || (cprim_isAnyChar (c1) && context_msgCharInt ()));
179 else if (context_getFlag (FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL))
181 return (cprim_closeEnough (c1, CTX_ULINT));
189 if (c2 == CTX_SIGNEDINTEGRAL)
191 if (context_getFlag (FLG_MATCHANYINTEGRAL))
193 return (cprim_isAnyInt (c2)
194 || (cprim_isAnyChar (c2) && context_msgCharInt ()));
196 else if (context_getFlag (FLG_LONGSIGNEDINTEGRAL))
198 return (cprim_closeEnough (c1, CTX_LINT));
206 if (context_getFlag (FLG_RELAXTYPES))
208 if (cprim_isNumeric (c1) && cprim_isNumeric (c2)) return TRUE;
211 if (context_getFlag (FLG_IGNOREQUALS))
217 return (cprim_isAnyChar (c2)
218 || (cprim_isAnyInt (c2) && (context_msgCharInt ())));
222 return (c2 == CTX_DOUBLE || c2 == CTX_FLOAT || c2 == CTX_LDOUBLE);
231 return (cprim_isAnyInt (c2)
232 || (cprim_isAnyChar (c2) && context_msgCharInt ()));
239 if (context_getFlag (FLG_IGNORESIGNS))
245 else if (c1 == CTX_UINT)
249 else if (c1 == CTX_ULINT)
253 /* 2001-06-10: This fix provided by Jim Zelenka: */
254 else if (c1 == CTX_ULLINT)
259 else if (c1 == CTX_USINT)
272 else if (c2 == CTX_UINT)
276 else if (c2 == CTX_ULINT)
280 /* 2001-06-10: This fix provided by Jim Zelenka: */
281 else if (c2 == CTX_ULLINT)
286 else if (c2 == CTX_USINT)
296 if (c1 == c2) return TRUE;
298 if (context_getFlag (FLG_FLOATDOUBLE))
300 if (c1 == CTX_FLOAT && c2 == CTX_DOUBLE)
304 if (c2 == CTX_FLOAT && c1 == CTX_DOUBLE)
310 if (!deep && context_getFlag (FLG_RELAXQUALS))
315 return (c2 == CTX_FLOAT);
317 return (c2 == CTX_DOUBLE || c2 == CTX_FLOAT);
319 return (c2 == CTX_CHAR && context_msgCharInt ());
321 return (c2 == CTX_SINT
322 || (cprim_isAnyChar (c2) && context_msgCharInt ()));
324 return (c2 == CTX_SINT
327 || (cprim_isAnyChar (c2) && context_msgCharInt ()));
329 return (c2 == CTX_USINT
332 /* 2001-06-10: This fix provided by Jim Zelenka: */
333 || (cprim_isAnyChar (c2) && context_msgCharInt ()));
335 return (c2 == CTX_SINT
337 || (cprim_isAnyChar (c2) && context_msgCharInt ()));
339 return (c2 == CTX_USINT
340 || (c2 == CTX_UCHAR && context_msgCharInt ()));
342 return (c2 == CTX_UCHAR && context_msgCharInt ());
344 /* 2001-06-10: This fix provided by Jim Zelenka: */
345 return (c2 == CTX_UINT || c2 == CTX_USINT
346 || (c2 == CTX_UCHAR && context_msgCharInt()));
348 return (c2 == CTX_UINT && context_msgCharInt ());
350 return ((c2 == CTX_INT || c2 == CTX_SINT)
351 && context_msgCharInt ());
367 return (c2 == CTX_CHAR && context_msgCharInt ());
372 return (c2 == CTX_UCHAR && context_msgCharInt ());
374 return (c2 == CTX_UINT && context_msgCharInt ());
376 return ((c2 == CTX_INT || c2 == CTX_SINT)
377 && context_msgCharInt ());
386 cprim_unparse (cprim c)
391 return cstring_makeLiteral ("-");
393 return cstring_makeLiteral ("void");
395 return cstring_makeLiteral ("char");
397 return cstring_makeLiteral ("unsigned char");
399 return cstring_makeLiteral ("double");
401 return cstring_makeLiteral ("long double");
403 return cstring_makeLiteral ("float");
405 return cstring_makeLiteral ("int");
407 return cstring_makeLiteral ("long int");
409 return cstring_makeLiteral ("long long");
411 return cstring_makeLiteral ("unsigned long long");
413 return cstring_makeLiteral ("short int");
415 return cstring_makeLiteral ("unsigned int");
417 return cstring_makeLiteral ("unsigned long int");
419 return cstring_makeLiteral ("unsigned short int");
420 case CTX_UNSIGNEDINTEGRAL:
421 return cstring_makeLiteral ("arbitrary unsigned integral type");
422 case CTX_SIGNEDINTEGRAL:
423 return cstring_makeLiteral ("arbitrary signed integral type");
424 case CTX_ANYINTEGRAL:
425 return cstring_makeLiteral ("arbitrary integral type");
427 return cstring_makeLiteral ("unknown prim");
431 bool cprim_isInt (cprim c)
433 return (cprim_isAnyInt (c)
434 || (cprim_isAnyChar (c) && context_msgCharInt ()));