@@ -131,8 +131,11 @@ abstract class TranslatedReturnStmt extends TranslatedStmt {
131131 }
132132}
133133
134+ /**
135+ * The IR translation of a `return` statement that returns a value.
136+ */
134137class TranslatedReturnValueStmt extends TranslatedReturnStmt , TranslatedVariableInitialization {
135- TranslatedReturnValueStmt ( ) { stmt .hasExpr ( ) }
138+ TranslatedReturnValueStmt ( ) { stmt .hasExpr ( ) and hasReturnValue ( stmt . getEnclosingFunction ( ) ) }
136139
137140 final override Instruction getInitializationSuccessor ( ) {
138141 result = getEnclosingFunction ( ) .getReturnSuccessorInstruction ( )
@@ -147,8 +150,49 @@ class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariable
147150 final override IRVariable getIRVariable ( ) { result = getEnclosingFunction ( ) .getReturnVariable ( ) }
148151}
149152
153+ /**
154+ * The IR translation of a `return` statement that returns an expression of `void` type.
155+ */
156+ class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt {
157+ TranslatedReturnVoidExpressionStmt ( ) {
158+ stmt .hasExpr ( ) and not hasReturnValue ( stmt .getEnclosingFunction ( ) )
159+ }
160+
161+ override TranslatedElement getChild ( int id ) {
162+ id = 0 and
163+ result = getExpr ( )
164+ }
165+
166+ override Instruction getFirstInstruction ( ) { result = getExpr ( ) .getFirstInstruction ( ) }
167+
168+ override predicate hasInstruction ( Opcode opcode , InstructionTag tag , CppType resultType ) {
169+ tag = OnlyInstructionTag ( ) and
170+ opcode instanceof Opcode:: NoOp and
171+ resultType = getVoidType ( )
172+ }
173+
174+ override Instruction getInstructionSuccessor ( InstructionTag tag , EdgeKind kind ) {
175+ tag = OnlyInstructionTag ( ) and
176+ result = getEnclosingFunction ( ) .getReturnSuccessorInstruction ( ) and
177+ kind instanceof GotoEdge
178+ }
179+
180+ override Instruction getChildSuccessor ( TranslatedElement child ) {
181+ child = getExpr ( ) and
182+ result = getInstruction ( OnlyInstructionTag ( ) )
183+ }
184+
185+ private TranslatedExpr getExpr ( ) { result = getTranslatedExpr ( stmt .getExpr ( ) ) }
186+ }
187+
188+ /**
189+ * The IR translation of a `return` statement that does not return a value. This includes implicit
190+ * return statements at the end of `void`-returning functions.
191+ */
150192class TranslatedReturnVoidStmt extends TranslatedReturnStmt {
151- TranslatedReturnVoidStmt ( ) { not stmt .hasExpr ( ) }
193+ TranslatedReturnVoidStmt ( ) {
194+ not stmt .hasExpr ( ) and not hasReturnValue ( stmt .getEnclosingFunction ( ) )
195+ }
152196
153197 override TranslatedElement getChild ( int id ) { none ( ) }
154198
@@ -169,6 +213,33 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt {
169213 override Instruction getChildSuccessor ( TranslatedElement child ) { none ( ) }
170214}
171215
216+ /**
217+ * The IR translation of an implicit `return` statement generated by the extractor to handle control
218+ * flow that reaches the end of a non-`void`-returning function body. Since such control flow
219+ * produces undefined behavior, we simply generate an `Unreached` instruction to prevent that flow
220+ * from continuing on to pollute other analysis. The assumption is that the developer is certain
221+ * that the implicit `return` is unreachable, even if the compiler cannot prove it.
222+ */
223+ class TranslatedUnreachableReturnStmt extends TranslatedReturnStmt {
224+ TranslatedUnreachableReturnStmt ( ) {
225+ not stmt .hasExpr ( ) and hasReturnValue ( stmt .getEnclosingFunction ( ) )
226+ }
227+
228+ override TranslatedElement getChild ( int id ) { none ( ) }
229+
230+ override Instruction getFirstInstruction ( ) { result = getInstruction ( OnlyInstructionTag ( ) ) }
231+
232+ override predicate hasInstruction ( Opcode opcode , InstructionTag tag , CppType resultType ) {
233+ tag = OnlyInstructionTag ( ) and
234+ opcode instanceof Opcode:: Unreached and
235+ resultType = getVoidType ( )
236+ }
237+
238+ override Instruction getInstructionSuccessor ( InstructionTag tag , EdgeKind kind ) { none ( ) }
239+
240+ override Instruction getChildSuccessor ( TranslatedElement child ) { none ( ) }
241+ }
242+
172243/**
173244 * The IR translation of a C++ `try` statement.
174245 */
0 commit comments