Skip to content

Commit 5cde3fa

Browse files
authored
Merge pull request #16414 from jketema/range-based-for-loop-destructor-fix
C++: Correctly handle destructors at the end of range-based for-loops in the IR
2 parents eb0621a + ba64cf3 commit 5cde3fa

File tree

3 files changed

+128
-91
lines changed

3 files changed

+128
-91
lines changed

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,8 @@ class TranslatedForStmt extends TranslatedLoop {
11631163
class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
11641164
override RangeBasedForStmt stmt;
11651165

1166+
override predicate handlesDestructorsExplicitly() { any() }
1167+
11661168
override TranslatedElement getChildInternal(int id) {
11671169
id = 0 and result = this.getInitialization()
11681170
or
@@ -1216,6 +1218,19 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
12161218
or
12171219
child = this.getUpdate() and
12181220
result = this.getCondition().getFirstInstruction(kind)
1221+
or
1222+
exists(int destructorId |
1223+
destructorId >= this.getFirstDestructorCallIndex() and
1224+
child = this.getChild(destructorId) and
1225+
result = this.getChild(destructorId + 1).getFirstInstruction(kind)
1226+
)
1227+
or
1228+
exists(int lastDestructorIndex |
1229+
lastDestructorIndex =
1230+
max(int n | exists(this.getChild(n)) and n >= this.getFirstDestructorCallIndex()) and
1231+
child = this.getChild(lastDestructorIndex) and
1232+
result = this.getParent().getChildSuccessor(this, kind)
1233+
)
12191234
}
12201235

12211236
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -1231,7 +1246,9 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
12311246

12321247
override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
12331248
child = this.getCondition() and
1234-
result = this.getParent().getChildSuccessor(this, kind)
1249+
if this.hasAnImplicitDestructorCall()
1250+
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
1251+
else result = this.getParent().getChildSuccessor(this, kind)
12351252
}
12361253

12371254
private TranslatedDeclStmt getRangeVariableDeclStmt() {

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

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15600,10 +15600,18 @@ ir.cpp:
1560015600
# 2215| r2215_73(glval<iterator<random_access_iterator_tag, ClassWithDestructor, ptrdiff_t, ClassWithDestructor *, ClassWithDestructor &>>) = CopyValue : r2215_61
1560115601
#-----| Goto (back edge) -> Block 8
1560215602

15603-
# 2218| Block 10
15603+
# 2215| Block 10
15604+
# 2215| r2215_74(glval<vector<ClassWithDestructor>>) = VariableAddress[ys] :
15605+
# 2215| r2215_75(glval<unknown>) = FunctionAddress[~vector] :
15606+
# 2215| v2215_76(void) = Call[~vector] : func:r2215_75, this:r2215_74
15607+
# 2215| m2215_77(unknown) = ^CallSideEffect : ~m2215_50
15608+
# 2215| m2215_78(unknown) = Chi : total:m2215_50, partial:m2215_77
15609+
# 2215| v2215_79(void) = ^IndirectReadSideEffect[-1] : &:r2215_74, ~m2215_78
15610+
# 2215| m2215_80(vector<ClassWithDestructor>) = ^IndirectMayWriteSideEffect[-1] : &:r2215_74
15611+
# 2215| m2215_81(unknown) = Chi : total:m2215_78, partial:m2215_80
1560415612
# 2218| r2218_1(glval<vector<ClassWithDestructor>>) = VariableAddress[ys] :
1560515613
# 2218| m2218_2(vector<ClassWithDestructor>) = Uninitialized[ys] : &:r2218_1
15606-
# 2218| m2218_3(unknown) = Chi : total:m2215_50, partial:m2218_2
15614+
# 2218| m2218_3(unknown) = Chi : total:m2215_81, partial:m2218_2
1560715615
# 2218| r2218_4(glval<unknown>) = FunctionAddress[vector] :
1560815616
# 2218| r2218_5(glval<ClassWithDestructor>) = VariableAddress[#temp2218:45] :
1560915617
# 2218| r2218_6(glval<ClassWithDestructor>) = VariableAddress[x] :
@@ -15753,10 +15761,18 @@ ir.cpp:
1575315761
# 2233| m2233_8(ClassWithDestructor) = Chi : total:m2214_8, partial:m2233_7
1575415762
#-----| Goto -> Block 1
1575515763

15756-
# 2224| Block 15
15764+
# 2218| Block 15
15765+
# 2218| r2218_90(glval<vector<ClassWithDestructor>>) = VariableAddress[ys] :
15766+
# 2218| r2218_91(glval<unknown>) = FunctionAddress[~vector] :
15767+
# 2218| v2218_92(void) = Call[~vector] : func:r2218_91, this:r2218_90
15768+
# 2218| m2218_93(unknown) = ^CallSideEffect : ~m2218_50
15769+
# 2218| m2218_94(unknown) = Chi : total:m2218_50, partial:m2218_93
15770+
# 2218| v2218_95(void) = ^IndirectReadSideEffect[-1] : &:r2218_90, ~m2218_94
15771+
# 2218| m2218_96(vector<ClassWithDestructor>) = ^IndirectMayWriteSideEffect[-1] : &:r2218_90
15772+
# 2218| m2218_97(unknown) = Chi : total:m2218_94, partial:m2218_96
1575715773
# 2224| r2224_1(glval<vector<int>>) = VariableAddress[ys] :
1575815774
# 2224| m2224_2(vector<int>) = Uninitialized[ys] : &:r2224_1
15759-
# 2224| m2224_3(unknown) = Chi : total:m2218_50, partial:m2224_2
15775+
# 2224| m2224_3(unknown) = Chi : total:m2218_97, partial:m2224_2
1576015776
# 2224| r2224_4(glval<unknown>) = FunctionAddress[vector] :
1576115777
# 2224| r2224_5(int) = Constant[1] :
1576215778
# 2224| v2224_6(void) = Call[vector] : func:r2224_4, this:r2224_1, 0:r2224_5
@@ -15862,10 +15878,18 @@ ir.cpp:
1586215878
# 2233| m2233_16(ClassWithDestructor) = Chi : total:m2214_8, partial:m2233_15
1586315879
#-----| Goto -> Block 1
1586415880

15865-
# 2229| Block 20
15881+
# 2224| Block 20
15882+
# 2224| r2224_62(glval<vector<int>>) = VariableAddress[ys] :
15883+
# 2224| r2224_63(glval<unknown>) = FunctionAddress[~vector] :
15884+
# 2224| v2224_64(void) = Call[~vector] : func:r2224_63, this:r2224_62
15885+
# 2224| m2224_65(unknown) = ^CallSideEffect : ~m2224_38
15886+
# 2224| m2224_66(unknown) = Chi : total:m2224_38, partial:m2224_65
15887+
# 2224| v2224_67(void) = ^IndirectReadSideEffect[-1] : &:r2224_62, ~m2224_66
15888+
# 2224| m2224_68(vector<int>) = ^IndirectMayWriteSideEffect[-1] : &:r2224_62
15889+
# 2224| m2224_69(unknown) = Chi : total:m2224_66, partial:m2224_68
1586615890
# 2229| r2229_1(glval<vector<ClassWithDestructor>>) = VariableAddress[ys] :
1586715891
# 2229| m2229_2(vector<ClassWithDestructor>) = Uninitialized[ys] : &:r2229_1
15868-
# 2229| m2229_3(unknown) = Chi : total:m2224_38, partial:m2229_2
15892+
# 2229| m2229_3(unknown) = Chi : total:m2224_69, partial:m2229_2
1586915893
# 2229| r2229_4(glval<unknown>) = FunctionAddress[vector] :
1587015894
# 2229| r2229_5(glval<ClassWithDestructor>) = VariableAddress[#temp2229:45] :
1587115895
# 2229| r2229_6(glval<ClassWithDestructor>) = VariableAddress[x] :
@@ -15994,16 +16018,24 @@ ir.cpp:
1599416018
# 2229| r2229_73(glval<iterator<random_access_iterator_tag, ClassWithDestructor, ptrdiff_t, ClassWithDestructor *, ClassWithDestructor &>>) = CopyValue : r2229_61
1599516019
#-----| Goto (back edge) -> Block 21
1599616020

15997-
# 2233| Block 23
15998-
# 2233| v2233_17(void) = NoOp :
15999-
# 2233| r2233_18(glval<ClassWithDestructor>) = VariableAddress[x] :
16000-
# 2233| r2233_19(glval<unknown>) = FunctionAddress[~ClassWithDestructor] :
16001-
# 2233| v2233_20(void) = Call[~ClassWithDestructor] : func:r2233_19, this:r2233_18
16002-
# 2233| m2233_21(unknown) = ^CallSideEffect : ~m2229_50
16003-
# 2233| m2233_22(unknown) = Chi : total:m2229_50, partial:m2233_21
16004-
# 2233| v2233_23(void) = ^IndirectReadSideEffect[-1] : &:r2233_18, m2214_8
16005-
# 2233| m2233_24(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2233_18
16006-
# 2233| m2233_25(ClassWithDestructor) = Chi : total:m2214_8, partial:m2233_24
16021+
# 2229| Block 23
16022+
# 2229| r2229_74(glval<vector<ClassWithDestructor>>) = VariableAddress[ys] :
16023+
# 2229| r2229_75(glval<unknown>) = FunctionAddress[~vector] :
16024+
# 2229| v2229_76(void) = Call[~vector] : func:r2229_75, this:r2229_74
16025+
# 2229| m2229_77(unknown) = ^CallSideEffect : ~m2229_50
16026+
# 2229| m2229_78(unknown) = Chi : total:m2229_50, partial:m2229_77
16027+
# 2229| v2229_79(void) = ^IndirectReadSideEffect[-1] : &:r2229_74, ~m2229_78
16028+
# 2229| m2229_80(vector<ClassWithDestructor>) = ^IndirectMayWriteSideEffect[-1] : &:r2229_74
16029+
# 2229| m2229_81(unknown) = Chi : total:m2229_78, partial:m2229_80
16030+
# 2233| v2233_17(void) = NoOp :
16031+
# 2233| r2233_18(glval<ClassWithDestructor>) = VariableAddress[x] :
16032+
# 2233| r2233_19(glval<unknown>) = FunctionAddress[~ClassWithDestructor] :
16033+
# 2233| v2233_20(void) = Call[~ClassWithDestructor] : func:r2233_19, this:r2233_18
16034+
# 2233| m2233_21(unknown) = ^CallSideEffect : ~m2229_81
16035+
# 2233| m2233_22(unknown) = Chi : total:m2229_81, partial:m2233_21
16036+
# 2233| v2233_23(void) = ^IndirectReadSideEffect[-1] : &:r2233_18, m2214_8
16037+
# 2233| m2233_24(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2233_18
16038+
# 2233| m2233_25(ClassWithDestructor) = Chi : total:m2214_8, partial:m2233_24
1600716039
#-----| Goto -> Block 1
1600816040

1600916041
# 2198| Block 24

0 commit comments

Comments
 (0)