C++: Fix IR generation of return of void expression

This commit is contained in:
Dave Bartolomeo
2020-04-14 11:40:33 -04:00
parent 603a3af19b
commit 125a09ce6e
4 changed files with 80 additions and 1 deletions

View File

@@ -135,7 +135,7 @@ abstract class TranslatedReturnStmt extends TranslatedStmt {
* The IR translation of a `return` statement that returns a value.
*/
class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariableInitialization {
TranslatedReturnValueStmt() { stmt.hasExpr() }
TranslatedReturnValueStmt() { stmt.hasExpr() and hasReturnValue(stmt.getEnclosingFunction()) }
final override Instruction getInitializationSuccessor() {
result = getEnclosingFunction().getReturnSuccessorInstruction()
@@ -150,6 +150,41 @@ class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariable
final override IRVariable getIRVariable() { result = getEnclosingFunction().getReturnVariable() }
}
/**
* The IR translation of a `return` statement that returns an expression of `void` type.
*/
class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt {
TranslatedReturnVoidExpressionStmt() {
stmt.hasExpr() and not hasReturnValue(stmt.getEnclosingFunction())
}
override TranslatedElement getChild(int id) {
id = 0 and
result = getExpr()
}
override Instruction getFirstInstruction() { result = getExpr().getFirstInstruction() }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = OnlyInstructionTag() and
opcode instanceof Opcode::NoOp and
resultType = getVoidType()
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
result = getEnclosingFunction().getReturnSuccessorInstruction() and
kind instanceof GotoEdge
}
override Instruction getChildSuccessor(TranslatedElement child) {
child = getExpr() and
result = getInstruction(OnlyInstructionTag())
}
private TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr()) }
}
/**
* The IR translation of a `return` statement that does not return a value. This includes implicit
* return statements at the end of `void`-returning functions.

View File

@@ -8767,6 +8767,23 @@ ir.cpp:
# 1291| Type = [IntType] int
# 1291| ValueCategory = prvalue(load)
# 1293| 1: [ReturnStmt] return ...
# 1295| [TopLevelFunction] void returnVoid(int, int)
# 1295| params:
# 1295| 0: [Parameter] x
# 1295| Type = [IntType] int
# 1295| 1: [Parameter] y
# 1295| Type = [IntType] int
# 1295| body: [Block] { ... }
# 1296| 0: [ReturnStmt] return ...
# 1296| 0: [FunctionCall] call to IntegerOps
# 1296| Type = [VoidType] void
# 1296| ValueCategory = prvalue
# 1296| 0: [VariableAccess] x
# 1296| Type = [IntType] int
# 1296| ValueCategory = prvalue(load)
# 1296| 1: [VariableAccess] y
# 1296| Type = [IntType] int
# 1296| ValueCategory = prvalue(load)
perf-regression.cpp:
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
# 4| params:

View File

@@ -1292,4 +1292,8 @@ int missingReturnValue(bool b, int x) {
}
}
void returnVoid(int x, int y) {
return IntegerOps(x, y);
}
// semmle-extractor-options: -std=c++17 --clang

View File

@@ -6661,6 +6661,29 @@ ir.cpp:
# 1289| v1289_12(void) = AliasedUse : ~mu1289_4
# 1289| v1289_13(void) = ExitFunction :
# 1295| void returnVoid(int, int)
# 1295| Block 0
# 1295| v1295_1(void) = EnterFunction :
# 1295| mu1295_2(unknown) = AliasedDefinition :
# 1295| mu1295_3(unknown) = InitializeNonLocal :
# 1295| mu1295_4(unknown) = UnmodeledDefinition :
# 1295| r1295_5(glval<int>) = VariableAddress[x] :
# 1295| mu1295_6(int) = InitializeParameter[x] : &:r1295_5
# 1295| r1295_7(glval<int>) = VariableAddress[y] :
# 1295| mu1295_8(int) = InitializeParameter[y] : &:r1295_7
# 1296| r1296_1(glval<unknown>) = FunctionAddress[IntegerOps] :
# 1296| r1296_2(glval<int>) = VariableAddress[x] :
# 1296| r1296_3(int) = Load : &:r1296_2, ~mu1295_4
# 1296| r1296_4(glval<int>) = VariableAddress[y] :
# 1296| r1296_5(int) = Load : &:r1296_4, ~mu1295_4
# 1296| v1296_6(void) = Call : func:r1296_1, 0:r1296_3, 1:r1296_5
# 1296| mu1296_7(unknown) = ^CallSideEffect : ~mu1295_4
# 1296| v1296_8(void) = NoOp :
# 1295| v1295_9(void) = ReturnVoid :
# 1295| v1295_10(void) = UnmodeledUse : mu*
# 1295| v1295_11(void) = AliasedUse : ~mu1295_4
# 1295| v1295_12(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0