labels: handle "extern" after definition (BR 3392924)

Using "extern" or "required" after the definition should be
interpreted as "global", just as if "extern" or "required" had been
specified before the definition.

Unfortunately the code did not correctly handle the case of upgrading
from LOCAL to GLOBAL via an EXTERN or REQUIRED directive, only from
EXTERN or REQUIRED to GLOBAL via definition or a GLOBAL or COMMON
directive.

Fix.

Reported-by: E. C. Masloch <pushbx@ulukai.org>
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin 2025-09-19 14:19:49 -07:00
parent ca50adfb7d
commit d2aed9fa9d
2 changed files with 25 additions and 3 deletions

View file

@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
* Copyright 1996-2018 The NASM Authors - All Rights Reserved
* Copyright 1996-2025 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@ -391,8 +391,17 @@ static bool declare_label_lptr(union label *lptr,
if (special && !special[0])
special = NULL;
if (oldtype == type || (!pass_stable() && oldtype == LBL_LOCAL) ||
(oldtype == LBL_EXTERN && type == LBL_REQUIRED)) {
if (!pass_stable() && oldtype == LBL_LOCAL) {
/* Type declared after definition */
if (is_extern(type))
oldtype = LBL_GLOBAL; /* Already defined! */
else
oldtype = type;
lptr->defn.type = oldtype;
}
if (oldtype == type || (oldtype == LBL_EXTERN && type == LBL_REQUIRED)) {
lptr->defn.type = type;
if (special) {

13
test/extern.asm Normal file
View file

@ -0,0 +1,13 @@
nop
global global_before
global_before:
nop
extern extern_before
extern_before:
nop
global_after:
nop
global global_after
extern_after:
nop
extern extern_after