1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-23 04:30:10 +00:00

Rewrote handling of the -W command line option. It is now used to enable or

disable warnings by name.


git-svn-id: svn://svn.cc65.org/cc65/trunk@4348 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz 2009-10-08 13:29:35 +00:00
parent 58e8826da2
commit b55419af59
8 changed files with 299 additions and 152 deletions

View File

@ -64,7 +64,7 @@ Short options:
-Os Inline some known functions
-T Include source as comment
-V Print the compiler version number
-W Suppress warnings
-W name[,name] Enable or disable warnings
-d Debug mode
-g Add debug info to object file
-h Help (this text)
@ -118,7 +118,7 @@ Here is a description of all the command line options:
Tells the compiler to generate code that checks for stack overflows. See
<tt><ref id="pragma-checkstack" name="#pragma&nbsp;checkstack"></tt> for an
explanation of this feature.
<tag><tt>--code-name seg</tt></tag>
@ -383,11 +383,27 @@ Here is a description of all the command line options:
<label id="option-W">
<tag><tt>-W</tt></tag>
<tag><tt>-W name[,name]</tt></tag>
This option will suppress any warnings generated by the compiler. Since
any source file may be written in a manner that it will not produce
compiler warnings, using this option is usually not a good idea.
This option allows to control warnings generated by the compiler. It is
followed by a comma separated list of warnings that should be enabled or
disabled. To disable a warning, its name is prefixed by a minus sign. If
no such prefix exists, or the name is prefixed by a plus sign, the warning
is enabled.
The following warning names are currently recognized:
<descrip>
<tag><tt/error/</tag>
Treat all warnings as errors.
<tag><tt/unknown-pragma/</tag>
Warn about known #pragmas.
<tag><tt/unused-label/</tag>
Warn about unused labels.
<tag><tt/unused-param/</tag>
Warn about unused function parameters.
<tag><tt/unused-var/</tag>
Warn about unused variables.
</descrip>
</descrip><p>
@ -398,7 +414,7 @@ The compiler will accept one C file per invocation and create a file with
the same base name, but with the extension replaced by ".s". The output
file contains assembler code suitable for the use with the ca65 macro
assembler.
Include files in single quotes are searched in the following places:
<enum>
<item>The current directory.
@ -411,7 +427,7 @@ Include files in angle brackets are searched in the following places:
<item>A compiled in directory which is often <tt>/usr/lib/cc65/include</tt> on
Linux systems.
<item>The value of the environment variable <tt/CC65_INC/ if it is defined.
<item>A subdirectory named <tt/include/ of the directory defined in the
<item>A subdirectory named <tt/include/ of the directory defined in the
environment variable <tt/CC65_HOME/, if it is defined.
<item>Any directory added with the <tt/-I/ option on the command line.
</enum>

View File

@ -60,115 +60,37 @@
unsigned ErrorCount = 0;
unsigned WarningCount = 0;
/* Warning and error options */
IntStack WarnEnable = INTSTACK(1); /* Enable warnings */
IntStack WarningsAreErrors = INTSTACK(0); /* Treat warnings as errors */
IntStack WarnUnusedLabel = INTSTACK(1); /* Warn about unused labels */
IntStack WarnUnusedParam = INTSTACK(1); /* Warn about unused parameters */
IntStack WarnUnusedVar = INTSTACK(1); /* Warn about unused variables */
IntStack WarnUnknownPragma = INTSTACK(1); /* Warn about unknown #pragmas */
/* Map the name of a warning to the intstack that holds its state */
typedef struct WarnMapEntry WarnMapEntry;
struct WarnMapEntry {
IntStack* Stack;
const char* Name;
};
static WarnMapEntry WarnMap[] = {
/* Keep sorted, even if this isn't used for now */
{ &WarningsAreErrors, "error" },
{ &WarnUnknownPragma, "unknown-pragma" },
{ &WarnUnusedLabel, "unused-label" },
{ &WarnUnusedParam, "unused-param" },
{ &WarnUnusedVar, "unused-var" },
};
/*****************************************************************************/
/* Code */
/* Handling of fatal errors */
/*****************************************************************************/
static void IntWarning (const char* Filename, unsigned LineNo, const char* Msg, va_list ap)
/* Print warning message - internal function. */
{
if (!IS_Get (&WarnDisable)) {
fprintf (stderr, "%s(%u): Warning: ", Filename, LineNo);
vfprintf (stderr, Msg, ap);
fprintf (stderr, "\n");
if (Line) {
Print (stderr, 1, "Input: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line));
}
++WarningCount;
}
}
void Warning (const char* Format, ...)
/* Print warning message. */
{
va_list ap;
va_start (ap, Format);
IntWarning (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap);
va_end (ap);
}
void LIWarning (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);
va_end (ap);
}
void PPWarning (const char* Format, ...)
/* Print warning message. For use within the preprocessor. */
{
va_list ap;
va_start (ap, Format);
IntWarning (GetCurrentFile(), GetCurrentLine(), Format, ap);
va_end (ap);
}
static void IntError (const char* Filename, unsigned LineNo, const char* Msg, va_list ap)
/* Print an error message - internal function*/
{
fprintf (stderr, "%s(%u): Error: ", Filename, LineNo);
vfprintf (stderr, Msg, ap);
fprintf (stderr, "\n");
if (Line) {
Print (stderr, 1, "Input: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line));
}
++ErrorCount;
if (ErrorCount > 10) {
Fatal ("Too many errors");
}
}
void Error (const char* Format, ...)
/* Print an error message */
{
va_list ap;
va_start (ap, Format);
IntError (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap);
va_end (ap);
}
void LIError (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);
va_end (ap);
}
void PPError (const char* Format, ...)
/* Print an error message. For use within the preprocessor. */
{
va_list ap;
va_start (ap, Format);
IntError (GetCurrentFile(), GetCurrentLine(), Format, ap);
va_end (ap);
}
void Fatal (const char* Format, ...)
/* Print a message about a fatal error and die */
{
@ -232,6 +154,150 @@ void Internal (const char* Format, ...)
/*****************************************************************************/
/* Handling of errors */
/*****************************************************************************/
static void IntError (const char* Filename, unsigned LineNo, const char* Msg, va_list ap)
/* Print an error message - internal function*/
{
fprintf (stderr, "%s(%u): Error: ", Filename, LineNo);
vfprintf (stderr, Msg, ap);
fprintf (stderr, "\n");
if (Line) {
Print (stderr, 1, "Input: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line));
}
++ErrorCount;
if (ErrorCount > 10) {
Fatal ("Too many errors");
}
}
void Error (const char* Format, ...)
/* Print an error message */
{
va_list ap;
va_start (ap, Format);
IntError (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap);
va_end (ap);
}
void LIError (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);
va_end (ap);
}
void PPError (const char* Format, ...)
/* Print an error message. For use within the preprocessor. */
{
va_list ap;
va_start (ap, Format);
IntError (GetCurrentFile(), GetCurrentLine(), Format, ap);
va_end (ap);
}
/*****************************************************************************/
/* Handling of warnings */
/*****************************************************************************/
static void IntWarning (const char* Filename, unsigned LineNo, const char* Msg, va_list ap)
/* Print warning message - internal function. */
{
if (IS_Get (&WarningsAreErrors)) {
/* Treat the warning as an error */
IntError (Filename, LineNo, Msg, ap);
} else if (IS_Get (&WarnEnable)) {
fprintf (stderr, "%s(%u): Warning: ", Filename, LineNo);
vfprintf (stderr, Msg, ap);
fprintf (stderr, "\n");
if (Line) {
Print (stderr, 1, "Input: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line));
}
++WarningCount;
}
}
void Warning (const char* Format, ...)
/* Print warning message. */
{
va_list ap;
va_start (ap, Format);
IntWarning (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap);
va_end (ap);
}
void LIWarning (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);
va_end (ap);
}
void PPWarning (const char* Format, ...)
/* Print warning message. For use within the preprocessor. */
{
va_list ap;
va_start (ap, Format);
IntWarning (GetCurrentFile(), GetCurrentLine(), Format, ap);
va_end (ap);
}
IntStack* FindWarning (const char* Name)
/* Search for a warning in the WarnMap table and return a pointer to the
* intstack that holds its state. Return NULL if there is no such warning.
*/
{
unsigned I;
/* For now, do a linear search */
for (I = 0; I < sizeof(WarnMap) / sizeof (WarnMap[0]); ++I) {
if (strcmp (WarnMap[I].Name, Name) == 0) {
return WarnMap[I].Stack;
}
}
return 0;
}
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void ErrorReport (void)
/* Report errors (called at end of compile) */
{

View File

@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 1998-2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* (C) 1998-2009, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -40,6 +40,7 @@
/* common */
#include "attrib.h"
#include "intstack.h"
/* cc65 */
#include "lineinfo.h"
@ -56,6 +57,14 @@
extern unsigned ErrorCount;
extern unsigned WarningCount;
/* Warning and error options */
extern IntStack WarnEnable; /* Enable warnings */
extern IntStack WarningsAreErrors; /* Treat warnings as errors */
extern IntStack WarnUnusedLabel; /* Warn about unused labels */
extern IntStack WarnUnusedParam; /* Warn about unused parameters */
extern IntStack WarnUnusedVar; /* Warn about unused variables */
extern IntStack WarnUnknownPragma; /* Warn about unknown #pragmas */
/*****************************************************************************/
@ -64,14 +73,11 @@ extern unsigned WarningCount;
void Warning (const char* Format, ...) attribute ((format (printf, 1, 2)));
/* Print warning message. */
void Fatal (const char* Format, ...) attribute ((noreturn, format (printf, 1, 2)));
/* Print a message about a fatal error and die */
void LIWarning (const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 2, 3)));
/* Print a warning message with the line info given explicitly */
void PPWarning (const char* Format, ...) attribute ((format (printf, 1, 2)));
/* Print warning message. For use within the preprocessor. */
void Internal (const char* Format, ...) attribute ((noreturn, format (printf, 1, 2)));
/* Print a message about an internal compiler error and die. */
void Error (const char* Format, ...) attribute ((format (printf, 1, 2)));
/* Print an error message */
@ -82,11 +88,19 @@ void LIError (const LineInfo* LI, const char* Format, ...) attribute ((format (p
void PPError (const char* Format, ...) attribute ((format (printf, 1, 2)));
/* Print an error message. For use within the preprocessor. */
void Fatal (const char* Format, ...) attribute ((noreturn, format (printf, 1, 2)));
/* Print a message about a fatal error and die */
void Warning (const char* Format, ...) attribute ((format (printf, 1, 2)));
/* Print warning message. */
void Internal (const char* Format, ...) attribute ((noreturn, format (printf, 1, 2)));
/* Print a message about an internal compiler error and die. */
void LIWarning (const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 2, 3)));
/* Print a warning message with the line info given explicitly */
void PPWarning (const char* Format, ...) attribute ((format (printf, 1, 2)));
/* Print warning message. For use within the preprocessor. */
IntStack* FindWarning (const char* Name);
/* Search for a warning in the WarnMap table and return a pointer to the
* intstack that holds its state. Return NULL if there is no such warning.
*/
void ErrorReport (void);
/* Report errors (called at end of compile) */

View File

@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 1998-2004 Ullrich von Bassewitz */
/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 1998-2009, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -50,7 +50,6 @@ unsigned char PreprocessOnly = 0; /* Just preprocess the input */
unsigned RegisterSpace = 6; /* Space available for register vars */
/* Stackable options */
IntStack WarnDisable = INTSTACK(0); /* Suppress warnings */
IntStack WritableStrings = INTSTACK(0); /* Literal strings are r/w */
IntStack InlineStdFuncs = INTSTACK(0); /* Inline some known functions */
IntStack EnableRegVars = INTSTACK(0); /* Enable register variables */

View File

@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 1998-2004 Ullrich von Bassewitz */
/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 1998-2009, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -57,7 +57,6 @@ extern unsigned char PreprocessOnly; /* Just preprocess the input */
extern unsigned RegisterSpace; /* Space available for register vars */
/* Stackable options */
extern IntStack WarnDisable; /* Suppress warnings */
extern IntStack WritableStrings; /* Literal strings are r/w */
extern IntStack InlineStdFuncs; /* Inline some known functions */
extern IntStack EnableRegVars; /* Enable register variables */

View File

@ -48,6 +48,7 @@
#include "mmodel.h"
#include "print.h"
#include "segnames.h"
#include "strbuf.h"
#include "target.h"
#include "tgttrans.h"
#include "version.h"
@ -373,7 +374,7 @@ static void OptCodeSize (const char* Opt, const char* Arg)
/* Numeric argument expected */
if (sscanf (Arg, "%u%c", &Factor, &BoundsCheck) != 1 ||
Factor < 10 || Factor > 1000) {
InvArg (Opt, Arg);
AbEnd ("Argument for %s is invalid", Opt);
}
IS_Set (&CodeSizeFactor, Factor);
}
@ -396,7 +397,7 @@ static void OptCPU (const char* Opt, const char* Arg)
CPU = FindCPU (Arg);
if (CPU != CPU_6502 && CPU != CPU_6502X && CPU != CPU_65SC02 &&
CPU != CPU_65C02 && CPU != CPU_65816 && CPU != CPU_HUC6280) {
InvArg (Opt, Arg);
AbEnd ("Invalid argument for %s: `%s'", Opt, Arg);
}
}
@ -584,7 +585,7 @@ static void OptRegisterSpace (const char* Opt, const char* Arg)
{
/* Numeric argument expected */
if (sscanf (Arg, "%u", &RegisterSpace) != 1 || RegisterSpace > 256) {
InvArg (Opt, Arg);
AbEnd ("Argument for option %s is invalid", Opt);
}
}
@ -626,7 +627,7 @@ static void OptStandard (const char* Opt, const char* Arg)
/* Find the standard from the given name */
standard_t Std = FindStandard (Arg);
if (Std == STD_UNKNOWN) {
InvArg (Opt, Arg);
AbEnd ("Invalid argument for %s: `%s'", Opt, Arg);
} else if (IS_Get (&Standard) != STD_UNKNOWN) {
AbEnd ("Option %s given more than once", Opt);
} else {
@ -674,6 +675,52 @@ static void OptVersion (const char* Opt attribute ((unused)),
static void OptWarning (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the -W option */
{
StrBuf W = AUTO_STRBUF_INITIALIZER;
/* Arg is a list of suboptions, separated by commas */
while (Arg) {
const char* Pos;
int Enabled = 1;
IntStack* S;
/* The suboption may be prefixed with '-' or '+' */
if (*Arg == '-') {
Enabled = 0;
++Arg;
} else if (*Arg == '+') {
/* This is the default */
++Arg;
}
/* Get the next suboption */
Pos = strchr (Arg, ',');
if (Pos) {
SB_CopyBuf (&W, Arg, Pos - Arg);
Arg = Pos + 1;
} else {
SB_CopyStr (&W, Arg);
Arg = 0;
}
SB_Terminate (&W);
/* Search for the warning */
S = FindWarning (SB_GetConstBuf (&W));
if (S == 0) {
InvArg (Opt, SB_GetConstBuf (&W));
}
IS_Set (S, Enabled);
}
/* Free allocated memory */
SB_Done (&W);
}
static void OptWritableStrings (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Make string literals writable */
@ -741,9 +788,9 @@ int main (int argc, char* argv[])
const char* Arg = ArgVec[I];
/* Check for an option */
if (Arg [0] == '-') {
if (Arg[0] == '-') {
switch (Arg [1]) {
switch (Arg[1]) {
case '-':
LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
@ -796,7 +843,7 @@ int main (int argc, char* argv[])
default:
UnknownOption (Arg);
break;
}
}
}
break;
@ -839,7 +886,7 @@ int main (int argc, char* argv[])
break;
case 'W':
IS_Set (&WarnDisable, 1);
OptWarning (Arg, GetArg (&I, 2));
break;
default:

View File

@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 1998-2008 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 1998-2009, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -501,7 +501,7 @@ static void ParsePragma (void)
break;
case PR_WARN:
FlagPragma (&B, &WarnDisable);
FlagPragma (&B, &WarnEnable);
break;
case PR_ZPSYM:

View File

@ -164,9 +164,13 @@ static void CheckSymTable (SymTable* Tab)
if (((Flags & SC_AUTO) || (Flags & SC_STATIC)) && (Flags & SC_EXTERN) == 0) {
if (SymIsDef (Entry) && !SymIsRef (Entry)) {
if (Flags & SC_PARAM) {
Warning ("Parameter `%s' is never used", Entry->Name);
if (IS_Get (&WarnUnusedParam)) {
Warning ("Parameter `%s' is never used", Entry->Name);
}
} else {
Warning ("`%s' is defined but never used", Entry->Name);
if (IS_Get (&WarnUnusedVar)) {
Warning ("`%s' is defined but never used", Entry->Name);
}
}
}
}
@ -177,8 +181,10 @@ static void CheckSymTable (SymTable* Tab)
/* Undefined label */
Error ("Undefined label: `%s'", Entry->Name);
} else if (!SymIsRef (Entry)) {
/* Defined but not used */
Warning ("`%s' is defined but never used", Entry->Name);
/* Defined but not used */
if (IS_Get (&WarnUnusedLabel)) {
Warning ("`%s' is defined but never used", Entry->Name);
}
}
}