From 723ab481a6550454a6f834bb854e751744ca340a Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Thu, 13 Dec 2018 21:53:31 -0800 Subject: 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) --- .gitignore | 3 +++ Makefile.in | 19 +++++++++++++- asm/assemble.c | 25 +++++++++++++++++- asm/directiv.c | 4 +-- asm/error.c | 68 +++++++++++++++++------------------------------- asm/float.c | 30 +++++++++++++++++----- asm/labels.c | 21 ++++++++++----- asm/nasm.c | 42 ++++++++++++++++-------------- asm/parser.c | 6 +++++ asm/pragma.c | 17 ++++++++++++ asm/preproc.c | 29 ++++++++++++++++++--- asm/stdscan.c | 6 +++++ asm/warnings.pl | 46 ++++++++++++++++++++++----------- doc/Makefile.in | 2 +- doc/nasmdoc.src | 77 +------------------------------------------------------ include/error.h | 49 ++++++----------------------------- nasmlib/readnum.c | 8 +++++- output/outelf.c | 5 ++++ 18 files changed, 238 insertions(+), 219 deletions(-) diff --git a/.gitignore b/.gitignore index 82ec14ea..7afbbe25 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/Makefile.in b/Makefile.in index 78eaffe2..d2f5889f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 diff --git a/asm/assemble.c b/asm/assemble.c index 964efb0e..03335eb3 100644 --- a/asm/assemble.c +++ b/asm/assemble.c @@ -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"); } diff --git a/asm/directiv.c b/asm/directiv.c index 90b8b7b2..66901530 100644 --- a/asm/directiv.c +++ b/asm/directiv.c @@ -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] */ diff --git a/asm/error.c b/asm/error.c index 2a0b34ad..ea2620fa 100644 --- a/asm/error.c +++ b/asm/error.c @@ -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 : ""; 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; } diff --git a/asm/float.c b/asm/float.c index 6f26e678..54af63cb 100644 --- a/asm/float.c +++ b/asm/float.c @@ -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; } diff --git a/asm/labels.c b/asm/labels.c index ead1f34b..7d87503d 100644 --- a/asm/labels.c +++ b/asm/labels.c @@ -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", diff --git a/asm/nasm.c b/asm/nasm.c index 2a95f6a1..6bc55528 100644 --- a/asm/nasm.c +++ b/asm/nasm.c @@ -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" diff --git a/asm/parser.c b/asm/parser.c index 04def6b4..c34f8337 100644 --- a/asm/parser.c +++ b/asm/parser.c @@ -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"); } diff --git a/asm/pragma.c b/asm/pragma.c index 85e8c9cd..b6878e9d 100644 --- a/asm/pragma.c +++ b/asm/pragma.c @@ -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; diff --git a/asm/preproc.c b/asm/preproc.c index 741430f2..cdea9206 100644 --- a/asm/preproc.c +++ b/asm/preproc.c @@ -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) diff --git a/asm/stdscan.c b/asm/stdscan.c index b197b27f..ee6d0442 100644 --- a/asm/stdscan.c +++ b/asm/stdscan.c @@ -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); } diff --git a/asm/warnings.pl b/asm/warnings.pl index 384c18da..cb336ada 100755 --- a/asm/warnings.pl +++ b/asm/warnings.pl @@ -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') { diff --git a/doc/Makefile.in b/doc/Makefile.in index 27e6fadb..efe5fccb 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -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: diff --git a/doc/nasmdoc.src b/doc/nasmdoc.src index f1abc507..7c7a75aa 100644 --- a/doc/nasmdoc.src +++ b/doc/nasmdoc.src @@ -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 diff --git a/include/error.h b/include/error.h index 34e7d50f..3019615b 100644 --- a/include/error.h +++ b/include/error.h @@ -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 */ diff --git a/nasmlib/readnum.c b/nasmlib/readnum.c index 02e30830..4e73c1a1 100644 --- a/nasmlib/readnum.c +++ b/nasmlib/readnum.c @@ -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; } diff --git a/output/outelf.c b/output/outelf.c index 8270ba0b..2adf4692 100644 --- a/output/outelf.c +++ b/output/outelf.c @@ -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) { -- cgit v1.2.1