C++: tests for destructors after a while-loop condition

This commit is contained in:
Robert Marsh
2024-02-12 23:55:42 +00:00
parent d1160f86e1
commit bac7e46b0f
5 changed files with 328 additions and 0 deletions

View File

@@ -16580,6 +16580,77 @@ ir.cpp:
# 2189| <params>:
# 2190| [Destructor] void Bool2::~Bool2()
# 2190| <params>:
# 2193| [TopLevelFunction] void WhileLoopDestructors(bool)
# 2193| <params>:
# 2193| getParameter(0): [Parameter] b
# 2193| Type = [BoolType] bool
# 2193| getEntryPoint(): [BlockStmt] { ... }
# 2194| getStmt(0): [BlockStmt] { ... }
# 2195| getStmt(0): [DeclStmt] declaration
# 2195| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
# 2195| Type = [Struct] String
# 2195| getVariable().getInitializer(): [Initializer] initializer for s
# 2195| getExpr(): [ConstructorCall] call to String
# 2195| Type = [VoidType] void
# 2195| ValueCategory = prvalue
# 2196| getStmt(1): [WhileStmt] while (...) ...
# 2196| getCondition(): [VariableAccess] b
# 2196| Type = [BoolType] bool
# 2196| ValueCategory = prvalue(load)
# 2196| getStmt(): [BlockStmt] { ... }
# 2197| getStmt(0): [ExprStmt] ExprStmt
# 2197| getExpr(): [AssignExpr] ... = ...
# 2197| Type = [BoolType] bool
# 2197| ValueCategory = lvalue
# 2197| getLValue(): [VariableAccess] b
# 2197| Type = [BoolType] bool
# 2197| ValueCategory = lvalue
# 2197| getRValue(): [Literal] 0
# 2197| Type = [BoolType] bool
# 2197| Value = [Literal] 0
# 2197| ValueCategory = prvalue
# 2199| getImplicitDestructorCall(0): [DestructorCall] call to ~String
# 2199| Type = [VoidType] void
# 2199| ValueCategory = prvalue
# 2199| getQualifier(): [VariableAccess] s
# 2199| Type = [Struct] String
# 2199| ValueCategory = lvalue
# 2201| getStmt(1): [BlockStmt] { ... }
# 2202| getStmt(0): [WhileStmt] while (...) ...
# 2202| getCondition(): [ConditionDeclExpr] (condition decl)
# 2202| Type = [BoolType] bool
# 2202| ValueCategory = prvalue
# 2202| getChild(0): [FunctionCall] call to operator bool
# 2202| Type = [BoolType] bool
# 2202| ValueCategory = prvalue
# 2202| getQualifier(): [VariableAccess] B
# 2202| Type = [Class] Bool
# 2202| ValueCategory = prvalue(load)
# 2202| getStmt(): [BlockStmt] { ... }
# 2203| getStmt(0): [ExprStmt] ExprStmt
# 2203| getExpr(): [AssignExpr] ... = ...
# 2203| Type = [BoolType] bool
# 2203| ValueCategory = lvalue
# 2203| getLValue(): [VariableAccess] b
# 2203| Type = [BoolType] bool
# 2203| ValueCategory = lvalue
# 2203| getRValue(): [Literal] 0
# 2203| Type = [BoolType] bool
# 2203| Value = [Literal] 0
# 2203| ValueCategory = prvalue
# 2204| getImplicitDestructorCall(0): [DestructorCall] call to ~Bool
# 2204| Type = [VoidType] void
# 2204| ValueCategory = prvalue
# 2204| getQualifier(): [VariableAccess] B
# 2204| Type = [Class] Bool
# 2204| ValueCategory = lvalue
# 2204| getImplicitDestructorCall(0): [DestructorCall] call to ~Bool
# 2204| Type = [VoidType] void
# 2204| ValueCategory = prvalue
# 2204| getQualifier(): [VariableAccess] B
# 2204| Type = [Class] Bool
# 2204| ValueCategory = lvalue
# 2206| getStmt(2): [ReturnStmt] return ...
perf-regression.cpp:
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
# 4| <params>:

View File

@@ -13163,6 +13163,95 @@ ir.cpp:
# 2177| v2177_8(void) = AliasedUse : ~m2182_14
# 2177| v2177_9(void) = ExitFunction :
# 2193| void WhileLoopDestructors(bool)
# 2193| Block 0
# 2193| v2193_1(void) = EnterFunction :
# 2193| m2193_2(unknown) = AliasedDefinition :
# 2193| m2193_3(unknown) = InitializeNonLocal :
# 2193| m2193_4(unknown) = Chi : total:m2193_2, partial:m2193_3
# 2193| r2193_5(glval<bool>) = VariableAddress[b] :
# 2193| m2193_6(bool) = InitializeParameter[b] : &:r2193_5
# 2195| r2195_1(glval<String>) = VariableAddress[s] :
# 2195| m2195_2(String) = Uninitialized[s] : &:r2195_1
# 2195| r2195_3(glval<unknown>) = FunctionAddress[String] :
# 2195| v2195_4(void) = Call[String] : func:r2195_3, this:r2195_1
# 2195| m2195_5(unknown) = ^CallSideEffect : ~m2193_4
# 2195| m2195_6(unknown) = Chi : total:m2193_4, partial:m2195_5
# 2195| m2195_7(String) = ^IndirectMayWriteSideEffect[-1] : &:r2195_1
# 2195| m2195_8(String) = Chi : total:m2195_2, partial:m2195_7
#-----| Goto -> Block 1
# 2196| Block 1
# 2196| m2196_1(bool) = Phi : from 0:m2193_6, from 2:m2197_3
# 2196| r2196_2(glval<bool>) = VariableAddress[b] :
# 2196| r2196_3(bool) = Load[b] : &:r2196_2, m2196_1
# 2196| v2196_4(void) = ConditionalBranch : r2196_3
#-----| False -> Block 3
#-----| True -> Block 2
# 2197| Block 2
# 2197| r2197_1(bool) = Constant[0] :
# 2197| r2197_2(glval<bool>) = VariableAddress[b] :
# 2197| m2197_3(bool) = Store[b] : &:r2197_2, r2197_1
#-----| Goto (back edge) -> Block 1
# 2199| Block 3
# 2199| r2199_1(glval<String>) = VariableAddress[s] :
# 2199| r2199_2(glval<unknown>) = FunctionAddress[~String] :
# 2199| v2199_3(void) = Call[~String] : func:r2199_2, this:r2199_1
# 2199| m2199_4(unknown) = ^CallSideEffect : ~m2195_6
# 2199| m2199_5(unknown) = Chi : total:m2195_6, partial:m2199_4
# 2199| v2199_6(void) = ^IndirectReadSideEffect[-1] : &:r2199_1, m2195_8
# 2199| m2199_7(String) = ^IndirectMayWriteSideEffect[-1] : &:r2199_1
# 2199| m2199_8(String) = Chi : total:m2195_8, partial:m2199_7
#-----| Goto -> Block 4
# 2202| Block 4
# 2202| m2202_1(unknown) = Phi : from 3:~m2199_5, from 5:~m2204_5
# 2202| m2202_2(bool) = Phi : from 3:m2196_1, from 5:m2203_3
# 2202| r2202_3(glval<Bool>) = VariableAddress[B] :
# 2202| m2202_4(Bool) = Uninitialized[B] : &:r2202_3
# 2202| r2202_5(glval<unknown>) = FunctionAddress[Bool] :
# 2202| r2202_6(glval<bool>) = VariableAddress[b] :
# 2202| r2202_7(bool) = Load[b] : &:r2202_6, m2202_2
# 2202| v2202_8(void) = Call[Bool] : func:r2202_5, this:r2202_3, 0:r2202_7
# 2202| m2202_9(unknown) = ^CallSideEffect : ~m2202_1
# 2202| m2202_10(unknown) = Chi : total:m2202_1, partial:m2202_9
# 2202| m2202_11(Bool) = ^IndirectMayWriteSideEffect[-1] : &:r2202_3
# 2202| m2202_12(Bool) = Chi : total:m2202_4, partial:m2202_11
# 2202| r2202_13(glval<Bool>) = VariableAddress[B] :
# 2202| r2202_14(glval<unknown>) = FunctionAddress[operator bool] :
# 2202| r2202_15(bool) = Call[operator bool] : func:r2202_14, this:r2202_13
# 2202| m2202_16(unknown) = ^CallSideEffect : ~m2202_10
# 2202| m2202_17(unknown) = Chi : total:m2202_10, partial:m2202_16
# 2202| v2202_18(void) = ^IndirectReadSideEffect[-1] : &:r2202_13, m2202_12
# 2202| m2202_19(Bool) = ^IndirectMayWriteSideEffect[-1] : &:r2202_13
# 2202| m2202_20(Bool) = Chi : total:m2202_12, partial:m2202_19
# 2202| r2202_21(bool) = CopyValue : r2202_15
# 2202| v2202_22(void) = ConditionalBranch : r2202_21
#-----| False -> Block 6
#-----| True -> Block 5
# 2203| Block 5
# 2203| r2203_1(bool) = Constant[0] :
# 2203| r2203_2(glval<bool>) = VariableAddress[b] :
# 2203| m2203_3(bool) = Store[b] : &:r2203_2, r2203_1
# 2204| r2204_1(glval<Bool>) = VariableAddress[B] :
# 2204| r2204_2(glval<unknown>) = FunctionAddress[~Bool] :
# 2204| v2204_3(void) = Call[~Bool] : func:r2204_2, this:r2204_1
# 2204| m2204_4(unknown) = ^CallSideEffect : ~m2202_17
# 2204| m2204_5(unknown) = Chi : total:m2202_17, partial:m2204_4
# 2204| v2204_6(void) = ^IndirectReadSideEffect[-1] : &:r2204_1, m2202_20
# 2204| m2204_7(Bool) = ^IndirectMayWriteSideEffect[-1] : &:r2204_1
# 2204| m2204_8(Bool) = Chi : total:m2202_20, partial:m2204_7
#-----| Goto (back edge) -> Block 4
# 2206| Block 6
# 2206| v2206_1(void) = NoOp :
# 2193| v2193_7(void) = ReturnVoid :
# 2193| v2193_8(void) = AliasedUse : ~m2202_17
# 2193| v2193_9(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0

View File

@@ -2190,4 +2190,18 @@ class Bool2 {
~Bool2();
};
void WhileLoopDestructors(bool b) {
{
String s;
while(b) {
b = false;
}
}
{
while (Bool B = Bool(b)) {
b = false;
}
}
}
// semmle-extractor-options: -std=c++17 --clang

View File

@@ -10758,6 +10758,76 @@
| ir.cpp:2182:5:2182:5 | SideEffect | m2181_8 |
| ir.cpp:2182:5:2182:5 | SideEffect | ~m2181_6 |
| ir.cpp:2182:5:2182:5 | SideEffect | ~m2182_9 |
| ir.cpp:2193:6:2193:25 | ChiPartial | partial:m2193_3 |
| ir.cpp:2193:6:2193:25 | ChiTotal | total:m2193_2 |
| ir.cpp:2193:6:2193:25 | SideEffect | ~m2202_17 |
| ir.cpp:2193:32:2193:32 | Address | &:r2193_5 |
| ir.cpp:2195:16:2195:16 | Address | &:r2195_1 |
| ir.cpp:2195:16:2195:16 | Address | &:r2195_1 |
| ir.cpp:2195:16:2195:16 | Arg(this) | this:r2195_1 |
| ir.cpp:2195:16:2195:16 | CallTarget | func:r2195_3 |
| ir.cpp:2195:16:2195:16 | ChiPartial | partial:m2195_5 |
| ir.cpp:2195:16:2195:16 | ChiPartial | partial:m2195_7 |
| ir.cpp:2195:16:2195:16 | ChiTotal | total:m2193_4 |
| ir.cpp:2195:16:2195:16 | ChiTotal | total:m2195_2 |
| ir.cpp:2195:16:2195:16 | SideEffect | ~m2193_4 |
| ir.cpp:2196:15:2196:15 | Address | &:r2196_2 |
| ir.cpp:2196:15:2196:15 | Condition | r2196_3 |
| ir.cpp:2196:15:2196:15 | Load | m2196_1 |
| ir.cpp:2196:15:2196:15 | Phi | from 0:m2193_6 |
| ir.cpp:2196:15:2196:15 | Phi | from 2:m2197_3 |
| ir.cpp:2197:13:2197:13 | Address | &:r2197_2 |
| ir.cpp:2197:17:2197:21 | StoreValue | r2197_1 |
| ir.cpp:2199:5:2199:5 | Address | &:r2199_1 |
| ir.cpp:2199:5:2199:5 | Address | &:r2199_1 |
| ir.cpp:2199:5:2199:5 | Arg(this) | this:r2199_1 |
| ir.cpp:2199:5:2199:5 | CallTarget | func:r2199_2 |
| ir.cpp:2199:5:2199:5 | ChiPartial | partial:m2199_4 |
| ir.cpp:2199:5:2199:5 | ChiPartial | partial:m2199_7 |
| ir.cpp:2199:5:2199:5 | ChiTotal | total:m2195_6 |
| ir.cpp:2199:5:2199:5 | ChiTotal | total:m2195_8 |
| ir.cpp:2199:5:2199:5 | SideEffect | m2195_8 |
| ir.cpp:2199:5:2199:5 | SideEffect | ~m2195_6 |
| ir.cpp:2202:16:2202:31 | Address | &:r2202_3 |
| ir.cpp:2202:16:2202:31 | Address | &:r2202_3 |
| ir.cpp:2202:16:2202:31 | Arg(this) | this:r2202_3 |
| ir.cpp:2202:16:2202:31 | Condition | r2202_21 |
| ir.cpp:2202:16:2202:31 | Phi | from 3:m2196_1 |
| ir.cpp:2202:16:2202:31 | Phi | from 3:~m2199_5 |
| ir.cpp:2202:16:2202:31 | Phi | from 5:m2203_3 |
| ir.cpp:2202:16:2202:31 | Phi | from 5:~m2204_5 |
| ir.cpp:2202:21:2202:21 | Address | &:r2202_13 |
| ir.cpp:2202:21:2202:21 | Address | &:r2202_13 |
| ir.cpp:2202:21:2202:21 | Arg(this) | this:r2202_13 |
| ir.cpp:2202:21:2202:21 | CallTarget | func:r2202_14 |
| ir.cpp:2202:21:2202:21 | ChiPartial | partial:m2202_16 |
| ir.cpp:2202:21:2202:21 | ChiPartial | partial:m2202_19 |
| ir.cpp:2202:21:2202:21 | ChiTotal | total:m2202_10 |
| ir.cpp:2202:21:2202:21 | ChiTotal | total:m2202_12 |
| ir.cpp:2202:21:2202:21 | SideEffect | m2202_12 |
| ir.cpp:2202:21:2202:21 | SideEffect | ~m2202_10 |
| ir.cpp:2202:21:2202:21 | Unary | r2202_15 |
| ir.cpp:2202:24:2202:31 | CallTarget | func:r2202_5 |
| ir.cpp:2202:24:2202:31 | ChiPartial | partial:m2202_9 |
| ir.cpp:2202:24:2202:31 | ChiPartial | partial:m2202_11 |
| ir.cpp:2202:24:2202:31 | ChiTotal | total:m2202_1 |
| ir.cpp:2202:24:2202:31 | ChiTotal | total:m2202_4 |
| ir.cpp:2202:24:2202:31 | SideEffect | ~m2202_1 |
| ir.cpp:2202:30:2202:30 | Address | &:r2202_6 |
| ir.cpp:2202:30:2202:30 | Arg(0) | 0:r2202_7 |
| ir.cpp:2202:30:2202:30 | Load | m2202_2 |
| ir.cpp:2203:13:2203:13 | Address | &:r2203_2 |
| ir.cpp:2203:17:2203:21 | StoreValue | r2203_1 |
| ir.cpp:2204:9:2204:9 | Address | &:r2204_1 |
| ir.cpp:2204:9:2204:9 | Address | &:r2204_1 |
| ir.cpp:2204:9:2204:9 | Arg(this) | this:r2204_1 |
| ir.cpp:2204:9:2204:9 | CallTarget | func:r2204_2 |
| ir.cpp:2204:9:2204:9 | ChiPartial | partial:m2204_4 |
| ir.cpp:2204:9:2204:9 | ChiPartial | partial:m2204_7 |
| ir.cpp:2204:9:2204:9 | ChiTotal | total:m2202_17 |
| ir.cpp:2204:9:2204:9 | ChiTotal | total:m2202_20 |
| ir.cpp:2204:9:2204:9 | SideEffect | m2202_20 |
| ir.cpp:2204:9:2204:9 | SideEffect | ~m2202_17 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_7 |

View File

@@ -12250,6 +12250,90 @@ ir.cpp:
# 2177| v2177_7(void) = AliasedUse : ~m?
# 2177| v2177_8(void) = ExitFunction :
# 2193| void WhileLoopDestructors(bool)
# 2193| Block 0
# 2193| v2193_1(void) = EnterFunction :
# 2193| mu2193_2(unknown) = AliasedDefinition :
# 2193| mu2193_3(unknown) = InitializeNonLocal :
# 2193| r2193_4(glval<bool>) = VariableAddress[b] :
# 2193| mu2193_5(bool) = InitializeParameter[b] : &:r2193_4
# 2195| r2195_1(glval<String>) = VariableAddress[s] :
# 2195| mu2195_2(String) = Uninitialized[s] : &:r2195_1
# 2195| r2195_3(glval<unknown>) = FunctionAddress[String] :
# 2195| v2195_4(void) = Call[String] : func:r2195_3, this:r2195_1
# 2195| mu2195_5(unknown) = ^CallSideEffect : ~m?
# 2195| mu2195_6(String) = ^IndirectMayWriteSideEffect[-1] : &:r2195_1
#-----| Goto -> Block 1
# 2196| Block 1
# 2196| r2196_1(glval<bool>) = VariableAddress[b] :
# 2196| r2196_2(bool) = Load[b] : &:r2196_1, ~m?
# 2196| v2196_3(void) = ConditionalBranch : r2196_2
#-----| False -> Block 3
#-----| True -> Block 2
# 2197| Block 2
# 2197| r2197_1(bool) = Constant[0] :
# 2197| r2197_2(glval<bool>) = VariableAddress[b] :
# 2197| mu2197_3(bool) = Store[b] : &:r2197_2, r2197_1
#-----| Goto (back edge) -> Block 1
# 2199| Block 3
# 2199| r2199_1(glval<String>) = VariableAddress[s] :
# 2199| r2199_2(glval<unknown>) = FunctionAddress[~String] :
# 2199| v2199_3(void) = Call[~String] : func:r2199_2, this:r2199_1
# 2199| mu2199_4(unknown) = ^CallSideEffect : ~m?
# 2199| v2199_5(void) = ^IndirectReadSideEffect[-1] : &:r2199_1, ~m?
# 2199| mu2199_6(String) = ^IndirectMayWriteSideEffect[-1] : &:r2199_1
#-----| Goto -> Block 4
# 2202| Block 4
# 2202| r2202_1(glval<Bool>) = VariableAddress[B] :
# 2202| mu2202_2(Bool) = Uninitialized[B] : &:r2202_1
# 2202| r2202_3(glval<unknown>) = FunctionAddress[Bool] :
# 2202| r2202_4(glval<bool>) = VariableAddress[b] :
# 2202| r2202_5(bool) = Load[b] : &:r2202_4, ~m?
# 2202| v2202_6(void) = Call[Bool] : func:r2202_3, this:r2202_1, 0:r2202_5
# 2202| mu2202_7(unknown) = ^CallSideEffect : ~m?
# 2202| mu2202_8(Bool) = ^IndirectMayWriteSideEffect[-1] : &:r2202_1
# 2202| r2202_9(glval<Bool>) = VariableAddress[B] :
# 2202| r2202_10(glval<unknown>) = FunctionAddress[operator bool] :
# 2202| r2202_11(bool) = Call[operator bool] : func:r2202_10, this:r2202_9
# 2202| mu2202_12(unknown) = ^CallSideEffect : ~m?
# 2202| v2202_13(void) = ^IndirectReadSideEffect[-1] : &:r2202_9, ~m?
# 2202| mu2202_14(Bool) = ^IndirectMayWriteSideEffect[-1] : &:r2202_9
# 2202| r2202_15(bool) = CopyValue : r2202_11
# 2202| v2202_16(void) = ConditionalBranch : r2202_15
#-----| False -> Block 7
#-----| True -> Block 5
# 2203| Block 5
# 2203| r2203_1(bool) = Constant[0] :
# 2203| r2203_2(glval<bool>) = VariableAddress[b] :
# 2203| mu2203_3(bool) = Store[b] : &:r2203_2, r2203_1
# 2204| r2204_1(glval<Bool>) = VariableAddress[B] :
# 2204| r2204_2(glval<unknown>) = FunctionAddress[~Bool] :
# 2204| v2204_3(void) = Call[~Bool] : func:r2204_2, this:r2204_1
# 2204| mu2204_4(unknown) = ^CallSideEffect : ~m?
# 2204| v2204_5(void) = ^IndirectReadSideEffect[-1] : &:r2204_1, ~m?
# 2204| mu2204_6(Bool) = ^IndirectMayWriteSideEffect[-1] : &:r2204_1
#-----| Goto (back edge) -> Block 4
# 2204| Block 6
# 2204| r2204_7(glval<Bool>) = VariableAddress[B] :
# 2204| r2204_8(glval<unknown>) = FunctionAddress[~Bool] :
# 2204| v2204_9(void) = Call[~Bool] : func:r2204_8, this:r2204_7
# 2204| mu2204_10(unknown) = ^CallSideEffect : ~m?
# 2204| v2204_11(void) = ^IndirectReadSideEffect[-1] : &:r2204_7, ~m?
# 2204| mu2204_12(Bool) = ^IndirectMayWriteSideEffect[-1] : &:r2204_7
#-----| Goto -> Block 7
# 2206| Block 7
# 2206| v2206_1(void) = NoOp :
# 2193| v2193_6(void) = ReturnVoid :
# 2193| v2193_7(void) = AliasedUse : ~m?
# 2193| v2193_8(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0