mirror of
https://github.com/cc65/cc65.git
synced 2024-12-23 19:29:37 +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 */
|
/* The default storage class could be wrong. Just clear them */
|
||||||
Decl.StorageClass &= ~SC_STORAGEMASK;
|
Decl.StorageClass &= ~SC_STORAGEMASK;
|
||||||
|
|
||||||
/* This is always a declaration */
|
/* This is always an extern declaration */
|
||||||
Decl.StorageClass |= SC_DECL;
|
Decl.StorageClass |= SC_DECL | SC_EXTERN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we don't have a name, this was flagged as an error earlier.
|
/* 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 ||
|
if ((Decl.StorageClass & SC_EXTERN) == SC_EXTERN ||
|
||||||
(Decl.StorageClass & SC_FUNC) == SC_FUNC) {
|
(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);
|
AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass);
|
||||||
} else {
|
} else {
|
||||||
/* Add the local symbol to the local symbol table */
|
/* Add the local symbol to the local symbol table */
|
||||||
|
@ -105,8 +105,8 @@ struct CodeEntry;
|
|||||||
#define SC_SPADJUSTMENT 0x400000U
|
#define SC_SPADJUSTMENT 0x400000U
|
||||||
#define SC_GOTO_IND 0x800000U /* Indirect goto */
|
#define SC_GOTO_IND 0x800000U /* Indirect goto */
|
||||||
|
|
||||||
#define SC_ALIAS 0x01000000U /* Alias of anonymous field */
|
#define SC_ALIAS 0x01000000U /* Alias of global or anonymous field */
|
||||||
#define SC_FICTITIOUS 0x02000000U /* Symbol is fictitious */
|
#define SC_FICTITIOUS 0x02000000U /* Symbol is fictitious (for error recovery) */
|
||||||
#define SC_HAVEFAM 0x04000000U /* Type has a Flexible Array Member */
|
#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 */
|
/* Try to find the symbol in this table */
|
||||||
SymEntry* E = FindSymInTable (Tab, Name, Hash);
|
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 */
|
/* Bail out if we found it */
|
||||||
if (E != 0) {
|
if (E != 0) {
|
||||||
return E;
|
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 */
|
/* Generate the assembler name from the data label number */
|
||||||
Entry->V.L.Label = Offs;
|
Entry->V.L.Label = Offs;
|
||||||
Entry->AsmName = xstrdup (LocalDataLabelName (Entry->V.L.Label));
|
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 {
|
} else {
|
||||||
Internal ("Invalid flags in AddLocalSym: %04X", Flags);
|
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)
|
SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
|
||||||
/* Add an external or global symbol to the symbol table and return the entry */
|
/* Add an external or global symbol to the symbol table and return the entry */
|
||||||
{
|
{
|
||||||
/* Start from the local symbol table */
|
/* Add the new declaration to the global symbol table if no errors */
|
||||||
SymTable* Tab = SymTab;
|
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) {
|
if (Entry) {
|
||||||
|
|
||||||
/* We have a symbol with this name already */
|
/* We have a symbol with this name already */
|
||||||
if (HandleSymRedefinition (Entry, T, Flags)) {
|
if (HandleSymRedefinition (Entry, T, Flags)) {
|
||||||
Entry = 0;
|
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
|
** declaration if both declarations are global, otherwise give an
|
||||||
** error.
|
** error.
|
||||||
*/
|
*/
|
||||||
if (Tab == SymTab0 &&
|
if (SymTab == SymTab0 &&
|
||||||
(Flags & SC_EXTERN) == 0 &&
|
(Flags & SC_EXTERN) == 0 &&
|
||||||
(Entry->Flags & SC_EXTERN) != 0) {
|
(Entry->Flags & SC_EXTERN) != 0) {
|
||||||
Warning ("Static declaration of '%s' follows non-static declaration", Name);
|
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 */
|
/* Use the fail-safe table for fictitious symbols */
|
||||||
Tab = FailSafeTab;
|
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 */
|
/* Create a new entry */
|
||||||
Entry = NewSymEntry (Name, Flags);
|
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 */
|
/* Add the entry to the symbol table */
|
||||||
AddSymEntry (Tab, Entry);
|
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 */
|
/* 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