C++: Ensure destructors for ifs are called after both branches

This commit is contained in:
Jeroen Ketema
2024-05-08 14:48:28 +02:00
parent 52db1c1253
commit 1a53b923a6
3 changed files with 121 additions and 98 deletions

View File

@@ -855,6 +855,8 @@ abstract class TranslatedIfLikeStmt extends TranslatedStmt, ConditionContext {
override TranslatedElement getLastChild() { result = this.getElse() or result = this.getThen() }
override predicate handlesDestructorsExplicitly() { any() }
override TranslatedElement getChildInternal(int id) {
id = 0 and result = this.getInitialization()
or
@@ -892,7 +894,11 @@ abstract class TranslatedIfLikeStmt extends TranslatedStmt, ConditionContext {
child = this.getCondition() and
if this.hasElse()
then result = this.getElse().getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
else (
if this.hasAnImplicitDestructorCall()
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
)
}
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
@@ -900,7 +906,24 @@ abstract class TranslatedIfLikeStmt extends TranslatedStmt, ConditionContext {
result = this.getFirstConditionInstruction(kind)
or
(child = this.getThen() or child = this.getElse()) and
result = this.getParent().getChildSuccessor(this, kind)
(
if this.hasAnImplicitDestructorCall()
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
)
or
exists(int destructorId |
destructorId >= this.getFirstDestructorCallIndex() and
child = this.getChild(destructorId) and
result = this.getChild(destructorId + 1).getFirstInstruction(kind)
)
or
exists(int lastDestructorIndex |
lastDestructorIndex =
max(int n | exists(this.getChild(n)) and n >= this.getFirstDestructorCallIndex()) and
child = this.getChild(lastDestructorIndex) and
result = this.getParent().getChildSuccessor(this, kind)
)
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {

View File

@@ -15378,37 +15378,38 @@ ir.cpp:
# 2199| v2199_12(void) = ExitFunction :
# 2201| Block 2
# 2201| r2201_1(glval<ClassWithDestructor>) = VariableAddress[x] :
# 2201| r2201_2(glval<unknown>) = FunctionAddress[set_x] :
# 2201| r2201_3(char) = Constant[97] :
# 2201| v2201_4(void) = Call[set_x] : func:r2201_2, this:r2201_1, 0:r2201_3
# 2201| m2201_5(unknown) = ^CallSideEffect : ~m2200_6
# 2201| m2201_6(unknown) = Chi : total:m2200_6, partial:m2201_5
# 2201| v2201_7(void) = ^IndirectReadSideEffect[-1] : &:r2201_1, m2200_8
# 2201| m2201_8(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2201_1
# 2201| m2201_9(ClassWithDestructor) = Chi : total:m2200_8, partial:m2201_8
# 2201| r2201_10(glval<ClassWithDestructor>) = VariableAddress[x] :
# 2201| r2201_11(glval<unknown>) = FunctionAddress[~ClassWithDestructor] :
# 2201| v2201_12(void) = Call[~ClassWithDestructor] : func:r2201_11, this:r2201_10
# 2201| m2201_13(unknown) = ^CallSideEffect : ~m2201_6
# 2201| m2201_14(unknown) = Chi : total:m2201_6, partial:m2201_13
# 2201| v2201_15(void) = ^IndirectReadSideEffect[-1] : &:r2201_10, m2201_9
# 2201| m2201_16(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2201_10
# 2201| m2201_17(ClassWithDestructor) = Chi : total:m2201_9, partial:m2201_16
# 2201| r2201_1(glval<ClassWithDestructor>) = VariableAddress[x] :
# 2201| r2201_2(glval<unknown>) = FunctionAddress[set_x] :
# 2201| r2201_3(char) = Constant[97] :
# 2201| v2201_4(void) = Call[set_x] : func:r2201_2, this:r2201_1, 0:r2201_3
# 2201| m2201_5(unknown) = ^CallSideEffect : ~m2200_6
# 2201| m2201_6(unknown) = Chi : total:m2200_6, partial:m2201_5
# 2201| v2201_7(void) = ^IndirectReadSideEffect[-1] : &:r2201_1, m2200_8
# 2201| m2201_8(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2201_1
# 2201| m2201_9(ClassWithDestructor) = Chi : total:m2200_8, partial:m2201_8
#-----| Goto -> Block 3
# 2203| Block 3
# 2203| m2203_1(unknown) = Phi : from 0:~m2200_6, from 2:~m2201_14
# 2203| r2203_2(glval<ClassWithDestructor>) = VariableAddress[x] :
# 2203| m2203_3(ClassWithDestructor) = Uninitialized[x] : &:r2203_2
# 2203| r2203_4(glval<unknown>) = FunctionAddress[ClassWithDestructor] :
# 2203| v2203_5(void) = Call[ClassWithDestructor] : func:r2203_4, this:r2203_2
# 2203| m2203_6(unknown) = ^CallSideEffect : ~m2203_1
# 2203| m2203_7(unknown) = Chi : total:m2203_1, partial:m2203_6
# 2203| m2203_8(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2203_2
# 2203| m2203_9(ClassWithDestructor) = Chi : total:m2203_3, partial:m2203_8
# 2203| r2203_10(bool) = Constant[1] :
# 2203| v2203_11(void) = ConditionalBranch : r2203_10
# 2201| Block 3
# 2201| m2201_10(ClassWithDestructor) = Phi : from 0:m2200_8, from 2:m2201_9
# 2201| m2201_11(unknown) = Phi : from 0:~m2200_6, from 2:~m2201_6
# 2201| r2201_12(glval<ClassWithDestructor>) = VariableAddress[x] :
# 2201| r2201_13(glval<unknown>) = FunctionAddress[~ClassWithDestructor] :
# 2201| v2201_14(void) = Call[~ClassWithDestructor] : func:r2201_13, this:r2201_12
# 2201| m2201_15(unknown) = ^CallSideEffect : ~m2201_11
# 2201| m2201_16(unknown) = Chi : total:m2201_11, partial:m2201_15
# 2201| v2201_17(void) = ^IndirectReadSideEffect[-1] : &:r2201_12, m2201_10
# 2201| m2201_18(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2201_12
# 2201| m2201_19(ClassWithDestructor) = Chi : total:m2201_10, partial:m2201_18
# 2203| r2203_1(glval<ClassWithDestructor>) = VariableAddress[x] :
# 2203| m2203_2(ClassWithDestructor) = Uninitialized[x] : &:r2203_1
# 2203| r2203_3(glval<unknown>) = FunctionAddress[ClassWithDestructor] :
# 2203| v2203_4(void) = Call[ClassWithDestructor] : func:r2203_3, this:r2203_1
# 2203| m2203_5(unknown) = ^CallSideEffect : ~m2201_16
# 2203| m2203_6(unknown) = Chi : total:m2201_16, partial:m2203_5
# 2203| m2203_7(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2203_1
# 2203| m2203_8(ClassWithDestructor) = Chi : total:m2203_2, partial:m2203_7
# 2203| r2203_9(bool) = Constant[1] :
# 2203| v2203_10(void) = ConditionalBranch : r2203_9
#-----| False -> Block 24
#-----| True -> Block 4
@@ -15417,11 +15418,11 @@ ir.cpp:
# 2204| r2204_2(glval<unknown>) = FunctionAddress[set_x] :
# 2204| r2204_3(char) = Constant[97] :
# 2204| v2204_4(void) = Call[set_x] : func:r2204_2, this:r2204_1, 0:r2204_3
# 2204| m2204_5(unknown) = ^CallSideEffect : ~m2203_7
# 2204| m2204_6(unknown) = Chi : total:m2203_7, partial:m2204_5
# 2204| v2204_7(void) = ^IndirectReadSideEffect[-1] : &:r2204_1, m2203_9
# 2204| m2204_5(unknown) = ^CallSideEffect : ~m2203_6
# 2204| m2204_6(unknown) = Chi : total:m2203_6, partial:m2204_5
# 2204| v2204_7(void) = ^IndirectReadSideEffect[-1] : &:r2204_1, m2203_8
# 2204| m2204_8(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2204_1
# 2204| m2204_9(ClassWithDestructor) = Chi : total:m2203_9, partial:m2204_8
# 2204| m2204_9(ClassWithDestructor) = Chi : total:m2203_8, partial:m2204_8
# 2204| r2204_10(glval<ClassWithDestructor>) = VariableAddress[x] :
# 2204| r2204_11(glval<unknown>) = FunctionAddress[~ClassWithDestructor] :
# 2204| v2204_12(void) = Call[~ClassWithDestructor] : func:r2204_11, this:r2204_10
@@ -18292,7 +18293,10 @@ ir.cpp:
#-----| True -> Block 1
# 2547| Block 1
# 2547| v2547_1(void) = NoOp :
# 2547| v2547_1(void) = NoOp :
#-----| Goto -> Block 2
# 2547| Block 2
# 2547| r2547_2(glval<ClassWithDestructor>) = CopyValue : r2546_2
# 2547| r2547_3(glval<unknown>) = FunctionAddress[~ClassWithDestructor] :
# 2547| v2547_4(void) = Call[~ClassWithDestructor] : func:r2547_3, this:r2547_2
@@ -18301,14 +18305,10 @@ ir.cpp:
# 2547| v2547_7(void) = ^IndirectReadSideEffect[-1] : &:r2547_2, ~m2547_6
# 2547| m2547_8(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2547_2
# 2547| m2547_9(unknown) = Chi : total:m2547_6, partial:m2547_8
#-----| Goto -> Block 2
# 2548| Block 2
# 2548| m2548_1(unknown) = Phi : from 0:~m2546_18, from 1:~m2547_9
# 2548| v2548_2(void) = NoOp :
# 2545| v2545_7(void) = ReturnVoid :
# 2545| v2545_8(void) = AliasedUse : ~m2548_1
# 2545| v2545_9(void) = ExitFunction :
# 2548| v2548_1(void) = NoOp :
# 2545| v2545_7(void) = ReturnVoid :
# 2545| v2545_8(void) = AliasedUse : ~m2547_6
# 2545| v2545_9(void) = ExitFunction :
# 2550| void constexpr_inconsistency(bool)
# 2550| Block 0

View File

@@ -14146,60 +14146,60 @@ ir.cpp:
# 2199| v2199_10(void) = ExitFunction :
# 2201| Block 2
# 2201| r2201_1(glval<ClassWithDestructor>) = VariableAddress[x] :
# 2201| r2201_2(glval<unknown>) = FunctionAddress[set_x] :
# 2201| r2201_3(char) = Constant[97] :
# 2201| v2201_4(void) = Call[set_x] : func:r2201_2, this:r2201_1, 0:r2201_3
# 2201| mu2201_5(unknown) = ^CallSideEffect : ~m?
# 2201| v2201_6(void) = ^IndirectReadSideEffect[-1] : &:r2201_1, ~m?
# 2201| mu2201_7(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2201_1
# 2201| r2201_1(glval<ClassWithDestructor>) = VariableAddress[x] :
# 2201| r2201_2(glval<unknown>) = FunctionAddress[set_x] :
# 2201| r2201_3(char) = Constant[97] :
# 2201| v2201_4(void) = Call[set_x] : func:r2201_2, this:r2201_1, 0:r2201_3
# 2201| mu2201_5(unknown) = ^CallSideEffect : ~m?
# 2201| v2201_6(void) = ^IndirectReadSideEffect[-1] : &:r2201_1, ~m?
# 2201| mu2201_7(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2201_1
#-----| Goto -> Block 3
# 2201| Block 3
# 2201| r2201_8(glval<ClassWithDestructor>) = VariableAddress[x] :
# 2201| r2201_9(glval<unknown>) = FunctionAddress[~ClassWithDestructor] :
# 2201| v2201_10(void) = Call[~ClassWithDestructor] : func:r2201_9, this:r2201_8
# 2201| mu2201_11(unknown) = ^CallSideEffect : ~m?
# 2201| v2201_12(void) = ^IndirectReadSideEffect[-1] : &:r2201_8, ~m?
# 2201| mu2201_13(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2201_8
#-----| Goto -> Block 3
# 2203| Block 3
# 2203| r2203_1(glval<ClassWithDestructor>) = VariableAddress[x] :
# 2203| mu2203_2(ClassWithDestructor) = Uninitialized[x] : &:r2203_1
# 2203| r2203_3(glval<unknown>) = FunctionAddress[ClassWithDestructor] :
# 2203| v2203_4(void) = Call[ClassWithDestructor] : func:r2203_3, this:r2203_1
# 2203| mu2203_5(unknown) = ^CallSideEffect : ~m?
# 2203| mu2203_6(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2203_1
# 2203| r2203_7(bool) = Constant[1] :
# 2203| v2203_8(void) = ConditionalBranch : r2203_7
# 2203| r2203_1(glval<ClassWithDestructor>) = VariableAddress[x] :
# 2203| mu2203_2(ClassWithDestructor) = Uninitialized[x] : &:r2203_1
# 2203| r2203_3(glval<unknown>) = FunctionAddress[ClassWithDestructor] :
# 2203| v2203_4(void) = Call[ClassWithDestructor] : func:r2203_3, this:r2203_1
# 2203| mu2203_5(unknown) = ^CallSideEffect : ~m?
# 2203| mu2203_6(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2203_1
# 2203| r2203_7(bool) = Constant[1] :
# 2203| v2203_8(void) = ConditionalBranch : r2203_7
#-----| False -> Block 5
#-----| True -> Block 4
# 2204| Block 4
# 2204| r2204_1(glval<ClassWithDestructor>) = VariableAddress[x] :
# 2204| r2204_2(glval<unknown>) = FunctionAddress[set_x] :
# 2204| r2204_3(char) = Constant[97] :
# 2204| v2204_4(void) = Call[set_x] : func:r2204_2, this:r2204_1, 0:r2204_3
# 2204| mu2204_5(unknown) = ^CallSideEffect : ~m?
# 2204| v2204_6(void) = ^IndirectReadSideEffect[-1] : &:r2204_1, ~m?
# 2204| mu2204_7(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2204_1
# 2204| r2204_1(glval<ClassWithDestructor>) = VariableAddress[x] :
# 2204| r2204_2(glval<unknown>) = FunctionAddress[set_x] :
# 2204| r2204_3(char) = Constant[97] :
# 2204| v2204_4(void) = Call[set_x] : func:r2204_2, this:r2204_1, 0:r2204_3
# 2204| mu2204_5(unknown) = ^CallSideEffect : ~m?
# 2204| v2204_6(void) = ^IndirectReadSideEffect[-1] : &:r2204_1, ~m?
# 2204| mu2204_7(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2204_1
#-----| Goto -> Block 5
# 2204| Block 5
# 2204| r2204_8(glval<ClassWithDestructor>) = VariableAddress[x] :
# 2204| r2204_9(glval<unknown>) = FunctionAddress[~ClassWithDestructor] :
# 2204| v2204_10(void) = Call[~ClassWithDestructor] : func:r2204_9, this:r2204_8
# 2204| mu2204_11(unknown) = ^CallSideEffect : ~m?
# 2204| v2204_12(void) = ^IndirectReadSideEffect[-1] : &:r2204_8, ~m?
# 2204| mu2204_13(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2204_8
#-----| Goto -> Block 5
# 2206| Block 5
# 2206| r2206_1(glval<ClassWithDestructor>) = VariableAddress[x] :
# 2206| mu2206_2(ClassWithDestructor) = Uninitialized[x] : &:r2206_1
# 2206| r2206_3(glval<unknown>) = FunctionAddress[ClassWithDestructor] :
# 2206| v2206_4(void) = Call[ClassWithDestructor] : func:r2206_3, this:r2206_1
# 2206| mu2206_5(unknown) = ^CallSideEffect : ~m?
# 2206| mu2206_6(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2206_1
# 2206| r2206_7(glval<char>) = VariableAddress[c] :
# 2206| r2206_8(char) = Load[c] : &:r2206_7, ~m?
# 2206| r2206_9(int) = Convert : r2206_8
# 2206| v2206_10(void) = Switch : r2206_9
# 2206| r2206_1(glval<ClassWithDestructor>) = VariableAddress[x] :
# 2206| mu2206_2(ClassWithDestructor) = Uninitialized[x] : &:r2206_1
# 2206| r2206_3(glval<unknown>) = FunctionAddress[ClassWithDestructor] :
# 2206| v2206_4(void) = Call[ClassWithDestructor] : func:r2206_3, this:r2206_1
# 2206| mu2206_5(unknown) = ^CallSideEffect : ~m?
# 2206| mu2206_6(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2206_1
# 2206| r2206_7(glval<char>) = VariableAddress[c] :
# 2206| r2206_8(char) = Load[c] : &:r2206_7, ~m?
# 2206| r2206_9(int) = Convert : r2206_8
# 2206| v2206_10(void) = Switch : r2206_9
#-----| Case[97] -> Block 6
#-----| Default -> Block 7
@@ -16641,20 +16641,20 @@ ir.cpp:
#-----| True -> Block 1
# 2547| Block 1
# 2547| v2547_1(void) = NoOp :
# 2547| v2547_1(void) = NoOp :
#-----| Goto -> Block 2
# 2547| Block 2
# 2547| r2547_2(glval<ClassWithDestructor>) = CopyValue : r2546_2
# 2547| r2547_3(glval<unknown>) = FunctionAddress[~ClassWithDestructor] :
# 2547| v2547_4(void) = Call[~ClassWithDestructor] : func:r2547_3, this:r2547_2
# 2547| mu2547_5(unknown) = ^CallSideEffect : ~m?
# 2547| v2547_6(void) = ^IndirectReadSideEffect[-1] : &:r2547_2, ~m?
# 2547| mu2547_7(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2547_2
#-----| Goto -> Block 2
# 2548| Block 2
# 2548| v2548_1(void) = NoOp :
# 2545| v2545_6(void) = ReturnVoid :
# 2545| v2545_7(void) = AliasedUse : ~m?
# 2545| v2545_8(void) = ExitFunction :
# 2548| v2548_1(void) = NoOp :
# 2545| v2545_6(void) = ReturnVoid :
# 2545| v2545_7(void) = AliasedUse : ~m?
# 2545| v2545_8(void) = ExitFunction :
# 2550| void constexpr_inconsistency(bool)
# 2550| Block 0
@@ -16678,20 +16678,20 @@ ir.cpp:
#-----| True -> Block 1
# 2552| Block 1
# 2552| v2552_1(void) = NoOp :
# 2552| v2552_1(void) = NoOp :
#-----| Goto -> Block 2
# 2552| Block 2
# 2552| r2552_2(glval<ClassWithDestructor>) = CopyValue : r2551_2
# 2552| r2552_3(glval<unknown>) = FunctionAddress[~ClassWithDestructor] :
# 2552| v2552_4(void) = Call[~ClassWithDestructor] : func:r2552_3, this:r2552_2
# 2552| mu2552_5(unknown) = ^CallSideEffect : ~m?
# 2552| v2552_6(void) = ^IndirectReadSideEffect[-1] : &:r2552_2, ~m?
# 2552| mu2552_7(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2552_2
#-----| Goto -> Block 2
# 2553| Block 2
# 2553| v2553_1(void) = NoOp :
# 2550| v2550_6(void) = ReturnVoid :
# 2550| v2550_7(void) = AliasedUse : ~m?
# 2550| v2550_8(void) = ExitFunction :
# 2553| v2553_1(void) = NoOp :
# 2550| v2550_6(void) = ReturnVoid :
# 2550| v2550_7(void) = AliasedUse : ~m?
# 2550| v2550_8(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()