diff --git a/doc/cc65.sgml b/doc/cc65.sgml
index 5c074991b7..d08e8418d8 100644
--- a/doc/cc65.sgml
+++ b/doc/cc65.sgml
@@ -824,6 +824,11 @@ and the one defined by the ISO standard:
         as it sounds, since the 6502 has so few registers that it isn't
         possible to keep values in registers anyway.
         <p>
+<item>  In <tt/cc65/ mode, <tt/main()/ cannot be called recursively. If this
+        is necessary, the program must be compiled in <tt/c89/ or <tt/c99/ mode
+        using the <tt><ref id="option--standard" name="--standard"></tt>
+        command line option.
+        <p>
 </itemize>
 
 There may be some more minor differences I'm currently not aware of. The
diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c
index 45823fab6d..166176f5e0 100644
--- a/src/cc65/codegen.c
+++ b/src/cc65/codegen.c
@@ -507,13 +507,13 @@ void g_enter (unsigned flags, unsigned argsize)
 
 
 
-void g_leave (int IsMainFunc)
+void g_leave (int DoCleanup)
 /* Function epilogue */
 {
-    /* In the main function nothing has to be dropped because the program
-    ** is terminated anyway.
+    /* In the main function in cc65 mode nothing has to be dropped because
+    ** the program is terminated anyway.
     */
-    if (!IsMainFunc) {
+    if (DoCleanup) {
         /* How many bytes of locals do we have to drop? */
         unsigned ToDrop = (unsigned) -StackPtr;
 
diff --git a/src/cc65/codegen.h b/src/cc65/codegen.h
index b95df5cfba..734c95372d 100644
--- a/src/cc65/codegen.h
+++ b/src/cc65/codegen.h
@@ -247,7 +247,7 @@ void g_scale (unsigned flags, long val);
 void g_enter (unsigned flags, unsigned argsize);
 /* Function prologue */
 
-void g_leave (int IsMainFunc);
+void g_leave (int DoCleanup);
 /* Function epilogue */
 
 
diff --git a/src/cc65/expr.c b/src/cc65/expr.c
index f6c681db87..2939ab1cc3 100644
--- a/src/cc65/expr.c
+++ b/src/cc65/expr.c
@@ -1219,9 +1219,6 @@ static void Primary (ExprDesc* E)
             /* Is the symbol known? */
             if (Sym) {
 
-                /* We found the symbol - skip the name token */
-                NextToken ();
-
                 /* Check for illegal symbol types */
                 CHECK ((Sym->Flags & SC_TYPEMASK) != SC_LABEL);
                 if ((Sym->Flags & SC_TYPEMASK) == SC_TYPEDEF) {
@@ -1230,9 +1227,14 @@ static void Primary (ExprDesc* E)
                     /* Assume an int type to make E valid */
                     E->Flags = E_LOC_STACK | E_RTYPE_LVAL;
                     E->Type  = type_int;
+                    /* Skip the erroneous token */
+                    NextToken ();
                     break;
                 }
 
+                /* Skip the name token */
+                NextToken ();
+
                 /* Mark the symbol as referenced */
                 Sym->Flags |= SC_REF;
 
@@ -1286,7 +1288,23 @@ static void Primary (ExprDesc* E)
                 ** rvalue, too, because we cannot store anything in a function.
                 ** So fix the flags depending on the type.
                 */
-                if (IsTypeArray (E->Type) || IsTypeFunc (E->Type)) {
+                if (IsTypeArray (E->Type)) {
+                    ED_AddrExpr (E);
+                } else if (IsTypeFunc (E->Type)) {
+                    /* In cc65 mode we cannot call or take the address of
+                    ** main().
+                    */
+                    if (IS_Get (&Standard) == STD_CC65 &&
+                        strcmp (Sym->Name, "main") == 0) {
+                        /* Adjust the error message depending on a call or an
+                        ** address operation.
+                        */
+                        if (CurTok.Tok == TOK_LPAREN) {
+                            Error ("'main' must not be called recursively");
+                        } else {
+                            Error ("The address of 'main' cannot be taken");
+                        }
+                    }
                     ED_AddrExpr (E);
                 }
 
diff --git a/src/cc65/function.c b/src/cc65/function.c
index d5cab3993e..fed0349dde 100644
--- a/src/cc65/function.c
+++ b/src/cc65/function.c
@@ -646,13 +646,17 @@ void NewFunc (SymEntry* Func, FuncDesc* D)
     /* Output the function exit code label */
     g_defcodelabel (F_GetRetLab (CurrentFunc));
 
-    /* Restore the register variables (not necessary for main function) */
-    if (!F_IsMainFunc (CurrentFunc)) {
+    /* Restore the register variables (not necessary for the main function in
+    ** cc65 mode)
+    */
+    int CleanupOnExit = (IS_Get (&Standard) != STD_CC65) ||
+                        !F_IsMainFunc (CurrentFunc);
+    if (CleanupOnExit) {
         F_RestoreRegVars (CurrentFunc);
     }
 
     /* Generate the exit code */
-    g_leave (F_IsMainFunc (CurrentFunc));
+    g_leave (CleanupOnExit);
 
     /* Emit references to imports/exports */
     EmitExternals ();
diff --git a/src/cc65/locals.c b/src/cc65/locals.c
index c4d0aa25b2..08e41918e9 100644
--- a/src/cc65/locals.c
+++ b/src/cc65/locals.c
@@ -111,6 +111,13 @@ static void ParseRegisterDecl (Declarator* Decl, int Reg)
     /* Get the size of the variable */
     unsigned Size = SizeOf (Decl->Type);
 
+    /* Check if this is the main function and we are in cc65 mode. If so, we
+    ** won't save the old contents of the register variables since in cc65
+    ** mode main() may not be called recursively.
+    */
+    int SaveRegVars = (IS_Get (&Standard) != STD_CC65) ||
+                      !F_IsMainFunc (CurrentFunc);
+
     /* Check for an optional initialization */
     if (CurTok.Tok == TOK_ASSIGN) {
 
@@ -126,13 +133,13 @@ static void ParseRegisterDecl (Declarator* Decl, int Reg)
         /* Save the current contents of the register variable on stack. This is
         ** not necessary for the main function.
         */
-        if (!F_IsMainFunc (CurrentFunc)) {
+        if (SaveRegVars) {
             g_save_regvars (Reg, Size);
         }
 
         /* Add the symbol to the symbol table. We do that now, because for
         ** register variables the current stack pointer is implicitly used
-        ** as location for the save area (unused in case of main()).
+        ** as location for the save area (maybe unused in case of main()).
         */
         Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, Reg);
 
@@ -187,14 +194,14 @@ static void ParseRegisterDecl (Declarator* Decl, int Reg)
         /* Save the current contents of the register variable on stack. This is
         ** not necessary for the main function.
         */
-        if (!F_IsMainFunc (CurrentFunc)) {
+        if (SaveRegVars) {
             F_AllocLocalSpace (CurrentFunc);
             g_save_regvars (Reg, Size);
         }
 
         /* Add the symbol to the symbol table. We do that now, because for
         ** register variables the current stack pointer is implicitly used
-        ** as location for the save area (unused in case of main()).
+        ** as location for the save area (maybe unused in case of main()).
         */
         Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, Reg);
     }
diff --git a/targettest/atari/mem.c b/targettest/atari/mem.c
index bc70aded64..b15b215edf 100644
--- a/targettest/atari/mem.c
+++ b/targettest/atari/mem.c
@@ -21,6 +21,8 @@ unsigned int *MEMTOP = (unsigned int *)741;
 unsigned int *MEMLO = (unsigned int *)743;
 void *allocmem;
 
+void code(void) { }
+
 int main(void)
 {
   allocmem = malloc(257);
@@ -35,7 +37,7 @@ int main(void)
   printf("  MEMLO  = $%04X (%u)\n", *MEMLO, *MEMLO);
 
   printf("  ----------------------\n");
-  printf("  main:            $%04X  (code)\n", &main);
+  printf("  code:            $%04X  (code)\n", &code);
   printf("  data:            $%04X  (data)\n", &data);
   printf("  _dos_type:       $%04X  (bss)\n", &_dos_type);
   printf("  allocmem:        $%04X  (dyn. data)\n", allocmem);
diff --git a/targettest/pce/conio.c b/targettest/pce/conio.c
index 55f828f264..819e601be8 100644
--- a/targettest/pce/conio.c
+++ b/targettest/pce/conio.c
@@ -11,6 +11,8 @@ static char hex[16] = { "0123456789abcdef" };
 static char charbuf[0x20];
 static char colbuf[0x20];
 
+void func(void) { }
+
 void main(void)
 {
         int stackvar = 42;
@@ -65,7 +67,7 @@ void main(void)
                         p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15]
                 );
         }
-        memcpy(p, main, i = 0);     /* test that a zero length doesn't copy 64K */
+        memcpy(p, func, i = 0);     /* test that a zero length doesn't copy 64K */
 
         gotoxy(0,ysize - 1);
         for (i = 0; i < xsize; ++i) {
diff --git a/targettest/scanf-test.c b/targettest/scanf-test.c
index f17b62294d..e0ab957568 100644
--- a/targettest/scanf-test.c
+++ b/targettest/scanf-test.c
@@ -159,12 +159,14 @@ static void Pause(void) {
 #endif
         }
 
+static void Nil() { }
+
 int main(void) {
         long n0;
         unsigned t;
         int c, n1 = 12345, n2, n3;
         char s1[80], s2[80];
-        void *p1 = main, *p2 = main, *p3 = main, *p4 = main;
+        void *p1 = Nil, *p2 = Nil, *p3 = Nil, *p4 = Nil;
 
 #ifndef USE_STDIO
         clrscr();
diff --git a/test/ref/custom-reference-error.c b/test/ref/custom-reference-error.c
index e98fb024dd..455e0276de 100644
--- a/test/ref/custom-reference-error.c
+++ b/test/ref/custom-reference-error.c
@@ -22,6 +22,5 @@ return_t main(int argc, char* argv[])
     n = 0;                /* produce an error */
     /* produce a warning */
 }
-
-int arr[main(0, 0)]; /* produce an error */
 int b = 0;
+int arr[b]; /* produce an error */
diff --git a/test/val/nullptr.c b/test/val/nullptr.c
index e64b82ee27..a5b72e8c5e 100644
--- a/test/val/nullptr.c
+++ b/test/val/nullptr.c
@@ -28,6 +28,8 @@ struct S {
         } \
     } while(0);
 
+void func() { }
+
 int main()
 {
     int a;
@@ -60,7 +62,7 @@ int main()
     TEST_NON_NULL(((struct S*)&a)->a)
 
     /* Non-null pointer obtained with cast and -> */
-    TEST_NON_NULL(((struct S*)&main)->a)
+    TEST_NON_NULL(((struct S*)&func)->a)
 
     if (failures != 0)
     {