mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
C++: Support the spaceship operator in the IR
This commit is contained in:
@@ -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`.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -20336,26 +20336,55 @@ ir.cpp:
|
||||
# 2766| r2766_20(glval<ThreeWay>) = CopyValue : r2766_19
|
||||
# 2766| r2766_21(glval<int>) = 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<strong_ordering>) = 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<int>) = VariableAddress[a] :
|
||||
# 2769| m2769_6(int) = InitializeParameter[a] : &:r2769_5
|
||||
# 2769| r2769_7(glval<int>) = VariableAddress[b] :
|
||||
# 2769| m2769_8(int) = InitializeParameter[b] : &:r2769_7
|
||||
# 2769| r2769_9(glval<ThreeWay>) = VariableAddress[c] :
|
||||
# 2769| m2769_10(ThreeWay) = InitializeParameter[c] : &:r2769_9
|
||||
# 2769| r2769_11(glval<ThreeWay>) = VariableAddress[d] :
|
||||
# 2769| m2769_12(ThreeWay) = InitializeParameter[d] : &:r2769_11
|
||||
# 2770| r2770_1(glval<strong_ordering>) = VariableAddress[x] :
|
||||
# 2770| r2770_2(glval<int>) = VariableAddress[a] :
|
||||
# 2770| r2770_3(int) = Load[a] : &:r2770_2, m2769_6
|
||||
# 2770| r2770_4(glval<int>) = 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<int>) = VariableAddress[a] :
|
||||
# 2769| m2769_6(int) = InitializeParameter[a] : &:r2769_5
|
||||
# 2769| r2769_7(glval<int>) = VariableAddress[b] :
|
||||
# 2769| m2769_8(int) = InitializeParameter[b] : &:r2769_7
|
||||
# 2769| r2769_9(glval<ThreeWay>) = VariableAddress[c] :
|
||||
# 2769| m2769_10(ThreeWay) = InitializeParameter[c] : &:r2769_9
|
||||
# 2769| r2769_11(glval<ThreeWay>) = VariableAddress[d] :
|
||||
# 2769| m2769_12(ThreeWay) = InitializeParameter[d] : &:r2769_11
|
||||
# 2770| r2770_1(glval<strong_ordering>) = VariableAddress[x] :
|
||||
# 2770| r2770_2(glval<int>) = VariableAddress[a] :
|
||||
# 2770| r2770_3(int) = Load[a] : &:r2770_2, m2769_6
|
||||
# 2770| r2770_4(glval<int>) = 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<strong_ordering>) = VariableAddress[y] :
|
||||
# 2771| r2771_2(glval<ThreeWay>) = VariableAddress[c] :
|
||||
# 2771| r2771_3(glval<unknown>) = FunctionAddress[operator<=>] :
|
||||
# 2771| r2771_4(glval<ThreeWay>) = 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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -18492,37 +18492,35 @@ ir.cpp:
|
||||
# 2766| r2766_19(glval<ThreeWay>) = CopyValue : r2766_18
|
||||
# 2766| r2766_20(glval<int>) = 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<strong_ordering>) = 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<strong_ordering>) = 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<int>) = VariableAddress[a] :
|
||||
# 2769| mu2769_5(int) = InitializeParameter[a] : &:r2769_4
|
||||
# 2769| r2769_6(glval<int>) = VariableAddress[b] :
|
||||
# 2769| mu2769_7(int) = InitializeParameter[b] : &:r2769_6
|
||||
# 2769| r2769_8(glval<ThreeWay>) = VariableAddress[c] :
|
||||
# 2769| mu2769_9(ThreeWay) = InitializeParameter[c] : &:r2769_8
|
||||
# 2769| r2769_10(glval<ThreeWay>) = VariableAddress[d] :
|
||||
# 2769| mu2769_11(ThreeWay) = InitializeParameter[d] : &:r2769_10
|
||||
# 2770| r2770_1(glval<strong_ordering>) = VariableAddress[x] :
|
||||
# 2770| r2770_2(glval<int>) = VariableAddress[a] :
|
||||
# 2770| r2770_3(int) = Load[a] : &:r2770_2, ~m?
|
||||
# 2770| r2770_4(glval<int>) = 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<int>) = VariableAddress[a] :
|
||||
# 2769| mu2769_5(int) = InitializeParameter[a] : &:r2769_4
|
||||
# 2769| r2769_6(glval<int>) = VariableAddress[b] :
|
||||
# 2769| mu2769_7(int) = InitializeParameter[b] : &:r2769_6
|
||||
# 2769| r2769_8(glval<ThreeWay>) = VariableAddress[c] :
|
||||
# 2769| mu2769_9(ThreeWay) = InitializeParameter[c] : &:r2769_8
|
||||
# 2769| r2769_10(glval<ThreeWay>) = VariableAddress[d] :
|
||||
# 2769| mu2769_11(ThreeWay) = InitializeParameter[d] : &:r2769_10
|
||||
# 2770| r2770_1(glval<strong_ordering>) = VariableAddress[x] :
|
||||
# 2770| r2770_2(glval<int>) = VariableAddress[a] :
|
||||
# 2770| r2770_3(int) = Load[a] : &:r2770_2, ~m?
|
||||
# 2770| r2770_4(glval<int>) = 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<strong_ordering>) = VariableAddress[y] :
|
||||
# 2771| r2771_2(glval<ThreeWay>) = VariableAddress[c] :
|
||||
# 2771| r2771_3(glval<unknown>) = FunctionAddress[operator<=>] :
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user