1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-07 07:29:33 +00:00

Merge pull request #1863 from acqn/LinkageFix

[cc65] Fixed symbol visibility and usage problems with extern/static declarations
This commit is contained in:
Bob Andrews 2022-10-09 18:59:12 +02:00 committed by GitHub
commit a169e67e43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 16 deletions

View File

@ -465,8 +465,8 @@ static void ParseOneDecl (const DeclSpec* Spec)
/* The default storage class could be wrong. Just clear them */
Decl.StorageClass &= ~SC_STORAGEMASK;
/* This is always a declaration */
Decl.StorageClass |= SC_DECL;
/* This is always an extern declaration */
Decl.StorageClass |= SC_DECL | SC_EXTERN;
}
/* If we don't have a name, this was flagged as an error earlier.
@ -524,7 +524,9 @@ static void ParseOneDecl (const DeclSpec* Spec)
if ((Decl.StorageClass & SC_EXTERN) == SC_EXTERN ||
(Decl.StorageClass & SC_FUNC) == SC_FUNC) {
/* Add the global symbol to the local symbol table */
/* Add the global symbol to both of the global and local symbol
** tables.
*/
AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass);
} else {
/* Add the local symbol to the local symbol table */

View File

@ -105,8 +105,8 @@ struct CodeEntry;
#define SC_SPADJUSTMENT 0x400000U
#define SC_GOTO_IND 0x800000U /* Indirect goto */
#define SC_ALIAS 0x01000000U /* Alias of anonymous field */
#define SC_FICTITIOUS 0x02000000U /* Symbol is fictitious */
#define SC_ALIAS 0x01000000U /* Alias of global or anonymous field */
#define SC_FICTITIOUS 0x02000000U /* Symbol is fictitious (for error recovery) */
#define SC_HAVEFAM 0x04000000U /* Type has a Flexible Array Member */

View File

@ -567,6 +567,11 @@ static SymEntry* FindSymInTree (const SymTable* Tab, const char* Name)
/* Try to find the symbol in this table */
SymEntry* E = FindSymInTable (Tab, Name, Hash);
while (E != 0 && (E->Flags & SC_ALIAS) == SC_ALIAS) {
/* Get the aliased entry */
E = E->V.A.Field;
}
/* Bail out if we found it */
if (E != 0) {
return E;
@ -1279,6 +1284,11 @@ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs
/* Generate the assembler name from the data label number */
Entry->V.L.Label = Offs;
Entry->AsmName = xstrdup (LocalDataLabelName (Entry->V.L.Label));
} else if ((Flags & SC_ALIAS) == SC_ALIAS) {
/* Just clear the info */
Entry->V.A.Field = 0;
Entry->V.A.ANumber = 0;
Entry->V.A.Offs = 0;
} else {
Internal ("Invalid flags in AddLocalSym: %04X", Flags);
}
@ -1296,13 +1306,26 @@ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs
SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
/* Add an external or global symbol to the symbol table and return the entry */
{
/* Start from the local symbol table */
SymTable* Tab = SymTab;
/* Add the new declaration to the global symbol table if no errors */
SymTable* Tab = SymTab0;
/* Only search this name in the local and global symbol tables */
SymEntry* Entry = 0;
SymEntry* Alias = 0;
if (SymTab != SymTab0) {
Alias = Entry = FindLocalSym (Name);
while (Entry && (Entry->Flags & SC_ALIAS) == SC_ALIAS) {
/* Get the aliased entry */
Entry = Entry->V.A.Field;
}
}
if (Entry == 0) {
Entry = FindGlobalSym (Name);
}
/* Do we have an entry with this name already? */
SymEntry* Entry = FindSymInTree (Tab, Name);
if (Entry) {
/* We have a symbol with this name already */
if (HandleSymRedefinition (Entry, T, Flags)) {
Entry = 0;
@ -1317,7 +1340,7 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
** declaration if both declarations are global, otherwise give an
** error.
*/
if (Tab == SymTab0 &&
if (SymTab == SymTab0 &&
(Flags & SC_EXTERN) == 0 &&
(Entry->Flags & SC_EXTERN) != 0) {
Warning ("Static declaration of '%s' follows non-static declaration", Name);
@ -1353,12 +1376,9 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
/* Use the fail-safe table for fictitious symbols */
Tab = FailSafeTab;
}
} else if ((Flags & (SC_EXTERN | SC_FUNC)) != 0) {
/* Add the new declaration to the global symbol table instead */
Tab = SymTab0;
}
if (Entry == 0 || Entry->Owner != Tab) {
if (Entry == 0) {
/* Create a new entry */
Entry = NewSymEntry (Name, Flags);
@ -1376,6 +1396,13 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
/* Add the entry to the symbol table */
AddSymEntry (Tab, Entry);
}
/* Add an alias of the global symbol to the local symbol table */
if (Tab == SymTab0 && SymTab != SymTab0 && Entry->Owner != SymTab && Alias == 0) {
Alias = AddLocalSym (Name, T, SC_ALIAS, 0);
Alias->V.A.Field = Entry;
}
/* Return the entry */

31
test/val/extern.c Normal file
View File

@ -0,0 +1,31 @@
/* Test for shadowing and linkage of file-scope "static" and block-scope "extern" declarations */
static int g(int x); /* Generated functions with internal linkage are not always kept in cc65 */
int main(void)
{
char f = 'f'; /* Shadows global "int f(void)" (if any) */
char c = 'c'; /* Shadows global "int c" (if any) */
{
void* f = 0; /* Shadows local "char f" */
void* c = 0; /* Shadows local "char c" */
{
int f(void); /* Shadows local "char f" and "void* f" */
extern int g(int); /* Shadows global "int g(int x)" */
extern int c; /* Shadows local "char c" and "void* c" */
return f() ^ g(c); /* Link to global "int g(int x)" */
}
}
}
int c = 42;
int f(void)
{
return 42;
}
int g(int x)
{
return x;
}