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:
parent
1ea503a036
commit
0a9c7484ad
@ -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 */
|
||||||
|
@ -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 */
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user