Merge pull request #381 from pfusik/static-forward-decl
"static" forward declarations
This commit is contained in:
@@ -157,7 +157,7 @@ static void Parse (void)
|
|||||||
CurTok.Tok == TOK_ASSIGN))) {
|
CurTok.Tok == TOK_ASSIGN))) {
|
||||||
|
|
||||||
/* We will allocate storage */
|
/* We will allocate storage */
|
||||||
Decl.StorageClass |= SC_STORAGE | SC_DEF;
|
Decl.StorageClass |= SC_STORAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this is a function declarator that is not followed by a comma
|
/* If this is a function declarator that is not followed by a comma
|
||||||
@@ -190,6 +190,13 @@ static void Parse (void)
|
|||||||
/* Allow initialization */
|
/* Allow initialization */
|
||||||
if (CurTok.Tok == TOK_ASSIGN) {
|
if (CurTok.Tok == TOK_ASSIGN) {
|
||||||
|
|
||||||
|
/* This is a definition */
|
||||||
|
if (SymIsDef (Entry)) {
|
||||||
|
Error ("Global variable `%s' has already been defined",
|
||||||
|
Entry->Name);
|
||||||
|
}
|
||||||
|
Entry->Flags |= SC_DEF;
|
||||||
|
|
||||||
/* We cannot initialize types of unknown size, or
|
/* We cannot initialize types of unknown size, or
|
||||||
** void types in ISO modes.
|
** void types in ISO modes.
|
||||||
*/
|
*/
|
||||||
@@ -237,18 +244,14 @@ static void Parse (void)
|
|||||||
Entry->Flags &= ~(SC_STORAGE | SC_DEF);
|
Entry->Flags &= ~(SC_STORAGE | SC_DEF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate storage if it is still needed */
|
/* A global (including static) uninitialized variable
|
||||||
if (Entry->Flags & SC_STORAGE) {
|
** is only a tentative definition. For example, this is valid:
|
||||||
|
** int i;
|
||||||
/* Switch to the BSS segment */
|
** int i;
|
||||||
g_usebss ();
|
** static int j;
|
||||||
|
** static int j = 42;
|
||||||
/* Define a label */
|
** Code for these will be generated in FinishCompile.
|
||||||
g_defgloblabel (Entry->Name);
|
*/
|
||||||
|
|
||||||
/* Allocate space for uninitialized variable */
|
|
||||||
g_res (Size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -303,7 +306,7 @@ void Compile (const char* FileName)
|
|||||||
struct tm* TM;
|
struct tm* TM;
|
||||||
|
|
||||||
/* Since strftime is locale dependent, we need the abbreviated month names
|
/* Since strftime is locale dependent, we need the abbreviated month names
|
||||||
** in english.
|
** in English.
|
||||||
*/
|
*/
|
||||||
static const char MonthNames[12][4] = {
|
static const char MonthNames[12][4] = {
|
||||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||||
@@ -400,20 +403,26 @@ void Compile (const char* FileName)
|
|||||||
void FinishCompile (void)
|
void FinishCompile (void)
|
||||||
/* Emit literals, externals, debug info, do cleanup and optimizations */
|
/* Emit literals, externals, debug info, do cleanup and optimizations */
|
||||||
{
|
{
|
||||||
SymTable* SymTab;
|
SymEntry* Entry;
|
||||||
SymEntry* Func;
|
|
||||||
|
|
||||||
/* Walk over all functions, doing cleanup, optimizations ... */
|
/* Walk over all global symbols:
|
||||||
SymTab = GetGlobalSymTab ();
|
** - for functions do cleanup, optimizations ...
|
||||||
Func = SymTab->SymHead;
|
** - generate code for uninitialized global variables
|
||||||
while (Func) {
|
*/
|
||||||
if (SymIsOutputFunc (Func)) {
|
for (Entry = GetGlobalSymTab ()->SymHead; Entry; Entry = Entry->NextSym) {
|
||||||
|
if (SymIsOutputFunc (Entry)) {
|
||||||
/* Function which is defined and referenced or extern */
|
/* Function which is defined and referenced or extern */
|
||||||
MoveLiteralPool (Func->V.F.LitPool);
|
MoveLiteralPool (Entry->V.F.LitPool);
|
||||||
CS_MergeLabels (Func->V.F.Seg->Code);
|
CS_MergeLabels (Entry->V.F.Seg->Code);
|
||||||
RunOpt (Func->V.F.Seg->Code);
|
RunOpt (Entry->V.F.Seg->Code);
|
||||||
|
} else if ((Entry->Flags & (SC_STORAGE | SC_DEF | SC_STATIC)) == (SC_STORAGE | SC_STATIC)) {
|
||||||
|
/* Tentative definition of uninitialized global variable */
|
||||||
|
g_usebss ();
|
||||||
|
g_defgloblabel (Entry->Name);
|
||||||
|
g_res (SizeOf (Entry->Type));
|
||||||
|
/* Mark as defined, so that it will be exported not imported */
|
||||||
|
Entry->Flags |= SC_DEF;
|
||||||
}
|
}
|
||||||
Func = Func->NextSym;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Output the literal pool */
|
/* Output the literal pool */
|
||||||
|
|||||||
@@ -821,7 +821,7 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* An extern declaration must not change the current linkage. */
|
/* An extern declaration must not change the current linkage. */
|
||||||
if (IsFunc || (Flags & (SC_EXTERN | SC_DEF)) == SC_EXTERN) {
|
if (IsFunc || (Flags & (SC_EXTERN | SC_STORAGE)) == SC_EXTERN) {
|
||||||
Flags &= ~SC_EXTERN;
|
Flags &= ~SC_EXTERN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
18
test/err/duplicate-global-static.c
Normal file
18
test/err/duplicate-global-static.c
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
!!DESCRIPTION!! global duplicated with static variable
|
||||||
|
!!ORIGIN!! cc65 regression tests
|
||||||
|
!!LICENCE!! Public Domain
|
||||||
|
!!AUTHOR!! Piotr Fusik
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
see: https://github.com/cc65/cc65/issues/191
|
||||||
|
*/
|
||||||
|
|
||||||
|
int n = 0;
|
||||||
|
static int n = 0; /* should give an error */
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return n;
|
||||||
|
}
|
||||||
20
test/err/duplicate-global.c
Normal file
20
test/err/duplicate-global.c
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
!!DESCRIPTION!! duplicate globals
|
||||||
|
!!ORIGIN!! cc65 regression tests
|
||||||
|
!!LICENCE!! Public Domain
|
||||||
|
!!AUTHOR!! Piotr Fusik
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
see: https://github.com/cc65/cc65/issues/191
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma warn(error, on)
|
||||||
|
|
||||||
|
int n = 0;
|
||||||
|
int n = 0; /* should give an error */
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return n;
|
||||||
|
}
|
||||||
18
test/err/duplicate-static-global.c
Normal file
18
test/err/duplicate-static-global.c
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
!!DESCRIPTION!! static duplicated with global variable
|
||||||
|
!!ORIGIN!! cc65 regression tests
|
||||||
|
!!LICENCE!! Public Domain
|
||||||
|
!!AUTHOR!! Piotr Fusik
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
see: https://github.com/cc65/cc65/issues/191
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int n = 0;
|
||||||
|
int n = 0; /* should give an error */
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return n;
|
||||||
|
}
|
||||||
20
test/err/duplicate-static.c
Normal file
20
test/err/duplicate-static.c
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
!!DESCRIPTION!! duplicate static variables
|
||||||
|
!!ORIGIN!! cc65 regression tests
|
||||||
|
!!LICENCE!! Public Domain
|
||||||
|
!!AUTHOR!! Piotr Fusik
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
see: https://github.com/cc65/cc65/issues/191
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma warn(error, on)
|
||||||
|
|
||||||
|
static int n = 0;
|
||||||
|
static int n = 0; /* should give an error */
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return n;
|
||||||
|
}
|
||||||
35
test/val/static-fwd-decl.c
Normal file
35
test/val/static-fwd-decl.c
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
!!DESCRIPTION!! static forward declarations
|
||||||
|
!!ORIGIN!! cc65 regression tests
|
||||||
|
!!LICENCE!! Public Domain
|
||||||
|
!!AUTHOR!! Bob Andrews
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
see: https://github.com/cc65/cc65/issues/204
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma warn(error, on)
|
||||||
|
|
||||||
|
typedef struct _DIRMENU
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
struct _DIRMENU *dest;
|
||||||
|
} DIRMENU;
|
||||||
|
|
||||||
|
static DIRMENU rmenu;
|
||||||
|
|
||||||
|
static DIRMENU lmenu = {
|
||||||
|
"left",
|
||||||
|
&rmenu
|
||||||
|
};
|
||||||
|
|
||||||
|
static DIRMENU rmenu = {
|
||||||
|
"right",
|
||||||
|
&lmenu
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return lmenu.dest == &rmenu && rmenu.dest == &lmenu ? 0 : 1;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user