X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Ffunction.c;h=8944d10077583c722124f0b19c75a8c5cf5f0921;hb=112ae0e3db511ddd92e769c11328646ebe2a6240;hp=9c2c3f45d26c0acc27437ea0ac39feff9a1cf22f;hpb=dff0e864589aa8871b7b4e271813cb2ac3b5dedd;p=cc65 diff --git a/src/cc65/function.c b/src/cc65/function.c index 9c2c3f45d..8944d1007 100644 --- a/src/cc65/function.c +++ b/src/cc65/function.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2000-2008 Ullrich von Bassewitz */ -/* Roemerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2000-2009, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -62,15 +62,24 @@ +/* Enumeration for function flags */ +typedef enum { + FF_NONE = 0x0000, + FF_HAS_RETURN = 0x0001, /* Function has a return statement */ + FF_IS_MAIN = 0x0002, /* This is the main function */ + FF_VOID_RETURN = 0x0004, /* Function returning void */ +} funcflags_t; + /* Structure that holds all data needed for function activation */ struct Function { struct SymEntry* FuncEntry; /* Symbol table entry */ - Type* ReturnType; /* Function return type */ + Type* ReturnType; /* Function return type */ struct FuncDesc* Desc; /* Function descriptor */ - int Reserved; /* Reserved local space */ - unsigned RetLab; /* Return code label */ - int TopLevelSP; /* SP at function top level */ + int Reserved; /* Reserved local space */ + unsigned RetLab; /* Return code label */ + int TopLevelSP; /* SP at function top level */ unsigned RegOffs; /* Register variable space offset */ + funcflags_t Flags; /* Function flags */ }; /* Pointer to current function */ @@ -79,7 +88,7 @@ Function* CurrentFunc = 0; /*****************************************************************************/ -/* Subroutines working with struct Function */ +/* Subroutines working with struct Function */ /*****************************************************************************/ @@ -98,6 +107,7 @@ static Function* NewFunction (struct SymEntry* Sym) F->RetLab = GetLocalLabel (); F->TopLevelSP = 0; F->RegOffs = RegisterSpace; + F->Flags = IsTypeVoid (F->ReturnType) ? FF_VOID_RETURN : FF_NONE; /* Return the new structure */ return F; @@ -148,7 +158,31 @@ Type* F_GetReturnType (Function* F) int F_HasVoidReturn (const Function* F) /* Return true if the function does not have a return value */ { - return IsTypeVoid (F->ReturnType); + return (F->Flags & FF_VOID_RETURN) != 0; +} + + + +void F_ReturnFound (Function* F) +/* Mark the function as having a return statement */ +{ + F->Flags |= FF_HAS_RETURN; +} + + + +int F_HasReturn (const Function* F) +/* Return true if the function contains a return statement*/ +{ + return (F->Flags & FF_HAS_RETURN) != 0; +} + + + +int F_IsMainFunc (const Function* F) +/* Return true if this is the main function */ +{ + return (F->Flags & FF_IS_MAIN) != 0; } @@ -325,7 +359,7 @@ static void F_RestoreRegVars (Function* F) } - + /*****************************************************************************/ /* code */ /*****************************************************************************/ @@ -335,7 +369,6 @@ static void F_RestoreRegVars (Function* F) void NewFunc (SymEntry* Func) /* Parse argument declarations and function body. */ { - int HadReturn; SymEntry* Param; /* Get the function descriptor from the function entry */ @@ -347,28 +380,36 @@ void NewFunc (SymEntry* Func) /* Reenter the lexical level */ ReenterFunctionLevel (D); + /* Check if the function header contains unnamed parameters. These are + * only allowed in cc65 mode. + */ + if ((D->Flags & FD_UNNAMED_PARAMS) != 0 && (IS_Get (&Standard) != STD_CC65)) { + Error ("Parameter name omitted"); + } + /* Declare two special functions symbols: __fixargs__ and __argsize__. * The latter is different depending on the type of the function (variadic * or not). */ AddConstSym ("__fixargs__", type_uint, SC_DEF | SC_CONST, D->ParamSize); if (D->Flags & FD_VARIADIC) { - /* Variadic function. The variable must be const. */ - static const Type T[] = { TYPE(T_UCHAR | T_QUAL_CONST), TYPE(T_END) }; - AddLocalSym ("__argsize__", T, SC_DEF | SC_REF | SC_AUTO, 0); + /* Variadic function. The variable must be const. */ + static const Type T[] = { TYPE(T_UCHAR | T_QUAL_CONST), TYPE(T_END) }; + AddLocalSym ("__argsize__", T, SC_DEF | SC_REF | SC_AUTO, 0); } else { - /* Non variadic */ + /* Non variadic */ AddConstSym ("__argsize__", type_uchar, SC_DEF | SC_CONST, D->ParamSize); } /* Function body now defined */ Func->Flags |= SC_DEF; - /* Allocate code and data segments for this function */ - Func->V.F.Seg = PushSegments (Func); - /* Special handling for main() */ if (strcmp (Func->Name, "main") == 0) { + + /* Mark this as the main function */ + CurrentFunc->Flags |= FF_IS_MAIN; + /* Main cannot be a fastcall function */ if (IsQualFastcall (Func->Type)) { Error ("`main' cannot be declared as __fastcall__"); @@ -395,16 +436,22 @@ void NewFunc (SymEntry* Func) } } + /* Allocate code and data segments for this function */ + Func->V.F.Seg = PushSegments (Func); + + /* Allocate a new literal pool */ + PushLiteralPool (Func); + /* If this is a fastcall function, push the last parameter onto the stack */ if (IsQualFastcall (Func->Type) && D->ParamCount > 0) { - unsigned Flags; + unsigned Flags; - /* Fastcall functions may never have an ellipsis or the compiler is buggy */ - CHECK ((D->Flags & FD_VARIADIC) == 0); + /* Fastcall functions may never have an ellipsis or the compiler is buggy */ + CHECK ((D->Flags & FD_VARIADIC) == 0); - /* Generate the push */ - if (IsTypeFunc (D->LastParam->Type)) { + /* Generate the push */ + if (IsTypeFunc (D->LastParam->Type)) { /* Pointer to function */ Flags = CF_PTR; } else { @@ -447,7 +494,6 @@ void NewFunc (SymEntry* Func) /* Generate swap code */ g_swap_regvars (Param->V.R.SaveOffs, Reg, CheckedSizeOf (Param->Type)); - } } @@ -467,13 +513,15 @@ void NewFunc (SymEntry* Func) CurrentFunc->TopLevelSP = StackPtr; /* Now process statements in this block */ - HadReturn = 0; - while (CurTok.Tok != TOK_RCURLY) { - if (CurTok.Tok != TOK_CEOF) { - HadReturn = Statement (0); - } else { - break; - } + while (CurTok.Tok != TOK_RCURLY && CurTok.Tok != TOK_CEOF) { + Statement (0); + } + + /* If this is not a void function, output a warning if we didn't see a + * return statement. + */ + if (!F_HasVoidReturn (CurrentFunc) && !F_HasReturn (CurrentFunc)) { + Warning ("Control reaches end of non-void function"); } /* Output the function exit code label */ @@ -494,6 +542,9 @@ void NewFunc (SymEntry* Func) /* Eat the closing brace */ ConsumeRCurly (); + /* Restore the old literal pool, remembering the one for the function */ + Func->V.F.LitPool = PopLiteralPool (); + /* Switch back to the old segments */ PopSegments ();