diff --git a/doc/cc65.sgml b/doc/cc65.sgml index 2219ccf6a..8dd6d0202 100644 --- a/doc/cc65.sgml +++ b/doc/cc65.sgml @@ -823,6 +823,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.
+
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 45823fab6..166176f5e 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 b95df5cfb..734c95372 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 f6c681db8..2939ab1cc 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 d5cab3993..fed0349dd 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 c4d0aa25b..08e41918e 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/test/ref/custom-reference-error.c b/test/ref/custom-reference-error.c
index e98fb024d..455e0276d 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 e64b82ee2..a5b72e8c5 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)
{