diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/Instruction.qll index d00999f894aa..661136c31124 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/Instruction.qll @@ -66,6 +66,13 @@ module InstructionSanity { count(instr.getOperand(tag)) > 1 and not tag instanceof UnmodeledUseOperand } + + query predicate operandAcrossFunctions( + Instruction op, Instruction operand, OperandTag tag + ) { + operand = op.getOperand(tag) and + operand.getFunctionIR() != op.getFunctionIR() + } } /** @@ -262,8 +269,8 @@ class Instruction extends Construction::TInstruction { // Register results are always in SSA form. not hasMemoryResult() or // An unmodeled result will have a use on the `UnmodeledUse` instruction. - not exists(UnmodeledUseOperand useTag | - hasUse(_, useTag) + not exists(Instruction useInstr, UnmodeledUseOperand useTag | + this = useInstr.getOperand(useTag) ) } @@ -296,15 +303,6 @@ class Instruction extends Construction::TInstruction { final Instruction getAPredecessor() { result = getPredecessor(_) } - - /** - * Holds if the result of this instruction is consumed by `useInstruction` as - * an operand with tag `useTag`. - */ - final predicate hasUse(Instruction useInstruction, OperandTag useTag) { - useInstruction.getFunctionIR() = funcIR and - this = useInstruction.getOperand(useTag) - } } class VariableInstruction extends Instruction { diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/AliasAnalysis.qll index c5fd6e1d5ae6..cc42ce1c96ea 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/AliasAnalysis.qll @@ -160,7 +160,7 @@ predicate operandEscapes(Instruction instr, OperandTag tag) { predicate resultEscapes(Instruction instr) { // The result escapes if it has at least one use that escapes. exists(Instruction useInstr, OperandTag useOperandTag | - instr.hasUse(useInstr, useOperandTag) and + useInstr.getOperand(useOperandTag) = instr and operandEscapes(useInstr, useOperandTag) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/Instruction.qll index d00999f894aa..661136c31124 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/Instruction.qll @@ -66,6 +66,13 @@ module InstructionSanity { count(instr.getOperand(tag)) > 1 and not tag instanceof UnmodeledUseOperand } + + query predicate operandAcrossFunctions( + Instruction op, Instruction operand, OperandTag tag + ) { + operand = op.getOperand(tag) and + operand.getFunctionIR() != op.getFunctionIR() + } } /** @@ -262,8 +269,8 @@ class Instruction extends Construction::TInstruction { // Register results are always in SSA form. not hasMemoryResult() or // An unmodeled result will have a use on the `UnmodeledUse` instruction. - not exists(UnmodeledUseOperand useTag | - hasUse(_, useTag) + not exists(Instruction useInstr, UnmodeledUseOperand useTag | + this = useInstr.getOperand(useTag) ) } @@ -296,15 +303,6 @@ class Instruction extends Construction::TInstruction { final Instruction getAPredecessor() { result = getPredecessor(_) } - - /** - * Holds if the result of this instruction is consumed by `useInstruction` as - * an operand with tag `useTag`. - */ - final predicate hasUse(Instruction useInstruction, OperandTag useTag) { - useInstruction.getFunctionIR() = funcIR and - this = useInstruction.getOperand(useTag) - } } class VariableInstruction extends Instruction { diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/AliasAnalysis.qll index c5fd6e1d5ae6..cc42ce1c96ea 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/AliasAnalysis.qll @@ -160,7 +160,7 @@ predicate operandEscapes(Instruction instr, OperandTag tag) { predicate resultEscapes(Instruction instr) { // The result escapes if it has at least one use that escapes. exists(Instruction useInstr, OperandTag useOperandTag | - instr.hasUse(useInstr, useOperandTag) and + useInstr.getOperand(useOperandTag) = instr and operandEscapes(useInstr, useOperandTag) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/Instruction.qll index d00999f894aa..661136c31124 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/Instruction.qll @@ -66,6 +66,13 @@ module InstructionSanity { count(instr.getOperand(tag)) > 1 and not tag instanceof UnmodeledUseOperand } + + query predicate operandAcrossFunctions( + Instruction op, Instruction operand, OperandTag tag + ) { + operand = op.getOperand(tag) and + operand.getFunctionIR() != op.getFunctionIR() + } } /** @@ -262,8 +269,8 @@ class Instruction extends Construction::TInstruction { // Register results are always in SSA form. not hasMemoryResult() or // An unmodeled result will have a use on the `UnmodeledUse` instruction. - not exists(UnmodeledUseOperand useTag | - hasUse(_, useTag) + not exists(Instruction useInstr, UnmodeledUseOperand useTag | + this = useInstr.getOperand(useTag) ) } @@ -296,15 +303,6 @@ class Instruction extends Construction::TInstruction { final Instruction getAPredecessor() { result = getPredecessor(_) } - - /** - * Holds if the result of this instruction is consumed by `useInstruction` as - * an operand with tag `useTag`. - */ - final predicate hasUse(Instruction useInstruction, OperandTag useTag) { - useInstruction.getFunctionIR() = funcIR and - this = useInstruction.getOperand(useTag) - } } class VariableInstruction extends Instruction { diff --git a/cpp/ql/test/library-tests/ir/ir/AliasedSSAIRSanity.expected b/cpp/ql/test/library-tests/ir/ir/AliasedSSAIRSanity.expected index 3d93d822b3cf..f05c1067fb9f 100644 --- a/cpp/ql/test/library-tests/ir/ir/AliasedSSAIRSanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/AliasedSSAIRSanity.expected @@ -1,3 +1,4 @@ missingOperand unexpectedOperand duplicateOperand +operandAcrossFunctions diff --git a/cpp/ql/test/library-tests/ir/ir/IRSanity.expected b/cpp/ql/test/library-tests/ir/ir/IRSanity.expected index 3d93d822b3cf..f05c1067fb9f 100644 --- a/cpp/ql/test/library-tests/ir/ir/IRSanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/IRSanity.expected @@ -1,3 +1,4 @@ missingOperand unexpectedOperand duplicateOperand +operandAcrossFunctions diff --git a/cpp/ql/test/library-tests/ir/ir/SSAIRSanity.expected b/cpp/ql/test/library-tests/ir/ir/SSAIRSanity.expected index 3d93d822b3cf..f05c1067fb9f 100644 --- a/cpp/ql/test/library-tests/ir/ir/SSAIRSanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/SSAIRSanity.expected @@ -1,3 +1,4 @@ missingOperand unexpectedOperand duplicateOperand +operandAcrossFunctions