🐞 Bugfix: Ensure that typed functions contain a return statement (#17)
* Parser - Added TODO for checking for non-`void` function's return statements * Parser - If a `ReturnStmt` is not found after calling `parseFuncDef()` * Parser - Added a FIXME comment that needs to be completed soon * Parser - Only check that a `ReturnStmt` is present in a function definition when `wantsBody` is true ELSE we'd expect it for `efunc` `extern`'d statements - Fixed a unit test which had a missing `return <expr>` - Added a unit test which tests for a function definition with a body with a non-void return type that it DOES fail - Removed two now-completed TODOs and FIXMEs Test cases - Fixed test case in `typecheck/simple_function_call.t` to now include the required `return <expr>` statements
This commit is contained in:
parent
4c99b56677
commit
ddedc0d806
|
@ -1600,6 +1600,30 @@ public final class Parser
|
|||
/* Will consume the `}` (or `;` if wantsBody-false) */
|
||||
funcDefPair pair = parseFuncDef(wantsBody);
|
||||
|
||||
/**
|
||||
* If this function definition has a body (i.e. `wantsBody == true`)
|
||||
* and if the return type is non-void, THEN ensure we have a `ReturnStmt`
|
||||
* (return statement)
|
||||
*/
|
||||
if(wantsBody && type != "void")
|
||||
{
|
||||
bool hasReturn;
|
||||
foreach(Statement stmt; pair.bodyStatements)
|
||||
{
|
||||
if(cast(ReturnStmt)stmt)
|
||||
{
|
||||
hasReturn = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Error if no return statement exists
|
||||
if(!hasReturn)
|
||||
{
|
||||
expect("Function '"~identifier~"' declared with return type does not contain a return statement");
|
||||
}
|
||||
}
|
||||
|
||||
generated = new Function(identifier, type, pair.bodyStatements, pair.params);
|
||||
|
||||
import std.stdio;
|
||||
|
@ -2736,6 +2760,8 @@ int thing()
|
|||
{
|
||||
int discardExpr = function(&j);
|
||||
int** l;
|
||||
|
||||
return 0;
|
||||
}
|
||||
`;
|
||||
LexerInterface currentLexer = new BasicLexer(sourceCode);
|
||||
|
@ -3015,4 +3041,52 @@ void function()
|
|||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function test case
|
||||
*
|
||||
* Test: A function of a non-void return type
|
||||
* must have a return statement
|
||||
*/
|
||||
unittest
|
||||
{
|
||||
string sourceCode = `
|
||||
module myModule;
|
||||
|
||||
int wrongFunction()
|
||||
{
|
||||
|
||||
}
|
||||
`;
|
||||
|
||||
LexerInterface currentLexer = new BasicLexer(sourceCode);
|
||||
try
|
||||
{
|
||||
(cast(BasicLexer)currentLexer).performLex();
|
||||
assert(true);
|
||||
}
|
||||
catch(LexerException e)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
|
||||
Parser parser = new Parser(currentLexer);
|
||||
|
||||
try
|
||||
{
|
||||
Module modulle = parser.parse();
|
||||
|
||||
assert(false);
|
||||
}
|
||||
catch(ParserException e)
|
||||
{
|
||||
// TODO: Try make errors specific enough to yank them out
|
||||
assert(true);
|
||||
}
|
||||
catch(TError)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
|
@ -5,15 +5,15 @@ j = 2+func(j,test());
|
|||
|
||||
int func(int x1, byte x2)
|
||||
{
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
byte t2()
|
||||
{
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
byte test()
|
||||
{
|
||||
|
||||
return 1;
|
||||
}
|
Loading…
Reference in New Issue