From 05819a52ef15a456af6fdc11daebe23a1badd84f Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Thu, 25 Apr 2024 13:20:21 +0200 Subject: [PATCH] C++: Print destructors for children of statements that are again statements --- cpp/ql/lib/semmle/code/cpp/PrintAST.qll | 26 +++ .../library-tests/ir/ir/PrintAST.expected | 108 +++++++++++++ .../library-tests/ir/ir/aliased_ir.expected | 153 ++++++++++++++++++ cpp/ql/test/library-tests/ir/ir/ir.cpp | 17 ++ .../test/library-tests/ir/ir/raw_ir.expected | 128 +++++++++++++++ 5 files changed, 432 insertions(+) diff --git a/cpp/ql/lib/semmle/code/cpp/PrintAST.qll b/cpp/ql/lib/semmle/code/cpp/PrintAST.qll index beabef322d20..b515a346bf3b 100644 --- a/cpp/ql/lib/semmle/code/cpp/PrintAST.qll +++ b/cpp/ql/lib/semmle/code/cpp/PrintAST.qll @@ -463,6 +463,25 @@ class StmtNode extends AstNode { } } +/** + * A node representing a child of a `Stmt` that is itself a `Stmt`. + */ +class ChildStmtNode extends StmtNode { + Stmt childStmt; + + ChildStmtNode() { exists(Stmt parent | parent.getAChild() = childStmt and childStmt = ast) } + + override BaseAstNode getChildInternal(int childIndex) { + result = super.getChildInternal(childIndex) + or + exists(int destructorIndex | + result.getAst() = childStmt.getImplicitDestructorCall(destructorIndex) and + childIndex = + destructorIndex + max(int index | exists(childStmt.getChild(index)) or index = 0) + 1 + ) + } +} + /** * A node representing a `DeclStmt`. */ @@ -674,6 +693,13 @@ class FunctionNode extends FunctionOrGlobalOrNamespaceVariableNode { private string getChildAccessorWithoutConversions(Locatable parent, Element child) { shouldPrintDeclaration(getAnEnclosingDeclaration(parent)) and ( + exists(Stmt s, int i | s.getChild(i) = parent | + exists(int n | + s.getChild(i).(Stmt).getImplicitDestructorCall(n) = child and + result = "getImplicitDestructorCall(" + n + ")" + ) + ) + or exists(Stmt s | s = parent | namedStmtChildPredicates(s, child, result) or diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index 1f6a29b57ed6..e0d2da046b2e 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -22334,6 +22334,114 @@ ir.cpp: # 2480| Type = [Struct] B # 2480| ValueCategory = xvalue # 2481| getStmt(1): [ReturnStmt] return ... +# 2484| [TopLevelFunction] void destructor_without_block(bool) +# 2484| : +# 2484| getParameter(0): [Parameter] b +# 2484| Type = [BoolType] bool +# 2485| getEntryPoint(): [BlockStmt] { ... } +# 2486| getStmt(0): [IfStmt] if (...) ... +# 2486| getCondition(): [VariableAccess] b +# 2486| Type = [BoolType] bool +# 2486| ValueCategory = prvalue(load) +# 2487| getThen(): [DeclStmt] declaration +# 2487| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c +# 2487| Type = [Class] ClassWithDestructor +# 2487| getVariable().getInitializer(): [Initializer] initializer for c +# 2487| getExpr(): [ConstructorCall] call to ClassWithDestructor +# 2487| Type = [VoidType] void +# 2487| ValueCategory = prvalue +#-----| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor +#-----| Type = [VoidType] void +#-----| ValueCategory = prvalue +#-----| getQualifier(): [VariableAccess] c +#-----| Type = [Class] ClassWithDestructor +#-----| ValueCategory = lvalue +# 2489| getStmt(1): [IfStmt] if (...) ... +# 2489| getCondition(): [VariableAccess] b +# 2489| Type = [BoolType] bool +# 2489| ValueCategory = prvalue(load) +# 2490| getThen(): [DeclStmt] declaration +# 2490| getDeclarationEntry(0): [VariableDeclarationEntry] definition of d +# 2490| Type = [Class] ClassWithDestructor +# 2490| getVariable().getInitializer(): [Initializer] initializer for d +# 2490| getExpr(): [ConstructorCall] call to ClassWithDestructor +# 2490| Type = [VoidType] void +# 2490| ValueCategory = prvalue +#-----| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor +#-----| Type = [VoidType] void +#-----| ValueCategory = prvalue +#-----| getQualifier(): [VariableAccess] d +#-----| Type = [Class] ClassWithDestructor +#-----| ValueCategory = lvalue +# 2492| getElse(): [DeclStmt] declaration +# 2492| getDeclarationEntry(0): [VariableDeclarationEntry] definition of e +# 2492| Type = [Class] ClassWithDestructor +# 2492| getVariable().getInitializer(): [Initializer] initializer for e +# 2492| getExpr(): [ConstructorCall] call to ClassWithDestructor +# 2492| Type = [VoidType] void +# 2492| ValueCategory = prvalue +#-----| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor +#-----| Type = [VoidType] void +#-----| ValueCategory = prvalue +#-----| getQualifier(): [VariableAccess] e +#-----| Type = [Class] ClassWithDestructor +#-----| ValueCategory = lvalue +# 2494| getStmt(2): [WhileStmt] while (...) ... +# 2494| getCondition(): [VariableAccess] b +# 2494| Type = [BoolType] bool +# 2494| ValueCategory = prvalue(load) +# 2495| getStmt(): [DeclStmt] declaration +# 2495| getDeclarationEntry(0): [VariableDeclarationEntry] definition of f +# 2495| Type = [Class] ClassWithDestructor +# 2495| getVariable().getInitializer(): [Initializer] initializer for f +# 2495| getExpr(): [ConstructorCall] call to ClassWithDestructor +# 2495| Type = [VoidType] void +# 2495| ValueCategory = prvalue +#-----| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor +#-----| Type = [VoidType] void +#-----| ValueCategory = prvalue +#-----| getQualifier(): [VariableAccess] f +#-----| Type = [Class] ClassWithDestructor +#-----| ValueCategory = lvalue +# 2497| getStmt(3): [ForStmt] for(...;...;...) ... +# 2497| getInitialization(): [DeclStmt] declaration +# 2497| getDeclarationEntry(0): [VariableDeclarationEntry] definition of i +# 2497| Type = [IntType] int +# 2497| getVariable().getInitializer(): [Initializer] initializer for i +# 2497| getExpr(): [Literal] 0 +# 2497| Type = [IntType] int +# 2497| Value = [Literal] 0 +# 2497| ValueCategory = prvalue +# 2497| getCondition(): [LTExpr] ... < ... +# 2497| Type = [BoolType] bool +# 2497| ValueCategory = prvalue +# 2497| getLesserOperand(): [VariableAccess] i +# 2497| Type = [IntType] int +# 2497| ValueCategory = prvalue(load) +# 2497| getGreaterOperand(): [Literal] 42 +# 2497| Type = [IntType] int +# 2497| Value = [Literal] 42 +# 2497| ValueCategory = prvalue +# 2497| getUpdate(): [PrefixIncrExpr] ++ ... +# 2497| Type = [IntType] int +# 2497| ValueCategory = lvalue +# 2497| getOperand(): [VariableAccess] i +# 2497| Type = [IntType] int +# 2497| ValueCategory = lvalue +# 2498| getStmt(): [DeclStmt] declaration +# 2498| getDeclarationEntry(0): [VariableDeclarationEntry] definition of g +# 2498| Type = [Class] ClassWithDestructor +# 2498| getVariable().getInitializer(): [Initializer] initializer for g +# 2498| getExpr(): [ConstructorCall] call to ClassWithDestructor +# 2498| Type = [VoidType] void +# 2498| ValueCategory = prvalue +#-----| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor +#-----| Type = [VoidType] void +#-----| ValueCategory = prvalue +#-----| getQualifier(): [VariableAccess] g +#-----| Type = [Class] ClassWithDestructor +#-----| ValueCategory = lvalue +# 2499| getStmt(4): [ReturnStmt] return ... perf-regression.cpp: # 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&) # 4| : diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected index 51e12b7a6e5d..3d3a56e790e9 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -17805,6 +17805,159 @@ ir.cpp: # 2478| v2478_6(void) = AliasedUse : ~m2480_20 # 2478| v2478_7(void) = ExitFunction : +# 2484| void destructor_without_block(bool) +# 2484| Block 0 +# 2484| v2484_1(void) = EnterFunction : +# 2484| m2484_2(unknown) = AliasedDefinition : +# 2484| m2484_3(unknown) = InitializeNonLocal : +# 2484| m2484_4(unknown) = Chi : total:m2484_2, partial:m2484_3 +# 2484| r2484_5(glval) = VariableAddress[b] : +# 2484| m2484_6(bool) = InitializeParameter[b] : &:r2484_5 +# 2486| r2486_1(glval) = VariableAddress[b] : +# 2486| r2486_2(bool) = Load[b] : &:r2486_1, m2484_6 +# 2486| v2486_3(void) = ConditionalBranch : r2486_2 +#-----| False -> Block 2 +#-----| True -> Block 1 + +# 2487| Block 1 +# 2487| r2487_1(glval) = VariableAddress[c] : +# 2487| m2487_2(ClassWithDestructor) = Uninitialized[c] : &:r2487_1 +# 2487| r2487_3(glval) = FunctionAddress[ClassWithDestructor] : +# 2487| v2487_4(void) = Call[ClassWithDestructor] : func:r2487_3, this:r2487_1 +# 2487| m2487_5(unknown) = ^CallSideEffect : ~m2484_4 +# 2487| m2487_6(unknown) = Chi : total:m2484_4, partial:m2487_5 +# 2487| m2487_7(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2487_1 +# 2487| m2487_8(ClassWithDestructor) = Chi : total:m2487_2, partial:m2487_7 +#-----| r0_1(glval) = VariableAddress[c] : +#-----| r0_2(glval) = FunctionAddress[~ClassWithDestructor] : +#-----| v0_3(void) = Call[~ClassWithDestructor] : func:r0_2, this:r0_1 +#-----| m0_4(unknown) = ^CallSideEffect : ~m2487_6 +#-----| m0_5(unknown) = Chi : total:m2487_6, partial:m0_4 +#-----| v0_6(void) = ^IndirectReadSideEffect[-1] : &:r0_1, m2487_8 +#-----| m0_7(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r0_1 +#-----| m0_8(ClassWithDestructor) = Chi : total:m2487_8, partial:m0_7 +#-----| Goto -> Block 2 + +# 2489| Block 2 +# 2489| m2489_1(unknown) = Phi : from 0:~m2484_4, from 1:~m0_5 +# 2489| r2489_2(glval) = VariableAddress[b] : +# 2489| r2489_3(bool) = Load[b] : &:r2489_2, m2484_6 +# 2489| v2489_4(void) = ConditionalBranch : r2489_3 +#-----| False -> Block 4 +#-----| True -> Block 3 + +# 2490| Block 3 +# 2490| r2490_1(glval) = VariableAddress[d] : +# 2490| m2490_2(ClassWithDestructor) = Uninitialized[d] : &:r2490_1 +# 2490| r2490_3(glval) = FunctionAddress[ClassWithDestructor] : +# 2490| v2490_4(void) = Call[ClassWithDestructor] : func:r2490_3, this:r2490_1 +# 2490| m2490_5(unknown) = ^CallSideEffect : ~m2489_1 +# 2490| m2490_6(unknown) = Chi : total:m2489_1, partial:m2490_5 +# 2490| m2490_7(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2490_1 +# 2490| m2490_8(ClassWithDestructor) = Chi : total:m2490_2, partial:m2490_7 +#-----| r0_9(glval) = VariableAddress[d] : +#-----| r0_10(glval) = FunctionAddress[~ClassWithDestructor] : +#-----| v0_11(void) = Call[~ClassWithDestructor] : func:r0_10, this:r0_9 +#-----| m0_12(unknown) = ^CallSideEffect : ~m2490_6 +#-----| m0_13(unknown) = Chi : total:m2490_6, partial:m0_12 +#-----| v0_14(void) = ^IndirectReadSideEffect[-1] : &:r0_9, m2490_8 +#-----| m0_15(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r0_9 +#-----| m0_16(ClassWithDestructor) = Chi : total:m2490_8, partial:m0_15 +#-----| Goto -> Block 5 + +# 2492| Block 4 +# 2492| r2492_1(glval) = VariableAddress[e] : +# 2492| m2492_2(ClassWithDestructor) = Uninitialized[e] : &:r2492_1 +# 2492| r2492_3(glval) = FunctionAddress[ClassWithDestructor] : +# 2492| v2492_4(void) = Call[ClassWithDestructor] : func:r2492_3, this:r2492_1 +# 2492| m2492_5(unknown) = ^CallSideEffect : ~m2489_1 +# 2492| m2492_6(unknown) = Chi : total:m2489_1, partial:m2492_5 +# 2492| m2492_7(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2492_1 +# 2492| m2492_8(ClassWithDestructor) = Chi : total:m2492_2, partial:m2492_7 +#-----| r0_17(glval) = VariableAddress[e] : +#-----| r0_18(glval) = FunctionAddress[~ClassWithDestructor] : +#-----| v0_19(void) = Call[~ClassWithDestructor] : func:r0_18, this:r0_17 +#-----| m0_20(unknown) = ^CallSideEffect : ~m2492_6 +#-----| m0_21(unknown) = Chi : total:m2492_6, partial:m0_20 +#-----| v0_22(void) = ^IndirectReadSideEffect[-1] : &:r0_17, m2492_8 +#-----| m0_23(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r0_17 +#-----| m0_24(ClassWithDestructor) = Chi : total:m2492_8, partial:m0_23 +#-----| Goto -> Block 5 + +# 2494| Block 5 +# 2494| m2494_1(unknown) = Phi : from 3:~m0_13, from 4:~m0_21, from 6:~m0_29 +# 2494| r2494_2(glval) = VariableAddress[b] : +# 2494| r2494_3(bool) = Load[b] : &:r2494_2, m2484_6 +# 2494| v2494_4(void) = ConditionalBranch : r2494_3 +#-----| False -> Block 7 +#-----| True -> Block 6 + +# 2495| Block 6 +# 2495| r2495_1(glval) = VariableAddress[f] : +# 2495| m2495_2(ClassWithDestructor) = Uninitialized[f] : &:r2495_1 +# 2495| r2495_3(glval) = FunctionAddress[ClassWithDestructor] : +# 2495| v2495_4(void) = Call[ClassWithDestructor] : func:r2495_3, this:r2495_1 +# 2495| m2495_5(unknown) = ^CallSideEffect : ~m2494_1 +# 2495| m2495_6(unknown) = Chi : total:m2494_1, partial:m2495_5 +# 2495| m2495_7(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2495_1 +# 2495| m2495_8(ClassWithDestructor) = Chi : total:m2495_2, partial:m2495_7 +#-----| r0_25(glval) = VariableAddress[f] : +#-----| r0_26(glval) = FunctionAddress[~ClassWithDestructor] : +#-----| v0_27(void) = Call[~ClassWithDestructor] : func:r0_26, this:r0_25 +#-----| m0_28(unknown) = ^CallSideEffect : ~m2495_6 +#-----| m0_29(unknown) = Chi : total:m2495_6, partial:m0_28 +#-----| v0_30(void) = ^IndirectReadSideEffect[-1] : &:r0_25, m2495_8 +#-----| m0_31(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r0_25 +#-----| m0_32(ClassWithDestructor) = Chi : total:m2495_8, partial:m0_31 +#-----| Goto (back edge) -> Block 5 + +# 2497| Block 7 +# 2497| r2497_1(glval) = VariableAddress[i] : +# 2497| r2497_2(int) = Constant[0] : +# 2497| m2497_3(int) = Store[i] : &:r2497_1, r2497_2 +#-----| Goto -> Block 8 + +# 2497| Block 8 +# 2497| m2497_4(unknown) = Phi : from 7:~m2494_1, from 9:~m0_37 +# 2497| m2497_5(int) = Phi : from 7:m2497_3, from 9:m2497_15 +# 2497| r2497_6(glval) = VariableAddress[i] : +# 2497| r2497_7(int) = Load[i] : &:r2497_6, m2497_5 +# 2497| r2497_8(int) = Constant[42] : +# 2497| r2497_9(bool) = CompareLT : r2497_7, r2497_8 +# 2497| v2497_10(void) = ConditionalBranch : r2497_9 +#-----| False -> Block 10 +#-----| True -> Block 9 + +# 2498| Block 9 +# 2498| r2498_1(glval) = VariableAddress[g] : +# 2498| m2498_2(ClassWithDestructor) = Uninitialized[g] : &:r2498_1 +# 2498| r2498_3(glval) = FunctionAddress[ClassWithDestructor] : +# 2498| v2498_4(void) = Call[ClassWithDestructor] : func:r2498_3, this:r2498_1 +# 2498| m2498_5(unknown) = ^CallSideEffect : ~m2497_4 +# 2498| m2498_6(unknown) = Chi : total:m2497_4, partial:m2498_5 +# 2498| m2498_7(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2498_1 +# 2498| m2498_8(ClassWithDestructor) = Chi : total:m2498_2, partial:m2498_7 +#-----| r0_33(glval) = VariableAddress[g] : +#-----| r0_34(glval) = FunctionAddress[~ClassWithDestructor] : +#-----| v0_35(void) = Call[~ClassWithDestructor] : func:r0_34, this:r0_33 +#-----| m0_36(unknown) = ^CallSideEffect : ~m2498_6 +#-----| m0_37(unknown) = Chi : total:m2498_6, partial:m0_36 +#-----| v0_38(void) = ^IndirectReadSideEffect[-1] : &:r0_33, m2498_8 +#-----| m0_39(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r0_33 +#-----| m0_40(ClassWithDestructor) = Chi : total:m2498_8, partial:m0_39 +# 2497| r2497_11(glval) = VariableAddress[i] : +# 2497| r2497_12(int) = Load[i] : &:r2497_11, m2497_5 +# 2497| r2497_13(int) = Constant[1] : +# 2497| r2497_14(int) = Add : r2497_12, r2497_13 +# 2497| m2497_15(int) = Store[i] : &:r2497_11, r2497_14 +#-----| Goto (back edge) -> Block 8 + +# 2499| Block 10 +# 2499| v2499_1(void) = NoOp : +# 2484| v2484_7(void) = ReturnVoid : +# 2484| v2484_8(void) = AliasedUse : ~m2497_4 +# 2484| v2484_9(void) = ExitFunction : + perf-regression.cpp: # 6| void Big::Big() # 6| Block 0 diff --git a/cpp/ql/test/library-tests/ir/ir/ir.cpp b/cpp/ql/test/library-tests/ir/ir/ir.cpp index 95b639aac6bf..c8840fd0b56e 100644 --- a/cpp/ql/test/library-tests/ir/ir/ir.cpp +++ b/cpp/ql/test/library-tests/ir/ir/ir.cpp @@ -2481,4 +2481,21 @@ namespace rvalue_conversion_with_destructor { } } +void destructor_without_block(bool b) +{ + if (b) + ClassWithDestructor c; + + if (b) + ClassWithDestructor d; + else + ClassWithDestructor e; + + while (b) + ClassWithDestructor f; + + for(int i = 0; i < 42; ++i) + ClassWithDestructor g; +} + // semmle-extractor-options: -std=c++20 --clang diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 7c0a525d0ca0..6ff42a28cb35 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -16244,6 +16244,134 @@ ir.cpp: # 2478| v2478_5(void) = AliasedUse : ~m? # 2478| v2478_6(void) = ExitFunction : +# 2484| void destructor_without_block(bool) +# 2484| Block 0 +# 2484| v2484_1(void) = EnterFunction : +# 2484| mu2484_2(unknown) = AliasedDefinition : +# 2484| mu2484_3(unknown) = InitializeNonLocal : +# 2484| r2484_4(glval) = VariableAddress[b] : +# 2484| mu2484_5(bool) = InitializeParameter[b] : &:r2484_4 +# 2486| r2486_1(glval) = VariableAddress[b] : +# 2486| r2486_2(bool) = Load[b] : &:r2486_1, ~m? +# 2486| v2486_3(void) = ConditionalBranch : r2486_2 +#-----| False -> Block 2 +#-----| True -> Block 1 + +# 2487| Block 1 +# 2487| r2487_1(glval) = VariableAddress[c] : +# 2487| mu2487_2(ClassWithDestructor) = Uninitialized[c] : &:r2487_1 +# 2487| r2487_3(glval) = FunctionAddress[ClassWithDestructor] : +# 2487| v2487_4(void) = Call[ClassWithDestructor] : func:r2487_3, this:r2487_1 +# 2487| mu2487_5(unknown) = ^CallSideEffect : ~m? +# 2487| mu2487_6(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2487_1 +#-----| r0_1(glval) = VariableAddress[c] : +#-----| r0_2(glval) = FunctionAddress[~ClassWithDestructor] : +#-----| v0_3(void) = Call[~ClassWithDestructor] : func:r0_2, this:r0_1 +#-----| mu0_4(unknown) = ^CallSideEffect : ~m? +#-----| v0_5(void) = ^IndirectReadSideEffect[-1] : &:r0_1, ~m? +#-----| mu0_6(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r0_1 +#-----| Goto -> Block 2 + +# 2489| Block 2 +# 2489| r2489_1(glval) = VariableAddress[b] : +# 2489| r2489_2(bool) = Load[b] : &:r2489_1, ~m? +# 2489| v2489_3(void) = ConditionalBranch : r2489_2 +#-----| False -> Block 4 +#-----| True -> Block 3 + +# 2490| Block 3 +# 2490| r2490_1(glval) = VariableAddress[d] : +# 2490| mu2490_2(ClassWithDestructor) = Uninitialized[d] : &:r2490_1 +# 2490| r2490_3(glval) = FunctionAddress[ClassWithDestructor] : +# 2490| v2490_4(void) = Call[ClassWithDestructor] : func:r2490_3, this:r2490_1 +# 2490| mu2490_5(unknown) = ^CallSideEffect : ~m? +# 2490| mu2490_6(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2490_1 +#-----| r0_7(glval) = VariableAddress[d] : +#-----| r0_8(glval) = FunctionAddress[~ClassWithDestructor] : +#-----| v0_9(void) = Call[~ClassWithDestructor] : func:r0_8, this:r0_7 +#-----| mu0_10(unknown) = ^CallSideEffect : ~m? +#-----| v0_11(void) = ^IndirectReadSideEffect[-1] : &:r0_7, ~m? +#-----| mu0_12(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r0_7 +#-----| Goto -> Block 5 + +# 2492| Block 4 +# 2492| r2492_1(glval) = VariableAddress[e] : +# 2492| mu2492_2(ClassWithDestructor) = Uninitialized[e] : &:r2492_1 +# 2492| r2492_3(glval) = FunctionAddress[ClassWithDestructor] : +# 2492| v2492_4(void) = Call[ClassWithDestructor] : func:r2492_3, this:r2492_1 +# 2492| mu2492_5(unknown) = ^CallSideEffect : ~m? +# 2492| mu2492_6(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2492_1 +#-----| r0_13(glval) = VariableAddress[e] : +#-----| r0_14(glval) = FunctionAddress[~ClassWithDestructor] : +#-----| v0_15(void) = Call[~ClassWithDestructor] : func:r0_14, this:r0_13 +#-----| mu0_16(unknown) = ^CallSideEffect : ~m? +#-----| v0_17(void) = ^IndirectReadSideEffect[-1] : &:r0_13, ~m? +#-----| mu0_18(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r0_13 +#-----| Goto -> Block 5 + +# 2494| Block 5 +# 2494| r2494_1(glval) = VariableAddress[b] : +# 2494| r2494_2(bool) = Load[b] : &:r2494_1, ~m? +# 2494| v2494_3(void) = ConditionalBranch : r2494_2 +#-----| False -> Block 7 +#-----| True -> Block 6 + +# 2495| Block 6 +# 2495| r2495_1(glval) = VariableAddress[f] : +# 2495| mu2495_2(ClassWithDestructor) = Uninitialized[f] : &:r2495_1 +# 2495| r2495_3(glval) = FunctionAddress[ClassWithDestructor] : +# 2495| v2495_4(void) = Call[ClassWithDestructor] : func:r2495_3, this:r2495_1 +# 2495| mu2495_5(unknown) = ^CallSideEffect : ~m? +# 2495| mu2495_6(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2495_1 +#-----| r0_19(glval) = VariableAddress[f] : +#-----| r0_20(glval) = FunctionAddress[~ClassWithDestructor] : +#-----| v0_21(void) = Call[~ClassWithDestructor] : func:r0_20, this:r0_19 +#-----| mu0_22(unknown) = ^CallSideEffect : ~m? +#-----| v0_23(void) = ^IndirectReadSideEffect[-1] : &:r0_19, ~m? +#-----| mu0_24(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r0_19 +#-----| Goto (back edge) -> Block 5 + +# 2497| Block 7 +# 2497| r2497_1(glval) = VariableAddress[i] : +# 2497| r2497_2(int) = Constant[0] : +# 2497| mu2497_3(int) = Store[i] : &:r2497_1, r2497_2 +#-----| Goto -> Block 8 + +# 2497| Block 8 +# 2497| r2497_4(glval) = VariableAddress[i] : +# 2497| r2497_5(int) = Load[i] : &:r2497_4, ~m? +# 2497| r2497_6(int) = Constant[42] : +# 2497| r2497_7(bool) = CompareLT : r2497_5, r2497_6 +# 2497| v2497_8(void) = ConditionalBranch : r2497_7 +#-----| False -> Block 10 +#-----| True -> Block 9 + +# 2498| Block 9 +# 2498| r2498_1(glval) = VariableAddress[g] : +# 2498| mu2498_2(ClassWithDestructor) = Uninitialized[g] : &:r2498_1 +# 2498| r2498_3(glval) = FunctionAddress[ClassWithDestructor] : +# 2498| v2498_4(void) = Call[ClassWithDestructor] : func:r2498_3, this:r2498_1 +# 2498| mu2498_5(unknown) = ^CallSideEffect : ~m? +# 2498| mu2498_6(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2498_1 +#-----| r0_25(glval) = VariableAddress[g] : +#-----| r0_26(glval) = FunctionAddress[~ClassWithDestructor] : +#-----| v0_27(void) = Call[~ClassWithDestructor] : func:r0_26, this:r0_25 +#-----| mu0_28(unknown) = ^CallSideEffect : ~m? +#-----| v0_29(void) = ^IndirectReadSideEffect[-1] : &:r0_25, ~m? +#-----| mu0_30(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r0_25 +# 2497| r2497_9(glval) = VariableAddress[i] : +# 2497| r2497_10(int) = Load[i] : &:r2497_9, ~m? +# 2497| r2497_11(int) = Constant[1] : +# 2497| r2497_12(int) = Add : r2497_10, r2497_11 +# 2497| mu2497_13(int) = Store[i] : &:r2497_9, r2497_12 +#-----| Goto (back edge) -> Block 8 + +# 2499| Block 10 +# 2499| v2499_1(void) = NoOp : +# 2484| v2484_6(void) = ReturnVoid : +# 2484| v2484_7(void) = AliasedUse : ~m? +# 2484| v2484_8(void) = ExitFunction : + perf-regression.cpp: # 6| void Big::Big() # 6| Block 0