warnings: define warning classes at point of use

It is extremely desirable to allow the user fine-grained control of
warnings, but this has been complicated by the fact that a warning
class has had to be defined in no less than three places (error.h,
error.c, nasmdoc.src) before it can be used in source code. Instead,
use a script to define these via magic comments at the point of use.

This hopefully will encourage creating new classes as needed.

Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin (Intel) 2018-12-13 21:53:31 -08:00
parent 6bde2ed880
commit 723ab481a6
18 changed files with 238 additions and 219 deletions

3
.gitignore vendored
View File

@ -48,6 +48,7 @@ TAGS
/asm/pptok.ph
/asm/tokens.h
/asm/tokhash.c
/asm/warnings.c
/config/config.h
/config/config.h.in
/config.log
@ -66,6 +67,8 @@ TAGS
/doc/info
/doc/inslist.src
/doc/version.src
/doc/warnings.src
/include/warnings.h
/macros/macros.c
/misc/omfdump
/nasm

View File

@ -114,7 +114,7 @@ LIBOBJ = stdlib/snprintf.$(O) stdlib/vsnprintf.$(O) stdlib/strlcpy.$(O) \
x86/regs.$(O) x86/regvals.$(O) x86/regflags.$(O) x86/regdis.$(O) \
x86/disp8.$(O) x86/iflag.$(O) \
\
asm/error.$(O) \
asm/error.$(O) asm/warnings.$(O) \
asm/float.$(O) \
asm/directiv.$(O) asm/directbl.$(O) \
asm/pragma.$(O) \
@ -240,6 +240,23 @@ x86/regs.h: x86/regs.dat x86/regs.pl
$(RUNPERL) $(srcdir)/x86/regs.pl h \
$(srcdir)/x86/regs.dat > x86/regs.h
# Extract warnings from source code. Since this depends on
# ALL the source files, this is only done on demand.
WARNFILES = asm/warnings.c include/warnings.h doc/warnings.src
warnings:
rm -f $(WARNFILES)
$(MAKE) $(WARNFILES)
asm/warnings.c: asm/warnings.pl
$(RUNPERL) $(srcdir)/asm/warnings.pl c asm/warnings.c $(srcdir)
include/warnings.h: asm/warnings.pl
$(RUNPERL) $(srcdir)/asm/warnings.pl h include/warnings.h $(srcdir)
doc/warnings.src: asm/warnings.pl
$(RUNPERL) $(srcdir)/asm/warnings.pl doc doc/warnings.src $(srcdir)
# Assembler token hash
asm/tokhash.c: x86/insns.dat x86/regs.dat asm/tokens.dat asm/tokhash.pl \
perllib/phash.ph

View File

@ -405,7 +405,12 @@ static void out(struct out_data *data)
nasm_nonfatal("%u-bit signed relocation unsupported by output format %s",
(unsigned int)(asize << 3), ofmt->shortname);
} else {
nasm_warnf(WARN_ZEXTRELOC,
/*!
*!zext-reloc [on] relocation zero-extended to match output format
*! warns that a relocation has been zero-extended due
*! to limitations in the output format.
*/
nasm_warnf(WARN_ZEXT_RELOC,
"%u-bit %s relocation zero-extended from %u bits",
(unsigned int)(asize << 3),
data->type == OUT_SEGMENT ? "segment" : "unsigned",
@ -555,6 +560,15 @@ static bool jmp_match(int32_t segment, int64_t offset, int bits,
if (is_byte && c == 0371 && ins->prefixes[PPS_REP] == P_BND) {
/* jmp short (opcode eb) cannot be used with bnd prefix. */
ins->prefixes[PPS_REP] = P_none;
/*!
*!bnd [on] invalid BND prefixes
*! warns about ineffective use of the \c{BND} prefix when the
*! \c{JMP} instruction is converted to the \c{SHORT} form.
*! This should be extremely rare since the short \c{JMP} only
*! is applicable to jumps inside the same module, but if
*! it is legitimate, it may be necessary to use
*! \c{BND JMP DWORD}...
*/
nasm_warnf(WARN_BND | ERR_PASS2 ,
"jmp short does not init bnd regs - bnd prefix dropped.");
}
@ -904,6 +918,11 @@ static void bad_hle_warn(const insn * ins, uint8_t hleok)
if (!is_class(MEMORY, ins->oprs[0].type))
ww = w_inval; /* HLE requires operand 0 to be memory */
/*!
*!hle [on] invalid HLE prefixes
*! warns about invalid use of the HLE \c{XACQUIRE} or \c{XRELEASE}
*! prefixes.
*/
switch (ww) {
case w_none:
break;
@ -1398,6 +1417,10 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
if (has_prefix(ins, PPS_LOCK, P_LOCK) && lockcheck &&
(!itemp_has(temp,IF_LOCK) || !is_class(MEMORY, ins->oprs[0].type))) {
/*!
*!lock [on] lock prefix on unlockable instructions
*! warns about \c{LOCK} prefixes on unlockable instructions.
*/
nasm_warnf(WARN_LOCK | ERR_PASS2 , "instruction is not lockable");
}

View File

@ -435,9 +435,7 @@ bool process_directives(char *directive)
}
case D_WARNING: /* [WARNING {+|-|*}warn-name] */
if (!set_warning_status(value)) {
nasm_warnf(WARN_UNK_WARNING, "unknown warning option: %s", value);
}
set_warning_status(value);
break;
case D_CPU: /* [CPU] */

View File

@ -42,49 +42,6 @@
#include "nasmlib.h"
#include "error.h"
/*
* Description of the suppressible warnings for the command line and
* the [warning] directive.
*/
#define on (WARN_ST_ENABLED)
#define off 0
#define err (WARN_ST_ENABLED|WARN_ST_ERROR)
const struct warning warnings[WARN_ALL+1] = {
{NULL, NULL, on}, /* must be on - used for unconditional enable */
{"macro-params", "macro calls with wrong parameter count", on},
{"macro-selfref", "cyclic macro references", off},
{"macro-defaults", "macros with more default than optional parameters", on},
{"orphan-labels", "labels alone on lines without trailing `:'", on},
{"number-overflow", "numeric constant does not fit", on},
{"gnu-elf-extensions", "using 8- or 16-bit relocation in ELF32, a GNU extension", off},
{"float-overflow", "floating point overflow", on},
{"float-denorm", "floating point denormal", off},
{"float-underflow", "floating point underflow", off},
{"float-toolong", "too many digits in floating-point number", on},
{"user", "%warning directives", on},
{"lock", "lock prefix on unlockable instructions", on},
{"hle", "invalid hle prefixes", on},
{"bnd", "invalid bnd prefixes", on},
{"zext-reloc", "relocation zero-extended to match output format", on},
{"ptr", "non-NASM keyword used in other assemblers", on},
{"bad-pragma", "empty or malformed %pragma", off},
{"unknown-pragma", "unknown %pragma facility or directive", off},
{"not-my-pragma", "%pragma not applicable to this compilation", off},
{"unknown-warning", "unknown warning in -W/-w or warning directive", off},
{"negative-rep", "regative %rep count", on},
{"phase", "phase error during stabilization", off},
{"label-redef", "label redefined to an identical value", off},
{"label-redef-late", "label (re)defined during code generation", err},
/* THESE ENTRIES SHOULD COME LAST */
{"other", "any warning not specifially mentioned above", on},
{"all", "all possible warnings", off}
};
uint8_t warning_state[WARN_ALL];/* Current state */
uint8_t warning_state_init[WARN_ALL]; /* Command-line state, for reset */
/* Global error handling function */
vefunc nasm_verror;
@ -134,11 +91,22 @@ fatal_func nasm_assert_failed(const char *file, int line, const char *msg)
/*
* This is called when processing a -w or -W option, or a warning directive.
* Returns on if if the action was successful.
*
* Special pseudo-warnings:
*
*!other [on] any warning not specifially mentioned above
*! specifies any warning not included in any specific warning class.
*
*!all [all] all possible warnings
*! is an alias for \e{all} suppressible warning classes.
*! Thus, \c{-w+all} enables all available warnings, and \c{-w-all}
*! disables warnings entirely (since NASM 2.13).
*/
bool set_warning_status(const char *value)
{
enum warn_action { WID_OFF, WID_ON, WID_RESET };
enum warn_action action;
const char *name;
bool ok = false;
uint8_t mask;
int i;
@ -192,12 +160,13 @@ bool set_warning_status(const char *value)
}
}
name = value ? value : "<none>";
if (value && !nasm_stricmp(value, "all"))
value = NULL;
/* This is inefficient, but it shouldn't matter... */
for (i = 0; i < WARN_ALL; i++) {
if (!value || !nasm_stricmp(value, warnings[i].name)) {
for (i = 1; i < WARN_IDX_ALL; i++) {
if (!value || !nasm_stricmp(value, warning_name[i])) {
ok = true; /* At least one action taken */
switch (action) {
case WID_OFF:
@ -214,5 +183,14 @@ bool set_warning_status(const char *value)
}
}
if (!ok) {
/*!
*!unknown-warning [off] unknown warning in -W/-w or warning directive
*! warns about a \c{-w} or \c{-W} option or a \c{[WARNING]} directive
*! that contains an unknown warning name or is otherwise not possible to process.
*/
nasm_warnf(WARN_UNKNOWN_WARNING, "unknown warning name: %s", name);
}
return ok;
}

View File

@ -232,6 +232,10 @@ static bool ieee_flconvert(const char *string, fp_limb *mant,
*p++ = *string - '0';
} else {
if (!warned) {
/*!
*!float-toolong [on] too many digits in floating-point number
*! warns about too many digits in floating-point numbers.
*/
nasm_warnf(WARN_FLOAT_TOOLONG|ERR_PASS2,
"floating-point constant significand contains "
"more than %i digits", MANT_DIGITS);
@ -798,9 +802,8 @@ static int to_float(const char *str, int s, uint8_t *result,
if (exponent >= 2 - expmax && exponent <= expmax) {
type = FL_NORMAL;
} else if (exponent > 0) {
if (pass0 == 1)
nasm_warnf(WARN_FLOAT_OVERFLOW|ERR_PASS2,
"overflow in floating-point constant");
nasm_warnf(WARN_FLOAT_OVERFLOW|ERR_PASS2,
"overflow in floating-point constant");
type = FL_INFINITY;
} else {
/* underflow or denormal; the denormal code handles
@ -833,13 +836,22 @@ static int to_float(const char *str, int s, uint8_t *result,
mant[0] |= exponent << (LIMB_BITS-1 - fmt->exponent);
} else {
if (daz || is_zero(mant)) {
/* Flush denormals to zero */
/*!
*!float-underflow [off] floating point underflow
*! warns about floating point underflow (a nonzero
*! constant rounded to zero.)
*/
nasm_warnf(WARN_FLOAT_UNDERFLOW|ERR_PASS2,
"underflow in floating-point constant");
goto zero;
} else
} else {
/*!
*!float-denorm [off] floating point denormal
*! warns about denormal floating point constants.
*/
nasm_warnf(WARN_FLOAT_DENORM|ERR_PASS2,
"denormal floating-point constant");
}
}
break;
}
@ -853,8 +865,12 @@ static int to_float(const char *str, int s, uint8_t *result,
ieee_shr(mant, 1);
exponent++;
if (exponent >= (expmax << 1)-1) {
nasm_warnf(WARN_FLOAT_OVERFLOW|ERR_PASS2,
"overflow in floating-point constant");
/*!
*!float-overflow [on] floating point overflow
*! warns about floating point underflow.
*/
nasm_warnf(WARN_FLOAT_OVERFLOW|ERR_PASS2,
"overflow in floating-point constant");
type = FL_INFINITY;
goto overflow;
}

View File

@ -505,6 +505,12 @@ void define_label(const char *label, int32_t segment,
nasm_nonfatal("label `%s' inconsistently redefined", lptr->defn.label);
noteflags = ERR_NOTE|ERR_HERE;
} else {
/*!
*!label-redef [off] label redefined to an identical value
*! warns if a label is defined more than once, but the
*! value is identical. It is an unconditional error to
*! define the same label more than once to \e{different} values.
*/
nasm_warnf(WARN_LABEL_REDEF|ERR_PASS2,
"label `%s' redefined to an identical value", lptr->defn.label);
noteflags = ERR_NOTE|ERR_HERE|WARN_LABEL_REDEF|ERR_PASS2;
@ -516,13 +522,16 @@ void define_label(const char *label, int32_t segment,
lptr->defn.label);
src_set(saved_line, saved_fname);
} else if (changed && pass0 > 1 && lptr->defn.type != LBL_SPECIAL) {
/*
* WARN_LABEL_REDEF_LATE defaults to an error, as this should never actually happen.
* Just in case this is a backwards compatibility problem, still make it a
* warning so that the user can suppress or demote it.
/*!
*!label-redef-late [err] label (re)defined during code generation
*! the value of a label changed during the final, code-generation
*! pass. This may be the result of strange use of the
*! preprocessor. This is very likely to produce incorrect code and
*! may end up being an unconditional error in a future
*! version of NASM.
*
* As a special case, LBL_SPECIAL symbols are allowed to be changed
* even during the last pass.
* Note: As a special case, LBL_SPECIAL symbols are allowed
* to be changed even during the last pass.
*/
nasm_warnf(WARN_LABEL_REDEF_LATE,
"label `%s' %s during code generation",

View File

@ -510,7 +510,7 @@ int main(int argc, char **argv)
}
/* Save away the default state of warnings */
memcpy(warning_state_init, warning_state, sizeof warning_state);
memcpy(warning_state_init, warning_state, sizeof warning_state_init);
/* Dependency filename if we are also doing other things */
if (!depend_file && (operating_mode & ~OP_DEPEND)) {
@ -1040,11 +1040,8 @@ static bool process_arg(char *p, char *q, int pass)
case 'w':
case 'W':
if (pass == 2) {
if (!set_warning_status(param)) {
nasm_warnf(WARN_UNK_WARNING, "unknown warning option: %s", param);
}
}
if (pass == 2)
set_warning_status(param);
break;
case 'M':
@ -1323,14 +1320,13 @@ static void parse_cmdline(int argc, char **argv, int pass)
{
FILE *rfile;
char *envreal, *envcopy = NULL, *p;
int i;
/*
* Initialize all the warnings to their default state, including
* warning index 0 used for "always on".
*/
for (i = 0; i < WARN_ALL; i++)
warning_state_init[i] = warning_state[i] = warnings[i].state;
memcpy(warning_state, warning_default, sizeof warning_state);
memcpy(warning_state_init, warning_default, sizeof warning_state_init);
/*
* First, process the NASMENV environment variable.
@ -1640,7 +1636,14 @@ static void assemble_file(const char *fname, struct strlist *depend_list)
if (global_offset_changed && !terminate_after_phase) {
switch (pass0) {
case 1:
nasm_warnf(WARN_PHASE, "phase error during stabilization pass, hoping for the best");
/*!
*!phase [off] phase error during stabilization
*! warns about symbols having changed values during
*! the second-to-last assembly pass. This is not
*! inherently fatal, but may be a source of bugs.
*/
nasm_warnf(WARN_PHASE, "phase error during stabilization "
"pass, hoping for the best");
break;
case 2:
@ -1712,7 +1715,7 @@ static size_t warn_index(errflags severity)
severity |= WARN_OTHER;
index = WARN_IDX(severity);
nasm_assert(index < WARN_ALL);
nasm_assert(index < WARN_IDX_ALL);
return index;
}
@ -1830,8 +1833,8 @@ static void nasm_verror_asm(errflags severity, const char *fmt, va_list args)
*warnsuf = 0;
if (spec_type == ERR_WARNING) {
snprintf(warnsuf, sizeof warnsuf, " [-w+%s%s]",
true_type ? "error=" : "",
warnings[warn_index(severity)].name);
(true_type >= ERR_NONFATAL) ? "error=" : "",
warning_name[warn_index(severity)]);
}
*linestr = 0;
@ -1989,14 +1992,15 @@ static void help(const char xopt)
}
}
printf("\nWarnings for the -W/-w options: (default in brackets)\n");
printf("\nWarnings for the -W/-w options: (defaults in brackets)\n");
for (i = 1; i <= WARN_ALL; i++)
for (i = 1; i <= WARN_IDX_ALL; i++) {
printf(" %-23s %s%s\n",
warnings[i].name, warnings[i].help,
i == WARN_ALL ? "\n" :
(warnings[i].state & WARN_ST_ERROR) ? " [error]" :
(warnings[i].state & WARN_ST_ENABLED) ? " [on]" : " [off]");
warning_name[i], warning_help[i],
i == WARN_IDX_ALL ? "\n" :
(warning_default[i] & WARN_ST_ERROR) ? " [error]" :
(warning_default[i] & WARN_ST_ENABLED) ? " [on]" : " [off]");
}
if (xopt == 'f') {
printf("valid output formats for -f are"

View File

@ -463,6 +463,12 @@ restart_parse:
if (i == ':') { /* skip over the optional colon */
i = stdscan(NULL, &tokval);
} else if (i == 0) {
/*!
*!orphan-labels [on] labels alone on lines without trailing `:'
*! warns about source lines which contain no instruction but define
*! a label without a trailing colon. This is most likely indicative
*! of a typo, but is technically correct NASM syntax (see \k{syntax}.)
*/
nasm_warnf(WARN_ORPHAN_LABELS | ERR_PASS1,
"label alone on a line without a colon might be in error");
}

View File

@ -146,10 +146,20 @@ found_it:
case DIRR_UNKNOWN:
switch (pragma->opcode) {
case D_none:
/*!
*!bad-pragma [off] empty or malformed %pragma
*! warns about a malformed or otherwise unparsable
*! \c{%pragma} directive.
*/
nasm_error(ERR_WARNING|ERR_PASS2|WARN_BAD_PRAGMA,
"empty %%pragma %s", pragma->facility_name);
break;
default:
/*!
*!unknown-pragma [off] unknown %pragma facility or directive
*! warns about an unknown \c{%pragma} directive.
*! This is not yet implemented for most cases.
*/
nasm_error(ERR_WARNING|ERR_PASS2|WARN_UNKNOWN_PRAGMA,
"unknown %%pragma %s %s",
pragma->facility_name, pragma->opname);
@ -176,6 +186,13 @@ found_it:
return true;
}
/* This warning message is intended for future use */
/*!
*!not-my-pragma [off] %pragma not applicable to this compilation
*! warns about a \c{%pragma} directive which is not applicable to
*! this particular assembly session. This is not yet implemented.
*/
void process_pragma(char *str)
{
struct pragma pragma;

View File

@ -2132,8 +2132,15 @@ static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
def->expansion = NULL;
if (def->defaults && def->ndefs > def->nparam_max - def->nparam_min &&
!def->plus)
nasm_warnf(ERR_PASS1|WARN_MACRO_DEFAULTS, "too many default macro parameters in macro `%s'", def->name);
!def->plus) {
/*
*!macro-defaults [on] macros with more default than optional parameters
*! warns when a macro has more default parameters than optional parameters.
*! See \k{mlmacdef} for why might want to disable this warning.
*/
nasm_warnf(ERR_PASS1|WARN_MACRO_DEFAULTS,
"too many default macro parameters in macro `%s'", def->name);
}
return true;
}
@ -2655,6 +2662,10 @@ static int do_directive(Token *tline, char **output)
severity = ERR_NONFATAL;
goto issue_error;
case PP_WARNING:
/*!
*!user [on] %warning directives
*! controls output of \c{%warning} directives (see \k{pperror}).
*/
severity = ERR_WARNING|WARN_USER;
goto issue_error;
@ -2966,6 +2977,11 @@ issue_error:
count, nasm_limit[LIMIT_REP]);
count = 0;
} else if (count < 0) {
/*!
*!negative-rep [on] regative %rep count
*! warns about negative counts given to the \c{%rep}
*! preprocessor directive.
*/
nasm_warnf(ERR_PASS2|WARN_NEGATIVE_REP,
"negative `%%rep' count: %"PRId64, count);
count = 0;
@ -4284,11 +4300,18 @@ again:
mstrcmp(m->name, mname,
m->casesense)))
m = m->next;
if (!m)
if (!m) {
/*!
*!macro-params [on] macro calls with wrong parameter count
*! covers warnings about \i{multi-line macros} being invoked
*! with the wrong number of parameters. See \k{mlmacover} for an
*! example of why you might want to disable this warning.
*/
nasm_warnf(ERR_PASS1|WARN_MACRO_PARAMS,
"macro `%s' exists, "
"but not taking %d parameters",
mstart->text, nparam);
}
}
}
if (m && m->in_progress)

View File

@ -167,6 +167,12 @@ int stdscan(void *private_data, struct tokenval *tv)
token_type = nasm_token_hash(ourcopy, tv);
if (unlikely(tv->t_flag & TFLAG_WARN)) {
/*!
*!ptr [on] non-NASM keyword used in other assemblers
*! warns about keywords used in other assemblers that might
*! indicate a mistake in the source code. Currently only the MASM
*! \c{PTR} keyword is recognized.
*/
nasm_warnf(ERR_PASS1|WARN_PTR, "`%s' is not a NASM keyword",
tv->t_charptr);
}

View File

@ -18,7 +18,7 @@ sub quote_for_c($) {
sub find_warnings {
my $infile = $_;
return unless ($infile =~ /\.[ch]$/i);
return unless (basename($infile) =~ /^\w.*\.[ch]$/i);
open(my $in, '<', $infile)
or die "$0: cannot open input file $infile: $!\n";
@ -50,8 +50,10 @@ sub find_warnings {
my $ws = $1;
my $str = $2;
next if ($str eq '');
if (!defined($this) || ($ws eq '' && $str ne '')) {
if ($str =~ /^(\w+)\s+(\w+)\s(.+)$/) {
if ($str =~ /^([\w-]+)\s+\[(\w+)\]\s(.+)$/) {
my $name = $1;
my $def = $2;
my $help = $3;
@ -106,7 +108,7 @@ open(my $out, '>', $outfile)
if ($what eq 'c') {
print $out "#include \"error.h\"\n\n";
printf $out "const char * const warning_names[%d] = {\n",
printf $out "const char * const warning_name[%d] = {\n",
$#warnings + 2;
print $out "\tNULL";
foreach my $warn (@warnings) {
@ -121,44 +123,58 @@ if ($what eq 'c') {
print $out ",\n\t\"", $help, "\"";
}
print $out "\n};\n\n";
printf $out "const uint8_t warning_defaults[%d] = {\n",
printf $out "const uint8_t warning_default[%d] = {\n",
$#warn_noall + 2;
print $out "\tWARN_INIT_ON"; # for entry 0
foreach my $warn (@warn_noall) {
print $out ",\n\tWARN_INIT_", uc($warn->{def});
}
print $out "\n};\n";
print $out "\n};\n\n";
printf $out "uint8_t warning_state[%d];\t/* Current state */\n",
$#warn_noall + 2;
printf $out "uint8_t warning_state_init[%d];\t/* Command-line state, for reset */\n",
$#warn_noall + 2;
} elsif ($what eq 'h') {
my $guard = basename($outfile);
my $filename = basename($outfile);
my $guard = $filename;
$guard =~ s/[^A-Za-z0-9_]+/_/g;
$guard = "NASM_\U$guard";
print $out "#ifndef $guard\n";
print $out "#define $guard\n";
print $out "\n";
print $out "#include \"compiler.h\"\n\n";
print $out "#ifndef WARN_SHR\n";
print $out "# error \"$filename should only be included from within error.h\"\n";
print $out "#endif\n\n";
print $out "enum warn_index {\n";
printf $out "\tWARN_IDX_%-15s = %2d", 'NONE', 0;
printf $out "\tWARN_IDX_%-23s = %3d, /* not suppressible */\n", 'NONE', 0;
my $n = 1;
foreach my $warn (@warnings) {
printf $out ",\n\tWARN_IDX_%-15s = %2d%s /* %s */",
$warn->{cname}, $n++, $warn->{help};
printf $out "\tWARN_IDX_%-23s = %3d%s /* %s */\n",
$warn->{cname}, $n,
($n == $#warnings + 1) ? " " : ",",
$warn->{help};
$n++;
}
print $out "\n};\n\n";
print $out "};\n\n";
print $out "enum warn_const {\n";
printf $out "\tWARN_%-19s = %2d << WARN_SHR", 'NONE', 0;
printf $out "\tWARN_%-27s = %3d << WARN_SHR", 'NONE', 0;
my $n = 1;
foreach my $warn (@warn_noall) {
printf $out ",\n\tWARN_%-19s = %2d << WARN_SHR", $warn->{cname}, $n++;
printf $out ",\n\tWARN_%-27s = %3d << WARN_SHR", $warn->{cname}, $n++;
}
print $out "\n};\n\n";
printf $out "extern const char * const warning_names[%d];\n",
printf $out "extern const char * const warning_name[%d];\n",
$#warnings + 2;
printf $out "extern const char * const warning_help[%d];\n",
$#warnings + 2;
printf $out "extern const uint8_t warning_defaults[%d];\n",
printf $out "extern const uint8_t warning_default[%d];\n",
$#warn_noall + 2;
printf $out "extern uint8_t warning_state[%d];\n",
$#warn_noall + 2;
printf $out "extern uint8_t warning_state_init[%d];\n",
$#warn_noall + 2;
print $out "\n#endif /* $guard */\n";
} elsif ($what eq 'doc') {

View File

@ -31,7 +31,7 @@ CP_UF = cp -ufv
# Auxiliary files referenced by the HTML files
HTMLAUX = nasmdoc.css local.css nasmlogw.png
SRCS = nasmdoc.src inslist.src changes.src version.src
SRCS = nasmdoc.src inslist.src changes.src warnings.src version.src
OUT = html nasmdoc.txt nasmdoc.pdf
.SUFFIXES:

View File

@ -809,82 +809,7 @@ disable it by \c{-w-orphan-labels}.
The current \i{warning classes} are:
\b \i\c{other} specifies any warning not otherwise specified in any
class. Enabled by default.
\b \i\c{macro-params} covers warnings about \i{multi-line macros}
being invoked with the wrong number of parameters. Enabled by default;
see \k{mlmacover} for an example of why you might want to disable it.
\b \i\c{macro-selfref} warns if a macro references itself. Disabled by
default.
\b \i\c{macro-defaults} warns when a macro has more default parameters
than optional parameters. Enabled by default; see \k{mlmacdef} for why
you might want to disable it.
\b \i\c{orphan-labels} covers warnings about source lines which
contain no instruction but define a label without a trailing colon.
NASM warns about this somewhat obscure condition by default;
see \k{syntax} for more information.
\b \i\c{number-overflow} covers warnings about numeric constants which
don't fit in 64 bits. Enabled by default.
\b \i\c{gnu-elf-extensions} warns if 8-bit or 16-bit relocations
are used in \c{-f elf} format. The GNU extensions allow this.
Disabled by default.
\b \i\c{float-overflow} warns about floating point overflow.
Enabled by default.
\b \i\c{float-denorm} warns about floating point denormals.
Disabled by default.
\b \i\c{float-underflow} warns about floating point underflow.
Disabled by default.
\b \i\c{float-toolong} warns about too many digits in floating-point numbers.
Enabled by default.
\b \i\c{user} controls \c{%warning} directives (see \k{pperror}).
Enabled by default.
\b \i\c{lock} warns about \c{LOCK} prefixes on unlockable instructions.
Enabled by default.
\b \i\c{hle} warns about invalid use of the HLE \c{XACQUIRE} or \c{XRELEASE}
prefixes.
Enabled by default.
\b \i\c{bnd} warns about ineffective use of the \c{BND} prefix when a relaxed
form of jmp instruction becomes jmp short form.
Enabled by default.
\b \i\c{zext-reloc} warns that a relocation has been zero-extended due
to limitations in the output format. Enabled by default.
\b \i\c\{ptr} warns about keywords used in other assemblers that might
indicate a mistake in the source code. Currently only the MASM
\c{PTR} keyword is recognized. Enabled by default.
\b \i\c{bad-pragma} warns about a malformed or otherwise unparsable
\c{%pragma} directive. Disabled by default.
\b \i\c{unknown-pragma} warns about an unknown \c{%pragma} directive.
This is not yet implemented. Disabled by default.
\b \i\c{not-my-pragma} warns about a \c{%pragma} directive which is
not applicable to this particular assembly session. This is not yet
implemented. Disabled by default.
\b \i\c{unknown-warning} warns about a \c{-w} or \c{-W} option or a
\c{[WARNING]} directive that contains an unknown warning name or is
otherwise not possible to process. Disabled by default.
\b \i\c{all} is an alias for \e{all} suppressible warning classes.
Thus, \c{-w+all} enables all available warnings, and \c{-w-all}
disables warnings entirely (since NASM 2.13).
\& warnings.src
Since version 2.00, NASM has also supported the \c{gcc}-like syntax
\c{-Wwarning-class} and \c{-Wno-warning-class} instead of

View File

@ -83,7 +83,6 @@ static inline vefunc nasm_set_verror(vefunc ve)
* These are the error severity codes which get passed as the first
* argument to an efunc.
*/
#define ERR_DEBUG 0x00000000 /* put out debugging message */
#define ERR_NOTE 0x00000001 /* additional error information */
#define ERR_WARNING 0x00000002 /* warn only: no further action */
@ -107,55 +106,23 @@ static inline vefunc nasm_set_verror(vefunc ve)
* They are assumed to occupy the most significant bits of the
* severity code.
*/
#define WARN_SHR 12 /* how far to shift right */
#define WARN(x) (((errflags)(x)) << WARN_SHR)
#define WARN_MASK WARN(~0)
#define WARN_IDX(x) (((errflags)(x)) >> WARN_SHR)
#define WARN_MACRO_PARAMS WARN( 1) /* macro-num-parameters warning */
#define WARN_MACRO_SELFREF WARN( 2) /* macro self-reference */
#define WARN_MACRO_DEFAULTS WARN( 3) /* macro default parameters check */
#define WARN_ORPHAN_LABELS WARN( 4) /* orphan label (no colon, and alone on line) */
#define WARN_NUMBER_OVERFLOW WARN( 5) /* numeric overflow */
#define WARN_GNU_ELF_EXTENSIONS WARN( 6) /* using GNU ELF extensions */
#define WARN_FLOAT_OVERFLOW WARN( 7) /* FP overflow */
#define WARN_FLOAT_DENORM WARN( 8) /* FP denormal */
#define WARN_FLOAT_UNDERFLOW WARN( 9) /* FP underflow */
#define WARN_FLOAT_TOOLONG WARN(10) /* FP too many digits */
#define WARN_USER WARN(11) /* %warning directives */
#define WARN_LOCK WARN(12) /* bad LOCK prefixes */
#define WARN_HLE WARN(13) /* bad HLE prefixes */
#define WARN_BND WARN(14) /* bad BND prefixes */
#define WARN_ZEXTRELOC WARN(15) /* relocation zero-extended */
#define WARN_PTR WARN(16) /* not a NASM keyword */
#define WARN_BAD_PRAGMA WARN(17) /* malformed pragma */
#define WARN_UNKNOWN_PRAGMA WARN(18) /* unknown pragma */
#define WARN_NOT_MY_PRAGMA WARN(19) /* pragma inapplicable */
#define WARN_UNK_WARNING WARN(20) /* unknown warning */
#define WARN_NEGATIVE_REP WARN(21) /* negative repeat count */
#define WARN_PHASE WARN(22) /* phase error in pass 1 */
#define WARN_LABEL_REDEF WARN(23) /* label redefined, but consistent */
#define WARN_LABEL_REDEF_LATE WARN(24) /* label (re)defined during code generation */
/* These two should come last */
#define WARN_ALL (24+2) /* Do not use WARN() here */
#define WARN_OTHER WARN(WARN_ALL-1) /* any noncategorized warning */
#define WARN_MASK ((~(errflags)0) << WARN_SHR)
/* This is a bitmask */
#define WARN_ST_ENABLED 1 /* Warning is currently enabled */
#define WARN_ST_ERROR 2 /* Treat this warning as an error */
struct warning {
const char *name;
const char *help;
uint8_t state; /* Default state for this warning */
};
extern const struct warning warnings[WARN_ALL+1];
extern uint8_t warning_state[WARN_ALL];
extern uint8_t warning_state_init[WARN_ALL];
/* Possible initial state for warnings */
#define WARN_INIT_OFF 0
#define WARN_INIT_ON WARN_ST_ENABLED
#define WARN_INIT_ERR (WARN_ST_ENABLED|WARN_ST_ERROR)
/* Process a warning option or directive */
bool set_warning_status(const char *value);
/* Should be included from within error.h only */
#include "warnings.h"
#endif /* NASM_ERROR_H */

View File

@ -163,10 +163,16 @@ int64_t readnum(const char *str, bool *error)
r++;
}
if (warn)
if (warn) {
/*!
*!number-overflow [on] numeric constant does not fit
*! covers warnings about numeric constants which
*! don't fit in 64 bits.
*/
nasm_error(ERR_WARNING | ERR_PASS1 | WARN_NUMBER_OVERFLOW,
"numeric constant %s does not fit in 64 bits",
str);
}
return result * sign;
}

View File

@ -919,6 +919,11 @@ static void elf32_out(int32_t segto, const void *data,
}
if (gnu16) {
/*!
*!gnu-elf-extensions [off] using 8- or 16-bit relocation in ELF32, a GNU extension
*! warns if 8-bit or 16-bit relocations are used in the \c{elf32} output format.
*! The GNU extensions allow this.
*/
nasm_warnf(WARN_GNU_ELF_EXTENSIONS, "8- or 16-bit relocations "
"in ELF32 is a GNU extension");
} else if (asize != 4 && segment != NO_SEG) {