Skip to content

Commit 125a09c

Browse files
author
Dave Bartolomeo
committed
C++: Fix IR generation of return of void expression
1 parent 603a3af commit 125a09c

File tree

4 files changed

+80
-1
lines changed

4 files changed

+80
-1
lines changed

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ abstract class TranslatedReturnStmt extends TranslatedStmt {
135135
* The IR translation of a `return` statement that returns a value.
136136
*/
137137
class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariableInitialization {
138-
TranslatedReturnValueStmt() { stmt.hasExpr() }
138+
TranslatedReturnValueStmt() { stmt.hasExpr() and hasReturnValue(stmt.getEnclosingFunction()) }
139139

140140
final override Instruction getInitializationSuccessor() {
141141
result = getEnclosingFunction().getReturnSuccessorInstruction()
@@ -150,6 +150,41 @@ class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariable
150150
final override IRVariable getIRVariable() { result = getEnclosingFunction().getReturnVariable() }
151151
}
152152

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+
153188
/**
154189
* The IR translation of a `return` statement that does not return a value. This includes implicit
155190
* return statements at the end of `void`-returning functions.

cpp/ql/test/library-tests/ir/ir/PrintAST.expected

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8767,6 +8767,23 @@ ir.cpp:
87678767
# 1291| Type = [IntType] int
87688768
# 1291| ValueCategory = prvalue(load)
87698769
# 1293| 1: [ReturnStmt] return ...
8770+
# 1295| [TopLevelFunction] void returnVoid(int, int)
8771+
# 1295| params:
8772+
# 1295| 0: [Parameter] x
8773+
# 1295| Type = [IntType] int
8774+
# 1295| 1: [Parameter] y
8775+
# 1295| Type = [IntType] int
8776+
# 1295| body: [Block] { ... }
8777+
# 1296| 0: [ReturnStmt] return ...
8778+
# 1296| 0: [FunctionCall] call to IntegerOps
8779+
# 1296| Type = [VoidType] void
8780+
# 1296| ValueCategory = prvalue
8781+
# 1296| 0: [VariableAccess] x
8782+
# 1296| Type = [IntType] int
8783+
# 1296| ValueCategory = prvalue(load)
8784+
# 1296| 1: [VariableAccess] y
8785+
# 1296| Type = [IntType] int
8786+
# 1296| ValueCategory = prvalue(load)
87708787
perf-regression.cpp:
87718788
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
87728789
# 4| params:

cpp/ql/test/library-tests/ir/ir/ir.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,4 +1292,8 @@ int missingReturnValue(bool b, int x) {
12921292
}
12931293
}
12941294

1295+
void returnVoid(int x, int y) {
1296+
return IntegerOps(x, y);
1297+
}
1298+
12951299
// semmle-extractor-options: -std=c++17 --clang

cpp/ql/test/library-tests/ir/ir/raw_ir.expected

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6661,6 +6661,29 @@ ir.cpp:
66616661
# 1289| v1289_12(void) = AliasedUse : ~mu1289_4
66626662
# 1289| v1289_13(void) = ExitFunction :
66636663

6664+
# 1295| void returnVoid(int, int)
6665+
# 1295| Block 0
6666+
# 1295| v1295_1(void) = EnterFunction :
6667+
# 1295| mu1295_2(unknown) = AliasedDefinition :
6668+
# 1295| mu1295_3(unknown) = InitializeNonLocal :
6669+
# 1295| mu1295_4(unknown) = UnmodeledDefinition :
6670+
# 1295| r1295_5(glval<int>) = VariableAddress[x] :
6671+
# 1295| mu1295_6(int) = InitializeParameter[x] : &:r1295_5
6672+
# 1295| r1295_7(glval<int>) = VariableAddress[y] :
6673+
# 1295| mu1295_8(int) = InitializeParameter[y] : &:r1295_7
6674+
# 1296| r1296_1(glval<unknown>) = FunctionAddress[IntegerOps] :
6675+
# 1296| r1296_2(glval<int>) = VariableAddress[x] :
6676+
# 1296| r1296_3(int) = Load : &:r1296_2, ~mu1295_4
6677+
# 1296| r1296_4(glval<int>) = VariableAddress[y] :
6678+
# 1296| r1296_5(int) = Load : &:r1296_4, ~mu1295_4
6679+
# 1296| v1296_6(void) = Call : func:r1296_1, 0:r1296_3, 1:r1296_5
6680+
# 1296| mu1296_7(unknown) = ^CallSideEffect : ~mu1295_4
6681+
# 1296| v1296_8(void) = NoOp :
6682+
# 1295| v1295_9(void) = ReturnVoid :
6683+
# 1295| v1295_10(void) = UnmodeledUse : mu*
6684+
# 1295| v1295_11(void) = AliasedUse : ~mu1295_4
6685+
# 1295| v1295_12(void) = ExitFunction :
6686+
66646687
perf-regression.cpp:
66656688
# 6| void Big::Big()
66666689
# 6| Block 0

0 commit comments

Comments
 (0)