mirror of
https://github.com/cc65/cc65.git
synced 2025-01-18 11:29:45 +00:00
Fixed check for conflicting extern vs no-linkage/static declarations in functions.
This commit is contained in:
parent
5ed3108eea
commit
39abd233fe
@ -1225,6 +1225,15 @@ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs
|
|||||||
/* Do we have an entry with this name already? */
|
/* Do we have an entry with this name already? */
|
||||||
SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name));
|
SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name));
|
||||||
if (Entry) {
|
if (Entry) {
|
||||||
|
int CheckExtern = 0;
|
||||||
|
if ((Flags & SC_STRUCTFIELD) == 0) {
|
||||||
|
while (Entry && (Entry->Flags & SC_ALIAS) == SC_ALIAS) {
|
||||||
|
/* Get the aliased entry */
|
||||||
|
Entry = Entry->V.A.Field;
|
||||||
|
/* Check for conflict with local storage class */
|
||||||
|
CheckExtern = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* 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)) {
|
||||||
@ -1234,19 +1243,14 @@ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs
|
|||||||
if (SymIsDef (Entry) && (Flags & SC_DEF) == SC_DEF) {
|
if (SymIsDef (Entry) && (Flags & SC_DEF) == SC_DEF) {
|
||||||
Error ("Multiple definition of '%s'", Entry->Name);
|
Error ("Multiple definition of '%s'", Entry->Name);
|
||||||
Entry = 0;
|
Entry = 0;
|
||||||
} else if ((Flags & (SC_AUTO | SC_REGISTER)) != 0 &&
|
} else if (CheckExtern) {
|
||||||
(Entry->Flags & SC_EXTERN) != 0) {
|
if ((Flags & (SC_AUTO | SC_REGISTER)) != 0) {
|
||||||
/* Check for local storage class conflict */
|
Error ("Declaration of '%s' with no linkage follows extern declaration", Name);
|
||||||
Error ("Declaration of '%s' with no linkage follows extern declaration",
|
Entry = 0;
|
||||||
Name);
|
} else if ((Flags & SC_DEF) != 0 && (Flags & SC_EXTERN) == 0) {
|
||||||
Entry = 0;
|
/* If a static declaration follows a non-static declaration,
|
||||||
} else {
|
** then it is an error.
|
||||||
/* If a static declaration follows a non-static declaration,
|
*/
|
||||||
** then it is an error.
|
|
||||||
*/
|
|
||||||
if ((Flags & SC_DEF) &&
|
|
||||||
(Flags & SC_EXTERN) == 0 &&
|
|
||||||
(Entry->Flags & SC_EXTERN) != 0) {
|
|
||||||
Error ("Static declaration of '%s' follows extern declaration", Name);
|
Error ("Static declaration of '%s' follows extern declaration", Name);
|
||||||
Entry = 0;
|
Entry = 0;
|
||||||
}
|
}
|
||||||
@ -1340,7 +1344,8 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
|
|||||||
Name);
|
Name);
|
||||||
Entry = 0;
|
Entry = 0;
|
||||||
} else if ((Flags & SC_ESUTYPEMASK) != SC_TYPEDEF) {
|
} else if ((Flags & SC_ESUTYPEMASK) != SC_TYPEDEF) {
|
||||||
/* If a static declaration follows a non-static declaration, then the result is undefined.
|
/* If a static declaration follows a non-static declaration, then
|
||||||
|
** the result is undefined.
|
||||||
** Most compilers choose to either give an error at compile time,
|
** Most compilers choose to either give an error at compile time,
|
||||||
** or remove the extern property for a link time error if used.
|
** or remove the extern property for a link time error if used.
|
||||||
*/
|
*/
|
||||||
@ -1348,6 +1353,7 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
|
|||||||
(Flags & SC_EXTERN) == 0 &&
|
(Flags & SC_EXTERN) == 0 &&
|
||||||
(Entry->Flags & SC_EXTERN) != 0) {
|
(Entry->Flags & SC_EXTERN) != 0) {
|
||||||
Error ("Static declaration of '%s' follows non-static declaration", Name);
|
Error ("Static declaration of '%s' follows non-static declaration", Name);
|
||||||
|
Entry = 0;
|
||||||
} else if ((Flags & SC_EXTERN) != 0 &&
|
} else if ((Flags & SC_EXTERN) != 0 &&
|
||||||
(Entry->Owner == SymTab0 || (Entry->Flags & SC_DEF) != 0) &&
|
(Entry->Owner == SymTab0 || (Entry->Flags & SC_DEF) != 0) &&
|
||||||
(Entry->Flags & SC_EXTERN) == 0) {
|
(Entry->Flags & SC_EXTERN) == 0) {
|
||||||
@ -1359,14 +1365,15 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
|
|||||||
*/
|
*/
|
||||||
if (Entry->Owner == SymTab0) {
|
if (Entry->Owner == SymTab0) {
|
||||||
if ((Flags & SC_STORAGE) == 0) {
|
if ((Flags & SC_STORAGE) == 0) {
|
||||||
/* Linkage must be unchanged.
|
/* The C standard specifies that a later extern declaration will keep
|
||||||
** The C standard specifies that a later extern declaration will be ignored,
|
** the previously declared internal or external linkage unchanged.
|
||||||
** and will use the previous linkage instead. Giving a warning for this case.
|
** Though not required by the standard, we are warning on this case.
|
||||||
*/
|
*/
|
||||||
Flags &= ~SC_EXTERN;
|
Flags &= ~SC_EXTERN;
|
||||||
Warning ("Extern declaration of '%s' follows static declaration, extern ignored", Name);
|
Warning ("Extern declaration of '%s' follows static declaration, linkage unchanged", Name);
|
||||||
} else {
|
} else {
|
||||||
Error ("Non-static declaration of '%s' follows static declaration", Name);
|
Error ("Non-static declaration of '%s' follows static declaration", Name);
|
||||||
|
Entry = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Error ("Extern declaration of '%s' follows static declaration", Name);
|
Error ("Extern declaration of '%s' follows static declaration", Name);
|
||||||
|
8
test/err/bug2162-none-extern-auto.c
Normal file
8
test/err/bug2162-none-extern-auto.c
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/* Bug #2162 - conflicting declarations in functions */
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
extern int i;
|
||||||
|
int i = 42; /* Error */
|
||||||
|
return i;
|
||||||
|
}
|
8
test/err/bug2162-none-static-extern.c
Normal file
8
test/err/bug2162-none-static-extern.c
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/* Bug #2162 - conflicting declarations in functions */
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
static int i = 42;
|
||||||
|
extern int i; /* Error */
|
||||||
|
return i;
|
||||||
|
}
|
10
test/err/bug2162-static-extern-auto.c
Normal file
10
test/err/bug2162-static-extern-auto.c
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/* Bug #2162 - conflicting declarations in functions */
|
||||||
|
|
||||||
|
static int i;
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
extern int i; /* cc65 allows this */
|
||||||
|
int i = 42; /* Error - if this were accepted, it would be confusing which object i refers to */
|
||||||
|
return i;
|
||||||
|
}
|
10
test/err/bug2162-static-static-extern.c
Normal file
10
test/err/bug2162-static-static-extern.c
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/* Bug #2162 - conflicting declarations in functions */
|
||||||
|
|
||||||
|
static int i;
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
static int i = 42; /* OK - this shadows the i in file scope */
|
||||||
|
extern int i; /* Error - if this were accepted, it would be confusing which object i refers to */
|
||||||
|
return i;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user