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
32 # include "splintMacros.nf"
36 ** Use this for assertions in error-generation code (that
37 ** might lead to infinite loops of failed assertions if
38 ** the normal error generation routines are used).
41 /*@function static noreturnwhenfalse void llassertprotect (sef bool p_test); @*/
42 # define llassertprotect(tst) \
44 fprintf (stderr, "%s:%d: at source point: ", __FILE__, __LINE__); \
45 fprintf (stderr, "protected fatal llassert failed: " #tst "\n"); \
49 /* Don't allow possibly-recursive assertion failures. */
51 # define llassert llassertprotect
53 static void printIndentMessage (FILE *p_stream
, /*@only@*/ cstring p_sc
, int p_indent
)
54 /*@modifies *p_stream@*/ ;
56 static bool s_scanOpen
= FALSE
;
57 static int s_lclerrors
= 0;
58 static size_t s_lastfileloclen
= 10;
59 static /*@only@*/ cstring s_lastmsg
= cstring_undefined
;
60 static int s_mcount
= 0;
61 static /*@only@*/ cstring saveOneMessage
= cstring_undefined
;
62 static /*@only@*/ fileloc lastparseerror
= fileloc_undefined
;
63 static /*@only@*/ fileloc lastbug
= fileloc_undefined
;
64 static bool llgenerrorreal (flagcode p_code
,
65 const char *p_srcFile
, int p_srcLine
,
66 /*@only@*/ cstring p_s
,
67 /*@temp@*/ cstring p_addtext
,
68 fileloc p_fl
, bool p_iserror
, bool p_indent
)
69 /*@modifies g_warningstream@*/ ;
70 static bool llgenerroraux (flagcode p_code
, const char *p_srcFile
, int p_srcLine
,
71 /*@only@*/ cstring p_s
,
72 /*@temp@*/ cstring p_addtext
,
73 fileloc p_fl
, bool p_iserror
, bool p_indent
)
74 /*@modifies g_warningstream@*/ ;
76 static void generateCSV (flagcode p_code
, cstring p_s
, cstring p_addtext
, fileloc p_fl
)
77 /*@modifies g_csvstream@*/ ;
79 static void printError (FILE *p_stream
, /*@only@*/ cstring p_sc
)
80 /*@globals s_lastfileloclen @*/
81 /*@modifies *p_stream@*/ ;
82 static void printMessage (FILE *p_stream
, /*@only@*/ cstring p_s
)
83 /*@modifies *p_stream@*/ ;
85 static void llgenhint (/*@only@*/ cstring p_s
) /*@modifies g_warningstream@*/ ;
87 static void showSourceLoc (const char *srcFile
, int srcLine
)
88 /*@modifies g_warningstream@*/
90 if (context_getFlag (FLG_SHOWSOURCELOC
)) {
91 llgenhint (message ("%s:%d: Source code error generation point.",
92 cstring_fromChars (srcFile
), srcLine
));
97 static /*@null@*/ char *
98 maxcp (/*@null@*/ /*@returned@*/ char *a
, /*@null@*/ /*@returned@*/ char *b
)
105 printBugReport (void)
107 fprintf (g_errorstream
, " *** Please report bug to %s ***\n",
110 /* don't exit (EXIT_FAILURE); */
113 static bool s_needsPrepare
= TRUE
;
115 static void prepareMessage (void)
116 /*@modifies internalState, g_messagestream@*/
118 DPRINTF (("Prepare message: %s", bool_unparse (context_loadingLibrary ())));
121 if ((context_isPreprocessing () || context_loadingLibrary ())
123 && context_getFlag (FLG_SHOWSCAN
))
127 s_needsPrepare
= FALSE
;
133 static void closeMessage (void)
134 /*@modifies internalState, g_messagestream@*/
136 if (context_isPreprocessing ()
137 && context_getFlag (FLG_SHOWSCAN
))
140 displayScanOpen (cstring_makeLiteral ("more preprocessing ."));
141 llassertprotect (!s_needsPrepare
);
142 s_needsPrepare
= TRUE
;
151 llmsg (/*@only@*/ cstring s
)
153 context_setNeednl ();
155 printMessage (g_messagestream
, s
);
160 lldiagmsg (/*@only@*/ cstring s
)
162 static bool inmsg
= FALSE
;
166 fprintf (g_errorstream
,
167 "Recursive message call detected: %s\n",
168 cstring_toCharsSafe (s
));
174 context_setNeednl ();
176 printMessage (g_messagestream
, s
);
183 llmsgplain (/*@only@*/ cstring s
)
185 context_setNeednl ();
187 printMessage (g_messagestream
, s
);
191 void llerror_flagWarning (cstring s
)
193 if (context_getFlag (FLG_WARNFLAGS
))
195 llgenmsg (s
, g_currentloc
);
204 llgenhint (/*@only@*/ cstring s
) /*@modifies g_warningstream@*/
206 int indent
= context_getIndentSpaces () - 1;
208 if (indent
< 0) indent
= 0;
210 context_setNeednl ();
211 printIndentMessage (g_warningstream
, s
, indent
);
217 if (context_getFlag (FLG_HINTS
) &&
218 !(context_inSuppressRegion () || context_inSuppressZone (g_currentloc
)))
229 llshowhint (flagcode f
)
231 if (context_getFlag (FLG_HINTS
))
233 if ((flagcode_numReported (f
) == 0) || context_getFlag (FLG_FORCEHINTS
))
235 cstring desc
= flagcodeHint (f
);
237 if (cstring_isDefined (desc
))
239 llgenhint (cstring_copy (desc
));
246 llsuppresshint2 (char c
, flagcode f1
, flagcode f2
)
249 if (context_getFlag (FLG_HINTS
))
251 if ((flagcode_numReported (f1
) == 0
252 || flagcode_numReported (f2
) == 0)
253 || context_getFlag (FLG_FORCEHINTS
))
255 cstring desc
= flagcodeHint (f1
);
256 context_setNeednl ();
257 s_lastfileloclen
= 8;
259 if (cstring_isUndefined (desc
))
261 desc
= flagcodeHint (f2
);
264 if (flagcode_isNamePrefixFlag (f1
))
269 if (flagcode_isNamePrefixFlag (f2
))
276 if (cstring_isDefined (desc
))
278 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc
,
280 flagcode_unparse (f1
)));
284 llgenhint (message ("(Use %h%s to inhibit warning)",
285 c
, flagcode_unparse (f1
)));
290 if (cstring_isDefined (desc
))
292 llgenhint (message ("%s (Use either %h%s or %h%s to inhibit warning)", desc
,
294 flagcode_unparse (f1
),
296 flagcode_unparse (f2
)));
300 llgenhint (message ("(Use either %h%s or %h%s to inhibit warning)", c
,
301 flagcode_unparse (f1
),
302 c
, flagcode_unparse (f2
)));
310 llsuppresshint (char c
, flagcode f
)
312 if (context_getFlag (FLG_HINTS
))
314 if ((flagcode_numReported (f
) == 0) || context_getFlag (FLG_FORCEHINTS
))
316 cstring desc
= flagcodeHint (f
);
317 context_setNeednl ();
318 s_lastfileloclen
= 8;
320 if (flagcode_isNamePrefixFlag (f
))
325 if (cstring_isDefined (desc
))
327 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc
, c
,
328 flagcode_unparse (f
)));
332 llgenhint (message ("(Use %h%s to inhibit warning)", c
,
333 flagcode_unparse (f
)));
340 llnosuppresshint (flagcode f
)
342 if (context_getFlag (FLG_FORCEHINTS
))
344 cstring desc
= flagcodeHint (f
);
345 context_setNeednl ();
346 s_lastfileloclen
= 8;
348 if (cstring_isDefined (desc
))
350 printError (g_warningstream
, message (" %s", desc
));
355 /*@constant int MAXSEARCH; @*/
356 # define MAXSEARCH 20
358 /*@constant int MINLINE; @*/
361 typedef /*@null@*/ /*@dependent@*/ char *nd_charp
;
364 mstring_spaces (int n
)
372 ret
= (char *) dmalloc (size_fromInt (n
+ 1));
375 for (i
= 0; i
< n
; i
++)
388 ** Divides a string into lines of up to maxline characters.
390 ** Initial string: *sp
392 ** Output split: *sp / *tp
397 mstring_split (/*@returned@*/ char **sp
,
398 /*@out@*/ nd_charp
*tp
,
399 int maxline
, /*@in@*/ int *indentchars
)
408 DPRINTF (("Split: %s / %d", *sp
, maxline
));
410 if (maxline
< MINLINELEN
)
412 maxline
= MINLINELEN
;
415 if (*indentchars
> 0)
417 s
= *sp
= mstring_concatFree1 (mstring_spaces (*indentchars
), s
);
424 ** if there is a newline in first maxline characters, split there
425 ** if line len is <= maxline, return no split
426 ** if there is a ':' or ';' or ',' followed by ' ' in first maxline characters,
427 ** split there unless the ' ' is followed by a '}', then
429 ** of the ';' is inside quotation marks
430 ** if there is a space or tab in last maxsearch characters, split there
431 ** else, split at maxline
433 ** special code: slash [1-9] after a newline means indent the rest <n> chars
437 nl
= strchr (s
, '\n');
439 if ((nl
!= NULL
) && ((nl
- s
) < maxline
))
446 llassertprotect (*tp
== NULL
|| (*tp
> osp
));
450 if (*t
>= '\1' && *t
<= '\7')
452 *indentchars
+= (int) (*t
- '\1') + 1;
459 else if (size_toInt (strlen (s
)) < maxline
)
461 llassertprotect (*tp
== NULL
);
468 char *lcolon
, *lsemi
, *lcomma
;
475 lcolon
= strrchr (s
, ':');
476 lsemi
= strrchr (s
, ';');
477 lcomma
= strrchr (s
, ',');
481 splitat
= maxcp (lcolon
, lsemi
);
483 if (splitat
!= NULL
&& ((int)(splitat
- s
) > MINLINE
)
484 && *(splitat
) != '\0'
485 && *(splitat
+ 1) == ' '
486 && (*(splitat
+ 2) != '}'
487 && *(splitat
+ 2) != ','
488 && (*(splitat
+ 2) != '\0')))
490 *(splitat
+ 1) = '\0';
493 llassertprotect (*tp
== NULL
|| (*tp
> osp
));
497 if (lcomma
!= NULL
&& ((lcomma
- s
) > maxline
- 5))
501 if (splitat
!= NULL
&& ((int)(splitat
- s
) > MINLINE
)
502 && *(splitat
) != '\0'
503 && *(splitat
+ 1) == ' '
504 && (*(splitat
+ 2) != '}'
505 && (*(splitat
+ 2) != '\0')))
507 *(splitat
+ 1) = '\0';
510 llassertprotect (*tp
== NULL
|| (*tp
> osp
));
516 ** Search for any breaking point (at least 4 letters past s)
519 while (*t
!= ' ' && *t
!= '\t' && i
< MAXSEARCH
&& t
> (s
+ 4))
525 if (*t
!= ' ' && *t
!= '\t')
527 llassertprotect (maxline
> 0);
528 t
= mstring_copy (s
+ maxline
);
529 *(s
+ maxline
) = '\0';
534 llassertprotect (*tp
== NULL
|| (*tp
> osp
));
540 /* Won't be true since t is a copy: llassertprotect (*tp == NULL || (*tp > osp)); */
549 if (*t
== '\0') return;
552 ** returns unqualified as only
557 llassert (*sp
!= *tp
);
566 void limitmessage (/*@only@*/ cstring s
, fileloc loc
)
568 if (s_mcount
> context_getLimit () + 1)
574 cstring flstring
= fileloc_unparse (loc
);
576 s_lastfileloclen
= cstring_length (flstring
);
577 cstring_free (saveOneMessage
);
578 saveOneMessage
= message ("%q: %q", flstring
, s
);
582 static int parseerrorcount
= 0;
584 void cleanupMessages (void)
588 if (context_unlimitedMessages ())
594 int unprinted
= s_mcount
- context_getLimit ();
598 if (unprinted
== 1 && cstring_isDefined (saveOneMessage
))
601 printError (g_warningstream
, saveOneMessage
);
603 saveOneMessage
= cstring_undefined
;
607 if (cstring_isDefined (saveOneMessage
))
609 /* cstring_free (saveOneMessage); */
610 saveOneMessage
= cstring_undefined
;
613 fprintf (g_warningstream
, "%s: (%d more similar errors unprinted)\n",
614 cstring_toCharsSafe (fileloc_filename (g_currentloc
)),
615 s_mcount
- context_getLimit ());
624 llgenmsg (/*@only@*/ cstring s
, fileloc fl
)
626 cstring flstring
= fileloc_unparse (fl
);
627 s_lastfileloclen
= cstring_length (flstring
);
630 (void) printError (g_warningstream
, message ("%q: %q", flstring
, s
));
635 llgenindentmsg (/*@only@*/ cstring s
, fileloc fl
)
637 cstring flstring
= fileloc_unparse (fl
);
638 int indentspaces
= context_getLocIndentSpaces ();
641 (void) printIndentMessage (g_warningstream
, message ("%q: %q", flstring
, s
),
648 llgenindentmsgnoloc (/*@only@*/ cstring s
)
651 (void) printIndentMessage (g_warningstream
, s
, context_getIndentSpaces ());
656 llgentypeerroraux (const char *srcFile
, int srcLine
,
657 flagcode ocode
, ctype t1
, exprNode e1
, ctype t2
, exprNode e2
,
658 /*@only@*/ cstring s
, fileloc fl
)
660 cstring hint
= cstring_undefined
;
661 flagcode code
= ocode
;
662 flagcode hcode
= INVALID_FLAG
;
666 DPRINTF (("Type error [%s]: %s / %s : %s / %s",
667 flagcode_unparse (ocode
),
668 exprNode_unparse (e1
), exprNode_unparse (e2
),
669 ctype_unparse (t1
), ctype_unparse (t2
)));
671 DPRINTF (("Bool: %s / %s",
672 bool_unparse (ctype_isBool (t1
)),
673 bool_unparse (ctype_isBool (t2
))));
676 ** Set the flag using the underlying types that didn't match.
679 while (ctype_isPointer (ut1
) && ctype_isPointer (ut2
)) {
680 ut1
= ctype_baseArrayPtr (ut1
);
681 ut2
= ctype_baseArrayPtr (ut2
);
684 if (ctype_isRealNumAbstract (ut1
) && exprNode_isNumLiteral (e2
))
686 hcode
= FLG_NUMABSTRACTLIT
;
688 else if ((ctype_isFloat (ut1
) && ctype_isDouble (ut2
))
689 || (ctype_isFloat (ut1
) && ctype_isDouble (ut2
)))
691 hcode
= FLG_FLOATDOUBLE
;
693 else if ((exprNode_isCharLiteral (e1
) && ctype_isInt (ut2
))
694 || (exprNode_isCharLiteral (e2
) && ctype_isInt (ut1
)))
696 hcode
= FLG_CHARINTLITERAL
;
698 else if ((exprNode_isNumLiteral (e1
) && ctype_isReal (ut2
))
699 || (exprNode_isNumLiteral (e2
) && ctype_isReal (ut1
)))
701 hcode
= FLG_NUMLITERAL
;
703 else if ((ctype_isManifestBool (ut1
) && ctype_isInt (ut2
))
704 || (ctype_isInt (ut1
) && ctype_isManifestBool (ut2
)))
705 /* evs 2000-07-24: was ctype_isDirectBool */
709 else if (((ctype_isChar (ut1
) && !ctype_isInt (ut1
)) && ctype_isInt (ut2
))
710 || ((ctype_isInt (ut1
) && (ctype_isChar (ut2
) && !ctype_isInt (ut2
)))))
714 else if ((ctype_isInt (ut1
) && ctype_isInt (ut2
))
715 || (ctype_isChar (ut1
) && ctype_isChar (ut2
))
716 || (ctype_isDouble (ut1
) && ctype_isDouble (ut2
)))
718 if (!bool_equal (ctype_isSigned (ut1
), ctype_isSigned (ut2
)))
720 if (ctype_isArbitraryIntegral (ctype_realType (ut1
))
721 && !ctype_isArbitraryIntegral (ctype_realType (ut2
)))
723 hcode
= FLG_MATCHANYINTEGRAL
;
725 else if (ctype_isArbitraryIntegral (ctype_realType (ut2
))
726 && !ctype_isArbitraryIntegral (ctype_realType (ut1
)))
728 hcode
= FLG_MATCHANYINTEGRAL
;
731 /*drl 4-270-2003 even if ignoresigns is set there may be another
732 problem that is causing splint to complain about a type error.
733 Don't tell the user that they can add +ignoresigns if it's
736 DPRINTF(("TEST INGORESIGNS"));
737 if (context_getFlag(FLG_IGNORESIGNS
) )
739 DPRINTF(("INGORESIGNS SET"));
740 hcode
= FLG_IGNOREQUALS
;
745 DPRINTF(("INGORESIGNS NOT SET"));
746 hcode
= FLG_IGNORESIGNS
;
752 hcode
= FLG_IGNOREQUALS
;
755 else if (ctype_isArbitraryIntegral (ctype_realType (ut1
)))
757 DPRINTF (("HERE: %s", ctype_unparse (ctype_realType (ut2
))));
759 if (ctype_isArbitraryIntegral (ctype_realType (ut2
)))
761 hcode
= FLG_MATCHANYINTEGRAL
;
763 else if (ctype_equal (ut2
, ctype_ulint
))
765 hcode
= FLG_LONGUNSIGNEDINTEGRAL
;
767 else if (ctype_equal (ut2
, ctype_lint
))
769 hcode
= FLG_LONGINTEGRAL
;
771 else if (ctype_isInt (ut2
))
773 hcode
= FLG_MATCHANYINTEGRAL
;
780 else if (ctype_isArbitraryIntegral (ctype_realType (ut2
)))
782 ctype tr
= ctype_realType (ut1
);
784 if (ctype_isArbitraryIntegral (tr
))
786 hcode
= FLG_MATCHANYINTEGRAL
;
788 else if (ctype_match (ut1
, ctype_ulint
))
790 if (ctype_isUnsignedIntegral (tr
))
792 hcode
= FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL
;
794 else if (ctype_isSignedIntegral (tr
))
800 hcode
= FLG_LONGUNSIGNEDINTEGRAL
;
803 else if (ctype_match (ut1
, ctype_lint
))
805 if (ctype_isSignedIntegral (tr
))
807 hcode
= FLG_LONGSIGNEDINTEGRAL
;
809 else if (ctype_isSignedIntegral (tr
))
815 hcode
= FLG_LONGINTEGRAL
;
818 else if (ctype_isInt (ut1
))
820 hcode
= FLG_MATCHANYINTEGRAL
;
832 if (hcode
== INVALID_FLAG
)
834 DPRINTF (("[%s] %s - %s / %s",
836 bool_unparse (ctype_isEnum (ut1
)),
837 bool_unparse (ctype_isEnum (ctype_realType (ut1
))),
838 bool_unparse (ctype_isInt (ut2
))));
840 if (ctype_isAbstract (ut1
) && !ctype_isAbstract (ut2
))
842 uentry ue1
= usymtab_getTypeEntry (ctype_typeId (ut1
));
843 ctype ct
= uentry_getType (ue1
);
845 if (ctype_match (ct
, ut2
))
848 hint
= message ("Underlying types match, but %s is an "
849 "abstract type that is not accessible here.",
853 else if (ctype_isAbstract (ut2
) && !ctype_isAbstract (ut1
))
855 uentry ue
= usymtab_getTypeEntry (ctype_typeId (ut2
));
856 ctype ct
= uentry_getType (ue
);
858 if (ctype_match (ct
, ut1
))
860 if (ctype_isNumAbstract (ut2
))
862 if (exprNode_isNumLiteral (e1
))
864 code
= FLG_NUMABSTRACTLIT
;
865 hint
= message ("Underlying types match, but %s is a "
866 "numabstract type that is not accessible here. "
867 "(Use +numabstractlit to allow numeric literals "
868 "to be used as numabstract type values.)",
873 code
= FLG_NUMABSTRACT
;
874 hint
= message ("Underlying types match, but %s is a "
875 "numabstract type that is not accessible here.",
882 hint
= message ("Underlying types match, but %s is an "
883 "abstract type that is not accessible here.",
890 ; /* Not an abstract mismatch. */
894 if (hcode
== INVALID_FLAG
)
896 if ((ctype_isEnum (ut1
) && ctype_isInt (ut2
))
897 || (ctype_isEnum (ut2
) && ctype_isInt (ut1
)))
901 else if ((ctype_isEnum (ut1
) && ctype_isInt (ut2
))
902 || (ctype_isEnum (ut2
) && ctype_isInt (ut1
)))
906 else if ((ctype_isSignedChar (ut1
) && ctype_isUnsignedChar (ut2
))
907 || (ctype_isUnsignedChar (ut1
) && ctype_isSignedChar (ut2
)))
909 hcode
= FLG_CHARUNSIGNEDCHAR
;
911 else if (ctype_isNumeric (ut1
) && ctype_isNumeric (ut2
))
913 hcode
= FLG_RELAXTYPES
;
914 DPRINTF (("Setting relax types!"));
918 DPRINTF (("No special type rule: %s / %s", ctype_unparse (ut1
),
919 ctype_unparse (ut2
)));
924 if (cstring_isDefined (hint
))
926 if (!context_suppressFlagMsg (ocode
, fl
))
928 return xllgenhinterror (srcFile
, srcLine
, code
, s
, hint
, fl
);
939 if (hcode
!= INVALID_FLAG
&& hcode
!= ocode
)
944 if (llgenerroraux (ocode
, srcFile
, srcLine
, s
,
945 flagcodeHint (code
), fl
, TRUE
, FALSE
))
949 if (context_flagOn (code
, fl
))
951 /* The flag is alreay set, something buggy in the flag code */
952 llcontbug (message ("No hint available, flag %s is already set.",
953 flagcode_unparse (code
)));
962 llsuppresshint ('-', code
);
965 flagcode_recordError (code
);
974 xllgentypeerror (const char *srcFile
, int srcLine
,
975 ctype t1
, exprNode e1
, ctype t2
, exprNode e2
,
976 /*@only@*/ cstring s
, fileloc fl
)
978 return llgentypeerroraux (srcFile
, srcLine
, FLG_TYPE
, t1
, e1
, t2
, e2
, s
, fl
);
982 xllgenformattypeerror (const char *srcFile
, int srcLine
,
983 ctype t1
, exprNode e1
, ctype t2
, exprNode e2
,
984 /*@only@*/ cstring s
, fileloc fl
)
986 if (!context_suppressFlagMsg (FLG_FORMATTYPE
, fl
))
989 && ctype_isNumAbstract (t2
))
991 if (!context_suppressFlagMsg (FLG_NUMABSTRACTPRINT
, fl
))
993 return llgentypeerroraux (srcFile
, srcLine
, FLG_NUMABSTRACTPRINT
, t1
, e1
, t2
, e2
, s
, fl
);
1002 return llgentypeerroraux (srcFile
, srcLine
, FLG_FORMATTYPE
, t1
, e1
, t2
, e2
, s
, fl
);
1013 xllgenerror (const char *srcFile
, int srcLine
, flagcode o
, /*@only@*/ cstring s
, fileloc fl
)
1015 if (llgenerroraux (o
, srcFile
, srcLine
, s
, flagcodeHint (o
), fl
, TRUE
, FALSE
))
1017 llnosuppresshint (o
);
1018 flagcode_recordError (o
);
1024 flagcode_recordSuppressed (o
);
1030 xllgenhinterror (const char *srcFile
, int srcLine
,
1031 flagcode o
, /*@only@*/ cstring s
, /*@only@*/ cstring hint
,
1034 if (!context_suppressFlagMsg (o
, fl
))
1036 if (llgenerroraux (o
, srcFile
, srcLine
, s
, hint
, fl
, TRUE
, FALSE
))
1038 flagcode_recordError (o
);
1040 if (context_getFlag (FLG_HINTS
))
1046 cstring_free (hint
);
1053 cstring_free (hint
);
1057 cstring_free (hint
);
1061 flagcode_recordSuppressed (o
);
1066 llrealerror (flagcode code
, const char *srcFile
, int srcLine
, /*@only@*/ cstring s
, /*@temp@*/ cstring addtext
, fileloc fl
)
1068 return (llgenerrorreal (code
, srcFile
, srcLine
, s
, addtext
, fl
, TRUE
, FALSE
));
1072 llgenerroraux (flagcode code
,
1073 const char *srcFile
, int srcLine
,
1074 /*@only@*/ cstring s
,
1076 fileloc fl
, bool iserror
, bool indent
)
1078 if (context_inSuppressZone (fl
))
1084 if (llgenerrorreal (code
, srcFile
, srcLine
, s
, addtext
, fl
, iserror
, indent
)) {
1092 xllforceerror (const char *srcFile
, int srcLine
,
1093 flagcode code
, /*@only@*/ cstring s
, fileloc fl
)
1095 flagcode_recordError (code
);
1097 if (llgenerrorreal (code
, srcFile
, srcLine
, s
, cstring_undefined
, fl
, TRUE
, FALSE
)) {
1105 static void generateCSV (flagcode code
, cstring s
, cstring addtext
, fileloc fl
)
1108 if (g_csvstream
!= NULL
) {
1109 /* Warning, Flag Code, Flag Name, Priority, File, Line, Column, Warning Text, Additional Text */
1110 fprintf (g_csvstream
, "%d,%d,%s,%d,%s,%d,%d,\"%s\"",
1111 context_numErrors (),
1112 (int) code
, /* flag code */
1113 cstring_toCharsSafe (flagcode_unparse (code
)), /* flag name */
1114 flagcode_priority (code
), /* priority */
1115 cstring_toCharsSafe (fileloc_outputFilename (fl
)),
1116 fileloc_lineno (fl
),
1117 fileloc_column (fl
),
1118 cstring_toCharsSafe (s
));
1120 if (cstring_isDefined (addtext
)) {
1121 fprintf (g_csvstream
, ",\"%s\"\n", cstring_toCharsSafe (addtext
));
1123 fprintf (g_csvstream
, "\n");
1129 llgenerrorreal (flagcode code
, const char *srcFile
, int srcLine
,
1130 /*@only@*/ cstring s
,
1132 fileloc fl
, bool iserror
, bool indent
)
1136 /* duplicate message (rescanning a header file */
1138 if (!messageLog_add (context_messageLog (), fl
, s
))
1140 DPRINTF (("Duplicate message suppressed! %s / %s",
1141 fileloc_unparse (fl
), s
));
1147 ** If herald has not been displayed, display it before the first message.
1152 if (iserror
) context_hasError ();
1154 if (context_unlimitedMessages ())
1161 ** suppress excessive messages:
1166 char *sc
= cstring_toCharsSafe (s
);
1167 char *tmpmsg
= strchr (sc
, ':');
1175 char *savechar
= tmpmsg
;
1181 if (cstring_equal (s_lastmsg
, cstring_fromChars (tmpmsg
)))
1184 if (s_mcount
== (context_getLimit () + 1))
1186 limitmessage (s
, fl
);
1190 if (s_mcount
> (context_getLimit ()))
1200 cstring_free (s_lastmsg
);
1201 s_lastmsg
= cstring_fromCharsNew (tmpmsg
);
1205 DPRINTF (("Here..."));
1207 if (context_hasAliasAnnote ())
1209 char *sc
= cstring_toCharsSafe (s
);
1210 char *fcolon
= strchr (sc
, ':');
1211 cstring a
= context_getAliasAnnote ();
1216 s
= message ("%q (%q)", s
, a
);
1223 afterColon
= cstring_fromCharsNew (fcolon
+ 1);
1225 s
= message ("%q (%q):%q", s
, a
, afterColon
);
1229 if (context_hasMessageAnnote ())
1231 char *fcolon
= strchr (cstring_toCharsSafe (s
), ':');
1236 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1237 s
= message ("%q (%q)", s
, context_getMessageAnnote ());
1238 /*@=dependenttrans@*/
1245 afterColon
= cstring_fromCharsNew (fcolon
+ 1);
1247 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1248 s
= message ("%q (%q):%q", s
,
1249 context_getMessageAnnote (), afterColon
);
1250 /*@=dependenttrans@*/
1254 context_setNeednl ();
1257 if (context_showFunction ())
1259 cstring fname
= fileloc_unparseFilename (g_currentloc
);
1261 if (context_inIterDef ())
1263 fprintf (g_warningstream
, "%s: (in iter %s)\n",
1264 cstring_toCharsSafe (fname
),
1265 cstring_toCharsSafe (context_inFunctionName ()));
1267 else if (context_inIterEnd ())
1269 fprintf (g_warningstream
, "%s: (in iter finalizer %s)\n",
1270 cstring_toCharsSafe (fname
),
1271 cstring_toCharsSafe (context_inFunctionName ()));
1273 else if (context_inMacro ())
1275 fprintf (g_warningstream
, "%s: (in macro %s)\n", cstring_toCharsSafe (fname
),
1276 cstring_toCharsSafe (context_inFunctionName ()));
1280 fprintf (g_warningstream
, "%s: (in function %s)\n",
1281 cstring_toCharsSafe (fname
),
1282 cstring_toCharsSafe (context_inFunctionName ()));
1285 cstring_free (fname
);
1286 context_setShownFunction ();
1289 flstring
= fileloc_unparse (fl
);
1290 s_lastfileloclen
= cstring_length (flstring
);
1292 generateCSV (code
, s
, addtext
, fl
);
1296 printError (g_warningstream
, message (" %q: %q", flstring
, s
));
1300 printError (g_warningstream
, message ("%q: %q", flstring
, s
));
1303 showSourceLoc (srcFile
, srcLine
);
1311 ** message contains no '\n'
1312 ** message fits in one line: print it
1313 ** message fits in two lines with 3-space indent after fileloc: print it
1314 ** split line with 5-space indent from left margin: print it
1319 void printMessage (FILE *stream
, /*@only@*/ cstring s
)
1321 printIndentMessage (stream
, s
, 0);
1325 void printIndentMessage (FILE *stream
, /*@only@*/ cstring sc
, int indent
)
1327 static bool inbody
= FALSE
;
1328 int maxlen
= context_getLineLen ();
1329 char *s
= cstring_toCharsSafe (sc
);
1332 llassertprotect (!inbody
);
1340 llassertprotect (st
!= olds
);
1342 mstring_split (&st
, &t
, maxlen
, &indent
);
1343 fprintf (stream
, "%s\n", st
);
1344 llassertprotect (t
!= s
);
1346 } while (s
!= NULL
) ;
1353 void printError (FILE *stream
, /*@only@*/ cstring sc
)
1355 int maxlen
= context_getLineLen ();
1356 size_t nspaces
= s_lastfileloclen
+ 5;
1357 int nextlen
= maxlen
- size_toInt (nspaces
);
1358 size_t len
= cstring_length (sc
);
1360 char *s
= cstring_toCharsSafe (sc
);
1364 DPRINTF (("Print error: [%s]", sc
));
1366 if (size_toInt (len
) < (maxlen
+ nextlen
) && (strchr (s
, '\n') == NULL
))
1368 mstring_split (&s
, &t
, maxlen
, &indent
);
1370 fprintf (stream
, "%s\n", s
);
1374 len
= mstring_length (t
);
1376 if (size_toInt (len
) < (maxlen
- 3) && (strchr (t
, '\n') == NULL
)
1377 && size_toInt (len
) > (nextlen
- 1))
1379 fprintf (stream
, " %s\n", t
);
1383 char *spaces
= (char *) dmalloc ((nspaces
+ 1) * sizeof (*spaces
));
1386 for (i
= 0; i
< size_toInt (nspaces
); i
++)
1391 spaces
[nspaces
] = '\0';
1396 mstring_split (&st
, &t
, nextlen
, &indent
);
1397 fprintf (stream
, "%s%s\n", spaces
, st
);
1406 DPRINTF (("Here 1: [%s]", sc
));
1408 if (size_toInt (len
) < (maxlen
+ maxlen
- 1) && (strchr (s
, '\n') != NULL
))
1410 nspaces
= ((maxlen
+ maxlen
- 1) - len
) / 2;
1412 if (nspaces
< 1) nspaces
= 1;
1414 nextlen
= size_toInt (maxlen
- nspaces
);
1416 mstring_split (&s
, &t
, maxlen
, &indent
);
1418 fprintf (stream
, "%s\n", s
);
1422 char *spaces
= (char *) dmalloc ((nspaces
+ 1) * sizeof (*spaces
));
1425 for (i
= 0; i
< size_toInt (nspaces
); i
++)
1430 spaces
[nspaces
] = '\0';
1436 mstring_split (&st
, &t
, nextlen
, &indent
);
1437 fprintf (stream
, "%s%s\n", spaces
, st
);
1446 nextlen
= size_toInt (maxlen
- nspaces
);
1448 DPRINTF (("Here 2: [%s]", s
));
1449 mstring_split (&s
, &t
, maxlen
, &indent
);
1450 DPRINTF (("Here 3: [%s] [%s]", s
, t
));
1452 fprintf (stream
, "%s\n", s
);
1456 char *spaces
= (char *) dmalloc ((nspaces
+ 1) * sizeof (*spaces
));
1459 for (i
= 0; i
< nspaces
; i
++)
1464 spaces
[nspaces
] = '\0';
1469 DPRINTF (("Loop: [%s]", t
));
1470 mstring_split (&st
, &t
, nextlen
, &indent
);
1471 DPRINTF (("Split: [%s] [%s]", st
, t
));
1472 fprintf (stream
, "%s%s\n", spaces
, st
);
1473 DPRINTF (("Next..."));
1486 xllfatalbug (const char *srcFile
, int srcLine
, /*@only@*/ cstring s
)
1489 printError (g_errorstream
, message ("%q: *** Fatal bug: %q",
1490 fileloc_unparse (g_currentloc
), s
));
1491 showSourceLoc (srcFile
, srcLine
);
1498 lclfatalbug (char *msg
)
1501 printError (g_errorstream
,
1502 message ("*** Fatal Bug: %s", cstring_fromChars (msg
)));
1509 checkParseError (void)
1511 if (fileloc_withinLines (lastparseerror
, g_currentloc
, 10))
1513 llfatalerror (message ("%q: Cannot recover from parse error.",
1514 fileloc_unparse (g_currentloc
)));
1518 void llbugaux (cstring file
, int line
, /*@only@*/ cstring s
)
1521 static int numbugs
= 0;
1522 static bool inbug
= FALSE
;
1524 context_recordBug ();
1528 cstring temps
= fileloc_unparseRaw (file
, line
);
1530 fprintf (g_errorstream
,
1531 "%s: Recursive bug detected: %s\n",
1532 cstring_toCharsSafe (temps
),
1533 cstring_toCharsSafe (s
));
1534 cstring_free (temps
);
1543 if (fileloc_withinLines (lastparseerror
, g_currentloc
, 7))
1545 llfatalerror (message ("%q: Cannot recover from parse error.",
1546 fileloc_unparse (g_currentloc
)));
1549 (void) fflush (g_warningstream
);
1551 printError (g_errorstream
,
1552 message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1553 fileloc_unparse (g_currentloc
),
1554 fileloc_unparseRaw (file
, line
),
1557 /* printCodePoint (); no longer useful */
1562 ** This is confusing, and hardly ever useful.
1566 perror ("Possible system error diagnostic: ");
1577 if (numbugs
> context_getBugsLimit () && fileloc_withinLines (lastbug
, g_currentloc
, 2))
1580 (message ("%q: Cannot recover from last bug. "
1581 "(If you really want Splint to try to continue, use -bugslimit <n>.)",
1582 fileloc_unparse (g_currentloc
)));
1585 fprintf (g_errorstream
, " (attempting to continue, results may be incorrect)\n");
1586 fileloc_free (lastbug
);
1587 lastbug
= fileloc_copy (g_currentloc
);
1593 lclbug (/*@only@*/ cstring s
)
1596 printError (g_errorstream
, message ("*** Internal Bug: %q", s
));
1599 fprintf (g_errorstream
, " (attempting to continue, results may be incorrect)\n");
1604 xllfatalerror (const char *srcFile
, int srcLine
, cstring s
)
1607 printError (g_errorstream
, s
);
1608 printError (g_errorstream
, cstring_makeLiteral ("*** Cannot continue."));
1609 showSourceLoc (srcFile
, srcLine
);
1614 xllfatalerrorLoc (const char *srcFile
, int srcLine
, /*@only@*/ cstring s
)
1617 (void) fflush (g_warningstream
);
1618 printError (g_errorstream
, message ("%q: %q", fileloc_unparse (g_currentloc
), s
));
1619 printError (g_errorstream
, cstring_makeLiteral ("*** Cannot continue."));
1620 showSourceLoc (srcFile
, srcLine
);
1621 (void) fflush (g_warningstream
);
1628 return (s_lclerrors
> 0);
1632 lclHadNewError (void)
1634 static int lastcall
= 0;
1636 if (s_lclerrors
> lastcall
)
1638 lastcall
= s_lclerrors
;
1648 lclNumberErrors (void)
1650 return (s_lclerrors
);
1654 xlclerror (const char *srcFile
, int srcLine
, ltoken t
, /*@only@*/ cstring msg
)
1658 if (ltoken_getCode (t
) != NOTTOKEN
)
1660 cstring loc
= ltoken_unparseLoc (t
);
1661 s_lastfileloclen
= cstring_length (loc
);
1663 printError (g_warningstream
, message ("%q: %q", loc
, msg
));
1664 showSourceLoc (srcFile
, srcLine
);
1668 printError (g_warningstream
, msg
);
1669 showSourceLoc (srcFile
, srcLine
);
1674 lclplainerror (/*@only@*/ cstring msg
)
1677 printError (g_warningstream
, msg
);
1681 lclfatalerror (ltoken t
, /*@only@*/ cstring msg
)
1683 if (ltoken_getCode (t
) != NOTTOKEN
)
1685 cstring loc
= ltoken_unparseLoc (t
);
1686 s_lastfileloclen
= cstring_length (loc
);
1687 printError (g_errorstream
, message ("%q: %q", loc
, msg
));
1691 printError (g_errorstream
, msg
);
1694 printError (g_errorstream
, cstring_makeLiteral ("*** Cannot continue"));
1699 lclplainfatalerror (/*@only@*/ cstring msg
)
1701 (void) fflush (g_warningstream
);
1702 printError (g_errorstream
, message ("*** Cannot continue: %q", msg
));
1707 lclRedeclarationError (ltoken id
)
1709 cstring s
= ltoken_getRawString (id
);
1712 if (usymtab_existsEither (s
))
1714 uentry le
= usymtab_lookupEither (s
);
1716 lclerror (id
, message ("Respecification of %s", s
));
1717 llgenindentmsg (message ("Previous specification of %q",
1718 uentry_getName (le
)),
1719 uentry_whereSpecified (le
));
1723 lclerror (id
, message ("Identifier redeclared: %s", s
));
1727 void genppllerror (flagcode code
, /*@only@*/ cstring s
)
1729 if (context_inSuppressZone (g_currentloc
))
1735 if (context_getFlag (code
))
1739 displayScanClose ();
1744 if (code
!= FLG_PREPROC
)
1746 llsuppresshint ('-', code
);
1749 if (!context_isInCommandLine ())
1751 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1761 void genppllerrorhint (flagcode code
, /*@only@*/ cstring s
,
1762 /*@only@*/ cstring hint
)
1764 if (context_inSuppressZone (g_currentloc
))
1767 cstring_free (hint
);
1771 if (context_getFlag (code
))
1773 generateCSV (code
, s
, hint
, g_currentloc
);
1775 context_clearPreprocessing ();
1778 context_setPreprocessing ();
1784 cstring_free (hint
);
1789 void ppllerror (/*@only@*/ cstring s
)
1791 genppllerror (FLG_PREPROC
, s
);
1795 void pplldiagmsg (cstring s
)
1797 if (!context_isInCommandLine ())
1801 displayScanClose ();
1805 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1812 # endif /* DEADCODE */
1814 void loadllmsg (cstring s
)
1816 displayScanClose ();
1818 displayScanOpen (cstring_makeLiteral ("< ."));
1821 static void llreportparseerror (/*@only@*/ cstring s
)
1823 if (fileloc_withinLines (lastparseerror
, g_currentloc
, 5))
1829 llerror (FLG_SYNTAX
, s
);
1831 fileloc_free (lastparseerror
);
1832 lastparseerror
= fileloc_copy (g_currentloc
);
1836 bool xlloptgenerror (const char *srcFile
, int srcLine
,
1837 flagcode o
, /*@only@*/ cstring s
, fileloc loc
)
1839 DPRINTF (("xllopt: %s", s
));
1841 if (llrealerror (o
, srcFile
, srcLine
, s
, flagcodeHint (o
), loc
))
1843 DPRINTF (("Here we are!"));
1844 llsuppresshint ('-', o
);
1846 flagcode_recordError (o
);
1851 DPRINTF (("Suppressed!"));
1852 flagcode_recordSuppressed (o
);
1857 bool xoptgenerror2 (const char *srcFile
, int srcLine
,
1858 flagcode f1
, flagcode f2
, /*@only@*/ cstring s
, fileloc loc
)
1860 if (context_suppressFlagMsg (f1
, loc
))
1862 flagcode_recordSuppressed (f1
);
1867 if (context_suppressFlagMsg (f2
, loc
))
1869 flagcode_recordSuppressed (f2
);
1874 if (llrealerror (f1
, srcFile
, srcLine
, s
, flagcodeHint (f1
), loc
))
1876 llsuppresshint2 ('-', f1
, f2
);
1877 flagcode_recordError (f2
);
1883 flagcode_recordSuppressed (f2
);
1891 bool xoptgenerror2n (const char *srcFile
, int srcLine
,
1892 flagcode f1
, flagcode f2
, /*@only@*/ cstring s
, fileloc loc
)
1895 if (context_suppressFlagMsg (f1
, loc
))
1897 flagcode_recordSuppressed (f1
);
1902 if (context_suppressNotFlagMsg (f2
, loc
))
1904 flagcode_recordSuppressed (f2
);
1909 if (llrealerror (f1
, srcFile
, srcLine
, s
, flagcodeHint (f2
), loc
))
1911 llsuppresshint ('+', f2
);
1912 flagcode_recordError (f2
);
1917 flagcode_recordSuppressed (f2
);
1923 bool xllnoptgenerror (const char *srcFile
, int srcLine
,
1924 flagcode o
, /*@only@*/ cstring s
, fileloc loc
)
1926 if (llrealerror (o
, srcFile
, srcLine
, s
, flagcodeHint (o
), loc
))
1928 llsuppresshint ('+', o
);
1929 flagcode_recordError (o
);
1934 flagcode_recordSuppressed (o
);
1938 void xllparseerror (const char *srcFile
, int srcLine
, cstring s
)
1940 if (context_getFlag (FLG_TRYTORECOVER
))
1944 if (parseerrorcount
> GIVEUPPARSE
)
1946 if (cstring_isDefined (s
))
1948 xllfatalerror (srcFile
, srcLine
,
1949 message ("%q: Parse Error: %q. "
1950 "Too many errors, giving up.",
1951 fileloc_unparse (g_currentloc
), s
));
1955 xllfatalerror (srcFile
, srcLine
,
1956 message ("%q: Parse Error. Too many errors, giving up.",
1957 fileloc_unparse (g_currentloc
)));
1962 if (cstring_isDefined (s
))
1964 llreportparseerror (message ("Parse Error: %q. Attempting to continue.",
1966 showSourceLoc (srcFile
, srcLine
);
1970 llreportparseerror (message ("Parse Error. Attempting to continue."));
1971 showSourceLoc (srcFile
, srcLine
);
1979 if (cstring_isDefined (s
))
1981 msg
= message ("Parse Error: %q.", s
);
1985 msg
= message ("Parse Error.");
1990 message ("%q: %s (For help on parse errors, "
1991 "see splint -help parseerrors.)",
1992 fileloc_unparse (g_currentloc
), msg
));
1996 bool xfsgenerror (const char *srcFile
, int srcLine
,
1997 flagSpec fs
, /*@only@*/ cstring s
, fileloc fl
)
1999 if (flagSpec_isOn (fs
, fl
))
2001 flagcode firston
= flagSpec_getFirstOn (fs
, fl
);
2003 if (llgenerroraux (firston
, srcFile
, srcLine
, s
,
2004 flagcodeHint (firston
),
2007 llsuppresshint ('-', firston
);
2008 flagcode_recordError (firston
);
2013 flagcode_recordSuppressed (firston
);
2019 flagcode_recordSuppressed (flagSpec_getDominant (fs
));
2025 bool doCheck (bool x
, cstring pred
, cstring file
, int line
)
2028 llbug (message ("%q: Check Failed: %s",
2029 fileloc_unparseRaw (file
, line
),
2036 /*@observer@*/ cstring
lldecodeerror (int errnum
)
2038 return cstring_fromChars (strerror (errnum
));
2041 void llquietbugaux (cstring s
, /*@unused@*/ cstring file
, /*@unused@*/ int line
)
2045 printError (g_errorstream
, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
2046 fileloc_unparse (g_currentloc
),
2047 fileloc_unparseRaw (file
, line
),
2058 (void) fflush (g_warningstream
);
2059 (void) fflush (g_messagestream
);
2062 void displayScan (cstring msg
)
2066 displayScanClose ();
2069 llassert (!s_scanOpen
);
2071 if (context_getFlag (FLG_SHOWSCAN
))
2074 fprintf (g_messagestream
, "< %s >\n", cstring_toCharsSafe (msg
));
2075 (void) fflush (g_messagestream
);
2081 void displayScanOpen (cstring msg
)
2085 displayScanClose ();
2088 llassert (!s_scanOpen
);
2091 if (context_getFlag (FLG_SHOWSCAN
))
2093 fprintf (g_messagestream
, "< %s", cstring_toCharsSafe (msg
));
2094 (void) fflush (g_messagestream
);
2100 void displayScanContinue (/*@temp@*/ cstring msg
)
2102 if (context_getFlag (FLG_SHOWSCAN
))
2106 fprintf (g_messagestream
, "%s", cstring_toCharsSafe (msg
));
2107 (void) fflush (g_messagestream
);
2112 ** Don't call bug recursively
2115 fprintf (stderr
, "*** Bug: scan continue scan not open\n");
2120 void displayScanClose (void)
2124 if (context_getFlag (FLG_SHOWSCAN
))
2126 fprintf (g_messagestream
, " >\n");
2127 (void) fflush (g_messagestream
);
2133 ** Don't call bug recursively
2136 fprintf (stderr
, "*** Bug: scan close scan not open\n");