Fixed check for conflicting extern vs no-linkage/static declarations in functions.

This commit is contained in:
acqn 2023-09-17 23:47:22 +08:00
parent 5ed3108eea
commit 39abd233fe
5 changed files with 61 additions and 18 deletions

View File

@ -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? */
SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name));
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 */
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) {
Error ("Multiple definition of '%s'", Entry->Name);
Entry = 0;
} else if ((Flags & (SC_AUTO | SC_REGISTER)) != 0 &&
(Entry->Flags & SC_EXTERN) != 0) {
/* Check for local storage class conflict */
Error ("Declaration of '%s' with no linkage follows extern declaration",
Name);
Entry = 0;
} else {
/* 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) {
} else if (CheckExtern) {
if ((Flags & (SC_AUTO | SC_REGISTER)) != 0) {
Error ("Declaration of '%s' with no linkage follows extern declaration", Name);
Entry = 0;
} else if ((Flags & SC_DEF) != 0 && (Flags & SC_EXTERN) == 0) {
/* If a static declaration follows a non-static declaration,
** then it is an error.
*/
Error ("Static declaration of '%s' follows extern declaration", Name);
Entry = 0;
}
@ -1340,7 +1344,8 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
Name);
Entry = 0;
} 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,
** 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 &&
(Entry->Flags & SC_EXTERN) != 0) {
Error ("Static declaration of '%s' follows non-static declaration", Name);
Entry = 0;
} else if ((Flags & SC_EXTERN) != 0 &&
(Entry->Owner == SymTab0 || (Entry->Flags & SC_DEF) != 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 ((Flags & SC_STORAGE) == 0) {
/* Linkage must be unchanged.
** The C standard specifies that a later extern declaration will be ignored,
** and will use the previous linkage instead. Giving a warning for this case.
/* The C standard specifies that a later extern declaration will keep
** the previously declared internal or external linkage unchanged.
** Though not required by the standard, we are warning on this case.
*/
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 {
Error ("Non-static declaration of '%s' follows static declaration", Name);
Entry = 0;
}
} else {
Error ("Extern declaration of '%s' follows static declaration", Name);

View File

@ -0,0 +1,8 @@
/* Bug #2162 - conflicting declarations in functions */
int main(void)
{
extern int i;
int i = 42; /* Error */
return i;
}

View File

@ -0,0 +1,8 @@
/* Bug #2162 - conflicting declarations in functions */
int main(void)
{
static int i = 42;
extern int i; /* Error */
return i;
}

View 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;
}

View 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;
}