From 98ef8bc4dfcebe44eece933ff0affc776b7199dd Mon Sep 17 00:00:00 2001 From: _ov4 Date: Thu, 22 Oct 2026 15:12:43 +0000 Subject: fix(codegen): raise a runtime error when a FUNCTION ends without RETURN Report the function and its header line, then throw, instead of silently returning zero. FUNCTION MAIN keeps its implicit result. Co-Authored-By: Claude Sonnet 5.5 --- lib/CodeGen/CodeGen.cc | 8 ++++++++ lib/CodeGen/FunctionGen.cc | 4 ++++ 2 files changed, 12 insertions(+) (limited to 'lib/CodeGen') diff --git a/lib/CodeGen/CodeGen.cc b/lib/CodeGen/CodeGen.cc index e45a3db..772dc82 100644 --- a/lib/CodeGen/CodeGen.cc +++ b/lib/CodeGen/CodeGen.cc @@ -77,6 +77,14 @@ CodeGen::CodeGen() { activateStackObject(registerStackObject(Addr, TypeName, Line)); }); + FuncGen->setMissingReturnHandler([this](int Line, const std::string &Name) { + Value *Msg = Builder->CreateGlobalString("[Fatal] line %d: FUNCTION %s ended without RETURN\n", + "err_missing_return", 0, TheModule.get()); + Value *NameStr = Builder->CreateGlobalString(Name, "function_name", 0, TheModule.get()); + RuntimeChecker->emitStderr(Msg, {RuntimeChecker->lineValue(Line), NameStr}); + Exceptions->emitThrow(); + }); + SetupExternalFunctions(); } diff --git a/lib/CodeGen/FunctionGen.cc b/lib/CodeGen/FunctionGen.cc index 48c9978..c233205 100644 --- a/lib/CodeGen/FunctionGen.cc +++ b/lib/CodeGen/FunctionGen.cc @@ -444,6 +444,10 @@ Function *FunctionGen::emitFunctionDef(FunctionDefAST *FuncAST, if (!Builder.GetInsertBlock()->hasTerminator()) { if (sameIdentifier(Proto->getReturnType(), "VOID")) { Exceptions.recordExit(Builder.CreateRetVoid()); + } else if (MissingReturn && !(!IsMethod && sameIdentifier(Proto->getName(), "MAIN"))) { + // Falling off the end of a FUNCTION is a runtime error, not a zero value. + // The handler ends the block with a throw (unreachable). + MissingReturn(FuncAST->getLine(), Proto->getName()); } else { Exceptions.recordExit(Builder.CreateRet(Constant::getNullValue(TheFunction->getReturnType()))); } -- cgit v1.3.1-4-g156e