]> git.sur5r.net Git - cc65/commitdiff
Merge pull request #381 from pfusik/static-forward-decl
authorOliver Schmidt <ol.sc@web.de>
Sun, 12 Mar 2017 17:26:14 +0000 (18:26 +0100)
committerGitHub <noreply@github.com>
Sun, 12 Mar 2017 17:26:14 +0000 (18:26 +0100)
"static" forward declarations

src/cc65/compile.c
src/cc65/symtab.c
test/err/duplicate-global-static.c [new file with mode: 0644]
test/err/duplicate-global.c [new file with mode: 0644]
test/err/duplicate-static-global.c [new file with mode: 0644]
test/err/duplicate-static.c [new file with mode: 0644]
test/val/static-fwd-decl.c [new file with mode: 0644]

index 9f1ab29f55a0a89d1945f8e649f11ccd357364cb..48a5c29d35adca95c566a0adf9f490b041ffbab9 100644 (file)
@@ -157,7 +157,7 @@ static void Parse (void)
                   CurTok.Tok == TOK_ASSIGN))) {
 
                 /* 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
@@ -190,6 +190,13 @@ static void Parse (void)
                 /* Allow initialization */
                 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
                     ** void types in ISO modes.
                     */
@@ -237,18 +244,14 @@ static void Parse (void)
                         Entry->Flags &= ~(SC_STORAGE | SC_DEF);
                     }
 
-                    /* Allocate storage if it is still needed */
-                    if (Entry->Flags & SC_STORAGE) {
-
-                        /* Switch to the BSS segment */
-                        g_usebss ();
-
-                        /* Define a label */
-                        g_defgloblabel (Entry->Name);
-
-                        /* Allocate space for uninitialized variable */
-                        g_res (Size);
-                    }
+                    /* A global (including static) uninitialized variable
+                    ** is only a tentative definition. For example, this is valid:
+                    ** int i;
+                    ** int i;
+                    ** static int j;
+                    ** static int j = 42;
+                    ** Code for these will be generated in FinishCompile.
+                    */
                 }
 
             }
@@ -303,7 +306,7 @@ void Compile (const char* FileName)
     struct tm*  TM;
 
     /* Since strftime is locale dependent, we need the abbreviated month names
-    ** in english.
+    ** in English.
     */
     static const char MonthNames[12][4] = {
         "Jan", "Feb", "Mar", "Apr", "May", "Jun",
@@ -400,20 +403,26 @@ void Compile (const char* FileName)
 void FinishCompile (void)
 /* Emit literals, externals, debug info, do cleanup and optimizations */
 {
-    SymTable* SymTab;
-    SymEntry* Func;
-
-    /* Walk over all functions, doing cleanup, optimizations ... */
-    SymTab = GetGlobalSymTab ();
-    Func   = SymTab->SymHead;
-    while (Func) {
-        if (SymIsOutputFunc (Func)) {
+    SymEntry* Entry;
+
+    /* Walk over all global symbols:
+    ** - for functions do cleanup, optimizations ...
+    ** - generate code for uninitialized global variables
+    */
+    for (Entry = GetGlobalSymTab ()->SymHead; Entry; Entry = Entry->NextSym) {
+        if (SymIsOutputFunc (Entry)) {
             /* Function which is defined and referenced or extern */
-            MoveLiteralPool (Func->V.F.LitPool);
-            CS_MergeLabels (Func->V.F.Seg->Code);
-            RunOpt (Func->V.F.Seg->Code);
+            MoveLiteralPool (Entry->V.F.LitPool);
+            CS_MergeLabels (Entry->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 */
index fdf45987370581f3d833104d92f937c4080b7d70..3275332c5490c68b89ab7a5c4b6e560716574144 100644 (file)
@@ -821,7 +821,7 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
         }
 
         /* 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;
         }
 
diff --git a/test/err/duplicate-global-static.c b/test/err/duplicate-global-static.c
new file mode 100644 (file)
index 0000000..6aa27f5
--- /dev/null
@@ -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;
+}
diff --git a/test/err/duplicate-global.c b/test/err/duplicate-global.c
new file mode 100644 (file)
index 0000000..bd4fcc2
--- /dev/null
@@ -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;
+}
diff --git a/test/err/duplicate-static-global.c b/test/err/duplicate-static-global.c
new file mode 100644 (file)
index 0000000..6e5e70a
--- /dev/null
@@ -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;
+}
diff --git a/test/err/duplicate-static.c b/test/err/duplicate-static.c
new file mode 100644 (file)
index 0000000..394cc1e
--- /dev/null
@@ -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;
+}
diff --git a/test/val/static-fwd-decl.c b/test/val/static-fwd-decl.c
new file mode 100644 (file)
index 0000000..420640d
--- /dev/null
@@ -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;
+}