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) <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin (Intel) 2018-12-18 12:25:11 -08:00
parent 21da8ae8e5
commit 5df6ca712d
15 changed files with 101 additions and 88 deletions

View file

@ -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;

View file

@ -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:

View file

@ -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);
}

View file

@ -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");
}
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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 */

View file

@ -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);
}

View file

@ -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;

View file

@ -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;
} 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) {
nasm_warn(WARN_OTHER, "section attributes ignored on"
" redeclaration of section `%s'", name);
/* 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;
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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 {