From f319381f277cd3469298f0e66077cde55fef47b7 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Wed, 16 Jul 2025 17:53:55 +0200 Subject: [PATCH 1/2] C++: Support the spaceship operator in the IR --- .../code/cpp/ir/implementation/Opcode.qll | 10 +++ .../aliased_ssa/Instruction.qll | 7 +++ .../cpp/ir/implementation/raw/Instruction.qll | 7 +++ .../raw/internal/TranslatedExpr.qll | 8 ++- .../unaliased_ssa/Instruction.qll | 7 +++ .../library-tests/ir/ir/aliased_ir.expected | 63 ++++++++++++++----- .../ir/ir/aliased_ssa_consistency.expected | 2 - .../aliased_ssa_consistency_unsound.expected | 2 - .../ir/ir/raw_consistency.expected | 8 --- .../test/library-tests/ir/ir/raw_ir.expected | 54 ++++++++-------- .../ir/ir/unaliased_ssa_consistency.expected | 2 - ...unaliased_ssa_consistency_unsound.expected | 2 - 12 files changed, 110 insertions(+), 62 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/Opcode.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/Opcode.qll index 90afabca30de..d8c1c6115c80 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/Opcode.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/Opcode.qll @@ -42,6 +42,7 @@ private newtype TOpcode = TCompareGT() or TCompareLE() or TCompareGE() or + TSpaceship() or TPointerAdd() or TPointerSub() or TPointerDiff() or @@ -765,6 +766,15 @@ module Opcode { final override string toString() { result = "CompareGE" } } + /** + * The `Opcode` for a `SpaceshipInstruction`. + * + * See the `SpaceshipInstruction` documentation for more details. + */ + class Spaceship extends BinaryOpcode, TSpaceship { + final override string toString() { result = "Spaceship" } + } + /** * The `Opcode` for a `PointerAddInstruction`. * diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index d5332cecf85a..f766185db86a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -1604,6 +1604,13 @@ class CompareGEInstruction extends RelationalInstruction { override predicate isStrict() { none() } } +/** + * An instruction that represents a three-way comparison operator. + */ +class CompareThreeWayInstruction extends BinaryInstruction { + CompareThreeWayInstruction() { this.getOpcode() instanceof Opcode::Spaceship } +} + /** * An instruction that branches to one of multiple successor instructions based on the value of an * integer operand. diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll index d5332cecf85a..f766185db86a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -1604,6 +1604,13 @@ class CompareGEInstruction extends RelationalInstruction { override predicate isStrict() { none() } } +/** + * An instruction that represents a three-way comparison operator. + */ +class CompareThreeWayInstruction extends BinaryInstruction { + CompareThreeWayInstruction() { this.getOpcode() instanceof Opcode::Spaceship } +} + /** * An instruction that branches to one of multiple successor instructions based on the value of an * integer operand. diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index 2aa5eeebb6b7..a7e85fe9b1a5 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -1808,6 +1808,11 @@ private Opcode comparisonOpcode(ComparisonOperation expr) { expr instanceof GEExpr and result instanceof Opcode::CompareGE } +private Opcode spaceShipOpcode(SpaceshipExpr expr) { + exists(expr) and + result instanceof Opcode::Spaceship +} + /** * IR translation of a simple binary operation. */ @@ -1867,7 +1872,8 @@ class TranslatedBinaryOperation extends TranslatedSingleInstructionExpr { override Opcode getOpcode() { result = binaryArithmeticOpcode(expr) or result = binaryBitwiseOpcode(expr) or - result = comparisonOpcode(expr) + result = comparisonOpcode(expr) or + result = spaceShipOpcode(expr) } override Type getExprType() { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index d5332cecf85a..f766185db86a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -1604,6 +1604,13 @@ class CompareGEInstruction extends RelationalInstruction { override predicate isStrict() { none() } } +/** + * An instruction that represents a three-way comparison operator. + */ +class CompareThreeWayInstruction extends BinaryInstruction { + CompareThreeWayInstruction() { this.getOpcode() instanceof Opcode::Spaceship } +} + /** * An instruction that branches to one of multiple successor instructions based on the value of an * integer operand. diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected index 51baf8a73f28..6d58656b55ff 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -20336,26 +20336,55 @@ ir.cpp: # 2766| r2766_20(glval) = CopyValue : r2766_19 # 2766| r2766_21(glval) = FieldAddress[x] : r2766_20 # 2766| r2766_22(int) = Load[?] : &:r2766_21, ~m2766_12 +# 2766| r2766_23(strong_ordering) = Spaceship : r2766_17, r2766_22 +# 2766| m2766_24(strong_ordering) = Store[#return] : &:r2766_13, r2766_23 +# 2766| v2766_25(void) = ReturnIndirection[#this] : &:r2766_7, m2766_8 +# 2766| v2766_26(void) = ReturnIndirection[y] : &:r2766_11, m2766_12 +# 2766| r2766_27(glval) = VariableAddress[#return] : +# 2766| v2766_28(void) = ReturnValue : &:r2766_27, m2766_24 +# 2766| v2766_29(void) = AliasedUse : m2766_3 +# 2766| v2766_30(void) = ExitFunction : # 2769| void test_three_way(int, int, ThreeWay, ThreeWay) # 2769| Block 0 -# 2769| v2769_1(void) = EnterFunction : -# 2769| m2769_2(unknown) = AliasedDefinition : -# 2769| m2769_3(unknown) = InitializeNonLocal : -# 2769| m2769_4(unknown) = Chi : total:m2769_2, partial:m2769_3 -# 2769| r2769_5(glval) = VariableAddress[a] : -# 2769| m2769_6(int) = InitializeParameter[a] : &:r2769_5 -# 2769| r2769_7(glval) = VariableAddress[b] : -# 2769| m2769_8(int) = InitializeParameter[b] : &:r2769_7 -# 2769| r2769_9(glval) = VariableAddress[c] : -# 2769| m2769_10(ThreeWay) = InitializeParameter[c] : &:r2769_9 -# 2769| r2769_11(glval) = VariableAddress[d] : -# 2769| m2769_12(ThreeWay) = InitializeParameter[d] : &:r2769_11 -# 2770| r2770_1(glval) = VariableAddress[x] : -# 2770| r2770_2(glval) = VariableAddress[a] : -# 2770| r2770_3(int) = Load[a] : &:r2770_2, m2769_6 -# 2770| r2770_4(glval) = VariableAddress[b] : -# 2770| r2770_5(int) = Load[b] : &:r2770_4, m2769_8 +# 2769| v2769_1(void) = EnterFunction : +# 2769| m2769_2(unknown) = AliasedDefinition : +# 2769| m2769_3(unknown) = InitializeNonLocal : +# 2769| m2769_4(unknown) = Chi : total:m2769_2, partial:m2769_3 +# 2769| r2769_5(glval) = VariableAddress[a] : +# 2769| m2769_6(int) = InitializeParameter[a] : &:r2769_5 +# 2769| r2769_7(glval) = VariableAddress[b] : +# 2769| m2769_8(int) = InitializeParameter[b] : &:r2769_7 +# 2769| r2769_9(glval) = VariableAddress[c] : +# 2769| m2769_10(ThreeWay) = InitializeParameter[c] : &:r2769_9 +# 2769| r2769_11(glval) = VariableAddress[d] : +# 2769| m2769_12(ThreeWay) = InitializeParameter[d] : &:r2769_11 +# 2770| r2770_1(glval) = VariableAddress[x] : +# 2770| r2770_2(glval) = VariableAddress[a] : +# 2770| r2770_3(int) = Load[a] : &:r2770_2, m2769_6 +# 2770| r2770_4(glval) = VariableAddress[b] : +# 2770| r2770_5(int) = Load[b] : &:r2770_4, m2769_8 +# 2770| r2770_6(strong_ordering) = Spaceship : r2770_3, r2770_5 +# 2770| m2770_7(strong_ordering) = Store[x] : &:r2770_1, r2770_6 +# 2771| r2771_1(glval) = VariableAddress[y] : +# 2771| r2771_2(glval) = VariableAddress[c] : +# 2771| r2771_3(glval) = FunctionAddress[operator<=>] : +# 2771| r2771_4(glval) = VariableAddress[d] : +# 2771| r2771_5(ThreeWay &) = CopyValue : r2771_4 +# 2771| r2771_6(strong_ordering) = Call[operator<=>] : func:r2771_3, this:r2771_2, 0:r2771_5 +# 2771| m2771_7(unknown) = ^CallSideEffect : ~m2769_4 +# 2771| m2771_8(unknown) = Chi : total:m2769_4, partial:m2771_7 +# 2771| v2771_9(void) = ^IndirectReadSideEffect[-1] : &:r2771_2, m2769_10 +# 2771| v2771_10(void) = ^BufferReadSideEffect[0] : &:r2771_5, ~m2769_12 +# 2771| m2771_11(ThreeWay) = ^IndirectMayWriteSideEffect[-1] : &:r2771_2 +# 2771| m2771_12(ThreeWay) = Chi : total:m2769_10, partial:m2771_11 +# 2771| m2771_13(unknown) = ^BufferMayWriteSideEffect[0] : &:r2771_5 +# 2771| m2771_14(ThreeWay) = Chi : total:m2769_12, partial:m2771_13 +# 2771| m2771_15(strong_ordering) = Store[y] : &:r2771_1, r2771_6 +# 2772| v2772_1(void) = NoOp : +# 2769| v2769_13(void) = ReturnVoid : +# 2769| v2769_14(void) = AliasedUse : ~m2771_8 +# 2769| v2769_15(void) = ExitFunction : ir23.cpp: # 1| bool consteval_1() diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected index d8abe2017336..b83d9ea47e38 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected @@ -6,8 +6,6 @@ missingOperandType duplicateChiOperand sideEffectWithoutPrimary instructionWithoutSuccessor -| ir.cpp:2766:72:2766:72 | Load: x | Instruction 'Load: x' has no successors in function '$@'. | ir.cpp:2766:24:2766:34 | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | -| ir.cpp:2770:18:2770:18 | Load: b | Instruction 'Load: b' has no successors in function '$@'. | ir.cpp:2769:6:2769:19 | void test_three_way(int, int, ThreeWay, ThreeWay) | void test_three_way(int, int, ThreeWay, ThreeWay) | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected index d8abe2017336..b83d9ea47e38 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected @@ -6,8 +6,6 @@ missingOperandType duplicateChiOperand sideEffectWithoutPrimary instructionWithoutSuccessor -| ir.cpp:2766:72:2766:72 | Load: x | Instruction 'Load: x' has no successors in function '$@'. | ir.cpp:2766:24:2766:34 | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | -| ir.cpp:2770:18:2770:18 | Load: b | Instruction 'Load: b' has no successors in function '$@'. | ir.cpp:2769:6:2769:19 | void test_three_way(int, int, ThreeWay, ThreeWay) | void test_three_way(int, int, ThreeWay, ThreeWay) | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction diff --git a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected index 949580140850..e30106d35204 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected @@ -1,6 +1,4 @@ missingOperand -| ir.cpp:2766:58:2766:72 | Store: ... <=> ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | ir.cpp:2766:24:2766:34 | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | -| ir.cpp:2770:12:2770:18 | Store: ... <=> ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | ir.cpp:2769:6:2769:19 | void test_three_way(int, int, ThreeWay, ThreeWay) | void test_three_way(int, int, ThreeWay, ThreeWay) | unexpectedOperand duplicateOperand missingPhiOperand @@ -8,8 +6,6 @@ missingOperandType duplicateChiOperand sideEffectWithoutPrimary instructionWithoutSuccessor -| ir.cpp:2766:72:2766:72 | Load: x | Instruction 'Load: x' has no successors in function '$@'. | ir.cpp:2766:24:2766:34 | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | -| ir.cpp:2770:18:2770:18 | Load: b | Instruction 'Load: b' has no successors in function '$@'. | ir.cpp:2769:6:2769:19 | void test_three_way(int, int, ThreeWay, ThreeWay) | void test_three_way(int, int, ThreeWay, ThreeWay) | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction @@ -25,10 +21,6 @@ lostReachability backEdgeCountMismatch useNotDominatedByDefinition | ir.cpp:1535:8:1535:8 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:1535:8:1535:8 | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | -| ir.cpp:2766:24:2766:34 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | ir.cpp:2766:24:2766:34 | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | -| ir.cpp:2766:46:2766:46 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | ir.cpp:2766:24:2766:34 | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | -| ir.cpp:2766:51:2766:73 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | ir.cpp:2766:24:2766:34 | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | -| ir.cpp:2770:8:2770:8 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | ir.cpp:2769:6:2769:19 | void test_three_way(int, int, ThreeWay, ThreeWay) | void test_three_way(int, int, ThreeWay, ThreeWay) | switchInstructionWithoutDefaultEdge notMarkedAsConflated wronglyMarkedAsConflated 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 436c59a32005..8cdb5e8c351f 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -18492,37 +18492,35 @@ ir.cpp: # 2766| r2766_19(glval) = CopyValue : r2766_18 # 2766| r2766_20(glval) = FieldAddress[x] : r2766_19 # 2766| r2766_21(int) = Load[?] : &:r2766_20, ~m? - -# 2766| Block 1 -# 2766| mu2766_22(strong_ordering) = Store[#return] : &:r2766_12 -# 2766| v2766_23(void) = ReturnIndirection[#this] : &:r2766_6, ~m? -# 2766| v2766_24(void) = ReturnIndirection[y] : &:r2766_10, ~m? -# 2766| r2766_25(glval) = VariableAddress[#return] : -# 2766| v2766_26(void) = ReturnValue : &:r2766_25, ~m? -# 2766| v2766_27(void) = AliasedUse : ~m? -# 2766| v2766_28(void) = ExitFunction : +# 2766| r2766_22(strong_ordering) = Spaceship : r2766_16, r2766_21 +# 2766| mu2766_23(strong_ordering) = Store[#return] : &:r2766_12, r2766_22 +# 2766| v2766_24(void) = ReturnIndirection[#this] : &:r2766_6, ~m? +# 2766| v2766_25(void) = ReturnIndirection[y] : &:r2766_10, ~m? +# 2766| r2766_26(glval) = VariableAddress[#return] : +# 2766| v2766_27(void) = ReturnValue : &:r2766_26, ~m? +# 2766| v2766_28(void) = AliasedUse : ~m? +# 2766| v2766_29(void) = ExitFunction : # 2769| void test_three_way(int, int, ThreeWay, ThreeWay) # 2769| Block 0 -# 2769| v2769_1(void) = EnterFunction : -# 2769| mu2769_2(unknown) = AliasedDefinition : -# 2769| mu2769_3(unknown) = InitializeNonLocal : -# 2769| r2769_4(glval) = VariableAddress[a] : -# 2769| mu2769_5(int) = InitializeParameter[a] : &:r2769_4 -# 2769| r2769_6(glval) = VariableAddress[b] : -# 2769| mu2769_7(int) = InitializeParameter[b] : &:r2769_6 -# 2769| r2769_8(glval) = VariableAddress[c] : -# 2769| mu2769_9(ThreeWay) = InitializeParameter[c] : &:r2769_8 -# 2769| r2769_10(glval) = VariableAddress[d] : -# 2769| mu2769_11(ThreeWay) = InitializeParameter[d] : &:r2769_10 -# 2770| r2770_1(glval) = VariableAddress[x] : -# 2770| r2770_2(glval) = VariableAddress[a] : -# 2770| r2770_3(int) = Load[a] : &:r2770_2, ~m? -# 2770| r2770_4(glval) = VariableAddress[b] : -# 2770| r2770_5(int) = Load[b] : &:r2770_4, ~m? - -# 2770| Block 1 -# 2770| mu2770_6(strong_ordering) = Store[x] : &:r2770_1 +# 2769| v2769_1(void) = EnterFunction : +# 2769| mu2769_2(unknown) = AliasedDefinition : +# 2769| mu2769_3(unknown) = InitializeNonLocal : +# 2769| r2769_4(glval) = VariableAddress[a] : +# 2769| mu2769_5(int) = InitializeParameter[a] : &:r2769_4 +# 2769| r2769_6(glval) = VariableAddress[b] : +# 2769| mu2769_7(int) = InitializeParameter[b] : &:r2769_6 +# 2769| r2769_8(glval) = VariableAddress[c] : +# 2769| mu2769_9(ThreeWay) = InitializeParameter[c] : &:r2769_8 +# 2769| r2769_10(glval) = VariableAddress[d] : +# 2769| mu2769_11(ThreeWay) = InitializeParameter[d] : &:r2769_10 +# 2770| r2770_1(glval) = VariableAddress[x] : +# 2770| r2770_2(glval) = VariableAddress[a] : +# 2770| r2770_3(int) = Load[a] : &:r2770_2, ~m? +# 2770| r2770_4(glval) = VariableAddress[b] : +# 2770| r2770_5(int) = Load[b] : &:r2770_4, ~m? +# 2770| r2770_6(strong_ordering) = Spaceship : r2770_3, r2770_5 +# 2770| mu2770_7(strong_ordering) = Store[x] : &:r2770_1, r2770_6 # 2771| r2771_1(glval) = VariableAddress[y] : # 2771| r2771_2(glval) = VariableAddress[c] : # 2771| r2771_3(glval) = FunctionAddress[operator<=>] : diff --git a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency.expected b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency.expected index d8abe2017336..b83d9ea47e38 100644 --- a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency.expected @@ -6,8 +6,6 @@ missingOperandType duplicateChiOperand sideEffectWithoutPrimary instructionWithoutSuccessor -| ir.cpp:2766:72:2766:72 | Load: x | Instruction 'Load: x' has no successors in function '$@'. | ir.cpp:2766:24:2766:34 | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | -| ir.cpp:2770:18:2770:18 | Load: b | Instruction 'Load: b' has no successors in function '$@'. | ir.cpp:2769:6:2769:19 | void test_three_way(int, int, ThreeWay, ThreeWay) | void test_three_way(int, int, ThreeWay, ThreeWay) | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction diff --git a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency_unsound.expected b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency_unsound.expected index d8abe2017336..b83d9ea47e38 100644 --- a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency_unsound.expected @@ -6,8 +6,6 @@ missingOperandType duplicateChiOperand sideEffectWithoutPrimary instructionWithoutSuccessor -| ir.cpp:2766:72:2766:72 | Load: x | Instruction 'Load: x' has no successors in function '$@'. | ir.cpp:2766:24:2766:34 | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | -| ir.cpp:2770:18:2770:18 | Load: b | Instruction 'Load: b' has no successors in function '$@'. | ir.cpp:2769:6:2769:19 | void test_three_way(int, int, ThreeWay, ThreeWay) | void test_three_way(int, int, ThreeWay, ThreeWay) | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction From 29a6af4efd18763a24b795b0ae1598814402a061 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Wed, 16 Jul 2025 18:11:17 +0200 Subject: [PATCH 2/2] C++: Fix instruction class name --- .../code/cpp/ir/implementation/aliased_ssa/Instruction.qll | 4 ++-- .../lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll | 4 ++-- .../code/cpp/ir/implementation/unaliased_ssa/Instruction.qll | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index f766185db86a..a564508e16b4 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -1607,8 +1607,8 @@ class CompareGEInstruction extends RelationalInstruction { /** * An instruction that represents a three-way comparison operator. */ -class CompareThreeWayInstruction extends BinaryInstruction { - CompareThreeWayInstruction() { this.getOpcode() instanceof Opcode::Spaceship } +class SpaceshipInstruction extends BinaryInstruction { + SpaceshipInstruction() { this.getOpcode() instanceof Opcode::Spaceship } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll index f766185db86a..a564508e16b4 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -1607,8 +1607,8 @@ class CompareGEInstruction extends RelationalInstruction { /** * An instruction that represents a three-way comparison operator. */ -class CompareThreeWayInstruction extends BinaryInstruction { - CompareThreeWayInstruction() { this.getOpcode() instanceof Opcode::Spaceship } +class SpaceshipInstruction extends BinaryInstruction { + SpaceshipInstruction() { this.getOpcode() instanceof Opcode::Spaceship } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index f766185db86a..a564508e16b4 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -1607,8 +1607,8 @@ class CompareGEInstruction extends RelationalInstruction { /** * An instruction that represents a three-way comparison operator. */ -class CompareThreeWayInstruction extends BinaryInstruction { - CompareThreeWayInstruction() { this.getOpcode() instanceof Opcode::Spaceship } +class SpaceshipInstruction extends BinaryInstruction { + SpaceshipInstruction() { this.getOpcode() instanceof Opcode::Spaceship } } /**