Skip to content

Commit 6370391

Browse files
C++: Add sanity test for definitions that don't dominate their uses.
1 parent 912679e commit 6370391

File tree

8 files changed

+152
-0
lines changed

8 files changed

+152
-0
lines changed

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,55 @@ module InstructionSanity {
215215
) and
216216
fromInstr != fromBlock
217217
}
218+
219+
/**
220+
* Gets the point in the function at which the specified operand is evaluated. For most operands,
221+
* this is at the instruction that consumes the use. For a `PhiInputOperand`, the effective point
222+
* of evaluation is at the end of the corresponding predecessor block.
223+
*/
224+
private predicate pointOfEvaluation(Operand operand, IRBlock block, int index) {
225+
(
226+
block = operand.(PhiInputOperand).getPredecessorBlock() and
227+
index = block.getInstructionCount()
228+
) or
229+
exists (Instruction use |
230+
use = operand.(NonPhiOperand).getUse() and
231+
block.getInstruction(index) = use
232+
)
233+
}
234+
235+
/**
236+
* Holds if `useOperand` has a definition that does not dominate the use.
237+
*/
238+
query predicate useNotDominatedByDefinition(Operand useOperand, string message, IRFunction func,
239+
string funcText) {
240+
241+
exists (IRBlock useBlock, int useIndex, Instruction defInstr, IRBlock defBlock, int defIndex |
242+
not useOperand.getUse() instanceof UnmodeledUseInstruction and
243+
pointOfEvaluation(useOperand, useBlock, useIndex) and
244+
defInstr = useOperand.getAnyDef() and
245+
(
246+
(
247+
defInstr instanceof PhiInstruction and
248+
defBlock = defInstr.getBlock() and
249+
defIndex = -1
250+
)
251+
or
252+
defBlock.getInstruction(defIndex) = defInstr
253+
) and
254+
not (
255+
defBlock.strictlyDominates(useBlock) or
256+
(
257+
defBlock = useBlock and
258+
defIndex < useIndex
259+
)
260+
) and
261+
message = "Operand '" + useOperand.toString() +
262+
"' is not dominated by its definition in function '$@'." and
263+
func = useOperand.getEnclosingIRFunction() and
264+
funcText = Language::getIdentityString(func.getFunction())
265+
)
266+
}
218267
}
219268

220269
/**

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,55 @@ module InstructionSanity {
215215
) and
216216
fromInstr != fromBlock
217217
}
218+
219+
/**
220+
* Gets the point in the function at which the specified operand is evaluated. For most operands,
221+
* this is at the instruction that consumes the use. For a `PhiInputOperand`, the effective point
222+
* of evaluation is at the end of the corresponding predecessor block.
223+
*/
224+
private predicate pointOfEvaluation(Operand operand, IRBlock block, int index) {
225+
(
226+
block = operand.(PhiInputOperand).getPredecessorBlock() and
227+
index = block.getInstructionCount()
228+
) or
229+
exists (Instruction use |
230+
use = operand.(NonPhiOperand).getUse() and
231+
block.getInstruction(index) = use
232+
)
233+
}
234+
235+
/**
236+
* Holds if `useOperand` has a definition that does not dominate the use.
237+
*/
238+
query predicate useNotDominatedByDefinition(Operand useOperand, string message, IRFunction func,
239+
string funcText) {
240+
241+
exists (IRBlock useBlock, int useIndex, Instruction defInstr, IRBlock defBlock, int defIndex |
242+
not useOperand.getUse() instanceof UnmodeledUseInstruction and
243+
pointOfEvaluation(useOperand, useBlock, useIndex) and
244+
defInstr = useOperand.getAnyDef() and
245+
(
246+
(
247+
defInstr instanceof PhiInstruction and
248+
defBlock = defInstr.getBlock() and
249+
defIndex = -1
250+
)
251+
or
252+
defBlock.getInstruction(defIndex) = defInstr
253+
) and
254+
not (
255+
defBlock.strictlyDominates(useBlock) or
256+
(
257+
defBlock = useBlock and
258+
defIndex < useIndex
259+
)
260+
) and
261+
message = "Operand '" + useOperand.toString() +
262+
"' is not dominated by its definition in function '$@'." and
263+
func = useOperand.getEnclosingIRFunction() and
264+
funcText = Language::getIdentityString(func.getFunction())
265+
)
266+
}
218267
}
219268

220269
/**

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,55 @@ module InstructionSanity {
215215
) and
216216
fromInstr != fromBlock
217217
}
218+
219+
/**
220+
* Gets the point in the function at which the specified operand is evaluated. For most operands,
221+
* this is at the instruction that consumes the use. For a `PhiInputOperand`, the effective point
222+
* of evaluation is at the end of the corresponding predecessor block.
223+
*/
224+
private predicate pointOfEvaluation(Operand operand, IRBlock block, int index) {
225+
(
226+
block = operand.(PhiInputOperand).getPredecessorBlock() and
227+
index = block.getInstructionCount()
228+
) or
229+
exists (Instruction use |
230+
use = operand.(NonPhiOperand).getUse() and
231+
block.getInstruction(index) = use
232+
)
233+
}
234+
235+
/**
236+
* Holds if `useOperand` has a definition that does not dominate the use.
237+
*/
238+
query predicate useNotDominatedByDefinition(Operand useOperand, string message, IRFunction func,
239+
string funcText) {
240+
241+
exists (IRBlock useBlock, int useIndex, Instruction defInstr, IRBlock defBlock, int defIndex |
242+
not useOperand.getUse() instanceof UnmodeledUseInstruction and
243+
pointOfEvaluation(useOperand, useBlock, useIndex) and
244+
defInstr = useOperand.getAnyDef() and
245+
(
246+
(
247+
defInstr instanceof PhiInstruction and
248+
defBlock = defInstr.getBlock() and
249+
defIndex = -1
250+
)
251+
or
252+
defBlock.getInstruction(defIndex) = defInstr
253+
) and
254+
not (
255+
defBlock.strictlyDominates(useBlock) or
256+
(
257+
defBlock = useBlock and
258+
defIndex < useIndex
259+
)
260+
) and
261+
message = "Operand '" + useOperand.toString() +
262+
"' is not dominated by its definition in function '$@'." and
263+
func = useOperand.getEnclosingIRFunction() and
264+
funcText = Language::getIdentityString(func.getFunction())
265+
)
266+
}
218267
}
219268

220269
/**

cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ instructionWithoutUniqueBlock
1212
containsLoopOfForwardEdges
1313
lostReachability
1414
backEdgeCountMismatch
15+
useNotDominatedByDefinition

cpp/ql/test/library-tests/ir/ir/raw_sanity.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ instructionWithoutUniqueBlock
1212
containsLoopOfForwardEdges
1313
lostReachability
1414
backEdgeCountMismatch
15+
useNotDominatedByDefinition

cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ instructionWithoutUniqueBlock
1212
containsLoopOfForwardEdges
1313
lostReachability
1414
backEdgeCountMismatch
15+
useNotDominatedByDefinition

cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ instructionWithoutUniqueBlock
1212
containsLoopOfForwardEdges
1313
lostReachability
1414
backEdgeCountMismatch
15+
useNotDominatedByDefinition

cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ instructionWithoutUniqueBlock
1212
containsLoopOfForwardEdges
1313
lostReachability
1414
backEdgeCountMismatch
15+
useNotDominatedByDefinition

0 commit comments

Comments
 (0)