mirror of
https://github.com/github/codeql.git
synced 2026-04-29 02:35:15 +02:00
Merge pull request #3795 from rdmarsh2/rdmarsh/cpp/add-qldoc-3
C++: QLDoc for PrintAST and AST-based range analysis
This commit is contained in:
@@ -1,3 +1,11 @@
|
||||
/**
|
||||
* Provides queries to pretty-print a C++ AST as a graph.
|
||||
*
|
||||
* By default, this will print the AST for all functions in the database. To change this behavior,
|
||||
* extend `PrintASTConfiguration` and override `shouldPrintFunction` to hold for only the functions
|
||||
* you wish to view the AST for.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
private import semmle.code.cpp.Print
|
||||
|
||||
@@ -7,6 +15,9 @@ private newtype TPrintASTConfiguration = MkPrintASTConfiguration()
|
||||
* The query can extend this class to control which functions are printed.
|
||||
*/
|
||||
class PrintASTConfiguration extends TPrintASTConfiguration {
|
||||
/**
|
||||
* Gets a textual representation of this `PrintASTConfiguration`.
|
||||
*/
|
||||
string toString() { result = "PrintASTConfiguration" }
|
||||
|
||||
/**
|
||||
@@ -96,6 +107,9 @@ private newtype TPrintASTNode =
|
||||
* A node in the output tree.
|
||||
*/
|
||||
class PrintASTNode extends TPrintASTNode {
|
||||
/**
|
||||
* Gets a textual representation of this node in the PrintAST output tree.
|
||||
*/
|
||||
abstract string toString();
|
||||
|
||||
/**
|
||||
@@ -208,6 +222,9 @@ class ExprNode extends ASTNode {
|
||||
result = expr.getValueCategoryString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of this expression, if it is a constant.
|
||||
*/
|
||||
string getValue() { result = expr.getValue() }
|
||||
}
|
||||
|
||||
@@ -373,6 +390,9 @@ class ParametersNode extends PrintASTNode, TParametersNode {
|
||||
|
||||
override ASTNode getChild(int childIndex) { result.getAST() = func.getParameter(childIndex) }
|
||||
|
||||
/**
|
||||
* Gets the `Function` for which this node represents the parameters.
|
||||
*/
|
||||
final Function getFunction() { result = func }
|
||||
}
|
||||
|
||||
@@ -392,6 +412,9 @@ class ConstructorInitializersNode extends PrintASTNode, TConstructorInitializers
|
||||
result.getAST() = ctor.getInitializer(childIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `Constructor` for which this node represents the initializer list.
|
||||
*/
|
||||
final Constructor getConstructor() { result = ctor }
|
||||
}
|
||||
|
||||
@@ -411,6 +434,9 @@ class DestructorDestructionsNode extends PrintASTNode, TDestructorDestructionsNo
|
||||
result.getAST() = dtor.getDestruction(childIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `Destructor` for which this node represents the destruction list.
|
||||
*/
|
||||
final Destructor getDestructor() { result = dtor }
|
||||
}
|
||||
|
||||
@@ -464,6 +490,9 @@ class FunctionNode extends ASTNode {
|
||||
key = "semmle.order" and result = getOrder().toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `Function` this node represents.
|
||||
*/
|
||||
final Function getFunction() { result = func }
|
||||
}
|
||||
|
||||
@@ -499,11 +528,16 @@ class ArrayAggregateLiteralNode extends ExprNode {
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if `node` belongs to the output tree, and its property `key` has the given `value`. */
|
||||
query predicate nodes(PrintASTNode node, string key, string value) {
|
||||
node.shouldPrint() and
|
||||
value = node.getProperty(key)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `target` is a child of `source` in the AST, and property `key` of the edge has the
|
||||
* given `value`.
|
||||
*/
|
||||
query predicate edges(PrintASTNode source, PrintASTNode target, string key, string value) {
|
||||
exists(int childIndex |
|
||||
source.shouldPrint() and
|
||||
@@ -517,6 +551,7 @@ query predicate edges(PrintASTNode source, PrintASTNode target, string key, stri
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if property `key` of the graph has the given `value`. */
|
||||
query predicate graphProperties(string key, string value) {
|
||||
key = "semmle.graphKind" and value = "tree"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes and predicates for recognizing floating point expressions which cannot be NaN.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
private import semmle.code.cpp.rangeanalysis.RangeSSA
|
||||
|
||||
|
||||
@@ -11,8 +11,17 @@ private float lowerBoundFC(Expr expr) { result = lowerBound(expr.getFullyConvert
|
||||
/** Gets the upper bound of the fully converted expression. */
|
||||
private float upperBoundFC(Expr expr) { result = upperBound(expr.getFullyConverted()) }
|
||||
|
||||
/**
|
||||
* Describes which side of a pointless comparison is known to be smaller.
|
||||
*/
|
||||
newtype SmallSide =
|
||||
/**
|
||||
* Represents that the left side of a pointless comparison is known to be smaller.
|
||||
*/
|
||||
LeftIsSmaller() or
|
||||
/**
|
||||
* Represents that the right side of a pointless comparison is known to be smaller.
|
||||
*/
|
||||
RightIsSmaller()
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,13 @@ import cpp
|
||||
* relation) or 'non-strict' (a `<=` or `>=` relation).
|
||||
*/
|
||||
newtype RelationStrictness =
|
||||
/**
|
||||
* Represents that a relation is 'strict' (that is, a `<` or `>` relation).
|
||||
*/
|
||||
Strict() or
|
||||
/**
|
||||
* Represents that a relation is 'non-strict' (that is, a `<=` or `>=` relation)
|
||||
*/
|
||||
Nonstrict()
|
||||
|
||||
/**
|
||||
@@ -13,7 +19,13 @@ newtype RelationStrictness =
|
||||
* relation) or 'lesser' (a `<` or `<=` relation).
|
||||
*/
|
||||
newtype RelationDirection =
|
||||
/**
|
||||
* Represents that a relation is 'greater' (that is, a `>` or `>=` relation).
|
||||
*/
|
||||
Greater() or
|
||||
/**
|
||||
* Represents that a relation is 'lesser' (that is, a `<` or `<=` relation).
|
||||
*/
|
||||
Lesser()
|
||||
|
||||
private RelationStrictness negateStrictness(RelationStrictness strict) {
|
||||
@@ -28,12 +40,18 @@ private RelationDirection negateDirection(RelationDirection dir) {
|
||||
dir = Lesser() and result = Greater()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `dir` is `Greater` (that is, a `>` or `>=` relation)
|
||||
*/
|
||||
boolean directionIsGreater(RelationDirection dir) {
|
||||
dir = Greater() and result = true
|
||||
or
|
||||
dir = Lesser() and result = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `dir` is `Lesser` (that is, a `<` or `<=` relation)
|
||||
*/
|
||||
boolean directionIsLesser(RelationDirection dir) {
|
||||
dir = Greater() and result = false
|
||||
or
|
||||
|
||||
@@ -25,6 +25,10 @@ import semmle.code.cpp.controlflow.Dominance
|
||||
import semmle.code.cpp.controlflow.SSAUtils
|
||||
private import RangeAnalysisUtils
|
||||
|
||||
/**
|
||||
* The SSA logic comes in two versions: the standard SSA and range-analysis RangeSSA.
|
||||
* This class provides the range-analysis SSA logic.
|
||||
*/
|
||||
library class RangeSSA extends SSAHelper {
|
||||
RangeSSA() { this = 1 }
|
||||
|
||||
@@ -84,6 +88,7 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
|
||||
/** Gets the control flow node for this definition. */
|
||||
ControlFlowNode getDefinition() { result = this }
|
||||
|
||||
/** Gets the basic block containing this definition. */
|
||||
BasicBlock getBasicBlock() { result.contains(getDefinition()) }
|
||||
|
||||
/** Whether this definition is a phi node for variable `v`. */
|
||||
@@ -97,11 +102,13 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
|
||||
guard_defn(v, guard, this, branch)
|
||||
}
|
||||
|
||||
/** Gets the primary location of this definition. */
|
||||
Location getLocation() { result = this.(ControlFlowNode).getLocation() }
|
||||
|
||||
/** Whether this definition is from a parameter */
|
||||
predicate definedByParameter(Parameter p) { this = p.getFunction().getEntryPoint() }
|
||||
|
||||
/** Gets a definition of `v` that is a phi input for this basic block. */
|
||||
RangeSsaDefinition getAPhiInput(StackVariable v) {
|
||||
this.isPhiNode(v) and
|
||||
exists(BasicBlock pred |
|
||||
@@ -153,6 +160,9 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this definition of the variable `v` reached the end of the basic block `b`.
|
||||
*/
|
||||
predicate reachesEndOfBB(StackVariable v, BasicBlock b) {
|
||||
exists(RangeSSA x | x.ssaDefinitionReachesEndOfBB(v, this, b))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user