From 5df6ca712df59a7f83b27ebd382bfb6ee851fff8 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Tue, 18 Dec 2018 12:25:11 -0800 Subject: With buffered warnings, change the handling of error passes With buffered warnings, most warnings *must* be issued on every pass, so ERR_PASS1 is simply wrong in most cases. ERR_PASS1 now means "force this warning to be output even in pass_first(). This is to be used for the case where the warning is only executed in pass_first() code; this is highly discouraged as it means the warnings will not appear in the list file and subsequent passes may make the warning suddenly vanish. ERR_PASS2 just as before suppresses an error or warning unless we are in pass_final(). Signed-off-by: H. Peter Anvin (Intel) --- asm/assemble.c | 4 ++-- asm/eval.c | 4 ++-- asm/nasm.c | 22 ++++++++++-------- asm/parser.c | 8 +++---- asm/preproc.c | 53 ++++++++++++++++++++----------------------- asm/stdscan.c | 2 +- include/error.h | 4 ++-- nasmlib/readnum.c | 2 +- output/outbin.c | 4 ++-- output/outcoff.c | 68 ++++++++++++++++++++++++++++++------------------------- output/outelf.c | 9 ++++---- output/outelf.h | 1 + output/outieee.c | 5 +++- output/outobj.c | 4 +++- output/pecoff.h | 1 + 15 files changed, 102 insertions(+), 89 deletions(-) diff --git a/asm/assemble.c b/asm/assemble.c index c5d3f65c..d5706820 100644 --- a/asm/assemble.c +++ b/asm/assemble.c @@ -1205,7 +1205,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits, nasm_nonfatal("attempt to reserve non-constant" " quantity of BSS space"); else if (ins->oprs[0].opflags & OPFLAG_FORWARD) - nasm_warn(WARN_OTHER|ERR_PASS1, "forward reference in RESx " + nasm_warn(WARN_OTHER, "forward reference in RESx " "can have unpredictable results"); else length += ins->oprs[0].offset; @@ -2528,7 +2528,7 @@ static enum ea_type process_ea(operand *input, ea *output, int bits, if (eaflags & EAF_BYTEOFFS || (eaflags & EAF_WORDOFFS && input->disp_size != (addrbits != 16 ? 32 : 16))) - nasm_warn(WARN_OTHER|ERR_PASS1, "displacement size ignored on absolute address"); + nasm_warn(WARN_OTHER, "displacement size ignored on absolute address"); if (bits == 64 && (~input->type & IP_REL)) { output->sib_present = true; diff --git a/asm/eval.c b/asm/eval.c index 9179c0bf..28db3276 100644 --- a/asm/eval.c +++ b/asm/eval.c @@ -784,7 +784,7 @@ static expr *eval_strfunc(enum strfunc type) } if (rn_warn) - nasm_warn(WARN_OTHER|ERR_PASS1, "character constant too long"); + nasm_warn(WARN_OTHER, "character constant too long"); begintemp(); addtotemp(EXPR_SIMPLE, val); @@ -942,7 +942,7 @@ static expr *expr6(void) case TOKEN_STR: tmpval = readstrnum(tokval->t_charptr, tokval->t_inttwo, &rn_warn); if (rn_warn) - nasm_warn(WARN_OTHER|ERR_PASS1, "character constant too long"); + nasm_warn(WARN_OTHER, "character constant too long"); addtotemp(EXPR_SIMPLE, tmpval); break; case TOKEN_REG: diff --git a/asm/nasm.c b/asm/nasm.c index 6800a5b6..e0c23af3 100644 --- a/asm/nasm.c +++ b/asm/nasm.c @@ -206,7 +206,7 @@ nasm_set_limit(const char *limit, const char *valstr) if (not_started()) errlevel = ERR_WARNING|WARN_OTHER|ERR_USAGE; else - errlevel = ERR_WARNING|ERR_PASS1|WARN_UNKNOWN_PRAGMA; + errlevel = ERR_WARNING|WARN_UNKNOWN_PRAGMA; nasm_error(errlevel, "unknown limit: `%s'", limit); return DIRR_ERROR; } @@ -219,7 +219,7 @@ nasm_set_limit(const char *limit, const char *valstr) if (not_started()) errlevel = ERR_WARNING|WARN_OTHER|ERR_USAGE; else - errlevel = ERR_WARNING|ERR_PASS1|WARN_BAD_PRAGMA; + errlevel = ERR_WARNING|WARN_BAD_PRAGMA; nasm_error(errlevel, "invalid limit value: `%s'", limit); return DIRR_ERROR; } @@ -1754,11 +1754,8 @@ static bool skip_this_pass(errflags severity) if ((severity & ERR_MASK) >= ERR_FATAL) return false; - /* - * Let's get rid of these flags when and if we can... - */ - return ((severity & ERR_PASS1) && !pass_first()) || - ((severity & ERR_PASS2) && !pass_final()); + /* This message not applicable unless pass_final */ + return (severity & ERR_PASS2) && !pass_final(); } /** @@ -1869,7 +1866,9 @@ static void nasm_verror_asm(errflags severity, const char *fmt, va_list args) const char *file = currentfile ? currentfile : "nasm"; const char *here = (severity & ERR_HERE) ? " here" : ""; - if (warn_list && true_type < ERR_NONFATAL) { + if (warn_list && true_type < ERR_NONFATAL && + !(pass_first() && (severity & ERR_PASS1))) + { /* * Buffer up warnings until we either get an error * or we are on the code-generation pass. @@ -1878,8 +1877,11 @@ static void nasm_verror_asm(errflags severity, const char *fmt, va_list args) file, linestr, errfmt->beforemsg, pfx, msg, here, warnsuf); } else { - /* If we have buffered warnings, output them now. */ - if (warn_list) { + /* + * If we have buffered warnings, and this is a non-warning, + * output them now. + */ + if (true_type >= ERR_NONFATAL && warn_list) { strlist_write(warn_list, "\n", error_file); strlist_free(&warn_list); } diff --git a/asm/parser.c b/asm/parser.c index 9c96732d..abc1ea40 100644 --- a/asm/parser.c +++ b/asm/parser.c @@ -469,7 +469,7 @@ restart_parse: *! a label without a trailing colon. This is most likely indicative *! of a typo, but is technically correct NASM syntax (see \k{syntax}.) */ - nasm_warn(WARN_ORPHAN_LABELS | ERR_PASS1, + nasm_warn(WARN_ORPHAN_LABELS , "label alone on a line without a colon might be in error"); } if (i != TOKEN_INSN || tokval.t_integer != I_EQU) { @@ -519,7 +519,7 @@ restart_parse: int slot = prefix_slot(tokval.t_integer); if (result->prefixes[slot]) { if (result->prefixes[slot] == tokval.t_integer) - nasm_warn(WARN_OTHER|ERR_PASS1, "instruction has redundant prefixes"); + nasm_warn(WARN_OTHER, "instruction has redundant prefixes"); else nasm_nonfatal("instruction has conflicting prefixes"); } @@ -732,7 +732,7 @@ is_expression: */ goto fail; } else /* DB ... */ if (oper_num == 0) - nasm_warn(WARN_OTHER|ERR_PASS1, "no operand for data declaration"); + nasm_warn(WARN_OTHER, "no operand for data declaration"); else result->operands = oper_num; @@ -1126,7 +1126,7 @@ is_expression: op->basereg = value->type; if (rs && (op->type & SIZE_MASK) != rs) - nasm_warn(WARN_OTHER|ERR_PASS1, "register size specification ignored"); + nasm_warn(WARN_OTHER, "register size specification ignored"); } } diff --git a/asm/preproc.c b/asm/preproc.c index 9e1d2f44..93dcd263 100644 --- a/asm/preproc.c +++ b/asm/preproc.c @@ -909,7 +909,7 @@ static Token *tokenize(char *line) p++; } if (*p != '}') - nasm_warn(WARN_OTHER|ERR_PASS1, "unterminated %%{ construct"); + nasm_warn(WARN_OTHER, "unterminated %%{ construct"); p[-1] = '\0'; if (*p) p++; @@ -997,7 +997,7 @@ static Token *tokenize(char *line) if (*p) { p++; } else { - nasm_warn(WARN_OTHER|ERR_PASS1, "unterminated string"); + nasm_warn(WARN_OTHER, "unterminated string"); /* Handling unterminated strings by UNV */ /* type = -1; */ } @@ -1911,7 +1911,7 @@ static bool if_condition(Token * tline, enum preproc_token ct) mmac = mmac->next; } if (tline && tline->next) - nasm_warn(WARN_OTHER|ERR_PASS1, "trailing garbage after %%ifmacro ignored"); + nasm_warn(WARN_OTHER, "trailing garbage after %%ifmacro ignored"); nasm_free(searching.name); j = found; break; @@ -1970,7 +1970,7 @@ iftype: if (!evalresult) return -1; if (tokval.t_type) - nasm_warn(WARN_OTHER|ERR_PASS1, "trailing garbage after expression ignored"); + nasm_warn(WARN_OTHER, "trailing garbage after expression ignored"); if (!is_simple(evalresult)) { nasm_nonfatal("non-constant value given to `%s'", pp_directives[ct]); @@ -2004,7 +2004,7 @@ static bool define_smacro(Context *ctx, const char *mname, bool casesense, if (smacro_defined(ctx, mname, nparam, &smac, casesense)) { if (!smac) { - nasm_warn(WARN_OTHER|ERR_PASS1, "single-line macro `%s' defined both with and" + nasm_warn(WARN_OTHER, "single-line macro `%s' defined both with and" " without parameters", mname); /* * Some instances of the old code considered this a failure, @@ -2137,7 +2137,7 @@ static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive) *! warns when a macro has more default parameters than optional parameters. *! See \k{mlmacdef} for why might want to disable this warning. */ - nasm_warn(ERR_PASS1|WARN_MACRO_DEFAULTS, + nasm_warn(WARN_MACRO_DEFAULTS, "too many default macro parameters in macro `%s'", def->name); } @@ -2514,7 +2514,7 @@ static int do_directive(Token *tline, char **output) case PP_CLEAR: if (tline->next) - nasm_warn(WARN_OTHER|ERR_PASS1, "trailing garbage after `%%clear' ignored"); + nasm_warn(WARN_OTHER, "trailing garbage after `%%clear' ignored"); free_macros(); init_macros(); free_tlist(origline); @@ -2530,7 +2530,7 @@ static int do_directive(Token *tline, char **output) return DIRECTIVE_FOUND; /* but we did _something_ */ } if (t->next) - nasm_warn(WARN_OTHER|ERR_PASS1, "trailing garbage after `%%depend' ignored"); + nasm_warn(WARN_OTHER, "trailing garbage after `%%depend' ignored"); p = t->text; if (t->type != TOK_INTERNAL_STRING) nasm_unquote_cstr(p, i); @@ -2549,7 +2549,7 @@ static int do_directive(Token *tline, char **output) return DIRECTIVE_FOUND; /* but we did _something_ */ } if (t->next) - nasm_warn(WARN_OTHER|ERR_PASS1, "trailing garbage after `%%include' ignored"); + nasm_warn(WARN_OTHER, "trailing garbage after `%%include' ignored"); p = t->text; if (t->type != TOK_INTERNAL_STRING) nasm_unquote_cstr(p, i); @@ -2592,7 +2592,7 @@ static int do_directive(Token *tline, char **output) return DIRECTIVE_FOUND; /* but we did _something_ */ } if (tline->next) - nasm_warn(WARN_OTHER|ERR_PASS1, "trailing garbage after `%%use' ignored"); + nasm_warn(WARN_OTHER, "trailing garbage after `%%use' ignored"); if (tline->type == TOK_STRING) nasm_unquote_cstr(tline->text, i); use_pkg = nasm_stdmac_find_package(tline->text); @@ -2621,7 +2621,7 @@ static int do_directive(Token *tline, char **output) return DIRECTIVE_FOUND; /* but we did _something_ */ } if (tline->next) - nasm_warn(WARN_OTHER|ERR_PASS1, "trailing garbage after `%s' ignored", + nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", pp_directives[i]); p = nasm_strdup(tline->text); } else { @@ -2659,22 +2659,19 @@ static int do_directive(Token *tline, char **output) severity = ERR_FATAL; goto issue_error; case PP_ERROR: - severity = ERR_NONFATAL; + severity = ERR_NONFATAL|ERR_PASS2; goto issue_error; case PP_WARNING: /*! *!user [on] %warning directives *! controls output of \c{%warning} directives (see \k{pperror}). */ - severity = ERR_WARNING|WARN_USER; + severity = ERR_WARNING|WARN_USER|ERR_PASS2; goto issue_error; issue_error: { /* Only error out if this is the final pass */ - if (pass_final() && i != PP_FATAL) - return DIRECTIVE_FOUND; - tline->next = expand_smacro(tline->next); tline = tline->next; skip_white_(tline); @@ -2726,7 +2723,7 @@ issue_error: case COND_ELSE_TRUE: case COND_ELSE_FALSE: - nasm_warn(WARN_OTHER|ERR_PASS1|ERR_PP_PRECOND, + nasm_warn(WARN_OTHER|ERR_PP_PRECOND, "`%%elif' after `%%else' ignored"); istk->conds->state = COND_NEVER; break; @@ -2751,7 +2748,7 @@ issue_error: case PP_ELSE: if (tline->next) - nasm_warn(WARN_OTHER|ERR_PASS1|ERR_PP_PRECOND, + nasm_warn(WARN_OTHER|ERR_PP_PRECOND, "trailing garbage after `%%else' ignored"); if (!istk->conds) nasm_fatal("`%%else: no matching `%%if'"); @@ -2770,7 +2767,7 @@ issue_error: case COND_ELSE_TRUE: case COND_ELSE_FALSE: - nasm_warn(WARN_OTHER|ERR_PASS1|ERR_PP_PRECOND, + nasm_warn(WARN_OTHER|ERR_PP_PRECOND, "`%%else' after `%%else' ignored."); istk->conds->state = COND_NEVER; break; @@ -2780,7 +2777,7 @@ issue_error: case PP_ENDIF: if (tline->next) - nasm_warn(WARN_OTHER|ERR_PASS1|ERR_PP_PRECOND, + nasm_warn(WARN_OTHER|ERR_PP_PRECOND, "trailing garbage after `%%endif' ignored"); if (!istk->conds) nasm_fatal("`%%endif': no matching `%%if'"); @@ -2820,7 +2817,7 @@ issue_error: || defining->plus) && (defining->nparam_min <= mmac->nparam_max || mmac->plus)) { - nasm_warn(WARN_OTHER|ERR_PASS1, "redefining multi-line macro `%s'", + nasm_warn(WARN_OTHER, "redefining multi-line macro `%s'", defining->name); return DIRECTIVE_FOUND; } @@ -2918,7 +2915,7 @@ issue_error: if (!evalresult) return DIRECTIVE_FOUND; if (tokval.t_type) - nasm_warn(WARN_OTHER|ERR_PASS1, "trailing garbage after expression ignored"); + nasm_warn(WARN_OTHER, "trailing garbage after expression ignored"); if (!is_simple(evalresult)) { nasm_nonfatal("non-constant value given to `%%rotate'"); return DIRECTIVE_FOUND; @@ -2966,7 +2963,7 @@ issue_error: return DIRECTIVE_FOUND; } if (tokval.t_type) - nasm_warn(WARN_OTHER|ERR_PASS1, "trailing garbage after expression ignored"); + nasm_warn(WARN_OTHER, "trailing garbage after expression ignored"); if (!is_simple(evalresult)) { nasm_nonfatal("non-constant value given to `%%rep'"); return DIRECTIVE_FOUND; @@ -3163,7 +3160,7 @@ issue_error: return DIRECTIVE_FOUND; } if (tline->next) - nasm_warn(WARN_OTHER|ERR_PASS1, "trailing garbage after macro name ignored"); + nasm_warn(WARN_OTHER, "trailing garbage after macro name ignored"); /* Find the context that symbol belongs to */ ctx = get_ctx(tline->text, &mname); @@ -3295,7 +3292,7 @@ issue_error: return DIRECTIVE_FOUND; /* but we did _something_ */ } if (t->next) - nasm_warn(WARN_OTHER|ERR_PASS1, "trailing garbage after `%%pathsearch' ignored"); + nasm_warn(WARN_OTHER, "trailing garbage after `%%pathsearch' ignored"); p = t->text; if (t->type != TOK_INTERNAL_STRING) nasm_unquote(p, NULL); @@ -3554,7 +3551,7 @@ issue_error: } if (tokval.t_type) - nasm_warn(WARN_OTHER|ERR_PASS1, "trailing garbage after expression ignored"); + nasm_warn(WARN_OTHER, "trailing garbage after expression ignored"); if (!is_simple(evalresult)) { nasm_nonfatal("non-constant value given to `%%%sassign'", @@ -4311,7 +4308,7 @@ again: *! with the wrong number of parameters. See \k{mlmacover} for an *! example of why you might want to disable this warning. */ - nasm_warn(ERR_PASS1|WARN_MACRO_PARAMS, + nasm_warn(WARN_MACRO_PARAMS, "macro `%s' exists, " "but not taking %d parameters", mstart->text, nparam); @@ -4612,7 +4609,7 @@ static MMacro *is_mmacro(Token * tline, Token *** params_array) * After all that, we didn't find one with the right number of * parameters. Issue a warning, and fail to expand the macro. */ - nasm_warn(ERR_PASS1|WARN_MACRO_PARAMS, + nasm_warn(WARN_MACRO_PARAMS, "macro `%s' exists, but not taking %d parameters", tline->text, nparam); nasm_free(params); diff --git a/asm/stdscan.c b/asm/stdscan.c index dbe0fd54..4f256fc6 100644 --- a/asm/stdscan.c +++ b/asm/stdscan.c @@ -173,7 +173,7 @@ int stdscan(void *private_data, struct tokenval *tv) *! indicate a mistake in the source code. Currently only the MASM *! \c{PTR} keyword is recognized. */ - nasm_warn(ERR_PASS1|WARN_PTR, "`%s' is not a NASM keyword", + nasm_warn(WARN_PTR, "`%s' is not a NASM keyword", tv->t_charptr); } diff --git a/include/error.h b/include/error.h index 9c935214..03a220ec 100644 --- a/include/error.h +++ b/include/error.h @@ -93,8 +93,8 @@ static inline vefunc nasm_set_verror(vefunc ve) #define ERR_NOFILE 0x00000010 /* don't give source file name/line */ #define ERR_HERE 0x00000020 /* point to a specific source location */ #define ERR_USAGE 0x00000040 /* print a usage message */ -#define ERR_PASS1 0x00000080 /* only print this error on pass one */ -#define ERR_PASS2 0x00000100 /* only print this error on pass one */ +#define ERR_PASS1 0x00000080 /* message on pass_first */ +#define ERR_PASS2 0x00000100 /* ignore unless on pass_final */ #define ERR_NO_SEVERITY 0x00000200 /* suppress printing severity */ #define ERR_PP_PRECOND 0x00000400 /* for preprocessor use */ diff --git a/nasmlib/readnum.c b/nasmlib/readnum.c index 4e73c1a1..3ed6b3f2 100644 --- a/nasmlib/readnum.c +++ b/nasmlib/readnum.c @@ -169,7 +169,7 @@ int64_t readnum(const char *str, bool *error) *! covers warnings about numeric constants which *! don't fit in 64 bits. */ - nasm_error(ERR_WARNING | ERR_PASS1 | WARN_NUMBER_OVERFLOW, + nasm_error(ERR_WARNING | WARN_NUMBER_OVERFLOW, "numeric constant %s does not fit in 64 bits", str); } diff --git a/output/outbin.c b/output/outbin.c index 4bf13fa4..73a4d8a7 100644 --- a/output/outbin.c +++ b/output/outbin.c @@ -1328,13 +1328,13 @@ bin_directive(enum directive directive, char *args) else { /* Must be a filename. */ rf = nasm_open_write(p, NF_TEXT); if (!rf) { - nasm_warn(WARN_OTHER, "unable to open map file `%s'", p); + nasm_warn(WARN_OTHER|ERR_PASS1, "unable to open map file `%s'", p); map_control = 0; return DIRR_OK; } } } else - nasm_warn(WARN_OTHER, "map file already specified"); + nasm_warn(WARN_OTHER|ERR_PASS1, "map file already specified"); } if (map_control == 0) map_control |= MAP_ORIGIN | MAP_SUMMARY; diff --git a/output/outcoff.c b/output/outcoff.c index a90e355e..2c8520f1 100644 --- a/output/outcoff.c +++ b/output/outcoff.c @@ -402,45 +402,51 @@ static int32_t coff_section_names(char *name, int *bits) coff_sects[i]->flags = flags; coff_sects[i]->flags &= align_and; coff_sects[i]->flags |= align_or; - } else if (pass_first()) { - /* Check if any flags are specified */ - if (flags) { - unsigned int align_flags = flags & IMAGE_SCN_ALIGN_MASK; - - /* Warn if non-alignment flags differ */ - if ((flags ^ coff_sects[i]->flags) & ~IMAGE_SCN_ALIGN_MASK) { - nasm_warn(WARN_OTHER, "section attributes ignored on" - " redeclaration of section `%s'", name); + } else if (flags) { + /* Check if any flags are respecified */ + unsigned int align_flags = flags & IMAGE_SCN_ALIGN_MASK; + + /* Warn if non-alignment flags differ */ + if ((flags ^ coff_sects[i]->flags) & ~IMAGE_SCN_ALIGN_MASK && + coff_sects[i]->pass_last_seen == pass_count()) { + nasm_warn(WARN_OTHER, "section attributes changed on" + " redeclaration of section `%s'", name); + } + /* Check if alignment might be needed */ + if (align_flags > IMAGE_SCN_ALIGN_1BYTES) { + unsigned int sect_align_flags = coff_sects[i]->flags & IMAGE_SCN_ALIGN_MASK; + + /* Compute the actual alignment */ + unsigned int align = 1u << ((align_flags - IMAGE_SCN_ALIGN_1BYTES) >> 20); + + /* Update section header as needed */ + if (align_flags > sect_align_flags) { + coff_sects[i]->flags = (coff_sects[i]->flags & ~IMAGE_SCN_ALIGN_MASK) | align_flags; } - /* Check if alignment might be needed */ - if (align_flags > IMAGE_SCN_ALIGN_1BYTES) { - unsigned int sect_align_flags = coff_sects[i]->flags & IMAGE_SCN_ALIGN_MASK; + /* Check if not already aligned */ + if (coff_sects[i]->len % align) { + unsigned int padding = (align - coff_sects[i]->len) % align; + /* We need to write at most 8095 bytes */ + char buffer[8095]; - /* Compute the actual alignment */ - unsigned int align = 1u << ((align_flags - IMAGE_SCN_ALIGN_1BYTES) >> 20); + nasm_assert(padding <= sizeof buffer); - /* Update section header as needed */ - if (align_flags > sect_align_flags) { - coff_sects[i]->flags = (coff_sects[i]->flags & ~IMAGE_SCN_ALIGN_MASK) | align_flags; - } - /* Check if not already aligned */ - if (coff_sects[i]->len % align) { - unsigned int padding = (align - coff_sects[i]->len) % align; - /* We need to write at most 8095 bytes */ - char buffer[8095]; - if (coff_sects[i]->flags & IMAGE_SCN_CNT_CODE) { - /* Fill with INT 3 instructions */ - memset(buffer, 0xCC, padding); - } else { - memset(buffer, 0x00, padding); - } - saa_wbytes(coff_sects[i]->data, buffer, padding); - coff_sects[i]->len += padding; + if (pass_final()) + nasm_nonfatal("section alignment changed during code generation"); + + if (coff_sects[i]->flags & IMAGE_SCN_CNT_CODE) { + /* Fill with INT 3 instructions */ + memset(buffer, 0xCC, padding); + } else { + memset(buffer, 0x00, padding); } + saa_wbytes(coff_sects[i]->data, buffer, padding); + coff_sects[i]->len += padding; } } } + coff_sects[i]->pass_last_seen = pass_count(); return coff_sects[i]->index; } diff --git a/output/outelf.c b/output/outelf.c index cd77901f..366e52de 100644 --- a/output/outelf.c +++ b/output/outelf.c @@ -258,8 +258,8 @@ static void elf_section_attrib(char *name, char *attr, *type = SHT_PROGBITS; } else if (!nasm_stricmp(opt, "nobits")) { *type = SHT_NOBITS; - } else if (pass_first()) { - nasm_warn(WARN_OTHER, "Unknown section attribute '%s' ignored on" + } else { + nasm_warn(WARN_OTHER, "unknown section attribute '%s' ignored on" " declaration of section `%s'", opt, name); } opt = next; @@ -458,14 +458,15 @@ static int32_t elf_section_names(char *name, int *bits) flags = (ks->flags & ~flags_and) | flags_or; i = elf_make_section(name, type, flags, align); - } else if (pass_first()) { + } else if (sects[i]->pass_last_seen == pass_count()) { if ((type && sects[i]->type != type) || (align && sects[i]->align != align) || (flags_and && ((sects[i]->flags & flags_and) != flags_or))) - nasm_warn(WARN_OTHER, "incompatible section attributes ignored on" + nasm_warn(WARN_OTHER|ERR_PASS1, "incompatible section attributes ignored on" " redeclaration of section `%s'", name); } + sects[i]->pass_last_seen = pass_count(); return sects[i]->index; } diff --git a/output/outelf.h b/output/outelf.h index 8eef73ae..0801eaf8 100644 --- a/output/outelf.h +++ b/output/outelf.h @@ -141,6 +141,7 @@ struct elf_section { int type; /* SHT_PROGBITS or SHT_NOBITS */ uint64_t align; /* alignment: power of two */ uint64_t flags; /* section flags */ + int64_t pass_last_seen; char *name; struct SAA *rel; uint64_t rellen; diff --git a/output/outieee.c b/output/outieee.c index 1247077e..f2f598ee 100644 --- a/output/outieee.c +++ b/output/outieee.c @@ -151,6 +151,7 @@ static struct ieeeSection { int32_t align; /* can be SEG_ABS + absolute addr */ int32_t startpos; int32_t use32; /* is this segment 32-bit? */ + int64_t pass_last_seen; struct ieeePublic *pubhead, **pubtail, *lochead, **loctail; enum { CMB_PRIVATE = 0, @@ -705,13 +706,15 @@ static int32_t ieee_segment(char *name, int *bits) for (seg = seghead; seg; seg = seg->next) { ieee_idx++; if (!strcmp(seg->name, name)) { - if (attrs > 0 && pass_first()) + if (attrs > 0 && seg->pass_last_seen == pass_count()) nasm_warn(WARN_OTHER, "segment attributes specified on" " redeclaration of segment: ignoring"); if (seg->use32) *bits = 32; else *bits = 16; + + seg->pass_last_seen = pass_count(); return seg->index; } } diff --git a/output/outobj.c b/output/outobj.c index e861754e..c7407cf9 100644 --- a/output/outobj.c +++ b/output/outobj.c @@ -580,6 +580,7 @@ static struct Segment { struct Group *grp; /* the group it beint32_ts to */ uint32_t currentpos; int32_t align; /* can be SEG_ABS + absolute addr */ + int64_t pass_last_seen; struct Public *pubhead, **pubtail, *lochead, **loctail; char *segclass, *overlay; /* `class' is a C++ keyword :-) */ ObjRecord *orp; @@ -1379,7 +1380,7 @@ static int32_t obj_segment(char *name, int *bits) break; if (!strcmp(seg->name, name)) { - if (attrs > 0 && pass_first()) + if (attrs > 0 && seg->pass_last_seen == pass_count()) nasm_warn(WARN_OTHER, "segment attributes specified on" " redeclaration of segment: ignoring"); if (seg->use32) @@ -1387,6 +1388,7 @@ static int32_t obj_segment(char *name, int *bits) else *bits = 16; current_seg = seg; + seg->pass_last_seen = pass_count(); return seg->index; } } diff --git a/output/pecoff.h b/output/pecoff.h index 8b57d6b2..7b6f46c2 100644 --- a/output/pecoff.h +++ b/output/pecoff.h @@ -484,6 +484,7 @@ struct coff_Section { char *name; int32_t namepos; /* Offset of name into the strings table */ int32_t pos, relpos; + int64_t pass_last_seen; }; struct coff_Reloc { -- cgit v1.2.1