summaryrefslogtreecommitdiff
path: root/miniany/cc.c
diff options
context:
space:
mode:
Diffstat (limited to 'miniany/cc.c')
-rw-r--r--miniany/cc.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/miniany/cc.c b/miniany/cc.c
index 44cdd76..22781a2 100644
--- a/miniany/cc.c
+++ b/miniany/cc.c
@@ -365,6 +365,7 @@ struct Symbol {
int type; /* type of variable when class is SYMBOL_CLASS_VARIABLE */
struct Symbol *next; /* pointer to next symbol */
int return_type; /* return type when class is SYMBOL_CLASS_FUNCTION */
+ int seen_return; /* whether we saw a return in the definiton of a function (SYMBOL_CLASS_FUNCTION) */
};
struct Symbol *createSymbol( int class, char *s )
@@ -526,6 +527,7 @@ struct Parser {
int token;
struct Scanner *scanner;
struct Scope *global_scope;
+ struct Symbol *current_function;
int debug;
};
@@ -1099,6 +1101,7 @@ struct Parser *createParser( )
parser->scanner = createScanner( );
parser->global_scope = createScope( "global" );
parser->debug = 0;
+ parser->current_function = NULL;
return parser;
}
@@ -1561,11 +1564,30 @@ void parseDo( struct Compiler *compiler )
void parseReturn( struct Compiler *compiler )
{
struct Parser *parser;
+ struct Symbol *sym;
struct ASTnode *node;
parser = compiler->parser;
+ sym = parser->current_function;
+ if( sym == NULL ) {
+ scannerPrintErrorHeader( parser->scanner );
+ putstring( "return outside a function" );
+ putnl( );
+ exit( EXIT_FAILURE );
+ }
+ if( sym->return_type == S_VOID ) {
+ scannerPrintErrorHeader( parser->scanner );
+ putstring( "return inside function '" ) ;
+ putstring( sym->name );
+ putstring( "' can not return any value" );
+ putnl( );
+ exit( EXIT_FAILURE );
+ }
+ sym->seen_return = 1;
+
parserExpect( parser, S_RETURN, "return" );
node = parseExpression( parser, 0 );
+ /* TODO: verify that sym->return_type fits to the type of the expression */
generateFromAST( compiler->generator, node, NOREG );
freeASTnode( node );
parserExpect( parser, S_SEMICOLON, ";" );
@@ -1632,6 +1654,8 @@ void parseFunctionDeclaration( struct Compiler *compiler )
sym = createSymbol( SYMBOL_CLASS_FUNCTION, parser->scanner->ident );
insertSymbol( parser->global_scope, sym );
sym->return_type = type;
+ sym->seen_return = 0;
+ parser->current_function = sym;
} else {
scannerPrintErrorHeader( parser->scanner );
putstring( "duplicate global symbol '" );
@@ -1653,7 +1677,18 @@ void parseFunctionDeclaration( struct Compiler *compiler )
parserExpect( parser, S_LPAREN, "(" );
/* TODO: parse parameter list */
parserExpect( parser, S_RPAREN, ")" );
+
parseStatementBlock( compiler );
+
+ if( sym->return_type != S_VOID && !sym->seen_return ) {
+ scannerPrintErrorHeader( parser->scanner );
+ putstring( "return excpected in non-void function '" );
+ putstring( sym->name );
+ putstring( "'" );
+ putnl( );
+ exit( EXIT_FAILURE );
+ }
+
putstring( "pop ebp" ); putnl( );
putstring( "ret" ); putnl( );
genFreeAllRegs( compiler->generator );