mirror of
https://github.com/cc65/cc65.git
synced 2024-12-23 04:30:10 +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:
commit
a169e67e43
@ -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 */
|
||||
|
@ -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 */
|
||||
|
||||
|
||||
|
@ -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
31
test/val/extern.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user