diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index d9270f604..a2bbf13dd 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -1340,15 +1340,14 @@ 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 - ** diagnose the conflict. It will warn and compile an extern - ** declaration if both declarations are global, otherwise give an - ** error. + /* 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. */ if (SymTab == SymTab0 && (Flags & SC_EXTERN) == 0 && (Entry->Flags & SC_EXTERN) != 0) { - Warning ("Static declaration of '%s' follows non-static declaration", Name); + Error ("Static declaration of '%s' follows non-static declaration", Name); } else if ((Flags & SC_EXTERN) != 0 && (Entry->Owner == SymTab0 || (Entry->Flags & SC_DEF) != 0) && (Entry->Flags & SC_EXTERN) == 0) { @@ -1360,8 +1359,12 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags) */ if (Entry->Owner == SymTab0) { if ((Flags & SC_STORAGE) == 0) { - /* Linkage must be unchanged */ + /* 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. + */ Flags &= ~SC_EXTERN; + Warning ("Extern declaration of '%s' follows static declaration, extern ignored", Name); } else { Error ("Non-static declaration of '%s' follows static declaration", Name); } diff --git a/test/val/decl-static-extern.c b/test/val/decl-static-extern.c index 6918e0033..2be4d336f 100644 --- a/test/val/decl-static-extern.c +++ b/test/val/decl-static-extern.c @@ -7,13 +7,12 @@ /* see: https://github.com/cc65/cc65/issues/191 + https://github.com/cc65/cc65/issues/2111 */ -#pragma warn(error, on) - static int n = 0; -extern int n; /* should not give an error */ -static int n; /* should not give an error */ +extern int n; /* extern is ignored, gives a warning but keeps previous static definiton */ +static int n; /* no error or warning, the previous static is still in effect */ int main(void) {