mirror of
https://github.com/cc65/cc65.git
synced 2024-12-27 15:29:46 +00:00
Merge pull request #2370 from acqn/VisibilityFix
[cc65] Fixed visibility of undeclared functions and objects
This commit is contained in:
commit
998dfd6fa7
@ -163,19 +163,19 @@ static void Parse (void)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if we must reserve storage for the variable. We do this,
|
||||
**
|
||||
** - if it is not a typedef or function,
|
||||
** - if we don't had a storage class given ("int i")
|
||||
** - if the storage class is explicitly specified as static,
|
||||
** - or if there is an initialization.
|
||||
**
|
||||
** This means that "extern int i;" will not get storage allocated
|
||||
** in this translation unit.
|
||||
*/
|
||||
/* The symbol is now visible in the file scope */
|
||||
if ((Decl.StorageClass & SC_TYPEMASK) != SC_FUNC &&
|
||||
(Decl.StorageClass & SC_TYPEMASK) != SC_TYPEDEF) {
|
||||
/* The variable is visible in the file scope */
|
||||
/* Check if we must reserve storage for the variable. We do this,
|
||||
**
|
||||
** - if it is not a typedef or function,
|
||||
** - if we don't had a storage class given ("int i")
|
||||
** - if the storage class is explicitly specified as static,
|
||||
** - or if there is an initialization.
|
||||
**
|
||||
** This means that "extern int i;" will not get storage allocated
|
||||
** in this translation unit.
|
||||
*/
|
||||
if ((Decl.StorageClass & SC_STORAGEMASK) == SC_NONE ||
|
||||
(Decl.StorageClass & SC_STORAGEMASK) == SC_STATIC ||
|
||||
((Decl.StorageClass & SC_STORAGEMASK) == SC_EXTERN &&
|
||||
@ -189,7 +189,6 @@ static void Parse (void)
|
||||
** or semicolon, it must be followed by a function body.
|
||||
*/
|
||||
if ((Decl.StorageClass & SC_TYPEMASK) == SC_FUNC) {
|
||||
/* The function is now visible in the file scope */
|
||||
if (CurTok.Tok == TOK_LCURLY) {
|
||||
/* A definition */
|
||||
Decl.StorageClass |= SC_DEF;
|
||||
|
@ -557,8 +557,10 @@ static SymEntry* FindSymInTable (const SymTable* T, const char* Name, unsigned H
|
||||
|
||||
|
||||
|
||||
static SymEntry* FindSymInTree (const SymTable* Tab, const char* Name)
|
||||
/* Find the symbol with the given name in the table tree that starts with T */
|
||||
static SymEntry* FindVisibleSymInTree (const SymTable* Tab, const char* Name)
|
||||
/* Find the visible symbol with the given name in the table tree that starts
|
||||
** with Tab.
|
||||
*/
|
||||
{
|
||||
/* Get the hash over the name */
|
||||
unsigned Hash = HashStr (Name);
|
||||
@ -574,7 +576,7 @@ static SymEntry* FindSymInTree (const SymTable* Tab, const char* Name)
|
||||
}
|
||||
|
||||
/* Bail out if we found it */
|
||||
if (E != 0) {
|
||||
if (E != 0 && (Tab != SymTab0 || (E->Flags & SC_LOCALSCOPE) == 0)) {
|
||||
return E;
|
||||
}
|
||||
|
||||
@ -589,9 +591,9 @@ static SymEntry* FindSymInTree (const SymTable* Tab, const char* Name)
|
||||
|
||||
|
||||
SymEntry* FindSym (const char* Name)
|
||||
/* Find the symbol with the given name */
|
||||
/* Find with the given name the symbol visible in the current scope */
|
||||
{
|
||||
return FindSymInTree (SymTab, Name);
|
||||
return FindVisibleSymInTree (SymTab, Name);
|
||||
}
|
||||
|
||||
|
||||
@ -613,9 +615,9 @@ SymEntry* FindLocalSym (const char* Name)
|
||||
|
||||
|
||||
SymEntry* FindTagSym (const char* Name)
|
||||
/* Find the symbol with the given name in the tag table */
|
||||
/* Find with the given name the tag symbol visible in the current scope */
|
||||
{
|
||||
return FindSymInTree (TagTab, Name);
|
||||
return FindVisibleSymInTree (TagTab, Name);
|
||||
}
|
||||
|
||||
|
||||
@ -1356,6 +1358,13 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
|
||||
Name);
|
||||
Entry = 0;
|
||||
} else if ((Flags & SC_TYPEMASK) != SC_TYPEDEF) {
|
||||
/* If we are adding the symbol in the file scope, it is now
|
||||
** visible there.
|
||||
*/
|
||||
if (SymTab == SymTab0) {
|
||||
Entry->Flags &= ~SC_LOCALSCOPE;
|
||||
}
|
||||
|
||||
/* The C standard specifies that the result is undefined if the
|
||||
** same thing has both internal and external linkage. Most
|
||||
** compilers choose to either give an error at compile time, or
|
||||
@ -1415,6 +1424,13 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
|
||||
}
|
||||
|
||||
if (Entry == 0) {
|
||||
/* Hide the symbol in the file scope if we are declaring it in a
|
||||
** local scope.
|
||||
*/
|
||||
if (Tab == SymTab0 && SymTab != SymTab0) {
|
||||
Flags |= SC_LOCALSCOPE;
|
||||
}
|
||||
|
||||
/* Create a new entry */
|
||||
Entry = NewSymEntry (Name, Flags);
|
||||
|
||||
|
@ -142,7 +142,7 @@ void LeaveStructLevel (void);
|
||||
|
||||
|
||||
SymEntry* FindSym (const char* Name);
|
||||
/* Find the symbol with the given name */
|
||||
/* Find with the given name the symbol visible in the current scope */
|
||||
|
||||
SymEntry* FindGlobalSym (const char* Name);
|
||||
/* Find the symbol with the given name in the global symbol table only */
|
||||
@ -151,7 +151,7 @@ SymEntry* FindLocalSym (const char* Name);
|
||||
/* Find the symbol with the given name in the current symbol table only */
|
||||
|
||||
SymEntry* FindTagSym (const char* Name);
|
||||
/* Find the symbol with the given name in the tag table */
|
||||
/* Find with the given name the tag symbol visible in the current scope */
|
||||
|
||||
SymEntry FindStructField (const Type* TypeArray, const char* Name);
|
||||
/* Find a struct/union field in the fields list.
|
||||
|
15
test/err/bug2304-var-use.c
Normal file
15
test/err/bug2304-var-use.c
Normal file
@ -0,0 +1,15 @@
|
||||
/* Bug 2304 - Visibility of objects/functions undeclared in file scope but 'extern'-declared in unrelated block scopes */
|
||||
|
||||
void f1(void)
|
||||
{
|
||||
extern int a;
|
||||
}
|
||||
|
||||
/* 'a' is still invisible in the file scope */
|
||||
|
||||
int main(void)
|
||||
{
|
||||
return a * 0; /* Usage of 'a' should be an error */
|
||||
}
|
||||
|
||||
int a = 42;
|
@ -133,6 +133,12 @@ $(WORKDIR)/goto.$1.$2.prg: goto.c $(ISEQUAL) | $(WORKDIR)
|
||||
$(CC65) -t sim$2 -$1 -o $$@ $$< 2>$(WORKDIR)/goto.$1.$2.out
|
||||
$(ISEQUAL) $(WORKDIR)/goto.$1.$2.out goto.ref
|
||||
|
||||
# this one requires failure with --std=c89, it fails with --std=cc65 due to
|
||||
# stricter checks
|
||||
$(WORKDIR)/bug2304-implicit-func.$1.$2.prg: bug2304-implicit-func.c | $(WORKDIR)
|
||||
$(if $(QUIET),echo misc/bug2304-implicit-func.$1.$2.prg)
|
||||
$(NOT) $(CC65) --standard c89 -t sim$2 -$1 -o $$@ $$< $(NULLERR)
|
||||
|
||||
# should not compile until 3-byte struct by value tests are re-enabled
|
||||
$(WORKDIR)/struct-by-value.$1.$2.prg: struct-by-value.c | $(WORKDIR)
|
||||
$(if $(QUIET),echo misc/struct-by-value.$1.$2.prg)
|
||||
|
21
test/misc/bug2304-implicit-func.c
Normal file
21
test/misc/bug2304-implicit-func.c
Normal file
@ -0,0 +1,21 @@
|
||||
/* Bug 2304 - Visibility of objects/functions undeclared in file scope but 'extern'-declared in unrelated block scopes */
|
||||
|
||||
/* This one should fail even in C89 */
|
||||
|
||||
void f1(void)
|
||||
{
|
||||
extern unsigned int f();
|
||||
}
|
||||
|
||||
/* 'f' is still invisible in the file scope */
|
||||
|
||||
int main(void)
|
||||
{
|
||||
f(); /* Should be a conflict since the implicit function type is incompatible */
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int f()
|
||||
{
|
||||
return 42;
|
||||
}
|
Loading…
Reference in New Issue
Block a user