1
0
mirror of https://github.com/cc65/cc65.git synced 2025-02-05 20:31:53 +00:00

Add a warning if a function returning something does not contain a return

statement.


git-svn-id: svn://svn.cc65.org/cc65/trunk@4095 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz 2009-08-31 13:18:49 +00:00
parent 1ea503a036
commit 0a9c7484ad
3 changed files with 45 additions and 29 deletions

View File

@ -6,10 +6,10 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000-2008 Ullrich von Bassewitz */ /* (C) 2000-2009, Ullrich von Bassewitz */
/* Roemerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* This software is provided 'as-is', without any expressed or implied */
@ -71,6 +71,7 @@ struct Function {
unsigned RetLab; /* Return code label */ unsigned RetLab; /* Return code label */
int TopLevelSP; /* SP at function top level */ int TopLevelSP; /* SP at function top level */
unsigned RegOffs; /* Register variable space offset */ unsigned RegOffs; /* Register variable space offset */
int HasRetStmt; /* Function has a return statement */
}; };
/* Pointer to current function */ /* Pointer to current function */
@ -79,7 +80,7 @@ Function* CurrentFunc = 0;
/*****************************************************************************/ /*****************************************************************************/
/* Subroutines working with struct Function */ /* Subroutines working with struct Function */
/*****************************************************************************/ /*****************************************************************************/
@ -98,6 +99,7 @@ static Function* NewFunction (struct SymEntry* Sym)
F->RetLab = GetLocalLabel (); F->RetLab = GetLocalLabel ();
F->TopLevelSP = 0; F->TopLevelSP = 0;
F->RegOffs = RegisterSpace; F->RegOffs = RegisterSpace;
F->HasRetStmt = 0;
/* Return the new structure */ /* Return the new structure */
return F; return F;
@ -153,6 +155,14 @@ int F_HasVoidReturn (const Function* F)
void F_HasReturn (Function* F)
/* Mark the function as having a return statement */
{
F->HasRetStmt = 1;
}
int F_IsVariadic (const Function* F) int F_IsVariadic (const Function* F)
/* Return true if this is a variadic function */ /* Return true if this is a variadic function */
{ {
@ -335,7 +345,6 @@ static void F_RestoreRegVars (Function* F)
void NewFunc (SymEntry* Func) void NewFunc (SymEntry* Func)
/* Parse argument declarations and function body. */ /* Parse argument declarations and function body. */
{ {
int HadReturn;
SymEntry* Param; SymEntry* Param;
/* Get the function descriptor from the function entry */ /* Get the function descriptor from the function entry */
@ -467,13 +476,15 @@ void NewFunc (SymEntry* Func)
CurrentFunc->TopLevelSP = StackPtr; CurrentFunc->TopLevelSP = StackPtr;
/* Now process statements in this block */ /* Now process statements in this block */
HadReturn = 0; while (CurTok.Tok != TOK_RCURLY && CurTok.Tok != TOK_CEOF) {
while (CurTok.Tok != TOK_RCURLY) { Statement (0);
if (CurTok.Tok != TOK_CEOF) { }
HadReturn = Statement (0);
} else { /* If this is not a void function, output a warning if we didn't see a
break; * return statement.
} */
if (!F_HasVoidReturn (CurrentFunc) && !CurrentFunc->HasRetStmt) {
Warning ("Control reaches end of non-void function");
} }
/* Output the function exit code label */ /* Output the function exit code label */

View File

@ -6,10 +6,10 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 1998-2006 Ullrich von Bassewitz */ /* (C) 1998-2009, Ullrich von Bassewitz */
/* Römerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* This software is provided 'as-is', without any expressed or implied */
@ -73,6 +73,9 @@ Type* F_GetReturnType (Function* F);
int F_HasVoidReturn (const Function* F); int F_HasVoidReturn (const Function* F);
/* Return true if the function does not have a return value */ /* Return true if the function does not have a return value */
void F_HasReturn (Function* F);
/* Mark the function as having a return statement */
int F_IsVariadic (const Function* F); int F_IsVariadic (const Function* F);
/* Return true if this is a variadic function */ /* Return true if this is a variadic function */

View File

@ -6,10 +6,10 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 1998-2008 Ullrich von Bassewitz */ /* (C) 1998-2009, Ullrich von Bassewitz */
/* Roemerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* This software is provided 'as-is', without any expressed or implied */
@ -292,17 +292,16 @@ static void ReturnStatement (void)
NextToken (); NextToken ();
if (CurTok.Tok != TOK_SEMI) { if (CurTok.Tok != TOK_SEMI) {
/* Check if the function has a return value declared */
if (F_HasVoidReturn (CurrentFunc)) {
Error ("Returning a value in function with return type void");
}
/* Evaluate the return expression */ /* Evaluate the return expression */
hie0 (&Expr); hie0 (&Expr);
/* Ignore the return expression if the function returns void */ /* If we return something in a void function, print an error and
if (!F_HasVoidReturn (CurrentFunc)) { * ignore the value. Otherwise convert the value to the type of the
* return.
*/
if (F_HasVoidReturn (CurrentFunc)) {
Error ("Returning a value in function with return type void");
} else {
/* Convert the return value to the type of the function result */ /* Convert the return value to the type of the function result */
TypeConversion (&Expr, F_GetReturnType (CurrentFunc)); TypeConversion (&Expr, F_GetReturnType (CurrentFunc));
@ -314,6 +313,9 @@ static void ReturnStatement (void)
Error ("Function `%s' must return a value", F_GetFuncName (CurrentFunc)); Error ("Function `%s' must return a value", F_GetFuncName (CurrentFunc));
} }
/* Mark the function as having a return statement */
F_HasReturn (CurrentFunc);
/* Cleanup the stack in case we're inside a block with locals */ /* Cleanup the stack in case we're inside a block with locals */
g_space (StackPtr - F_GetTopLevelSP (CurrentFunc)); g_space (StackPtr - F_GetTopLevelSP (CurrentFunc));