Add missing QLdoc comments to IR.qll classes, predicates, and newtype branches

Agent-Logs-Url: https://github.com/github/codeql/sessions/12c0f9c8-1b85-4db4-b26f-8dbce818aa5a

Co-authored-by: owen-mc <62447351+owen-mc@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-03-31 09:29:39 +00:00
committed by Owen Mansel-Chan
parent b6b01245c2
commit 190a76125e

View File

@@ -340,6 +340,7 @@ module IR {
/** Gets the field being read. */
Field getField() { result = fld }
/** Gets the instruction computing the base value on which the field is read. */
Instruction getBaseInstruction() {
exists(ImplicitFieldReadInstruction fri |
fri.getSelectorExpr() = sel and fri.getIndex() = pragma[only_bind_into](idx + 1)
@@ -374,8 +375,10 @@ module IR {
MethodReadInstruction() { e.getSelector() = method.getAReference() }
/** Gets the instruction computing the receiver value on which the method is looked up. */
Instruction getReceiver() { result = selectorBase(e) }
/** Gets the method being looked up. */
Method getMethod() { result = method }
override predicate readsMethod(Instruction receiver, Method m) {
@@ -389,6 +392,7 @@ module IR {
class ElementReadInstruction extends ComponentReadInstruction, EvalInstruction {
override IndexExpr e;
/** Gets the instruction computing the index of the element being looked up. */
Instruction getIndex() { result = evalExprInstruction(e.getIndex()) }
override predicate readsElement(Instruction base, Instruction index) {
@@ -402,18 +406,22 @@ module IR {
class SliceInstruction extends EvalInstruction {
override SliceExpr e;
/** Gets the instruction computing the base value from which the slice is constructed. */
Instruction getBase() { result = selectorBase(e) }
/** Gets the instruction computing the lower bound of the slice. */
Instruction getLow() {
result = evalExprInstruction(e.getLow()) or
result = implicitLowerSliceBoundInstruction(e)
}
/** Gets the instruction computing the upper bound of the slice. */
Instruction getHigh() {
result = evalExprInstruction(e.getHigh()) or
result = implicitUpperSliceBoundInstruction(e)
}
/** Gets the instruction computing the capacity of the slice. */
Instruction getMax() {
result = evalExprInstruction(e.getMax()) or
result = implicitMaxSliceBoundInstruction(e)
@@ -438,10 +446,13 @@ module IR {
lhs = MkLiteralElementTarget(this) and initialization = true
}
/** Gets the target to which this instruction writes. */
WriteTarget getLhs() { result = lhs }
/** Holds if this instruction initializes a literal. */
predicate isInitialization() { initialization = true }
/** Gets the instruction computing the value this instruction writes. */
Instruction getRhs() { none() }
override predicate writes(ValueEntity v, Instruction rhs) {
@@ -463,6 +474,7 @@ module IR {
elt = lit.getElement(litIdx)
}
/** Gets the instruction allocating the composite literal. */
Instruction getBase() { result = evalExprInstruction(lit) }
override Instruction getRhs() {
@@ -479,6 +491,7 @@ module IR {
class InitLiteralStructFieldInstruction extends InitLiteralComponentInstruction {
override StructLit lit;
/** Gets the name of the initialized field. */
pragma[nomagic]
string getFieldName() {
if elt instanceof KeyValueExpr
@@ -486,6 +499,7 @@ module IR {
else pragma[only_bind_out](lit.getStructType()).hasOwnField(litIdx, result, _, _)
}
/** Gets the initialized field. */
Field getField() {
result.getDeclaringType() = lit.getStructType() and
result.getName() = this.getFieldName()
@@ -507,6 +521,7 @@ module IR {
)
}
/** Gets the instruction computing the index of the initialized element. */
Instruction getIndex() {
result = evalExprInstruction(elt.(KeyValueExpr).getKey())
or
@@ -514,23 +529,29 @@ module IR {
}
}
/** An IR instruction that initializes an element of an array literal. */
class InitLiteralArrayElementInstruction extends InitLiteralElementInstruction {
override ArrayType literalType;
}
/** An IR instruction that initializes an element of a slice literal. */
class InitLiteralSliceElementInstruction extends InitLiteralElementInstruction {
override SliceType literalType;
}
/** An IR instruction that initializes an element of a map literal. */
class InitLiteralMapElementInstruction extends InitLiteralElementInstruction {
override MapType literalType;
}
/** An IR instruction that writes to a field. */
class FieldWriteInstruction extends WriteInstruction {
override FieldTarget lhs;
/** Gets the instruction computing the base value on which the field is written. */
Instruction getBase() { result = lhs.getBase() }
/** Gets the field being written. */
Field getField() { result = lhs.getField() }
override predicate writesField(Instruction base, Field f, Instruction rhs) {
@@ -538,11 +559,14 @@ module IR {
}
}
/** An IR instruction that writes to an element of an array, slice, or map. */
class ElementWriteInstruction extends WriteInstruction {
override ElementTarget lhs;
/** Gets the instruction computing the base value on which the element is written. */
Instruction getBase() { result = lhs.getBase() }
/** Gets the instruction computing the element index being written. */
Instruction getIndex() { result = lhs.getIndex() }
override predicate writesElement(Instruction base, Instruction index) {
@@ -638,11 +662,15 @@ module IR {
override ControlFlow::Root getRoot() { result.isRootOf(assgn) }
}
/**
* An instruction that computes the (implicit) right-hand side of a compound assignment.
*/
class EvalCompoundAssignRhsInstruction extends Instruction {
CompoundAssignStmt assgn;
EvalCompoundAssignRhsInstruction() { this.isAdditional(assgn, "compound-rhs") }
/** Gets the corresponding compound assignment statement. */
CompoundAssignStmt getAssignment() { result = assgn }
override Type getResultType() { result = assgn.getRhs().getType() }
@@ -650,6 +678,7 @@ module IR {
override ControlFlow::Root getRoot() { result.isRootOf(assgn) }
}
/** An instruction extracting a component of a tuple value. */
class ExtractTupleElementInstruction extends Instruction {
AstNode s;
int i;
@@ -677,6 +706,7 @@ module IR {
)
}
/** Gets the instruction computing the tuple value from which the element is extracted. */
Instruction getBase() {
exists(Expr baseExpr |
baseExpr = s.(Assignment).getRhs() or
@@ -692,6 +722,7 @@ module IR {
result = evalExprInstruction(s.(CallExpr).getArgument(0).stripParens())
}
/** Holds if this instruction extracts element `idx` from the tuple `base`. */
predicate extractsElement(Instruction base, int idx) { base = this.getBase() and idx = i }
override Type getResultType() {
@@ -733,6 +764,10 @@ module IR {
override ControlFlow::Root getRoot() { result.isRootOf(s) }
}
/**
* An instruction that computes the zero value to which a variable without an initializer
* expression is initialized.
*/
class EvalImplicitInitInstruction extends Instruction {
ValueEntity v;
int idx;
@@ -775,6 +810,7 @@ module IR {
override predicate isPlatformIndependentConstant() { any() }
}
/** An instruction that declares a function. */
class DeclareFunctionInstruction extends Instruction {
FuncDecl fd;
@@ -783,6 +819,7 @@ module IR {
override Type getResultType() { result = fd.getType() }
}
/** An instruction that corresponds to a `defer` statement. */
class DeferInstruction extends Instruction {
DeferStmt defer;
@@ -791,6 +828,7 @@ module IR {
override ControlFlow::Root getRoot() { result.isRootOf(defer) }
}
/** An instruction that corresponds to a `go` statement. */
class GoInstruction extends Instruction {
GoStmt go;
@@ -799,6 +837,7 @@ module IR {
override ControlFlow::Root getRoot() { result.isRootOf(go) }
}
/** An instruction that corresponds to an increment or decrement statement. */
class IncDecInstruction extends WriteInstruction {
IncDecStmt ids;
@@ -811,11 +850,16 @@ module IR {
override ControlFlow::Root getRoot() { result.isRootOf(ids) }
}
/**
* An instruction that computes the (implicit) right-hand side of an increment or
* decrement statement.
*/
class EvalIncDecRhsInstruction extends Instruction {
IncDecStmt ids;
EvalIncDecRhsInstruction() { this.isAdditional(ids, "incdec-rhs") }
/** Gets the corresponding increment or decrement statement. */
IncDecStmt getStmt() { result = ids }
override Type getResultType() { result = ids.getOperand().getType() }
@@ -823,11 +867,13 @@ module IR {
override ControlFlow::Root getRoot() { result.isRootOf(ids) }
}
/** An instruction computing the implicit operand `1` in an increment or decrement statement. */
class EvalImplicitOneInstruction extends Instruction {
IncDecStmt ids;
EvalImplicitOneInstruction() { this.isAdditional(ids, "implicit-one") }
/** Gets the corresponding increment or decrement statement. */
IncDecStmt getStmt() { result = ids }
override Type getResultType() { result = ids.getOperand().getType() }
@@ -843,24 +889,29 @@ module IR {
override predicate isPlatformIndependentConstant() { any() }
}
/** An instruction corresponding to a return from a function. */
class ReturnInstruction extends Instruction {
ReturnStmt ret;
ReturnInstruction() { this.isAdditional(ret, "return") }
/** Gets the corresponding `ReturnStmt`. */
ReturnStmt getReturnStmt() { result = ret }
/** Holds if this statement returns multiple results. */
predicate returnsMultipleResults() {
exists(ExtractTupleElementInstruction ext | ext.isAdditional(ret, _))
or
ret.getNumExpr() > 1
}
/** Gets the instruction whose result is the (unique) result returned by this statement. */
Instruction getResult() {
not this.returnsMultipleResults() and
result = evalExprInstruction(ret.getExpr())
}
/** Gets the instruction whose result is the `i`th result returned by this statement. */
Instruction getResult(int i) {
result.isAdditional(ret, _) and
result.(ExtractTupleElementInstruction).extractsElement(_, i)
@@ -872,6 +923,10 @@ module IR {
override ControlFlow::Root getRoot() { result.isRootOf(ret) }
}
/**
* An instruction that represents the implicit assignment to a result variable
* performed by a return statement.
*/
class WriteResultInstruction extends WriteInstruction {
ResultVariable var;
int idx;
@@ -889,6 +944,7 @@ module IR {
override Instruction getRhs() { result = this.getReturnInstruction().getResult(idx) }
/** Gets the result variable being assigned. */
ResultVariable getResultVariable() { result = var }
override Type getResultType() { result = var.getType() }
@@ -896,6 +952,10 @@ module IR {
override ControlFlow::Root getRoot() { var = result.(FuncDef).getAResultVar() }
}
/**
* An instruction that reads the final value of a result variable upon returning
* from a function.
*/
class ReadResultInstruction extends Instruction {
ResultVariable var;
int idx;
@@ -913,6 +973,7 @@ module IR {
override ControlFlow::Root getRoot() { var = result.(FuncDef).getAResultVar() }
}
/** An instruction corresponding to a send statement. */
class SendInstruction extends Instruction {
SendStmt send;
@@ -921,6 +982,7 @@ module IR {
override ControlFlow::Root getRoot() { result.isRootOf(send) }
}
/** An instruction initializing a parameter to the corresponding argument. */
class InitParameterInstruction extends WriteInstruction {
Parameter parm;
int idx;
@@ -938,6 +1000,7 @@ module IR {
override ControlFlow::Root getRoot() { result = parm.getFunction() }
}
/** An instruction reading the value of a function argument. */
class ReadArgumentInstruction extends Instruction {
Parameter parm;
int idx;
@@ -953,6 +1016,7 @@ module IR {
override ControlFlow::Root getRoot() { result = parm.getFunction() }
}
/** An instruction initializing a result variable to its zero value. */
class InitResultInstruction extends WriteInstruction {
ResultVariable res;
int idx;
@@ -1005,16 +1069,23 @@ module IR {
override predicate isPlatformIndependentConstant() { any() }
}
/** An instruction that gets the next key-value pair in a range loop. */
class GetNextEntryInstruction extends Instruction {
RangeStmt rs;
GetNextEntryInstruction() { this.isAdditional(rs, "next") }
/**
* Gets the instruction computing the value whose key-value pairs this instruction reads.
*/
Instruction getDomain() { result = evalExprInstruction(rs.getDomain()) }
override ControlFlow::Root getRoot() { result.isRootOf(rs) }
}
/**
* An instruction computing the implicit `true` value in an expression-less `switch` statement.
*/
class EvalImplicitTrueInstruction extends Instruction {
ExpressionSwitchStmt stmt;
@@ -1033,6 +1104,10 @@ module IR {
override predicate isPlatformIndependentConstant() { any() }
}
/**
* An instruction corresponding to the implicit comparison or type check performed by an
* expression in a `case` clause.
*/
class CaseInstruction extends Instruction {
CaseClause cc;
int i;
@@ -1045,6 +1120,10 @@ module IR {
override ControlFlow::Root getRoot() { result.isRootOf(cc) }
}
/**
* An instruction corresponding to the implicit declaration and assignment of a variable
* in a type switch case clause.
*/
class TypeSwitchImplicitVariableInstruction extends Instruction {
CaseClause cc;
@@ -1058,6 +1137,7 @@ module IR {
override ControlFlow::Root getRoot() { result.isRootOf(cc) }
}
/** An instruction computing the implicit lower bound of a slice expression. */
class EvalImplicitLowerSliceBoundInstruction extends Instruction {
SliceExpr slice;
@@ -1076,6 +1156,7 @@ module IR {
override predicate isPlatformIndependentConstant() { any() }
}
/** An instruction computing the implicit upper bound of a slice expression. */
class EvalImplicitUpperSliceBoundInstruction extends Instruction {
SliceExpr slice;
@@ -1086,6 +1167,7 @@ module IR {
override Type getResultType() { result instanceof IntType }
}
/** An instruction computing the implicit maximum bound of a slice expression. */
class EvalImplicitMaxSliceBoundInstruction extends Instruction {
SliceExpr slice;
@@ -1096,11 +1178,16 @@ module IR {
override Type getResultType() { result instanceof IntType }
}
/**
* An instruction computing the implicit dereference of a pointer used as the base of a field
* or method access, element access, or slice expression.
*/
class EvalImplicitDerefInstruction extends Instruction {
Expr e;
EvalImplicitDerefInstruction() { this.isAdditional(e, "implicit-deref") }
/** Gets the operand that is being dereferenced. */
Expr getOperand() { result = e }
override Type getResultType() {
@@ -1112,6 +1199,7 @@ module IR {
/** A representation of the target of a write instruction. */
newtype TWriteTarget =
/** A left-hand side of an assignment. */
MkLhs(ControlFlow::Node write, Expr lhs) {
exists(AstNode assgn, int i | write.isAdditional(assgn, "assign:" + i.toString()) |
lhs = assgn.(Assignment).getLhs(i).stripParens()
@@ -1137,9 +1225,12 @@ module IR {
lhs = fd.getResultVar(idx).getDeclaration()
)
} or
/** A composite literal element target. */
MkLiteralElementTarget(InitLiteralComponentInstruction elt) or
/** A result variable write target. */
MkResultWriteTarget(WriteResultInstruction w)
/** A representation of the target of a write instruction. */
class WriteTarget extends TWriteTarget {
ControlFlow::Node w;
@@ -1147,20 +1238,31 @@ module IR {
this = MkLhs(w, _) or this = MkLiteralElementTarget(w) or this = MkResultWriteTarget(w)
}
/** Gets the write instruction of which this is the target. */
WriteInstruction getWrite() { result = w }
/** Gets the name of the variable or field being written to, if any. */
string getName() { none() }
/** Gets the SSA variable being written to, if any. */
SsaVariable asSsaVariable() {
this.getWrite() = result.getDefinition().(SsaExplicitDefinition).getInstruction()
}
/** Holds if `e` is the variable or field being written to. */
predicate refersTo(ValueEntity e) { none() }
/** Gets a textual representation of this target. */
string toString() { result = "write target" }
/** Gets the source location for this element. */
Location getLocation() { none() }
/**
* DEPRECATED: Use `getLocation()` instead.
*
* Holds if this element is at the specified location.
*/
deprecated predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
@@ -1175,6 +1277,7 @@ module IR {
}
}
/** A reference to a variable or constant, used as the target of a write. */
class VarOrConstTarget extends WriteTarget {
Expr loc;
@@ -1215,11 +1318,14 @@ module IR {
)
}
/** Gets the variable this refers to, if any. */
Variable getVariable() { this.refersTo(result) }
/** Gets the constant this refers to, if any. */
Constant getConstant() { this.refersTo(result) }
}
/** A reference to a field, used as the target of a write. */
class FieldTarget extends WriteTarget {
FieldTarget() {
exists(SelectorExpr sel | this = MkLhs(_, sel) | sel.getBase() instanceof ValueExpr)
@@ -1227,12 +1333,14 @@ module IR {
w instanceof InitLiteralStructFieldInstruction
}
/** Gets the instruction computing the base value on which this field is accessed. */
Instruction getBase() {
exists(SelectorExpr sel | this = MkLhs(_, sel) | result = selectorBase(sel))
or
result = w.(InitLiteralStructFieldInstruction).getBase()
}
/** Gets the type of the base of this field access, that is, the type that contains the field. */
Type getBaseType() { result = this.getBase().getResultType() }
override predicate refersTo(ValueEntity e) {
@@ -1243,9 +1351,13 @@ module IR {
override string getName() { exists(Field f | this.refersTo(f) | result = f.getName()) }
/** Gets the field this refers to, if it can be determined. */
Field getField() { this.refersTo(result) }
}
/**
* A reference to an element of an array, slice, or map, used as the target of a write.
*/
class ElementTarget extends WriteTarget {
ElementTarget() {
this = MkLhs(_, any(IndexExpr idx))
@@ -1253,12 +1365,14 @@ module IR {
w instanceof InitLiteralElementInstruction
}
/** Gets the instruction computing the base value of this element reference. */
Instruction getBase() {
exists(IndexExpr idx | this = MkLhs(_, idx) | result = selectorBase(idx))
or
result = w.(InitLiteralComponentInstruction).getBase()
}
/** Gets the instruction computing the index of this element reference. */
Instruction getIndex() {
exists(IndexExpr idx | this = MkLhs(_, idx) | result = evalExprInstruction(idx.getIndex()))
or
@@ -1266,6 +1380,9 @@ module IR {
}
}
/**
* A pointer dereference, used as the target of a write.
*/
class PointerTarget extends WriteTarget {
Expr lhs;
@@ -1274,6 +1391,7 @@ module IR {
(lhs instanceof StarExpr or lhs instanceof DerefExpr)
}
/** Gets the instruction computing the pointer value being dereferenced. */
Instruction getBase() {
exists(Expr base | base = lhs.(StarExpr).getBase() or base = lhs.(DerefExpr).getOperand() |
result = evalExprInstruction(base)
@@ -1290,32 +1408,58 @@ module IR {
result = evalExprInstruction(e.(ParenExpr).getExpr())
}
/**
* Gets the instruction corresponding to the initialization of `r`.
*/
InitParameterInstruction initRecvInstruction(ReceiverVariable r) {
exists(FuncDef fd, int i |
fd.getParameter(i) = r and result.isAdditional(fd, "param-init:" + i.toString())
)
}
/**
* Gets the instruction corresponding to the initialization of `p`.
*/
InitParameterInstruction initParamInstruction(Parameter p) {
exists(FuncDef fd, int i |
fd.getParameter(i) = p and result.isAdditional(fd, "param-init:" + i.toString())
)
}
/**
* Gets the instruction corresponding to the `i`th assignment happening at
* `assgn` (0-based).
*/
AssignInstruction assignInstruction(Assignment assgn, int i) {
result.isAdditional(assgn, "assign:" + i.toString()) and
exists(assgn.getLhs(i))
}
/**
* Gets the instruction corresponding to the `i`th initialization happening
* at `spec` (0-based).
*/
AssignInstruction initInstruction(ValueSpec spec, int i) {
result.isAdditional(spec, "assign:" + i.toString()) and
exists(spec.getNameExpr(i))
}
/**
* Gets the instruction corresponding to the assignment of the key variable
* of range statement `rs`.
*/
AssignInstruction assignKeyInstruction(RangeStmt rs) { result.isAdditional(rs, "assign:0") }
/**
* Gets the instruction corresponding to the assignment of the value variable
* of range statement `rs`.
*/
AssignInstruction assignValueInstruction(RangeStmt rs) { result.isAdditional(rs, "assign:1") }
/**
* Gets the instruction corresponding to the implicit initialization of `v`
* to its zero value.
*/
EvalImplicitInitInstruction implicitInitInstruction(ValueEntity v) {
exists(ValueSpec spec, int i |
spec.getNameExpr(i) = v.getDeclaration() and
@@ -1323,26 +1467,44 @@ module IR {
)
}
/**
* Gets the instruction corresponding to the extraction of the `idx`th element
* of the tuple produced by `base`.
*/
ExtractTupleElementInstruction extractTupleElement(Instruction base, int idx) {
result.extractsElement(base, idx)
}
/**
* Gets the instruction corresponding to the implicit lower bound of slice `e`, if any.
*/
EvalImplicitLowerSliceBoundInstruction implicitLowerSliceBoundInstruction(SliceExpr e) {
result.isAdditional(e, "implicit-low")
}
/**
* Gets the instruction corresponding to the implicit upper bound of slice `e`, if any.
*/
EvalImplicitUpperSliceBoundInstruction implicitUpperSliceBoundInstruction(SliceExpr e) {
result.isAdditional(e, "implicit-high")
}
/**
* Gets the instruction corresponding to the implicit maximum bound of slice `e`, if any.
*/
EvalImplicitMaxSliceBoundInstruction implicitMaxSliceBoundInstruction(SliceExpr e) {
result.isAdditional(e, "implicit-max")
}
/**
* Gets the implicit dereference instruction for `e`, where `e` is a pointer used as the base
* in a field/method access, element access, or slice expression.
*/
EvalImplicitDerefInstruction implicitDerefInstruction(Expr e) {
result.isAdditional(e, "implicit-deref")
}
/** Gets the base of `insn`, if `insn` is an implicit field read. */
Instruction lookThroughImplicitFieldRead(Instruction insn) {
result = insn.(ImplicitFieldReadInstruction).getBaseInstruction()
}