Skip to content

Commit 1a53b92

Browse files
committed
C++: Ensure destructors for ifs are called after both branches
1 parent 52db1c1 commit 1a53b92

File tree

3 files changed

+121
-98
lines changed

3 files changed

+121
-98
lines changed

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

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,8 @@ abstract class TranslatedIfLikeStmt extends TranslatedStmt, ConditionContext {
855855

856856
override TranslatedElement getLastChild() { result = this.getElse() or result = this.getThen() }
857857

858+
override predicate handlesDestructorsExplicitly() { any() }
859+
858860
override TranslatedElement getChildInternal(int id) {
859861
id = 0 and result = this.getInitialization()
860862
or
@@ -892,15 +894,36 @@ abstract class TranslatedIfLikeStmt extends TranslatedStmt, ConditionContext {
892894
child = this.getCondition() and
893895
if this.hasElse()
894896
then result = this.getElse().getFirstInstruction(kind)
895-
else result = this.getParent().getChildSuccessor(this, kind)
897+
else (
898+
if this.hasAnImplicitDestructorCall()
899+
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
900+
else result = this.getParent().getChildSuccessor(this, kind)
901+
)
896902
}
897903

898904
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
899905
child = this.getInitialization() and
900906
result = this.getFirstConditionInstruction(kind)
901907
or
902908
(child = this.getThen() or child = this.getElse()) and
903-
result = this.getParent().getChildSuccessor(this, kind)
909+
(
910+
if this.hasAnImplicitDestructorCall()
911+
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
912+
else result = this.getParent().getChildSuccessor(this, kind)
913+
)
914+
or
915+
exists(int destructorId |
916+
destructorId >= this.getFirstDestructorCallIndex() and
917+
child = this.getChild(destructorId) and
918+
result = this.getChild(destructorId + 1).getFirstInstruction(kind)
919+
)
920+
or
921+
exists(int lastDestructorIndex |
922+
lastDestructorIndex =
923+
max(int n | exists(this.getChild(n)) and n >= this.getFirstDestructorCallIndex()) and
924+
child = this.getChild(lastDestructorIndex) and
925+
result = this.getParent().getChildSuccessor(this, kind)
926+
)
904927
}
905928

906929
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {

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

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -15378,37 +15378,38 @@ ir.cpp:
1537815378
# 2199| v2199_12(void) = ExitFunction :
1537915379

1538015380
# 2201| Block 2
15381-
# 2201| r2201_1(glval<ClassWithDestructor>) = VariableAddress[x] :
15382-
# 2201| r2201_2(glval<unknown>) = FunctionAddress[set_x] :
15383-
# 2201| r2201_3(char) = Constant[97] :
15384-
# 2201| v2201_4(void) = Call[set_x] : func:r2201_2, this:r2201_1, 0:r2201_3
15385-
# 2201| m2201_5(unknown) = ^CallSideEffect : ~m2200_6
15386-
# 2201| m2201_6(unknown) = Chi : total:m2200_6, partial:m2201_5
15387-
# 2201| v2201_7(void) = ^IndirectReadSideEffect[-1] : &:r2201_1, m2200_8
15388-
# 2201| m2201_8(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2201_1
15389-
# 2201| m2201_9(ClassWithDestructor) = Chi : total:m2200_8, partial:m2201_8
15390-
# 2201| r2201_10(glval<ClassWithDestructor>) = VariableAddress[x] :
15391-
# 2201| r2201_11(glval<unknown>) = FunctionAddress[~ClassWithDestructor] :
15392-
# 2201| v2201_12(void) = Call[~ClassWithDestructor] : func:r2201_11, this:r2201_10
15393-
# 2201| m2201_13(unknown) = ^CallSideEffect : ~m2201_6
15394-
# 2201| m2201_14(unknown) = Chi : total:m2201_6, partial:m2201_13
15395-
# 2201| v2201_15(void) = ^IndirectReadSideEffect[-1] : &:r2201_10, m2201_9
15396-
# 2201| m2201_16(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2201_10
15397-
# 2201| m2201_17(ClassWithDestructor) = Chi : total:m2201_9, partial:m2201_16
15381+
# 2201| r2201_1(glval<ClassWithDestructor>) = VariableAddress[x] :
15382+
# 2201| r2201_2(glval<unknown>) = FunctionAddress[set_x] :
15383+
# 2201| r2201_3(char) = Constant[97] :
15384+
# 2201| v2201_4(void) = Call[set_x] : func:r2201_2, this:r2201_1, 0:r2201_3
15385+
# 2201| m2201_5(unknown) = ^CallSideEffect : ~m2200_6
15386+
# 2201| m2201_6(unknown) = Chi : total:m2200_6, partial:m2201_5
15387+
# 2201| v2201_7(void) = ^IndirectReadSideEffect[-1] : &:r2201_1, m2200_8
15388+
# 2201| m2201_8(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2201_1
15389+
# 2201| m2201_9(ClassWithDestructor) = Chi : total:m2200_8, partial:m2201_8
1539815390
#-----| Goto -> Block 3
1539915391

15400-
# 2203| Block 3
15401-
# 2203| m2203_1(unknown) = Phi : from 0:~m2200_6, from 2:~m2201_14
15402-
# 2203| r2203_2(glval<ClassWithDestructor>) = VariableAddress[x] :
15403-
# 2203| m2203_3(ClassWithDestructor) = Uninitialized[x] : &:r2203_2
15404-
# 2203| r2203_4(glval<unknown>) = FunctionAddress[ClassWithDestructor] :
15405-
# 2203| v2203_5(void) = Call[ClassWithDestructor] : func:r2203_4, this:r2203_2
15406-
# 2203| m2203_6(unknown) = ^CallSideEffect : ~m2203_1
15407-
# 2203| m2203_7(unknown) = Chi : total:m2203_1, partial:m2203_6
15408-
# 2203| m2203_8(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2203_2
15409-
# 2203| m2203_9(ClassWithDestructor) = Chi : total:m2203_3, partial:m2203_8
15410-
# 2203| r2203_10(bool) = Constant[1] :
15411-
# 2203| v2203_11(void) = ConditionalBranch : r2203_10
15392+
# 2201| Block 3
15393+
# 2201| m2201_10(ClassWithDestructor) = Phi : from 0:m2200_8, from 2:m2201_9
15394+
# 2201| m2201_11(unknown) = Phi : from 0:~m2200_6, from 2:~m2201_6
15395+
# 2201| r2201_12(glval<ClassWithDestructor>) = VariableAddress[x] :
15396+
# 2201| r2201_13(glval<unknown>) = FunctionAddress[~ClassWithDestructor] :
15397+
# 2201| v2201_14(void) = Call[~ClassWithDestructor] : func:r2201_13, this:r2201_12
15398+
# 2201| m2201_15(unknown) = ^CallSideEffect : ~m2201_11
15399+
# 2201| m2201_16(unknown) = Chi : total:m2201_11, partial:m2201_15
15400+
# 2201| v2201_17(void) = ^IndirectReadSideEffect[-1] : &:r2201_12, m2201_10
15401+
# 2201| m2201_18(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2201_12
15402+
# 2201| m2201_19(ClassWithDestructor) = Chi : total:m2201_10, partial:m2201_18
15403+
# 2203| r2203_1(glval<ClassWithDestructor>) = VariableAddress[x] :
15404+
# 2203| m2203_2(ClassWithDestructor) = Uninitialized[x] : &:r2203_1
15405+
# 2203| r2203_3(glval<unknown>) = FunctionAddress[ClassWithDestructor] :
15406+
# 2203| v2203_4(void) = Call[ClassWithDestructor] : func:r2203_3, this:r2203_1
15407+
# 2203| m2203_5(unknown) = ^CallSideEffect : ~m2201_16
15408+
# 2203| m2203_6(unknown) = Chi : total:m2201_16, partial:m2203_5
15409+
# 2203| m2203_7(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2203_1
15410+
# 2203| m2203_8(ClassWithDestructor) = Chi : total:m2203_2, partial:m2203_7
15411+
# 2203| r2203_9(bool) = Constant[1] :
15412+
# 2203| v2203_10(void) = ConditionalBranch : r2203_9
1541215413
#-----| False -> Block 24
1541315414
#-----| True -> Block 4
1541415415

@@ -15417,11 +15418,11 @@ ir.cpp:
1541715418
# 2204| r2204_2(glval<unknown>) = FunctionAddress[set_x] :
1541815419
# 2204| r2204_3(char) = Constant[97] :
1541915420
# 2204| v2204_4(void) = Call[set_x] : func:r2204_2, this:r2204_1, 0:r2204_3
15420-
# 2204| m2204_5(unknown) = ^CallSideEffect : ~m2203_7
15421-
# 2204| m2204_6(unknown) = Chi : total:m2203_7, partial:m2204_5
15422-
# 2204| v2204_7(void) = ^IndirectReadSideEffect[-1] : &:r2204_1, m2203_9
15421+
# 2204| m2204_5(unknown) = ^CallSideEffect : ~m2203_6
15422+
# 2204| m2204_6(unknown) = Chi : total:m2203_6, partial:m2204_5
15423+
# 2204| v2204_7(void) = ^IndirectReadSideEffect[-1] : &:r2204_1, m2203_8
1542315424
# 2204| m2204_8(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2204_1
15424-
# 2204| m2204_9(ClassWithDestructor) = Chi : total:m2203_9, partial:m2204_8
15425+
# 2204| m2204_9(ClassWithDestructor) = Chi : total:m2203_8, partial:m2204_8
1542515426
# 2204| r2204_10(glval<ClassWithDestructor>) = VariableAddress[x] :
1542615427
# 2204| r2204_11(glval<unknown>) = FunctionAddress[~ClassWithDestructor] :
1542715428
# 2204| v2204_12(void) = Call[~ClassWithDestructor] : func:r2204_11, this:r2204_10
@@ -18292,7 +18293,10 @@ ir.cpp:
1829218293
#-----| True -> Block 1
1829318294

1829418295
# 2547| Block 1
18295-
# 2547| v2547_1(void) = NoOp :
18296+
# 2547| v2547_1(void) = NoOp :
18297+
#-----| Goto -> Block 2
18298+
18299+
# 2547| Block 2
1829618300
# 2547| r2547_2(glval<ClassWithDestructor>) = CopyValue : r2546_2
1829718301
# 2547| r2547_3(glval<unknown>) = FunctionAddress[~ClassWithDestructor] :
1829818302
# 2547| v2547_4(void) = Call[~ClassWithDestructor] : func:r2547_3, this:r2547_2
@@ -18301,14 +18305,10 @@ ir.cpp:
1830118305
# 2547| v2547_7(void) = ^IndirectReadSideEffect[-1] : &:r2547_2, ~m2547_6
1830218306
# 2547| m2547_8(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2547_2
1830318307
# 2547| m2547_9(unknown) = Chi : total:m2547_6, partial:m2547_8
18304-
#-----| Goto -> Block 2
18305-
18306-
# 2548| Block 2
18307-
# 2548| m2548_1(unknown) = Phi : from 0:~m2546_18, from 1:~m2547_9
18308-
# 2548| v2548_2(void) = NoOp :
18309-
# 2545| v2545_7(void) = ReturnVoid :
18310-
# 2545| v2545_8(void) = AliasedUse : ~m2548_1
18311-
# 2545| v2545_9(void) = ExitFunction :
18308+
# 2548| v2548_1(void) = NoOp :
18309+
# 2545| v2545_7(void) = ReturnVoid :
18310+
# 2545| v2545_8(void) = AliasedUse : ~m2547_6
18311+
# 2545| v2545_9(void) = ExitFunction :
1831218312

1831318313
# 2550| void constexpr_inconsistency(bool)
1831418314
# 2550| Block 0

0 commit comments

Comments
 (0)