From a75c766f80126525e8dfa525b32252ba38b17b26 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 30 Oct 2021 20:54:23 +0200 Subject: cc: some proper checking of return types and some primitive check for missing or superflous return statements --- miniany/cc.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'miniany/cc.c') 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 ); -- cgit v1.2.3-54-g00ecf