C++: Create an abstract class to control debug 'toString' output for dataflow nodes.

This commit is contained in:
Mathias Vorreiter Pedersen
2023-12-13 12:05:04 +00:00
parent 27be5ba14b
commit 45080ec9f0
4 changed files with 94 additions and 14 deletions

View File

@@ -6,6 +6,7 @@ private import semmle.code.cpp.ir.internal.IRCppLanguage
private import SsaInternals as Ssa
private import DataFlowImplCommon as DataFlowImplCommon
private import codeql.util.Unit
import Node0ToString
cached
private module Cached {
@@ -138,11 +139,7 @@ abstract class InstructionNode0 extends Node0Impl {
override DataFlowType getType() { result = getInstructionType(instr, _) }
override string toStringImpl() {
if instr.(InitializeParameterInstruction).getIRVariable() instanceof IRThisVariable
then result = "this"
else result = instr.getAst().toString()
}
override string toStringImpl() { result = instructionToString(instr) }
override Location getLocationImpl() {
if exists(instr.getAst().getLocation())
@@ -187,11 +184,7 @@ abstract class OperandNode0 extends Node0Impl {
override DataFlowType getType() { result = getOperandType(op, _) }
override string toStringImpl() {
if op.getDef().(InitializeParameterInstruction).getIRVariable() instanceof IRThisVariable
then result = "this"
else result = op.getDef().getAst().toString()
}
override string toStringImpl() { result = operandToString(op) }
override Location getLocationImpl() {
if exists(op.getDef().getAst().getLocation())

View File

@@ -486,10 +486,13 @@ class Node extends TIRDataFlowNode {
}
private string toExprString(Node n) {
result = n.asExpr(0).toString()
or
not exists(n.asExpr()) and
result = n.asIndirectExpr(0, 1).toString() + " indirection"
isDebugMode() and
(
result = n.asExpr(0).toString()
or
not exists(n.asExpr()) and
result = n.asIndirectExpr(0, 1).toString() + " indirection"
)
}
/**

View File

@@ -0,0 +1,9 @@
/**
* This file activates debugging mode for dataflow node printing.
*/
private import Node0ToString
private class DebugNode0ToString extends Node0ToString {
final override predicate isDebugMode() { any() }
}

View File

@@ -0,0 +1,75 @@
/**
* This file contains the abstract class that serves as the base class for
* dataflow node printing.
*
* By default, a non-debug string is produced. However, a debug-friendly
* string can be produced by importing `DebugPrinting.qll`.
*/
private import semmle.code.cpp.ir.IR
private import codeql.util.Unit
/**
* A class to control whether a debugging version of instructions and operands
* should be printed as part of the `toString` output of dataflow nodes.
*
* To enable debug printing import the `DebugPrinting.ql` file. By default,
* non-debug output will be used.
*/
class Node0ToString extends Unit {
abstract predicate isDebugMode();
private string normalInstructionToString(Instruction i) {
not this.isDebugMode() and
if i.(InitializeParameterInstruction).getIRVariable() instanceof IRThisVariable
then result = "this"
else result = i.getAst().toString()
}
private string normalOperandToString(Operand op) {
not this.isDebugMode() and
if op.getDef().(InitializeParameterInstruction).getIRVariable() instanceof IRThisVariable
then result = "this"
else result = op.getDef().getAst().toString()
}
/**
* Gets the string that should be used by `InstructionNode.toString`
*/
string instructionToString(Instruction i) {
if this.isDebugMode()
then result = i.getDumpString()
else result = this.normalInstructionToString(i)
}
/**
* Gets the string that should be used by `OperandNode.toString`.
*/
string operandToString(Operand op) {
if this.isDebugMode()
then result = op.getDumpString() + " @ " + op.getUse().getResultId()
else result = this.normalOperandToString(op)
}
}
private class NoDebugNode0ToString extends Node0ToString {
final override predicate isDebugMode() { none() }
}
/**
* Gets the string that should be used by `OperandNode.toString`.
*/
string operandToString(Operand op) { result = any(Node0ToString nts).operandToString(op) }
/**
* Gets the string that should be used by `InstructionNode.toString`
*/
string instructionToString(Instruction i) { result = any(Node0ToString nts).instructionToString(i) }
/**
* Holds if debugging mode is enabled.
*
* In debug mode the `toString` on dataflow nodes is more expensive to compute,
* but gives more precise information about the different dataflow nodes.
*/
predicate isDebugMode() { not any(Node0ToString nts).isDebugMode() }