Merge pull request #3393 from dbartol/codeql-c-analysis-team/40/1

C++: A few IR QLDoc comments
This commit is contained in:
Jonas Jensen
2020-05-11 15:56:43 +02:00
committed by GitHub
16 changed files with 189 additions and 41 deletions

View File

@@ -17,6 +17,7 @@ private newtype TEdgeKind =
* `EdgeKind`.
*/
abstract class EdgeKind extends TEdgeKind {
/** Gets a textual representation of this edge kind. */
abstract string toString();
}
@@ -28,8 +29,6 @@ class GotoEdge extends EdgeKind, TGotoEdge {
final override string toString() { result = "Goto" }
}
GotoEdge gotoEdge() { result = TGotoEdge() }
/**
* A "true" edge, representing the successor of a conditional branch when the
* condition is non-zero.
@@ -38,8 +37,6 @@ class TrueEdge extends EdgeKind, TTrueEdge {
final override string toString() { result = "True" }
}
TrueEdge trueEdge() { result = TTrueEdge() }
/**
* A "false" edge, representing the successor of a conditional branch when the
* condition is zero.
@@ -48,8 +45,6 @@ class FalseEdge extends EdgeKind, TFalseEdge {
final override string toString() { result = "False" }
}
FalseEdge falseEdge() { result = TFalseEdge() }
/**
* An "exception" edge, representing the successor of an instruction when that
* instruction's evaluation throws an exception.
@@ -58,8 +53,6 @@ class ExceptionEdge extends EdgeKind, TExceptionEdge {
final override string toString() { result = "Exception" }
}
ExceptionEdge exceptionEdge() { result = TExceptionEdge() }
/**
* A "default" edge, representing the successor of a `Switch` instruction when
* none of the case values matches the condition value.
@@ -68,8 +61,6 @@ class DefaultEdge extends EdgeKind, TDefaultEdge {
final override string toString() { result = "Default" }
}
DefaultEdge defaultEdge() { result = TDefaultEdge() }
/**
* A "case" edge, representing the successor of a `Switch` instruction when the
* the condition value matches a correponding `case` label.
@@ -91,4 +82,48 @@ class CaseEdge extends EdgeKind, TCaseEdge {
string getMaxValue() { result = maxValue }
}
CaseEdge caseEdge(string minValue, string maxValue) { result = TCaseEdge(minValue, maxValue) }
/**
* Predicates to access the single instance of each `EdgeKind` class.
*/
module EdgeKind {
/**
* Gets the single instance of the `GotoEdge` class.
*/
GotoEdge gotoEdge() { result = TGotoEdge() }
/**
* Gets the single instance of the `TrueEdge` class.
*/
TrueEdge trueEdge() { result = TTrueEdge() }
/**
* Gets the single instance of the `FalseEdge` class.
*/
FalseEdge falseEdge() { result = TFalseEdge() }
/**
* Gets the single instance of the `ExceptionEdge` class.
*/
ExceptionEdge exceptionEdge() { result = TExceptionEdge() }
/**
* Gets the single instance of the `DefaultEdge` class.
*/
DefaultEdge defaultEdge() { result = TDefaultEdge() }
/**
* Gets the `CaseEdge` representing a `case` label with the specified lower and upper bounds.
* For example:
* ```
* switch (x) {
* case 1: // Edge kind is `caseEdge("1", "1")`
* return x;
* case 2...8: // Edge kind is `caseEdge("2", "8")`
* return x - 1;
* default: // Edge kind is `defaultEdge()`
* return 0;
* }
* ```
*/
CaseEdge caseEdge(string minValue, string maxValue) { result = TCaseEdge(minValue, maxValue) }
}

View File

@@ -1,6 +1,16 @@
/**
* Defines the public interface to temporary variable tags, which describe the reason a particular
* `IRTempVariable` was generated.
*/
private import internal.TempVariableTagInternal
private import Imports::TempVariableTag
/**
* A reason that a particular IR temporary variable was generated. For example, it could be
* generated to hold the return value of a function, or to hold the result of a `?:` operator
* computed on each branch. The set of possible `TempVariableTag`s is language-dependent.
*/
class TempVariableTag extends TTempVariableTag {
string toString() { result = getTempVariableTagId(this) }
}

View File

@@ -585,9 +585,9 @@ class ConditionalBranchInstruction extends Instruction {
final Instruction getCondition() { result = getConditionOperand().getDef() }
final Instruction getTrueSuccessor() { result = getSuccessor(trueEdge()) }
final Instruction getTrueSuccessor() { result = getSuccessor(EdgeKind::trueEdge()) }
final Instruction getFalseSuccessor() { result = getSuccessor(falseEdge()) }
final Instruction getFalseSuccessor() { result = getSuccessor(EdgeKind::falseEdge()) }
}
class ExitFunctionInstruction extends Instruction {
@@ -907,7 +907,7 @@ class SwitchInstruction extends Instruction {
final Instruction getACaseSuccessor() { exists(CaseEdge edge | result = getSuccessor(edge)) }
final Instruction getDefaultSuccessor() { result = getSuccessor(defaultEdge()) }
final Instruction getDefaultSuccessor() { result = getSuccessor(EdgeKind::defaultEdge()) }
}
/**

View File

@@ -1,3 +1,8 @@
/**
* Defines the set of possible `OperandTag`s, which are used to identify the role each `Operand`
* plays in the evaluation of its `Instruction`.
*/
private import OperandTagInternal
private newtype TOperandTag =
@@ -24,10 +29,18 @@ private newtype TOperandTag =
* an `Instruction` is determined by the instruction's opcode.
*/
abstract class OperandTag extends TOperandTag {
/** Gets a textual representation of this operand tag */
abstract string toString();
/**
* Gets an integer that represents where this this operand will appear in the operand list of an
* instruction when the IR is printed.
*/
abstract int getSortOrder();
/**
* Gets a label that will appear before the operand when the IR is printed.
*/
string getLabel() { result = "" }
}
@@ -47,7 +60,7 @@ abstract class RegisterOperandTag extends OperandTag { }
abstract class TypedOperandTag extends MemoryOperandTag { }
// Note: individual subtypes are listed in the order that the operands should
// appear in the operand list of the instruction when printing.
// appear in the operand list of the instruction when the IR is printed.
/**
* The address operand of an instruction that loads or stores a value from
* memory (e.g. `Load`, `Store`, `InitializeParameter`, `IndirectReadSideEffect`).

View File

@@ -585,9 +585,9 @@ class ConditionalBranchInstruction extends Instruction {
final Instruction getCondition() { result = getConditionOperand().getDef() }
final Instruction getTrueSuccessor() { result = getSuccessor(trueEdge()) }
final Instruction getTrueSuccessor() { result = getSuccessor(EdgeKind::trueEdge()) }
final Instruction getFalseSuccessor() { result = getSuccessor(falseEdge()) }
final Instruction getFalseSuccessor() { result = getSuccessor(EdgeKind::falseEdge()) }
}
class ExitFunctionInstruction extends Instruction {
@@ -907,7 +907,7 @@ class SwitchInstruction extends Instruction {
final Instruction getACaseSuccessor() { exists(CaseEdge edge | result = getSuccessor(edge)) }
final Instruction getDefaultSuccessor() { result = getSuccessor(defaultEdge()) }
final Instruction getDefaultSuccessor() { result = getSuccessor(EdgeKind::defaultEdge()) }
}
/**

View File

@@ -375,7 +375,7 @@ class TranslatedAllocationSideEffects extends TranslatedSideEffects,
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
kind = gotoEdge() and
kind = EdgeKind::gotoEdge() and
if exists(getChild(0))
then result = getChild(0).getFirstInstruction()
else result = getParent().getChildSuccessor(this)

View File

@@ -720,7 +720,7 @@ class TranslatedReadEffect extends TranslatedElement, TTranslatedReadEffect {
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind edge) {
tag = OnlyInstructionTag() and
edge = gotoEdge() and
edge = EdgeKind::gotoEdge() and
result = getParent().getChildSuccessor(this)
}

View File

@@ -585,9 +585,9 @@ class ConditionalBranchInstruction extends Instruction {
final Instruction getCondition() { result = getConditionOperand().getDef() }
final Instruction getTrueSuccessor() { result = getSuccessor(trueEdge()) }
final Instruction getTrueSuccessor() { result = getSuccessor(EdgeKind::trueEdge()) }
final Instruction getFalseSuccessor() { result = getSuccessor(falseEdge()) }
final Instruction getFalseSuccessor() { result = getSuccessor(EdgeKind::falseEdge()) }
}
class ExitFunctionInstruction extends Instruction {
@@ -907,7 +907,7 @@ class SwitchInstruction extends Instruction {
final Instruction getACaseSuccessor() { exists(CaseEdge edge | result = getSuccessor(edge)) }
final Instruction getDefaultSuccessor() { result = getSuccessor(defaultEdge()) }
final Instruction getDefaultSuccessor() { result = getSuccessor(EdgeKind::defaultEdge()) }
}
/**

View File

@@ -203,6 +203,7 @@ private newtype TCppType =
* of a `VariableAddress` where the variable is of reference type)
*/
class CppType extends TCppType {
/** Gets a textual representation of this type. */
string toString() { none() }
/** Gets a string used in IR dumps */
@@ -224,6 +225,10 @@ class CppType extends TCppType {
*/
predicate hasType(Type type, boolean isGLValue) { none() }
/**
* Holds if this type represents the C++ type `type`. If `isGLValue` is `true`, then this type
* represents a glvalue of type `type`. Otherwise, it represents a prvalue of type `type`.
*/
final predicate hasUnspecifiedType(Type type, boolean isGLValue) {
exists(Type specifiedType |
hasType(specifiedType, isGLValue) and
@@ -540,6 +545,9 @@ string getOpaqueTagIdentityString(Type tag) {
}
module LanguageTypeSanity {
/**
* Sanity query to detect C++ `Type` objects which have no corresponding `CppType` object.
*/
query predicate missingCppType(Type type, string message) {
not exists(getTypeForPRValue(type)) and
exists(type.getSize()) and

View File

@@ -1,3 +1,15 @@
/**
* Provides predicates for manipulating integer constants that are tracked by constant folding and
* similar analyses.
*/
/**
* An alias used to represent the constant value of an integer, if one can be determined. If no
* single constant value can be determined, or if the constant value is out of the representable
* range, it will be represented as the special value `unknown()`. This allows `IntValue` to be used
* in contexts where there must always be a value for the `IntValue`, even if no constant value is
* known.
*/
class IntValue = int;
/**