From 279fc16b60c6d5e5578ab2485a70dd644397100f Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Sun, 10 Nov 2019 10:35:53 +0100 Subject: [PATCH 1/4] C++: ConvertToBase -> ConvertToNonVirtualBase This rename was done with perl -p -i -e's/ConvertToBase/ConvertToNonVirtualBase/g' **/*.ql* **/*.expected followed by re-running the affected tests. --- .../ir/dataflow/internal/DataFlowDispatch.qll | 4 +- .../code/cpp/ir/implementation/Opcode.qll | 6 +- .../aliased_ssa/Instruction.qll | 4 +- .../aliased_ssa/internal/AliasAnalysis.qll | 2 +- .../cpp/ir/implementation/raw/Instruction.qll | 4 +- .../raw/internal/TranslatedExpr.qll | 2 +- .../raw/internal/TranslatedInitialization.qll | 2 +- .../unaliased_ssa/Instruction.qll | 4 +- .../unaliased_ssa/internal/AliasAnalysis.qll | 2 +- .../ir/escape/points_to.expected | 12 +- .../test/library-tests/ir/ir/raw_ir.expected | 1204 ++++++++--------- .../GlobalValueNumbering/ir_gvn.expected | 64 +- .../code/csharp/ir/implementation/Opcode.qll | 6 +- .../ir/implementation/raw/Instruction.qll | 4 +- .../unaliased_ssa/Instruction.qll | 4 +- .../unaliased_ssa/internal/AliasAnalysis.qll | 2 +- 16 files changed, 651 insertions(+), 675 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll index 9572639de59..d149f33e55e 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll @@ -57,13 +57,13 @@ private predicate overrideMayAffectCall( * should usually be fewer classes than calls. * * If a value is cast several classes up in the hierarchy, that will be modeled - * as a chain of `ConvertToBaseInstruction`s and will cause the search to start + * as a chain of `ConvertToNonVirtualBaseInstruction`s and will cause the search to start * from each of them and pass through subsequent ones. There might be * performance to gain by stopping before a second upcast and reconstructing * the full chain in a "big-step" recursion after this one. */ private predicate nodeMayHaveClass(Class derived, DataFlow::Node node) { - exists(ConvertToBaseInstruction toBase | + exists(ConvertToNonVirtualBaseInstruction toBase | derived = toBase.getDerivedClass() and overrideMayAffectCall(derived, _, toBase.getEnclosingFunction(), _, _) and node.asInstruction() = toBase diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll index eb07be7f30c..4e3039b933e 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll @@ -34,7 +34,7 @@ private newtype TOpcode = TPointerSub() or TPointerDiff() or TConvert() or - TConvertToBase() or + TConvertToNonVirtualBase() or TConvertToVirtualBase() or TConvertToDerived() or TCheckedConvertOrNull() or @@ -302,8 +302,8 @@ module Opcode { final override string toString() { result = "Convert" } } - class ConvertToBase extends UnaryOpcode, TConvertToBase { - final override string toString() { result = "ConvertToBase" } + class ConvertToNonVirtualBase extends UnaryOpcode, TConvertToNonVirtualBase { + final override string toString() { result = "ConvertToNonVirtualBase" } } class ConvertToVirtualBase extends UnaryOpcode, TConvertToVirtualBase { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index 9f7cf68b065..4bdeedf2334 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -980,8 +980,8 @@ class InheritanceConversionInstruction extends UnaryInstruction { * Represents an instruction that converts from the address of a derived class * to the address of a direct non-virtual base class. */ -class ConvertToBaseInstruction extends InheritanceConversionInstruction { - ConvertToBaseInstruction() { getOpcode() instanceof Opcode::ConvertToBase } +class ConvertToNonVirtualBaseInstruction extends InheritanceConversionInstruction { + ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } } /** diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index 0923ec8f994..6ecfd1470bb 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -109,7 +109,7 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) { instr = operand.getUse() and ( // Converting to a non-virtual base class adds the offset of the base class. - exists(ConvertToBaseInstruction convert | + exists(ConvertToNonVirtualBaseInstruction convert | convert = instr and bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8) ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll index 9f7cf68b065..4bdeedf2334 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -980,8 +980,8 @@ class InheritanceConversionInstruction extends UnaryInstruction { * Represents an instruction that converts from the address of a derived class * to the address of a direct non-virtual base class. */ -class ConvertToBaseInstruction extends InheritanceConversionInstruction { - ConvertToBaseInstruction() { getOpcode() instanceof Opcode::ConvertToBase } +class ConvertToNonVirtualBaseInstruction extends InheritanceConversionInstruction { + ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } } /** diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index c9806cd03c8..9db42c742ac 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -1038,7 +1038,7 @@ class TranslatedInheritanceConversion extends TranslatedSingleInstructionConvers then if expr.(BaseClassConversion).isVirtual() then result instanceof Opcode::ConvertToVirtualBase - else result instanceof Opcode::ConvertToBase + else result instanceof Opcode::ConvertToNonVirtualBase else result instanceof Opcode::ConvertToDerived } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll index c6911a048c7..609f8276640 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll @@ -752,7 +752,7 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = OnlyInstructionTag() and - opcode instanceof Opcode::ConvertToBase and + opcode instanceof Opcode::ConvertToNonVirtualBase and resultType = getTypeForGLValue(call.getTarget().getDeclaringType()) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index 9f7cf68b065..4bdeedf2334 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -980,8 +980,8 @@ class InheritanceConversionInstruction extends UnaryInstruction { * Represents an instruction that converts from the address of a derived class * to the address of a direct non-virtual base class. */ -class ConvertToBaseInstruction extends InheritanceConversionInstruction { - ConvertToBaseInstruction() { getOpcode() instanceof Opcode::ConvertToBase } +class ConvertToNonVirtualBaseInstruction extends InheritanceConversionInstruction { + ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } } /** diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index 0923ec8f994..6ecfd1470bb 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -109,7 +109,7 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) { instr = operand.getUse() and ( // Converting to a non-virtual base class adds the offset of the base class. - exists(ConvertToBaseInstruction convert | + exists(ConvertToNonVirtualBaseInstruction convert | convert = instr and bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8) ) diff --git a/cpp/ql/test/library-tests/ir/escape/points_to.expected b/cpp/ql/test/library-tests/ir/escape/points_to.expected index c58d97f7988..ac518b5dd79 100644 --- a/cpp/ql/test/library-tests/ir/escape/points_to.expected +++ b/cpp/ql/test/library-tests/ir/escape/points_to.expected @@ -35,15 +35,15 @@ | escape.cpp:146:5:146:18 | CopyValue | no_Point+8:0 | no_Point+8:0 | | escape.cpp:146:7:146:17 | CopyValue | no_Point+8:0 | no_Point+8:0 | | escape.cpp:146:17:146:17 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | -| escape.cpp:149:5:149:14 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:149:5:149:14 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:149:5:149:14 | ConvertToNonVirtualBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:149:5:149:14 | ConvertToNonVirtualBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:149:16:149:16 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:150:18:150:27 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:150:18:150:27 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:150:18:150:27 | ConvertToNonVirtualBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:150:18:150:27 | ConvertToNonVirtualBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:150:29:150:29 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:151:5:151:14 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | +| escape.cpp:151:5:151:14 | ConvertToNonVirtualBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | | escape.cpp:151:16:151:17 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | -| escape.cpp:152:19:152:28 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | +| escape.cpp:152:19:152:28 | ConvertToNonVirtualBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | | escape.cpp:152:30:152:31 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | | escape.cpp:155:17:155:30 | CopyValue | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | | escape.cpp:155:17:155:30 | Store | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | 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 ee8bae8f6c1..5078a471b2b 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -1,28 +1,4 @@ bad_asts.cpp: -# 9| int Bad::S::MemberFunction(int) -# 9| Block 0 -# 9| v0_0(void) = EnterFunction : -# 9| mu0_1(unknown) = AliasedDefinition : -# 9| mu0_2(unknown) = UnmodeledDefinition : -# 9| r0_3(glval) = InitializeThis : -# 9| r0_4(glval) = VariableAddress[y] : -# 9| mu0_5(int) = InitializeParameter[y] : &:r0_4 -# 10| r0_6(glval) = VariableAddress[#return] : -# 10| r0_7(int) = Constant[6] : -#-----| r0_8(S *) = CopyValue : r0_3 -# 10| r0_9(glval) = FieldAddress[x] : r0_8 -# 10| r0_10(int) = Load : &:r0_9, ~mu0_2 -# 10| r0_11(int) = Add : r0_7, r0_10 -# 10| r0_12(glval) = VariableAddress[y] : -# 10| r0_13(int) = Load : &:r0_12, ~mu0_2 -# 10| r0_14(int) = Add : r0_11, r0_13 -# 10| mu0_15(int) = Store : &:r0_6, r0_14 -# 9| r0_16(glval) = VariableAddress[#return] : -# 9| v0_17(void) = ReturnValue : &:r0_16, ~mu0_2 -# 9| v0_18(void) = UnmodeledUse : mu* -# 9| v0_19(void) = AliasedUse : ~mu0_2 -# 9| v0_20(void) = ExitFunction : - # 14| void Bad::CallBadMemberFunction() # 14| Block 0 # 14| v0_0(void) = EnterFunction : @@ -3478,606 +3454,606 @@ ir.cpp: # 754| Middle& Middle::operator=(Middle const&) # 754| Block 0 -# 754| v0_0(void) = EnterFunction : -# 754| mu0_1(unknown) = AliasedDefinition : -# 754| mu0_2(unknown) = UnmodeledDefinition : -# 754| r0_3(glval) = InitializeThis : -#-----| r0_4(glval) = VariableAddress[p#0] : -#-----| mu0_5(Middle &) = InitializeParameter[p#0] : &:r0_4 -#-----| r0_6(Middle *) = CopyValue : r0_3 -#-----| r0_7(Base *) = ConvertToBase[Middle : Base] : r0_6 -# 754| r0_8(glval) = FunctionAddress[operator=] : -#-----| r0_9(glval) = VariableAddress[p#0] : -#-----| r0_10(Middle &) = Load : &:r0_9, ~mu0_2 -#-----| r0_11(glval) = CopyValue : r0_10 -#-----| r0_12(Middle *) = CopyValue : r0_11 -#-----| r0_13(Base *) = ConvertToBase[Middle : Base] : r0_12 -#-----| r0_14(glval) = CopyValue : r0_13 -#-----| r0_15(Base &) = CopyValue : r0_14 -# 754| r0_16(Base &) = Call : func:r0_8, this:r0_7, 0:r0_15 -# 754| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v0_18(void) = ^BufferReadSideEffect[-1] : &:r0_7, ~mu0_2 -#-----| v0_19(void) = ^BufferReadSideEffect[0] : &:r0_15, ~mu0_2 -#-----| mu0_20(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_7 -#-----| mu0_21(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_15 -#-----| r0_22(glval) = CopyValue : r0_16 -#-----| r0_23(Middle *) = CopyValue : r0_3 -#-----| r0_24(glval) = FieldAddress[middle_s] : r0_23 -#-----| r0_25(String *) = CopyValue : r0_24 -# 754| r0_26(glval) = FunctionAddress[operator=] : -#-----| r0_27(glval) = VariableAddress[p#0] : -#-----| r0_28(Middle &) = Load : &:r0_27, ~mu0_2 -#-----| r0_29(glval) = CopyValue : r0_28 -#-----| r0_30(glval) = FieldAddress[middle_s] : r0_29 -#-----| r0_31(String &) = CopyValue : r0_30 -# 754| r0_32(String &) = Call : func:r0_26, this:r0_25, 0:r0_31 -# 754| mu0_33(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v0_34(void) = ^BufferReadSideEffect[-1] : &:r0_25, ~mu0_2 -#-----| v0_35(void) = ^BufferReadSideEffect[0] : &:r0_31, ~mu0_2 -#-----| mu0_36(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_25 -#-----| mu0_37(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_31 -#-----| r0_38(glval) = CopyValue : r0_32 -#-----| r0_39(glval) = VariableAddress[#return] : -#-----| r0_40(Middle *) = CopyValue : r0_3 -#-----| r0_41(glval) = CopyValue : r0_40 -#-----| r0_42(Middle &) = CopyValue : r0_41 -#-----| mu0_43(Middle &) = Store : &:r0_39, r0_42 -# 754| r0_44(glval) = VariableAddress[#return] : -# 754| v0_45(void) = ReturnValue : &:r0_44, ~mu0_2 -# 754| v0_46(void) = UnmodeledUse : mu* -# 754| v0_47(void) = AliasedUse : ~mu0_2 -# 754| v0_48(void) = ExitFunction : +# 754| v0_0(void) = EnterFunction : +# 754| mu0_1(unknown) = AliasedDefinition : +# 754| mu0_2(unknown) = UnmodeledDefinition : +# 754| r0_3(glval) = InitializeThis : +#-----| r0_4(glval) = VariableAddress[p#0] : +#-----| mu0_5(Middle &) = InitializeParameter[p#0] : &:r0_4 +#-----| r0_6(Middle *) = CopyValue : r0_3 +#-----| r0_7(Base *) = ConvertToNonVirtualBase[Middle : Base] : r0_6 +# 754| r0_8(glval) = FunctionAddress[operator=] : +#-----| r0_9(glval) = VariableAddress[p#0] : +#-----| r0_10(Middle &) = Load : &:r0_9, ~mu0_2 +#-----| r0_11(glval) = CopyValue : r0_10 +#-----| r0_12(Middle *) = CopyValue : r0_11 +#-----| r0_13(Base *) = ConvertToNonVirtualBase[Middle : Base] : r0_12 +#-----| r0_14(glval) = CopyValue : r0_13 +#-----| r0_15(Base &) = CopyValue : r0_14 +# 754| r0_16(Base &) = Call : func:r0_8, this:r0_7, 0:r0_15 +# 754| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v0_18(void) = ^BufferReadSideEffect[-1] : &:r0_7, ~mu0_2 +#-----| v0_19(void) = ^BufferReadSideEffect[0] : &:r0_15, ~mu0_2 +#-----| mu0_20(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_7 +#-----| mu0_21(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_15 +#-----| r0_22(glval) = CopyValue : r0_16 +#-----| r0_23(Middle *) = CopyValue : r0_3 +#-----| r0_24(glval) = FieldAddress[middle_s] : r0_23 +#-----| r0_25(String *) = CopyValue : r0_24 +# 754| r0_26(glval) = FunctionAddress[operator=] : +#-----| r0_27(glval) = VariableAddress[p#0] : +#-----| r0_28(Middle &) = Load : &:r0_27, ~mu0_2 +#-----| r0_29(glval) = CopyValue : r0_28 +#-----| r0_30(glval) = FieldAddress[middle_s] : r0_29 +#-----| r0_31(String &) = CopyValue : r0_30 +# 754| r0_32(String &) = Call : func:r0_26, this:r0_25, 0:r0_31 +# 754| mu0_33(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v0_34(void) = ^BufferReadSideEffect[-1] : &:r0_25, ~mu0_2 +#-----| v0_35(void) = ^BufferReadSideEffect[0] : &:r0_31, ~mu0_2 +#-----| mu0_36(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_25 +#-----| mu0_37(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_31 +#-----| r0_38(glval) = CopyValue : r0_32 +#-----| r0_39(glval) = VariableAddress[#return] : +#-----| r0_40(Middle *) = CopyValue : r0_3 +#-----| r0_41(glval) = CopyValue : r0_40 +#-----| r0_42(Middle &) = CopyValue : r0_41 +#-----| mu0_43(Middle &) = Store : &:r0_39, r0_42 +# 754| r0_44(glval) = VariableAddress[#return] : +# 754| v0_45(void) = ReturnValue : &:r0_44, ~mu0_2 +# 754| v0_46(void) = UnmodeledUse : mu* +# 754| v0_47(void) = AliasedUse : ~mu0_2 +# 754| v0_48(void) = ExitFunction : # 757| void Middle::Middle() # 757| Block 0 -# 757| v0_0(void) = EnterFunction : -# 757| mu0_1(unknown) = AliasedDefinition : -# 757| mu0_2(unknown) = UnmodeledDefinition : -# 757| r0_3(glval) = InitializeThis : -# 757| r0_4(glval) = ConvertToBase[Middle : Base] : r0_3 -# 757| r0_5(glval) = FunctionAddress[Base] : -# 757| v0_6(void) = Call : func:r0_5, this:r0_4 -# 757| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 757| r0_8(glval) = FieldAddress[middle_s] : r0_3 -# 757| r0_9(glval) = FunctionAddress[String] : -# 757| v0_10(void) = Call : func:r0_9, this:r0_8 -# 757| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 758| v0_12(void) = NoOp : -# 757| v0_13(void) = ReturnVoid : -# 757| v0_14(void) = UnmodeledUse : mu* -# 757| v0_15(void) = AliasedUse : ~mu0_2 -# 757| v0_16(void) = ExitFunction : +# 757| v0_0(void) = EnterFunction : +# 757| mu0_1(unknown) = AliasedDefinition : +# 757| mu0_2(unknown) = UnmodeledDefinition : +# 757| r0_3(glval) = InitializeThis : +# 757| r0_4(glval) = ConvertToNonVirtualBase[Middle : Base] : r0_3 +# 757| r0_5(glval) = FunctionAddress[Base] : +# 757| v0_6(void) = Call : func:r0_5, this:r0_4 +# 757| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 757| r0_8(glval) = FieldAddress[middle_s] : r0_3 +# 757| r0_9(glval) = FunctionAddress[String] : +# 757| v0_10(void) = Call : func:r0_9, this:r0_8 +# 757| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 +# 758| v0_12(void) = NoOp : +# 757| v0_13(void) = ReturnVoid : +# 757| v0_14(void) = UnmodeledUse : mu* +# 757| v0_15(void) = AliasedUse : ~mu0_2 +# 757| v0_16(void) = ExitFunction : # 759| void Middle::~Middle() # 759| Block 0 -# 759| v0_0(void) = EnterFunction : -# 759| mu0_1(unknown) = AliasedDefinition : -# 759| mu0_2(unknown) = UnmodeledDefinition : -# 759| r0_3(glval) = InitializeThis : -# 760| v0_4(void) = NoOp : -# 760| r0_5(glval) = FieldAddress[middle_s] : r0_3 -# 760| r0_6(glval) = FunctionAddress[~String] : -# 760| v0_7(void) = Call : func:r0_6, this:r0_5 -# 760| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 -# 760| r0_9(glval) = ConvertToBase[Middle : Base] : r0_3 -# 760| r0_10(glval) = FunctionAddress[~Base] : -# 760| v0_11(void) = Call : func:r0_10, this:r0_9 -# 760| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 759| v0_13(void) = ReturnVoid : -# 759| v0_14(void) = UnmodeledUse : mu* -# 759| v0_15(void) = AliasedUse : ~mu0_2 -# 759| v0_16(void) = ExitFunction : +# 759| v0_0(void) = EnterFunction : +# 759| mu0_1(unknown) = AliasedDefinition : +# 759| mu0_2(unknown) = UnmodeledDefinition : +# 759| r0_3(glval) = InitializeThis : +# 760| v0_4(void) = NoOp : +# 760| r0_5(glval) = FieldAddress[middle_s] : r0_3 +# 760| r0_6(glval) = FunctionAddress[~String] : +# 760| v0_7(void) = Call : func:r0_6, this:r0_5 +# 760| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 +# 760| r0_9(glval) = ConvertToNonVirtualBase[Middle : Base] : r0_3 +# 760| r0_10(glval) = FunctionAddress[~Base] : +# 760| v0_11(void) = Call : func:r0_10, this:r0_9 +# 760| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 +# 759| v0_13(void) = ReturnVoid : +# 759| v0_14(void) = UnmodeledUse : mu* +# 759| v0_15(void) = AliasedUse : ~mu0_2 +# 759| v0_16(void) = ExitFunction : # 763| Derived& Derived::operator=(Derived const&) # 763| Block 0 -# 763| v0_0(void) = EnterFunction : -# 763| mu0_1(unknown) = AliasedDefinition : -# 763| mu0_2(unknown) = UnmodeledDefinition : -# 763| r0_3(glval) = InitializeThis : -#-----| r0_4(glval) = VariableAddress[p#0] : -#-----| mu0_5(Derived &) = InitializeParameter[p#0] : &:r0_4 -#-----| r0_6(Derived *) = CopyValue : r0_3 -#-----| r0_7(Middle *) = ConvertToBase[Derived : Middle] : r0_6 -# 763| r0_8(glval) = FunctionAddress[operator=] : -#-----| r0_9(glval) = VariableAddress[p#0] : -#-----| r0_10(Derived &) = Load : &:r0_9, ~mu0_2 -#-----| r0_11(glval) = CopyValue : r0_10 -#-----| r0_12(Derived *) = CopyValue : r0_11 -#-----| r0_13(Middle *) = ConvertToBase[Derived : Middle] : r0_12 -#-----| r0_14(glval) = CopyValue : r0_13 -#-----| r0_15(Middle &) = CopyValue : r0_14 -# 763| r0_16(Middle &) = Call : func:r0_8, this:r0_7, 0:r0_15 -# 763| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v0_18(void) = ^BufferReadSideEffect[-1] : &:r0_7, ~mu0_2 -#-----| v0_19(void) = ^BufferReadSideEffect[0] : &:r0_15, ~mu0_2 -#-----| mu0_20(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_7 -#-----| mu0_21(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_15 -#-----| r0_22(glval) = CopyValue : r0_16 -#-----| r0_23(Derived *) = CopyValue : r0_3 -#-----| r0_24(glval) = FieldAddress[derived_s] : r0_23 -#-----| r0_25(String *) = CopyValue : r0_24 -# 763| r0_26(glval) = FunctionAddress[operator=] : -#-----| r0_27(glval) = VariableAddress[p#0] : -#-----| r0_28(Derived &) = Load : &:r0_27, ~mu0_2 -#-----| r0_29(glval) = CopyValue : r0_28 -#-----| r0_30(glval) = FieldAddress[derived_s] : r0_29 -#-----| r0_31(String &) = CopyValue : r0_30 -# 763| r0_32(String &) = Call : func:r0_26, this:r0_25, 0:r0_31 -# 763| mu0_33(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v0_34(void) = ^BufferReadSideEffect[-1] : &:r0_25, ~mu0_2 -#-----| v0_35(void) = ^BufferReadSideEffect[0] : &:r0_31, ~mu0_2 -#-----| mu0_36(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_25 -#-----| mu0_37(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_31 -#-----| r0_38(glval) = CopyValue : r0_32 -#-----| r0_39(glval) = VariableAddress[#return] : -#-----| r0_40(Derived *) = CopyValue : r0_3 -#-----| r0_41(glval) = CopyValue : r0_40 -#-----| r0_42(Derived &) = CopyValue : r0_41 -#-----| mu0_43(Derived &) = Store : &:r0_39, r0_42 -# 763| r0_44(glval) = VariableAddress[#return] : -# 763| v0_45(void) = ReturnValue : &:r0_44, ~mu0_2 -# 763| v0_46(void) = UnmodeledUse : mu* -# 763| v0_47(void) = AliasedUse : ~mu0_2 -# 763| v0_48(void) = ExitFunction : +# 763| v0_0(void) = EnterFunction : +# 763| mu0_1(unknown) = AliasedDefinition : +# 763| mu0_2(unknown) = UnmodeledDefinition : +# 763| r0_3(glval) = InitializeThis : +#-----| r0_4(glval) = VariableAddress[p#0] : +#-----| mu0_5(Derived &) = InitializeParameter[p#0] : &:r0_4 +#-----| r0_6(Derived *) = CopyValue : r0_3 +#-----| r0_7(Middle *) = ConvertToNonVirtualBase[Derived : Middle] : r0_6 +# 763| r0_8(glval) = FunctionAddress[operator=] : +#-----| r0_9(glval) = VariableAddress[p#0] : +#-----| r0_10(Derived &) = Load : &:r0_9, ~mu0_2 +#-----| r0_11(glval) = CopyValue : r0_10 +#-----| r0_12(Derived *) = CopyValue : r0_11 +#-----| r0_13(Middle *) = ConvertToNonVirtualBase[Derived : Middle] : r0_12 +#-----| r0_14(glval) = CopyValue : r0_13 +#-----| r0_15(Middle &) = CopyValue : r0_14 +# 763| r0_16(Middle &) = Call : func:r0_8, this:r0_7, 0:r0_15 +# 763| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v0_18(void) = ^BufferReadSideEffect[-1] : &:r0_7, ~mu0_2 +#-----| v0_19(void) = ^BufferReadSideEffect[0] : &:r0_15, ~mu0_2 +#-----| mu0_20(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_7 +#-----| mu0_21(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_15 +#-----| r0_22(glval) = CopyValue : r0_16 +#-----| r0_23(Derived *) = CopyValue : r0_3 +#-----| r0_24(glval) = FieldAddress[derived_s] : r0_23 +#-----| r0_25(String *) = CopyValue : r0_24 +# 763| r0_26(glval) = FunctionAddress[operator=] : +#-----| r0_27(glval) = VariableAddress[p#0] : +#-----| r0_28(Derived &) = Load : &:r0_27, ~mu0_2 +#-----| r0_29(glval) = CopyValue : r0_28 +#-----| r0_30(glval) = FieldAddress[derived_s] : r0_29 +#-----| r0_31(String &) = CopyValue : r0_30 +# 763| r0_32(String &) = Call : func:r0_26, this:r0_25, 0:r0_31 +# 763| mu0_33(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v0_34(void) = ^BufferReadSideEffect[-1] : &:r0_25, ~mu0_2 +#-----| v0_35(void) = ^BufferReadSideEffect[0] : &:r0_31, ~mu0_2 +#-----| mu0_36(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_25 +#-----| mu0_37(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_31 +#-----| r0_38(glval) = CopyValue : r0_32 +#-----| r0_39(glval) = VariableAddress[#return] : +#-----| r0_40(Derived *) = CopyValue : r0_3 +#-----| r0_41(glval) = CopyValue : r0_40 +#-----| r0_42(Derived &) = CopyValue : r0_41 +#-----| mu0_43(Derived &) = Store : &:r0_39, r0_42 +# 763| r0_44(glval) = VariableAddress[#return] : +# 763| v0_45(void) = ReturnValue : &:r0_44, ~mu0_2 +# 763| v0_46(void) = UnmodeledUse : mu* +# 763| v0_47(void) = AliasedUse : ~mu0_2 +# 763| v0_48(void) = ExitFunction : # 766| void Derived::Derived() # 766| Block 0 -# 766| v0_0(void) = EnterFunction : -# 766| mu0_1(unknown) = AliasedDefinition : -# 766| mu0_2(unknown) = UnmodeledDefinition : -# 766| r0_3(glval) = InitializeThis : -# 766| r0_4(glval) = ConvertToBase[Derived : Middle] : r0_3 -# 766| r0_5(glval) = FunctionAddress[Middle] : -# 766| v0_6(void) = Call : func:r0_5, this:r0_4 -# 766| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 766| r0_8(glval) = FieldAddress[derived_s] : r0_3 -# 766| r0_9(glval) = FunctionAddress[String] : -# 766| v0_10(void) = Call : func:r0_9, this:r0_8 -# 766| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 767| v0_12(void) = NoOp : -# 766| v0_13(void) = ReturnVoid : -# 766| v0_14(void) = UnmodeledUse : mu* -# 766| v0_15(void) = AliasedUse : ~mu0_2 -# 766| v0_16(void) = ExitFunction : +# 766| v0_0(void) = EnterFunction : +# 766| mu0_1(unknown) = AliasedDefinition : +# 766| mu0_2(unknown) = UnmodeledDefinition : +# 766| r0_3(glval) = InitializeThis : +# 766| r0_4(glval) = ConvertToNonVirtualBase[Derived : Middle] : r0_3 +# 766| r0_5(glval) = FunctionAddress[Middle] : +# 766| v0_6(void) = Call : func:r0_5, this:r0_4 +# 766| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 766| r0_8(glval) = FieldAddress[derived_s] : r0_3 +# 766| r0_9(glval) = FunctionAddress[String] : +# 766| v0_10(void) = Call : func:r0_9, this:r0_8 +# 766| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 +# 767| v0_12(void) = NoOp : +# 766| v0_13(void) = ReturnVoid : +# 766| v0_14(void) = UnmodeledUse : mu* +# 766| v0_15(void) = AliasedUse : ~mu0_2 +# 766| v0_16(void) = ExitFunction : # 768| void Derived::~Derived() # 768| Block 0 -# 768| v0_0(void) = EnterFunction : -# 768| mu0_1(unknown) = AliasedDefinition : -# 768| mu0_2(unknown) = UnmodeledDefinition : -# 768| r0_3(glval) = InitializeThis : -# 769| v0_4(void) = NoOp : -# 769| r0_5(glval) = FieldAddress[derived_s] : r0_3 -# 769| r0_6(glval) = FunctionAddress[~String] : -# 769| v0_7(void) = Call : func:r0_6, this:r0_5 -# 769| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 -# 769| r0_9(glval) = ConvertToBase[Derived : Middle] : r0_3 -# 769| r0_10(glval) = FunctionAddress[~Middle] : -# 769| v0_11(void) = Call : func:r0_10, this:r0_9 -# 769| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 768| v0_13(void) = ReturnVoid : -# 768| v0_14(void) = UnmodeledUse : mu* -# 768| v0_15(void) = AliasedUse : ~mu0_2 -# 768| v0_16(void) = ExitFunction : +# 768| v0_0(void) = EnterFunction : +# 768| mu0_1(unknown) = AliasedDefinition : +# 768| mu0_2(unknown) = UnmodeledDefinition : +# 768| r0_3(glval) = InitializeThis : +# 769| v0_4(void) = NoOp : +# 769| r0_5(glval) = FieldAddress[derived_s] : r0_3 +# 769| r0_6(glval) = FunctionAddress[~String] : +# 769| v0_7(void) = Call : func:r0_6, this:r0_5 +# 769| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 +# 769| r0_9(glval) = ConvertToNonVirtualBase[Derived : Middle] : r0_3 +# 769| r0_10(glval) = FunctionAddress[~Middle] : +# 769| v0_11(void) = Call : func:r0_10, this:r0_9 +# 769| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 +# 768| v0_13(void) = ReturnVoid : +# 768| v0_14(void) = UnmodeledUse : mu* +# 768| v0_15(void) = AliasedUse : ~mu0_2 +# 768| v0_16(void) = ExitFunction : # 775| void MiddleVB1::MiddleVB1() # 775| Block 0 -# 775| v0_0(void) = EnterFunction : -# 775| mu0_1(unknown) = AliasedDefinition : -# 775| mu0_2(unknown) = UnmodeledDefinition : -# 775| r0_3(glval) = InitializeThis : -# 775| r0_4(glval) = ConvertToBase[MiddleVB1 : Base] : r0_3 -# 775| r0_5(glval) = FunctionAddress[Base] : -# 775| v0_6(void) = Call : func:r0_5, this:r0_4 -# 775| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 775| r0_8(glval) = FieldAddress[middlevb1_s] : r0_3 -# 775| r0_9(glval) = FunctionAddress[String] : -# 775| v0_10(void) = Call : func:r0_9, this:r0_8 -# 775| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 776| v0_12(void) = NoOp : -# 775| v0_13(void) = ReturnVoid : -# 775| v0_14(void) = UnmodeledUse : mu* -# 775| v0_15(void) = AliasedUse : ~mu0_2 -# 775| v0_16(void) = ExitFunction : +# 775| v0_0(void) = EnterFunction : +# 775| mu0_1(unknown) = AliasedDefinition : +# 775| mu0_2(unknown) = UnmodeledDefinition : +# 775| r0_3(glval) = InitializeThis : +# 775| r0_4(glval) = ConvertToNonVirtualBase[MiddleVB1 : Base] : r0_3 +# 775| r0_5(glval) = FunctionAddress[Base] : +# 775| v0_6(void) = Call : func:r0_5, this:r0_4 +# 775| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 775| r0_8(glval) = FieldAddress[middlevb1_s] : r0_3 +# 775| r0_9(glval) = FunctionAddress[String] : +# 775| v0_10(void) = Call : func:r0_9, this:r0_8 +# 775| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 +# 776| v0_12(void) = NoOp : +# 775| v0_13(void) = ReturnVoid : +# 775| v0_14(void) = UnmodeledUse : mu* +# 775| v0_15(void) = AliasedUse : ~mu0_2 +# 775| v0_16(void) = ExitFunction : # 777| void MiddleVB1::~MiddleVB1() # 777| Block 0 -# 777| v0_0(void) = EnterFunction : -# 777| mu0_1(unknown) = AliasedDefinition : -# 777| mu0_2(unknown) = UnmodeledDefinition : -# 777| r0_3(glval) = InitializeThis : -# 778| v0_4(void) = NoOp : -# 778| r0_5(glval) = FieldAddress[middlevb1_s] : r0_3 -# 778| r0_6(glval) = FunctionAddress[~String] : -# 778| v0_7(void) = Call : func:r0_6, this:r0_5 -# 778| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 -# 778| r0_9(glval) = ConvertToBase[MiddleVB1 : Base] : r0_3 -# 778| r0_10(glval) = FunctionAddress[~Base] : -# 778| v0_11(void) = Call : func:r0_10, this:r0_9 -# 778| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 777| v0_13(void) = ReturnVoid : -# 777| v0_14(void) = UnmodeledUse : mu* -# 777| v0_15(void) = AliasedUse : ~mu0_2 -# 777| v0_16(void) = ExitFunction : +# 777| v0_0(void) = EnterFunction : +# 777| mu0_1(unknown) = AliasedDefinition : +# 777| mu0_2(unknown) = UnmodeledDefinition : +# 777| r0_3(glval) = InitializeThis : +# 778| v0_4(void) = NoOp : +# 778| r0_5(glval) = FieldAddress[middlevb1_s] : r0_3 +# 778| r0_6(glval) = FunctionAddress[~String] : +# 778| v0_7(void) = Call : func:r0_6, this:r0_5 +# 778| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 +# 778| r0_9(glval) = ConvertToNonVirtualBase[MiddleVB1 : Base] : r0_3 +# 778| r0_10(glval) = FunctionAddress[~Base] : +# 778| v0_11(void) = Call : func:r0_10, this:r0_9 +# 778| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 +# 777| v0_13(void) = ReturnVoid : +# 777| v0_14(void) = UnmodeledUse : mu* +# 777| v0_15(void) = AliasedUse : ~mu0_2 +# 777| v0_16(void) = ExitFunction : # 784| void MiddleVB2::MiddleVB2() # 784| Block 0 -# 784| v0_0(void) = EnterFunction : -# 784| mu0_1(unknown) = AliasedDefinition : -# 784| mu0_2(unknown) = UnmodeledDefinition : -# 784| r0_3(glval) = InitializeThis : -# 784| r0_4(glval) = ConvertToBase[MiddleVB2 : Base] : r0_3 -# 784| r0_5(glval) = FunctionAddress[Base] : -# 784| v0_6(void) = Call : func:r0_5, this:r0_4 -# 784| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 784| r0_8(glval) = FieldAddress[middlevb2_s] : r0_3 -# 784| r0_9(glval) = FunctionAddress[String] : -# 784| v0_10(void) = Call : func:r0_9, this:r0_8 -# 784| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 785| v0_12(void) = NoOp : -# 784| v0_13(void) = ReturnVoid : -# 784| v0_14(void) = UnmodeledUse : mu* -# 784| v0_15(void) = AliasedUse : ~mu0_2 -# 784| v0_16(void) = ExitFunction : +# 784| v0_0(void) = EnterFunction : +# 784| mu0_1(unknown) = AliasedDefinition : +# 784| mu0_2(unknown) = UnmodeledDefinition : +# 784| r0_3(glval) = InitializeThis : +# 784| r0_4(glval) = ConvertToNonVirtualBase[MiddleVB2 : Base] : r0_3 +# 784| r0_5(glval) = FunctionAddress[Base] : +# 784| v0_6(void) = Call : func:r0_5, this:r0_4 +# 784| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 784| r0_8(glval) = FieldAddress[middlevb2_s] : r0_3 +# 784| r0_9(glval) = FunctionAddress[String] : +# 784| v0_10(void) = Call : func:r0_9, this:r0_8 +# 784| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 +# 785| v0_12(void) = NoOp : +# 784| v0_13(void) = ReturnVoid : +# 784| v0_14(void) = UnmodeledUse : mu* +# 784| v0_15(void) = AliasedUse : ~mu0_2 +# 784| v0_16(void) = ExitFunction : # 786| void MiddleVB2::~MiddleVB2() # 786| Block 0 -# 786| v0_0(void) = EnterFunction : -# 786| mu0_1(unknown) = AliasedDefinition : -# 786| mu0_2(unknown) = UnmodeledDefinition : -# 786| r0_3(glval) = InitializeThis : -# 787| v0_4(void) = NoOp : -# 787| r0_5(glval) = FieldAddress[middlevb2_s] : r0_3 -# 787| r0_6(glval) = FunctionAddress[~String] : -# 787| v0_7(void) = Call : func:r0_6, this:r0_5 -# 787| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 -# 787| r0_9(glval) = ConvertToBase[MiddleVB2 : Base] : r0_3 -# 787| r0_10(glval) = FunctionAddress[~Base] : -# 787| v0_11(void) = Call : func:r0_10, this:r0_9 -# 787| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 786| v0_13(void) = ReturnVoid : -# 786| v0_14(void) = UnmodeledUse : mu* -# 786| v0_15(void) = AliasedUse : ~mu0_2 -# 786| v0_16(void) = ExitFunction : +# 786| v0_0(void) = EnterFunction : +# 786| mu0_1(unknown) = AliasedDefinition : +# 786| mu0_2(unknown) = UnmodeledDefinition : +# 786| r0_3(glval) = InitializeThis : +# 787| v0_4(void) = NoOp : +# 787| r0_5(glval) = FieldAddress[middlevb2_s] : r0_3 +# 787| r0_6(glval) = FunctionAddress[~String] : +# 787| v0_7(void) = Call : func:r0_6, this:r0_5 +# 787| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 +# 787| r0_9(glval) = ConvertToNonVirtualBase[MiddleVB2 : Base] : r0_3 +# 787| r0_10(glval) = FunctionAddress[~Base] : +# 787| v0_11(void) = Call : func:r0_10, this:r0_9 +# 787| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 +# 786| v0_13(void) = ReturnVoid : +# 786| v0_14(void) = UnmodeledUse : mu* +# 786| v0_15(void) = AliasedUse : ~mu0_2 +# 786| v0_16(void) = ExitFunction : # 793| void DerivedVB::DerivedVB() # 793| Block 0 -# 793| v0_0(void) = EnterFunction : -# 793| mu0_1(unknown) = AliasedDefinition : -# 793| mu0_2(unknown) = UnmodeledDefinition : -# 793| r0_3(glval) = InitializeThis : -# 793| r0_4(glval) = ConvertToBase[DerivedVB : Base] : r0_3 -# 793| r0_5(glval) = FunctionAddress[Base] : -# 793| v0_6(void) = Call : func:r0_5, this:r0_4 -# 793| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 793| r0_8(glval) = ConvertToBase[DerivedVB : MiddleVB1] : r0_3 -# 793| r0_9(glval) = FunctionAddress[MiddleVB1] : -# 793| v0_10(void) = Call : func:r0_9, this:r0_8 -# 793| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 793| r0_12(glval) = ConvertToBase[DerivedVB : MiddleVB2] : r0_3 -# 793| r0_13(glval) = FunctionAddress[MiddleVB2] : -# 793| v0_14(void) = Call : func:r0_13, this:r0_12 -# 793| mu0_15(unknown) = ^CallSideEffect : ~mu0_2 -# 793| r0_16(glval) = FieldAddress[derivedvb_s] : r0_3 -# 793| r0_17(glval) = FunctionAddress[String] : -# 793| v0_18(void) = Call : func:r0_17, this:r0_16 -# 793| mu0_19(unknown) = ^CallSideEffect : ~mu0_2 -# 794| v0_20(void) = NoOp : -# 793| v0_21(void) = ReturnVoid : -# 793| v0_22(void) = UnmodeledUse : mu* -# 793| v0_23(void) = AliasedUse : ~mu0_2 -# 793| v0_24(void) = ExitFunction : +# 793| v0_0(void) = EnterFunction : +# 793| mu0_1(unknown) = AliasedDefinition : +# 793| mu0_2(unknown) = UnmodeledDefinition : +# 793| r0_3(glval) = InitializeThis : +# 793| r0_4(glval) = ConvertToNonVirtualBase[DerivedVB : Base] : r0_3 +# 793| r0_5(glval) = FunctionAddress[Base] : +# 793| v0_6(void) = Call : func:r0_5, this:r0_4 +# 793| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 793| r0_8(glval) = ConvertToNonVirtualBase[DerivedVB : MiddleVB1] : r0_3 +# 793| r0_9(glval) = FunctionAddress[MiddleVB1] : +# 793| v0_10(void) = Call : func:r0_9, this:r0_8 +# 793| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 +# 793| r0_12(glval) = ConvertToNonVirtualBase[DerivedVB : MiddleVB2] : r0_3 +# 793| r0_13(glval) = FunctionAddress[MiddleVB2] : +# 793| v0_14(void) = Call : func:r0_13, this:r0_12 +# 793| mu0_15(unknown) = ^CallSideEffect : ~mu0_2 +# 793| r0_16(glval) = FieldAddress[derivedvb_s] : r0_3 +# 793| r0_17(glval) = FunctionAddress[String] : +# 793| v0_18(void) = Call : func:r0_17, this:r0_16 +# 793| mu0_19(unknown) = ^CallSideEffect : ~mu0_2 +# 794| v0_20(void) = NoOp : +# 793| v0_21(void) = ReturnVoid : +# 793| v0_22(void) = UnmodeledUse : mu* +# 793| v0_23(void) = AliasedUse : ~mu0_2 +# 793| v0_24(void) = ExitFunction : # 795| void DerivedVB::~DerivedVB() # 795| Block 0 -# 795| v0_0(void) = EnterFunction : -# 795| mu0_1(unknown) = AliasedDefinition : -# 795| mu0_2(unknown) = UnmodeledDefinition : -# 795| r0_3(glval) = InitializeThis : -# 796| v0_4(void) = NoOp : -# 796| r0_5(glval) = FieldAddress[derivedvb_s] : r0_3 -# 796| r0_6(glval) = FunctionAddress[~String] : -# 796| v0_7(void) = Call : func:r0_6, this:r0_5 -# 796| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 -# 796| r0_9(glval) = ConvertToBase[DerivedVB : MiddleVB2] : r0_3 -# 796| r0_10(glval) = FunctionAddress[~MiddleVB2] : -# 796| v0_11(void) = Call : func:r0_10, this:r0_9 -# 796| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 796| r0_13(glval) = ConvertToBase[DerivedVB : MiddleVB1] : r0_3 -# 796| r0_14(glval) = FunctionAddress[~MiddleVB1] : -# 796| v0_15(void) = Call : func:r0_14, this:r0_13 -# 796| mu0_16(unknown) = ^CallSideEffect : ~mu0_2 -# 796| r0_17(glval) = ConvertToBase[DerivedVB : Base] : r0_3 -# 796| r0_18(glval) = FunctionAddress[~Base] : -# 796| v0_19(void) = Call : func:r0_18, this:r0_17 -# 796| mu0_20(unknown) = ^CallSideEffect : ~mu0_2 -# 795| v0_21(void) = ReturnVoid : -# 795| v0_22(void) = UnmodeledUse : mu* -# 795| v0_23(void) = AliasedUse : ~mu0_2 -# 795| v0_24(void) = ExitFunction : +# 795| v0_0(void) = EnterFunction : +# 795| mu0_1(unknown) = AliasedDefinition : +# 795| mu0_2(unknown) = UnmodeledDefinition : +# 795| r0_3(glval) = InitializeThis : +# 796| v0_4(void) = NoOp : +# 796| r0_5(glval) = FieldAddress[derivedvb_s] : r0_3 +# 796| r0_6(glval) = FunctionAddress[~String] : +# 796| v0_7(void) = Call : func:r0_6, this:r0_5 +# 796| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 +# 796| r0_9(glval) = ConvertToNonVirtualBase[DerivedVB : MiddleVB2] : r0_3 +# 796| r0_10(glval) = FunctionAddress[~MiddleVB2] : +# 796| v0_11(void) = Call : func:r0_10, this:r0_9 +# 796| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 +# 796| r0_13(glval) = ConvertToNonVirtualBase[DerivedVB : MiddleVB1] : r0_3 +# 796| r0_14(glval) = FunctionAddress[~MiddleVB1] : +# 796| v0_15(void) = Call : func:r0_14, this:r0_13 +# 796| mu0_16(unknown) = ^CallSideEffect : ~mu0_2 +# 796| r0_17(glval) = ConvertToNonVirtualBase[DerivedVB : Base] : r0_3 +# 796| r0_18(glval) = FunctionAddress[~Base] : +# 796| v0_19(void) = Call : func:r0_18, this:r0_17 +# 796| mu0_20(unknown) = ^CallSideEffect : ~mu0_2 +# 795| v0_21(void) = ReturnVoid : +# 795| v0_22(void) = UnmodeledUse : mu* +# 795| v0_23(void) = AliasedUse : ~mu0_2 +# 795| v0_24(void) = ExitFunction : # 799| void HierarchyConversions() # 799| Block 0 -# 799| v0_0(void) = EnterFunction : -# 799| mu0_1(unknown) = AliasedDefinition : -# 799| mu0_2(unknown) = UnmodeledDefinition : -# 800| r0_3(glval) = VariableAddress[b] : -# 800| r0_4(glval) = FunctionAddress[Base] : -# 800| v0_5(void) = Call : func:r0_4, this:r0_3 -# 800| mu0_6(unknown) = ^CallSideEffect : ~mu0_2 -# 801| r0_7(glval) = VariableAddress[m] : -# 801| r0_8(glval) = FunctionAddress[Middle] : -# 801| v0_9(void) = Call : func:r0_8, this:r0_7 -# 801| mu0_10(unknown) = ^CallSideEffect : ~mu0_2 -# 802| r0_11(glval) = VariableAddress[d] : -# 802| r0_12(glval) = FunctionAddress[Derived] : -# 802| v0_13(void) = Call : func:r0_12, this:r0_11 -# 802| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 -# 804| r0_15(glval) = VariableAddress[pb] : -# 804| r0_16(glval) = VariableAddress[b] : -# 804| r0_17(Base *) = CopyValue : r0_16 -# 804| mu0_18(Base *) = Store : &:r0_15, r0_17 -# 805| r0_19(glval) = VariableAddress[pm] : -# 805| r0_20(glval) = VariableAddress[m] : -# 805| r0_21(Middle *) = CopyValue : r0_20 -# 805| mu0_22(Middle *) = Store : &:r0_19, r0_21 -# 806| r0_23(glval) = VariableAddress[pd] : -# 806| r0_24(glval) = VariableAddress[d] : -# 806| r0_25(Derived *) = CopyValue : r0_24 -# 806| mu0_26(Derived *) = Store : &:r0_23, r0_25 -# 808| r0_27(glval) = VariableAddress[b] : -# 808| r0_28(glval) = FunctionAddress[operator=] : -# 808| r0_29(glval) = VariableAddress[m] : -# 808| r0_30(glval) = ConvertToBase[Middle : Base] : r0_29 -# 808| r0_31(Base &) = CopyValue : r0_30 -# 808| r0_32(Base &) = Call : func:r0_28, this:r0_27, 0:r0_31 -# 808| mu0_33(unknown) = ^CallSideEffect : ~mu0_2 -# 808| v0_34(void) = ^BufferReadSideEffect[-1] : &:r0_27, ~mu0_2 -# 808| v0_35(void) = ^BufferReadSideEffect[0] : &:r0_31, ~mu0_2 -# 808| mu0_36(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_27 -# 808| mu0_37(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_31 -# 808| r0_38(glval) = CopyValue : r0_32 -# 809| r0_39(glval) = VariableAddress[b] : -# 809| r0_40(glval) = FunctionAddress[operator=] : -# 809| r0_41(glval) = FunctionAddress[Base] : -# 809| r0_42(glval) = VariableAddress[m] : -# 809| r0_43(glval) = ConvertToBase[Middle : Base] : r0_42 -# 809| r0_44(Base &) = CopyValue : r0_43 -# 809| v0_45(void) = Call : func:r0_41, 0:r0_44 -# 809| mu0_46(unknown) = ^CallSideEffect : ~mu0_2 -# 809| v0_47(void) = ^BufferReadSideEffect[0] : &:r0_44, ~mu0_2 -# 809| mu0_48(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_44 -# 809| r0_49(glval) = Convert : v0_45 -# 809| r0_50(Base &) = CopyValue : r0_49 -# 809| r0_51(Base &) = Call : func:r0_40, this:r0_39, 0:r0_50 -# 809| mu0_52(unknown) = ^CallSideEffect : ~mu0_2 -# 809| v0_53(void) = ^BufferReadSideEffect[-1] : &:r0_39, ~mu0_2 -# 809| v0_54(void) = ^BufferReadSideEffect[0] : &:r0_50, ~mu0_2 -# 809| mu0_55(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_39 -# 809| mu0_56(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_50 -# 809| r0_57(glval) = CopyValue : r0_51 -# 810| r0_58(glval) = VariableAddress[b] : -# 810| r0_59(glval) = FunctionAddress[operator=] : -# 810| r0_60(glval) = FunctionAddress[Base] : -# 810| r0_61(glval) = VariableAddress[m] : -# 810| r0_62(glval) = ConvertToBase[Middle : Base] : r0_61 -# 810| r0_63(Base &) = CopyValue : r0_62 -# 810| v0_64(void) = Call : func:r0_60, 0:r0_63 -# 810| mu0_65(unknown) = ^CallSideEffect : ~mu0_2 -# 810| v0_66(void) = ^BufferReadSideEffect[0] : &:r0_63, ~mu0_2 -# 810| mu0_67(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_63 -# 810| r0_68(glval) = Convert : v0_64 -# 810| r0_69(Base &) = CopyValue : r0_68 -# 810| r0_70(Base &) = Call : func:r0_59, this:r0_58, 0:r0_69 -# 810| mu0_71(unknown) = ^CallSideEffect : ~mu0_2 -# 810| v0_72(void) = ^BufferReadSideEffect[-1] : &:r0_58, ~mu0_2 -# 810| v0_73(void) = ^BufferReadSideEffect[0] : &:r0_69, ~mu0_2 -# 810| mu0_74(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_58 -# 810| mu0_75(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_69 -# 810| r0_76(glval) = CopyValue : r0_70 -# 811| r0_77(glval) = VariableAddress[pm] : -# 811| r0_78(Middle *) = Load : &:r0_77, ~mu0_2 -# 811| r0_79(Base *) = ConvertToBase[Middle : Base] : r0_78 -# 811| r0_80(glval) = VariableAddress[pb] : -# 811| mu0_81(Base *) = Store : &:r0_80, r0_79 -# 812| r0_82(glval) = VariableAddress[pm] : -# 812| r0_83(Middle *) = Load : &:r0_82, ~mu0_2 -# 812| r0_84(Base *) = ConvertToBase[Middle : Base] : r0_83 -# 812| r0_85(glval) = VariableAddress[pb] : -# 812| mu0_86(Base *) = Store : &:r0_85, r0_84 -# 813| r0_87(glval) = VariableAddress[pm] : -# 813| r0_88(Middle *) = Load : &:r0_87, ~mu0_2 -# 813| r0_89(Base *) = ConvertToBase[Middle : Base] : r0_88 -# 813| r0_90(glval) = VariableAddress[pb] : -# 813| mu0_91(Base *) = Store : &:r0_90, r0_89 -# 814| r0_92(glval) = VariableAddress[pm] : -# 814| r0_93(Middle *) = Load : &:r0_92, ~mu0_2 -# 814| r0_94(Base *) = Convert : r0_93 -# 814| r0_95(glval) = VariableAddress[pb] : -# 814| mu0_96(Base *) = Store : &:r0_95, r0_94 -# 816| r0_97(glval) = VariableAddress[m] : -# 816| r0_98(glval) = FunctionAddress[operator=] : -# 816| r0_99(glval) = VariableAddress[b] : -# 816| r0_100(glval) = ConvertToDerived[Middle : Base] : r0_99 -# 816| r0_101(glval) = Convert : r0_100 -# 816| r0_102(Middle &) = CopyValue : r0_101 -# 816| r0_103(Middle &) = Call : func:r0_98, this:r0_97, 0:r0_102 -# 816| mu0_104(unknown) = ^CallSideEffect : ~mu0_2 -# 816| v0_105(void) = ^BufferReadSideEffect[-1] : &:r0_97, ~mu0_2 -# 816| v0_106(void) = ^BufferReadSideEffect[0] : &:r0_102, ~mu0_2 -# 816| mu0_107(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_97 -# 816| mu0_108(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_102 -# 816| r0_109(glval) = CopyValue : r0_103 -# 817| r0_110(glval) = VariableAddress[m] : -# 817| r0_111(glval) = FunctionAddress[operator=] : -# 817| r0_112(glval) = VariableAddress[b] : -# 817| r0_113(glval) = ConvertToDerived[Middle : Base] : r0_112 -# 817| r0_114(glval) = Convert : r0_113 -# 817| r0_115(Middle &) = CopyValue : r0_114 -# 817| r0_116(Middle &) = Call : func:r0_111, this:r0_110, 0:r0_115 -# 817| mu0_117(unknown) = ^CallSideEffect : ~mu0_2 -# 817| v0_118(void) = ^BufferReadSideEffect[-1] : &:r0_110, ~mu0_2 -# 817| v0_119(void) = ^BufferReadSideEffect[0] : &:r0_115, ~mu0_2 -# 817| mu0_120(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_110 -# 817| mu0_121(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_115 -# 817| r0_122(glval) = CopyValue : r0_116 -# 818| r0_123(glval) = VariableAddress[pb] : -# 818| r0_124(Base *) = Load : &:r0_123, ~mu0_2 -# 818| r0_125(Middle *) = ConvertToDerived[Middle : Base] : r0_124 -# 818| r0_126(glval) = VariableAddress[pm] : -# 818| mu0_127(Middle *) = Store : &:r0_126, r0_125 -# 819| r0_128(glval) = VariableAddress[pb] : -# 819| r0_129(Base *) = Load : &:r0_128, ~mu0_2 -# 819| r0_130(Middle *) = ConvertToDerived[Middle : Base] : r0_129 -# 819| r0_131(glval) = VariableAddress[pm] : -# 819| mu0_132(Middle *) = Store : &:r0_131, r0_130 -# 820| r0_133(glval) = VariableAddress[pb] : -# 820| r0_134(Base *) = Load : &:r0_133, ~mu0_2 -# 820| r0_135(Middle *) = Convert : r0_134 -# 820| r0_136(glval) = VariableAddress[pm] : -# 820| mu0_137(Middle *) = Store : &:r0_136, r0_135 -# 822| r0_138(glval) = VariableAddress[b] : -# 822| r0_139(glval) = FunctionAddress[operator=] : -# 822| r0_140(glval) = VariableAddress[d] : -# 822| r0_141(glval) = ConvertToBase[Derived : Middle] : r0_140 -# 822| r0_142(glval) = ConvertToBase[Middle : Base] : r0_141 -# 822| r0_143(Base &) = CopyValue : r0_142 -# 822| r0_144(Base &) = Call : func:r0_139, this:r0_138, 0:r0_143 -# 822| mu0_145(unknown) = ^CallSideEffect : ~mu0_2 -# 822| v0_146(void) = ^BufferReadSideEffect[-1] : &:r0_138, ~mu0_2 -# 822| v0_147(void) = ^BufferReadSideEffect[0] : &:r0_143, ~mu0_2 -# 822| mu0_148(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_138 -# 822| mu0_149(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_143 -# 822| r0_150(glval) = CopyValue : r0_144 -# 823| r0_151(glval) = VariableAddress[b] : -# 823| r0_152(glval) = FunctionAddress[operator=] : -# 823| r0_153(glval) = FunctionAddress[Base] : -# 823| r0_154(glval) = VariableAddress[d] : -# 823| r0_155(glval) = ConvertToBase[Derived : Middle] : r0_154 -# 823| r0_156(glval) = ConvertToBase[Middle : Base] : r0_155 -# 823| r0_157(Base &) = CopyValue : r0_156 -# 823| v0_158(void) = Call : func:r0_153, 0:r0_157 -# 823| mu0_159(unknown) = ^CallSideEffect : ~mu0_2 -# 823| v0_160(void) = ^BufferReadSideEffect[0] : &:r0_157, ~mu0_2 -# 823| mu0_161(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_157 -# 823| r0_162(glval) = Convert : v0_158 -# 823| r0_163(Base &) = CopyValue : r0_162 -# 823| r0_164(Base &) = Call : func:r0_152, this:r0_151, 0:r0_163 -# 823| mu0_165(unknown) = ^CallSideEffect : ~mu0_2 -# 823| v0_166(void) = ^BufferReadSideEffect[-1] : &:r0_151, ~mu0_2 -# 823| v0_167(void) = ^BufferReadSideEffect[0] : &:r0_163, ~mu0_2 -# 823| mu0_168(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_151 -# 823| mu0_169(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_163 -# 823| r0_170(glval) = CopyValue : r0_164 -# 824| r0_171(glval) = VariableAddress[b] : -# 824| r0_172(glval) = FunctionAddress[operator=] : -# 824| r0_173(glval) = FunctionAddress[Base] : -# 824| r0_174(glval) = VariableAddress[d] : -# 824| r0_175(glval) = ConvertToBase[Derived : Middle] : r0_174 -# 824| r0_176(glval) = ConvertToBase[Middle : Base] : r0_175 -# 824| r0_177(Base &) = CopyValue : r0_176 -# 824| v0_178(void) = Call : func:r0_173, 0:r0_177 -# 824| mu0_179(unknown) = ^CallSideEffect : ~mu0_2 -# 824| v0_180(void) = ^BufferReadSideEffect[0] : &:r0_177, ~mu0_2 -# 824| mu0_181(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_177 -# 824| r0_182(glval) = Convert : v0_178 -# 824| r0_183(Base &) = CopyValue : r0_182 -# 824| r0_184(Base &) = Call : func:r0_172, this:r0_171, 0:r0_183 -# 824| mu0_185(unknown) = ^CallSideEffect : ~mu0_2 -# 824| v0_186(void) = ^BufferReadSideEffect[-1] : &:r0_171, ~mu0_2 -# 824| v0_187(void) = ^BufferReadSideEffect[0] : &:r0_183, ~mu0_2 -# 824| mu0_188(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_171 -# 824| mu0_189(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_183 -# 824| r0_190(glval) = CopyValue : r0_184 -# 825| r0_191(glval) = VariableAddress[pd] : -# 825| r0_192(Derived *) = Load : &:r0_191, ~mu0_2 -# 825| r0_193(Middle *) = ConvertToBase[Derived : Middle] : r0_192 -# 825| r0_194(Base *) = ConvertToBase[Middle : Base] : r0_193 -# 825| r0_195(glval) = VariableAddress[pb] : -# 825| mu0_196(Base *) = Store : &:r0_195, r0_194 -# 826| r0_197(glval) = VariableAddress[pd] : -# 826| r0_198(Derived *) = Load : &:r0_197, ~mu0_2 -# 826| r0_199(Middle *) = ConvertToBase[Derived : Middle] : r0_198 -# 826| r0_200(Base *) = ConvertToBase[Middle : Base] : r0_199 -# 826| r0_201(glval) = VariableAddress[pb] : -# 826| mu0_202(Base *) = Store : &:r0_201, r0_200 -# 827| r0_203(glval) = VariableAddress[pd] : -# 827| r0_204(Derived *) = Load : &:r0_203, ~mu0_2 -# 827| r0_205(Middle *) = ConvertToBase[Derived : Middle] : r0_204 -# 827| r0_206(Base *) = ConvertToBase[Middle : Base] : r0_205 -# 827| r0_207(glval) = VariableAddress[pb] : -# 827| mu0_208(Base *) = Store : &:r0_207, r0_206 -# 828| r0_209(glval) = VariableAddress[pd] : -# 828| r0_210(Derived *) = Load : &:r0_209, ~mu0_2 -# 828| r0_211(Base *) = Convert : r0_210 -# 828| r0_212(glval) = VariableAddress[pb] : -# 828| mu0_213(Base *) = Store : &:r0_212, r0_211 -# 830| r0_214(glval) = VariableAddress[d] : -# 830| r0_215(glval) = FunctionAddress[operator=] : -# 830| r0_216(glval) = VariableAddress[b] : -# 830| r0_217(glval) = ConvertToDerived[Middle : Base] : r0_216 -# 830| r0_218(glval) = ConvertToDerived[Derived : Middle] : r0_217 -# 830| r0_219(glval) = Convert : r0_218 -# 830| r0_220(Derived &) = CopyValue : r0_219 -# 830| r0_221(Derived &) = Call : func:r0_215, this:r0_214, 0:r0_220 -# 830| mu0_222(unknown) = ^CallSideEffect : ~mu0_2 -# 830| v0_223(void) = ^BufferReadSideEffect[-1] : &:r0_214, ~mu0_2 -# 830| v0_224(void) = ^BufferReadSideEffect[0] : &:r0_220, ~mu0_2 -# 830| mu0_225(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_214 -# 830| mu0_226(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_220 -# 830| r0_227(glval) = CopyValue : r0_221 -# 831| r0_228(glval) = VariableAddress[d] : -# 831| r0_229(glval) = FunctionAddress[operator=] : -# 831| r0_230(glval) = VariableAddress[b] : -# 831| r0_231(glval) = ConvertToDerived[Middle : Base] : r0_230 -# 831| r0_232(glval) = ConvertToDerived[Derived : Middle] : r0_231 -# 831| r0_233(glval) = Convert : r0_232 -# 831| r0_234(Derived &) = CopyValue : r0_233 -# 831| r0_235(Derived &) = Call : func:r0_229, this:r0_228, 0:r0_234 -# 831| mu0_236(unknown) = ^CallSideEffect : ~mu0_2 -# 831| v0_237(void) = ^BufferReadSideEffect[-1] : &:r0_228, ~mu0_2 -# 831| v0_238(void) = ^BufferReadSideEffect[0] : &:r0_234, ~mu0_2 -# 831| mu0_239(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_228 -# 831| mu0_240(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_234 -# 831| r0_241(glval) = CopyValue : r0_235 -# 832| r0_242(glval) = VariableAddress[pb] : -# 832| r0_243(Base *) = Load : &:r0_242, ~mu0_2 -# 832| r0_244(Middle *) = ConvertToDerived[Middle : Base] : r0_243 -# 832| r0_245(Derived *) = ConvertToDerived[Derived : Middle] : r0_244 -# 832| r0_246(glval) = VariableAddress[pd] : -# 832| mu0_247(Derived *) = Store : &:r0_246, r0_245 -# 833| r0_248(glval) = VariableAddress[pb] : -# 833| r0_249(Base *) = Load : &:r0_248, ~mu0_2 -# 833| r0_250(Middle *) = ConvertToDerived[Middle : Base] : r0_249 -# 833| r0_251(Derived *) = ConvertToDerived[Derived : Middle] : r0_250 -# 833| r0_252(glval) = VariableAddress[pd] : -# 833| mu0_253(Derived *) = Store : &:r0_252, r0_251 -# 834| r0_254(glval) = VariableAddress[pb] : -# 834| r0_255(Base *) = Load : &:r0_254, ~mu0_2 -# 834| r0_256(Derived *) = Convert : r0_255 -# 834| r0_257(glval) = VariableAddress[pd] : -# 834| mu0_258(Derived *) = Store : &:r0_257, r0_256 -# 836| r0_259(glval) = VariableAddress[pmv] : -# 836| r0_260(MiddleVB1 *) = Constant[0] : -# 836| mu0_261(MiddleVB1 *) = Store : &:r0_259, r0_260 -# 837| r0_262(glval) = VariableAddress[pdv] : -# 837| r0_263(DerivedVB *) = Constant[0] : -# 837| mu0_264(DerivedVB *) = Store : &:r0_262, r0_263 -# 838| r0_265(glval) = VariableAddress[pmv] : -# 838| r0_266(MiddleVB1 *) = Load : &:r0_265, ~mu0_2 -# 838| r0_267(Base *) = ConvertToVirtualBase[MiddleVB1 : Base] : r0_266 -# 838| r0_268(glval) = VariableAddress[pb] : -# 838| mu0_269(Base *) = Store : &:r0_268, r0_267 -# 839| r0_270(glval) = VariableAddress[pdv] : -# 839| r0_271(DerivedVB *) = Load : &:r0_270, ~mu0_2 -# 839| r0_272(Base *) = ConvertToVirtualBase[DerivedVB : Base] : r0_271 -# 839| r0_273(glval) = VariableAddress[pb] : -# 839| mu0_274(Base *) = Store : &:r0_273, r0_272 -# 840| v0_275(void) = NoOp : -# 799| v0_276(void) = ReturnVoid : -# 799| v0_277(void) = UnmodeledUse : mu* -# 799| v0_278(void) = AliasedUse : ~mu0_2 -# 799| v0_279(void) = ExitFunction : +# 799| v0_0(void) = EnterFunction : +# 799| mu0_1(unknown) = AliasedDefinition : +# 799| mu0_2(unknown) = UnmodeledDefinition : +# 800| r0_3(glval) = VariableAddress[b] : +# 800| r0_4(glval) = FunctionAddress[Base] : +# 800| v0_5(void) = Call : func:r0_4, this:r0_3 +# 800| mu0_6(unknown) = ^CallSideEffect : ~mu0_2 +# 801| r0_7(glval) = VariableAddress[m] : +# 801| r0_8(glval) = FunctionAddress[Middle] : +# 801| v0_9(void) = Call : func:r0_8, this:r0_7 +# 801| mu0_10(unknown) = ^CallSideEffect : ~mu0_2 +# 802| r0_11(glval) = VariableAddress[d] : +# 802| r0_12(glval) = FunctionAddress[Derived] : +# 802| v0_13(void) = Call : func:r0_12, this:r0_11 +# 802| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 +# 804| r0_15(glval) = VariableAddress[pb] : +# 804| r0_16(glval) = VariableAddress[b] : +# 804| r0_17(Base *) = CopyValue : r0_16 +# 804| mu0_18(Base *) = Store : &:r0_15, r0_17 +# 805| r0_19(glval) = VariableAddress[pm] : +# 805| r0_20(glval) = VariableAddress[m] : +# 805| r0_21(Middle *) = CopyValue : r0_20 +# 805| mu0_22(Middle *) = Store : &:r0_19, r0_21 +# 806| r0_23(glval) = VariableAddress[pd] : +# 806| r0_24(glval) = VariableAddress[d] : +# 806| r0_25(Derived *) = CopyValue : r0_24 +# 806| mu0_26(Derived *) = Store : &:r0_23, r0_25 +# 808| r0_27(glval) = VariableAddress[b] : +# 808| r0_28(glval) = FunctionAddress[operator=] : +# 808| r0_29(glval) = VariableAddress[m] : +# 808| r0_30(glval) = ConvertToNonVirtualBase[Middle : Base] : r0_29 +# 808| r0_31(Base &) = CopyValue : r0_30 +# 808| r0_32(Base &) = Call : func:r0_28, this:r0_27, 0:r0_31 +# 808| mu0_33(unknown) = ^CallSideEffect : ~mu0_2 +# 808| v0_34(void) = ^BufferReadSideEffect[-1] : &:r0_27, ~mu0_2 +# 808| v0_35(void) = ^BufferReadSideEffect[0] : &:r0_31, ~mu0_2 +# 808| mu0_36(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_27 +# 808| mu0_37(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_31 +# 808| r0_38(glval) = CopyValue : r0_32 +# 809| r0_39(glval) = VariableAddress[b] : +# 809| r0_40(glval) = FunctionAddress[operator=] : +# 809| r0_41(glval) = FunctionAddress[Base] : +# 809| r0_42(glval) = VariableAddress[m] : +# 809| r0_43(glval) = ConvertToNonVirtualBase[Middle : Base] : r0_42 +# 809| r0_44(Base &) = CopyValue : r0_43 +# 809| v0_45(void) = Call : func:r0_41, 0:r0_44 +# 809| mu0_46(unknown) = ^CallSideEffect : ~mu0_2 +# 809| v0_47(void) = ^BufferReadSideEffect[0] : &:r0_44, ~mu0_2 +# 809| mu0_48(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_44 +# 809| r0_49(glval) = Convert : v0_45 +# 809| r0_50(Base &) = CopyValue : r0_49 +# 809| r0_51(Base &) = Call : func:r0_40, this:r0_39, 0:r0_50 +# 809| mu0_52(unknown) = ^CallSideEffect : ~mu0_2 +# 809| v0_53(void) = ^BufferReadSideEffect[-1] : &:r0_39, ~mu0_2 +# 809| v0_54(void) = ^BufferReadSideEffect[0] : &:r0_50, ~mu0_2 +# 809| mu0_55(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_39 +# 809| mu0_56(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_50 +# 809| r0_57(glval) = CopyValue : r0_51 +# 810| r0_58(glval) = VariableAddress[b] : +# 810| r0_59(glval) = FunctionAddress[operator=] : +# 810| r0_60(glval) = FunctionAddress[Base] : +# 810| r0_61(glval) = VariableAddress[m] : +# 810| r0_62(glval) = ConvertToNonVirtualBase[Middle : Base] : r0_61 +# 810| r0_63(Base &) = CopyValue : r0_62 +# 810| v0_64(void) = Call : func:r0_60, 0:r0_63 +# 810| mu0_65(unknown) = ^CallSideEffect : ~mu0_2 +# 810| v0_66(void) = ^BufferReadSideEffect[0] : &:r0_63, ~mu0_2 +# 810| mu0_67(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_63 +# 810| r0_68(glval) = Convert : v0_64 +# 810| r0_69(Base &) = CopyValue : r0_68 +# 810| r0_70(Base &) = Call : func:r0_59, this:r0_58, 0:r0_69 +# 810| mu0_71(unknown) = ^CallSideEffect : ~mu0_2 +# 810| v0_72(void) = ^BufferReadSideEffect[-1] : &:r0_58, ~mu0_2 +# 810| v0_73(void) = ^BufferReadSideEffect[0] : &:r0_69, ~mu0_2 +# 810| mu0_74(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_58 +# 810| mu0_75(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_69 +# 810| r0_76(glval) = CopyValue : r0_70 +# 811| r0_77(glval) = VariableAddress[pm] : +# 811| r0_78(Middle *) = Load : &:r0_77, ~mu0_2 +# 811| r0_79(Base *) = ConvertToNonVirtualBase[Middle : Base] : r0_78 +# 811| r0_80(glval) = VariableAddress[pb] : +# 811| mu0_81(Base *) = Store : &:r0_80, r0_79 +# 812| r0_82(glval) = VariableAddress[pm] : +# 812| r0_83(Middle *) = Load : &:r0_82, ~mu0_2 +# 812| r0_84(Base *) = ConvertToNonVirtualBase[Middle : Base] : r0_83 +# 812| r0_85(glval) = VariableAddress[pb] : +# 812| mu0_86(Base *) = Store : &:r0_85, r0_84 +# 813| r0_87(glval) = VariableAddress[pm] : +# 813| r0_88(Middle *) = Load : &:r0_87, ~mu0_2 +# 813| r0_89(Base *) = ConvertToNonVirtualBase[Middle : Base] : r0_88 +# 813| r0_90(glval) = VariableAddress[pb] : +# 813| mu0_91(Base *) = Store : &:r0_90, r0_89 +# 814| r0_92(glval) = VariableAddress[pm] : +# 814| r0_93(Middle *) = Load : &:r0_92, ~mu0_2 +# 814| r0_94(Base *) = Convert : r0_93 +# 814| r0_95(glval) = VariableAddress[pb] : +# 814| mu0_96(Base *) = Store : &:r0_95, r0_94 +# 816| r0_97(glval) = VariableAddress[m] : +# 816| r0_98(glval) = FunctionAddress[operator=] : +# 816| r0_99(glval) = VariableAddress[b] : +# 816| r0_100(glval) = ConvertToDerived[Middle : Base] : r0_99 +# 816| r0_101(glval) = Convert : r0_100 +# 816| r0_102(Middle &) = CopyValue : r0_101 +# 816| r0_103(Middle &) = Call : func:r0_98, this:r0_97, 0:r0_102 +# 816| mu0_104(unknown) = ^CallSideEffect : ~mu0_2 +# 816| v0_105(void) = ^BufferReadSideEffect[-1] : &:r0_97, ~mu0_2 +# 816| v0_106(void) = ^BufferReadSideEffect[0] : &:r0_102, ~mu0_2 +# 816| mu0_107(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_97 +# 816| mu0_108(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_102 +# 816| r0_109(glval) = CopyValue : r0_103 +# 817| r0_110(glval) = VariableAddress[m] : +# 817| r0_111(glval) = FunctionAddress[operator=] : +# 817| r0_112(glval) = VariableAddress[b] : +# 817| r0_113(glval) = ConvertToDerived[Middle : Base] : r0_112 +# 817| r0_114(glval) = Convert : r0_113 +# 817| r0_115(Middle &) = CopyValue : r0_114 +# 817| r0_116(Middle &) = Call : func:r0_111, this:r0_110, 0:r0_115 +# 817| mu0_117(unknown) = ^CallSideEffect : ~mu0_2 +# 817| v0_118(void) = ^BufferReadSideEffect[-1] : &:r0_110, ~mu0_2 +# 817| v0_119(void) = ^BufferReadSideEffect[0] : &:r0_115, ~mu0_2 +# 817| mu0_120(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_110 +# 817| mu0_121(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_115 +# 817| r0_122(glval) = CopyValue : r0_116 +# 818| r0_123(glval) = VariableAddress[pb] : +# 818| r0_124(Base *) = Load : &:r0_123, ~mu0_2 +# 818| r0_125(Middle *) = ConvertToDerived[Middle : Base] : r0_124 +# 818| r0_126(glval) = VariableAddress[pm] : +# 818| mu0_127(Middle *) = Store : &:r0_126, r0_125 +# 819| r0_128(glval) = VariableAddress[pb] : +# 819| r0_129(Base *) = Load : &:r0_128, ~mu0_2 +# 819| r0_130(Middle *) = ConvertToDerived[Middle : Base] : r0_129 +# 819| r0_131(glval) = VariableAddress[pm] : +# 819| mu0_132(Middle *) = Store : &:r0_131, r0_130 +# 820| r0_133(glval) = VariableAddress[pb] : +# 820| r0_134(Base *) = Load : &:r0_133, ~mu0_2 +# 820| r0_135(Middle *) = Convert : r0_134 +# 820| r0_136(glval) = VariableAddress[pm] : +# 820| mu0_137(Middle *) = Store : &:r0_136, r0_135 +# 822| r0_138(glval) = VariableAddress[b] : +# 822| r0_139(glval) = FunctionAddress[operator=] : +# 822| r0_140(glval) = VariableAddress[d] : +# 822| r0_141(glval) = ConvertToNonVirtualBase[Derived : Middle] : r0_140 +# 822| r0_142(glval) = ConvertToNonVirtualBase[Middle : Base] : r0_141 +# 822| r0_143(Base &) = CopyValue : r0_142 +# 822| r0_144(Base &) = Call : func:r0_139, this:r0_138, 0:r0_143 +# 822| mu0_145(unknown) = ^CallSideEffect : ~mu0_2 +# 822| v0_146(void) = ^BufferReadSideEffect[-1] : &:r0_138, ~mu0_2 +# 822| v0_147(void) = ^BufferReadSideEffect[0] : &:r0_143, ~mu0_2 +# 822| mu0_148(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_138 +# 822| mu0_149(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_143 +# 822| r0_150(glval) = CopyValue : r0_144 +# 823| r0_151(glval) = VariableAddress[b] : +# 823| r0_152(glval) = FunctionAddress[operator=] : +# 823| r0_153(glval) = FunctionAddress[Base] : +# 823| r0_154(glval) = VariableAddress[d] : +# 823| r0_155(glval) = ConvertToNonVirtualBase[Derived : Middle] : r0_154 +# 823| r0_156(glval) = ConvertToNonVirtualBase[Middle : Base] : r0_155 +# 823| r0_157(Base &) = CopyValue : r0_156 +# 823| v0_158(void) = Call : func:r0_153, 0:r0_157 +# 823| mu0_159(unknown) = ^CallSideEffect : ~mu0_2 +# 823| v0_160(void) = ^BufferReadSideEffect[0] : &:r0_157, ~mu0_2 +# 823| mu0_161(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_157 +# 823| r0_162(glval) = Convert : v0_158 +# 823| r0_163(Base &) = CopyValue : r0_162 +# 823| r0_164(Base &) = Call : func:r0_152, this:r0_151, 0:r0_163 +# 823| mu0_165(unknown) = ^CallSideEffect : ~mu0_2 +# 823| v0_166(void) = ^BufferReadSideEffect[-1] : &:r0_151, ~mu0_2 +# 823| v0_167(void) = ^BufferReadSideEffect[0] : &:r0_163, ~mu0_2 +# 823| mu0_168(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_151 +# 823| mu0_169(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_163 +# 823| r0_170(glval) = CopyValue : r0_164 +# 824| r0_171(glval) = VariableAddress[b] : +# 824| r0_172(glval) = FunctionAddress[operator=] : +# 824| r0_173(glval) = FunctionAddress[Base] : +# 824| r0_174(glval) = VariableAddress[d] : +# 824| r0_175(glval) = ConvertToNonVirtualBase[Derived : Middle] : r0_174 +# 824| r0_176(glval) = ConvertToNonVirtualBase[Middle : Base] : r0_175 +# 824| r0_177(Base &) = CopyValue : r0_176 +# 824| v0_178(void) = Call : func:r0_173, 0:r0_177 +# 824| mu0_179(unknown) = ^CallSideEffect : ~mu0_2 +# 824| v0_180(void) = ^BufferReadSideEffect[0] : &:r0_177, ~mu0_2 +# 824| mu0_181(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_177 +# 824| r0_182(glval) = Convert : v0_178 +# 824| r0_183(Base &) = CopyValue : r0_182 +# 824| r0_184(Base &) = Call : func:r0_172, this:r0_171, 0:r0_183 +# 824| mu0_185(unknown) = ^CallSideEffect : ~mu0_2 +# 824| v0_186(void) = ^BufferReadSideEffect[-1] : &:r0_171, ~mu0_2 +# 824| v0_187(void) = ^BufferReadSideEffect[0] : &:r0_183, ~mu0_2 +# 824| mu0_188(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_171 +# 824| mu0_189(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_183 +# 824| r0_190(glval) = CopyValue : r0_184 +# 825| r0_191(glval) = VariableAddress[pd] : +# 825| r0_192(Derived *) = Load : &:r0_191, ~mu0_2 +# 825| r0_193(Middle *) = ConvertToNonVirtualBase[Derived : Middle] : r0_192 +# 825| r0_194(Base *) = ConvertToNonVirtualBase[Middle : Base] : r0_193 +# 825| r0_195(glval) = VariableAddress[pb] : +# 825| mu0_196(Base *) = Store : &:r0_195, r0_194 +# 826| r0_197(glval) = VariableAddress[pd] : +# 826| r0_198(Derived *) = Load : &:r0_197, ~mu0_2 +# 826| r0_199(Middle *) = ConvertToNonVirtualBase[Derived : Middle] : r0_198 +# 826| r0_200(Base *) = ConvertToNonVirtualBase[Middle : Base] : r0_199 +# 826| r0_201(glval) = VariableAddress[pb] : +# 826| mu0_202(Base *) = Store : &:r0_201, r0_200 +# 827| r0_203(glval) = VariableAddress[pd] : +# 827| r0_204(Derived *) = Load : &:r0_203, ~mu0_2 +# 827| r0_205(Middle *) = ConvertToNonVirtualBase[Derived : Middle] : r0_204 +# 827| r0_206(Base *) = ConvertToNonVirtualBase[Middle : Base] : r0_205 +# 827| r0_207(glval) = VariableAddress[pb] : +# 827| mu0_208(Base *) = Store : &:r0_207, r0_206 +# 828| r0_209(glval) = VariableAddress[pd] : +# 828| r0_210(Derived *) = Load : &:r0_209, ~mu0_2 +# 828| r0_211(Base *) = Convert : r0_210 +# 828| r0_212(glval) = VariableAddress[pb] : +# 828| mu0_213(Base *) = Store : &:r0_212, r0_211 +# 830| r0_214(glval) = VariableAddress[d] : +# 830| r0_215(glval) = FunctionAddress[operator=] : +# 830| r0_216(glval) = VariableAddress[b] : +# 830| r0_217(glval) = ConvertToDerived[Middle : Base] : r0_216 +# 830| r0_218(glval) = ConvertToDerived[Derived : Middle] : r0_217 +# 830| r0_219(glval) = Convert : r0_218 +# 830| r0_220(Derived &) = CopyValue : r0_219 +# 830| r0_221(Derived &) = Call : func:r0_215, this:r0_214, 0:r0_220 +# 830| mu0_222(unknown) = ^CallSideEffect : ~mu0_2 +# 830| v0_223(void) = ^BufferReadSideEffect[-1] : &:r0_214, ~mu0_2 +# 830| v0_224(void) = ^BufferReadSideEffect[0] : &:r0_220, ~mu0_2 +# 830| mu0_225(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_214 +# 830| mu0_226(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_220 +# 830| r0_227(glval) = CopyValue : r0_221 +# 831| r0_228(glval) = VariableAddress[d] : +# 831| r0_229(glval) = FunctionAddress[operator=] : +# 831| r0_230(glval) = VariableAddress[b] : +# 831| r0_231(glval) = ConvertToDerived[Middle : Base] : r0_230 +# 831| r0_232(glval) = ConvertToDerived[Derived : Middle] : r0_231 +# 831| r0_233(glval) = Convert : r0_232 +# 831| r0_234(Derived &) = CopyValue : r0_233 +# 831| r0_235(Derived &) = Call : func:r0_229, this:r0_228, 0:r0_234 +# 831| mu0_236(unknown) = ^CallSideEffect : ~mu0_2 +# 831| v0_237(void) = ^BufferReadSideEffect[-1] : &:r0_228, ~mu0_2 +# 831| v0_238(void) = ^BufferReadSideEffect[0] : &:r0_234, ~mu0_2 +# 831| mu0_239(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_228 +# 831| mu0_240(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_234 +# 831| r0_241(glval) = CopyValue : r0_235 +# 832| r0_242(glval) = VariableAddress[pb] : +# 832| r0_243(Base *) = Load : &:r0_242, ~mu0_2 +# 832| r0_244(Middle *) = ConvertToDerived[Middle : Base] : r0_243 +# 832| r0_245(Derived *) = ConvertToDerived[Derived : Middle] : r0_244 +# 832| r0_246(glval) = VariableAddress[pd] : +# 832| mu0_247(Derived *) = Store : &:r0_246, r0_245 +# 833| r0_248(glval) = VariableAddress[pb] : +# 833| r0_249(Base *) = Load : &:r0_248, ~mu0_2 +# 833| r0_250(Middle *) = ConvertToDerived[Middle : Base] : r0_249 +# 833| r0_251(Derived *) = ConvertToDerived[Derived : Middle] : r0_250 +# 833| r0_252(glval) = VariableAddress[pd] : +# 833| mu0_253(Derived *) = Store : &:r0_252, r0_251 +# 834| r0_254(glval) = VariableAddress[pb] : +# 834| r0_255(Base *) = Load : &:r0_254, ~mu0_2 +# 834| r0_256(Derived *) = Convert : r0_255 +# 834| r0_257(glval) = VariableAddress[pd] : +# 834| mu0_258(Derived *) = Store : &:r0_257, r0_256 +# 836| r0_259(glval) = VariableAddress[pmv] : +# 836| r0_260(MiddleVB1 *) = Constant[0] : +# 836| mu0_261(MiddleVB1 *) = Store : &:r0_259, r0_260 +# 837| r0_262(glval) = VariableAddress[pdv] : +# 837| r0_263(DerivedVB *) = Constant[0] : +# 837| mu0_264(DerivedVB *) = Store : &:r0_262, r0_263 +# 838| r0_265(glval) = VariableAddress[pmv] : +# 838| r0_266(MiddleVB1 *) = Load : &:r0_265, ~mu0_2 +# 838| r0_267(Base *) = ConvertToVirtualBase[MiddleVB1 : Base] : r0_266 +# 838| r0_268(glval) = VariableAddress[pb] : +# 838| mu0_269(Base *) = Store : &:r0_268, r0_267 +# 839| r0_270(glval) = VariableAddress[pdv] : +# 839| r0_271(DerivedVB *) = Load : &:r0_270, ~mu0_2 +# 839| r0_272(Base *) = ConvertToVirtualBase[DerivedVB : Base] : r0_271 +# 839| r0_273(glval) = VariableAddress[pb] : +# 839| mu0_274(Base *) = Store : &:r0_273, r0_272 +# 840| v0_275(void) = NoOp : +# 799| v0_276(void) = ReturnVoid : +# 799| v0_277(void) = UnmodeledUse : mu* +# 799| v0_278(void) = AliasedUse : ~mu0_2 +# 799| v0_279(void) = ExitFunction : # 842| void PolymorphicBase::PolymorphicBase() # 842| Block 0 @@ -4093,35 +4069,35 @@ ir.cpp: # 846| void PolymorphicDerived::PolymorphicDerived() # 846| Block 0 -# 846| v0_0(void) = EnterFunction : -# 846| mu0_1(unknown) = AliasedDefinition : -# 846| mu0_2(unknown) = UnmodeledDefinition : -# 846| r0_3(glval) = InitializeThis : -# 846| r0_4(glval) = ConvertToBase[PolymorphicDerived : PolymorphicBase] : r0_3 -# 846| r0_5(glval) = FunctionAddress[PolymorphicBase] : -# 846| v0_6(void) = Call : func:r0_5, this:r0_4 -# 846| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 846| v0_8(void) = NoOp : -# 846| v0_9(void) = ReturnVoid : -# 846| v0_10(void) = UnmodeledUse : mu* -# 846| v0_11(void) = AliasedUse : ~mu0_2 -# 846| v0_12(void) = ExitFunction : +# 846| v0_0(void) = EnterFunction : +# 846| mu0_1(unknown) = AliasedDefinition : +# 846| mu0_2(unknown) = UnmodeledDefinition : +# 846| r0_3(glval) = InitializeThis : +# 846| r0_4(glval) = ConvertToNonVirtualBase[PolymorphicDerived : PolymorphicBase] : r0_3 +# 846| r0_5(glval) = FunctionAddress[PolymorphicBase] : +# 846| v0_6(void) = Call : func:r0_5, this:r0_4 +# 846| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 846| v0_8(void) = NoOp : +# 846| v0_9(void) = ReturnVoid : +# 846| v0_10(void) = UnmodeledUse : mu* +# 846| v0_11(void) = AliasedUse : ~mu0_2 +# 846| v0_12(void) = ExitFunction : # 846| void PolymorphicDerived::~PolymorphicDerived() # 846| Block 0 -# 846| v0_0(void) = EnterFunction : -# 846| mu0_1(unknown) = AliasedDefinition : -# 846| mu0_2(unknown) = UnmodeledDefinition : -# 846| r0_3(glval) = InitializeThis : -#-----| v0_4(void) = NoOp : -# 846| r0_5(glval) = ConvertToBase[PolymorphicDerived : PolymorphicBase] : r0_3 -# 846| r0_6(glval) = FunctionAddress[~PolymorphicBase] : -# 846| v0_7(void) = Call : func:r0_6, this:r0_5 -# 846| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 -# 846| v0_9(void) = ReturnVoid : -# 846| v0_10(void) = UnmodeledUse : mu* -# 846| v0_11(void) = AliasedUse : ~mu0_2 -# 846| v0_12(void) = ExitFunction : +# 846| v0_0(void) = EnterFunction : +# 846| mu0_1(unknown) = AliasedDefinition : +# 846| mu0_2(unknown) = UnmodeledDefinition : +# 846| r0_3(glval) = InitializeThis : +#-----| v0_4(void) = NoOp : +# 846| r0_5(glval) = ConvertToNonVirtualBase[PolymorphicDerived : PolymorphicBase] : r0_3 +# 846| r0_6(glval) = FunctionAddress[~PolymorphicBase] : +# 846| v0_7(void) = Call : func:r0_6, this:r0_5 +# 846| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 +# 846| v0_9(void) = ReturnVoid : +# 846| v0_10(void) = UnmodeledUse : mu* +# 846| v0_11(void) = AliasedUse : ~mu0_2 +# 846| v0_12(void) = ExitFunction : # 849| void DynamicCast() # 849| Block 0 diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected index c37bf5c8bfc..4180c41eb5f 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected @@ -700,65 +700,65 @@ test.cpp: # 104| int inheritanceConversions(Derived*) # 104| Block 0 -# 104| v0_0(void) = EnterFunction : -# 104| m0_1(unknown) = AliasedDefinition : +# 104| v0_0(void) = EnterFunction : +# 104| m0_1(unknown) = AliasedDefinition : # 104| valnum = unique -# 104| mu0_2(unknown) = UnmodeledDefinition : +# 104| mu0_2(unknown) = UnmodeledDefinition : # 104| valnum = unique -# 104| r0_3(glval) = VariableAddress[pd] : +# 104| r0_3(glval) = VariableAddress[pd] : # 104| valnum = r0_3 -# 104| m0_4(Derived *) = InitializeParameter[pd] : &:r0_3 +# 104| m0_4(Derived *) = InitializeParameter[pd] : &:r0_3 # 104| valnum = m0_4 -# 105| r0_5(glval) = VariableAddress[x] : +# 105| r0_5(glval) = VariableAddress[x] : # 105| valnum = unique -# 105| r0_6(glval) = VariableAddress[pd] : +# 105| r0_6(glval) = VariableAddress[pd] : # 105| valnum = r0_3 -# 105| r0_7(Derived *) = Load : &:r0_6, m0_4 +# 105| r0_7(Derived *) = Load : &:r0_6, m0_4 # 105| valnum = m0_4 -# 105| r0_8(Base *) = ConvertToBase[Derived : Base] : r0_7 +# 105| r0_8(Base *) = ConvertToNonVirtualBase[Derived : Base] : r0_7 # 105| valnum = r0_8 -# 105| r0_9(glval) = FieldAddress[b] : r0_8 +# 105| r0_9(glval) = FieldAddress[b] : r0_8 # 105| valnum = r0_9 -# 105| r0_10(int) = Load : &:r0_9, ~m0_1 +# 105| r0_10(int) = Load : &:r0_9, ~m0_1 # 105| valnum = r0_10 -# 105| m0_11(int) = Store : &:r0_5, r0_10 +# 105| m0_11(int) = Store : &:r0_5, r0_10 # 105| valnum = r0_10 -# 106| r0_12(glval) = VariableAddress[pb] : +# 106| r0_12(glval) = VariableAddress[pb] : # 106| valnum = r0_12 -# 106| r0_13(glval) = VariableAddress[pd] : +# 106| r0_13(glval) = VariableAddress[pd] : # 106| valnum = r0_3 -# 106| r0_14(Derived *) = Load : &:r0_13, m0_4 +# 106| r0_14(Derived *) = Load : &:r0_13, m0_4 # 106| valnum = m0_4 -# 106| r0_15(Base *) = ConvertToBase[Derived : Base] : r0_14 +# 106| r0_15(Base *) = ConvertToNonVirtualBase[Derived : Base] : r0_14 # 106| valnum = r0_8 -# 106| m0_16(Base *) = Store : &:r0_12, r0_15 +# 106| m0_16(Base *) = Store : &:r0_12, r0_15 # 106| valnum = r0_8 -# 107| r0_17(glval) = VariableAddress[y] : +# 107| r0_17(glval) = VariableAddress[y] : # 107| valnum = r0_17 -# 107| r0_18(glval) = VariableAddress[pb] : +# 107| r0_18(glval) = VariableAddress[pb] : # 107| valnum = r0_12 -# 107| r0_19(Base *) = Load : &:r0_18, m0_16 +# 107| r0_19(Base *) = Load : &:r0_18, m0_16 # 107| valnum = r0_8 -# 107| r0_20(glval) = FieldAddress[b] : r0_19 +# 107| r0_20(glval) = FieldAddress[b] : r0_19 # 107| valnum = r0_9 -# 107| r0_21(int) = Load : &:r0_20, ~m0_1 +# 107| r0_21(int) = Load : &:r0_20, ~m0_1 # 107| valnum = r0_21 -# 107| m0_22(int) = Store : &:r0_17, r0_21 +# 107| m0_22(int) = Store : &:r0_17, r0_21 # 107| valnum = r0_21 -# 109| r0_23(glval) = VariableAddress[#return] : +# 109| r0_23(glval) = VariableAddress[#return] : # 109| valnum = r0_23 -# 109| r0_24(glval) = VariableAddress[y] : +# 109| r0_24(glval) = VariableAddress[y] : # 109| valnum = r0_17 -# 109| r0_25(int) = Load : &:r0_24, m0_22 +# 109| r0_25(int) = Load : &:r0_24, m0_22 # 109| valnum = r0_21 -# 109| m0_26(int) = Store : &:r0_23, r0_25 +# 109| m0_26(int) = Store : &:r0_23, r0_25 # 109| valnum = r0_21 -# 104| r0_27(glval) = VariableAddress[#return] : +# 104| r0_27(glval) = VariableAddress[#return] : # 104| valnum = r0_23 -# 104| v0_28(void) = ReturnValue : &:r0_27, m0_26 -# 104| v0_29(void) = UnmodeledUse : mu* -# 104| v0_30(void) = AliasedUse : ~m0_1 -# 104| v0_31(void) = ExitFunction : +# 104| v0_28(void) = ReturnValue : &:r0_27, m0_26 +# 104| v0_29(void) = UnmodeledUse : mu* +# 104| v0_30(void) = AliasedUse : ~m0_1 +# 104| v0_31(void) = ExitFunction : # 112| void test06() # 112| Block 0 diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll index eb07be7f30c..4e3039b933e 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll @@ -34,7 +34,7 @@ private newtype TOpcode = TPointerSub() or TPointerDiff() or TConvert() or - TConvertToBase() or + TConvertToNonVirtualBase() or TConvertToVirtualBase() or TConvertToDerived() or TCheckedConvertOrNull() or @@ -302,8 +302,8 @@ module Opcode { final override string toString() { result = "Convert" } } - class ConvertToBase extends UnaryOpcode, TConvertToBase { - final override string toString() { result = "ConvertToBase" } + class ConvertToNonVirtualBase extends UnaryOpcode, TConvertToNonVirtualBase { + final override string toString() { result = "ConvertToNonVirtualBase" } } class ConvertToVirtualBase extends UnaryOpcode, TConvertToVirtualBase { diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll index 9f7cf68b065..4bdeedf2334 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll @@ -980,8 +980,8 @@ class InheritanceConversionInstruction extends UnaryInstruction { * Represents an instruction that converts from the address of a derived class * to the address of a direct non-virtual base class. */ -class ConvertToBaseInstruction extends InheritanceConversionInstruction { - ConvertToBaseInstruction() { getOpcode() instanceof Opcode::ConvertToBase } +class ConvertToNonVirtualBaseInstruction extends InheritanceConversionInstruction { + ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } } /** diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll index 9f7cf68b065..4bdeedf2334 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll @@ -980,8 +980,8 @@ class InheritanceConversionInstruction extends UnaryInstruction { * Represents an instruction that converts from the address of a derived class * to the address of a direct non-virtual base class. */ -class ConvertToBaseInstruction extends InheritanceConversionInstruction { - ConvertToBaseInstruction() { getOpcode() instanceof Opcode::ConvertToBase } +class ConvertToNonVirtualBaseInstruction extends InheritanceConversionInstruction { + ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } } /** diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index 1f5064f6766..a90eec8c17c 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -105,7 +105,7 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) { ( // REVIEW: See the REVIEW comment bellow // // Converting to a non-virtual base class adds the offset of the base class. - // exists(ConvertToBaseInstruction convert | + // exists(ConvertToNonVirtualBaseInstruction convert | // convert = instr and // bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8) // ) From 7758b43e34fd9c6050b7fd0b6dddfe46f4d66f85 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Sun, 10 Nov 2019 11:09:54 +0100 Subject: [PATCH 2/4] C++: Add ConvertToBase{Opcode,Instruction} classes These should make it easy to match base-class conversions when it's not important whether the base class is virtual. --- .../src/semmle/code/cpp/ir/implementation/Opcode.qll | 6 ++++-- .../ir/implementation/aliased_ssa/Instruction.qll | 12 ++++++++++-- .../code/cpp/ir/implementation/raw/Instruction.qll | 12 ++++++++++-- .../ir/implementation/unaliased_ssa/Instruction.qll | 12 ++++++++++-- .../semmle/code/csharp/ir/implementation/Opcode.qll | 6 ++++-- .../csharp/ir/implementation/raw/Instruction.qll | 12 ++++++++++-- .../ir/implementation/unaliased_ssa/Instruction.qll | 12 ++++++++++-- 7 files changed, 58 insertions(+), 14 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll index 4e3039b933e..0e4f800bb1b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll @@ -110,6 +110,8 @@ abstract class RelationalOpcode extends CompareOpcode { } abstract class CopyOpcode extends Opcode { } +abstract class ConvertToBaseOpcode extends UnaryOpcode { } + abstract class MemoryAccessOpcode extends Opcode { } abstract class ReturnOpcode extends Opcode { } @@ -302,11 +304,11 @@ module Opcode { final override string toString() { result = "Convert" } } - class ConvertToNonVirtualBase extends UnaryOpcode, TConvertToNonVirtualBase { + class ConvertToNonVirtualBase extends ConvertToBaseOpcode, TConvertToNonVirtualBase { final override string toString() { result = "ConvertToNonVirtualBase" } } - class ConvertToVirtualBase extends UnaryOpcode, TConvertToVirtualBase { + class ConvertToVirtualBase extends ConvertToBaseOpcode, TConvertToVirtualBase { final override string toString() { result = "ConvertToVirtualBase" } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index 4bdeedf2334..6cc1127c4bd 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -980,7 +980,15 @@ class InheritanceConversionInstruction extends UnaryInstruction { * Represents an instruction that converts from the address of a derived class * to the address of a direct non-virtual base class. */ -class ConvertToNonVirtualBaseInstruction extends InheritanceConversionInstruction { +class ConvertToBaseInstruction extends InheritanceConversionInstruction { + ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode } +} + +/** + * Represents an instruction that converts from the address of a derived class + * to the address of a direct non-virtual base class. + */ +class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } } @@ -988,7 +996,7 @@ class ConvertToNonVirtualBaseInstruction extends InheritanceConversionInstructio * Represents an instruction that converts from the address of a derived class * to the address of a virtual base class. */ -class ConvertToVirtualBaseInstruction extends InheritanceConversionInstruction { +class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll index 4bdeedf2334..6cc1127c4bd 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -980,7 +980,15 @@ class InheritanceConversionInstruction extends UnaryInstruction { * Represents an instruction that converts from the address of a derived class * to the address of a direct non-virtual base class. */ -class ConvertToNonVirtualBaseInstruction extends InheritanceConversionInstruction { +class ConvertToBaseInstruction extends InheritanceConversionInstruction { + ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode } +} + +/** + * Represents an instruction that converts from the address of a derived class + * to the address of a direct non-virtual base class. + */ +class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } } @@ -988,7 +996,7 @@ class ConvertToNonVirtualBaseInstruction extends InheritanceConversionInstructio * Represents an instruction that converts from the address of a derived class * to the address of a virtual base class. */ -class ConvertToVirtualBaseInstruction extends InheritanceConversionInstruction { +class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index 4bdeedf2334..6cc1127c4bd 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -980,7 +980,15 @@ class InheritanceConversionInstruction extends UnaryInstruction { * Represents an instruction that converts from the address of a derived class * to the address of a direct non-virtual base class. */ -class ConvertToNonVirtualBaseInstruction extends InheritanceConversionInstruction { +class ConvertToBaseInstruction extends InheritanceConversionInstruction { + ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode } +} + +/** + * Represents an instruction that converts from the address of a derived class + * to the address of a direct non-virtual base class. + */ +class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } } @@ -988,7 +996,7 @@ class ConvertToNonVirtualBaseInstruction extends InheritanceConversionInstructio * Represents an instruction that converts from the address of a derived class * to the address of a virtual base class. */ -class ConvertToVirtualBaseInstruction extends InheritanceConversionInstruction { +class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase } } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll index 4e3039b933e..0e4f800bb1b 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll @@ -110,6 +110,8 @@ abstract class RelationalOpcode extends CompareOpcode { } abstract class CopyOpcode extends Opcode { } +abstract class ConvertToBaseOpcode extends UnaryOpcode { } + abstract class MemoryAccessOpcode extends Opcode { } abstract class ReturnOpcode extends Opcode { } @@ -302,11 +304,11 @@ module Opcode { final override string toString() { result = "Convert" } } - class ConvertToNonVirtualBase extends UnaryOpcode, TConvertToNonVirtualBase { + class ConvertToNonVirtualBase extends ConvertToBaseOpcode, TConvertToNonVirtualBase { final override string toString() { result = "ConvertToNonVirtualBase" } } - class ConvertToVirtualBase extends UnaryOpcode, TConvertToVirtualBase { + class ConvertToVirtualBase extends ConvertToBaseOpcode, TConvertToVirtualBase { final override string toString() { result = "ConvertToVirtualBase" } } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll index 4bdeedf2334..6cc1127c4bd 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll @@ -980,7 +980,15 @@ class InheritanceConversionInstruction extends UnaryInstruction { * Represents an instruction that converts from the address of a derived class * to the address of a direct non-virtual base class. */ -class ConvertToNonVirtualBaseInstruction extends InheritanceConversionInstruction { +class ConvertToBaseInstruction extends InheritanceConversionInstruction { + ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode } +} + +/** + * Represents an instruction that converts from the address of a derived class + * to the address of a direct non-virtual base class. + */ +class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } } @@ -988,7 +996,7 @@ class ConvertToNonVirtualBaseInstruction extends InheritanceConversionInstructio * Represents an instruction that converts from the address of a derived class * to the address of a virtual base class. */ -class ConvertToVirtualBaseInstruction extends InheritanceConversionInstruction { +class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase } } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll index 4bdeedf2334..6cc1127c4bd 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll @@ -980,7 +980,15 @@ class InheritanceConversionInstruction extends UnaryInstruction { * Represents an instruction that converts from the address of a derived class * to the address of a direct non-virtual base class. */ -class ConvertToNonVirtualBaseInstruction extends InheritanceConversionInstruction { +class ConvertToBaseInstruction extends InheritanceConversionInstruction { + ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode } +} + +/** + * Represents an instruction that converts from the address of a derived class + * to the address of a direct non-virtual base class. + */ +class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } } @@ -988,7 +996,7 @@ class ConvertToNonVirtualBaseInstruction extends InheritanceConversionInstructio * Represents an instruction that converts from the address of a derived class * to the address of a virtual base class. */ -class ConvertToVirtualBaseInstruction extends InheritanceConversionInstruction { +class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase } } From 751263db919110e73e882e3a80222da6bcc8130b Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Sun, 10 Nov 2019 11:17:35 +0100 Subject: [PATCH 3/4] C++: Use ConvertToBaseInstruction in IR data flow This should make virtual dispatch work also for virtual bases. --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll index d149f33e55e..9572639de59 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll @@ -57,13 +57,13 @@ private predicate overrideMayAffectCall( * should usually be fewer classes than calls. * * If a value is cast several classes up in the hierarchy, that will be modeled - * as a chain of `ConvertToNonVirtualBaseInstruction`s and will cause the search to start + * as a chain of `ConvertToBaseInstruction`s and will cause the search to start * from each of them and pass through subsequent ones. There might be * performance to gain by stopping before a second upcast and reconstructing * the full chain in a "big-step" recursion after this one. */ private predicate nodeMayHaveClass(Class derived, DataFlow::Node node) { - exists(ConvertToNonVirtualBaseInstruction toBase | + exists(ConvertToBaseInstruction toBase | derived = toBase.getDerivedClass() and overrideMayAffectCall(derived, _, toBase.getEnclosingFunction(), _, _) and node.asInstruction() = toBase From eb55d964a8896e4421433ed79a9a07bc261de499 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Mon, 11 Nov 2019 15:39:53 +0100 Subject: [PATCH 4/4] C++: Fix semantic merge conflict This test output must have been wrong because I produced it with an extractor that didn't have #2153 applied. --- .../test/library-tests/ir/ir/raw_ir.expected | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) 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 5078a471b2b..1fedd09d5a6 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -1,4 +1,28 @@ bad_asts.cpp: +# 9| int Bad::S::MemberFunction(int) +# 9| Block 0 +# 9| v0_0(void) = EnterFunction : +# 9| mu0_1(unknown) = AliasedDefinition : +# 9| mu0_2(unknown) = UnmodeledDefinition : +# 9| r0_3(glval) = InitializeThis : +# 9| r0_4(glval) = VariableAddress[y] : +# 9| mu0_5(int) = InitializeParameter[y] : &:r0_4 +# 10| r0_6(glval) = VariableAddress[#return] : +# 10| r0_7(int) = Constant[6] : +#-----| r0_8(S *) = CopyValue : r0_3 +# 10| r0_9(glval) = FieldAddress[x] : r0_8 +# 10| r0_10(int) = Load : &:r0_9, ~mu0_2 +# 10| r0_11(int) = Add : r0_7, r0_10 +# 10| r0_12(glval) = VariableAddress[y] : +# 10| r0_13(int) = Load : &:r0_12, ~mu0_2 +# 10| r0_14(int) = Add : r0_11, r0_13 +# 10| mu0_15(int) = Store : &:r0_6, r0_14 +# 9| r0_16(glval) = VariableAddress[#return] : +# 9| v0_17(void) = ReturnValue : &:r0_16, ~mu0_2 +# 9| v0_18(void) = UnmodeledUse : mu* +# 9| v0_19(void) = AliasedUse : ~mu0_2 +# 9| v0_20(void) = ExitFunction : + # 14| void Bad::CallBadMemberFunction() # 14| Block 0 # 14| v0_0(void) = EnterFunction :