From 5d0a33e157fcab9612479162024dfc73c29e2952 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 28 Jul 2025 21:43:26 +0200 Subject: [PATCH] Apply the implicit conversions in return statements Fixes #640 Signed-off-by: Roberto Raggi --- src/parser/cxx/parser.cc | 13 +++++++++++++ src/parser/cxx/parser.h | 1 + src/parser/cxx/type_checker.cc | 24 ++++++++++++++++++++++++ src/parser/cxx/type_checker.h | 2 ++ 4 files changed, 40 insertions(+) diff --git a/src/parser/cxx/parser.cc b/src/parser/cxx/parser.cc index 25aa1b23..c570fd2f 100644 --- a/src/parser/cxx/parser.cc +++ b/src/parser/cxx/parser.cc @@ -3790,6 +3790,8 @@ auto Parser::parse_return_statement(StatementAST*& yyast) -> bool { parse_expr_or_braced_init_list(ast->expression, ExprContext{}); expect(TokenKind::T_SEMICOLON, ast->semicolonLoc); + + check(ast); } return true; @@ -9808,6 +9810,17 @@ void Parser::check(ExpressionAST* ast) { check(ast); } +void Parser::check(StatementAST* ast) { + if (binder_.inTemplate()) return; + auto returnStatement = ast_cast(ast); + if (!returnStatement) return; + + TypeChecker check{unit}; + check.setScope(scope()); + check.setReportErrors(config().checkTypes); + check.checkReturnStatement(returnStatement); +} + auto Parser::getFunction(Scope* scope, const Name* name, const Type* type) -> FunctionSymbol* { auto parentScope = scope; diff --git a/src/parser/cxx/parser.h b/src/parser/cxx/parser.h index a7b10a7b..bbb14c3c 100644 --- a/src/parser/cxx/parser.h +++ b/src/parser/cxx/parser.h @@ -789,6 +789,7 @@ class Parser final { void setScope(ScopedSymbol* symbol); void check(ExpressionAST* ast); + void check(StatementAST* ast); // lookup diff --git a/src/parser/cxx/type_checker.cc b/src/parser/cxx/type_checker.cc index 01dfb03d..dc7d9c09 100644 --- a/src/parser/cxx/type_checker.cc +++ b/src/parser/cxx/type_checker.cc @@ -2262,4 +2262,28 @@ auto TypeChecker::Visitor::check_pseudo_destructor_access( return true; } +void TypeChecker::checkReturnStatement(ReturnStatementAST* ast) { + const Type* targetType = nullptr; + for (auto current = scope_; current; current = current->parent()) { + if (auto function = symbol_cast(current->owner())) { + if (auto functionType = type_cast(function->type())) { + targetType = functionType->returnType(); + } + break; + } + + if (auto lambda = symbol_cast(current->owner())) { + if (auto functionType = type_cast(lambda->type())) { + targetType = functionType->returnType(); + } + break; + } + } + + if (!targetType) return; + + Visitor visitor{*this}; + (void)visitor.implicit_conversion(ast->expression, targetType); +} + } // namespace cxx diff --git a/src/parser/cxx/type_checker.h b/src/parser/cxx/type_checker.h index 228aad1d..e2ae0188 100644 --- a/src/parser/cxx/type_checker.h +++ b/src/parser/cxx/type_checker.h @@ -45,6 +45,8 @@ class TypeChecker { void check(ExpressionAST* ast); + void checkReturnStatement(ReturnStatementAST* ast); + private: struct Visitor;