C++: Treat implicit end of body of non-void function as Unreached#3254
Conversation
When the extractor can't prove that control flow will never reach the end of a non-`void`-returning function without reaching an explicit `return` statement, it inserts an implicit `return` without an operand. If control actually reaches this point, the behavior is undefined. We were previously generating invalid IR for these implicit `return` statements, because the lack of an operand meant that there was no definition of the return value variable along that path. Instead, I've changed the IR generation to emit an `Unreached` instruction for the implicit `return`. This ensures that we don't create a control flow edge from the end of the body to the function epilogue. The change to the range analysis test avoids having that test depend on the previous bad IR behavior, while still preserving the original spirit of the test.
| class TranslatedReturnVoidStmt extends TranslatedReturnStmt { | ||
| TranslatedReturnVoidStmt() { not stmt.hasExpr() } | ||
| TranslatedReturnVoidStmt() { | ||
| not stmt.hasExpr() and not hasReturnValue(stmt.getEnclosingFunction()) |
There was a problem hiding this comment.
A return statement in a function with void as its return type can have a void-typed expression - what happens then?
There was a problem hiding this comment.
Great question. I’ll add a test case (and probably a fix).
There was a problem hiding this comment.
Fix and test case added. We didn't handle this correctly before, either. Good catch.
|
oh, missed the failing tests - looks like some noise in block numbering in the syntax zoo consistency failures and a real change in the IR value numbering test |
Mostly noise, but a couple of the missing operand errors are actual fixes.
|
A couple of the failures in Also, whoever wrote the original value number tests had something against |
When the extractor can't prove that control flow will never reach the end of a non-
void-returning function without reaching an explicitreturnstatement, it inserts an implicitreturnwithout an operand. If control actually reaches this point, the behavior is undefined.We were previously generating invalid IR for these implicit
returnstatements, because the lack of an operand meant that there was no definition of the return value variable along that path. Instead, I've changed the IR generation to emit anUnreachedinstruction for the implicitreturn. This ensures that we don't create a control flow edge from the end of the body to the function epilogue.The change to the range analysis test avoids having that test depend on the previous bad IR behavior, while still preserving the original spirit of the test.