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
27 ** error reporting procedures
30 # include "splintMacros.nf"
35 # include "cpperror.h"
36 # include "Headers/version.h" /* Visual C++ finds a different version.h on some path! */
38 /* Don't allow possibly-recursive assertion failures. */
40 # define llassert llassertprotect
42 static void printIndentMessage (FILE *p_stream, /*@only@*/ cstring p_sc, int p_indent)
43 /*@modifies *p_stream@*/ ;
45 static bool s_scanOpen = FALSE;
46 static int s_lclerrors = 0;
47 static size_t s_lastfileloclen = 10;
48 static /*@only@*/ cstring s_lastmsg = cstring_undefined;
49 static int s_mcount = 0;
50 static /*@only@*/ cstring saveOneMessage = cstring_undefined;
51 static /*@only@*/ fileloc lastparseerror = fileloc_undefined;
52 static /*@only@*/ fileloc lastbug = fileloc_undefined;
53 static bool llgenerrorreal (flagcode p_code,
54 char *p_srcFile, int p_srcLine,
55 /*@only@*/ cstring p_s,
56 /*@temp@*/ cstring p_addtext,
57 fileloc p_fl, bool p_iserror, bool p_indent)
58 /*@modifies g_warningstream@*/ ;
59 static bool llgenerroraux (flagcode p_code, char *p_srcFile, int p_srcLine,
60 /*@only@*/ cstring p_s,
61 /*@temp@*/ cstring p_addtext,
62 fileloc p_fl, bool p_iserror, bool p_indent)
63 /*@modifies g_warningstream@*/ ;
65 static void generateCSV (flagcode p_code, cstring p_s, cstring p_addtext, fileloc p_fl)
66 /*@modifies g_csvstream@*/ ;
68 static void printError (FILE *p_stream, /*@only@*/ cstring p_sc)
69 /*@globals s_lastfileloclen @*/
70 /*@modifies *p_stream@*/ ;
71 static void printMessage (FILE *p_stream, /*@only@*/ cstring p_s)
72 /*@modifies *p_stream@*/ ;
74 static void llgenhint (/*@only@*/ cstring p_s) /*@modifies g_warningstream@*/ ;
76 static void showSourceLoc (char *srcFile, int srcLine)
77 /*@modifies g_warningstream@*/
79 if (context_getFlag (FLG_SHOWSOURCELOC)) {
80 llgenhint (message ("%s:%d: Source code error generation point.",
81 cstring_fromChars (srcFile), srcLine));
86 static /*@null@*/ char *
87 maxcp (/*@null@*/ /*@returned@*/ char *a, /*@null@*/ /*@returned@*/ char *b)
96 fprintf (g_errorstream, " *** Please report bug to %s ***\n",
99 /* don't exit (EXIT_FAILURE); */
102 static bool s_needsPrepare = TRUE;
104 void prepareMessage ()
106 DPRINTF (("Prepare message: %s", bool_unparse (context_loadingLibrary ())));
109 if ((context_isPreprocessing () || context_loadingLibrary ())
111 && context_getFlag (FLG_SHOWSCAN))
115 s_needsPrepare = FALSE;
121 void closeMessage (void)
123 if (context_isPreprocessing ()
124 && context_getFlag (FLG_SHOWSCAN))
127 displayScanOpen (cstring_makeLiteral ("more preprocessing ."));
128 llassertprotect (!s_needsPrepare);
129 s_needsPrepare = TRUE;
138 llmsg (/*@only@*/ cstring s)
140 context_setNeednl ();
142 printMessage (g_messagestream, s);
147 lldiagmsg (/*@only@*/ cstring s)
149 static bool inmsg = FALSE;
153 fprintf (g_errorstream,
154 "Recursive message call detected: %s\n",
155 cstring_toCharsSafe (s));
161 context_setNeednl ();
163 printMessage (g_messagestream, s);
170 llmsgplain (/*@only@*/ cstring s)
172 context_setNeednl ();
174 printMessage (g_messagestream, s);
178 void llerror_flagWarning (cstring s)
180 if (context_getFlag (FLG_WARNFLAGS))
182 llgenmsg (s, g_currentloc);
191 llgenhint (/*@only@*/ cstring s) /*@modifies g_warningstream@*/
193 int indent = context_getIndentSpaces () - 1;
195 if (indent < 0) indent = 0;
197 context_setNeednl ();
198 printIndentMessage (g_warningstream, s, indent);
204 if (context_getFlag (FLG_HINTS) &&
205 !(context_inSuppressRegion () || context_inSuppressZone (g_currentloc)))
216 llshowhint (flagcode f)
218 if (context_getFlag (FLG_HINTS))
220 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
222 cstring desc = flagcodeHint (f);
224 if (cstring_isDefined (desc))
226 llgenhint (cstring_copy (desc));
233 llsuppresshint2 (char c, flagcode f1, flagcode f2)
236 if (context_getFlag (FLG_HINTS))
238 if ((flagcode_numReported (f1) == 0
239 || flagcode_numReported (f2) == 0)
240 || context_getFlag (FLG_FORCEHINTS))
242 cstring desc = flagcodeHint (f1);
243 context_setNeednl ();
244 s_lastfileloclen = 8;
246 if (cstring_isUndefined (desc))
248 desc = flagcodeHint (f2);
251 if (flagcode_isNamePrefixFlag (f1))
256 if (flagcode_isNamePrefixFlag (f2))
263 if (cstring_isDefined (desc))
265 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc,
267 flagcode_unparse (f1)));
271 llgenhint (message ("(Use %h%s to inhibit warning)",
272 c, flagcode_unparse (f1)));
277 if (cstring_isDefined (desc))
279 llgenhint (message ("%s (Use either %h%s or %h%s to inhibit warning)", desc,
281 flagcode_unparse (f1),
283 flagcode_unparse (f2)));
287 llgenhint (message ("(Use either %h%s or %h%s to inhibit warning)", c,
288 flagcode_unparse (f1),
289 c, flagcode_unparse (f2)));
297 llsuppresshint (char c, flagcode f)
299 if (context_getFlag (FLG_HINTS))
301 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
303 cstring desc = flagcodeHint (f);
304 context_setNeednl ();
305 s_lastfileloclen = 8;
307 if (flagcode_isNamePrefixFlag (f))
312 if (cstring_isDefined (desc))
314 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc, c,
315 flagcode_unparse (f)));
319 llgenhint (message ("(Use %h%s to inhibit warning)", c,
320 flagcode_unparse (f)));
327 llnosuppresshint (flagcode f)
329 if (context_getFlag (FLG_FORCEHINTS))
331 cstring desc = flagcodeHint (f);
332 context_setNeednl ();
333 s_lastfileloclen = 8;
335 if (cstring_isDefined (desc))
337 printError (g_warningstream, message (" %s", desc));
342 /*@constant int MAXSEARCH; @*/
343 # define MAXSEARCH 20
345 /*@constant int MINLINE; @*/
348 typedef /*@null@*/ /*@dependent@*/ char *nd_charp;
353 ** Divides a string into lines of up to maxline characters.
355 ** Initial string: *sp
357 ** Output split: *sp / *tp
362 mstring_split (/*@returned@*/ char **sp,
363 /*@out@*/ nd_charp *tp,
364 int maxline, /*@in@*/ int *indentchars)
373 DPRINTF (("Split: %s / %d", *sp, maxline));
375 if (maxline < MINLINELEN)
377 maxline = MINLINELEN;
380 if (*indentchars > 0)
382 s = *sp = mstring_concatFree1 (mstring_spaces (*indentchars), s);
389 ** if there is a newline in first maxline characters, split there
390 ** if line len is <= maxline, return no split
391 ** if there is a ':' or ';' or ',' followed by ' ' in first maxline characters,
392 ** split there unless the ' ' is followed by a '}', then
394 ** of the ';' is inside quotation marks
395 ** if there is a space or tab in last maxsearch characters, split there
396 ** else, split at maxline
398 ** special code: slash [1-9] after a newline means indent the rest <n> chars
402 nl = strchr (s, '\n');
404 if ((nl != NULL) && ((nl - s) < maxline))
411 llassertprotect (*tp == NULL || (*tp > osp));
415 if (*t >= '\1' && *t <= '\7')
417 *indentchars += (int) (*t - '\1') + 1;
424 else if (size_toInt (strlen (s)) < maxline)
426 llassertprotect (*tp == NULL);
433 char *lcolon, *lsemi, *lcomma;
442 lcolon = strrchr (s, ':');
443 lsemi = strrchr (s, ';');
444 lcomma = strrchr (s, ',');
448 splitat = maxcp (lcolon, lsemi);
450 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
451 && *(splitat) != '\0'
452 && *(splitat + 1) == ' '
453 && (*(splitat + 2) != '}'
454 && *(splitat + 2) != ','
455 && (*(splitat + 2) != '\0')))
457 *(splitat + 1) = '\0';
460 llassertprotect (*tp == NULL || (*tp > osp));
464 if (lcomma != NULL && ((lcomma - s) > maxline - 5))
468 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
469 && *(splitat) != '\0'
470 && *(splitat + 1) == ' '
471 && (*(splitat + 2) != '}'
472 && (*(splitat + 2) != '\0')))
474 *(splitat + 1) = '\0';
477 llassertprotect (*tp == NULL || (*tp > osp));
483 ** Search for any breaking point (at least 4 letters past s)
486 while (*t != ' ' && *t != '\t' && i < MAXSEARCH && t > (s + 4))
492 if (*t != ' ' && *t != '\t')
494 llassertprotect (maxline > 0);
495 t = mstring_copy (s + maxline);
496 *(s + maxline) = '\0';
501 llassertprotect (*tp == NULL || (*tp > osp));
505 mstring_markFree (t);
507 /* Won't be true since t is a copy: llassertprotect (*tp == NULL || (*tp > osp)); */
516 if (*t == '\0') return;
519 ** returns unqualified as only
524 llassert (*sp != *tp);
533 void limitmessage (/*@only@*/ cstring s, fileloc loc)
535 if (s_mcount > context_getLimit () + 1)
541 cstring flstring = fileloc_unparse (loc);
543 s_lastfileloclen = cstring_length (flstring);
544 cstring_free (saveOneMessage);
545 saveOneMessage = message ("%q: %q", flstring, s);
549 static int parseerrorcount = 0;
551 void cleanupMessages ()
555 if (context_unlimitedMessages ())
561 int unprinted = s_mcount - context_getLimit ();
565 if (unprinted == 1 && cstring_isDefined (saveOneMessage))
568 printError (g_warningstream, saveOneMessage);
570 saveOneMessage = cstring_undefined;
574 if (cstring_isDefined (saveOneMessage))
576 /* cstring_free (saveOneMessage); */
577 saveOneMessage = cstring_undefined;
580 fprintf (g_warningstream, "%s: (%d more similar errors unprinted)\n",
581 cstring_toCharsSafe (fileloc_filename (g_currentloc)),
582 s_mcount - context_getLimit ());
591 llgenmsg (/*@only@*/ cstring s, fileloc fl)
593 cstring flstring = fileloc_unparse (fl);
594 s_lastfileloclen = cstring_length (flstring);
597 (void) printError (g_warningstream, message ("%q: %q", flstring, s));
602 llgenindentmsg (/*@only@*/ cstring s, fileloc fl)
604 cstring flstring = fileloc_unparse (fl);
605 int indentspaces = context_getLocIndentSpaces ();
608 (void) printIndentMessage (g_warningstream, message ("%q: %q", flstring, s),
615 llgenindentmsgnoloc (/*@only@*/ cstring s)
618 (void) printIndentMessage (g_warningstream, s, context_getIndentSpaces ());
623 llgentypeerroraux (char *srcFile, int srcLine,
624 flagcode ocode, ctype t1, exprNode e1, ctype t2, exprNode e2,
625 /*@only@*/ cstring s, fileloc fl)
627 cstring hint = cstring_undefined;
628 flagcode code = ocode;
629 flagcode hcode = INVALID_FLAG;
633 DPRINTF (("Type error [%s]: %s / %s : %s / %s",
634 flagcode_unparse (ocode),
635 exprNode_unparse (e1), exprNode_unparse (e2),
636 ctype_unparse (t1), ctype_unparse (t2)));
638 DPRINTF (("Bool: %s / %s",
639 bool_unparse (ctype_isBool (t1)),
640 bool_unparse (ctype_isBool (t2))));
643 ** Set the flag using the underlying types that didn't match.
646 while (ctype_isPointer (ut1) && ctype_isPointer (ut2)) {
647 ut1 = ctype_baseArrayPtr (ut1);
648 ut2 = ctype_baseArrayPtr (ut2);
651 if (ctype_isRealNumAbstract (ut1) && exprNode_isNumLiteral (e2))
653 hcode = FLG_NUMABSTRACTLIT;
655 else if ((ctype_isFloat (ut1) && ctype_isDouble (ut2))
656 || (ctype_isFloat (ut1) && ctype_isDouble (ut2)))
658 hcode = FLG_FLOATDOUBLE;
660 else if ((exprNode_isCharLiteral (e1) && ctype_isInt (ut2))
661 || (exprNode_isCharLiteral (e2) && ctype_isInt (ut1)))
663 hcode = FLG_CHARINTLITERAL;
665 else if ((exprNode_isNumLiteral (e1) && ctype_isReal (ut2))
666 || (exprNode_isNumLiteral (e2) && ctype_isReal (ut1)))
668 hcode = FLG_NUMLITERAL;
670 else if ((ctype_isManifestBool (ut1) && ctype_isInt (ut2))
671 || (ctype_isInt (ut1) && ctype_isManifestBool (ut2)))
672 /* evs 2000-07-24: was ctype_isDirectBool */
676 else if (((ctype_isChar (ut1) && !ctype_isInt (ut1)) && ctype_isInt (ut2))
677 || ((ctype_isInt (ut1) && (ctype_isChar (ut2) && !ctype_isInt (ut2)))))
681 else if ((ctype_isInt (ut1) && ctype_isInt (ut2))
682 || (ctype_isChar (ut1) && ctype_isChar (ut2))
683 || (ctype_isDouble (ut1) && ctype_isDouble (ut2)))
685 if (!bool_equal (ctype_isSigned (ut1), ctype_isSigned (ut2)))
687 if (ctype_isArbitraryIntegral (ctype_realType (ut1))
688 && !ctype_isArbitraryIntegral (ctype_realType (ut2)))
690 hcode = FLG_MATCHANYINTEGRAL;
692 else if (ctype_isArbitraryIntegral (ctype_realType (ut2))
693 && !ctype_isArbitraryIntegral (ctype_realType (ut1)))
695 hcode = FLG_MATCHANYINTEGRAL;
698 /*drl 4-270-2003 even if ignoresigns is set there may be another
699 problem that is causing splint to complain about a type error.
700 Don't tell the user that they can add +ignoresigns if it's
703 DPRINTF(("TEST INGORESIGNS"));
704 if (context_getFlag(FLG_IGNORESIGNS) )
706 DPRINTF(("INGORESIGNS SET"));
707 hcode = FLG_IGNOREQUALS;
712 DPRINTF(("INGORESIGNS NOT SET"));
713 hcode = FLG_IGNORESIGNS;
719 hcode = FLG_IGNOREQUALS;
722 else if (ctype_isArbitraryIntegral (ctype_realType (ut1)))
724 if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
726 hcode = FLG_MATCHANYINTEGRAL;
728 else if (ctype_match (ut2, ctype_ulint))
730 hcode = FLG_LONGUNSIGNEDINTEGRAL;
732 else if (ctype_match (ut2, ctype_lint))
734 hcode = FLG_LONGINTEGRAL;
736 else if (ctype_isInt (ut2))
738 hcode = FLG_MATCHANYINTEGRAL;
745 else if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
747 ctype tr = ctype_realType (ut1);
749 if (ctype_isArbitraryIntegral (tr))
751 hcode = FLG_MATCHANYINTEGRAL;
753 else if (ctype_match (ut1, ctype_ulint))
755 if (ctype_isUnsignedIntegral (tr))
757 hcode = FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL;
759 else if (ctype_isSignedIntegral (tr))
765 hcode = FLG_LONGUNSIGNEDINTEGRAL;
768 else if (ctype_match (ut1, ctype_lint))
770 if (ctype_isSignedIntegral (tr))
772 hcode = FLG_LONGSIGNEDINTEGRAL;
774 else if (ctype_isSignedIntegral (tr))
780 hcode = FLG_LONGINTEGRAL;
783 else if (ctype_isInt (ut1))
785 hcode = FLG_MATCHANYINTEGRAL;
797 if (hcode == INVALID_FLAG)
799 DPRINTF (("[%s] %s - %s / %s",
801 bool_unparse (ctype_isEnum (ut1)),
802 bool_unparse (ctype_isEnum (ctype_realType (ut1))),
803 bool_unparse (ctype_isInt (ut2))));
805 if (ctype_isAbstract (ut1) && !ctype_isAbstract (ut2))
807 uentry ue1 = usymtab_getTypeEntry (ctype_typeId (ut1));
808 ctype ct = uentry_getType (ue1);
810 if (ctype_match (ct, ut2))
813 hint = message ("Underlying types match, but %s is an "
814 "abstract type that is not accessible here.",
818 else if (ctype_isAbstract (ut2) && !ctype_isAbstract (ut1))
820 uentry ue = usymtab_getTypeEntry (ctype_typeId (ut2));
821 ctype ct = uentry_getType (ue);
823 if (ctype_match (ct, ut1))
825 if (ctype_isNumAbstract (ut2))
827 if (exprNode_isNumLiteral (e1))
829 code = FLG_NUMABSTRACTLIT;
830 hint = message ("Underlying types match, but %s is a "
831 "numabstract type that is not accessible here. "
832 "(Use +numabstractlit to allow numeric literals "
833 "to be used as numabstract type values.)",
838 code = FLG_NUMABSTRACT;
839 hint = message ("Underlying types match, but %s is a "
840 "numabstract type that is not accessible here.",
847 hint = message ("Underlying types match, but %s is an "
848 "abstract type that is not accessible here.",
855 ; /* Not an abstract mismatch. */
859 if (hcode == INVALID_FLAG)
861 if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
862 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
866 else if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
867 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
871 else if ((ctype_isSignedChar (ut1) && ctype_isUnsignedChar (ut2))
872 || (ctype_isUnsignedChar (ut1) && ctype_isSignedChar (ut2)))
874 hcode = FLG_CHARUNSIGNEDCHAR;
876 else if (ctype_isNumeric (ut1) && ctype_isNumeric (ut2))
878 hcode = FLG_RELAXTYPES;
879 DPRINTF (("Setting relax types!"));
883 DPRINTF (("No special type rule: %s / %s", ctype_unparse (ut1),
884 ctype_unparse (ut2)));
889 if (cstring_isDefined (hint))
891 if (!context_suppressFlagMsg (ocode, fl))
893 return xllgenhinterror (srcFile, srcLine, code, s, hint, fl);
904 if (hcode != INVALID_FLAG && hcode != ocode)
909 if (llgenerroraux (ocode, srcFile, srcLine, s,
910 flagcodeHint (code), fl, TRUE, FALSE))
914 if (context_flagOn (code, fl))
916 /* The flag is alreay set, something buggy in the flag code */
917 llcontbug (message ("No hint available, flag %s is already set.",
918 flagcode_unparse (code)));
927 llsuppresshint ('-', code);
930 flagcode_recordError (code);
939 xllgentypeerror (char *srcFile, int srcLine,
940 ctype t1, exprNode e1, ctype t2, exprNode e2,
941 /*@only@*/ cstring s, fileloc fl)
943 return llgentypeerroraux (srcFile, srcLine, FLG_TYPE, t1, e1, t2, e2, s, fl);
947 xllgenformattypeerror (char *srcFile, int srcLine,
948 ctype t1, exprNode e1, ctype t2, exprNode e2,
949 /*@only@*/ cstring s, fileloc fl)
951 if (!context_suppressFlagMsg (FLG_FORMATTYPE, fl))
954 && ctype_isNumAbstract (t2))
956 if (!context_suppressFlagMsg (FLG_NUMABSTRACTPRINT, fl))
958 return llgentypeerroraux (srcFile, srcLine, FLG_NUMABSTRACTPRINT, t1, e1, t2, e2, s, fl);
967 return llgentypeerroraux (srcFile, srcLine, FLG_FORMATTYPE, t1, e1, t2, e2, s, fl);
978 xllgenerror (char *srcFile, int srcLine, flagcode o, /*@only@*/ cstring s, fileloc fl)
980 if (llgenerroraux (o, srcFile, srcLine, s, flagcodeHint (o), fl, TRUE, FALSE))
982 llnosuppresshint (o);
983 flagcode_recordError (o);
989 flagcode_recordSuppressed (o);
995 xllgenhinterror (char *srcFile, int srcLine,
996 flagcode o, /*@only@*/ cstring s, /*@only@*/ cstring hint,
999 if (!context_suppressFlagMsg (o, fl))
1001 if (llgenerroraux (o, srcFile, srcLine, s, hint, fl, TRUE, FALSE))
1003 flagcode_recordError (o);
1005 if (context_getFlag (FLG_HINTS))
1011 cstring_free (hint);
1018 cstring_free (hint);
1022 cstring_free (hint);
1026 flagcode_recordSuppressed (o);
1031 llrealerror (flagcode code, char *srcFile, int srcLine, /*@only@*/ cstring s, /*@temp@*/ cstring addtext, fileloc fl)
1033 return (llgenerrorreal (code, srcFile, srcLine, s, addtext, fl, TRUE, FALSE));
1037 llgenerroraux (flagcode code,
1038 char *srcFile, int srcLine,
1039 /*@only@*/ cstring s,
1041 fileloc fl, bool iserror, bool indent)
1043 if (context_inSuppressZone (fl))
1049 if (llgenerrorreal (code, srcFile, srcLine, s, addtext, fl, iserror, indent)) {
1057 xllforceerror (char *srcFile, int srcLine,
1058 flagcode code, /*@only@*/ cstring s, fileloc fl)
1060 flagcode_recordError (code);
1062 if (llgenerrorreal (code, srcFile, srcLine, s, cstring_undefined, fl, TRUE, FALSE)) {
1070 static void generateCSV (flagcode code, cstring s, cstring addtext, fileloc fl)
1073 if (g_csvstream != NULL) {
1074 /* Warning, Flag Code, Flag Name, Priority, File, Line, Column, Warning Text, Additional Text */
1075 fprintf (g_csvstream, "%d,%d,%s,%d,%s,%d,%d,\"%s\"",
1076 context_numErrors (),
1077 (int) code, /* flag code */
1078 cstring_toCharsSafe (flagcode_unparse (code)), /* flag name */
1079 flagcode_priority (code), /* priority */
1080 cstring_toCharsSafe (fileloc_outputFilename (fl)),
1081 fileloc_lineno (fl),
1082 fileloc_column (fl),
1083 cstring_toCharsSafe (s));
1085 if (cstring_isDefined (addtext)) {
1086 fprintf (g_csvstream, ",\"%s\"\n", cstring_toCharsSafe (addtext));
1088 fprintf (g_csvstream, "\n");
1094 llgenerrorreal (flagcode code, char *srcFile, int srcLine,
1095 /*@only@*/ cstring s,
1097 fileloc fl, bool iserror, bool indent)
1101 /* duplicate message (rescanning a header file */
1103 if (!messageLog_add (context_messageLog (), fl, s))
1105 DPRINTF (("Duplicate message suppressed! %s / %s",
1106 fileloc_unparse (fl), s));
1112 ** If herald has not been displayed, display it before the first message.
1117 if (iserror) context_hasError ();
1119 if (context_unlimitedMessages ())
1126 ** suppress excessive messages:
1131 char *sc = cstring_toCharsSafe (s);
1132 char *tmpmsg = strchr (sc, ':');
1140 char *savechar = tmpmsg;
1146 if (cstring_equal (s_lastmsg, cstring_fromChars (tmpmsg)))
1149 if (s_mcount == (context_getLimit () + 1))
1151 limitmessage (s, fl);
1155 if (s_mcount > (context_getLimit ()))
1165 cstring_free (s_lastmsg);
1166 s_lastmsg = cstring_fromCharsNew (tmpmsg);
1170 DPRINTF (("Here..."));
1172 if (context_hasAliasAnnote ())
1174 char *sc = cstring_toCharsSafe (s);
1175 char *fcolon = strchr (sc, ':');
1176 cstring a = context_getAliasAnnote ();
1181 s = message ("%q (%q)", s, a);
1188 afterColon = cstring_fromCharsNew (fcolon + 1);
1190 s = message ("%q (%q):%q", s, a, afterColon);
1194 if (context_hasMessageAnnote ())
1196 char *fcolon = strchr (cstring_toCharsSafe (s), ':');
1201 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1202 s = message ("%q (%q)", s, context_getMessageAnnote ());
1203 /*@=dependenttrans@*/
1210 afterColon = cstring_fromCharsNew (fcolon + 1);
1212 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1213 s = message ("%q (%q):%q", s,
1214 context_getMessageAnnote (), afterColon);
1215 /*@=dependenttrans@*/
1219 context_setNeednl ();
1222 if (context_showFunction ())
1224 cstring fname = fileloc_unparseFilename (g_currentloc);
1226 if (context_inIterDef ())
1228 fprintf (g_warningstream, "%s: (in iter %s)\n",
1229 cstring_toCharsSafe (fname),
1230 cstring_toCharsSafe (context_inFunctionName ()));
1232 else if (context_inIterEnd ())
1234 fprintf (g_warningstream, "%s: (in iter finalizer %s)\n",
1235 cstring_toCharsSafe (fname),
1236 cstring_toCharsSafe (context_inFunctionName ()));
1238 else if (context_inMacro ())
1240 fprintf (g_warningstream, "%s: (in macro %s)\n", cstring_toCharsSafe (fname),
1241 cstring_toCharsSafe (context_inFunctionName ()));
1245 fprintf (g_warningstream, "%s: (in function %s)\n",
1246 cstring_toCharsSafe (fname),
1247 cstring_toCharsSafe (context_inFunctionName ()));
1250 cstring_free (fname);
1251 context_setShownFunction ();
1254 flstring = fileloc_unparse (fl);
1255 s_lastfileloclen = cstring_length (flstring);
1257 generateCSV (code, s, addtext, fl);
1261 printError (g_warningstream, message (" %q: %q", flstring, s));
1265 printError (g_warningstream, message ("%q: %q", flstring, s));
1268 showSourceLoc (srcFile, srcLine);
1276 ** message contains no '\n'
1277 ** message fits in one line: print it
1278 ** message fits in two lines with 3-space indent after fileloc: print it
1279 ** split line with 5-space indent from left margin: print it
1284 void printMessage (FILE *stream, /*@only@*/ cstring s)
1286 printIndentMessage (stream, s, 0);
1290 void printIndentMessage (FILE *stream, /*@only@*/ cstring sc, int indent)
1292 static bool inbody = FALSE;
1293 int maxlen = context_getLineLen ();
1294 char *s = cstring_toCharsSafe (sc);
1297 llassertprotect (!inbody);
1305 llassertprotect (st != olds);
1307 mstring_split (&st, &t, maxlen, &indent);
1308 fprintf (stream, "%s\n", st);
1309 llassertprotect (t != s);
1311 } while (s != NULL) ;
1318 void printError (FILE *stream, /*@only@*/ cstring sc)
1320 int maxlen = context_getLineLen ();
1321 size_t nspaces = s_lastfileloclen + 5;
1322 int nextlen = maxlen - size_toInt (nspaces);
1323 size_t len = cstring_length (sc);
1325 char *s = cstring_toCharsSafe (sc);
1329 DPRINTF (("Print error: [%s]", sc));
1331 if (size_toInt (len) < (maxlen + nextlen) && (strchr (s, '\n') == NULL))
1333 mstring_split (&s, &t, maxlen, &indent);
1335 fprintf (stream, "%s\n", s);
1339 len = mstring_length (t);
1341 if (size_toInt (len) < (maxlen - 3) && (strchr (t, '\n') == NULL)
1342 && size_toInt (len) > (nextlen - 1))
1344 fprintf (stream, " %s\n", t);
1348 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1351 for (i = 0; i < size_toInt (nspaces); i++)
1356 spaces[nspaces] = '\0';
1361 mstring_split (&st, &t, nextlen, &indent);
1362 fprintf (stream, "%s%s\n", spaces, st);
1371 DPRINTF (("Here 1: [%s]", sc));
1373 if (size_toInt (len) < (maxlen + maxlen - 1) && (strchr (s, '\n') != NULL))
1375 nspaces = ((maxlen + maxlen - 1) - len) / 2;
1377 if (nspaces < 1) nspaces = 1;
1379 nextlen = size_toInt (maxlen - nspaces);
1381 mstring_split (&s, &t, maxlen, &indent);
1383 fprintf (stream, "%s\n", s);
1387 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1390 for (i = 0; i < size_toInt (nspaces); i++)
1395 spaces[nspaces] = '\0';
1401 mstring_split (&st, &t, nextlen, &indent);
1402 fprintf (stream, "%s%s\n", spaces, st);
1411 nextlen = size_toInt (maxlen - nspaces);
1413 DPRINTF (("Here 2: [%s]", s));
1414 mstring_split (&s, &t, maxlen, &indent);
1415 DPRINTF (("Here 3: [%s] [%s]", s, t));
1417 fprintf (stream, "%s\n", s);
1421 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1424 for (i = 0; i < nspaces; i++)
1429 spaces[nspaces] = '\0';
1434 DPRINTF (("Loop: [%s]", t));
1435 mstring_split (&st, &t, nextlen, &indent);
1436 DPRINTF (("Split: [%s] [%s]", st, t));
1437 fprintf (stream, "%s%s\n", spaces, st);
1438 DPRINTF (("Next..."));
1451 xllfatalbug (char *srcFile, int srcLine, /*@only@*/ cstring s)
1454 printError (g_errorstream, message ("%q: *** Fatal bug: %q",
1455 fileloc_unparse (g_currentloc), s));
1456 showSourceLoc (srcFile, srcLine);
1463 lclfatalbug (char *msg)
1466 printError (g_errorstream,
1467 message ("*** Fatal Bug: %s", cstring_fromChars (msg)));
1474 checkParseError (void)
1476 if (fileloc_withinLines (lastparseerror, g_currentloc, 10))
1478 llfatalerror (message ("%q: Cannot recover from parse error.",
1479 fileloc_unparse (g_currentloc)));
1483 void llbugaux (cstring file, int line, /*@only@*/ cstring s)
1486 static int numbugs = 0;
1487 static bool inbug = FALSE;
1489 context_recordBug ();
1493 cstring temps = fileloc_unparseRaw (file, line);
1495 fprintf (g_errorstream,
1496 "%s: Recursive bug detected: %s\n",
1497 cstring_toCharsSafe (temps),
1498 cstring_toCharsSafe (s));
1499 cstring_free (temps);
1508 if (fileloc_withinLines (lastparseerror, g_currentloc, 7))
1510 llfatalerror (message ("%q: Cannot recover from parse error.",
1511 fileloc_unparse (g_currentloc)));
1514 (void) fflush (g_warningstream);
1516 printError (g_errorstream,
1517 message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1518 fileloc_unparse (g_currentloc),
1519 fileloc_unparseRaw (file, line),
1522 /* printCodePoint (); no longer useful */
1527 ** This is confusing, and hardly ever useful.
1531 perror ("Possible system error diagnostic: ");
1542 if (numbugs > context_getBugsLimit () && fileloc_withinLines (lastbug, g_currentloc, 2))
1545 (message ("%q: Cannot recover from last bug. "
1546 "(If you really want Splint to try to continue, use -bugslimit <n>.)",
1547 fileloc_unparse (g_currentloc)));
1550 fprintf (g_errorstream, " (attempting to continue, results may be incorrect)\n");
1551 fileloc_free (lastbug);
1552 lastbug = fileloc_copy (g_currentloc);
1558 lclbug (/*@only@*/ cstring s)
1561 printError (g_errorstream, message ("*** Internal Bug: %q", s));
1564 fprintf (g_errorstream, " (attempting to continue, results may be incorrect)\n");
1569 xllfatalerror (char *srcFile, int srcLine, cstring s)
1572 printError (g_errorstream, s);
1573 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1574 showSourceLoc (srcFile, srcLine);
1579 xllfatalerrorLoc (char *srcFile, int srcLine, /*@only@*/ cstring s)
1582 (void) fflush (g_warningstream);
1583 printError (g_errorstream, message ("%q: %q", fileloc_unparse (g_currentloc), s));
1584 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1585 showSourceLoc (srcFile, srcLine);
1586 (void) fflush (g_warningstream);
1593 return (s_lclerrors > 0);
1597 lclHadNewError (void)
1599 static int lastcall = 0;
1601 if (s_lclerrors > lastcall)
1603 lastcall = s_lclerrors;
1613 lclNumberErrors (void)
1615 return (s_lclerrors);
1619 xlclerror (char *srcFile, int srcLine, ltoken t, /*@only@*/ cstring msg)
1623 if (ltoken_getCode (t) != NOTTOKEN)
1625 cstring loc = ltoken_unparseLoc (t);
1626 s_lastfileloclen = cstring_length (loc);
1628 printError (g_warningstream, message ("%q: %q", loc, msg));
1629 showSourceLoc (srcFile, srcLine);
1633 printError (g_warningstream, msg);
1634 showSourceLoc (srcFile, srcLine);
1639 lclplainerror (/*@only@*/ cstring msg)
1642 printError (g_warningstream, msg);
1646 lclfatalerror (ltoken t, /*@only@*/ cstring msg)
1648 if (ltoken_getCode (t) != NOTTOKEN)
1650 cstring loc = ltoken_unparseLoc (t);
1651 s_lastfileloclen = cstring_length (loc);
1652 printError (g_errorstream, message ("%q: %q", loc, msg));
1656 printError (g_errorstream, msg);
1659 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue"));
1664 lclplainfatalerror (/*@only@*/ cstring msg)
1666 (void) fflush (g_warningstream);
1667 printError (g_errorstream, message ("*** Cannot continue: %q", msg));
1672 lclRedeclarationError (ltoken id)
1674 cstring s = ltoken_getRawString (id);
1677 if (usymtab_existsEither (s))
1679 uentry le = usymtab_lookupEither (s);
1681 lclerror (id, message ("Respecification of %s", s));
1682 llgenindentmsg (message ("Previous specification of %q",
1683 uentry_getName (le)),
1684 uentry_whereSpecified (le));
1688 lclerror (id, message ("Identifier redeclared: %s", s));
1692 void genppllerror (flagcode code, /*@only@*/ cstring s)
1694 if (context_inSuppressZone (g_currentloc))
1700 if (context_getFlag (code))
1704 displayScanClose ();
1709 if (code != FLG_PREPROC)
1711 llsuppresshint ('-', code);
1714 if (!context_isInCommandLine ())
1716 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1726 void genppllerrorhint (flagcode code, /*@only@*/ cstring s,
1727 /*@only@*/ cstring hint)
1729 if (context_inSuppressZone (g_currentloc))
1732 cstring_free (hint);
1736 if (context_getFlag (code))
1738 generateCSV (code, s, hint, g_currentloc);
1740 context_clearPreprocessing ();
1743 context_setPreprocessing ();
1749 cstring_free (hint);
1754 void ppllerror (/*@only@*/ cstring s)
1756 genppllerror (FLG_PREPROC, s);
1759 void pplldiagmsg (cstring s)
1761 if (!context_isInCommandLine ())
1765 displayScanClose ();
1769 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1777 void loadllmsg (cstring s)
1779 displayScanClose ();
1781 displayScanOpen (cstring_makeLiteral ("< ."));
1784 static void llreportparseerror (/*@only@*/ cstring s)
1786 if (fileloc_withinLines (lastparseerror, g_currentloc, 5))
1792 llerror (FLG_SYNTAX, s);
1794 fileloc_free (lastparseerror);
1795 lastparseerror = fileloc_copy (g_currentloc);
1799 bool xcppoptgenerror (char *srcFile, int srcLine,
1801 /*@only@*/ cstring s,
1805 fileloc loc = cppReader_getLoc (pfile);
1807 if (context_flagOn (o, loc))
1809 if (xlloptgenerror (srcFile, srcLine, o, s, loc))
1811 cppReader_printContainingFiles (pfile);
1825 bool xlloptgenerror (char *srcFile, int srcLine,
1826 flagcode o, /*@only@*/ cstring s, fileloc loc)
1828 DPRINTF (("xllopt: %s", s));
1830 if (llrealerror (o, srcFile, srcLine, s, flagcodeHint (o), loc))
1832 DPRINTF (("Here we are!"));
1833 llsuppresshint ('-', o);
1835 flagcode_recordError (o);
1840 DPRINTF (("Suppressed!"));
1841 flagcode_recordSuppressed (o);
1846 bool xoptgenerror2 (char *srcFile, int srcLine,
1847 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1849 if (context_suppressFlagMsg (f1, loc))
1851 flagcode_recordSuppressed (f1);
1856 if (context_suppressFlagMsg (f2, loc))
1858 flagcode_recordSuppressed (f2);
1863 if (llrealerror (f1, srcFile, srcLine, s, flagcodeHint (f1), loc))
1865 llsuppresshint2 ('-', f1, f2);
1866 flagcode_recordError (f2);
1872 flagcode_recordSuppressed (f2);
1880 bool xoptgenerror2n (char *srcFile, int srcLine,
1881 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1884 if (context_suppressFlagMsg (f1, loc))
1886 flagcode_recordSuppressed (f1);
1891 if (context_suppressNotFlagMsg (f2, loc))
1893 flagcode_recordSuppressed (f2);
1898 if (llrealerror (f1, srcFile, srcLine, s, flagcodeHint (f2), loc))
1900 llsuppresshint ('+', f2);
1901 flagcode_recordError (f2);
1906 flagcode_recordSuppressed (f2);
1912 bool xllnoptgenerror (char *srcFile, int srcLine,
1913 flagcode o, /*@only@*/ cstring s, fileloc loc)
1915 if (llrealerror (o, srcFile, srcLine, s, flagcodeHint (o), loc))
1917 llsuppresshint ('+', o);
1918 flagcode_recordError (o);
1923 flagcode_recordSuppressed (o);
1927 void xllparseerror (char *srcFile, int srcLine, cstring s)
1929 if (context_getFlag (FLG_TRYTORECOVER))
1933 if (parseerrorcount > GIVEUPPARSE)
1935 if (cstring_isDefined (s))
1937 xllfatalerror (srcFile, srcLine,
1938 message ("%q: Parse Error: %q. "
1939 "Too many errors, giving up.",
1940 fileloc_unparse (g_currentloc), s));
1944 xllfatalerror (srcFile, srcLine,
1945 message ("%q: Parse Error. Too many errors, giving up.",
1946 fileloc_unparse (g_currentloc)));
1951 if (cstring_isDefined (s))
1953 llreportparseerror (message ("Parse Error: %q. Attempting to continue.",
1955 showSourceLoc (srcFile, srcLine);
1959 llreportparseerror (message ("Parse Error. Attempting to continue."));
1960 showSourceLoc (srcFile, srcLine);
1968 if (cstring_isDefined (s))
1970 msg = message ("Parse Error: %q.", s);
1974 msg = message ("Parse Error.");
1979 message ("%q: %s (For help on parse errors, "
1980 "see splint -help parseerrors.)",
1981 fileloc_unparse (g_currentloc), msg));
1985 bool xfsgenerror (char *srcFile, int srcLine,
1986 flagSpec fs, /*@only@*/ cstring s, fileloc fl)
1988 if (flagSpec_isOn (fs, fl))
1990 flagcode firston = flagSpec_getFirstOn (fs, fl);
1992 if (llgenerroraux (firston, srcFile, srcLine, s,
1993 flagcodeHint (firston),
1996 llsuppresshint ('-', firston);
1997 flagcode_recordError (firston);
2002 flagcode_recordSuppressed (firston);
2008 flagcode_recordSuppressed (flagSpec_getDominant (fs));
2014 bool doCheck (bool x, cstring pred, cstring file, int line)
2017 llbug (message ("%q: Check Failed: %s",
2018 fileloc_unparseRaw (file, line),
2025 /*@observer@*/ cstring lldecodeerror (/*@unused@*/ int errnum)
2030 #ifndef HAVE_STRERROR
2033 result = strerror (errnum);
2036 /* VAXCRTL's strerror() takes an optional second argument, which only
2037 matters when the first argument is EVMSERR. However, it's simplest
2038 just to pass it unconditionally. `vaxc$errno' is declared in
2039 <errno.h>, and maintained by the library in parallel with `errno'.
2040 We assume that caller's `errnum' either matches the last setting of
2041 `errno' by the library or else does not have the value `EVMSERR'. */
2043 result = strerror (errnum, vaxc$errno);
2048 result = cstring_toCharsSafe (message ("undocumented I/O error: %d", errnum));
2051 return cstring_fromChars (result);
2054 void llquietbugaux (cstring s, /*@unused@*/ cstring file, /*@unused@*/ int line)
2059 printError (g_errorstream, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
2060 fileloc_unparse (g_currentloc),
2061 fileloc_unparseRaw (file, line),
2073 (void) fflush (g_warningstream);
2074 (void) fflush (g_messagestream);
2077 void displayScan (cstring msg)
2081 displayScanClose ();
2084 llassert (!s_scanOpen);
2086 if (context_getFlag (FLG_SHOWSCAN))
2089 fprintf (g_messagestream, "< %s >\n", cstring_toCharsSafe (msg));
2090 (void) fflush (g_messagestream);
2096 void displayScanOpen (cstring msg)
2100 displayScanClose ();
2103 llassert (!s_scanOpen);
2106 if (context_getFlag (FLG_SHOWSCAN))
2108 fprintf (g_messagestream, "< %s", cstring_toCharsSafe (msg));
2109 (void) fflush (g_messagestream);
2115 void displayScanContinue (/*@temp@*/ cstring msg)
2117 if (context_getFlag (FLG_SHOWSCAN))
2121 fprintf (g_messagestream, "%s", cstring_toCharsSafe (msg));
2122 (void) fflush (g_messagestream);
2127 ** Don't call bug recursively
2130 fprintf (stderr, "*** Bug: scan continue scan not open\n");
2135 void displayScanClose (void)
2139 if (context_getFlag (FLG_SHOWSCAN))
2141 fprintf (g_messagestream, " >\n");
2142 (void) fflush (g_messagestream);
2148 ** Don't call bug recursively
2151 fprintf (stderr, "*** Bug: scan close scan not open\n");