🐞 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) */
|
/* Will consume the `}` (or `;` if wantsBody-false) */
|
||||||
funcDefPair pair = parseFuncDef(wantsBody);
|
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);
|
generated = new Function(identifier, type, pair.bodyStatements, pair.params);
|
||||||
|
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
|
@ -2736,6 +2760,8 @@ int thing()
|
||||||
{
|
{
|
||||||
int discardExpr = function(&j);
|
int discardExpr = function(&j);
|
||||||
int** l;
|
int** l;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
LexerInterface currentLexer = new BasicLexer(sourceCode);
|
LexerInterface currentLexer = new BasicLexer(sourceCode);
|
||||||
|
@ -3015,4 +3041,52 @@ void function()
|
||||||
{
|
{
|
||||||
assert(false);
|
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)
|
int func(int x1, byte x2)
|
||||||
{
|
{
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte t2()
|
byte t2()
|
||||||
{
|
{
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte test()
|
byte test()
|
||||||
{
|
{
|
||||||
|
return 1;
|
||||||
}
|
}
|
Loading…
Reference in New Issue