diff --git a/src/cc65/error.c b/src/cc65/error.c index 2ad7133ed..5cd29b388 100644 --- a/src/cc65/error.c +++ b/src/cc65/error.c @@ -59,8 +59,10 @@ /* Count of errors/warnings */ -unsigned ErrorCount = 0; -unsigned WarningCount = 0; +unsigned PPErrorCount = 0; /* Pre-parser errors */ +unsigned PPWarningCount = 0; /* Pre-parser warnings */ +unsigned ErrorCount = 0; /* Errors occurred in parser and later translation phases */ +unsigned WarningCount = 0; /* Warnings occurred in parser and later translation phases */ unsigned RecentLineNo = 0; unsigned RecentErrorCount = 0; @@ -197,7 +199,7 @@ void Internal (const char* Format, ...) -static void IntError (const char* Filename, unsigned LineNo, const char* Msg, va_list ap) +static void IntError (errcat_t EC, const char* Filename, unsigned LineNo, const char* Msg, va_list ap) /* Print an error message - internal function */ { fprintf (stderr, "%s:%u: Error: ", Filename, LineNo); @@ -208,7 +210,11 @@ static void IntError (const char* Filename, unsigned LineNo, const char* Msg, va Print (stderr, 1, "Input: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line)); } - ++ErrorCount; + if (EC != EC_PP) { + ++ErrorCount; + } else { + ++PPErrorCount; + } if (RecentLineNo != LineNo) { RecentLineNo = LineNo; RecentErrorCount = 0; @@ -216,7 +222,7 @@ static void IntError (const char* Filename, unsigned LineNo, const char* Msg, va ++RecentErrorCount; } - if (RecentErrorCount > 20 || ErrorCount > 200) { + if (RecentErrorCount > 20 || GetTotalErrors () > 200) { Fatal ("Too many errors"); } } @@ -228,18 +234,18 @@ void Error (const char* Format, ...) { va_list ap; va_start (ap, Format); - IntError (GetDiagnosticFileName (), GetDiagnosticLineNum (), Format, ap); + IntError (EC_PARSER, GetDiagnosticFileName (), GetDiagnosticLineNum (), Format, ap); va_end (ap); } -void LIError (const LineInfo* LI, const char* Format, ...) +void LIError (errcat_t EC, const LineInfo* LI, const char* Format, ...) /* Print an error message with the line info given explicitly */ { va_list ap; va_start (ap, Format); - IntError (GetInputName (LI), GetInputLine (LI), Format, ap); + IntError (EC, GetInputName (LI), GetInputLine (LI), Format, ap); va_end (ap); } @@ -250,7 +256,7 @@ void PPError (const char* Format, ...) { va_list ap; va_start (ap, Format); - IntError (GetCurrentFilename(), GetCurrentLineNum(), Format, ap); + IntError (EC_PP, GetCurrentFilename(), GetCurrentLineNum(), Format, ap); va_end (ap); } @@ -262,13 +268,13 @@ void PPError (const char* Format, ...) -static void IntWarning (const char* Filename, unsigned LineNo, const char* Msg, va_list ap) +static void IntWarning (errcat_t EC, const char* Filename, unsigned LineNo, const char* Msg, va_list ap) /* Print a warning message - internal function */ { if (IS_Get (&WarningsAreErrors)) { /* Treat the warning as an error */ - IntError (Filename, LineNo, Msg, ap); + IntError (EC, Filename, LineNo, Msg, ap); } else if (IS_Get (&WarnEnable)) { @@ -279,7 +285,12 @@ static void IntWarning (const char* Filename, unsigned LineNo, const char* Msg, if (Line) { Print (stderr, 1, "Input: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line)); } - ++WarningCount; + + if (EC != EC_PP) { + ++WarningCount; + } else { + ++PPWarningCount; + } } } @@ -291,18 +302,18 @@ void Warning (const char* Format, ...) { va_list ap; va_start (ap, Format); - IntWarning (GetDiagnosticFileName (), GetDiagnosticLineNum (), Format, ap); + IntWarning (EC_PARSER, GetDiagnosticFileName (), GetDiagnosticLineNum (), Format, ap); va_end (ap); } -void LIWarning (const LineInfo* LI, const char* Format, ...) +void LIWarning (errcat_t EC, const LineInfo* LI, const char* Format, ...) /* Print a warning message with the line info given explicitly */ { va_list ap; va_start (ap, Format); - IntWarning (GetInputName (LI), GetInputLine (LI), Format, ap); + IntWarning (EC, GetInputName (LI), GetInputLine (LI), Format, ap); va_end (ap); } @@ -313,7 +324,7 @@ void PPWarning (const char* Format, ...) { va_list ap; va_start (ap, Format); - IntWarning (GetCurrentFilename(), GetCurrentLineNum(), Format, ap); + IntWarning (EC_PP, GetCurrentFilename(), GetCurrentLineNum(), Format, ap); va_end (ap); } @@ -398,16 +409,34 @@ void PPNote (const char* Format, ...) /*****************************************************************************/ -/* Code */ +/* Error summary */ /*****************************************************************************/ +unsigned GetTotalErrors (void) +/* Get total count of errors of all categories */ +{ + return PPErrorCount + ErrorCount; +} + + + +unsigned GetTotalWarnings (void) +/* Get total count of warnings of all categories */ +{ + return PPWarningCount + WarningCount; +} + + + void ErrorReport (void) /* Report errors (called at end of compile) */ { - unsigned int V = (ErrorCount != 0 ? 0 : 1); - Print (stdout, V, "%u errors and %u warnings generated.\n", ErrorCount, WarningCount); + unsigned TotalErrors = GetTotalErrors (); + unsigned TotalWarnings = GetTotalWarnings (); + unsigned int V = (TotalErrors != 0 ? 0 : 1); + Print (stdout, V, "%u errors and %u warnings generated.\n", TotalErrors, TotalWarnings); } diff --git a/src/cc65/error.h b/src/cc65/error.h index 83be8c782..4dce6cf91 100644 --- a/src/cc65/error.h +++ b/src/cc65/error.h @@ -55,9 +55,20 @@ +/* Error categories */ +typedef enum errcat_t errcat_t; +enum errcat_t { + EC_PP, /* Pre-parser phases */ + EC_PARSER, /* Parser and later phases */ +}; + + + /* Count of errors/warnings */ -extern unsigned ErrorCount; -extern unsigned WarningCount; +extern unsigned PPErrorCount; /* Pre-parser errors */ +extern unsigned PPWarningCount; /* Pre-parser warnings */ +extern unsigned ErrorCount; /* Errors occurred in parser and later translation phases */ +extern unsigned WarningCount; /* Warnings occurred in parser and later translation phases */ /* Warning and error options */ extern IntStack WarnEnable; /* Enable warnings */ @@ -98,7 +109,7 @@ void Internal (const char* Format, ...) attribute ((noreturn, format (printf, 1, void Error (const char* Format, ...) attribute ((format (printf, 1, 2))); /* Print an error message */ -void LIError (const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 2, 3))); +void LIError (errcat_t EC, const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 3, 4))); /* Print an error message with the line info given explicitly */ void PPError (const char* Format, ...) attribute ((format (printf, 1, 2))); @@ -107,7 +118,7 @@ void PPError (const char* Format, ...) attribute ((format (printf, 1, 2))); void Warning (const char* Format, ...) attribute ((format (printf, 1, 2))); /* Print a warning message */ -void LIWarning (const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 2, 3))); +void LIWarning (errcat_t EC, const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 3, 4))); /* Print a warning message with the line info given explicitly */ void PPWarning (const char* Format, ...) attribute ((format (printf, 1, 2))); @@ -130,6 +141,12 @@ void LINote (const LineInfo* LI, const char* Format, ...) attribute ((format (pr void PPNote (const char* Format, ...) attribute ((format (printf, 1, 2))); /* Print a note message. For use within the preprocessor */ +unsigned GetTotalErrors (void); +/* Get total count of errors of all categories */ + +unsigned GetTotalWarnings (void); +/* Get total count of warnings of all categories */ + void ErrorReport (void); /* Report errors (called at end of compile) */ diff --git a/test/ref/Makefile b/test/ref/Makefile index 9538fdee7..9ecb33c00 100644 --- a/test/ref/Makefile +++ b/test/ref/Makefile @@ -63,7 +63,8 @@ CUSTOMSOURCES = \ # exact error output is required ERRORSOURCES = \ custom-reference-error.c \ - bug1889-missing-identifier.c + bug1889-missing-identifier.c \ + bug2312-preprocessor-error.c SOURCES := $(filter-out $(CUSTOMSOURCES) $(ERRORSOURCES),$(wildcard *.c)) diff --git a/test/ref/bug2312-preprocessor-error.c b/test/ref/bug2312-preprocessor-error.c new file mode 100644 index 000000000..b7872f514 --- /dev/null +++ b/test/ref/bug2312-preprocessor-error.c @@ -0,0 +1,8 @@ +/* Bug #2312 - Error recovery from preprocessor errors at the end of a declaration */ + +typedef int A; /* ';' consumption triggers PP below */ + +#define /* PP error during ';' consumption */ + +A f(void); /* Should be OK */ +int A(void); /* Should be an error */ diff --git a/test/ref/bug2312-preprocessor-error.cref b/test/ref/bug2312-preprocessor-error.cref new file mode 100644 index 000000000..680950fd6 --- /dev/null +++ b/test/ref/bug2312-preprocessor-error.cref @@ -0,0 +1,2 @@ +bug2312-preprocessor-error.c:5: Error: Missing macro name +bug2312-preprocessor-error.c:8: Error: Redefinition of typedef 'A' as different kind of symbol diff --git a/test/ref/custom-reference-error.c b/test/ref/custom-reference-error.c index 857145fc0..a7c1b6c56 100644 --- a/test/ref/custom-reference-error.c +++ b/test/ref/custom-reference-error.c @@ -13,7 +13,10 @@ and then "make" again to confirm */ -short main(int argc, char* argv[]) +typedef short return_t; +#error /* produce an error */ + +return_t main(int argc, char* argv[]) { printf("%02x", 0x42); /* produce an error */ n = 0; /* produce an error */ diff --git a/test/ref/custom-reference-error.cref b/test/ref/custom-reference-error.cref index 728cc0e15..b21c72dce 100644 --- a/test/ref/custom-reference-error.cref +++ b/test/ref/custom-reference-error.cref @@ -1,5 +1,6 @@ -custom-reference-error.c:18: Error: Call to undeclared function 'printf' -custom-reference-error.c:19: Error: Undeclared identifier 'n' -custom-reference-error.c:21: Warning: Control reaches end of non-void function [-Wreturn-type] -custom-reference-error.c:21: Warning: Parameter 'argc' is never used -custom-reference-error.c:21: Warning: Parameter 'argv' is never used +custom-reference-error.c:17: Error: #error +custom-reference-error.c:21: Error: Call to undeclared function 'printf' +custom-reference-error.c:22: Error: Undeclared identifier 'n' +custom-reference-error.c:24: Warning: Control reaches end of non-void function [-Wreturn-type] +custom-reference-error.c:24: Warning: Parameter 'argc' is never used +custom-reference-error.c:24: Warning: Parameter 'argv' is never used