mirror of
https://github.com/github/codeql.git
synced 2026-04-29 02:35:15 +02:00
Merge branch 'master' into copymove
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
* or data representation problems.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
* @precision high
|
||||
* @id cpp/tainted-format-string
|
||||
* @tags reliability
|
||||
* security
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* or data representation problems.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
* @precision high
|
||||
* @id cpp/tainted-format-string-through-global
|
||||
* @tags reliability
|
||||
* security
|
||||
|
||||
@@ -20,7 +20,7 @@ import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.ValueNumbering
|
||||
private import semmle.code.cpp.ir.internal.CppType
|
||||
private import semmle.code.cpp.models.interfaces.Allocation
|
||||
private import semmle.code.cpp.rangeanalysis.RangeUtils
|
||||
private import experimental.semmle.code.cpp.rangeanalysis.RangeUtils
|
||||
|
||||
private newtype TLength =
|
||||
TZeroLength() or
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
import cpp
|
||||
private import experimental.semmle.code.cpp.rangeanalysis.ArrayLengthAnalysis
|
||||
private import semmle.code.cpp.rangeanalysis.RangeAnalysis
|
||||
private import experimental.semmle.code.cpp.rangeanalysis.RangeAnalysis
|
||||
|
||||
/**
|
||||
* Gets the instruction that computes the address of memory that `i` accesses.
|
||||
|
||||
@@ -33,7 +33,7 @@ private import semmle.code.cpp.internal.ResolveClass
|
||||
class Class extends UserType {
|
||||
Class() { isClass(underlyingElement(this)) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "Class" }
|
||||
override string getAPrimaryQlClass() { result = "Class" }
|
||||
|
||||
/** Gets a child declaration of this class, struct or union. */
|
||||
override Declaration getADeclaration() { result = this.getAMember() }
|
||||
@@ -768,7 +768,7 @@ class ClassDerivation extends Locatable, @derivation {
|
||||
*/
|
||||
Class getBaseClass() { result = getBaseType().getUnderlyingType() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ClassDerivation" }
|
||||
override string getAPrimaryQlClass() { result = "ClassDerivation" }
|
||||
|
||||
/**
|
||||
* Gets the type from which we are deriving, without resolving any
|
||||
@@ -849,9 +849,7 @@ class ClassDerivation extends Locatable, @derivation {
|
||||
class LocalClass extends Class {
|
||||
LocalClass() { isLocal() }
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
not this instanceof LocalStruct and result = "LocalClass"
|
||||
}
|
||||
override string getAPrimaryQlClass() { not this instanceof LocalStruct and result = "LocalClass" }
|
||||
|
||||
override Function getEnclosingAccessHolder() { result = this.getEnclosingFunction() }
|
||||
}
|
||||
@@ -872,7 +870,7 @@ class LocalClass extends Class {
|
||||
class NestedClass extends Class {
|
||||
NestedClass() { this.isMember() }
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not this instanceof NestedStruct and result = "NestedClass"
|
||||
}
|
||||
|
||||
@@ -893,7 +891,7 @@ class NestedClass extends Class {
|
||||
class AbstractClass extends Class {
|
||||
AbstractClass() { exists(PureVirtualFunction f | this.getAMemberFunction() = f) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "AbstractClass" }
|
||||
override string getAPrimaryQlClass() { result = "AbstractClass" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -934,7 +932,7 @@ class TemplateClass extends Class {
|
||||
exists(result.getATemplateArgument())
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "TemplateClass" }
|
||||
override string getAPrimaryQlClass() { result = "TemplateClass" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -955,7 +953,7 @@ class ClassTemplateInstantiation extends Class {
|
||||
|
||||
ClassTemplateInstantiation() { tc.getAnInstantiation() = this }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ClassTemplateInstantiation" }
|
||||
override string getAPrimaryQlClass() { result = "ClassTemplateInstantiation" }
|
||||
|
||||
/**
|
||||
* Gets the class template from which this instantiation was instantiated.
|
||||
@@ -996,7 +994,7 @@ abstract class ClassTemplateSpecialization extends Class {
|
||||
count(int i | exists(result.getTemplateArgument(i)))
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "ClassTemplateSpecialization" }
|
||||
override string getAPrimaryQlClass() { result = "ClassTemplateSpecialization" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1025,7 +1023,7 @@ class FullClassTemplateSpecialization extends ClassTemplateSpecialization {
|
||||
not this instanceof ClassTemplateInstantiation
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "FullClassTemplateSpecialization" }
|
||||
override string getAPrimaryQlClass() { result = "FullClassTemplateSpecialization" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1064,7 +1062,7 @@ class PartialClassTemplateSpecialization extends ClassTemplateSpecialization {
|
||||
count(int i | exists(getTemplateArgument(i)))
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "PartialClassTemplateSpecialization" }
|
||||
override string getAPrimaryQlClass() { result = "PartialClassTemplateSpecialization" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1089,7 +1087,7 @@ deprecated class Interface extends Class {
|
||||
)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Interface" }
|
||||
override string getAPrimaryQlClass() { result = "Interface" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1104,7 +1102,7 @@ deprecated class Interface extends Class {
|
||||
class VirtualClassDerivation extends ClassDerivation {
|
||||
VirtualClassDerivation() { hasSpecifier("virtual") }
|
||||
|
||||
override string getCanonicalQLClass() { result = "VirtualClassDerivation" }
|
||||
override string getAPrimaryQlClass() { result = "VirtualClassDerivation" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1124,7 +1122,7 @@ class VirtualClassDerivation extends ClassDerivation {
|
||||
class VirtualBaseClass extends Class {
|
||||
VirtualBaseClass() { exists(VirtualClassDerivation cd | cd.getBaseClass() = this) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "VirtualBaseClass" }
|
||||
override string getAPrimaryQlClass() { result = "VirtualBaseClass" }
|
||||
|
||||
/** A virtual class derivation of which this class/struct is the base. */
|
||||
VirtualClassDerivation getAVirtualDerivation() { result.getBaseClass() = this }
|
||||
@@ -1146,7 +1144,7 @@ class VirtualBaseClass extends Class {
|
||||
class ProxyClass extends UserType {
|
||||
ProxyClass() { usertypes(underlyingElement(this), _, 9) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ProxyClass" }
|
||||
override string getAPrimaryQlClass() { result = "ProxyClass" }
|
||||
|
||||
/** Gets the location of the proxy class. */
|
||||
override Location getLocation() { result = getTemplateParameter().getDefinitionLocation() }
|
||||
|
||||
@@ -55,12 +55,21 @@ class ElementBase extends @element {
|
||||
cached
|
||||
string toString() { none() }
|
||||
|
||||
/** DEPRECATED: use `getAPrimaryQlClass` instead. */
|
||||
deprecated string getCanonicalQLClass() { result = this.getAPrimaryQlClass() }
|
||||
|
||||
/**
|
||||
* Canonical QL class corresponding to this element.
|
||||
* Gets the name of a primary CodeQL class to which this element belongs.
|
||||
*
|
||||
* ElementBase is the root class for this predicate.
|
||||
* For most elements, this is simply the most precise syntactic category to
|
||||
* which they belong; for example, `AddExpr` is a primary class, but
|
||||
* `BinaryOperation` is not.
|
||||
*
|
||||
* This predicate always has a result. If no primary class can be
|
||||
* determined, the result is `"???"`. If multiple primary classes match,
|
||||
* this predicate can have multiple results.
|
||||
*/
|
||||
string getCanonicalQLClass() { result = "???" }
|
||||
string getAPrimaryQlClass() { result = "???" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,7 +38,7 @@ class Enum extends UserType, IntegralOrEnumType {
|
||||
enumconstants(unresolveElement(result), underlyingElement(this), index, _, _, _)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Enum" }
|
||||
override string getAPrimaryQlClass() { result = "Enum" }
|
||||
|
||||
/**
|
||||
* Gets a descriptive string for the enum. This method is only intended to
|
||||
@@ -87,7 +87,7 @@ class Enum extends UserType, IntegralOrEnumType {
|
||||
class LocalEnum extends Enum {
|
||||
LocalEnum() { isLocal() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "LocalEnum" }
|
||||
override string getAPrimaryQlClass() { result = "LocalEnum" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,7 +105,7 @@ class LocalEnum extends Enum {
|
||||
class NestedEnum extends Enum {
|
||||
NestedEnum() { this.isMember() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "NestedEnum" }
|
||||
override string getAPrimaryQlClass() { result = "NestedEnum" }
|
||||
|
||||
/** Holds if this member is private. */
|
||||
predicate isPrivate() { this.hasSpecifier("private") }
|
||||
@@ -130,7 +130,7 @@ class NestedEnum extends Enum {
|
||||
class ScopedEnum extends Enum {
|
||||
ScopedEnum() { usertypes(underlyingElement(this), _, 13) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ScopedEnum" }
|
||||
override string getAPrimaryQlClass() { result = "ScopedEnum" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,7 +153,7 @@ class EnumConstant extends Declaration, @enumconstant {
|
||||
enumconstants(underlyingElement(this), unresolveElement(result), _, _, _, _)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "EnumConstant" }
|
||||
override string getAPrimaryQlClass() { result = "EnumConstant" }
|
||||
|
||||
override Class getDeclaringType() { result = this.getDeclaringEnum().getDeclaringType() }
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import semmle.code.cpp.exprs.Access
|
||||
class Field extends MemberVariable {
|
||||
Field() { fieldoffsets(underlyingElement(this), _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "Field" }
|
||||
override string getAPrimaryQlClass() { result = "Field" }
|
||||
|
||||
/**
|
||||
* Gets the offset of this field in bytes from the start of its declaring
|
||||
@@ -90,7 +90,7 @@ class Field extends MemberVariable {
|
||||
class BitField extends Field {
|
||||
BitField() { bitfield(underlyingElement(this), _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BitField" }
|
||||
override string getAPrimaryQlClass() { result = "BitField" }
|
||||
|
||||
/**
|
||||
* Gets the size of this bitfield in bits (on the machine where facts
|
||||
|
||||
@@ -178,7 +178,7 @@ class Folder extends Container, @folder {
|
||||
result.hasLocationInfo(_, 0, 0, 0, 0)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Folder" }
|
||||
override string getAPrimaryQlClass() { result = "Folder" }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getLocation` instead.
|
||||
@@ -246,7 +246,7 @@ class File extends Container, @file {
|
||||
|
||||
override string toString() { result = Container.super.toString() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "File" }
|
||||
override string getAPrimaryQlClass() { result = "File" }
|
||||
|
||||
override Location getLocation() {
|
||||
result.getContainer() = this and
|
||||
@@ -382,7 +382,7 @@ class HeaderFile extends File {
|
||||
exists(Include i | i.getIncludedFile() = this)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "HeaderFile" }
|
||||
override string getAPrimaryQlClass() { result = "HeaderFile" }
|
||||
|
||||
/**
|
||||
* Holds if this header file does not contain any declaration entries or top level
|
||||
@@ -408,7 +408,7 @@ class HeaderFile extends File {
|
||||
class CFile extends File {
|
||||
CFile() { exists(string ext | ext = this.getExtension().toLowerCase() | ext = "c" or ext = "i") }
|
||||
|
||||
override string getCanonicalQLClass() { result = "CFile" }
|
||||
override string getAPrimaryQlClass() { result = "CFile" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -436,7 +436,7 @@ class CppFile extends File {
|
||||
)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "CppFile" }
|
||||
override string getAPrimaryQlClass() { result = "CppFile" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,7 +27,7 @@ class FriendDecl extends Declaration, @frienddecl {
|
||||
*/
|
||||
override Location getADeclarationLocation() { result = this.getLocation() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "FriendDecl" }
|
||||
override string getAPrimaryQlClass() { result = "FriendDecl" }
|
||||
|
||||
/**
|
||||
* Implements the abstract method `Declaration.getDefinitionLocation`. A
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Location
|
||||
import semmle.code.cpp.Member
|
||||
import semmle.code.cpp.Class
|
||||
import semmle.code.cpp.Parameter
|
||||
import semmle.code.cpp.exprs.Call
|
||||
@@ -514,7 +513,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
|
||||
/** Gets the function which is being declared or defined. */
|
||||
override Function getDeclaration() { result = getFunction() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "FunctionDeclarationEntry" }
|
||||
override string getAPrimaryQlClass() { result = "FunctionDeclarationEntry" }
|
||||
|
||||
/** Gets the function which is being declared or defined. */
|
||||
Function getFunction() { fun_decls(underlyingElement(this), unresolveElement(result), _, _, _) }
|
||||
@@ -699,7 +698,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
|
||||
class TopLevelFunction extends Function {
|
||||
TopLevelFunction() { not this.isMember() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "TopLevelFunction" }
|
||||
override string getAPrimaryQlClass() { result = "TopLevelFunction" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -708,7 +707,7 @@ class TopLevelFunction extends Function {
|
||||
class Operator extends Function {
|
||||
Operator() { functions(underlyingElement(this), _, 5) }
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not this instanceof MemberFunction and result = "Operator"
|
||||
}
|
||||
}
|
||||
@@ -739,7 +738,7 @@ class TemplateFunction extends Function {
|
||||
is_function_template(underlyingElement(this)) and exists(getATemplateArgument())
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "TemplateFunction" }
|
||||
override string getAPrimaryQlClass() { result = "TemplateFunction" }
|
||||
|
||||
/**
|
||||
* Gets a compiler-generated instantiation of this function template.
|
||||
@@ -779,7 +778,7 @@ class FunctionTemplateInstantiation extends Function {
|
||||
|
||||
FunctionTemplateInstantiation() { tf.getAnInstantiation() = this }
|
||||
|
||||
override string getCanonicalQLClass() { result = "FunctionTemplateInstantiation" }
|
||||
override string getAPrimaryQlClass() { result = "FunctionTemplateInstantiation" }
|
||||
|
||||
/**
|
||||
* Gets the function template from which this instantiation was instantiated.
|
||||
@@ -824,7 +823,7 @@ class FunctionTemplateInstantiation extends Function {
|
||||
class FunctionTemplateSpecialization extends Function {
|
||||
FunctionTemplateSpecialization() { this.isSpecialization() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "FunctionTemplateSpecialization" }
|
||||
override string getAPrimaryQlClass() { result = "FunctionTemplateSpecialization" }
|
||||
|
||||
/**
|
||||
* Gets the primary template for the specialization (the function template
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides the `Initializer` class, representing C/C++ declaration initializers.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.controlflow.ControlFlowGraph
|
||||
|
||||
/**
|
||||
@@ -18,7 +22,7 @@ import semmle.code.cpp.controlflow.ControlFlowGraph
|
||||
class Initializer extends ControlFlowNode, @initialiser {
|
||||
override Location getLocation() { initialisers(underlyingElement(this), _, _, result) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "Initializer" }
|
||||
override string getAPrimaryQlClass() { result = "Initializer" }
|
||||
|
||||
/** Holds if this initializer is explicit in the source. */
|
||||
override predicate fromSource() { not this.getLocation() instanceof UnknownLocation }
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes for loop iteration variables.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Variable
|
||||
|
||||
/**
|
||||
@@ -7,14 +11,18 @@ import semmle.code.cpp.Variable
|
||||
class LoopCounter extends Variable {
|
||||
LoopCounter() { exists(ForStmt f | f.getAnIterationVariable() = this) }
|
||||
|
||||
// Gets an access of this variable within loop `f`.
|
||||
/**
|
||||
* Gets an access of this variable within loop `f`.
|
||||
*/
|
||||
VariableAccess getVariableAccessInLoop(ForStmt f) {
|
||||
this.getALoop() = f and
|
||||
result.getEnclosingStmt().getParent*() = f and
|
||||
this = result.getTarget()
|
||||
}
|
||||
|
||||
// Gets a loop which uses this variable as its counter.
|
||||
/**
|
||||
* Gets a loop which uses this variable as its counter.
|
||||
*/
|
||||
ForStmt getALoop() { result.getAnIterationVariable() = this }
|
||||
}
|
||||
|
||||
@@ -25,14 +33,18 @@ class LoopCounter extends Variable {
|
||||
class LoopControlVariable extends Variable {
|
||||
LoopControlVariable() { this = loopControlVariable(_) }
|
||||
|
||||
// Gets an access of this variable within loop `f`.
|
||||
/**
|
||||
* Gets an access of this variable within loop `f`.
|
||||
*/
|
||||
VariableAccess getVariableAccessInLoop(ForStmt f) {
|
||||
this.getALoop() = f and
|
||||
result.getEnclosingStmt().getParent*() = f and
|
||||
this = result.getTarget()
|
||||
}
|
||||
|
||||
// Gets a loop which uses this variable as its control variable.
|
||||
/**
|
||||
* Gets a loop which uses this variable as its control variable.
|
||||
*/
|
||||
ForStmt getALoop() { this = loopControlVariable(result) }
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Proivdes the `LinkTarget` class representing linker invocations during the build process.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Class
|
||||
import semmle.code.cpp.File
|
||||
import semmle.code.cpp.Function
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes and predicates for locations in the source code.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Element
|
||||
import semmle.code.cpp.File
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class Macro extends PreprocessorDirective, @ppd_define {
|
||||
*/
|
||||
override string getHead() { preproctext(underlyingElement(this), result, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "Macro" }
|
||||
override string getAPrimaryQlClass() { result = "Macro" }
|
||||
|
||||
/**
|
||||
* Gets the body of this macro. For example, `(((x)>(y))?(x):(y))` in
|
||||
@@ -74,7 +74,7 @@ class MacroAccess extends Locatable, @macroinvocation {
|
||||
*/
|
||||
override Location getLocation() { result = this.getOutermostMacroAccess().getActualLocation() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "MacroAccess" }
|
||||
override string getAPrimaryQlClass() { result = "MacroAccess" }
|
||||
|
||||
/**
|
||||
* Gets the location of this macro access. For a nested access, where
|
||||
@@ -147,7 +147,7 @@ class MacroAccess extends Locatable, @macroinvocation {
|
||||
class MacroInvocation extends MacroAccess {
|
||||
MacroInvocation() { macroinvocations(underlyingElement(this), _, _, 1) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "MacroInvocation" }
|
||||
override string getAPrimaryQlClass() { result = "MacroInvocation" }
|
||||
|
||||
/**
|
||||
* Gets an element that occurs in this macro invocation or a nested macro
|
||||
@@ -179,6 +179,11 @@ class MacroInvocation extends MacroAccess {
|
||||
result.(Stmt).getGeneratingMacro() = this
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a function that includes an expression that is affected by this macro
|
||||
* invocation. If the macro expansion includes the end of one function and
|
||||
* the beginning of another, this predicate will get both.
|
||||
*/
|
||||
Function getEnclosingFunction() {
|
||||
result = this.getAnAffectedElement().(Expr).getEnclosingFunction()
|
||||
}
|
||||
|
||||
@@ -1,2 +1,6 @@
|
||||
/**
|
||||
* DEPRECATED: import `semmle.code.cpp.Element` and/or `semmle.code.cpp.Type` directly as required.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Element
|
||||
import semmle.code.cpp.Type
|
||||
|
||||
@@ -25,7 +25,7 @@ import cpp
|
||||
class MemberFunction extends Function {
|
||||
MemberFunction() { this.isMember() }
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not this instanceof CopyAssignmentOperator and
|
||||
not this instanceof MoveAssignmentOperator and
|
||||
result = "MemberFunction"
|
||||
@@ -93,7 +93,7 @@ class MemberFunction extends Function {
|
||||
class VirtualFunction extends MemberFunction {
|
||||
VirtualFunction() { this.hasSpecifier("virtual") or purefunctions(underlyingElement(this)) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "VirtualFunction" }
|
||||
override string getAPrimaryQlClass() { result = "VirtualFunction" }
|
||||
|
||||
/** Holds if this virtual function is pure. */
|
||||
predicate isPure() { this instanceof PureVirtualFunction }
|
||||
@@ -125,7 +125,7 @@ class VirtualFunction extends MemberFunction {
|
||||
class PureVirtualFunction extends VirtualFunction {
|
||||
PureVirtualFunction() { purefunctions(underlyingElement(this)) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "PureVirtualFunction" }
|
||||
override string getAPrimaryQlClass() { result = "PureVirtualFunction" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,7 +147,7 @@ class PureVirtualFunction extends VirtualFunction {
|
||||
class ConstMemberFunction extends MemberFunction {
|
||||
ConstMemberFunction() { this.hasSpecifier("const") }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ConstMemberFunction" }
|
||||
override string getAPrimaryQlClass() { result = "ConstMemberFunction" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,7 +165,7 @@ class ConstMemberFunction extends MemberFunction {
|
||||
class Constructor extends MemberFunction {
|
||||
Constructor() { functions(underlyingElement(this), _, 2) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "Constructor" }
|
||||
override string getAPrimaryQlClass() { result = "Constructor" }
|
||||
|
||||
/**
|
||||
* Holds if this constructor serves as a default constructor.
|
||||
@@ -223,7 +223,7 @@ class ConversionConstructor extends Constructor, ImplicitConversionFunction {
|
||||
not hasSpecifier("explicit")
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not this instanceof CopyConstructor and
|
||||
not this instanceof MoveConstructor and
|
||||
result = "ConversionConstructor"
|
||||
@@ -283,7 +283,7 @@ class CopyConstructor extends Constructor {
|
||||
not exists(getATemplateArgument())
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "CopyConstructor" }
|
||||
override string getAPrimaryQlClass() { result = "CopyConstructor" }
|
||||
|
||||
/**
|
||||
* Holds if we cannot determine that this constructor will become a copy
|
||||
@@ -340,7 +340,7 @@ class MoveConstructor extends Constructor {
|
||||
not exists(getATemplateArgument())
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "MoveConstructor" }
|
||||
override string getAPrimaryQlClass() { result = "MoveConstructor" }
|
||||
|
||||
/**
|
||||
* Holds if we cannot determine that this constructor will become a move
|
||||
@@ -391,7 +391,7 @@ class NoArgConstructor extends Constructor {
|
||||
class Destructor extends MemberFunction {
|
||||
Destructor() { functions(underlyingElement(this), _, 3) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "Destructor" }
|
||||
override string getAPrimaryQlClass() { result = "Destructor" }
|
||||
|
||||
/**
|
||||
* Gets a compiler-generated action which destructs a base class or member
|
||||
@@ -422,7 +422,7 @@ class Destructor extends MemberFunction {
|
||||
class ConversionOperator extends MemberFunction, ImplicitConversionFunction {
|
||||
ConversionOperator() { functions(underlyingElement(this), _, 4) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ConversionOperator" }
|
||||
override string getAPrimaryQlClass() { result = "ConversionOperator" }
|
||||
|
||||
override Type getSourceType() { result = this.getDeclaringType() }
|
||||
|
||||
@@ -458,7 +458,7 @@ class CopyAssignmentOperator extends Operator {
|
||||
not exists(getATemplateArgument())
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "CopyAssignmentOperator" }
|
||||
override string getAPrimaryQlClass() { result = "CopyAssignmentOperator" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -484,5 +484,5 @@ class MoveAssignmentOperator extends Operator {
|
||||
not exists(getATemplateArgument())
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "MoveAssignmentOperator" }
|
||||
override string getAPrimaryQlClass() { result = "MoveAssignmentOperator" }
|
||||
}
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Provides classes for working with name qualifiers such as the `N::` in
|
||||
* `N::f()`.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes for modeling namespaces, `using` directives and `using` declarations.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Element
|
||||
import semmle.code.cpp.Type
|
||||
import semmle.code.cpp.metrics.MetricNamespace
|
||||
@@ -127,7 +131,7 @@ class NamespaceDeclarationEntry extends Locatable, @namespace_decl {
|
||||
*/
|
||||
Location getBodyLocation() { namespace_decls(underlyingElement(this), _, _, result) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "NamespaceDeclarationEntry" }
|
||||
override string getAPrimaryQlClass() { result = "NamespaceDeclarationEntry" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Provides a class for reasoning about nested field accesses, for example
|
||||
* the access `myLine.start.x`.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/**
|
||||
@@ -25,7 +30,7 @@ private Expr getUltimateQualifier(FieldAccess fa) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Accesses to nested fields.
|
||||
* A nested field access, for example the access `myLine.start.x`.
|
||||
*/
|
||||
class NestedFieldAccess extends FieldAccess {
|
||||
Expr ultimateQualifier;
|
||||
@@ -35,6 +40,30 @@ class NestedFieldAccess extends FieldAccess {
|
||||
getTarget() = getANestedField(ultimateQualifier.getType().stripType())
|
||||
}
|
||||
|
||||
/** Gets the ultimate qualifier of this nested field access. */
|
||||
/**
|
||||
* Gets the outermost qualifier of this nested field access. In the
|
||||
* following example, the access to `myLine.start.x` has outermost qualifier
|
||||
* `myLine`:
|
||||
* ```
|
||||
* struct Point
|
||||
* {
|
||||
* float x, y;
|
||||
* };
|
||||
*
|
||||
* struct Line
|
||||
* {
|
||||
* Point start, end;
|
||||
* };
|
||||
*
|
||||
* void init()
|
||||
* {
|
||||
* Line myLine;
|
||||
*
|
||||
* myLine.start.x = 0.0f;
|
||||
*
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
Expr getUltimateQualifier() { result = ultimateQualifier }
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Class
|
||||
private import semmle.code.cpp.internal.ResolveClass
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides a class that models parameters to functions.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Location
|
||||
import semmle.code.cpp.Declaration
|
||||
private import semmle.code.cpp.internal.ResolveClass
|
||||
@@ -45,7 +49,7 @@ class Parameter extends LocalScopeVariable, @parameter {
|
||||
result = "p#" + this.getIndex().toString()
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Parameter" }
|
||||
override string getAPrimaryQlClass() { result = "Parameter" }
|
||||
|
||||
/**
|
||||
* Gets the name of this parameter, including it's type.
|
||||
|
||||
@@ -152,7 +152,7 @@ class PreprocessorIf extends PreprocessorBranch, @ppd_if {
|
||||
class PreprocessorIfdef extends PreprocessorBranch, @ppd_ifdef {
|
||||
override string toString() { result = "#ifdef " + this.getHead() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "PreprocessorIfdef" }
|
||||
override string getAPrimaryQlClass() { result = "PreprocessorIfdef" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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();
|
||||
|
||||
/**
|
||||
@@ -155,7 +169,7 @@ class PrintASTNode extends TPrintASTNode {
|
||||
* Retrieves the canonical QL class(es) for entity `el`
|
||||
*/
|
||||
private string qlClass(ElementBase el) {
|
||||
result = "[" + concat(el.getCanonicalQLClass(), ",") + "] "
|
||||
result = "[" + concat(el.getAPrimaryQlClass(), ",") + "] "
|
||||
// Alternative implementation -- do not delete. It is useful for QL class discovery.
|
||||
//result = "["+ concat(el.getAQlClass(), ",") + "] "
|
||||
}
|
||||
@@ -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 for modeling specifiers and attributes.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Element
|
||||
private import semmle.code.cpp.internal.ResolveClass
|
||||
|
||||
@@ -12,7 +16,7 @@ class Specifier extends Element, @specifier {
|
||||
result instanceof UnknownDefaultLocation
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Specifier" }
|
||||
override string getAPrimaryQlClass() { result = "Specifier" }
|
||||
|
||||
/** Gets the name of this specifier. */
|
||||
string getName() { specifiers(underlyingElement(this), result) }
|
||||
@@ -33,7 +37,7 @@ class FunctionSpecifier extends Specifier {
|
||||
this.hasName("explicit")
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "FunctionSpecifier)" }
|
||||
override string getAPrimaryQlClass() { result = "FunctionSpecifier)" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,7 +53,7 @@ class StorageClassSpecifier extends Specifier {
|
||||
this.hasName("mutable")
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "StorageClassSpecifier" }
|
||||
override string getAPrimaryQlClass() { result = "StorageClassSpecifier" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,7 +108,7 @@ class AccessSpecifier extends Specifier {
|
||||
)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "AccessSpecifier" }
|
||||
override string getAPrimaryQlClass() { result = "AccessSpecifier" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,7 +238,7 @@ class FormatAttribute extends GnuAttribute {
|
||||
)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "FormatAttribute" }
|
||||
override string getAPrimaryQlClass() { result = "FormatAttribute" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes for modeling `struct`s.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Type
|
||||
import semmle.code.cpp.Class
|
||||
|
||||
@@ -18,7 +22,7 @@ import semmle.code.cpp.Class
|
||||
class Struct extends Class {
|
||||
Struct() { usertypes(underlyingElement(this), _, 1) or usertypes(underlyingElement(this), _, 3) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "Struct" }
|
||||
override string getAPrimaryQlClass() { result = "Struct" }
|
||||
|
||||
override string explain() { result = "struct " + this.getName() }
|
||||
|
||||
@@ -39,9 +43,7 @@ class Struct extends Class {
|
||||
class LocalStruct extends Struct {
|
||||
LocalStruct() { isLocal() }
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
not this instanceof LocalUnion and result = "LocalStruct"
|
||||
}
|
||||
override string getAPrimaryQlClass() { not this instanceof LocalUnion and result = "LocalStruct" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,7 +60,7 @@ class LocalStruct extends Struct {
|
||||
class NestedStruct extends Struct {
|
||||
NestedStruct() { this.isMember() }
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not this instanceof NestedUnion and result = "NestedStruct"
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
/**
|
||||
* Provides a hierarchy of classes for modeling C/C++ types.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Element
|
||||
import semmle.code.cpp.Member
|
||||
import semmle.code.cpp.Function
|
||||
private import semmle.code.cpp.internal.ResolveClass
|
||||
|
||||
@@ -322,7 +325,7 @@ class BuiltInType extends Type, @builtintype {
|
||||
class ErroneousType extends BuiltInType {
|
||||
ErroneousType() { builtintypes(underlyingElement(this), _, 1, _, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ErroneousType" }
|
||||
override string getAPrimaryQlClass() { result = "ErroneousType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -342,7 +345,7 @@ class ErroneousType extends BuiltInType {
|
||||
class UnknownType extends BuiltInType {
|
||||
UnknownType() { builtintypes(underlyingElement(this), _, 2, _, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "UnknownType" }
|
||||
override string getAPrimaryQlClass() { result = "UnknownType" }
|
||||
}
|
||||
|
||||
private predicate isArithmeticType(@builtintype type, int kind) {
|
||||
@@ -361,7 +364,7 @@ private predicate isArithmeticType(@builtintype type, int kind) {
|
||||
class ArithmeticType extends BuiltInType {
|
||||
ArithmeticType() { isArithmeticType(underlyingElement(this), _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ArithmeticType" }
|
||||
override string getAPrimaryQlClass() { result = "ArithmeticType" }
|
||||
}
|
||||
|
||||
private predicate isIntegralType(@builtintype type, int kind) {
|
||||
@@ -561,7 +564,7 @@ class IntegralType extends ArithmeticType, IntegralOrEnumType {
|
||||
class BoolType extends IntegralType {
|
||||
BoolType() { builtintypes(underlyingElement(this), _, 4, _, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BoolType" }
|
||||
override string getAPrimaryQlClass() { result = "BoolType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -586,7 +589,7 @@ abstract class CharType extends IntegralType { }
|
||||
class PlainCharType extends CharType {
|
||||
PlainCharType() { builtintypes(underlyingElement(this), _, 5, _, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "PlainCharType" }
|
||||
override string getAPrimaryQlClass() { result = "PlainCharType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -599,7 +602,7 @@ class PlainCharType extends CharType {
|
||||
class UnsignedCharType extends CharType {
|
||||
UnsignedCharType() { builtintypes(underlyingElement(this), _, 6, _, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "UnsignedCharType" }
|
||||
override string getAPrimaryQlClass() { result = "UnsignedCharType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -612,7 +615,7 @@ class UnsignedCharType extends CharType {
|
||||
class SignedCharType extends CharType {
|
||||
SignedCharType() { builtintypes(underlyingElement(this), _, 7, _, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "SignedCharType" }
|
||||
override string getAPrimaryQlClass() { result = "SignedCharType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -629,7 +632,7 @@ class ShortType extends IntegralType {
|
||||
builtintypes(underlyingElement(this), _, 10, _, _, _)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "ShortType" }
|
||||
override string getAPrimaryQlClass() { result = "ShortType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -646,7 +649,7 @@ class IntType extends IntegralType {
|
||||
builtintypes(underlyingElement(this), _, 13, _, _, _)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "IntType" }
|
||||
override string getAPrimaryQlClass() { result = "IntType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -663,7 +666,7 @@ class LongType extends IntegralType {
|
||||
builtintypes(underlyingElement(this), _, 16, _, _, _)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "LongType" }
|
||||
override string getAPrimaryQlClass() { result = "LongType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -680,7 +683,7 @@ class LongLongType extends IntegralType {
|
||||
builtintypes(underlyingElement(this), _, 19, _, _, _)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "LongLongType" }
|
||||
override string getAPrimaryQlClass() { result = "LongLongType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -698,7 +701,7 @@ class Int128Type extends IntegralType {
|
||||
builtintypes(underlyingElement(this), _, 37, _, _, _)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Int128Type" }
|
||||
override string getAPrimaryQlClass() { result = "Int128Type" }
|
||||
}
|
||||
|
||||
private newtype TTypeDomain =
|
||||
@@ -894,7 +897,7 @@ class DecimalFloatingPointType extends FloatingPointType {
|
||||
class FloatType extends RealNumberType, BinaryFloatingPointType {
|
||||
FloatType() { builtintypes(underlyingElement(this), _, 24, _, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "FloatType" }
|
||||
override string getAPrimaryQlClass() { result = "FloatType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -906,7 +909,7 @@ class FloatType extends RealNumberType, BinaryFloatingPointType {
|
||||
class DoubleType extends RealNumberType, BinaryFloatingPointType {
|
||||
DoubleType() { builtintypes(underlyingElement(this), _, 25, _, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "DoubleType" }
|
||||
override string getAPrimaryQlClass() { result = "DoubleType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -918,7 +921,7 @@ class DoubleType extends RealNumberType, BinaryFloatingPointType {
|
||||
class LongDoubleType extends RealNumberType, BinaryFloatingPointType {
|
||||
LongDoubleType() { builtintypes(underlyingElement(this), _, 26, _, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "LongDoubleType" }
|
||||
override string getAPrimaryQlClass() { result = "LongDoubleType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -930,7 +933,7 @@ class LongDoubleType extends RealNumberType, BinaryFloatingPointType {
|
||||
class Float128Type extends RealNumberType, BinaryFloatingPointType {
|
||||
Float128Type() { builtintypes(underlyingElement(this), _, 38, _, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "Float128Type" }
|
||||
override string getAPrimaryQlClass() { result = "Float128Type" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -942,7 +945,7 @@ class Float128Type extends RealNumberType, BinaryFloatingPointType {
|
||||
class Decimal32Type extends RealNumberType, DecimalFloatingPointType {
|
||||
Decimal32Type() { builtintypes(underlyingElement(this), _, 40, _, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "Decimal32Type" }
|
||||
override string getAPrimaryQlClass() { result = "Decimal32Type" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -954,7 +957,7 @@ class Decimal32Type extends RealNumberType, DecimalFloatingPointType {
|
||||
class Decimal64Type extends RealNumberType, DecimalFloatingPointType {
|
||||
Decimal64Type() { builtintypes(underlyingElement(this), _, 41, _, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "Decimal64Type" }
|
||||
override string getAPrimaryQlClass() { result = "Decimal64Type" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -966,7 +969,7 @@ class Decimal64Type extends RealNumberType, DecimalFloatingPointType {
|
||||
class Decimal128Type extends RealNumberType, DecimalFloatingPointType {
|
||||
Decimal128Type() { builtintypes(underlyingElement(this), _, 42, _, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "Decimal128Type" }
|
||||
override string getAPrimaryQlClass() { result = "Decimal128Type" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -978,7 +981,7 @@ class Decimal128Type extends RealNumberType, DecimalFloatingPointType {
|
||||
class VoidType extends BuiltInType {
|
||||
VoidType() { builtintypes(underlyingElement(this), _, 3, _, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "VoidType" }
|
||||
override string getAPrimaryQlClass() { result = "VoidType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -994,7 +997,7 @@ class VoidType extends BuiltInType {
|
||||
class WideCharType extends IntegralType {
|
||||
WideCharType() { builtintypes(underlyingElement(this), _, 33, _, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "WideCharType" }
|
||||
override string getAPrimaryQlClass() { result = "WideCharType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1006,7 +1009,7 @@ class WideCharType extends IntegralType {
|
||||
class Char8Type extends IntegralType {
|
||||
Char8Type() { builtintypes(underlyingElement(this), _, 51, _, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "Char8Type" }
|
||||
override string getAPrimaryQlClass() { result = "Char8Type" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1018,7 +1021,7 @@ class Char8Type extends IntegralType {
|
||||
class Char16Type extends IntegralType {
|
||||
Char16Type() { builtintypes(underlyingElement(this), _, 43, _, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "Char16Type" }
|
||||
override string getAPrimaryQlClass() { result = "Char16Type" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1030,7 +1033,7 @@ class Char16Type extends IntegralType {
|
||||
class Char32Type extends IntegralType {
|
||||
Char32Type() { builtintypes(underlyingElement(this), _, 44, _, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "Char32Type" }
|
||||
override string getAPrimaryQlClass() { result = "Char32Type" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1045,7 +1048,7 @@ class Char32Type extends IntegralType {
|
||||
class NullPointerType extends BuiltInType {
|
||||
NullPointerType() { builtintypes(underlyingElement(this), _, 34, _, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "NullPointerType" }
|
||||
override string getAPrimaryQlClass() { result = "NullPointerType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1080,22 +1083,46 @@ class DerivedType extends Type, @derivedtype {
|
||||
|
||||
override Type stripType() { result = getBaseType().stripType() }
|
||||
|
||||
predicate isAutoReleasing() {
|
||||
/**
|
||||
* Holds if this type has the `__autoreleasing` specifier or if it points to
|
||||
* a type with the `__autoreleasing` specifier.
|
||||
*
|
||||
* DEPRECATED: use `hasSpecifier` directly instead.
|
||||
*/
|
||||
deprecated predicate isAutoReleasing() {
|
||||
this.hasSpecifier("__autoreleasing") or
|
||||
this.(PointerType).getBaseType().hasSpecifier("__autoreleasing")
|
||||
}
|
||||
|
||||
predicate isStrong() {
|
||||
/**
|
||||
* Holds if this type has the `__strong` specifier or if it points to
|
||||
* a type with the `__strong` specifier.
|
||||
*
|
||||
* DEPRECATED: use `hasSpecifier` directly instead.
|
||||
*/
|
||||
deprecated predicate isStrong() {
|
||||
this.hasSpecifier("__strong") or
|
||||
this.(PointerType).getBaseType().hasSpecifier("__strong")
|
||||
}
|
||||
|
||||
predicate isUnsafeRetained() {
|
||||
/**
|
||||
* Holds if this type has the `__unsafe_unretained` specifier or if it points
|
||||
* to a type with the `__unsafe_unretained` specifier.
|
||||
*
|
||||
* DEPRECATED: use `hasSpecifier` directly instead.
|
||||
*/
|
||||
deprecated predicate isUnsafeRetained() {
|
||||
this.hasSpecifier("__unsafe_unretained") or
|
||||
this.(PointerType).getBaseType().hasSpecifier("__unsafe_unretained")
|
||||
}
|
||||
|
||||
predicate isWeak() {
|
||||
/**
|
||||
* Holds if this type has the `__weak` specifier or if it points to
|
||||
* a type with the `__weak` specifier.
|
||||
*
|
||||
* DEPRECATED: use `hasSpecifier` directly instead.
|
||||
*/
|
||||
deprecated predicate isWeak() {
|
||||
this.hasSpecifier("__weak") or
|
||||
this.(PointerType).getBaseType().hasSpecifier("__weak")
|
||||
}
|
||||
@@ -1109,7 +1136,7 @@ class DerivedType extends Type, @derivedtype {
|
||||
* ```
|
||||
*/
|
||||
class Decltype extends Type, @decltype {
|
||||
override string getCanonicalQLClass() { result = "Decltype" }
|
||||
override string getAPrimaryQlClass() { result = "Decltype" }
|
||||
|
||||
/**
|
||||
* The expression whose type is being obtained by this decltype.
|
||||
@@ -1182,7 +1209,7 @@ class Decltype extends Type, @decltype {
|
||||
class PointerType extends DerivedType {
|
||||
PointerType() { derivedtypes(underlyingElement(this), _, 1, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "PointerType" }
|
||||
override string getAPrimaryQlClass() { result = "PointerType" }
|
||||
|
||||
override int getPointerIndirectionLevel() {
|
||||
result = 1 + this.getBaseType().getPointerIndirectionLevel()
|
||||
@@ -1208,7 +1235,7 @@ class ReferenceType extends DerivedType {
|
||||
derivedtypes(underlyingElement(this), _, 2, _) or derivedtypes(underlyingElement(this), _, 8, _)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "ReferenceType" }
|
||||
override string getAPrimaryQlClass() { result = "ReferenceType" }
|
||||
|
||||
override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() }
|
||||
|
||||
@@ -1235,7 +1262,7 @@ class ReferenceType extends DerivedType {
|
||||
class LValueReferenceType extends ReferenceType {
|
||||
LValueReferenceType() { derivedtypes(underlyingElement(this), _, 2, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "LValueReferenceType" }
|
||||
override string getAPrimaryQlClass() { result = "LValueReferenceType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1251,7 +1278,7 @@ class LValueReferenceType extends ReferenceType {
|
||||
class RValueReferenceType extends ReferenceType {
|
||||
RValueReferenceType() { derivedtypes(underlyingElement(this), _, 8, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "RValueReferenceType" }
|
||||
override string getAPrimaryQlClass() { result = "RValueReferenceType" }
|
||||
|
||||
override string explain() { result = "rvalue " + super.explain() }
|
||||
}
|
||||
@@ -1266,7 +1293,7 @@ class RValueReferenceType extends ReferenceType {
|
||||
class SpecifiedType extends DerivedType {
|
||||
SpecifiedType() { derivedtypes(underlyingElement(this), _, 3, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "SpecifiedType" }
|
||||
override string getAPrimaryQlClass() { result = "SpecifiedType" }
|
||||
|
||||
override int getSize() { result = this.getBaseType().getSize() }
|
||||
|
||||
@@ -1314,8 +1341,12 @@ class SpecifiedType extends DerivedType {
|
||||
class ArrayType extends DerivedType {
|
||||
ArrayType() { derivedtypes(underlyingElement(this), _, 4, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ArrayType" }
|
||||
override string getAPrimaryQlClass() { result = "ArrayType" }
|
||||
|
||||
/**
|
||||
* Holds if this array is declared to be of a constant size. See
|
||||
* `getArraySize` and `getByteSize` to get the size of the array.
|
||||
*/
|
||||
predicate hasArraySize() { arraysizes(underlyingElement(this), _, _, _) }
|
||||
|
||||
/**
|
||||
@@ -1381,7 +1412,7 @@ class GNUVectorType extends DerivedType {
|
||||
*/
|
||||
int getNumElements() { arraysizes(underlyingElement(this), result, _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "GNUVectorType" }
|
||||
override string getAPrimaryQlClass() { result = "GNUVectorType" }
|
||||
|
||||
/**
|
||||
* Gets the size, in bytes, of this vector type.
|
||||
@@ -1412,7 +1443,7 @@ class GNUVectorType extends DerivedType {
|
||||
class FunctionPointerType extends FunctionPointerIshType {
|
||||
FunctionPointerType() { derivedtypes(underlyingElement(this), _, 6, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "FunctionPointerType" }
|
||||
override string getAPrimaryQlClass() { result = "FunctionPointerType" }
|
||||
|
||||
override int getPointerIndirectionLevel() { result = 1 }
|
||||
|
||||
@@ -1430,7 +1461,7 @@ class FunctionPointerType extends FunctionPointerIshType {
|
||||
class FunctionReferenceType extends FunctionPointerIshType {
|
||||
FunctionReferenceType() { derivedtypes(underlyingElement(this), _, 7, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "FunctionReferenceType" }
|
||||
override string getAPrimaryQlClass() { result = "FunctionReferenceType" }
|
||||
|
||||
override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() }
|
||||
|
||||
@@ -1519,7 +1550,7 @@ class PointerToMemberType extends Type, @ptrtomember {
|
||||
/** a printable representation of this named element */
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "PointerToMemberType" }
|
||||
override string getAPrimaryQlClass() { result = "PointerToMemberType" }
|
||||
|
||||
/** the name of this type */
|
||||
override string getName() { result = "..:: *" }
|
||||
@@ -1564,16 +1595,25 @@ class RoutineType extends Type, @routinetype {
|
||||
/** a printable representation of this named element */
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "RoutineType" }
|
||||
override string getAPrimaryQlClass() { result = "RoutineType" }
|
||||
|
||||
override string getName() { result = "..()(..)" }
|
||||
|
||||
/**
|
||||
* Gets the type of the `n`th parameter to this routine.
|
||||
*/
|
||||
Type getParameterType(int n) {
|
||||
routinetypeargs(underlyingElement(this), n, unresolveElement(result))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of a parameter to this routine.
|
||||
*/
|
||||
Type getAParameterType() { routinetypeargs(underlyingElement(this), _, unresolveElement(result)) }
|
||||
|
||||
/**
|
||||
* Gets the return type of this routine.
|
||||
*/
|
||||
Type getReturnType() { routinetypes(underlyingElement(this), unresolveElement(result)) }
|
||||
|
||||
override string explain() {
|
||||
@@ -1632,7 +1672,7 @@ class TemplateParameter extends UserType {
|
||||
usertypes(underlyingElement(this), _, 7) or usertypes(underlyingElement(this), _, 8)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "TemplateParameter" }
|
||||
override string getAPrimaryQlClass() { result = "TemplateParameter" }
|
||||
|
||||
override predicate involvesTemplateParameter() { any() }
|
||||
}
|
||||
@@ -1650,7 +1690,7 @@ class TemplateParameter extends UserType {
|
||||
class TemplateTemplateParameter extends TemplateParameter {
|
||||
TemplateTemplateParameter() { usertypes(underlyingElement(this), _, 8) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "TemplateTemplateParameter" }
|
||||
override string getAPrimaryQlClass() { result = "TemplateTemplateParameter" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1662,7 +1702,7 @@ class TemplateTemplateParameter extends TemplateParameter {
|
||||
class AutoType extends TemplateParameter {
|
||||
AutoType() { usertypes(underlyingElement(this), "auto", 7) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "AutoType" }
|
||||
override string getAPrimaryQlClass() { result = "AutoType" }
|
||||
|
||||
override Location getLocation() {
|
||||
suppressUnusedThis(this) and
|
||||
@@ -1698,7 +1738,7 @@ private predicate suppressUnusedThis(Type t) { any() }
|
||||
class TypeMention extends Locatable, @type_mention {
|
||||
override string toString() { result = "type mention" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "TypeMention" }
|
||||
override string getAPrimaryQlClass() { result = "TypeMention" }
|
||||
|
||||
/**
|
||||
* Gets the type being referenced by this type mention.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes for modeling typedefs and type aliases.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Type
|
||||
private import semmle.code.cpp.internal.ResolveClass
|
||||
|
||||
@@ -55,7 +59,7 @@ class TypedefType extends UserType {
|
||||
class CTypedefType extends TypedefType {
|
||||
CTypedefType() { usertypes(underlyingElement(this), _, 5) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "CTypedefType" }
|
||||
override string getAPrimaryQlClass() { result = "CTypedefType" }
|
||||
|
||||
override string explain() {
|
||||
result = "typedef {" + this.getBaseType().explain() + "} as \"" + this.getName() + "\""
|
||||
@@ -71,7 +75,7 @@ class CTypedefType extends TypedefType {
|
||||
class UsingAliasTypedefType extends TypedefType {
|
||||
UsingAliasTypedefType() { usertypes(underlyingElement(this), _, 14) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "UsingAliasTypedefType" }
|
||||
override string getAPrimaryQlClass() { result = "UsingAliasTypedefType" }
|
||||
|
||||
override string explain() {
|
||||
result = "using {" + this.getBaseType().explain() + "} as \"" + this.getName() + "\""
|
||||
@@ -88,7 +92,7 @@ class UsingAliasTypedefType extends TypedefType {
|
||||
class LocalTypedefType extends TypedefType {
|
||||
LocalTypedefType() { isLocal() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "LocalTypedefType" }
|
||||
override string getAPrimaryQlClass() { result = "LocalTypedefType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,7 +105,7 @@ class LocalTypedefType extends TypedefType {
|
||||
class NestedTypedefType extends TypedefType {
|
||||
NestedTypedefType() { this.isMember() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "NestedTypedefType" }
|
||||
override string getAPrimaryQlClass() { result = "NestedTypedefType" }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `.hasSpecifier("private")` instead.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes for modeling `union`s.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Type
|
||||
import semmle.code.cpp.Struct
|
||||
|
||||
@@ -13,7 +17,7 @@ import semmle.code.cpp.Struct
|
||||
class Union extends Struct {
|
||||
Union() { usertypes(underlyingElement(this), _, 3) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "Union" }
|
||||
override string getAPrimaryQlClass() { result = "Union" }
|
||||
|
||||
override string explain() { result = "union " + this.getName() }
|
||||
|
||||
@@ -35,7 +39,7 @@ class Union extends Struct {
|
||||
class LocalUnion extends Union {
|
||||
LocalUnion() { isLocal() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "LocalUnion" }
|
||||
override string getAPrimaryQlClass() { result = "LocalUnion" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,7 +57,7 @@ class LocalUnion extends Union {
|
||||
class NestedUnion extends Union {
|
||||
NestedUnion() { this.isMember() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "NestedUnion" }
|
||||
override string getAPrimaryQlClass() { result = "NestedUnion" }
|
||||
|
||||
/** Holds if this member is private. */
|
||||
predicate isPrivate() { this.hasSpecifier("private") }
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
/**
|
||||
* Provides classes for modeling user-defined types such as classes, typedefs
|
||||
* and enums.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Declaration
|
||||
import semmle.code.cpp.Type
|
||||
import semmle.code.cpp.Member
|
||||
import semmle.code.cpp.Function
|
||||
private import semmle.code.cpp.internal.ResolveClass
|
||||
|
||||
@@ -20,7 +24,7 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
|
||||
*/
|
||||
override string getName() { usertypes(underlyingElement(this), result, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "UserType" }
|
||||
override string getAPrimaryQlClass() { result = "UserType" }
|
||||
|
||||
/**
|
||||
* Gets the simple name of this type, without any template parameters. For example
|
||||
@@ -84,6 +88,9 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
|
||||
* type exactly - but this is not apparent from its subclasses
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets a child declaration within this user-defined type.
|
||||
*/
|
||||
Declaration getADeclaration() { none() }
|
||||
|
||||
override string explain() { result = this.getName() }
|
||||
@@ -104,7 +111,7 @@ class TypeDeclarationEntry extends DeclarationEntry, @type_decl {
|
||||
|
||||
override string getName() { result = getType().getName() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "TypeDeclarationEntry" }
|
||||
override string getAPrimaryQlClass() { result = "TypeDeclarationEntry" }
|
||||
|
||||
/**
|
||||
* The type which is being declared or defined.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes for modeling variables and their declarations.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Element
|
||||
import semmle.code.cpp.exprs.Access
|
||||
import semmle.code.cpp.Initializer
|
||||
@@ -28,7 +32,7 @@ private import semmle.code.cpp.internal.ResolveClass
|
||||
* can have multiple declarations.
|
||||
*/
|
||||
class Variable extends Declaration, @variable {
|
||||
override string getCanonicalQLClass() { result = "Variable" }
|
||||
override string getAPrimaryQlClass() { result = "Variable" }
|
||||
|
||||
/** Gets the initializer of this variable, if any. */
|
||||
Initializer getInitializer() { result.getDeclaration() = this }
|
||||
@@ -186,7 +190,7 @@ class Variable extends Declaration, @variable {
|
||||
class VariableDeclarationEntry extends DeclarationEntry, @var_decl {
|
||||
override Variable getDeclaration() { result = getVariable() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "VariableDeclarationEntry" }
|
||||
override string getAPrimaryQlClass() { result = "VariableDeclarationEntry" }
|
||||
|
||||
/**
|
||||
* Gets the variable which is being declared or defined.
|
||||
@@ -245,7 +249,7 @@ class VariableDeclarationEntry extends DeclarationEntry, @var_decl {
|
||||
class ParameterDeclarationEntry extends VariableDeclarationEntry {
|
||||
ParameterDeclarationEntry() { param_decl_bind(underlyingElement(this), _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ParameterDeclarationEntry" }
|
||||
override string getAPrimaryQlClass() { result = "ParameterDeclarationEntry" }
|
||||
|
||||
/**
|
||||
* Gets the function declaration or definition which this parameter
|
||||
@@ -359,7 +363,7 @@ class StackVariable extends LocalScopeVariable {
|
||||
* A local variable can be declared by a `DeclStmt` or a `ConditionDeclExpr`.
|
||||
*/
|
||||
class LocalVariable extends LocalScopeVariable, @localvariable {
|
||||
override string getCanonicalQLClass() { result = "LocalVariable" }
|
||||
override string getAPrimaryQlClass() { result = "LocalVariable" }
|
||||
|
||||
override string getName() { localvariables(underlyingElement(this), _, result) }
|
||||
|
||||
@@ -460,7 +464,7 @@ class NamespaceVariable extends GlobalOrNamespaceVariable {
|
||||
exists(Namespace n | namespacembrs(unresolveElement(n), underlyingElement(this)))
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "NamespaceVariable" }
|
||||
override string getAPrimaryQlClass() { result = "NamespaceVariable" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -481,7 +485,7 @@ class NamespaceVariable extends GlobalOrNamespaceVariable {
|
||||
class GlobalVariable extends GlobalOrNamespaceVariable {
|
||||
GlobalVariable() { not this instanceof NamespaceVariable }
|
||||
|
||||
override string getCanonicalQLClass() { result = "GlobalVariable" }
|
||||
override string getAPrimaryQlClass() { result = "GlobalVariable" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -501,7 +505,7 @@ class GlobalVariable extends GlobalOrNamespaceVariable {
|
||||
class MemberVariable extends Variable, @membervariable {
|
||||
MemberVariable() { this.isMember() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "MemberVariable" }
|
||||
override string getAPrimaryQlClass() { result = "MemberVariable" }
|
||||
|
||||
/** Holds if this member is private. */
|
||||
predicate isPrivate() { this.hasSpecifier("private") }
|
||||
|
||||
@@ -6,7 +6,7 @@ import semmle.code.cpp.Type
|
||||
class CharPointerType extends PointerType {
|
||||
CharPointerType() { this.getBaseType() instanceof CharType }
|
||||
|
||||
override string getCanonicalQLClass() { result = "CharPointerType" }
|
||||
override string getAPrimaryQlClass() { result = "CharPointerType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -15,7 +15,7 @@ class CharPointerType extends PointerType {
|
||||
class IntPointerType extends PointerType {
|
||||
IntPointerType() { this.getBaseType() instanceof IntType }
|
||||
|
||||
override string getCanonicalQLClass() { result = "IntPointerType" }
|
||||
override string getAPrimaryQlClass() { result = "IntPointerType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -24,7 +24,7 @@ class IntPointerType extends PointerType {
|
||||
class VoidPointerType extends PointerType {
|
||||
VoidPointerType() { this.getBaseType() instanceof VoidType }
|
||||
|
||||
override string getCanonicalQLClass() { result = "VoidPointerType" }
|
||||
override string getAPrimaryQlClass() { result = "VoidPointerType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,7 +36,7 @@ class Size_t extends Type {
|
||||
this.hasName("size_t")
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Size_t" }
|
||||
override string getAPrimaryQlClass() { result = "Size_t" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,7 +48,7 @@ class Ssize_t extends Type {
|
||||
this.hasName("ssize_t")
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Ssize_t" }
|
||||
override string getAPrimaryQlClass() { result = "Ssize_t" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,7 +60,7 @@ class Ptrdiff_t extends Type {
|
||||
this.hasName("ptrdiff_t")
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Ptrdiff_t" }
|
||||
override string getAPrimaryQlClass() { result = "Ptrdiff_t" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,7 +72,7 @@ class Intmax_t extends Type {
|
||||
this.hasName("intmax_t")
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Intmax_t" }
|
||||
override string getAPrimaryQlClass() { result = "Intmax_t" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,7 +84,7 @@ class Uintmax_t extends Type {
|
||||
this.hasName("uintmax_t")
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Uintmax_t" }
|
||||
override string getAPrimaryQlClass() { result = "Uintmax_t" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,7 +100,7 @@ class Wchar_t extends Type {
|
||||
this.hasName("wchar_t")
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Wchar_t" }
|
||||
override string getAPrimaryQlClass() { result = "Wchar_t" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,5 +176,5 @@ class MicrosoftInt64Type extends IntegralType {
|
||||
class BuiltInVarArgsList extends Type {
|
||||
BuiltInVarArgsList() { this.hasName("__builtin_va_list") }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInVarArgsList" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInVarArgsList" }
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides predicates for identifying function calls that open or close a file.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,7 +20,7 @@ class PrintfFormatAttribute extends FormatAttribute {
|
||||
* function by its use of the GNU `format` attribute.
|
||||
*/
|
||||
class AttributeFormattingFunction extends FormattingFunction {
|
||||
override string getCanonicalQLClass() { result = "AttributeFormattingFunction" }
|
||||
override string getAPrimaryQlClass() { result = "AttributeFormattingFunction" }
|
||||
|
||||
AttributeFormattingFunction() {
|
||||
exists(PrintfFormatAttribute printf_attrib |
|
||||
@@ -73,7 +73,7 @@ predicate variadicFormatter(Function f, int formatParamIndex) {
|
||||
* string and a variable number of arguments.
|
||||
*/
|
||||
class UserDefinedFormattingFunction extends FormattingFunction {
|
||||
override string getCanonicalQLClass() { result = "UserDefinedFormattingFunction" }
|
||||
override string getAPrimaryQlClass() { result = "UserDefinedFormattingFunction" }
|
||||
|
||||
UserDefinedFormattingFunction() { isVarargs() and callsVariadicFormatter(this, _) }
|
||||
|
||||
@@ -86,7 +86,7 @@ class UserDefinedFormattingFunction extends FormattingFunction {
|
||||
class FormattingFunctionCall extends Expr {
|
||||
FormattingFunctionCall() { this.(Call).getTarget() instanceof FormattingFunction }
|
||||
|
||||
override string getCanonicalQLClass() { result = "FormattingFunctionCall" }
|
||||
override string getAPrimaryQlClass() { result = "FormattingFunctionCall" }
|
||||
|
||||
/**
|
||||
* Gets the formatting function being called.
|
||||
|
||||
@@ -19,7 +19,7 @@ import DataFlowImplSpecific::Public
|
||||
* a subclass whose characteristic predicate is a unique singleton string.
|
||||
* For example, write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* class MyAnalysisConfiguration extends DataFlow::Configuration {
|
||||
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
|
||||
* // Override `isSource` and `isSink`.
|
||||
@@ -37,7 +37,7 @@ import DataFlowImplSpecific::Public
|
||||
* Then, to query whether there is flow between some `source` and `sink`,
|
||||
* write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
* ```
|
||||
*
|
||||
@@ -1051,6 +1051,17 @@ private predicate flowIntoCallNodeCand2(
|
||||
}
|
||||
|
||||
private module LocalFlowBigStep {
|
||||
/**
|
||||
* A node where some checking is required, and hence the big-step relation
|
||||
* is not allowed to step over.
|
||||
*/
|
||||
private class FlowCheckNode extends Node {
|
||||
FlowCheckNode() {
|
||||
this instanceof CastNode or
|
||||
clearsContent(this, _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` can be the first node in a maximal subsequence of local
|
||||
* flow steps in a dataflow path.
|
||||
@@ -1065,7 +1076,7 @@ private module LocalFlowBigStep {
|
||||
node instanceof OutNodeExt or
|
||||
store(_, _, node, _) or
|
||||
read(_, _, node) or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1083,7 +1094,7 @@ private module LocalFlowBigStep {
|
||||
read(node, _, next)
|
||||
)
|
||||
or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
config.isSink(node)
|
||||
}
|
||||
@@ -1127,14 +1138,14 @@ private module LocalFlowBigStep {
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
|
||||
localFlowStepNodeCand1(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
nodeCand2(node2, unbind(config))
|
||||
)
|
||||
or
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, _, _, config, cc) and
|
||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
preservesValue = false and
|
||||
t = getErasedNodeTypeBound(node2) and
|
||||
nodeCand2(node2, unbind(config))
|
||||
@@ -1190,6 +1201,7 @@ private predicate flowCandFwd(
|
||||
Configuration config
|
||||
) {
|
||||
flowCandFwd0(node, fromArg, argApf, apf, config) and
|
||||
not apf.isClearedAt(node) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
|
||||
else any()
|
||||
@@ -2564,7 +2576,7 @@ private module FlowExploration {
|
||||
|
||||
private newtype TPartialAccessPath =
|
||||
TPartialNil(DataFlowType t) or
|
||||
TPartialCons(TypedContent tc, int len) { len in [1 .. 5] }
|
||||
TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] }
|
||||
|
||||
/**
|
||||
* Conceptually a list of `TypedContent`s followed by a `Type`, but only the first
|
||||
|
||||
@@ -19,7 +19,7 @@ import DataFlowImplSpecific::Public
|
||||
* a subclass whose characteristic predicate is a unique singleton string.
|
||||
* For example, write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* class MyAnalysisConfiguration extends DataFlow::Configuration {
|
||||
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
|
||||
* // Override `isSource` and `isSink`.
|
||||
@@ -37,7 +37,7 @@ import DataFlowImplSpecific::Public
|
||||
* Then, to query whether there is flow between some `source` and `sink`,
|
||||
* write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
* ```
|
||||
*
|
||||
@@ -1051,6 +1051,17 @@ private predicate flowIntoCallNodeCand2(
|
||||
}
|
||||
|
||||
private module LocalFlowBigStep {
|
||||
/**
|
||||
* A node where some checking is required, and hence the big-step relation
|
||||
* is not allowed to step over.
|
||||
*/
|
||||
private class FlowCheckNode extends Node {
|
||||
FlowCheckNode() {
|
||||
this instanceof CastNode or
|
||||
clearsContent(this, _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` can be the first node in a maximal subsequence of local
|
||||
* flow steps in a dataflow path.
|
||||
@@ -1065,7 +1076,7 @@ private module LocalFlowBigStep {
|
||||
node instanceof OutNodeExt or
|
||||
store(_, _, node, _) or
|
||||
read(_, _, node) or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1083,7 +1094,7 @@ private module LocalFlowBigStep {
|
||||
read(node, _, next)
|
||||
)
|
||||
or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
config.isSink(node)
|
||||
}
|
||||
@@ -1127,14 +1138,14 @@ private module LocalFlowBigStep {
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
|
||||
localFlowStepNodeCand1(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
nodeCand2(node2, unbind(config))
|
||||
)
|
||||
or
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, _, _, config, cc) and
|
||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
preservesValue = false and
|
||||
t = getErasedNodeTypeBound(node2) and
|
||||
nodeCand2(node2, unbind(config))
|
||||
@@ -1190,6 +1201,7 @@ private predicate flowCandFwd(
|
||||
Configuration config
|
||||
) {
|
||||
flowCandFwd0(node, fromArg, argApf, apf, config) and
|
||||
not apf.isClearedAt(node) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
|
||||
else any()
|
||||
@@ -2564,7 +2576,7 @@ private module FlowExploration {
|
||||
|
||||
private newtype TPartialAccessPath =
|
||||
TPartialNil(DataFlowType t) or
|
||||
TPartialCons(TypedContent tc, int len) { len in [1 .. 5] }
|
||||
TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] }
|
||||
|
||||
/**
|
||||
* Conceptually a list of `TypedContent`s followed by a `Type`, but only the first
|
||||
|
||||
@@ -19,7 +19,7 @@ import DataFlowImplSpecific::Public
|
||||
* a subclass whose characteristic predicate is a unique singleton string.
|
||||
* For example, write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* class MyAnalysisConfiguration extends DataFlow::Configuration {
|
||||
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
|
||||
* // Override `isSource` and `isSink`.
|
||||
@@ -37,7 +37,7 @@ import DataFlowImplSpecific::Public
|
||||
* Then, to query whether there is flow between some `source` and `sink`,
|
||||
* write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
* ```
|
||||
*
|
||||
@@ -1051,6 +1051,17 @@ private predicate flowIntoCallNodeCand2(
|
||||
}
|
||||
|
||||
private module LocalFlowBigStep {
|
||||
/**
|
||||
* A node where some checking is required, and hence the big-step relation
|
||||
* is not allowed to step over.
|
||||
*/
|
||||
private class FlowCheckNode extends Node {
|
||||
FlowCheckNode() {
|
||||
this instanceof CastNode or
|
||||
clearsContent(this, _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` can be the first node in a maximal subsequence of local
|
||||
* flow steps in a dataflow path.
|
||||
@@ -1065,7 +1076,7 @@ private module LocalFlowBigStep {
|
||||
node instanceof OutNodeExt or
|
||||
store(_, _, node, _) or
|
||||
read(_, _, node) or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1083,7 +1094,7 @@ private module LocalFlowBigStep {
|
||||
read(node, _, next)
|
||||
)
|
||||
or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
config.isSink(node)
|
||||
}
|
||||
@@ -1127,14 +1138,14 @@ private module LocalFlowBigStep {
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
|
||||
localFlowStepNodeCand1(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
nodeCand2(node2, unbind(config))
|
||||
)
|
||||
or
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, _, _, config, cc) and
|
||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
preservesValue = false and
|
||||
t = getErasedNodeTypeBound(node2) and
|
||||
nodeCand2(node2, unbind(config))
|
||||
@@ -1190,6 +1201,7 @@ private predicate flowCandFwd(
|
||||
Configuration config
|
||||
) {
|
||||
flowCandFwd0(node, fromArg, argApf, apf, config) and
|
||||
not apf.isClearedAt(node) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
|
||||
else any()
|
||||
@@ -2564,7 +2576,7 @@ private module FlowExploration {
|
||||
|
||||
private newtype TPartialAccessPath =
|
||||
TPartialNil(DataFlowType t) or
|
||||
TPartialCons(TypedContent tc, int len) { len in [1 .. 5] }
|
||||
TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] }
|
||||
|
||||
/**
|
||||
* Conceptually a list of `TypedContent`s followed by a `Type`, but only the first
|
||||
|
||||
@@ -19,7 +19,7 @@ import DataFlowImplSpecific::Public
|
||||
* a subclass whose characteristic predicate is a unique singleton string.
|
||||
* For example, write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* class MyAnalysisConfiguration extends DataFlow::Configuration {
|
||||
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
|
||||
* // Override `isSource` and `isSink`.
|
||||
@@ -37,7 +37,7 @@ import DataFlowImplSpecific::Public
|
||||
* Then, to query whether there is flow between some `source` and `sink`,
|
||||
* write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
* ```
|
||||
*
|
||||
@@ -1051,6 +1051,17 @@ private predicate flowIntoCallNodeCand2(
|
||||
}
|
||||
|
||||
private module LocalFlowBigStep {
|
||||
/**
|
||||
* A node where some checking is required, and hence the big-step relation
|
||||
* is not allowed to step over.
|
||||
*/
|
||||
private class FlowCheckNode extends Node {
|
||||
FlowCheckNode() {
|
||||
this instanceof CastNode or
|
||||
clearsContent(this, _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` can be the first node in a maximal subsequence of local
|
||||
* flow steps in a dataflow path.
|
||||
@@ -1065,7 +1076,7 @@ private module LocalFlowBigStep {
|
||||
node instanceof OutNodeExt or
|
||||
store(_, _, node, _) or
|
||||
read(_, _, node) or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1083,7 +1094,7 @@ private module LocalFlowBigStep {
|
||||
read(node, _, next)
|
||||
)
|
||||
or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
config.isSink(node)
|
||||
}
|
||||
@@ -1127,14 +1138,14 @@ private module LocalFlowBigStep {
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
|
||||
localFlowStepNodeCand1(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
nodeCand2(node2, unbind(config))
|
||||
)
|
||||
or
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, _, _, config, cc) and
|
||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
preservesValue = false and
|
||||
t = getErasedNodeTypeBound(node2) and
|
||||
nodeCand2(node2, unbind(config))
|
||||
@@ -1190,6 +1201,7 @@ private predicate flowCandFwd(
|
||||
Configuration config
|
||||
) {
|
||||
flowCandFwd0(node, fromArg, argApf, apf, config) and
|
||||
not apf.isClearedAt(node) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
|
||||
else any()
|
||||
@@ -2564,7 +2576,7 @@ private module FlowExploration {
|
||||
|
||||
private newtype TPartialAccessPath =
|
||||
TPartialNil(DataFlowType t) or
|
||||
TPartialCons(TypedContent tc, int len) { len in [1 .. 5] }
|
||||
TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] }
|
||||
|
||||
/**
|
||||
* Conceptually a list of `TypedContent`s followed by a `Type`, but only the first
|
||||
|
||||
@@ -754,6 +754,13 @@ abstract class AccessPathFront extends TAccessPathFront {
|
||||
abstract boolean toBoolNonEmpty();
|
||||
|
||||
predicate headUsesContent(TypedContent tc) { this = TFrontHead(tc) }
|
||||
|
||||
predicate isClearedAt(Node n) {
|
||||
exists(TypedContent tc |
|
||||
this.headUsesContent(tc) and
|
||||
clearsContent(n, tc.getContent())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||
|
||||
@@ -19,7 +19,7 @@ import DataFlowImplSpecific::Public
|
||||
* a subclass whose characteristic predicate is a unique singleton string.
|
||||
* For example, write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* class MyAnalysisConfiguration extends DataFlow::Configuration {
|
||||
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
|
||||
* // Override `isSource` and `isSink`.
|
||||
@@ -37,7 +37,7 @@ import DataFlowImplSpecific::Public
|
||||
* Then, to query whether there is flow between some `source` and `sink`,
|
||||
* write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
* ```
|
||||
*
|
||||
@@ -1051,6 +1051,17 @@ private predicate flowIntoCallNodeCand2(
|
||||
}
|
||||
|
||||
private module LocalFlowBigStep {
|
||||
/**
|
||||
* A node where some checking is required, and hence the big-step relation
|
||||
* is not allowed to step over.
|
||||
*/
|
||||
private class FlowCheckNode extends Node {
|
||||
FlowCheckNode() {
|
||||
this instanceof CastNode or
|
||||
clearsContent(this, _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` can be the first node in a maximal subsequence of local
|
||||
* flow steps in a dataflow path.
|
||||
@@ -1065,7 +1076,7 @@ private module LocalFlowBigStep {
|
||||
node instanceof OutNodeExt or
|
||||
store(_, _, node, _) or
|
||||
read(_, _, node) or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1083,7 +1094,7 @@ private module LocalFlowBigStep {
|
||||
read(node, _, next)
|
||||
)
|
||||
or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
config.isSink(node)
|
||||
}
|
||||
@@ -1127,14 +1138,14 @@ private module LocalFlowBigStep {
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
|
||||
localFlowStepNodeCand1(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
nodeCand2(node2, unbind(config))
|
||||
)
|
||||
or
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, _, _, config, cc) and
|
||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
preservesValue = false and
|
||||
t = getErasedNodeTypeBound(node2) and
|
||||
nodeCand2(node2, unbind(config))
|
||||
@@ -1190,6 +1201,7 @@ private predicate flowCandFwd(
|
||||
Configuration config
|
||||
) {
|
||||
flowCandFwd0(node, fromArg, argApf, apf, config) and
|
||||
not apf.isClearedAt(node) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
|
||||
else any()
|
||||
@@ -2564,7 +2576,7 @@ private module FlowExploration {
|
||||
|
||||
private newtype TPartialAccessPath =
|
||||
TPartialNil(DataFlowType t) or
|
||||
TPartialCons(TypedContent tc, int len) { len in [1 .. 5] }
|
||||
TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] }
|
||||
|
||||
/**
|
||||
* Conceptually a list of `TypedContent`s followed by a `Type`, but only the first
|
||||
|
||||
@@ -216,6 +216,13 @@ predicate readStep(Node node1, Content f, Node node2) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if values stored inside content `c` are cleared at node `n`.
|
||||
*/
|
||||
predicate clearsContent(Node n, Content c) {
|
||||
none() // stub implementation
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a representative (boxed) type for `t` for the purpose of pruning
|
||||
* possible flow. A single type is used for all numeric types to account for
|
||||
|
||||
@@ -26,7 +26,7 @@ private import TaintTrackingParameter::Private
|
||||
* To create a configuration, extend this class with a subclass whose
|
||||
* characteristic predicate is a unique singleton string. For example, write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* class MyAnalysisConfiguration extends TaintTracking::Configuration {
|
||||
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
|
||||
* // Override `isSource` and `isSink`.
|
||||
@@ -41,7 +41,7 @@ private import TaintTrackingParameter::Private
|
||||
* Then, to query whether there is flow between some `source` and `sink`,
|
||||
* write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
* ```
|
||||
*
|
||||
|
||||
@@ -26,7 +26,7 @@ private import TaintTrackingParameter::Private
|
||||
* To create a configuration, extend this class with a subclass whose
|
||||
* characteristic predicate is a unique singleton string. For example, write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* class MyAnalysisConfiguration extends TaintTracking::Configuration {
|
||||
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
|
||||
* // Override `isSource` and `isSink`.
|
||||
@@ -41,7 +41,7 @@ private import TaintTrackingParameter::Private
|
||||
* Then, to query whether there is flow between some `source` and `sink`,
|
||||
* write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
* ```
|
||||
*
|
||||
|
||||
@@ -36,7 +36,7 @@ class Access extends Expr, NameQualifiableElement, @access {
|
||||
* ```
|
||||
*/
|
||||
class EnumConstantAccess extends Access, @varaccess {
|
||||
override string getCanonicalQLClass() { result = "EnumConstantAccess" }
|
||||
override string getAPrimaryQlClass() { result = "EnumConstantAccess" }
|
||||
|
||||
EnumConstantAccess() {
|
||||
exists(EnumConstant c | varbind(underlyingElement(this), unresolveElement(c)))
|
||||
@@ -61,7 +61,7 @@ class EnumConstantAccess extends Access, @varaccess {
|
||||
* ```
|
||||
*/
|
||||
class VariableAccess extends Access, @varaccess {
|
||||
override string getCanonicalQLClass() { result = "VariableAccess" }
|
||||
override string getAPrimaryQlClass() { result = "VariableAccess" }
|
||||
|
||||
VariableAccess() {
|
||||
not exists(EnumConstant c | varbind(underlyingElement(this), unresolveElement(c)))
|
||||
@@ -166,7 +166,7 @@ class VariableAccess extends Access, @varaccess {
|
||||
* ```
|
||||
*/
|
||||
class FieldAccess extends VariableAccess {
|
||||
override string getCanonicalQLClass() { result = "FieldAccess" }
|
||||
override string getAPrimaryQlClass() { result = "FieldAccess" }
|
||||
|
||||
FieldAccess() { exists(Field f | varbind(underlyingElement(this), unresolveElement(f))) }
|
||||
|
||||
@@ -194,7 +194,7 @@ class FieldAccess extends VariableAccess {
|
||||
* ```
|
||||
*/
|
||||
class PointerFieldAccess extends FieldAccess {
|
||||
override string getCanonicalQLClass() { result = "PointerFieldAccess" }
|
||||
override string getAPrimaryQlClass() { result = "PointerFieldAccess" }
|
||||
|
||||
PointerFieldAccess() {
|
||||
exists(PointerType t |
|
||||
@@ -211,7 +211,7 @@ class PointerFieldAccess extends FieldAccess {
|
||||
* distinguish whether or not the type of `obj` is a reference type.
|
||||
*/
|
||||
class DotFieldAccess extends FieldAccess {
|
||||
override string getCanonicalQLClass() { result = "DotFieldAccess" }
|
||||
override string getAPrimaryQlClass() { result = "DotFieldAccess" }
|
||||
|
||||
DotFieldAccess() { exists(Class c | c = getQualifier().getFullyConverted().getUnspecifiedType()) }
|
||||
}
|
||||
@@ -232,7 +232,7 @@ class DotFieldAccess extends FieldAccess {
|
||||
* ```
|
||||
*/
|
||||
class ReferenceFieldAccess extends DotFieldAccess {
|
||||
override string getCanonicalQLClass() { result = "ReferenceFieldAccess" }
|
||||
override string getAPrimaryQlClass() { result = "ReferenceFieldAccess" }
|
||||
|
||||
ReferenceFieldAccess() { exprHasReferenceConversion(this.getQualifier()) }
|
||||
}
|
||||
@@ -253,7 +253,7 @@ class ReferenceFieldAccess extends DotFieldAccess {
|
||||
* ```
|
||||
*/
|
||||
class ValueFieldAccess extends DotFieldAccess {
|
||||
override string getCanonicalQLClass() { result = "ValueFieldAccess" }
|
||||
override string getAPrimaryQlClass() { result = "ValueFieldAccess" }
|
||||
|
||||
ValueFieldAccess() { not exprHasReferenceConversion(this.getQualifier()) }
|
||||
}
|
||||
@@ -307,7 +307,7 @@ private predicate exprHasReferenceConversion(Expr e) { referenceConversion(e.get
|
||||
* `ImplicitThisFieldAccess`.
|
||||
*/
|
||||
class ImplicitThisFieldAccess extends FieldAccess {
|
||||
override string getCanonicalQLClass() { result = "ImplicitThisFieldAccess" }
|
||||
override string getAPrimaryQlClass() { result = "ImplicitThisFieldAccess" }
|
||||
|
||||
ImplicitThisFieldAccess() { not exists(this.getQualifier()) }
|
||||
}
|
||||
@@ -332,7 +332,7 @@ class PointerToFieldLiteral extends ImplicitThisFieldAccess {
|
||||
|
||||
override predicate isConstant() { any() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "PointerToFieldLiteral" }
|
||||
override string getAPrimaryQlClass() { result = "PointerToFieldLiteral" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -349,7 +349,7 @@ class PointerToFieldLiteral extends ImplicitThisFieldAccess {
|
||||
class FunctionAccess extends Access, @routineexpr {
|
||||
FunctionAccess() { not iscall(underlyingElement(this), _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "FunctionAccess" }
|
||||
override string getAPrimaryQlClass() { result = "FunctionAccess" }
|
||||
|
||||
/** Gets the accessed function. */
|
||||
override Function getTarget() { funbind(underlyingElement(this), unresolveElement(result)) }
|
||||
@@ -399,7 +399,7 @@ class ParamAccessForType extends Expr, @param_ref {
|
||||
* ```
|
||||
*/
|
||||
class TypeName extends Expr, @type_operand {
|
||||
override string getCanonicalQLClass() { result = "TypeName" }
|
||||
override string getAPrimaryQlClass() { result = "TypeName" }
|
||||
|
||||
override string toString() { result = this.getType().getName() }
|
||||
}
|
||||
@@ -418,7 +418,7 @@ class TypeName extends Expr, @type_operand {
|
||||
* `OverloadedArrayExpr`.
|
||||
*/
|
||||
class ArrayExpr extends Expr, @subscriptexpr {
|
||||
override string getCanonicalQLClass() { result = "ArrayExpr" }
|
||||
override string getAPrimaryQlClass() { result = "ArrayExpr" }
|
||||
|
||||
/**
|
||||
* Gets the array or pointer expression being subscripted.
|
||||
|
||||
@@ -14,7 +14,7 @@ class UnaryArithmeticOperation extends UnaryOperation, @un_arith_op_expr { }
|
||||
class UnaryMinusExpr extends UnaryArithmeticOperation, @arithnegexpr {
|
||||
override string getOperator() { result = "-" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "UnaryMinusExpr" }
|
||||
override string getAPrimaryQlClass() { result = "UnaryMinusExpr" }
|
||||
|
||||
override int getPrecedence() { result = 16 }
|
||||
}
|
||||
@@ -28,7 +28,7 @@ class UnaryMinusExpr extends UnaryArithmeticOperation, @arithnegexpr {
|
||||
class UnaryPlusExpr extends UnaryArithmeticOperation, @unaryplusexpr {
|
||||
override string getOperator() { result = "+" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "UnaryPlusExpr" }
|
||||
override string getAPrimaryQlClass() { result = "UnaryPlusExpr" }
|
||||
|
||||
override int getPrecedence() { result = 16 }
|
||||
}
|
||||
@@ -45,7 +45,7 @@ class UnaryPlusExpr extends UnaryArithmeticOperation, @unaryplusexpr {
|
||||
class ConjugationExpr extends UnaryArithmeticOperation, @conjugation {
|
||||
override string getOperator() { result = "~" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ConjugationExpr" }
|
||||
override string getAPrimaryQlClass() { result = "ConjugationExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +107,7 @@ class PostfixCrementOperation extends CrementOperation, @postfix_crement_expr {
|
||||
class PrefixIncrExpr extends IncrementOperation, PrefixCrementOperation, @preincrexpr {
|
||||
override string getOperator() { result = "++" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "PrefixIncrExpr" }
|
||||
override string getAPrimaryQlClass() { result = "PrefixIncrExpr" }
|
||||
|
||||
override int getPrecedence() { result = 16 }
|
||||
}
|
||||
@@ -123,7 +123,7 @@ class PrefixIncrExpr extends IncrementOperation, PrefixCrementOperation, @preinc
|
||||
class PrefixDecrExpr extends DecrementOperation, PrefixCrementOperation, @predecrexpr {
|
||||
override string getOperator() { result = "--" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "PrefixDecrExpr" }
|
||||
override string getAPrimaryQlClass() { result = "PrefixDecrExpr" }
|
||||
|
||||
override int getPrecedence() { result = 16 }
|
||||
}
|
||||
@@ -139,7 +139,7 @@ class PrefixDecrExpr extends DecrementOperation, PrefixCrementOperation, @predec
|
||||
class PostfixIncrExpr extends IncrementOperation, PostfixCrementOperation, @postincrexpr {
|
||||
override string getOperator() { result = "++" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "PostfixIncrExpr" }
|
||||
override string getAPrimaryQlClass() { result = "PostfixIncrExpr" }
|
||||
|
||||
override int getPrecedence() { result = 17 }
|
||||
|
||||
@@ -157,7 +157,7 @@ class PostfixIncrExpr extends IncrementOperation, PostfixCrementOperation, @post
|
||||
class PostfixDecrExpr extends DecrementOperation, PostfixCrementOperation, @postdecrexpr {
|
||||
override string getOperator() { result = "--" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "PostfixDecrExpr" }
|
||||
override string getAPrimaryQlClass() { result = "PostfixDecrExpr" }
|
||||
|
||||
override int getPrecedence() { result = 17 }
|
||||
|
||||
@@ -175,7 +175,7 @@ class PostfixDecrExpr extends DecrementOperation, PostfixCrementOperation, @post
|
||||
class RealPartExpr extends UnaryArithmeticOperation, @realpartexpr {
|
||||
override string getOperator() { result = "__real" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "RealPartExpr" }
|
||||
override string getAPrimaryQlClass() { result = "RealPartExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,7 +189,7 @@ class RealPartExpr extends UnaryArithmeticOperation, @realpartexpr {
|
||||
class ImaginaryPartExpr extends UnaryArithmeticOperation, @imagpartexpr {
|
||||
override string getOperator() { result = "__imag" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ImaginaryPartExpr" }
|
||||
override string getAPrimaryQlClass() { result = "ImaginaryPartExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,7 +208,7 @@ class BinaryArithmeticOperation extends BinaryOperation, @bin_arith_op_expr { }
|
||||
class AddExpr extends BinaryArithmeticOperation, @addexpr {
|
||||
override string getOperator() { result = "+" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "AddExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AddExpr" }
|
||||
|
||||
override int getPrecedence() { result = 13 }
|
||||
}
|
||||
@@ -222,7 +222,7 @@ class AddExpr extends BinaryArithmeticOperation, @addexpr {
|
||||
class SubExpr extends BinaryArithmeticOperation, @subexpr {
|
||||
override string getOperator() { result = "-" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "SubExpr" }
|
||||
override string getAPrimaryQlClass() { result = "SubExpr" }
|
||||
|
||||
override int getPrecedence() { result = 13 }
|
||||
}
|
||||
@@ -236,7 +236,7 @@ class SubExpr extends BinaryArithmeticOperation, @subexpr {
|
||||
class MulExpr extends BinaryArithmeticOperation, @mulexpr {
|
||||
override string getOperator() { result = "*" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "MulExpr" }
|
||||
override string getAPrimaryQlClass() { result = "MulExpr" }
|
||||
|
||||
override int getPrecedence() { result = 14 }
|
||||
}
|
||||
@@ -250,7 +250,7 @@ class MulExpr extends BinaryArithmeticOperation, @mulexpr {
|
||||
class DivExpr extends BinaryArithmeticOperation, @divexpr {
|
||||
override string getOperator() { result = "/" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "DivExpr" }
|
||||
override string getAPrimaryQlClass() { result = "DivExpr" }
|
||||
|
||||
override int getPrecedence() { result = 14 }
|
||||
}
|
||||
@@ -264,7 +264,7 @@ class DivExpr extends BinaryArithmeticOperation, @divexpr {
|
||||
class RemExpr extends BinaryArithmeticOperation, @remexpr {
|
||||
override string getOperator() { result = "%" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "RemExpr" }
|
||||
override string getAPrimaryQlClass() { result = "RemExpr" }
|
||||
|
||||
override int getPrecedence() { result = 14 }
|
||||
}
|
||||
@@ -281,7 +281,7 @@ class RemExpr extends BinaryArithmeticOperation, @remexpr {
|
||||
class ImaginaryMulExpr extends BinaryArithmeticOperation, @jmulexpr {
|
||||
override string getOperator() { result = "*" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ImaginaryMulExpr" }
|
||||
override string getAPrimaryQlClass() { result = "ImaginaryMulExpr" }
|
||||
|
||||
override int getPrecedence() { result = 14 }
|
||||
}
|
||||
@@ -298,7 +298,7 @@ class ImaginaryMulExpr extends BinaryArithmeticOperation, @jmulexpr {
|
||||
class ImaginaryDivExpr extends BinaryArithmeticOperation, @jdivexpr {
|
||||
override string getOperator() { result = "/" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ImaginaryDivExpr" }
|
||||
override string getAPrimaryQlClass() { result = "ImaginaryDivExpr" }
|
||||
|
||||
override int getPrecedence() { result = 14 }
|
||||
}
|
||||
@@ -316,7 +316,7 @@ class ImaginaryDivExpr extends BinaryArithmeticOperation, @jdivexpr {
|
||||
class RealImaginaryAddExpr extends BinaryArithmeticOperation, @fjaddexpr {
|
||||
override string getOperator() { result = "+" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "RealImaginaryAddExpr" }
|
||||
override string getAPrimaryQlClass() { result = "RealImaginaryAddExpr" }
|
||||
|
||||
override int getPrecedence() { result = 13 }
|
||||
}
|
||||
@@ -334,7 +334,7 @@ class RealImaginaryAddExpr extends BinaryArithmeticOperation, @fjaddexpr {
|
||||
class ImaginaryRealAddExpr extends BinaryArithmeticOperation, @jfaddexpr {
|
||||
override string getOperator() { result = "+" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ImaginaryRealAddExpr" }
|
||||
override string getAPrimaryQlClass() { result = "ImaginaryRealAddExpr" }
|
||||
|
||||
override int getPrecedence() { result = 13 }
|
||||
}
|
||||
@@ -352,7 +352,7 @@ class ImaginaryRealAddExpr extends BinaryArithmeticOperation, @jfaddexpr {
|
||||
class RealImaginarySubExpr extends BinaryArithmeticOperation, @fjsubexpr {
|
||||
override string getOperator() { result = "-" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "RealImaginarySubExpr" }
|
||||
override string getAPrimaryQlClass() { result = "RealImaginarySubExpr" }
|
||||
|
||||
override int getPrecedence() { result = 13 }
|
||||
}
|
||||
@@ -370,7 +370,7 @@ class RealImaginarySubExpr extends BinaryArithmeticOperation, @fjsubexpr {
|
||||
class ImaginaryRealSubExpr extends BinaryArithmeticOperation, @jfsubexpr {
|
||||
override string getOperator() { result = "-" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ImaginaryRealSubExpr" }
|
||||
override string getAPrimaryQlClass() { result = "ImaginaryRealSubExpr" }
|
||||
|
||||
override int getPrecedence() { result = 13 }
|
||||
}
|
||||
@@ -384,7 +384,7 @@ class ImaginaryRealSubExpr extends BinaryArithmeticOperation, @jfsubexpr {
|
||||
class MinExpr extends BinaryArithmeticOperation, @minexpr {
|
||||
override string getOperator() { result = "<?" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "MinExpr" }
|
||||
override string getAPrimaryQlClass() { result = "MinExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -396,7 +396,7 @@ class MinExpr extends BinaryArithmeticOperation, @minexpr {
|
||||
class MaxExpr extends BinaryArithmeticOperation, @maxexpr {
|
||||
override string getOperator() { result = ">?" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "MaxExpr" }
|
||||
override string getAPrimaryQlClass() { result = "MaxExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -414,7 +414,7 @@ class PointerArithmeticOperation extends BinaryArithmeticOperation, @p_arith_op_
|
||||
class PointerAddExpr extends PointerArithmeticOperation, @paddexpr {
|
||||
override string getOperator() { result = "+" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "PointerAddExpr" }
|
||||
override string getAPrimaryQlClass() { result = "PointerAddExpr" }
|
||||
|
||||
override int getPrecedence() { result = 13 }
|
||||
}
|
||||
@@ -429,7 +429,7 @@ class PointerAddExpr extends PointerArithmeticOperation, @paddexpr {
|
||||
class PointerSubExpr extends PointerArithmeticOperation, @psubexpr {
|
||||
override string getOperator() { result = "-" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "PointerSubExpr" }
|
||||
override string getAPrimaryQlClass() { result = "PointerSubExpr" }
|
||||
|
||||
override int getPrecedence() { result = 13 }
|
||||
}
|
||||
@@ -444,7 +444,7 @@ class PointerSubExpr extends PointerArithmeticOperation, @psubexpr {
|
||||
class PointerDiffExpr extends PointerArithmeticOperation, @pdiffexpr {
|
||||
override string getOperator() { result = "-" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "PointerDiffExpr" }
|
||||
override string getAPrimaryQlClass() { result = "PointerDiffExpr" }
|
||||
|
||||
override int getPrecedence() { result = 13 }
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ class Assignment extends Operation, @assign_expr {
|
||||
class AssignExpr extends Assignment, @assignexpr {
|
||||
override string getOperator() { result = "=" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "AssignExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignExpr" }
|
||||
|
||||
/** Gets a textual representation of this assignment. */
|
||||
override string toString() { result = "... = ..." }
|
||||
@@ -64,7 +64,7 @@ class AssignArithmeticOperation extends AssignOperation, @assign_arith_expr { }
|
||||
* ```
|
||||
*/
|
||||
class AssignAddExpr extends AssignArithmeticOperation, @assignaddexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignAddExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignAddExpr" }
|
||||
|
||||
override string getOperator() { result = "+=" }
|
||||
}
|
||||
@@ -76,7 +76,7 @@ class AssignAddExpr extends AssignArithmeticOperation, @assignaddexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignSubExpr extends AssignArithmeticOperation, @assignsubexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignSubExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignSubExpr" }
|
||||
|
||||
override string getOperator() { result = "-=" }
|
||||
}
|
||||
@@ -88,7 +88,7 @@ class AssignSubExpr extends AssignArithmeticOperation, @assignsubexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignMulExpr extends AssignArithmeticOperation, @assignmulexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignMulExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignMulExpr" }
|
||||
|
||||
override string getOperator() { result = "*=" }
|
||||
}
|
||||
@@ -100,7 +100,7 @@ class AssignMulExpr extends AssignArithmeticOperation, @assignmulexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignDivExpr extends AssignArithmeticOperation, @assigndivexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignDivExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignDivExpr" }
|
||||
|
||||
override string getOperator() { result = "/=" }
|
||||
}
|
||||
@@ -112,7 +112,7 @@ class AssignDivExpr extends AssignArithmeticOperation, @assigndivexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignRemExpr extends AssignArithmeticOperation, @assignremexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignRemExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignRemExpr" }
|
||||
|
||||
override string getOperator() { result = "%=" }
|
||||
}
|
||||
@@ -130,7 +130,7 @@ class AssignBitwiseOperation extends AssignOperation, @assign_bitwise_expr { }
|
||||
* ```
|
||||
*/
|
||||
class AssignAndExpr extends AssignBitwiseOperation, @assignandexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignAndExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignAndExpr" }
|
||||
|
||||
override string getOperator() { result = "&=" }
|
||||
}
|
||||
@@ -142,7 +142,7 @@ class AssignAndExpr extends AssignBitwiseOperation, @assignandexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignOrExpr extends AssignBitwiseOperation, @assignorexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignOrExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignOrExpr" }
|
||||
|
||||
override string getOperator() { result = "|=" }
|
||||
}
|
||||
@@ -154,7 +154,7 @@ class AssignOrExpr extends AssignBitwiseOperation, @assignorexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignXorExpr extends AssignBitwiseOperation, @assignxorexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignXorExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignXorExpr" }
|
||||
|
||||
override string getOperator() { result = "^=" }
|
||||
}
|
||||
@@ -166,7 +166,7 @@ class AssignXorExpr extends AssignBitwiseOperation, @assignxorexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignLShiftExpr extends AssignBitwiseOperation, @assignlshiftexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignLShiftExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignLShiftExpr" }
|
||||
|
||||
override string getOperator() { result = "<<=" }
|
||||
}
|
||||
@@ -178,7 +178,7 @@ class AssignLShiftExpr extends AssignBitwiseOperation, @assignlshiftexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignRShiftExpr extends AssignBitwiseOperation, @assignrshiftexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignRShiftExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignRShiftExpr" }
|
||||
|
||||
override string getOperator() { result = ">>=" }
|
||||
}
|
||||
@@ -190,7 +190,7 @@ class AssignRShiftExpr extends AssignBitwiseOperation, @assignrshiftexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignPointerAddExpr extends AssignOperation, @assignpaddexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignPointerAddExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignPointerAddExpr" }
|
||||
|
||||
override string getOperator() { result = "+=" }
|
||||
}
|
||||
@@ -202,7 +202,7 @@ class AssignPointerAddExpr extends AssignOperation, @assignpaddexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignPointerSubExpr extends AssignOperation, @assignpsubexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignPointerSubExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignPointerSubExpr" }
|
||||
|
||||
override string getOperator() { result = "-=" }
|
||||
}
|
||||
@@ -227,7 +227,7 @@ class ConditionDeclExpr extends Expr, @condition_decl {
|
||||
*/
|
||||
deprecated Expr getExpr() { result = this.getChild(0) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ConditionDeclExpr" }
|
||||
override string getAPrimaryQlClass() { result = "ConditionDeclExpr" }
|
||||
|
||||
/**
|
||||
* Gets the compiler-generated variable access that conceptually occurs after
|
||||
|
||||
@@ -16,7 +16,7 @@ class ComplementExpr extends UnaryBitwiseOperation, @complementexpr {
|
||||
|
||||
override int getPrecedence() { result = 16 }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ComplementExpr" }
|
||||
override string getAPrimaryQlClass() { result = "ComplementExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,7 +35,7 @@ class LShiftExpr extends BinaryBitwiseOperation, @lshiftexpr {
|
||||
|
||||
override int getPrecedence() { result = 12 }
|
||||
|
||||
override string getCanonicalQLClass() { result = "LShiftExpr" }
|
||||
override string getAPrimaryQlClass() { result = "LShiftExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,7 +49,7 @@ class RShiftExpr extends BinaryBitwiseOperation, @rshiftexpr {
|
||||
|
||||
override int getPrecedence() { result = 12 }
|
||||
|
||||
override string getCanonicalQLClass() { result = "RShiftExpr" }
|
||||
override string getAPrimaryQlClass() { result = "RShiftExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,7 +63,7 @@ class BitwiseAndExpr extends BinaryBitwiseOperation, @andexpr {
|
||||
|
||||
override int getPrecedence() { result = 8 }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BitwiseAndExpr" }
|
||||
override string getAPrimaryQlClass() { result = "BitwiseAndExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,7 +77,7 @@ class BitwiseOrExpr extends BinaryBitwiseOperation, @orexpr {
|
||||
|
||||
override int getPrecedence() { result = 6 }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BitwiseOrExpr" }
|
||||
override string getAPrimaryQlClass() { result = "BitwiseOrExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,5 +91,5 @@ class BitwiseXorExpr extends BinaryBitwiseOperation, @xorexpr {
|
||||
|
||||
override int getPrecedence() { result = 7 }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BitwiseXorExpr" }
|
||||
override string getAPrimaryQlClass() { result = "BitwiseXorExpr" }
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import semmle.code.cpp.exprs.Expr
|
||||
* built-in functionality.
|
||||
*/
|
||||
class BuiltInOperation extends Expr, @builtin_op {
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperation" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperation" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -25,7 +25,7 @@ class VarArgsExpr extends BuiltInOperation, @var_args_expr { }
|
||||
class BuiltInVarArgsStart extends BuiltInOperation, @vastartexpr {
|
||||
override string toString() { result = "__builtin_va_start" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInVarArgsStart" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInVarArgsStart" }
|
||||
|
||||
/**
|
||||
* Gets the `va_list` argument.
|
||||
@@ -50,7 +50,7 @@ class BuiltInVarArgsStart extends BuiltInOperation, @vastartexpr {
|
||||
class BuiltInVarArgsEnd extends BuiltInOperation, @vaendexpr {
|
||||
override string toString() { result = "__builtin_va_end" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInVarArgsEnd" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInVarArgsEnd" }
|
||||
|
||||
/**
|
||||
* Gets the `va_list` argument.
|
||||
@@ -68,7 +68,7 @@ class BuiltInVarArgsEnd extends BuiltInOperation, @vaendexpr {
|
||||
class BuiltInVarArg extends BuiltInOperation, @vaargexpr {
|
||||
override string toString() { result = "__builtin_va_arg" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInVarArg" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInVarArg" }
|
||||
|
||||
/**
|
||||
* Gets the `va_list` argument.
|
||||
@@ -88,7 +88,7 @@ class BuiltInVarArg extends BuiltInOperation, @vaargexpr {
|
||||
class BuiltInVarArgCopy extends BuiltInOperation, @vacopyexpr {
|
||||
override string toString() { result = "__builtin_va_copy" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInVarArgCopy" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInVarArgCopy" }
|
||||
|
||||
/**
|
||||
* Gets the destination `va_list` argument.
|
||||
@@ -110,7 +110,7 @@ class BuiltInVarArgCopy extends BuiltInOperation, @vacopyexpr {
|
||||
class BuiltInNoOp extends BuiltInOperation, @noopexpr {
|
||||
override string toString() { result = "__noop" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInNoOp" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInNoOp" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,7 +132,7 @@ deprecated class BuiltInOperationOffsetOf = BuiltInOperationBuiltInOffsetOf;
|
||||
class BuiltInOperationBuiltInOffsetOf extends BuiltInOperation, @offsetofexpr {
|
||||
override string toString() { result = "__builtin_offsetof" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationBuiltInOffsetOf" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInOffsetOf" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,7 +149,7 @@ class BuiltInOperationBuiltInOffsetOf extends BuiltInOperation, @offsetofexpr {
|
||||
class BuiltInIntAddr extends BuiltInOperation, @intaddrexpr {
|
||||
override string toString() { result = "__INTADDR__" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInIntAddr" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInIntAddr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,7 +164,7 @@ class BuiltInIntAddr extends BuiltInOperation, @intaddrexpr {
|
||||
class BuiltInOperationHasAssign extends BuiltInOperation, @hasassignexpr {
|
||||
override string toString() { result = "__has_assign" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationHasAssign" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationHasAssign" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,7 +179,7 @@ class BuiltInOperationHasAssign extends BuiltInOperation, @hasassignexpr {
|
||||
class BuiltInOperationHasCopy extends BuiltInOperation, @hascopyexpr {
|
||||
override string toString() { result = "__has_copy" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationHasCopy" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationHasCopy" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,7 +195,7 @@ class BuiltInOperationHasCopy extends BuiltInOperation, @hascopyexpr {
|
||||
class BuiltInOperationHasNoThrowAssign extends BuiltInOperation, @hasnothrowassign {
|
||||
override string toString() { result = "__has_nothrow_assign" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationHasNoThrowAssign" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationHasNoThrowAssign" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,7 +211,7 @@ class BuiltInOperationHasNoThrowAssign extends BuiltInOperation, @hasnothrowassi
|
||||
class BuiltInOperationHasNoThrowConstructor extends BuiltInOperation, @hasnothrowconstr {
|
||||
override string toString() { result = "__has_nothrow_constructor" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationHasNoThrowConstructor" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationHasNoThrowConstructor" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -226,7 +226,7 @@ class BuiltInOperationHasNoThrowConstructor extends BuiltInOperation, @hasnothro
|
||||
class BuiltInOperationHasNoThrowCopy extends BuiltInOperation, @hasnothrowcopy {
|
||||
override string toString() { result = "__has_nothrow_copy" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationHasNoThrowCopy" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationHasNoThrowCopy" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -242,7 +242,7 @@ class BuiltInOperationHasNoThrowCopy extends BuiltInOperation, @hasnothrowcopy {
|
||||
class BuiltInOperationHasTrivialAssign extends BuiltInOperation, @hastrivialassign {
|
||||
override string toString() { result = "__has_trivial_assign" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationHasTrivialAssign" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationHasTrivialAssign" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -257,7 +257,7 @@ class BuiltInOperationHasTrivialAssign extends BuiltInOperation, @hastrivialassi
|
||||
class BuiltInOperationHasTrivialConstructor extends BuiltInOperation, @hastrivialconstr {
|
||||
override string toString() { result = "__has_trivial_constructor" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationHasTrivialConstructor" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationHasTrivialConstructor" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,7 +272,7 @@ class BuiltInOperationHasTrivialConstructor extends BuiltInOperation, @hastrivia
|
||||
class BuiltInOperationHasTrivialCopy extends BuiltInOperation, @hastrivialcopy {
|
||||
override string toString() { result = "__has_trivial_copy" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationHasTrivialCopy" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationHasTrivialCopy" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -287,7 +287,7 @@ class BuiltInOperationHasTrivialCopy extends BuiltInOperation, @hastrivialcopy {
|
||||
class BuiltInOperationHasTrivialDestructor extends BuiltInOperation, @hastrivialdestructor {
|
||||
override string toString() { result = "__has_trivial_destructor" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationHasTrivialDestructor" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationHasTrivialDestructor" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -302,7 +302,7 @@ class BuiltInOperationHasTrivialDestructor extends BuiltInOperation, @hastrivial
|
||||
class BuiltInOperationHasUserDestructor extends BuiltInOperation, @hasuserdestr {
|
||||
override string toString() { result = "__has_user_destructor" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationHasUserDestructor" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationHasUserDestructor" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -320,7 +320,7 @@ class BuiltInOperationHasUserDestructor extends BuiltInOperation, @hasuserdestr
|
||||
class BuiltInOperationHasVirtualDestructor extends BuiltInOperation, @hasvirtualdestr {
|
||||
override string toString() { result = "__has_virtual_destructor" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationHasVirtualDestructor" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationHasVirtualDestructor" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -335,7 +335,7 @@ class BuiltInOperationHasVirtualDestructor extends BuiltInOperation, @hasvirtual
|
||||
class BuiltInOperationIsAbstract extends BuiltInOperation, @isabstractexpr {
|
||||
override string toString() { result = "__is_abstract" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsAbstract" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsAbstract" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -350,7 +350,7 @@ class BuiltInOperationIsAbstract extends BuiltInOperation, @isabstractexpr {
|
||||
class BuiltInOperationIsBaseOf extends BuiltInOperation, @isbaseofexpr {
|
||||
override string toString() { result = "__is_base_of" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsBaseOf" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsBaseOf" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -365,7 +365,7 @@ class BuiltInOperationIsBaseOf extends BuiltInOperation, @isbaseofexpr {
|
||||
class BuiltInOperationIsClass extends BuiltInOperation, @isclassexpr {
|
||||
override string toString() { result = "__is_class" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsClass" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsClass" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -380,7 +380,7 @@ class BuiltInOperationIsClass extends BuiltInOperation, @isclassexpr {
|
||||
class BuiltInOperationIsConvertibleTo extends BuiltInOperation, @isconvtoexpr {
|
||||
override string toString() { result = "__is_convertible_to" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsConvertibleTo" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsConvertibleTo" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -395,7 +395,7 @@ class BuiltInOperationIsConvertibleTo extends BuiltInOperation, @isconvtoexpr {
|
||||
class BuiltInOperationIsEmpty extends BuiltInOperation, @isemptyexpr {
|
||||
override string toString() { result = "__is_empty" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsEmpty" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsEmpty" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -410,7 +410,7 @@ class BuiltInOperationIsEmpty extends BuiltInOperation, @isemptyexpr {
|
||||
class BuiltInOperationIsEnum extends BuiltInOperation, @isenumexpr {
|
||||
override string toString() { result = "__is_enum" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsEnum" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsEnum" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -427,7 +427,7 @@ class BuiltInOperationIsEnum extends BuiltInOperation, @isenumexpr {
|
||||
class BuiltInOperationIsPod extends BuiltInOperation, @ispodexpr {
|
||||
override string toString() { result = "__is_pod" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsPod" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsPod" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -442,7 +442,7 @@ class BuiltInOperationIsPod extends BuiltInOperation, @ispodexpr {
|
||||
class BuiltInOperationIsPolymorphic extends BuiltInOperation, @ispolyexpr {
|
||||
override string toString() { result = "__is_polymorphic" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsPolymorphic" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsPolymorphic" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -457,7 +457,7 @@ class BuiltInOperationIsPolymorphic extends BuiltInOperation, @ispolyexpr {
|
||||
class BuiltInOperationIsUnion extends BuiltInOperation, @isunionexpr {
|
||||
override string toString() { result = "__is_union" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsUnion" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsUnion" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -496,7 +496,7 @@ class BuiltInOperationBuiltInTypesCompatibleP extends BuiltInOperation, @typesco
|
||||
class BuiltInOperationBuiltInShuffleVector extends BuiltInOperation, @builtinshufflevector {
|
||||
override string toString() { result = "__builtin_shufflevector" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationBuiltInShuffleVector" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInShuffleVector" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -516,7 +516,7 @@ class BuiltInOperationBuiltInShuffleVector extends BuiltInOperation, @builtinshu
|
||||
class BuiltInOperationBuiltInConvertVector extends BuiltInOperation, @builtinconvertvector {
|
||||
override string toString() { result = "__builtin_convertvector" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationBuiltInConvertVector" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInConvertVector" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -538,7 +538,7 @@ class BuiltInOperationBuiltInAddressOf extends UnaryOperation, BuiltInOperation,
|
||||
result = this.getOperand().(ReferenceDereferenceExpr).getChild(0).(Access).getTarget()
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationBuiltInAddressOf" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInAddressOf" }
|
||||
|
||||
override string getOperator() { result = "__builtin_addressof" }
|
||||
}
|
||||
@@ -560,7 +560,7 @@ class BuiltInOperationIsTriviallyConstructible extends BuiltInOperation,
|
||||
@istriviallyconstructibleexpr {
|
||||
override string toString() { result = "__is_trivially_constructible" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsTriviallyConstructible" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyConstructible" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -577,7 +577,7 @@ class BuiltInOperationIsTriviallyConstructible extends BuiltInOperation,
|
||||
class BuiltInOperationIsDestructible extends BuiltInOperation, @isdestructibleexpr {
|
||||
override string toString() { result = "__is_destructible" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsDestructible" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsDestructible" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -594,7 +594,7 @@ class BuiltInOperationIsDestructible extends BuiltInOperation, @isdestructibleex
|
||||
class BuiltInOperationIsNothrowDestructible extends BuiltInOperation, @isnothrowdestructibleexpr {
|
||||
override string toString() { result = "__is_nothrow_destructible" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsNothrowDestructible" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsNothrowDestructible" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -610,7 +610,7 @@ class BuiltInOperationIsNothrowDestructible extends BuiltInOperation, @isnothrow
|
||||
class BuiltInOperationIsTriviallyDestructible extends BuiltInOperation, @istriviallydestructibleexpr {
|
||||
override string toString() { result = "__is_trivially_destructible" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsTriviallyDestructible" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyDestructible" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -629,7 +629,7 @@ class BuiltInOperationIsTriviallyDestructible extends BuiltInOperation, @istrivi
|
||||
class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istriviallyassignableexpr {
|
||||
override string toString() { result = "__is_trivially_assignable" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsTriviallyAssignable" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyAssignable" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -645,7 +645,7 @@ class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istrivial
|
||||
class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowassignableexpr {
|
||||
override string toString() { result = "__is_nothrow_assignable" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsNothrowAssignable" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsNothrowAssignable" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -665,7 +665,7 @@ class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowas
|
||||
class BuiltInOperationIsStandardLayout extends BuiltInOperation, @isstandardlayoutexpr {
|
||||
override string toString() { result = "__is_standard_layout" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsStandardLayout" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsStandardLayout" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -679,7 +679,7 @@ class BuiltInOperationIsStandardLayout extends BuiltInOperation, @isstandardlayo
|
||||
class BuiltInOperationIsTriviallyCopyable extends BuiltInOperation, @istriviallycopyableexpr {
|
||||
override string toString() { result = "__is_trivially_copyable" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsTriviallyCopyable" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyCopyable" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -699,7 +699,7 @@ class BuiltInOperationIsTriviallyCopyable extends BuiltInOperation, @istrivially
|
||||
class BuiltInOperationIsLiteralType extends BuiltInOperation, @isliteraltypeexpr {
|
||||
override string toString() { result = "__is_literal_type" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsLiteralType" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsLiteralType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -717,7 +717,7 @@ class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation,
|
||||
@hastrivialmoveconstructorexpr {
|
||||
override string toString() { result = "__has_trivial_move_constructor" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationHasTrivialMoveConstructor" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationHasTrivialMoveConstructor" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -735,7 +735,7 @@ class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation,
|
||||
class BuiltInOperationHasTrivialMoveAssign extends BuiltInOperation, @hastrivialmoveassignexpr {
|
||||
override string toString() { result = "__has_trivial_move_assign" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationHasTrivialMoveAssign" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationHasTrivialMoveAssign" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -751,7 +751,7 @@ class BuiltInOperationHasTrivialMoveAssign extends BuiltInOperation, @hastrivial
|
||||
class BuiltInOperationHasNothrowMoveAssign extends BuiltInOperation, @hasnothrowmoveassignexpr {
|
||||
override string toString() { result = "__has_nothrow_move_assign" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationHasNothrowMoveAssign" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationHasNothrowMoveAssign" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -770,7 +770,7 @@ class BuiltInOperationHasNothrowMoveAssign extends BuiltInOperation, @hasnothrow
|
||||
class BuiltInOperationIsConstructible extends BuiltInOperation, @isconstructibleexpr {
|
||||
override string toString() { result = "__is_constructible" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsConstructible" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsConstructible" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -786,7 +786,7 @@ class BuiltInOperationIsConstructible extends BuiltInOperation, @isconstructible
|
||||
class BuiltInOperationIsNothrowConstructible extends BuiltInOperation, @isnothrowconstructibleexpr {
|
||||
override string toString() { result = "__is_nothrow_constructible" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsNothrowConstructible" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsNothrowConstructible" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -801,7 +801,7 @@ class BuiltInOperationIsNothrowConstructible extends BuiltInOperation, @isnothro
|
||||
class BuiltInOperationHasFinalizer extends BuiltInOperation, @hasfinalizerexpr {
|
||||
override string toString() { result = "__has_finalizer" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationHasFinalizer" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationHasFinalizer" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -815,7 +815,7 @@ class BuiltInOperationHasFinalizer extends BuiltInOperation, @hasfinalizerexpr {
|
||||
class BuiltInOperationIsDelegate extends BuiltInOperation, @isdelegateexpr {
|
||||
override string toString() { result = "__is_delegate" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsDelegate" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsDelegate" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -828,7 +828,7 @@ class BuiltInOperationIsDelegate extends BuiltInOperation, @isdelegateexpr {
|
||||
class BuiltInOperationIsInterfaceClass extends BuiltInOperation, @isinterfaceclassexpr {
|
||||
override string toString() { result = "__is_interface_class" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsInterfaceClass" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsInterfaceClass" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -845,7 +845,7 @@ class BuiltInOperationIsInterfaceClass extends BuiltInOperation, @isinterfacecla
|
||||
class BuiltInOperationIsRefArray extends BuiltInOperation, @isrefarrayexpr {
|
||||
override string toString() { result = "__is_ref_array" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsRefArray" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsRefArray" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -862,7 +862,7 @@ class BuiltInOperationIsRefArray extends BuiltInOperation, @isrefarrayexpr {
|
||||
class BuiltInOperationIsRefClass extends BuiltInOperation, @isrefclassexpr {
|
||||
override string toString() { result = "__is_ref_class" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsRefClass" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsRefClass" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -880,7 +880,7 @@ class BuiltInOperationIsRefClass extends BuiltInOperation, @isrefclassexpr {
|
||||
class BuiltInOperationIsSealed extends BuiltInOperation, @issealedexpr {
|
||||
override string toString() { result = "__is_sealed" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsSealed" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsSealed" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -899,7 +899,7 @@ class BuiltInOperationIsSealed extends BuiltInOperation, @issealedexpr {
|
||||
class BuiltInOperationIsSimpleValueClass extends BuiltInOperation, @issimplevalueclassexpr {
|
||||
override string toString() { result = "__is_simple_value_class" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsSimpleValueClass" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsSimpleValueClass" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -916,7 +916,7 @@ class BuiltInOperationIsSimpleValueClass extends BuiltInOperation, @issimplevalu
|
||||
class BuiltInOperationIsValueClass extends BuiltInOperation, @isvalueclassexpr {
|
||||
override string toString() { result = "__is_value_class" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsValueClass" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsValueClass" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -934,7 +934,7 @@ class BuiltInOperationIsValueClass extends BuiltInOperation, @isvalueclassexpr {
|
||||
class BuiltInOperationIsFinal extends BuiltInOperation, @isfinalexpr {
|
||||
override string toString() { result = "__is_final" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperationIsFinal" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsFinal" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -949,7 +949,7 @@ class BuiltInOperationIsFinal extends BuiltInOperation, @isfinalexpr {
|
||||
class BuiltInChooseExpr extends BuiltInOperation, @builtinchooseexpr {
|
||||
override string toString() { result = "__builtin_choose_expr" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInChooseExpr" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInChooseExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -966,7 +966,7 @@ class BuiltInChooseExpr extends BuiltInOperation, @builtinchooseexpr {
|
||||
class VectorFillOperation extends UnaryOperation, @vec_fill {
|
||||
override string getOperator() { result = "(vector fill)" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "VectorFillOperation" }
|
||||
override string getAPrimaryQlClass() { result = "VectorFillOperation" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -975,7 +975,7 @@ class VectorFillOperation extends UnaryOperation, @vec_fill {
|
||||
class BuiltInComplexOperation extends BuiltInOperation, @builtincomplex {
|
||||
override string toString() { result = "__builtin_complex" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInComplexOperation" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInComplexOperation" }
|
||||
|
||||
/** Gets the operand corresponding to the real part of the complex number. */
|
||||
Expr getRealOperand() { this.hasChild(result, 0) }
|
||||
|
||||
@@ -148,7 +148,7 @@ abstract class Call extends Expr, NameQualifiableElement {
|
||||
class FunctionCall extends Call, @funbindexpr {
|
||||
FunctionCall() { iscall(underlyingElement(this), _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "FunctionCall" }
|
||||
override string getAPrimaryQlClass() { result = "FunctionCall" }
|
||||
|
||||
/** Gets an explicit template argument for this call. */
|
||||
Locatable getAnExplicitTemplateArgument() { result = getExplicitTemplateArgument(_) }
|
||||
@@ -297,7 +297,7 @@ class OverloadedPointerDereferenceExpr extends FunctionCall {
|
||||
getTarget().getEffectiveNumberOfParameters() = 1
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "OverloadedPointerDereferenceExpr" }
|
||||
override string getAPrimaryQlClass() { result = "OverloadedPointerDereferenceExpr" }
|
||||
|
||||
/**
|
||||
* Gets the expression this operator * applies to.
|
||||
@@ -345,7 +345,7 @@ class OverloadedPointerDereferenceExpr extends FunctionCall {
|
||||
class OverloadedArrayExpr extends FunctionCall {
|
||||
OverloadedArrayExpr() { getTarget().hasName("operator[]") }
|
||||
|
||||
override string getCanonicalQLClass() { result = "OverloadedArrayExpr" }
|
||||
override string getAPrimaryQlClass() { result = "OverloadedArrayExpr" }
|
||||
|
||||
/**
|
||||
* Gets the expression being subscripted.
|
||||
@@ -377,7 +377,7 @@ class ExprCall extends Call, @callexpr {
|
||||
*/
|
||||
Expr getExpr() { result = this.getChild(0) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ExprCall" }
|
||||
override string getAPrimaryQlClass() { result = "ExprCall" }
|
||||
|
||||
override Expr getAnArgument() { exists(int i | result = this.getChild(i) and i >= 1) }
|
||||
|
||||
@@ -401,7 +401,7 @@ class ExprCall extends Call, @callexpr {
|
||||
class VariableCall extends ExprCall {
|
||||
VariableCall() { this.getExpr() instanceof VariableAccess }
|
||||
|
||||
override string getCanonicalQLClass() { result = "VariableCall" }
|
||||
override string getAPrimaryQlClass() { result = "VariableCall" }
|
||||
|
||||
/**
|
||||
* Gets the variable which yields the function pointer to call.
|
||||
@@ -419,7 +419,7 @@ class VariableCall extends ExprCall {
|
||||
class ConstructorCall extends FunctionCall {
|
||||
ConstructorCall() { super.getTarget() instanceof Constructor }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ConstructorCall" }
|
||||
override string getAPrimaryQlClass() { result = "ConstructorCall" }
|
||||
|
||||
/** Gets the constructor being called. */
|
||||
override Constructor getTarget() { result = super.getTarget() }
|
||||
@@ -438,7 +438,7 @@ class ThrowExpr extends Expr, @throw_expr {
|
||||
*/
|
||||
Expr getExpr() { result = this.getChild(0) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ThrowExpr" }
|
||||
override string getAPrimaryQlClass() { result = "ThrowExpr" }
|
||||
|
||||
override string toString() { result = "throw ..." }
|
||||
|
||||
@@ -454,7 +454,7 @@ class ThrowExpr extends Expr, @throw_expr {
|
||||
class ReThrowExpr extends ThrowExpr {
|
||||
ReThrowExpr() { this.getType() instanceof VoidType }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ReThrowExpr" }
|
||||
override string getAPrimaryQlClass() { result = "ReThrowExpr" }
|
||||
|
||||
override string toString() { result = "re-throw exception " }
|
||||
}
|
||||
@@ -469,7 +469,7 @@ class ReThrowExpr extends ThrowExpr {
|
||||
class DestructorCall extends FunctionCall {
|
||||
DestructorCall() { super.getTarget() instanceof Destructor }
|
||||
|
||||
override string getCanonicalQLClass() { result = "DestructorCall" }
|
||||
override string getAPrimaryQlClass() { result = "DestructorCall" }
|
||||
|
||||
/** Gets the destructor being called. */
|
||||
override Destructor getTarget() { result = super.getTarget() }
|
||||
@@ -493,7 +493,7 @@ class VacuousDestructorCall extends Expr, @vacuous_destructor_call {
|
||||
*/
|
||||
Expr getQualifier() { result = this.getChild(0) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "VacuousDestructorCall" }
|
||||
override string getAPrimaryQlClass() { result = "VacuousDestructorCall" }
|
||||
|
||||
override string toString() { result = "(vacuous destructor call)" }
|
||||
}
|
||||
@@ -506,7 +506,7 @@ class VacuousDestructorCall extends Expr, @vacuous_destructor_call {
|
||||
* initializations.
|
||||
*/
|
||||
class ConstructorInit extends Expr, @ctorinit {
|
||||
override string getCanonicalQLClass() { result = "ConstructorInit" }
|
||||
override string getAPrimaryQlClass() { result = "ConstructorInit" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -514,7 +514,7 @@ class ConstructorInit extends Expr, @ctorinit {
|
||||
* initializer list or compiler-generated actions.
|
||||
*/
|
||||
class ConstructorBaseInit extends ConstructorInit, ConstructorCall {
|
||||
override string getCanonicalQLClass() { result = "ConstructorBaseInit" }
|
||||
override string getAPrimaryQlClass() { result = "ConstructorBaseInit" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -531,7 +531,7 @@ class ConstructorBaseInit extends ConstructorInit, ConstructorCall {
|
||||
* ```
|
||||
*/
|
||||
class ConstructorDirectInit extends ConstructorBaseInit, @ctordirectinit {
|
||||
override string getCanonicalQLClass() { result = "ConstructorDirectInit" }
|
||||
override string getAPrimaryQlClass() { result = "ConstructorDirectInit" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -551,7 +551,7 @@ class ConstructorDirectInit extends ConstructorBaseInit, @ctordirectinit {
|
||||
* ```
|
||||
*/
|
||||
class ConstructorVirtualInit extends ConstructorBaseInit, @ctorvirtualinit {
|
||||
override string getCanonicalQLClass() { result = "ConstructorVirtualInit" }
|
||||
override string getAPrimaryQlClass() { result = "ConstructorVirtualInit" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -566,7 +566,7 @@ class ConstructorVirtualInit extends ConstructorBaseInit, @ctorvirtualinit {
|
||||
* ```
|
||||
*/
|
||||
class ConstructorDelegationInit extends ConstructorBaseInit, @ctordelegatinginit {
|
||||
override string getCanonicalQLClass() { result = "ConstructorDelegationInit" }
|
||||
override string getAPrimaryQlClass() { result = "ConstructorDelegationInit" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -585,7 +585,7 @@ class ConstructorFieldInit extends ConstructorInit, @ctorfieldinit {
|
||||
/** Gets the field being initialized. */
|
||||
Field getTarget() { varbind(underlyingElement(this), unresolveElement(result)) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ConstructorFieldInit" }
|
||||
override string getAPrimaryQlClass() { result = "ConstructorFieldInit" }
|
||||
|
||||
/**
|
||||
* Gets the expression to which the field is initialized.
|
||||
@@ -607,7 +607,7 @@ class ConstructorFieldInit extends ConstructorInit, @ctorfieldinit {
|
||||
* compiler-generated actions.
|
||||
*/
|
||||
class DestructorDestruction extends Expr, @dtordestruct {
|
||||
override string getCanonicalQLClass() { result = "DestructorDestruction" }
|
||||
override string getAPrimaryQlClass() { result = "DestructorDestruction" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -615,7 +615,7 @@ class DestructorDestruction extends Expr, @dtordestruct {
|
||||
* compiler-generated actions.
|
||||
*/
|
||||
class DestructorBaseDestruction extends DestructorCall, DestructorDestruction {
|
||||
override string getCanonicalQLClass() { result = "DestructorBaseDestruction" }
|
||||
override string getAPrimaryQlClass() { result = "DestructorBaseDestruction" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -629,7 +629,7 @@ class DestructorBaseDestruction extends DestructorCall, DestructorDestruction {
|
||||
* ```
|
||||
*/
|
||||
class DestructorDirectDestruction extends DestructorBaseDestruction, @dtordirectdestruct {
|
||||
override string getCanonicalQLClass() { result = "DestructorDirectDestruction" }
|
||||
override string getAPrimaryQlClass() { result = "DestructorDirectDestruction" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -646,7 +646,7 @@ class DestructorDirectDestruction extends DestructorBaseDestruction, @dtordirect
|
||||
* ```
|
||||
*/
|
||||
class DestructorVirtualDestruction extends DestructorBaseDestruction, @dtorvirtualdestruct {
|
||||
override string getCanonicalQLClass() { result = "DestructorVirtualDestruction" }
|
||||
override string getAPrimaryQlClass() { result = "DestructorVirtualDestruction" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -664,7 +664,7 @@ class DestructorFieldDestruction extends DestructorDestruction, @dtorfielddestru
|
||||
/** Gets the field being destructed. */
|
||||
Field getTarget() { varbind(underlyingElement(this), unresolveElement(result)) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "DestructorFieldDestruction" }
|
||||
override string getAPrimaryQlClass() { result = "DestructorFieldDestruction" }
|
||||
|
||||
/** Gets the compiler-generated call to the variable's destructor. */
|
||||
DestructorCall getExpr() { result = this.getChild(0) }
|
||||
|
||||
@@ -92,7 +92,7 @@ module CastConsistency {
|
||||
class CStyleCast extends Cast, @c_style_cast {
|
||||
override string toString() { result = "(" + this.getType().getName() + ")..." }
|
||||
|
||||
override string getCanonicalQLClass() { result = "CStyleCast" }
|
||||
override string getAPrimaryQlClass() { result = "CStyleCast" }
|
||||
|
||||
override int getPrecedence() { result = 16 }
|
||||
}
|
||||
@@ -111,7 +111,7 @@ class CStyleCast extends Cast, @c_style_cast {
|
||||
class StaticCast extends Cast, @static_cast {
|
||||
override string toString() { result = "static_cast<" + this.getType().getName() + ">..." }
|
||||
|
||||
override string getCanonicalQLClass() { result = "StaticCast" }
|
||||
override string getAPrimaryQlClass() { result = "StaticCast" }
|
||||
|
||||
override int getPrecedence() { result = 17 }
|
||||
}
|
||||
@@ -129,7 +129,7 @@ class StaticCast extends Cast, @static_cast {
|
||||
class ConstCast extends Cast, @const_cast {
|
||||
override string toString() { result = "const_cast<" + this.getType().getName() + ">..." }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ConstCast" }
|
||||
override string getAPrimaryQlClass() { result = "ConstCast" }
|
||||
|
||||
override int getPrecedence() { result = 17 }
|
||||
}
|
||||
@@ -147,7 +147,7 @@ class ConstCast extends Cast, @const_cast {
|
||||
class ReinterpretCast extends Cast, @reinterpret_cast {
|
||||
override string toString() { result = "reinterpret_cast<" + this.getType().getName() + ">..." }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ReinterpretCast" }
|
||||
override string getAPrimaryQlClass() { result = "ReinterpretCast" }
|
||||
|
||||
override int getPrecedence() { result = 17 }
|
||||
}
|
||||
@@ -203,7 +203,7 @@ class IntegralConversion extends ArithmeticConversion {
|
||||
isIntegralOrEnum(getExpr().getUnspecifiedType())
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not exists(qlCast(this)) and result = "IntegralConversion"
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ class FloatingPointConversion extends ArithmeticConversion {
|
||||
getExpr().getUnspecifiedType() instanceof FloatingPointType
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not exists(qlCast(this)) and result = "FloatingPointConversion"
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ class FloatingPointToIntegralConversion extends ArithmeticConversion {
|
||||
getExpr().getUnspecifiedType() instanceof FloatingPointType
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not exists(qlCast(this)) and result = "FloatingPointToIntegralConversion"
|
||||
}
|
||||
|
||||
@@ -263,7 +263,7 @@ class IntegralToFloatingPointConversion extends ArithmeticConversion {
|
||||
isIntegralOrEnum(getExpr().getUnspecifiedType())
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not exists(qlCast(this)) and result = "IntegralToFloatingPointConversion"
|
||||
}
|
||||
|
||||
@@ -289,9 +289,7 @@ class PointerConversion extends Cast {
|
||||
isPointerOrNullPointer(getExpr().getUnspecifiedType())
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
not exists(qlCast(this)) and result = "PointerConversion"
|
||||
}
|
||||
override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "PointerConversion" }
|
||||
|
||||
override string getSemanticConversionString() { result = "pointer conversion" }
|
||||
}
|
||||
@@ -325,7 +323,7 @@ class PointerToMemberConversion extends Cast {
|
||||
)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not exists(qlCast(this)) and result = "PointerToMemberConversion"
|
||||
}
|
||||
|
||||
@@ -346,7 +344,7 @@ class PointerToIntegralConversion extends Cast {
|
||||
isPointerOrNullPointer(getExpr().getUnspecifiedType())
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not exists(qlCast(this)) and result = "PointerToIntegralConversion"
|
||||
}
|
||||
|
||||
@@ -367,7 +365,7 @@ class IntegralToPointerConversion extends Cast {
|
||||
isIntegralOrEnum(getExpr().getUnspecifiedType())
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not exists(qlCast(this)) and result = "IntegralToPointerConversion"
|
||||
}
|
||||
|
||||
@@ -385,7 +383,7 @@ class IntegralToPointerConversion extends Cast {
|
||||
class BoolConversion extends Cast {
|
||||
BoolConversion() { conversionkinds(underlyingElement(this), 1) }
|
||||
|
||||
override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "BoolConversion" }
|
||||
override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "BoolConversion" }
|
||||
|
||||
override string getSemanticConversionString() { result = "conversion to bool" }
|
||||
}
|
||||
@@ -403,7 +401,7 @@ class VoidConversion extends Cast {
|
||||
getUnspecifiedType() instanceof VoidType
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "VoidConversion" }
|
||||
override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "VoidConversion" }
|
||||
|
||||
override string getSemanticConversionString() { result = "conversion to void" }
|
||||
}
|
||||
@@ -479,7 +477,7 @@ private Class getConversionClass(Expr expr) {
|
||||
class BaseClassConversion extends InheritanceConversion {
|
||||
BaseClassConversion() { conversionkinds(underlyingElement(this), 2) }
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not exists(qlCast(this)) and result = "BaseClassConversion"
|
||||
}
|
||||
|
||||
@@ -506,7 +504,7 @@ class BaseClassConversion extends InheritanceConversion {
|
||||
class DerivedClassConversion extends InheritanceConversion {
|
||||
DerivedClassConversion() { conversionkinds(underlyingElement(this), 3) }
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not exists(qlCast(this)) and result = "DerivedClassConversion"
|
||||
}
|
||||
|
||||
@@ -528,7 +526,7 @@ class DerivedClassConversion extends InheritanceConversion {
|
||||
class PointerToMemberBaseClassConversion extends Cast {
|
||||
PointerToMemberBaseClassConversion() { conversionkinds(underlyingElement(this), 4) }
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not exists(qlCast(this)) and result = "PointerToMemberBaseClassConversion"
|
||||
}
|
||||
|
||||
@@ -548,7 +546,7 @@ class PointerToMemberBaseClassConversion extends Cast {
|
||||
class PointerToMemberDerivedClassConversion extends Cast {
|
||||
PointerToMemberDerivedClassConversion() { conversionkinds(underlyingElement(this), 5) }
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not exists(qlCast(this)) and result = "PointerToMemberDerivedClassConversion"
|
||||
}
|
||||
|
||||
@@ -569,9 +567,7 @@ class PointerToMemberDerivedClassConversion extends Cast {
|
||||
class GlvalueConversion extends Cast {
|
||||
GlvalueConversion() { conversionkinds(underlyingElement(this), 6) }
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
not exists(qlCast(this)) and result = "GlvalueConversion"
|
||||
}
|
||||
override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "GlvalueConversion" }
|
||||
|
||||
override string getSemanticConversionString() { result = "glvalue conversion" }
|
||||
}
|
||||
@@ -597,7 +593,7 @@ class GlvalueConversion extends Cast {
|
||||
class PrvalueAdjustmentConversion extends Cast {
|
||||
PrvalueAdjustmentConversion() { conversionkinds(underlyingElement(this), 7) }
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not exists(qlCast(this)) and result = "PrvalueAdjustmentConversion"
|
||||
}
|
||||
|
||||
@@ -620,7 +616,7 @@ class DynamicCast extends Cast, @dynamic_cast {
|
||||
|
||||
override int getPrecedence() { result = 17 }
|
||||
|
||||
override string getCanonicalQLClass() { result = "DynamicCast" }
|
||||
override string getAPrimaryQlClass() { result = "DynamicCast" }
|
||||
|
||||
override string getSemanticConversionString() { result = "dynamic_cast" }
|
||||
}
|
||||
@@ -669,7 +665,7 @@ class TypeidOperator extends Expr, @type_id {
|
||||
*/
|
||||
deprecated Type getSpecifiedType() { result = this.getResultType() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "TypeidOperator" }
|
||||
override string getAPrimaryQlClass() { result = "TypeidOperator" }
|
||||
|
||||
/**
|
||||
* Gets the contained expression, if any (if this typeid contains
|
||||
@@ -699,7 +695,7 @@ class TypeidOperator extends Expr, @type_id {
|
||||
class SizeofPackOperator extends Expr, @sizeof_pack {
|
||||
override string toString() { result = "sizeof...(...)" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "SizeofPackOperator" }
|
||||
override string getAPrimaryQlClass() { result = "SizeofPackOperator" }
|
||||
|
||||
override predicate mayBeImpure() { none() }
|
||||
|
||||
@@ -722,7 +718,7 @@ class SizeofOperator extends Expr, @runtime_sizeof {
|
||||
class SizeofExprOperator extends SizeofOperator {
|
||||
SizeofExprOperator() { exists(Expr e | this.getChild(0) = e) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "SizeofExprOperator" }
|
||||
override string getAPrimaryQlClass() { result = "SizeofExprOperator" }
|
||||
|
||||
/** Gets the contained expression. */
|
||||
Expr getExprOperand() { result = this.getChild(0) }
|
||||
@@ -750,7 +746,7 @@ class SizeofExprOperator extends SizeofOperator {
|
||||
class SizeofTypeOperator extends SizeofOperator {
|
||||
SizeofTypeOperator() { sizeof_bind(underlyingElement(this), _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "SizeofTypeOperator" }
|
||||
override string getAPrimaryQlClass() { result = "SizeofTypeOperator" }
|
||||
|
||||
/** Gets the contained type. */
|
||||
Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) }
|
||||
@@ -829,7 +825,7 @@ class ArrayToPointerConversion extends Conversion, @array_to_pointer {
|
||||
/** Gets a textual representation of this conversion. */
|
||||
override string toString() { result = "array to pointer conversion" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ArrayToPointerConversion" }
|
||||
override string getAPrimaryQlClass() { result = "ArrayToPointerConversion" }
|
||||
|
||||
override predicate mayBeImpure() { none() }
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ class EqualityOperation extends ComparisonOperation, @eq_op_expr {
|
||||
* ```
|
||||
*/
|
||||
class EQExpr extends EqualityOperation, @eqexpr {
|
||||
override string getCanonicalQLClass() { result = "EQExpr" }
|
||||
override string getAPrimaryQlClass() { result = "EQExpr" }
|
||||
|
||||
override string getOperator() { result = "==" }
|
||||
}
|
||||
@@ -33,7 +33,7 @@ class EQExpr extends EqualityOperation, @eqexpr {
|
||||
* ```
|
||||
*/
|
||||
class NEExpr extends EqualityOperation, @neexpr {
|
||||
override string getCanonicalQLClass() { result = "NEExpr" }
|
||||
override string getAPrimaryQlClass() { result = "NEExpr" }
|
||||
|
||||
override string getOperator() { result = "!=" }
|
||||
}
|
||||
@@ -78,7 +78,7 @@ class RelationalOperation extends ComparisonOperation, @rel_op_expr {
|
||||
* ```
|
||||
*/
|
||||
class GTExpr extends RelationalOperation, @gtexpr {
|
||||
override string getCanonicalQLClass() { result = "GTExpr" }
|
||||
override string getAPrimaryQlClass() { result = "GTExpr" }
|
||||
|
||||
override string getOperator() { result = ">" }
|
||||
|
||||
@@ -94,7 +94,7 @@ class GTExpr extends RelationalOperation, @gtexpr {
|
||||
* ```
|
||||
*/
|
||||
class LTExpr extends RelationalOperation, @ltexpr {
|
||||
override string getCanonicalQLClass() { result = "LTExpr" }
|
||||
override string getAPrimaryQlClass() { result = "LTExpr" }
|
||||
|
||||
override string getOperator() { result = "<" }
|
||||
|
||||
@@ -110,7 +110,7 @@ class LTExpr extends RelationalOperation, @ltexpr {
|
||||
* ```
|
||||
*/
|
||||
class GEExpr extends RelationalOperation, @geexpr {
|
||||
override string getCanonicalQLClass() { result = "GEExpr" }
|
||||
override string getAPrimaryQlClass() { result = "GEExpr" }
|
||||
|
||||
override string getOperator() { result = ">=" }
|
||||
|
||||
@@ -126,7 +126,7 @@ class GEExpr extends RelationalOperation, @geexpr {
|
||||
* ```
|
||||
*/
|
||||
class LEExpr extends RelationalOperation, @leexpr {
|
||||
override string getCanonicalQLClass() { result = "LEExpr" }
|
||||
override string getAPrimaryQlClass() { result = "LEExpr" }
|
||||
|
||||
override string getOperator() { result = "<=" }
|
||||
|
||||
|
||||
@@ -565,7 +565,7 @@ class BinaryOperation extends Operation, @bin_op_expr {
|
||||
class ParenthesizedBracedInitializerList extends Expr, @braced_init_list {
|
||||
override string toString() { result = "({...})" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ParenthesizedBracedInitializerList" }
|
||||
override string getAPrimaryQlClass() { result = "ParenthesizedBracedInitializerList" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -580,7 +580,7 @@ class ParenthesizedBracedInitializerList extends Expr, @braced_init_list {
|
||||
class ParenthesisExpr extends Conversion, @parexpr {
|
||||
override string toString() { result = "(...)" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ParenthesisExpr" }
|
||||
override string getAPrimaryQlClass() { result = "ParenthesisExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -591,7 +591,7 @@ class ParenthesisExpr extends Conversion, @parexpr {
|
||||
class ErrorExpr extends Expr, @errorexpr {
|
||||
override string toString() { result = "<error expr>" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ErrorExpr" }
|
||||
override string getAPrimaryQlClass() { result = "ErrorExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -606,7 +606,7 @@ class ErrorExpr extends Expr, @errorexpr {
|
||||
class AssumeExpr extends Expr, @assume {
|
||||
override string toString() { result = "__assume(...)" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "AssumeExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssumeExpr" }
|
||||
|
||||
/**
|
||||
* Gets the operand of the `__assume` expressions.
|
||||
@@ -621,7 +621,7 @@ class AssumeExpr extends Expr, @assume {
|
||||
* ```
|
||||
*/
|
||||
class CommaExpr extends Expr, @commaexpr {
|
||||
override string getCanonicalQLClass() { result = "CommaExpr" }
|
||||
override string getAPrimaryQlClass() { result = "CommaExpr" }
|
||||
|
||||
/**
|
||||
* Gets the left operand, which is the one whose value is discarded.
|
||||
@@ -656,7 +656,7 @@ class CommaExpr extends Expr, @commaexpr {
|
||||
* ```
|
||||
*/
|
||||
class AddressOfExpr extends UnaryOperation, @address_of {
|
||||
override string getCanonicalQLClass() { result = "AddressOfExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AddressOfExpr" }
|
||||
|
||||
/** Gets the function or variable whose address is taken. */
|
||||
Declaration getAddressable() {
|
||||
@@ -688,7 +688,7 @@ class AddressOfExpr extends UnaryOperation, @address_of {
|
||||
class ReferenceToExpr extends Conversion, @reference_to {
|
||||
override string toString() { result = "(reference to)" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ReferenceToExpr" }
|
||||
override string getAPrimaryQlClass() { result = "ReferenceToExpr" }
|
||||
|
||||
override int getPrecedence() { result = 16 }
|
||||
}
|
||||
@@ -702,7 +702,7 @@ class ReferenceToExpr extends Conversion, @reference_to {
|
||||
* ```
|
||||
*/
|
||||
class PointerDereferenceExpr extends UnaryOperation, @indirect {
|
||||
override string getCanonicalQLClass() { result = "PointerDereferenceExpr" }
|
||||
override string getAPrimaryQlClass() { result = "PointerDereferenceExpr" }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use getOperand() instead.
|
||||
@@ -740,7 +740,7 @@ class PointerDereferenceExpr extends UnaryOperation, @indirect {
|
||||
class ReferenceDereferenceExpr extends Conversion, @ref_indirect {
|
||||
override string toString() { result = "(reference dereference)" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ReferenceDereferenceExpr" }
|
||||
override string getAPrimaryQlClass() { result = "ReferenceDereferenceExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -846,7 +846,7 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr {
|
||||
class NewExpr extends NewOrNewArrayExpr, @new_expr {
|
||||
override string toString() { result = "new" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "NewExpr" }
|
||||
override string getAPrimaryQlClass() { result = "NewExpr" }
|
||||
|
||||
/**
|
||||
* Gets the type that is being allocated.
|
||||
@@ -876,7 +876,7 @@ class NewExpr extends NewOrNewArrayExpr, @new_expr {
|
||||
class NewArrayExpr extends NewOrNewArrayExpr, @new_array_expr {
|
||||
override string toString() { result = "new[]" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "NewArrayExpr" }
|
||||
override string getAPrimaryQlClass() { result = "NewArrayExpr" }
|
||||
|
||||
/**
|
||||
* Gets the type that is being allocated.
|
||||
@@ -924,7 +924,7 @@ class NewArrayExpr extends NewOrNewArrayExpr, @new_array_expr {
|
||||
class DeleteExpr extends Expr, @delete_expr {
|
||||
override string toString() { result = "delete" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "DeleteExpr" }
|
||||
override string getAPrimaryQlClass() { result = "DeleteExpr" }
|
||||
|
||||
override int getPrecedence() { result = 16 }
|
||||
|
||||
@@ -998,7 +998,7 @@ class DeleteExpr extends Expr, @delete_expr {
|
||||
class DeleteArrayExpr extends Expr, @delete_array_expr {
|
||||
override string toString() { result = "delete[]" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "DeleteArrayExpr" }
|
||||
override string getAPrimaryQlClass() { result = "DeleteArrayExpr" }
|
||||
|
||||
override int getPrecedence() { result = 16 }
|
||||
|
||||
@@ -1078,7 +1078,7 @@ class StmtExpr extends Expr, @expr_stmt {
|
||||
*/
|
||||
Stmt getStmt() { result.getParent() = this }
|
||||
|
||||
override string getCanonicalQLClass() { result = "StmtExpr" }
|
||||
override string getAPrimaryQlClass() { result = "StmtExpr" }
|
||||
|
||||
/**
|
||||
* Gets the result expression of the enclosed statement. For example,
|
||||
@@ -1103,7 +1103,7 @@ private Expr getStmtResultExpr(Stmt stmt) {
|
||||
class ThisExpr extends Expr, @thisaccess {
|
||||
override string toString() { result = "this" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ThisExpr" }
|
||||
override string getAPrimaryQlClass() { result = "ThisExpr" }
|
||||
|
||||
override predicate mayBeImpure() { none() }
|
||||
|
||||
@@ -1139,7 +1139,7 @@ class BlockExpr extends Literal {
|
||||
class NoExceptExpr extends Expr, @noexceptexpr {
|
||||
override string toString() { result = "noexcept(...)" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "NoExceptExpr" }
|
||||
override string getAPrimaryQlClass() { result = "NoExceptExpr" }
|
||||
|
||||
/**
|
||||
* Gets the expression inside this noexcept expression.
|
||||
@@ -1171,7 +1171,7 @@ class FoldExpr extends Expr, @foldexpr {
|
||||
)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "FoldExpr" }
|
||||
override string getAPrimaryQlClass() { result = "FoldExpr" }
|
||||
|
||||
/** Gets the binary operator used in this fold expression, as a string. */
|
||||
string getOperatorString() { fold(underlyingElement(this), result, _) }
|
||||
@@ -1247,7 +1247,7 @@ private predicate constantTemplateLiteral(Expr e) {
|
||||
* ```
|
||||
*/
|
||||
class SpaceshipExpr extends BinaryOperation, @spaceshipexpr {
|
||||
override string getCanonicalQLClass() { result = "SpaceshipExpr" }
|
||||
override string getAPrimaryQlClass() { result = "SpaceshipExpr" }
|
||||
|
||||
override int getPrecedence() { result = 11 }
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import semmle.code.cpp.Class
|
||||
class LambdaExpression extends Expr, @lambdaexpr {
|
||||
override string toString() { result = "[...](...){...}" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "LambdaExpression" }
|
||||
override string getAPrimaryQlClass() { result = "LambdaExpression" }
|
||||
|
||||
/**
|
||||
* Gets an implicitly or explicitly captured value of this lambda expression.
|
||||
@@ -75,7 +75,7 @@ class LambdaExpression extends Expr, @lambdaexpr {
|
||||
class Closure extends Class {
|
||||
Closure() { exists(LambdaExpression e | this = e.getType()) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "Closure" }
|
||||
override string getAPrimaryQlClass() { result = "Closure" }
|
||||
|
||||
/** Gets the lambda expression of which this is the type. */
|
||||
LambdaExpression getLambdaExpression() { result.getType() = this }
|
||||
@@ -101,7 +101,7 @@ class Closure extends Class {
|
||||
class LambdaCapture extends Locatable, @lambdacapture {
|
||||
override string toString() { result = getField().getName() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "LambdaCapture" }
|
||||
override string getAPrimaryQlClass() { result = "LambdaCapture" }
|
||||
|
||||
/**
|
||||
* Holds if this capture was made implicitly.
|
||||
|
||||
@@ -14,7 +14,7 @@ class Literal extends Expr, @literal {
|
||||
result = "Unknown literal"
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Literal" }
|
||||
override string getAPrimaryQlClass() { result = "Literal" }
|
||||
|
||||
override predicate mayBeImpure() { none() }
|
||||
|
||||
@@ -35,7 +35,7 @@ class Literal extends Expr, @literal {
|
||||
class LabelLiteral extends Literal {
|
||||
LabelLiteral() { jumpinfo(underlyingElement(this), _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "LabelLiteral" }
|
||||
override string getAPrimaryQlClass() { result = "LabelLiteral" }
|
||||
|
||||
/** Gets the corresponding label statement. */
|
||||
LabelStmt getLabel() { jumpinfo(underlyingElement(this), _, unresolveElement(result)) }
|
||||
@@ -93,7 +93,7 @@ abstract class TextLiteral extends Literal {
|
||||
class CharLiteral extends TextLiteral {
|
||||
CharLiteral() { this.getValueText().regexpMatch("(?s)\\s*L?'.*") }
|
||||
|
||||
override string getCanonicalQLClass() { result = "CharLiteral" }
|
||||
override string getAPrimaryQlClass() { result = "CharLiteral" }
|
||||
|
||||
/**
|
||||
* Gets the character of this literal. For example `L'a'` has character `"a"`.
|
||||
@@ -115,7 +115,7 @@ class StringLiteral extends TextLiteral {
|
||||
// @aggregateliteral rather than @literal.
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "StringLiteral" }
|
||||
override string getAPrimaryQlClass() { result = "StringLiteral" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,7 +128,7 @@ class StringLiteral extends TextLiteral {
|
||||
class OctalLiteral extends Literal {
|
||||
OctalLiteral() { super.getValueText().regexpMatch("\\s*0[0-7]+[uUlL]*\\s*") }
|
||||
|
||||
override string getCanonicalQLClass() { result = "OctalLiteral" }
|
||||
override string getAPrimaryQlClass() { result = "OctalLiteral" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,14 +140,14 @@ class OctalLiteral extends Literal {
|
||||
class HexLiteral extends Literal {
|
||||
HexLiteral() { super.getValueText().regexpMatch("\\s*0[xX][0-9a-fA-F]+[uUlL]*\\s*") }
|
||||
|
||||
override string getCanonicalQLClass() { result = "HexLiteral" }
|
||||
override string getAPrimaryQlClass() { result = "HexLiteral" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C/C++ aggregate literal.
|
||||
*/
|
||||
class AggregateLiteral extends Expr, @aggregateliteral {
|
||||
override string getCanonicalQLClass() { result = "AggregateLiteral" }
|
||||
override string getAPrimaryQlClass() { result = "AggregateLiteral" }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use ClassAggregateLiteral.getFieldExpr() instead.
|
||||
@@ -179,7 +179,7 @@ class ClassAggregateLiteral extends AggregateLiteral {
|
||||
|
||||
ClassAggregateLiteral() { classType = this.getUnspecifiedType() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ClassAggregateLiteral" }
|
||||
override string getAPrimaryQlClass() { result = "ClassAggregateLiteral" }
|
||||
|
||||
/**
|
||||
* Gets the expression within the aggregate literal that is used to initialize
|
||||
@@ -299,7 +299,7 @@ class ArrayAggregateLiteral extends ArrayOrVectorAggregateLiteral {
|
||||
|
||||
ArrayAggregateLiteral() { arrayType = this.getUnspecifiedType() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ArrayAggregateLiteral" }
|
||||
override string getAPrimaryQlClass() { result = "ArrayAggregateLiteral" }
|
||||
|
||||
override int getArraySize() { result = arrayType.getArraySize() }
|
||||
|
||||
@@ -323,7 +323,7 @@ class VectorAggregateLiteral extends ArrayOrVectorAggregateLiteral {
|
||||
|
||||
VectorAggregateLiteral() { vectorType = this.getUnspecifiedType() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "VectorAggregateLiteral" }
|
||||
override string getAPrimaryQlClass() { result = "VectorAggregateLiteral" }
|
||||
|
||||
override int getArraySize() { result = vectorType.getNumElements() }
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ class UnaryLogicalOperation extends UnaryOperation, @un_log_op_expr { }
|
||||
class NotExpr extends UnaryLogicalOperation, @notexpr {
|
||||
override string getOperator() { result = "!" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "NotExpr" }
|
||||
override string getAPrimaryQlClass() { result = "NotExpr" }
|
||||
|
||||
override int getPrecedence() { result = 16 }
|
||||
}
|
||||
@@ -46,7 +46,7 @@ class BinaryLogicalOperation extends BinaryOperation, @bin_log_op_expr {
|
||||
class LogicalAndExpr extends BinaryLogicalOperation, @andlogicalexpr {
|
||||
override string getOperator() { result = "&&" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "LogicalAndExpr" }
|
||||
override string getAPrimaryQlClass() { result = "LogicalAndExpr" }
|
||||
|
||||
override int getPrecedence() { result = 5 }
|
||||
|
||||
@@ -67,7 +67,7 @@ class LogicalAndExpr extends BinaryLogicalOperation, @andlogicalexpr {
|
||||
class LogicalOrExpr extends BinaryLogicalOperation, @orlogicalexpr {
|
||||
override string getOperator() { result = "||" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "LogicalOrExpr" }
|
||||
override string getAPrimaryQlClass() { result = "LogicalOrExpr" }
|
||||
|
||||
override int getPrecedence() { result = 4 }
|
||||
|
||||
@@ -89,7 +89,7 @@ class ConditionalExpr extends Operation, @conditionalexpr {
|
||||
/** Gets the condition of this conditional expression. */
|
||||
Expr getCondition() { expr_cond_guard(underlyingElement(this), unresolveElement(result)) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ConditionalExpr" }
|
||||
override string getAPrimaryQlClass() { result = "ConditionalExpr" }
|
||||
|
||||
/** Gets the 'then' expression of this conditional expression. */
|
||||
Expr getThen() {
|
||||
|
||||
@@ -19,7 +19,7 @@ import DataFlowImplSpecific::Public
|
||||
* a subclass whose characteristic predicate is a unique singleton string.
|
||||
* For example, write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* class MyAnalysisConfiguration extends DataFlow::Configuration {
|
||||
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
|
||||
* // Override `isSource` and `isSink`.
|
||||
@@ -37,7 +37,7 @@ import DataFlowImplSpecific::Public
|
||||
* Then, to query whether there is flow between some `source` and `sink`,
|
||||
* write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
* ```
|
||||
*
|
||||
@@ -1051,6 +1051,17 @@ private predicate flowIntoCallNodeCand2(
|
||||
}
|
||||
|
||||
private module LocalFlowBigStep {
|
||||
/**
|
||||
* A node where some checking is required, and hence the big-step relation
|
||||
* is not allowed to step over.
|
||||
*/
|
||||
private class FlowCheckNode extends Node {
|
||||
FlowCheckNode() {
|
||||
this instanceof CastNode or
|
||||
clearsContent(this, _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` can be the first node in a maximal subsequence of local
|
||||
* flow steps in a dataflow path.
|
||||
@@ -1065,7 +1076,7 @@ private module LocalFlowBigStep {
|
||||
node instanceof OutNodeExt or
|
||||
store(_, _, node, _) or
|
||||
read(_, _, node) or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1083,7 +1094,7 @@ private module LocalFlowBigStep {
|
||||
read(node, _, next)
|
||||
)
|
||||
or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
config.isSink(node)
|
||||
}
|
||||
@@ -1127,14 +1138,14 @@ private module LocalFlowBigStep {
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
|
||||
localFlowStepNodeCand1(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
nodeCand2(node2, unbind(config))
|
||||
)
|
||||
or
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, _, _, config, cc) and
|
||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
preservesValue = false and
|
||||
t = getErasedNodeTypeBound(node2) and
|
||||
nodeCand2(node2, unbind(config))
|
||||
@@ -1190,6 +1201,7 @@ private predicate flowCandFwd(
|
||||
Configuration config
|
||||
) {
|
||||
flowCandFwd0(node, fromArg, argApf, apf, config) and
|
||||
not apf.isClearedAt(node) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
|
||||
else any()
|
||||
@@ -2564,7 +2576,7 @@ private module FlowExploration {
|
||||
|
||||
private newtype TPartialAccessPath =
|
||||
TPartialNil(DataFlowType t) or
|
||||
TPartialCons(TypedContent tc, int len) { len in [1 .. 5] }
|
||||
TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] }
|
||||
|
||||
/**
|
||||
* Conceptually a list of `TypedContent`s followed by a `Type`, but only the first
|
||||
|
||||
@@ -19,7 +19,7 @@ import DataFlowImplSpecific::Public
|
||||
* a subclass whose characteristic predicate is a unique singleton string.
|
||||
* For example, write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* class MyAnalysisConfiguration extends DataFlow::Configuration {
|
||||
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
|
||||
* // Override `isSource` and `isSink`.
|
||||
@@ -37,7 +37,7 @@ import DataFlowImplSpecific::Public
|
||||
* Then, to query whether there is flow between some `source` and `sink`,
|
||||
* write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
* ```
|
||||
*
|
||||
@@ -1051,6 +1051,17 @@ private predicate flowIntoCallNodeCand2(
|
||||
}
|
||||
|
||||
private module LocalFlowBigStep {
|
||||
/**
|
||||
* A node where some checking is required, and hence the big-step relation
|
||||
* is not allowed to step over.
|
||||
*/
|
||||
private class FlowCheckNode extends Node {
|
||||
FlowCheckNode() {
|
||||
this instanceof CastNode or
|
||||
clearsContent(this, _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` can be the first node in a maximal subsequence of local
|
||||
* flow steps in a dataflow path.
|
||||
@@ -1065,7 +1076,7 @@ private module LocalFlowBigStep {
|
||||
node instanceof OutNodeExt or
|
||||
store(_, _, node, _) or
|
||||
read(_, _, node) or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1083,7 +1094,7 @@ private module LocalFlowBigStep {
|
||||
read(node, _, next)
|
||||
)
|
||||
or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
config.isSink(node)
|
||||
}
|
||||
@@ -1127,14 +1138,14 @@ private module LocalFlowBigStep {
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
|
||||
localFlowStepNodeCand1(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
nodeCand2(node2, unbind(config))
|
||||
)
|
||||
or
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, _, _, config, cc) and
|
||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
preservesValue = false and
|
||||
t = getErasedNodeTypeBound(node2) and
|
||||
nodeCand2(node2, unbind(config))
|
||||
@@ -1190,6 +1201,7 @@ private predicate flowCandFwd(
|
||||
Configuration config
|
||||
) {
|
||||
flowCandFwd0(node, fromArg, argApf, apf, config) and
|
||||
not apf.isClearedAt(node) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
|
||||
else any()
|
||||
@@ -2564,7 +2576,7 @@ private module FlowExploration {
|
||||
|
||||
private newtype TPartialAccessPath =
|
||||
TPartialNil(DataFlowType t) or
|
||||
TPartialCons(TypedContent tc, int len) { len in [1 .. 5] }
|
||||
TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] }
|
||||
|
||||
/**
|
||||
* Conceptually a list of `TypedContent`s followed by a `Type`, but only the first
|
||||
|
||||
@@ -19,7 +19,7 @@ import DataFlowImplSpecific::Public
|
||||
* a subclass whose characteristic predicate is a unique singleton string.
|
||||
* For example, write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* class MyAnalysisConfiguration extends DataFlow::Configuration {
|
||||
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
|
||||
* // Override `isSource` and `isSink`.
|
||||
@@ -37,7 +37,7 @@ import DataFlowImplSpecific::Public
|
||||
* Then, to query whether there is flow between some `source` and `sink`,
|
||||
* write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
* ```
|
||||
*
|
||||
@@ -1051,6 +1051,17 @@ private predicate flowIntoCallNodeCand2(
|
||||
}
|
||||
|
||||
private module LocalFlowBigStep {
|
||||
/**
|
||||
* A node where some checking is required, and hence the big-step relation
|
||||
* is not allowed to step over.
|
||||
*/
|
||||
private class FlowCheckNode extends Node {
|
||||
FlowCheckNode() {
|
||||
this instanceof CastNode or
|
||||
clearsContent(this, _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` can be the first node in a maximal subsequence of local
|
||||
* flow steps in a dataflow path.
|
||||
@@ -1065,7 +1076,7 @@ private module LocalFlowBigStep {
|
||||
node instanceof OutNodeExt or
|
||||
store(_, _, node, _) or
|
||||
read(_, _, node) or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1083,7 +1094,7 @@ private module LocalFlowBigStep {
|
||||
read(node, _, next)
|
||||
)
|
||||
or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
config.isSink(node)
|
||||
}
|
||||
@@ -1127,14 +1138,14 @@ private module LocalFlowBigStep {
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
|
||||
localFlowStepNodeCand1(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
nodeCand2(node2, unbind(config))
|
||||
)
|
||||
or
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, _, _, config, cc) and
|
||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
preservesValue = false and
|
||||
t = getErasedNodeTypeBound(node2) and
|
||||
nodeCand2(node2, unbind(config))
|
||||
@@ -1190,6 +1201,7 @@ private predicate flowCandFwd(
|
||||
Configuration config
|
||||
) {
|
||||
flowCandFwd0(node, fromArg, argApf, apf, config) and
|
||||
not apf.isClearedAt(node) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
|
||||
else any()
|
||||
@@ -2564,7 +2576,7 @@ private module FlowExploration {
|
||||
|
||||
private newtype TPartialAccessPath =
|
||||
TPartialNil(DataFlowType t) or
|
||||
TPartialCons(TypedContent tc, int len) { len in [1 .. 5] }
|
||||
TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] }
|
||||
|
||||
/**
|
||||
* Conceptually a list of `TypedContent`s followed by a `Type`, but only the first
|
||||
|
||||
@@ -19,7 +19,7 @@ import DataFlowImplSpecific::Public
|
||||
* a subclass whose characteristic predicate is a unique singleton string.
|
||||
* For example, write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* class MyAnalysisConfiguration extends DataFlow::Configuration {
|
||||
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
|
||||
* // Override `isSource` and `isSink`.
|
||||
@@ -37,7 +37,7 @@ import DataFlowImplSpecific::Public
|
||||
* Then, to query whether there is flow between some `source` and `sink`,
|
||||
* write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
* ```
|
||||
*
|
||||
@@ -1051,6 +1051,17 @@ private predicate flowIntoCallNodeCand2(
|
||||
}
|
||||
|
||||
private module LocalFlowBigStep {
|
||||
/**
|
||||
* A node where some checking is required, and hence the big-step relation
|
||||
* is not allowed to step over.
|
||||
*/
|
||||
private class FlowCheckNode extends Node {
|
||||
FlowCheckNode() {
|
||||
this instanceof CastNode or
|
||||
clearsContent(this, _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` can be the first node in a maximal subsequence of local
|
||||
* flow steps in a dataflow path.
|
||||
@@ -1065,7 +1076,7 @@ private module LocalFlowBigStep {
|
||||
node instanceof OutNodeExt or
|
||||
store(_, _, node, _) or
|
||||
read(_, _, node) or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1083,7 +1094,7 @@ private module LocalFlowBigStep {
|
||||
read(node, _, next)
|
||||
)
|
||||
or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
config.isSink(node)
|
||||
}
|
||||
@@ -1127,14 +1138,14 @@ private module LocalFlowBigStep {
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
|
||||
localFlowStepNodeCand1(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
nodeCand2(node2, unbind(config))
|
||||
)
|
||||
or
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, _, _, config, cc) and
|
||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
preservesValue = false and
|
||||
t = getErasedNodeTypeBound(node2) and
|
||||
nodeCand2(node2, unbind(config))
|
||||
@@ -1190,6 +1201,7 @@ private predicate flowCandFwd(
|
||||
Configuration config
|
||||
) {
|
||||
flowCandFwd0(node, fromArg, argApf, apf, config) and
|
||||
not apf.isClearedAt(node) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
|
||||
else any()
|
||||
@@ -2564,7 +2576,7 @@ private module FlowExploration {
|
||||
|
||||
private newtype TPartialAccessPath =
|
||||
TPartialNil(DataFlowType t) or
|
||||
TPartialCons(TypedContent tc, int len) { len in [1 .. 5] }
|
||||
TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] }
|
||||
|
||||
/**
|
||||
* Conceptually a list of `TypedContent`s followed by a `Type`, but only the first
|
||||
|
||||
@@ -754,6 +754,13 @@ abstract class AccessPathFront extends TAccessPathFront {
|
||||
abstract boolean toBoolNonEmpty();
|
||||
|
||||
predicate headUsesContent(TypedContent tc) { this = TFrontHead(tc) }
|
||||
|
||||
predicate isClearedAt(Node n) {
|
||||
exists(TypedContent tc |
|
||||
this.headUsesContent(tc) and
|
||||
clearsContent(n, tc.getContent())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||
|
||||
@@ -184,14 +184,32 @@ private class ArrayContent extends Content, TArrayContent {
|
||||
override string toString() { result = "array" }
|
||||
}
|
||||
|
||||
private predicate storeStepNoChi(Node node1, Content f, PostUpdateNode node2) {
|
||||
exists(FieldAddressInstruction fa, StoreInstruction store |
|
||||
store = node2.asInstruction() and
|
||||
store.getDestinationAddress() = fa and
|
||||
store.getSourceValue() = node1.asInstruction() and
|
||||
f.(FieldContent).getField() = fa.getField()
|
||||
)
|
||||
}
|
||||
|
||||
private predicate storeStepChi(Node node1, Content f, PostUpdateNode node2) {
|
||||
exists(FieldAddressInstruction fa, StoreInstruction store |
|
||||
node1.asInstruction() = store and
|
||||
store.getDestinationAddress() = fa and
|
||||
node2.asInstruction().(ChiInstruction).getPartial() = store and
|
||||
f.(FieldContent).getField() = fa.getField()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
|
||||
* Thus, `node2` references an object with a field `f` that contains the
|
||||
* value of `node1`.
|
||||
*/
|
||||
predicate storeStep(Node node1, Content f, StoreStepNode node2) {
|
||||
node2.getStoredValue() = node1 and
|
||||
f.(FieldContent).getField() = node2.getAField()
|
||||
predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
|
||||
storeStepNoChi(node1, f, node2) or
|
||||
storeStepChi(node1, f, node2)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,9 +217,20 @@ predicate storeStep(Node node1, Content f, StoreStepNode node2) {
|
||||
* Thus, `node1` references an object with a field `f` whose value ends up in
|
||||
* `node2`.
|
||||
*/
|
||||
predicate readStep(Node node1, Content f, ReadStepNode node2) {
|
||||
node2.getReadValue() = node1 and
|
||||
f.(FieldContent).getField() = node2.getAField()
|
||||
predicate readStep(Node node1, Content f, Node node2) {
|
||||
exists(FieldAddressInstruction fa, LoadInstruction load |
|
||||
load.getSourceAddress() = fa and
|
||||
node1.asInstruction() = load.getSourceValueOperand().getAnyDef() and
|
||||
fa.getField() = f.(FieldContent).getField() and
|
||||
load = node2.asInstruction()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if values stored inside content `c` are cleared at node `n`.
|
||||
*/
|
||||
predicate clearsContent(Node n, Content c) {
|
||||
none() // stub implementation
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,9 +13,7 @@ private import semmle.code.cpp.models.interfaces.DataFlow
|
||||
|
||||
private newtype TIRDataFlowNode =
|
||||
TInstructionNode(Instruction i) or
|
||||
TVariableNode(Variable var) or
|
||||
TStoreNode(StoreChain chain) or
|
||||
TLoadNode(LoadChain load)
|
||||
TVariableNode(Variable var)
|
||||
|
||||
/**
|
||||
* A node in a data flow graph.
|
||||
@@ -61,7 +59,7 @@ class Node extends TIRDataFlowNode {
|
||||
|
||||
/**
|
||||
* Gets the variable corresponding to this node, if any. This can be used for
|
||||
* modelling flow in and out of global variables.
|
||||
* modeling flow in and out of global variables.
|
||||
*/
|
||||
Variable asVariable() { result = this.(VariableNode).getVariable() }
|
||||
|
||||
@@ -273,7 +271,7 @@ deprecated class UninitializedNode extends Node {
|
||||
* This class exists to match the interface used by Java. There are currently no non-abstract
|
||||
* classes that extend it. When we implement field flow, we can revisit this.
|
||||
*/
|
||||
abstract class PostUpdateNode extends Node {
|
||||
abstract class PostUpdateNode extends InstructionNode {
|
||||
/**
|
||||
* Gets the node before the state update.
|
||||
*/
|
||||
@@ -288,15 +286,59 @@ abstract class PostUpdateNode extends Node {
|
||||
* value, but does not necessarily replace it entirely. For example:
|
||||
* ```
|
||||
* x.y = 1; // a partial definition of the object `x`.
|
||||
* x.y.z = 1; // a partial definition of the objects `x.y` and `x`.
|
||||
* x.y.z = 1; // a partial definition of the object `x.y`.
|
||||
* x.setY(1); // a partial definition of the object `x`.
|
||||
* setY(&x); // a partial definition of the object `x`.
|
||||
* ```
|
||||
*/
|
||||
abstract private class PartialDefinitionNode extends PostUpdateNode {
|
||||
abstract private class PartialDefinitionNode extends PostUpdateNode, TInstructionNode {
|
||||
abstract Expr getDefinedExpr();
|
||||
}
|
||||
|
||||
private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
|
||||
override ChiInstruction instr;
|
||||
FieldAddressInstruction field;
|
||||
|
||||
ExplicitFieldStoreQualifierNode() {
|
||||
not instr.isResultConflated() and
|
||||
exists(StoreInstruction store |
|
||||
instr.getPartial() = store and field = store.getDestinationAddress()
|
||||
)
|
||||
}
|
||||
|
||||
// There might be multiple `ChiInstructions` that has a particular instruction as
|
||||
// the total operand - so this definition gives consistency errors in
|
||||
// DataFlowImplConsistency::Consistency. However, it's not clear what (if any) implications
|
||||
// this consistency failure has.
|
||||
override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() }
|
||||
|
||||
override Expr getDefinedExpr() {
|
||||
result = field.getObjectAddress().getUnconvertedResultExpression()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Not every store instruction generates a chi instruction that we can attach a PostUpdateNode to.
|
||||
* For instance, an update to a field of a struct containing only one field. For these cases we
|
||||
* attach the PostUpdateNode to the store instruction. There's no obvious pre update node for this case
|
||||
* (as the entire memory is updated), so `getPreUpdateNode` is implemented as `none()`.
|
||||
*/
|
||||
private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNode {
|
||||
override StoreInstruction instr;
|
||||
FieldAddressInstruction field;
|
||||
|
||||
ExplicitSingleFieldStoreQualifierNode() {
|
||||
field = instr.getDestinationAddress() and
|
||||
not exists(ChiInstruction chi | chi.getPartial() = instr)
|
||||
}
|
||||
|
||||
override Node getPreUpdateNode() { none() }
|
||||
|
||||
override Expr getDefinedExpr() {
|
||||
result = field.getObjectAddress().getUnconvertedResultExpression()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node that represents the value of a variable after a function call that
|
||||
* may have changed the variable because it's passed by reference.
|
||||
@@ -360,7 +402,7 @@ private class ArgumentIndirectionNode extends InstructionNode {
|
||||
/**
|
||||
* A `Node` corresponding to a variable in the program, as opposed to the
|
||||
* value of that variable at some particular point. This can be used for
|
||||
* modelling flow in and out of global variables.
|
||||
* modeling flow in and out of global variables.
|
||||
*/
|
||||
class VariableNode extends Node, TVariableNode {
|
||||
Variable v;
|
||||
@@ -388,413 +430,6 @@ class VariableNode extends Node, TVariableNode {
|
||||
override string toString() { result = v.toString() }
|
||||
}
|
||||
|
||||
/** The target node of a `readStep`. */
|
||||
abstract class ReadStepNode extends Node {
|
||||
/** Get the field that is read. */
|
||||
abstract Field getAField();
|
||||
|
||||
/** Get the node representing the value that is read. */
|
||||
abstract Node getReadValue();
|
||||
}
|
||||
|
||||
/** The target node of a `storeStep`. */
|
||||
abstract class StoreStepNode extends PostUpdateNode {
|
||||
/** Get the field that is stored into. */
|
||||
abstract Field getAField();
|
||||
|
||||
/** Get the node representing the value that is stored. */
|
||||
abstract Node getStoredValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sometimes a sequence of `FieldAddressInstruction`s does not end with a `StoreInstruction`.
|
||||
* This class abstracts out the information needed to end a `StoreChain`.
|
||||
*/
|
||||
abstract private class StoreChainEndInstruction extends Instruction {
|
||||
abstract FieldAddressInstruction getFieldInstruction();
|
||||
|
||||
abstract Instruction getBeginInstruction();
|
||||
|
||||
abstract Node getPreUpdateNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* A `StoreInstruction` that ends a sequence of `FieldAddressInstruction`s.
|
||||
*/
|
||||
private class StoreChainEndInstructionStoreWithChi extends StoreChainEndInstruction, ChiInstruction {
|
||||
StoreInstruction store;
|
||||
FieldAddressInstruction fi;
|
||||
|
||||
StoreChainEndInstructionStoreWithChi() {
|
||||
not this.isResultConflated() and
|
||||
this.getPartial() = store and
|
||||
fi = skipConversion*(store.getDestinationAddress())
|
||||
}
|
||||
|
||||
override FieldAddressInstruction getFieldInstruction() { result = fi }
|
||||
|
||||
override Node getPreUpdateNode() { result.asInstruction() = this.getTotal() }
|
||||
|
||||
override Instruction getBeginInstruction() { result = store }
|
||||
}
|
||||
|
||||
/**
|
||||
* Not every store instruction generates a chi instruction that we can attach a PostUpdateNode to.
|
||||
* For instance, an update to a field of a struct containing only one field. For these cases we
|
||||
* attach the PostUpdateNode to the store instruction. There's no obvious pre update node for this case
|
||||
* (as the entire memory is updated), so `getPreUpdateNode` is implemented as `none()`.
|
||||
*/
|
||||
private class StoreChainEndInstructionStoreWithoutChi extends StoreChainEndInstruction,
|
||||
StoreInstruction {
|
||||
FieldAddressInstruction fi;
|
||||
|
||||
StoreChainEndInstructionStoreWithoutChi() {
|
||||
not exists(ChiInstruction chi | chi.getPartial() = this) and
|
||||
fi = skipConversion*(this.getDestinationAddress())
|
||||
}
|
||||
|
||||
override FieldAddressInstruction getFieldInstruction() { result = fi }
|
||||
|
||||
override Node getPreUpdateNode() { none() }
|
||||
|
||||
override Instruction getBeginInstruction() { result = this.getSourceValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
* When traversing dependencies between an instruction and its operands
|
||||
* it is sometimes convenient to ignore certain instructions. For instance,
|
||||
* the `LoadChain` for `((B&)a.b).c` inserts a `CopyValueInstruction`
|
||||
* between the computed address for `b` and the `FieldAddressInstruction`
|
||||
* for `c`.
|
||||
*/
|
||||
private Instruction skipConversion(Instruction instr) {
|
||||
result = instr.(CopyInstruction).getSourceValue()
|
||||
or
|
||||
result = instr.(ConvertInstruction).getUnary()
|
||||
or
|
||||
result = instr.(CheckedConvertOrNullInstruction).getUnary()
|
||||
or
|
||||
result = instr.(InheritanceConversionInstruction).getUnary()
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends a `StoreChain` with a `WriteSideEffectInstruction` such that we build up
|
||||
* the correct access paths. For example in:
|
||||
* ```
|
||||
* void setter(B *b, int data) {
|
||||
* b->c = data;
|
||||
* }
|
||||
* ...
|
||||
* setter(&a.b, source());
|
||||
* sink(a.b.c)
|
||||
* ```
|
||||
* In order to register `a.b.c` as a `readStep`, the access path must
|
||||
* contain `[a, b, c]`, and thus the access path must be `[a, b]`
|
||||
* before entering `setter`.
|
||||
*/
|
||||
private class StoreChainEndInstructionSideEffect extends StoreChainEndInstruction, ChiInstruction {
|
||||
WriteSideEffectInstruction sideEffect;
|
||||
FieldAddressInstruction fi;
|
||||
|
||||
StoreChainEndInstructionSideEffect() {
|
||||
not this.isResultConflated() and
|
||||
this.getPartial() = sideEffect and
|
||||
fi = skipConversion*(sideEffect.getArgumentDef())
|
||||
}
|
||||
|
||||
override FieldAddressInstruction getFieldInstruction() { result = fi }
|
||||
|
||||
override Node getPreUpdateNode() { result.asInstruction() = this.getTotal() }
|
||||
|
||||
override Instruction getBeginInstruction() { result = sideEffect }
|
||||
}
|
||||
|
||||
private newtype TStoreChain =
|
||||
TStoreChainConsNil(FieldAddressInstruction f, StoreChainEndInstruction end) {
|
||||
end.getFieldInstruction() = f
|
||||
} or
|
||||
TStoreChainConsCons(FieldAddressInstruction f, TStoreChain next) {
|
||||
exists(FieldAddressInstruction g | skipConversion*(g.getObjectAddress()) = f |
|
||||
next = TStoreChainConsCons(g, _) or
|
||||
next = TStoreChainConsNil(g, _)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A `StoreChain` represents a series of field lookups that compute the destination of a store.
|
||||
* For example, given an assignment such as `a.b.c = x`, there are two `StoreChain`s:
|
||||
* One corresponding to the field `b`, and one corresponding to the field `c`. Here, `b` is the parent
|
||||
* `StoreChain` of `c`.
|
||||
*/
|
||||
private class StoreChain extends TStoreChain {
|
||||
string toString() { none() }
|
||||
|
||||
/**
|
||||
* Gets the parent of this `StoreChain`, if any. For example, for the assignment
|
||||
* ```
|
||||
* a.b.c = x;
|
||||
* ```
|
||||
* the parent of `c` is `b`, and `b` has no parent.
|
||||
*/
|
||||
final StoreChainConsCons getParent() { result.getChild() = this }
|
||||
|
||||
/** Gets the child of this `StoreChain`, if any. */
|
||||
StoreChain getChild() { none() }
|
||||
|
||||
/**
|
||||
* Gets the instruction that receives flow from the outermost `StoreChain` of this chain (i.e.,
|
||||
* the `StoreChain` with no parent).
|
||||
*/
|
||||
StoreChainEndInstruction getEndInstruction() { none() }
|
||||
|
||||
/**
|
||||
* Gets the instruction that flows to the innermost `StoreChain` of this chain (i.e.,
|
||||
* the `StoreChain` with no child).
|
||||
*/
|
||||
Instruction getBeginInstruction() { none() }
|
||||
|
||||
/** Gets the `FieldAddressInstruction` of this `StoreChain` */
|
||||
FieldAddressInstruction getFieldInstruction() { none() }
|
||||
|
||||
/** Gets the `FieldAddressInstruction` of any `StoreChain` in this chain. */
|
||||
FieldAddressInstruction getAFieldInstruction() { none() }
|
||||
|
||||
final Location getLocation() { result = getFieldInstruction().getLocation() }
|
||||
}
|
||||
|
||||
private class StoreChainConsNil extends StoreChain, TStoreChainConsNil {
|
||||
FieldAddressInstruction fi;
|
||||
StoreChainEndInstruction end;
|
||||
|
||||
StoreChainConsNil() { this = TStoreChainConsNil(fi, end) }
|
||||
|
||||
override string toString() { result = fi.getField().toString() }
|
||||
|
||||
override StoreChainEndInstruction getEndInstruction() { result = end }
|
||||
|
||||
override Instruction getBeginInstruction() { result = end.getBeginInstruction() }
|
||||
|
||||
override FieldAddressInstruction getFieldInstruction() { result = fi }
|
||||
|
||||
override FieldAddressInstruction getAFieldInstruction() { result = fi }
|
||||
}
|
||||
|
||||
private class StoreChainConsCons extends StoreChain, TStoreChainConsCons {
|
||||
FieldAddressInstruction fi;
|
||||
StoreChain next;
|
||||
|
||||
StoreChainConsCons() { this = TStoreChainConsCons(fi, next) }
|
||||
|
||||
override string toString() { result = fi.getField().toString() + "." + next.toString() }
|
||||
|
||||
override StoreChain getChild() { result = next }
|
||||
|
||||
override FieldAddressInstruction getFieldInstruction() { result = fi }
|
||||
|
||||
override FieldAddressInstruction getAFieldInstruction() {
|
||||
result = [fi, next.getAFieldInstruction()]
|
||||
}
|
||||
|
||||
override StoreChainEndInstruction getEndInstruction() { result = next.getEndInstruction() }
|
||||
|
||||
override Instruction getBeginInstruction() { result = next.getBeginInstruction() }
|
||||
}
|
||||
|
||||
private newtype TLoadChain =
|
||||
TLoadChainConsNil(FieldAddressInstruction fi, LoadChainEndInstruction end) {
|
||||
end.getFieldInstruction() = fi
|
||||
} or
|
||||
TLoadChainConsCons(FieldAddressInstruction fi, TLoadChain next) {
|
||||
exists(FieldAddressInstruction nextFi | skipConversion*(nextFi.getObjectAddress()) = fi |
|
||||
next = TLoadChainConsCons(nextFi, _) or
|
||||
next = TLoadChainConsNil(nextFi, _)
|
||||
)
|
||||
}
|
||||
|
||||
/** This class abstracts out the information needed to end a `LoadChain`. */
|
||||
abstract private class LoadChainEndInstruction extends Instruction {
|
||||
abstract FieldAddressInstruction getFieldInstruction();
|
||||
|
||||
abstract Instruction getReadValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* A `LoadInstruction` that ends a sequence of `FieldAddressInstruction`s.
|
||||
*/
|
||||
private class LoadChainEndInstructionLoad extends LoadChainEndInstruction, LoadInstruction {
|
||||
FieldAddressInstruction fi;
|
||||
|
||||
LoadChainEndInstructionLoad() { fi = skipConversion*(this.getSourceAddress()) }
|
||||
|
||||
override FieldAddressInstruction getFieldInstruction() { result = fi }
|
||||
|
||||
override Instruction getReadValue() { result = getSourceValueOperand().getAnyDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends a `LoadChain` with a `ReadSideEffectInstruction`. This ensures that we pop content from the
|
||||
* access path when passing an argument that reads a field. For example in:
|
||||
* ```
|
||||
* void read_f(Inner* inner) {
|
||||
* sink(inner->f);
|
||||
* }
|
||||
* ...
|
||||
* outer.inner.f = taint();
|
||||
* read_f(&outer.inner);
|
||||
* ```
|
||||
* In order to register `inner->f` as a `readStep`, the head of the access path must
|
||||
* be `f`, and thus reading `&outer.inner` must pop `inner` from the access path
|
||||
* before entering `read_f`.
|
||||
*/
|
||||
private class LoadChainEndInstructionSideEffect extends LoadChainEndInstruction,
|
||||
ReadSideEffectInstruction {
|
||||
FieldAddressInstruction fi;
|
||||
|
||||
LoadChainEndInstructionSideEffect() { fi = skipConversion*(this.getArgumentDef()) }
|
||||
|
||||
override FieldAddressInstruction getFieldInstruction() { result = fi }
|
||||
|
||||
override Instruction getReadValue() { result = getSideEffectOperand().getAnyDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `LoadChain` represents a series of field lookups that compute the source address of a load.
|
||||
* For example, given the field lookup in `f(a.b.c)`, there are two `LoadChains`s:
|
||||
* One corresponding to the field `b`, and one corresponding to the field `c`. Here, `b` is the parent
|
||||
* `LoadChain` of `c`.
|
||||
*/
|
||||
private class LoadChain extends TLoadChain {
|
||||
string toString() { none() }
|
||||
|
||||
/**
|
||||
* Gets the instruction that receives flow from the innermost `LoadChain` of this chain (i.e.,
|
||||
* the `LoadChain` with no child).
|
||||
*/
|
||||
LoadChainEndInstruction getEndInstruction() { none() }
|
||||
|
||||
/**
|
||||
* Gets the parent of this `LoadChain`, if any. For example in `f(a.b.c)` the parent of `c` is `b`,
|
||||
* and `b` has no parent.
|
||||
*/
|
||||
final LoadChainConsCons getParent() { result.getChild() = this }
|
||||
|
||||
/** Gets the child of this `LoadChain`, if any. */
|
||||
LoadChain getChild() { none() }
|
||||
|
||||
/** Gets the `FieldAddressInstruction` of this `LoadChain` */
|
||||
FieldAddressInstruction getFieldInstruction() { none() }
|
||||
|
||||
final Location getLocation() { result = getFieldInstruction().getLocation() }
|
||||
}
|
||||
|
||||
private class LoadChainConsNil extends LoadChain, TLoadChainConsNil {
|
||||
FieldAddressInstruction fi;
|
||||
LoadChainEndInstruction end;
|
||||
|
||||
LoadChainConsNil() { this = TLoadChainConsNil(fi, end) }
|
||||
|
||||
override string toString() { result = fi.getField().toString() }
|
||||
|
||||
override LoadChainEndInstruction getEndInstruction() { result = end }
|
||||
|
||||
override FieldAddressInstruction getFieldInstruction() { result = fi }
|
||||
}
|
||||
|
||||
private class LoadChainConsCons extends LoadChain, TLoadChainConsCons {
|
||||
FieldAddressInstruction fi;
|
||||
LoadChain next;
|
||||
|
||||
LoadChainConsCons() { this = TLoadChainConsCons(fi, next) }
|
||||
|
||||
override string toString() { result = fi.getField().toString() + "." + next.toString() }
|
||||
|
||||
override LoadChainEndInstruction getEndInstruction() { result = next.getEndInstruction() }
|
||||
|
||||
override LoadChain getChild() { result = next }
|
||||
|
||||
override FieldAddressInstruction getFieldInstruction() { result = fi }
|
||||
}
|
||||
|
||||
/**
|
||||
* A dataflow node generated by a partial definition.
|
||||
* The `StoreNode` class extends `ReadStepNode` to participate in reverse read steps.
|
||||
* A reverse read is a store step that is "inferred" by the DataFlow library. For example in the
|
||||
* assignment:
|
||||
* ```
|
||||
* a.b.c = x;
|
||||
* ```
|
||||
* Here, the access path after the store must reflect that a value has been stored into the field `c` of
|
||||
* the object at field `b`. The field `c` is added to the access path through a `storeStep`, and the
|
||||
* field `b` is inferred by the DataFlow library because there's a read step (reading the field `b`) from
|
||||
* the pre update node for `b.c` to the pre update node for `c`.
|
||||
*/
|
||||
private class StoreNode extends TStoreNode, StoreStepNode, ReadStepNode, PartialDefinitionNode {
|
||||
StoreChain storeChain;
|
||||
|
||||
StoreNode() { this = TStoreNode(storeChain) }
|
||||
|
||||
override string toString() { result = storeChain.toString() }
|
||||
|
||||
StoreChain getStoreChain() { result = storeChain }
|
||||
|
||||
override Node getPreUpdateNode() {
|
||||
result.(StoreNode).getStoreChain() = storeChain.getParent()
|
||||
or
|
||||
not exists(storeChain.getParent()) and
|
||||
result = storeChain.getEndInstruction().getPreUpdateNode()
|
||||
}
|
||||
|
||||
override Field getAField() { result = storeChain.getFieldInstruction().getField() }
|
||||
|
||||
override Node getStoredValue() {
|
||||
// Only the `StoreNode` attached to the end of the `StoreChain` has a `getStoredValue()`, so
|
||||
// this is the only `StoreNode` that matches storeStep.
|
||||
not exists(storeChain.getChild()) and result.asInstruction() = storeChain.getBeginInstruction()
|
||||
}
|
||||
|
||||
override Node getReadValue() { result = getPreUpdateNode() }
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override Function getFunction() { result = storeChain.getEndInstruction().getEnclosingFunction() }
|
||||
|
||||
override Type getType() { result = storeChain.getEndInstruction().getResultType() }
|
||||
|
||||
override Location getLocation() { result = storeChain.getEndInstruction().getLocation() }
|
||||
|
||||
override Expr getDefinedExpr() {
|
||||
result = storeChain.getAFieldInstruction().getObjectAddress().getUnconvertedResultExpression()
|
||||
}
|
||||
}
|
||||
|
||||
/** A dataflow node generated by loading from an address computed by a sequence of fields lookups. */
|
||||
private class LoadNode extends TLoadNode, ReadStepNode {
|
||||
LoadChain loadChain;
|
||||
|
||||
LoadNode() { this = TLoadNode(loadChain) }
|
||||
|
||||
override Field getAField() { result = loadChain.getFieldInstruction().getField() }
|
||||
|
||||
override Node getReadValue() {
|
||||
result.(LoadNode).getLoadChain() = loadChain.getParent()
|
||||
or
|
||||
not exists(loadChain.getParent()) and
|
||||
result.asInstruction() = loadChain.getEndInstruction().getReadValue()
|
||||
}
|
||||
|
||||
LoadChain getLoadChain() { result = loadChain }
|
||||
|
||||
override string toString() { result = loadChain.toString() }
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override Function getFunction() { result = loadChain.getEndInstruction().getEnclosingFunction() }
|
||||
|
||||
override Type getType() { result = loadChain.getEndInstruction().getResultType() }
|
||||
|
||||
override Location getLocation() { result = loadChain.getEndInstruction().getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the node corresponding to `instr`.
|
||||
*/
|
||||
@@ -848,22 +483,6 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFr
|
||||
*/
|
||||
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
simpleInstructionLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asInstruction())
|
||||
or
|
||||
// When flow has gone all the way through the chain of field accesses
|
||||
// `[f1,f2, ..., fn]` (from right to left) we add flow from f1 to the end instruction.
|
||||
exists(StoreNode synthFrom |
|
||||
synthFrom = nodeFrom and
|
||||
not exists(synthFrom.getStoreChain().getParent()) and
|
||||
synthFrom.getStoreChain().getEndInstruction() = nodeTo.asInstruction()
|
||||
)
|
||||
or
|
||||
// When flow has gone all the way through the chain of field accesses
|
||||
// `[f1, f2, ..., fn]` (from left to right) we add flow from fn to the end instruction.
|
||||
exists(LoadNode synthFrom |
|
||||
synthFrom = nodeFrom and
|
||||
not exists(synthFrom.getLoadChain().getChild()) and
|
||||
synthFrom.getLoadChain().getEndInstruction() = nodeTo.asInstruction()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
|
||||
@@ -26,7 +26,7 @@ private import TaintTrackingParameter::Private
|
||||
* To create a configuration, extend this class with a subclass whose
|
||||
* characteristic predicate is a unique singleton string. For example, write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* class MyAnalysisConfiguration extends TaintTracking::Configuration {
|
||||
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
|
||||
* // Override `isSource` and `isSink`.
|
||||
@@ -41,7 +41,7 @@ private import TaintTrackingParameter::Private
|
||||
* Then, to query whether there is flow between some `source` and `sink`,
|
||||
* write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
* ```
|
||||
*
|
||||
|
||||
@@ -26,7 +26,7 @@ private import TaintTrackingParameter::Private
|
||||
* To create a configuration, extend this class with a subclass whose
|
||||
* characteristic predicate is a unique singleton string. For example, write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* class MyAnalysisConfiguration extends TaintTracking::Configuration {
|
||||
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
|
||||
* // Override `isSource` and `isSink`.
|
||||
@@ -41,7 +41,7 @@ private import TaintTrackingParameter::Private
|
||||
* Then, to query whether there is flow between some `source` and `sink`,
|
||||
* write
|
||||
*
|
||||
* ```
|
||||
* ```ql
|
||||
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
* ```
|
||||
*
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes that represent the individual instructions in the IR for a function.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
import IRFunction
|
||||
import IRBlock
|
||||
@@ -27,7 +31,7 @@ private Instruction getAnInstructionAtLine(IRFunction irFunc, Language::File fil
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a single operation in the IR.
|
||||
* A single instruction in the IR.
|
||||
*/
|
||||
class Instruction extends Construction::TStageInstruction {
|
||||
Instruction() {
|
||||
@@ -36,6 +40,7 @@ class Instruction extends Construction::TStageInstruction {
|
||||
Construction::hasInstruction(this)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
final string toString() { result = getOpcode().toString() + ": " + getAST().toString() }
|
||||
|
||||
/**
|
||||
@@ -247,10 +252,12 @@ class Instruction extends Construction::TStageInstruction {
|
||||
* given by `getResultType()`.
|
||||
*
|
||||
* For example, the statement `y = x;` generates the following IR:
|
||||
* ```
|
||||
* r1_0(glval: int) = VariableAddress[x]
|
||||
* r1_1(int) = Load r1_0, mu0_1
|
||||
* r1_2(glval: int) = VariableAddress[y]
|
||||
* mu1_3(int) = Store r1_2, r1_1
|
||||
* ```
|
||||
*
|
||||
* The result of each `VariableAddress` instruction is a glvalue of type
|
||||
* `int`, representing the address of the corresponding integer variable. The
|
||||
@@ -399,6 +406,17 @@ class Instruction extends Construction::TStageInstruction {
|
||||
final Instruction getAPredecessor() { result = getPredecessor(_) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that refers to a variable.
|
||||
*
|
||||
* This class is used for any instruction whose operation fundamentally depends on a specific
|
||||
* variable. For example, it is used for `VariableAddress`, which returns the address of a specific
|
||||
* variable, and `InitializeParameter`, which returns the value that was passed to the specified
|
||||
* parameter by the caller. `VariableInstruction` is not used for `Load` or `Store` instructions
|
||||
* that happen to load from or store to a particular variable; in those cases, the memory location
|
||||
* being accessed is specified by the `AddressOperand` on the instruction, which may or may not be
|
||||
* defined by the result of a `VariableAddress` instruction.
|
||||
*/
|
||||
class VariableInstruction extends Instruction {
|
||||
IRVariable var;
|
||||
|
||||
@@ -406,6 +424,9 @@ class VariableInstruction extends Instruction {
|
||||
|
||||
override string getImmediateString() { result = var.toString() }
|
||||
|
||||
/**
|
||||
* Gets the variable that this instruction references.
|
||||
*/
|
||||
final IRVariable getIRVariable() { result = var }
|
||||
|
||||
/**
|
||||
@@ -414,6 +435,16 @@ class VariableInstruction extends Instruction {
|
||||
final Language::Variable getASTVariable() { result = var.(IRUserVariable).getVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that refers to a field of a class, struct, or union.
|
||||
*
|
||||
* This class is used for any instruction whose operation fundamentally depends on a specific
|
||||
* field. For example, it is used for `FieldAddress`, which computes the address of a specific
|
||||
* field on an object. `FieldInstruction` is not used for `Load` or `Store` instructions that happen
|
||||
* to load from or store to a particular field; in those cases, the memory location being accessed
|
||||
* is specified by the `AddressOperand` on the instruction, which may or may not be defined by the
|
||||
* result of a `FieldAddress` instruction.
|
||||
*/
|
||||
class FieldInstruction extends Instruction {
|
||||
Language::Field field;
|
||||
|
||||
@@ -421,9 +452,22 @@ class FieldInstruction extends Instruction {
|
||||
|
||||
final override string getImmediateString() { result = field.toString() }
|
||||
|
||||
/**
|
||||
* Gets the field that this instruction references.
|
||||
*/
|
||||
final Language::Field getField() { result = field }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that refers to a function.
|
||||
*
|
||||
* This class is used for any instruction whose operation fundamentally depends on a specific
|
||||
* function. For example, it is used for `FunctionAddress`, which returns the address of a specific
|
||||
* function. `FunctionInstruction` is not used for `Call` instructions that happen to call a
|
||||
* particular function; in that case, the function being called is specified by the
|
||||
* `CallTargetOperand` on the instruction, which may or may not be defined by the result of a
|
||||
* `FunctionAddress` instruction.
|
||||
*/
|
||||
class FunctionInstruction extends Instruction {
|
||||
Language::Function funcSymbol;
|
||||
|
||||
@@ -431,9 +475,15 @@ class FunctionInstruction extends Instruction {
|
||||
|
||||
final override string getImmediateString() { result = funcSymbol.toString() }
|
||||
|
||||
/**
|
||||
* Gets the function that this instruction references.
|
||||
*/
|
||||
final Language::Function getFunctionSymbol() { result = funcSymbol }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is a compile-time constant value.
|
||||
*/
|
||||
class ConstantValueInstruction extends Instruction {
|
||||
string value;
|
||||
|
||||
@@ -441,9 +491,18 @@ class ConstantValueInstruction extends Instruction {
|
||||
|
||||
final override string getImmediateString() { result = value }
|
||||
|
||||
/**
|
||||
* Gets the constant value of this instruction's result.
|
||||
*/
|
||||
final string getValue() { result = value }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that refers to an argument of a `Call` instruction.
|
||||
*
|
||||
* This instruction is used for side effects of a `Call` instruction that read or write memory
|
||||
* pointed to by one of the arguments of the call.
|
||||
*/
|
||||
class IndexedInstruction extends Instruction {
|
||||
int index;
|
||||
|
||||
@@ -451,26 +510,59 @@ class IndexedInstruction extends Instruction {
|
||||
|
||||
final override string getImmediateString() { result = index.toString() }
|
||||
|
||||
/**
|
||||
* Gets the zero-based index of the argument that this instruction references.
|
||||
*/
|
||||
final int getIndex() { result = index }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the entry point to a function.
|
||||
*
|
||||
* Each `IRFunction` has exactly one `EnterFunction` instruction. Execution of the function begins
|
||||
* at this instruction. This instruction has no predecessors.
|
||||
*/
|
||||
class EnterFunctionInstruction extends Instruction {
|
||||
EnterFunctionInstruction() { getOpcode() instanceof Opcode::EnterFunction }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns the address of a variable.
|
||||
*
|
||||
* This instruction returns the address of a local variable, parameter, static field,
|
||||
* namespace-scope variable, or global variable. For the address of a non-static field of a class,
|
||||
* struct, or union, see `FieldAddressInstruction`.
|
||||
*/
|
||||
class VariableAddressInstruction extends VariableInstruction {
|
||||
VariableAddressInstruction() { getOpcode() instanceof Opcode::VariableAddress }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that initializes a parameter of the enclosing function with the value of the
|
||||
* corresponding argument passed by the caller.
|
||||
*
|
||||
* Each parameter of a function will have exactly one `InitializeParameter` instruction that
|
||||
* initializes that parameter.
|
||||
*/
|
||||
class InitializeParameterInstruction extends VariableInstruction {
|
||||
InitializeParameterInstruction() { getOpcode() instanceof Opcode::InitializeParameter }
|
||||
|
||||
/**
|
||||
* Gets the parameter initialized by this instruction.
|
||||
*/
|
||||
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that initializes the memory pointed to by a parameter of the enclosing function
|
||||
* with the value of that memory on entry to the function.
|
||||
*/
|
||||
class InitializeIndirectionInstruction extends VariableInstruction {
|
||||
InitializeIndirectionInstruction() { getOpcode() instanceof Opcode::InitializeIndirection }
|
||||
|
||||
/**
|
||||
* Gets the parameter initialized by this instruction.
|
||||
*/
|
||||
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
|
||||
}
|
||||
|
||||
@@ -481,11 +573,20 @@ class InitializeThisInstruction extends Instruction {
|
||||
InitializeThisInstruction() { getOpcode() instanceof Opcode::InitializeThis }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the address of a non-static field of an object.
|
||||
*/
|
||||
class FieldAddressInstruction extends FieldInstruction {
|
||||
FieldAddressInstruction() { getOpcode() instanceof Opcode::FieldAddress }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the address of the object containing the field.
|
||||
*/
|
||||
final UnaryOperand getObjectAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the address of the object containing the field.
|
||||
*/
|
||||
final Instruction getObjectAddress() { result = getObjectAddressOperand().getDef() }
|
||||
}
|
||||
|
||||
@@ -503,6 +604,12 @@ class ErrorInstruction extends Instruction {
|
||||
ErrorInstruction() { getOpcode() instanceof Opcode::Error }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns an uninitialized value.
|
||||
*
|
||||
* This instruction is used to provide an initial definition for a stack variable that does not have
|
||||
* an initializer, or whose initializer only partially initializes the variable.
|
||||
*/
|
||||
class UninitializedInstruction extends VariableInstruction {
|
||||
UninitializedInstruction() { getOpcode() instanceof Opcode::Uninitialized }
|
||||
|
||||
@@ -512,35 +619,94 @@ class UninitializedInstruction extends VariableInstruction {
|
||||
final Language::Variable getLocalVariable() { result = var.(IRUserVariable).getVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that has no effect.
|
||||
*
|
||||
* This instruction is typically inserted to ensure that a particular AST is associated with at
|
||||
* least one instruction, even when the AST has no semantic effect.
|
||||
*/
|
||||
class NoOpInstruction extends Instruction {
|
||||
NoOpInstruction() { getOpcode() instanceof Opcode::NoOp }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns control to the caller of the function.
|
||||
*
|
||||
* This instruction represents the normal (non-exception) return from a function, either from an
|
||||
* explicit `return` statement or from control flow reaching the end of the function's body.
|
||||
*
|
||||
* Each function has exactly one `ReturnInstruction`. Each `return` statement in a function is
|
||||
* represented as an initialization of the temporary variable that holds the return value, with
|
||||
* control then flowing to the common `ReturnInstruction` for that function. Exception: A function
|
||||
* that never returns will not have a `ReturnInstruction`.
|
||||
*
|
||||
* The `ReturnInstruction` for a function will have a control-flow successor edge to a block
|
||||
* containing the `ExitFunction` instruction for that function.
|
||||
*
|
||||
* There are two differet return instructions: `ReturnValueInstruction`, for returning a value from
|
||||
* a non-`void`-returning function, and `ReturnVoidInstruction`, for returning from a
|
||||
* `void`-returning function.
|
||||
*/
|
||||
class ReturnInstruction extends Instruction {
|
||||
ReturnInstruction() { getOpcode() instanceof ReturnOpcode }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns control to the caller of the function, without returning a value.
|
||||
*/
|
||||
class ReturnVoidInstruction extends ReturnInstruction {
|
||||
ReturnVoidInstruction() { getOpcode() instanceof Opcode::ReturnVoid }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns control to the caller of the function, including a return value.
|
||||
*/
|
||||
class ReturnValueInstruction extends ReturnInstruction {
|
||||
ReturnValueInstruction() { getOpcode() instanceof Opcode::ReturnValue }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the value being returned by the function.
|
||||
*/
|
||||
final LoadOperand getReturnValueOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the value being returned by the function, if an
|
||||
* exact definition is available.
|
||||
*/
|
||||
final Instruction getReturnValue() { result = getReturnValueOperand().getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that represents the use of the value pointed to by a parameter of the function
|
||||
* after the function returns control to its caller.
|
||||
*
|
||||
* This instruction does not itself return control to the caller. It merely represents the potential
|
||||
* for a caller to use the memory pointed to by the parameter sometime after the call returns. This
|
||||
* is the counterpart to the `InitializeIndirection` instruction, which represents the possibility
|
||||
* that the caller initialized the memory pointed to by the parameter before the call.
|
||||
*/
|
||||
class ReturnIndirectionInstruction extends VariableInstruction {
|
||||
ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the value of the pointed-to memory.
|
||||
*/
|
||||
final SideEffectOperand getSideEffectOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the value of the pointed-to memory, if an exact
|
||||
* definition is available.
|
||||
*/
|
||||
final Instruction getSideEffect() { result = getSideEffectOperand().getDef() }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the address of the pointed-to memory.
|
||||
*/
|
||||
final AddressOperand getSourceAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the address of the pointed-to memory.
|
||||
*/
|
||||
final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() }
|
||||
|
||||
/**
|
||||
@@ -555,60 +721,128 @@ class ReturnIndirectionInstruction extends VariableInstruction {
|
||||
final predicate isThisIndirection() { var instanceof IRThisVariable }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a copy of its operand.
|
||||
*
|
||||
* There are several different copy instructions, depending on the source and destination of the
|
||||
* copy operation:
|
||||
* - `CopyInstruction` - Copies a register operand to a register result.
|
||||
* - `LoadInstruction` - Copies a memory operand to a register result.
|
||||
* - `StoreInstruction` - Copies a register operand to a memory result.
|
||||
*/
|
||||
class CopyInstruction extends Instruction {
|
||||
CopyInstruction() { getOpcode() instanceof CopyOpcode }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the input value of the copy.
|
||||
*/
|
||||
Operand getSourceValueOperand() { none() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the input value of the copy, if an exact definition
|
||||
* is available.
|
||||
*/
|
||||
final Instruction getSourceValue() { result = getSourceValueOperand().getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a register result containing a copy of its register operand.
|
||||
*/
|
||||
class CopyValueInstruction extends CopyInstruction, UnaryInstruction {
|
||||
CopyValueInstruction() { getOpcode() instanceof Opcode::CopyValue }
|
||||
|
||||
final override UnaryOperand getSourceValueOperand() { result = getAnOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a register result containing a copy of its memory operand.
|
||||
*/
|
||||
class LoadInstruction extends CopyInstruction {
|
||||
LoadInstruction() { getOpcode() instanceof Opcode::Load }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the address of the value being loaded.
|
||||
*/
|
||||
final AddressOperand getSourceAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the address of the value being loaded.
|
||||
*/
|
||||
final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() }
|
||||
|
||||
final override LoadOperand getSourceValueOperand() { result = getAnOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a memory result containing a copy of its register operand.
|
||||
*/
|
||||
class StoreInstruction extends CopyInstruction {
|
||||
StoreInstruction() { getOpcode() instanceof Opcode::Store }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the address of the location to which the value will be stored.
|
||||
*/
|
||||
final AddressOperand getDestinationAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the address of the location to which the value will
|
||||
* be stored, if an exact definition is available.
|
||||
*/
|
||||
final Instruction getDestinationAddress() { result = getDestinationAddressOperand().getDef() }
|
||||
|
||||
final override StoreValueOperand getSourceValueOperand() { result = getAnOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that branches to one of two successor instructions based on the value of a Boolean
|
||||
* operand.
|
||||
*/
|
||||
class ConditionalBranchInstruction extends Instruction {
|
||||
ConditionalBranchInstruction() { getOpcode() instanceof Opcode::ConditionalBranch }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the Boolean condition controlling the branch.
|
||||
*/
|
||||
final ConditionOperand getConditionOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the Boolean condition controlling the branch.
|
||||
*/
|
||||
final Instruction getCondition() { result = getConditionOperand().getDef() }
|
||||
|
||||
/**
|
||||
* Gets the instruction to which control will flow if the condition is true.
|
||||
*/
|
||||
final Instruction getTrueSuccessor() { result = getSuccessor(EdgeKind::trueEdge()) }
|
||||
|
||||
/**
|
||||
* Gets the instruction to which control will flow if the condition is false.
|
||||
*/
|
||||
final Instruction getFalseSuccessor() { result = getSuccessor(EdgeKind::falseEdge()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the exit point of a function.
|
||||
*
|
||||
* Each `IRFunction` has exactly one `ExitFunction` instruction, unless the function neither returns
|
||||
* nor throws an exception. Control flows to the `ExitFunction` instruction from both normal returns
|
||||
* (`ReturnVoid`, `ReturnValue`) and propagated exceptions (`Unwind`). This instruction has no
|
||||
* successors.
|
||||
*/
|
||||
class ExitFunctionInstruction extends Instruction {
|
||||
ExitFunctionInstruction() { getOpcode() instanceof Opcode::ExitFunction }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is a constant value.
|
||||
*/
|
||||
class ConstantInstruction extends ConstantValueInstruction {
|
||||
ConstantInstruction() { getOpcode() instanceof Opcode::Constant }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is a constant value of integer or Boolean type.
|
||||
*/
|
||||
class IntegerConstantInstruction extends ConstantInstruction {
|
||||
IntegerConstantInstruction() {
|
||||
exists(IRType resultType |
|
||||
@@ -618,27 +852,53 @@ class IntegerConstantInstruction extends ConstantInstruction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is a constant value of floating-point type.
|
||||
*/
|
||||
class FloatConstantInstruction extends ConstantInstruction {
|
||||
FloatConstantInstruction() { getResultIRType() instanceof IRFloatingPointType }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is the address of a string literal.
|
||||
*/
|
||||
class StringConstantInstruction extends VariableInstruction {
|
||||
override IRStringLiteral var;
|
||||
|
||||
final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) }
|
||||
|
||||
/**
|
||||
* Gets the string literal whose address is returned by this instruction.
|
||||
*/
|
||||
final Language::StringLiteral getValue() { result = var.getLiteral() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is computed from two operands.
|
||||
*/
|
||||
class BinaryInstruction extends Instruction {
|
||||
BinaryInstruction() { getOpcode() instanceof BinaryOpcode }
|
||||
|
||||
/**
|
||||
* Gets the left operand of this binary instruction.
|
||||
*/
|
||||
final LeftOperand getLeftOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the right operand of this binary instruction.
|
||||
*/
|
||||
final RightOperand getRightOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the value of the left operand of this binary
|
||||
* instruction.
|
||||
*/
|
||||
final Instruction getLeft() { result = getLeftOperand().getDef() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the value of the right operand of this binary
|
||||
* instruction.
|
||||
*/
|
||||
final Instruction getRight() { result = getRightOperand().getDef() }
|
||||
|
||||
/**
|
||||
@@ -651,66 +911,161 @@ class BinaryInstruction extends Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the result of an arithmetic operation.
|
||||
*/
|
||||
class ArithmeticInstruction extends Instruction {
|
||||
ArithmeticInstruction() { getOpcode() instanceof ArithmeticOpcode }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that performs an arithmetic operation on two numeric operands.
|
||||
*/
|
||||
class BinaryArithmeticInstruction extends ArithmeticInstruction, BinaryInstruction { }
|
||||
|
||||
/**
|
||||
* An instruction whose result is computed by performing an arithmetic operation on a single
|
||||
* numeric operand.
|
||||
*/
|
||||
class UnaryArithmeticInstruction extends ArithmeticInstruction, UnaryInstruction { }
|
||||
|
||||
/**
|
||||
* An instruction that computes the sum of two numeric operands.
|
||||
*
|
||||
* Both operands must have the same numeric type, which will also be the result type. The result of
|
||||
* integer overflow is the infinite-precision result modulo 2^n. Floating-point addition is
|
||||
* performed according to IEEE-754.
|
||||
*/
|
||||
class AddInstruction extends BinaryArithmeticInstruction {
|
||||
AddInstruction() { getOpcode() instanceof Opcode::Add }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the difference of two numeric operands.
|
||||
*
|
||||
* Both operands must have the same numeric type, which will also be the result type. The result of
|
||||
* integer overflow is the infinite-precision result modulo 2^n. Floating-point subtraction is performed
|
||||
* according to IEEE-754.
|
||||
*/
|
||||
class SubInstruction extends BinaryArithmeticInstruction {
|
||||
SubInstruction() { getOpcode() instanceof Opcode::Sub }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the product of two numeric operands.
|
||||
*
|
||||
* Both operands must have the same numeric type, which will also be the result type. The result of
|
||||
* integer overflow is the infinite-precision result modulo 2^n. Floating-point multiplication is
|
||||
* performed according to IEEE-754.
|
||||
*/
|
||||
class MulInstruction extends BinaryArithmeticInstruction {
|
||||
MulInstruction() { getOpcode() instanceof Opcode::Mul }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the quotient of two numeric operands.
|
||||
*
|
||||
* Both operands must have the same numeric type, which will also be the result type. The result of
|
||||
* division by zero or integer overflow is undefined. Floating-point division is performed according
|
||||
* to IEEE-754.
|
||||
*/
|
||||
class DivInstruction extends BinaryArithmeticInstruction {
|
||||
DivInstruction() { getOpcode() instanceof Opcode::Div }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the remainder of two integer operands.
|
||||
*
|
||||
* Both operands must have the same integer type, which will also be the result type. The result of
|
||||
* division by zero or integer overflow is undefined.
|
||||
*/
|
||||
class RemInstruction extends BinaryArithmeticInstruction {
|
||||
RemInstruction() { getOpcode() instanceof Opcode::Rem }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that negates a single numeric operand.
|
||||
*
|
||||
* The operand must have a numeric type, which will also be the result type. The result of integer
|
||||
* negation uses two's complement, and is computed modulo 2^n. The result of floating-point negation
|
||||
* is performed according to IEEE-754.
|
||||
*/
|
||||
class NegateInstruction extends UnaryArithmeticInstruction {
|
||||
NegateInstruction() { getOpcode() instanceof Opcode::Negate }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the result of a bitwise operation.
|
||||
*/
|
||||
class BitwiseInstruction extends Instruction {
|
||||
BitwiseInstruction() { getOpcode() instanceof BitwiseOpcode }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that performs a bitwise operation on two integer operands.
|
||||
*/
|
||||
class BinaryBitwiseInstruction extends BitwiseInstruction, BinaryInstruction { }
|
||||
|
||||
/**
|
||||
* An instruction that performs a bitwise operation on a single integer operand.
|
||||
*/
|
||||
class UnaryBitwiseInstruction extends BitwiseInstruction, UnaryInstruction { }
|
||||
|
||||
/**
|
||||
* An instruction that computes the bitwise "and" of two integer operands.
|
||||
*
|
||||
* Both operands must have the same integer type, which will also be the result type.
|
||||
*/
|
||||
class BitAndInstruction extends BinaryBitwiseInstruction {
|
||||
BitAndInstruction() { getOpcode() instanceof Opcode::BitAnd }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the bitwise "or" of two integer operands.
|
||||
*
|
||||
* Both operands must have the same integer type, which will also be the result type.
|
||||
*/
|
||||
class BitOrInstruction extends BinaryBitwiseInstruction {
|
||||
BitOrInstruction() { getOpcode() instanceof Opcode::BitOr }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the bitwise "xor" of two integer operands.
|
||||
*
|
||||
* Both operands must have the same integer type, which will also be the result type.
|
||||
*/
|
||||
class BitXorInstruction extends BinaryBitwiseInstruction {
|
||||
BitXorInstruction() { getOpcode() instanceof Opcode::BitXor }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that shifts its left operand to the left by the number of bits specified by its
|
||||
* right operand.
|
||||
*
|
||||
* Both operands must have an integer type. The result has the same type as the left operand. The
|
||||
* rightmost bits are zero-filled.
|
||||
*/
|
||||
class ShiftLeftInstruction extends BinaryBitwiseInstruction {
|
||||
ShiftLeftInstruction() { getOpcode() instanceof Opcode::ShiftLeft }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that shifts its left operand to the right by the number of bits specified by its
|
||||
* right operand.
|
||||
*
|
||||
* Both operands must have an integer type. The result has the same type as the left operand. If the
|
||||
* left operand has an unsigned integer type, the leftmost bits are zero-filled. If the left operand
|
||||
* has a signed integer type, the leftmost bits are filled by duplicating the most significant bit
|
||||
* of the left operand.
|
||||
*/
|
||||
class ShiftRightInstruction extends BinaryBitwiseInstruction {
|
||||
ShiftRightInstruction() { getOpcode() instanceof Opcode::ShiftRight }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that performs a binary arithmetic operation involving at least one pointer
|
||||
* operand.
|
||||
*/
|
||||
class PointerArithmeticInstruction extends BinaryInstruction {
|
||||
int elementSize;
|
||||
|
||||
@@ -721,25 +1076,64 @@ class PointerArithmeticInstruction extends BinaryInstruction {
|
||||
|
||||
final override string getImmediateString() { result = elementSize.toString() }
|
||||
|
||||
/**
|
||||
* Gets the size of the elements pointed to by the pointer operands, in bytes.
|
||||
*
|
||||
* When adding an integer offset to a pointer (`PointerAddInstruction`) or subtracting an integer
|
||||
* offset from a pointer (`PointerSubInstruction`), the integer offset is multiplied by the
|
||||
* element size to compute the actual number of bytes added to or subtracted from the pointer
|
||||
* address. When computing the integer difference between two pointers (`PointerDiffInstruction`),
|
||||
* the result is computed by computing the difference between the two pointer byte addresses, then
|
||||
* dividing that byte count by the element size.
|
||||
*/
|
||||
final int getElementSize() { result = elementSize }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that adds or subtracts an integer offset from a pointer.
|
||||
*/
|
||||
class PointerOffsetInstruction extends PointerArithmeticInstruction {
|
||||
PointerOffsetInstruction() { getOpcode() instanceof PointerOffsetOpcode }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that adds an integer offset to a pointer.
|
||||
*
|
||||
* The result is the byte address computed by adding the value of the right (integer) operand,
|
||||
* multiplied by the element size, to the value of the left (pointer) operand. The result of pointer
|
||||
* overflow is undefined.
|
||||
*/
|
||||
class PointerAddInstruction extends PointerOffsetInstruction {
|
||||
PointerAddInstruction() { getOpcode() instanceof Opcode::PointerAdd }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that subtracts an integer offset from a pointer.
|
||||
*
|
||||
* The result is the byte address computed by subtracting the value of the right (integer) operand,
|
||||
* multiplied by the element size, from the value of the left (pointer) operand. The result of
|
||||
* pointer underflow is undefined.
|
||||
*/
|
||||
class PointerSubInstruction extends PointerOffsetInstruction {
|
||||
PointerSubInstruction() { getOpcode() instanceof Opcode::PointerSub }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the difference between two pointers.
|
||||
*
|
||||
* Both operands must have the same pointer type. The result must have an integer type whose size is
|
||||
* the same as that of the pointer operands. The result is computed by subtracting the byte address
|
||||
* in the right operand from the byte address in the left operand, and dividing by the element size.
|
||||
* If the difference in byte addresses is not divisible by the element size, the result is
|
||||
* undefined.
|
||||
*/
|
||||
class PointerDiffInstruction extends PointerArithmeticInstruction {
|
||||
PointerDiffInstruction() { getOpcode() instanceof Opcode::PointerDiff }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is computed from a single operand.
|
||||
*/
|
||||
class UnaryInstruction extends Instruction {
|
||||
UnaryInstruction() { getOpcode() instanceof UnaryOpcode }
|
||||
|
||||
@@ -748,17 +1142,44 @@ class UnaryInstruction extends Instruction {
|
||||
final Instruction getUnary() { result = getUnaryOperand().getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that converts the value of its operand to a value of a different type.
|
||||
*/
|
||||
class ConvertInstruction extends UnaryInstruction {
|
||||
ConvertInstruction() { getOpcode() instanceof Opcode::Convert }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that converts the address of a polymorphic object to the address of a different
|
||||
* subobject of the same polymorphic object, returning a null address if the dynamic type of the
|
||||
* object is not compatible with the result type.
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*
|
||||
* This instruction is used to represent a C++ `dynamic_cast<>` to a pointer type, or a C# `is` or
|
||||
* `as` expression.
|
||||
*/
|
||||
class CheckedConvertOrNullInstruction extends UnaryInstruction {
|
||||
CheckedConvertOrNullInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrNull }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instruction that converts between two addresses
|
||||
* related by inheritance.
|
||||
* An instruction that converts the address of a polymorphic object to the address of a different
|
||||
* subobject of the same polymorphic object, throwing an exception if the dynamic type of the object
|
||||
* is not compatible with the result type.
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*
|
||||
* This instruction is used to represent a C++ `dynamic_cast<>` to a reference type, or a C# cast
|
||||
* expression.
|
||||
*/
|
||||
class CheckedConvertOrThrowInstruction extends UnaryInstruction {
|
||||
CheckedConvertOrThrowInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrThrow }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that converts the address of an object to the address of a different subobject of
|
||||
* the same object, without any type checking at runtime.
|
||||
*/
|
||||
class InheritanceConversionInstruction extends UnaryInstruction {
|
||||
Language::Class baseClass;
|
||||
@@ -795,59 +1216,91 @@ class InheritanceConversionInstruction extends UnaryInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instruction that converts from the address of a derived class
|
||||
* to the address of a base class.
|
||||
* An instruction that converts from the address of a derived class to the address of a base class.
|
||||
*/
|
||||
class ConvertToBaseInstruction extends InheritanceConversionInstruction {
|
||||
ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instruction that converts from the address of a derived class
|
||||
* to the address of a direct non-virtual base class.
|
||||
* An instruction that converts from the address of a derived class to the address of a direct
|
||||
* non-virtual base class.
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*/
|
||||
class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction {
|
||||
ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instruction that converts from the address of a derived class
|
||||
* to the address of a virtual base class.
|
||||
* An instruction that converts from the address of a derived class to the address of a virtual base
|
||||
* class.
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*/
|
||||
class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction {
|
||||
ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instruction that converts from the address of a base class
|
||||
* to the address of a direct non-virtual derived class.
|
||||
* An instruction that converts from the address of a base class to the address of a direct
|
||||
* non-virtual derived class.
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*/
|
||||
class ConvertToDerivedInstruction extends InheritanceConversionInstruction {
|
||||
ConvertToDerivedInstruction() { getOpcode() instanceof Opcode::ConvertToDerived }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the bitwise complement of its operand.
|
||||
*
|
||||
* The operand must have an integer type, which will also be the result type.
|
||||
*/
|
||||
class BitComplementInstruction extends UnaryBitwiseInstruction {
|
||||
BitComplementInstruction() { getOpcode() instanceof Opcode::BitComplement }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the logical complement of its operand.
|
||||
*
|
||||
* The operand must have a Boolean type, which will also be the result type.
|
||||
*/
|
||||
class LogicalNotInstruction extends UnaryInstruction {
|
||||
LogicalNotInstruction() { getOpcode() instanceof Opcode::LogicalNot }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that compares two numeric operands.
|
||||
*/
|
||||
class CompareInstruction extends BinaryInstruction {
|
||||
CompareInstruction() { getOpcode() instanceof CompareOpcode }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a `true` result if its operands are equal.
|
||||
*
|
||||
* Both operands must have the same numeric or address type. The result must have a Boolean type.
|
||||
* The result is `true` if `left == right`, and `false` if `left != right` or the two operands are
|
||||
* unordered. Floating-point comparison is performed according to IEEE-754.
|
||||
*/
|
||||
class CompareEQInstruction extends CompareInstruction {
|
||||
CompareEQInstruction() { getOpcode() instanceof Opcode::CompareEQ }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a `true` result if its operands are not equal.
|
||||
*
|
||||
* Both operands must have the same numeric or address type. The result must have a Boolean type.
|
||||
* The result is `true` if `left != right` or if the two operands are unordered, and `false` if
|
||||
* `left == right`. Floating-point comparison is performed according to IEEE-754.
|
||||
*/
|
||||
class CompareNEInstruction extends CompareInstruction {
|
||||
CompareNEInstruction() { getOpcode() instanceof Opcode::CompareNE }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instruction that does a relative comparison of two values, such as `<` or `>=`.
|
||||
* An instruction that does a relative comparison of two values, such as `<` or `>=`.
|
||||
*/
|
||||
class RelationalInstruction extends CompareInstruction {
|
||||
RelationalInstruction() { getOpcode() instanceof RelationalOpcode }
|
||||
@@ -874,6 +1327,13 @@ class RelationalInstruction extends CompareInstruction {
|
||||
predicate isStrict() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a `true` result if its left operand is less than its right operand.
|
||||
*
|
||||
* Both operands must have the same numeric or address type. The result must have a Boolean type.
|
||||
* The result is `true` if the `left < right`, and `false` if `left >= right` or if the two operands
|
||||
* are unordered. Floating-point comparison is performed according to IEEE-754.
|
||||
*/
|
||||
class CompareLTInstruction extends RelationalInstruction {
|
||||
CompareLTInstruction() { getOpcode() instanceof Opcode::CompareLT }
|
||||
|
||||
@@ -884,6 +1344,13 @@ class CompareLTInstruction extends RelationalInstruction {
|
||||
override predicate isStrict() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a `true` result if its left operand is greater than its right operand.
|
||||
*
|
||||
* Both operands must have the same numeric or address type. The result must have a Boolean type.
|
||||
* The result is `true` if the `left > right`, and `false` if `left <= right` or if the two operands
|
||||
* are unordered. Floating-point comparison is performed according to IEEE-754.
|
||||
*/
|
||||
class CompareGTInstruction extends RelationalInstruction {
|
||||
CompareGTInstruction() { getOpcode() instanceof Opcode::CompareGT }
|
||||
|
||||
@@ -894,6 +1361,14 @@ class CompareGTInstruction extends RelationalInstruction {
|
||||
override predicate isStrict() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a `true` result if its left operand is less than or equal to its
|
||||
* right operand.
|
||||
*
|
||||
* Both operands must have the same numeric or address type. The result must have a Boolean type.
|
||||
* The result is `true` if the `left <= right`, and `false` if `left > right` or if the two operands
|
||||
* are unordered. Floating-point comparison is performed according to IEEE-754.
|
||||
*/
|
||||
class CompareLEInstruction extends RelationalInstruction {
|
||||
CompareLEInstruction() { getOpcode() instanceof Opcode::CompareLE }
|
||||
|
||||
@@ -904,6 +1379,14 @@ class CompareLEInstruction extends RelationalInstruction {
|
||||
override predicate isStrict() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a `true` result if its left operand is greater than or equal to its
|
||||
* right operand.
|
||||
*
|
||||
* Both operands must have the same numeric or address type. The result must have a Boolean type.
|
||||
* The result is `true` if the `left >= right`, and `false` if `left < right` or if the two operands
|
||||
* are unordered. Floating-point comparison is performed according to IEEE-754.
|
||||
*/
|
||||
class CompareGEInstruction extends RelationalInstruction {
|
||||
CompareGEInstruction() { getOpcode() instanceof Opcode::CompareGE }
|
||||
|
||||
@@ -914,15 +1397,32 @@ class CompareGEInstruction extends RelationalInstruction {
|
||||
override predicate isStrict() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that branches to one of multiple successor instructions based on the value of an
|
||||
* integer operand.
|
||||
*
|
||||
* This instruction will have zero or more successors whose edge kind is `CaseEdge`, each
|
||||
* representing the branch that will be taken if the controlling expression is within the range
|
||||
* specified for that case edge. The range of a case edge must be disjoint from the range of each
|
||||
* other case edge.
|
||||
*
|
||||
* The instruction may optionally have a successor edge whose edge kind is `DefaultEdge`,
|
||||
* representing the branch that will be taken if the controlling expression is not within the range
|
||||
* of any case edge.
|
||||
*/
|
||||
class SwitchInstruction extends Instruction {
|
||||
SwitchInstruction() { getOpcode() instanceof Opcode::Switch }
|
||||
|
||||
/** Gets the operand that provides the integer value controlling the switch. */
|
||||
final ConditionOperand getExpressionOperand() { result = getAnOperand() }
|
||||
|
||||
/** Gets the instruction whose result provides the integer value controlling the switch. */
|
||||
final Instruction getExpression() { result = getExpressionOperand().getDef() }
|
||||
|
||||
/** Gets the successor instructions along the case edges of the switch. */
|
||||
final Instruction getACaseSuccessor() { exists(CaseEdge edge | result = getSuccessor(edge)) }
|
||||
|
||||
/** Gets the successor instruction along the default edge of the switch, if any. */
|
||||
final Instruction getDefaultSuccessor() { result = getSuccessor(EdgeKind::defaultEdge()) }
|
||||
}
|
||||
|
||||
@@ -998,6 +1498,9 @@ class CallInstruction extends Instruction {
|
||||
class SideEffectInstruction extends Instruction {
|
||||
SideEffectInstruction() { getOpcode() instanceof SideEffectOpcode }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose execution causes this side effect.
|
||||
*/
|
||||
final Instruction getPrimaryInstruction() {
|
||||
result = Construction::getPrimaryInstructionForSideEffect(this)
|
||||
}
|
||||
|
||||
@@ -196,16 +196,17 @@ private predicate operandReturned(Operand operand, IntValue bitOffset) {
|
||||
bitOffset = Ints::unknown()
|
||||
}
|
||||
|
||||
private predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instruction init) {
|
||||
private predicate isArgumentForParameter(
|
||||
CallInstruction ci, Operand operand, InitializeParameterInstruction init
|
||||
) {
|
||||
exists(Language::Function f |
|
||||
ci = operand.getUse() and
|
||||
f = ci.getStaticCallTarget() and
|
||||
(
|
||||
init.(InitializeParameterInstruction).getParameter() =
|
||||
f.getParameter(operand.(PositionalArgumentOperand).getIndex())
|
||||
init.getParameter() = f.getParameter(operand.(PositionalArgumentOperand).getIndex())
|
||||
or
|
||||
init.(InitializeParameterInstruction).getIRVariable() instanceof IRThisVariable and
|
||||
init.getEnclosingFunction() = f and
|
||||
init.getIRVariable() instanceof IRThisVariable and
|
||||
unique( | | init.getEnclosingFunction()) = f and
|
||||
operand instanceof ThisArgumentOperand
|
||||
) and
|
||||
not Language::isFunctionVirtual(f) and
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes that represent the individual instructions in the IR for a function.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
import IRFunction
|
||||
import IRBlock
|
||||
@@ -27,7 +31,7 @@ private Instruction getAnInstructionAtLine(IRFunction irFunc, Language::File fil
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a single operation in the IR.
|
||||
* A single instruction in the IR.
|
||||
*/
|
||||
class Instruction extends Construction::TStageInstruction {
|
||||
Instruction() {
|
||||
@@ -36,6 +40,7 @@ class Instruction extends Construction::TStageInstruction {
|
||||
Construction::hasInstruction(this)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
final string toString() { result = getOpcode().toString() + ": " + getAST().toString() }
|
||||
|
||||
/**
|
||||
@@ -247,10 +252,12 @@ class Instruction extends Construction::TStageInstruction {
|
||||
* given by `getResultType()`.
|
||||
*
|
||||
* For example, the statement `y = x;` generates the following IR:
|
||||
* ```
|
||||
* r1_0(glval: int) = VariableAddress[x]
|
||||
* r1_1(int) = Load r1_0, mu0_1
|
||||
* r1_2(glval: int) = VariableAddress[y]
|
||||
* mu1_3(int) = Store r1_2, r1_1
|
||||
* ```
|
||||
*
|
||||
* The result of each `VariableAddress` instruction is a glvalue of type
|
||||
* `int`, representing the address of the corresponding integer variable. The
|
||||
@@ -399,6 +406,17 @@ class Instruction extends Construction::TStageInstruction {
|
||||
final Instruction getAPredecessor() { result = getPredecessor(_) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that refers to a variable.
|
||||
*
|
||||
* This class is used for any instruction whose operation fundamentally depends on a specific
|
||||
* variable. For example, it is used for `VariableAddress`, which returns the address of a specific
|
||||
* variable, and `InitializeParameter`, which returns the value that was passed to the specified
|
||||
* parameter by the caller. `VariableInstruction` is not used for `Load` or `Store` instructions
|
||||
* that happen to load from or store to a particular variable; in those cases, the memory location
|
||||
* being accessed is specified by the `AddressOperand` on the instruction, which may or may not be
|
||||
* defined by the result of a `VariableAddress` instruction.
|
||||
*/
|
||||
class VariableInstruction extends Instruction {
|
||||
IRVariable var;
|
||||
|
||||
@@ -406,6 +424,9 @@ class VariableInstruction extends Instruction {
|
||||
|
||||
override string getImmediateString() { result = var.toString() }
|
||||
|
||||
/**
|
||||
* Gets the variable that this instruction references.
|
||||
*/
|
||||
final IRVariable getIRVariable() { result = var }
|
||||
|
||||
/**
|
||||
@@ -414,6 +435,16 @@ class VariableInstruction extends Instruction {
|
||||
final Language::Variable getASTVariable() { result = var.(IRUserVariable).getVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that refers to a field of a class, struct, or union.
|
||||
*
|
||||
* This class is used for any instruction whose operation fundamentally depends on a specific
|
||||
* field. For example, it is used for `FieldAddress`, which computes the address of a specific
|
||||
* field on an object. `FieldInstruction` is not used for `Load` or `Store` instructions that happen
|
||||
* to load from or store to a particular field; in those cases, the memory location being accessed
|
||||
* is specified by the `AddressOperand` on the instruction, which may or may not be defined by the
|
||||
* result of a `FieldAddress` instruction.
|
||||
*/
|
||||
class FieldInstruction extends Instruction {
|
||||
Language::Field field;
|
||||
|
||||
@@ -421,9 +452,22 @@ class FieldInstruction extends Instruction {
|
||||
|
||||
final override string getImmediateString() { result = field.toString() }
|
||||
|
||||
/**
|
||||
* Gets the field that this instruction references.
|
||||
*/
|
||||
final Language::Field getField() { result = field }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that refers to a function.
|
||||
*
|
||||
* This class is used for any instruction whose operation fundamentally depends on a specific
|
||||
* function. For example, it is used for `FunctionAddress`, which returns the address of a specific
|
||||
* function. `FunctionInstruction` is not used for `Call` instructions that happen to call a
|
||||
* particular function; in that case, the function being called is specified by the
|
||||
* `CallTargetOperand` on the instruction, which may or may not be defined by the result of a
|
||||
* `FunctionAddress` instruction.
|
||||
*/
|
||||
class FunctionInstruction extends Instruction {
|
||||
Language::Function funcSymbol;
|
||||
|
||||
@@ -431,9 +475,15 @@ class FunctionInstruction extends Instruction {
|
||||
|
||||
final override string getImmediateString() { result = funcSymbol.toString() }
|
||||
|
||||
/**
|
||||
* Gets the function that this instruction references.
|
||||
*/
|
||||
final Language::Function getFunctionSymbol() { result = funcSymbol }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is a compile-time constant value.
|
||||
*/
|
||||
class ConstantValueInstruction extends Instruction {
|
||||
string value;
|
||||
|
||||
@@ -441,9 +491,18 @@ class ConstantValueInstruction extends Instruction {
|
||||
|
||||
final override string getImmediateString() { result = value }
|
||||
|
||||
/**
|
||||
* Gets the constant value of this instruction's result.
|
||||
*/
|
||||
final string getValue() { result = value }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that refers to an argument of a `Call` instruction.
|
||||
*
|
||||
* This instruction is used for side effects of a `Call` instruction that read or write memory
|
||||
* pointed to by one of the arguments of the call.
|
||||
*/
|
||||
class IndexedInstruction extends Instruction {
|
||||
int index;
|
||||
|
||||
@@ -451,26 +510,59 @@ class IndexedInstruction extends Instruction {
|
||||
|
||||
final override string getImmediateString() { result = index.toString() }
|
||||
|
||||
/**
|
||||
* Gets the zero-based index of the argument that this instruction references.
|
||||
*/
|
||||
final int getIndex() { result = index }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the entry point to a function.
|
||||
*
|
||||
* Each `IRFunction` has exactly one `EnterFunction` instruction. Execution of the function begins
|
||||
* at this instruction. This instruction has no predecessors.
|
||||
*/
|
||||
class EnterFunctionInstruction extends Instruction {
|
||||
EnterFunctionInstruction() { getOpcode() instanceof Opcode::EnterFunction }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns the address of a variable.
|
||||
*
|
||||
* This instruction returns the address of a local variable, parameter, static field,
|
||||
* namespace-scope variable, or global variable. For the address of a non-static field of a class,
|
||||
* struct, or union, see `FieldAddressInstruction`.
|
||||
*/
|
||||
class VariableAddressInstruction extends VariableInstruction {
|
||||
VariableAddressInstruction() { getOpcode() instanceof Opcode::VariableAddress }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that initializes a parameter of the enclosing function with the value of the
|
||||
* corresponding argument passed by the caller.
|
||||
*
|
||||
* Each parameter of a function will have exactly one `InitializeParameter` instruction that
|
||||
* initializes that parameter.
|
||||
*/
|
||||
class InitializeParameterInstruction extends VariableInstruction {
|
||||
InitializeParameterInstruction() { getOpcode() instanceof Opcode::InitializeParameter }
|
||||
|
||||
/**
|
||||
* Gets the parameter initialized by this instruction.
|
||||
*/
|
||||
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that initializes the memory pointed to by a parameter of the enclosing function
|
||||
* with the value of that memory on entry to the function.
|
||||
*/
|
||||
class InitializeIndirectionInstruction extends VariableInstruction {
|
||||
InitializeIndirectionInstruction() { getOpcode() instanceof Opcode::InitializeIndirection }
|
||||
|
||||
/**
|
||||
* Gets the parameter initialized by this instruction.
|
||||
*/
|
||||
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
|
||||
}
|
||||
|
||||
@@ -481,11 +573,20 @@ class InitializeThisInstruction extends Instruction {
|
||||
InitializeThisInstruction() { getOpcode() instanceof Opcode::InitializeThis }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the address of a non-static field of an object.
|
||||
*/
|
||||
class FieldAddressInstruction extends FieldInstruction {
|
||||
FieldAddressInstruction() { getOpcode() instanceof Opcode::FieldAddress }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the address of the object containing the field.
|
||||
*/
|
||||
final UnaryOperand getObjectAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the address of the object containing the field.
|
||||
*/
|
||||
final Instruction getObjectAddress() { result = getObjectAddressOperand().getDef() }
|
||||
}
|
||||
|
||||
@@ -503,6 +604,12 @@ class ErrorInstruction extends Instruction {
|
||||
ErrorInstruction() { getOpcode() instanceof Opcode::Error }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns an uninitialized value.
|
||||
*
|
||||
* This instruction is used to provide an initial definition for a stack variable that does not have
|
||||
* an initializer, or whose initializer only partially initializes the variable.
|
||||
*/
|
||||
class UninitializedInstruction extends VariableInstruction {
|
||||
UninitializedInstruction() { getOpcode() instanceof Opcode::Uninitialized }
|
||||
|
||||
@@ -512,35 +619,94 @@ class UninitializedInstruction extends VariableInstruction {
|
||||
final Language::Variable getLocalVariable() { result = var.(IRUserVariable).getVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that has no effect.
|
||||
*
|
||||
* This instruction is typically inserted to ensure that a particular AST is associated with at
|
||||
* least one instruction, even when the AST has no semantic effect.
|
||||
*/
|
||||
class NoOpInstruction extends Instruction {
|
||||
NoOpInstruction() { getOpcode() instanceof Opcode::NoOp }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns control to the caller of the function.
|
||||
*
|
||||
* This instruction represents the normal (non-exception) return from a function, either from an
|
||||
* explicit `return` statement or from control flow reaching the end of the function's body.
|
||||
*
|
||||
* Each function has exactly one `ReturnInstruction`. Each `return` statement in a function is
|
||||
* represented as an initialization of the temporary variable that holds the return value, with
|
||||
* control then flowing to the common `ReturnInstruction` for that function. Exception: A function
|
||||
* that never returns will not have a `ReturnInstruction`.
|
||||
*
|
||||
* The `ReturnInstruction` for a function will have a control-flow successor edge to a block
|
||||
* containing the `ExitFunction` instruction for that function.
|
||||
*
|
||||
* There are two differet return instructions: `ReturnValueInstruction`, for returning a value from
|
||||
* a non-`void`-returning function, and `ReturnVoidInstruction`, for returning from a
|
||||
* `void`-returning function.
|
||||
*/
|
||||
class ReturnInstruction extends Instruction {
|
||||
ReturnInstruction() { getOpcode() instanceof ReturnOpcode }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns control to the caller of the function, without returning a value.
|
||||
*/
|
||||
class ReturnVoidInstruction extends ReturnInstruction {
|
||||
ReturnVoidInstruction() { getOpcode() instanceof Opcode::ReturnVoid }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns control to the caller of the function, including a return value.
|
||||
*/
|
||||
class ReturnValueInstruction extends ReturnInstruction {
|
||||
ReturnValueInstruction() { getOpcode() instanceof Opcode::ReturnValue }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the value being returned by the function.
|
||||
*/
|
||||
final LoadOperand getReturnValueOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the value being returned by the function, if an
|
||||
* exact definition is available.
|
||||
*/
|
||||
final Instruction getReturnValue() { result = getReturnValueOperand().getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that represents the use of the value pointed to by a parameter of the function
|
||||
* after the function returns control to its caller.
|
||||
*
|
||||
* This instruction does not itself return control to the caller. It merely represents the potential
|
||||
* for a caller to use the memory pointed to by the parameter sometime after the call returns. This
|
||||
* is the counterpart to the `InitializeIndirection` instruction, which represents the possibility
|
||||
* that the caller initialized the memory pointed to by the parameter before the call.
|
||||
*/
|
||||
class ReturnIndirectionInstruction extends VariableInstruction {
|
||||
ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the value of the pointed-to memory.
|
||||
*/
|
||||
final SideEffectOperand getSideEffectOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the value of the pointed-to memory, if an exact
|
||||
* definition is available.
|
||||
*/
|
||||
final Instruction getSideEffect() { result = getSideEffectOperand().getDef() }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the address of the pointed-to memory.
|
||||
*/
|
||||
final AddressOperand getSourceAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the address of the pointed-to memory.
|
||||
*/
|
||||
final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() }
|
||||
|
||||
/**
|
||||
@@ -555,60 +721,128 @@ class ReturnIndirectionInstruction extends VariableInstruction {
|
||||
final predicate isThisIndirection() { var instanceof IRThisVariable }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a copy of its operand.
|
||||
*
|
||||
* There are several different copy instructions, depending on the source and destination of the
|
||||
* copy operation:
|
||||
* - `CopyInstruction` - Copies a register operand to a register result.
|
||||
* - `LoadInstruction` - Copies a memory operand to a register result.
|
||||
* - `StoreInstruction` - Copies a register operand to a memory result.
|
||||
*/
|
||||
class CopyInstruction extends Instruction {
|
||||
CopyInstruction() { getOpcode() instanceof CopyOpcode }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the input value of the copy.
|
||||
*/
|
||||
Operand getSourceValueOperand() { none() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the input value of the copy, if an exact definition
|
||||
* is available.
|
||||
*/
|
||||
final Instruction getSourceValue() { result = getSourceValueOperand().getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a register result containing a copy of its register operand.
|
||||
*/
|
||||
class CopyValueInstruction extends CopyInstruction, UnaryInstruction {
|
||||
CopyValueInstruction() { getOpcode() instanceof Opcode::CopyValue }
|
||||
|
||||
final override UnaryOperand getSourceValueOperand() { result = getAnOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a register result containing a copy of its memory operand.
|
||||
*/
|
||||
class LoadInstruction extends CopyInstruction {
|
||||
LoadInstruction() { getOpcode() instanceof Opcode::Load }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the address of the value being loaded.
|
||||
*/
|
||||
final AddressOperand getSourceAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the address of the value being loaded.
|
||||
*/
|
||||
final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() }
|
||||
|
||||
final override LoadOperand getSourceValueOperand() { result = getAnOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a memory result containing a copy of its register operand.
|
||||
*/
|
||||
class StoreInstruction extends CopyInstruction {
|
||||
StoreInstruction() { getOpcode() instanceof Opcode::Store }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the address of the location to which the value will be stored.
|
||||
*/
|
||||
final AddressOperand getDestinationAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the address of the location to which the value will
|
||||
* be stored, if an exact definition is available.
|
||||
*/
|
||||
final Instruction getDestinationAddress() { result = getDestinationAddressOperand().getDef() }
|
||||
|
||||
final override StoreValueOperand getSourceValueOperand() { result = getAnOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that branches to one of two successor instructions based on the value of a Boolean
|
||||
* operand.
|
||||
*/
|
||||
class ConditionalBranchInstruction extends Instruction {
|
||||
ConditionalBranchInstruction() { getOpcode() instanceof Opcode::ConditionalBranch }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the Boolean condition controlling the branch.
|
||||
*/
|
||||
final ConditionOperand getConditionOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the Boolean condition controlling the branch.
|
||||
*/
|
||||
final Instruction getCondition() { result = getConditionOperand().getDef() }
|
||||
|
||||
/**
|
||||
* Gets the instruction to which control will flow if the condition is true.
|
||||
*/
|
||||
final Instruction getTrueSuccessor() { result = getSuccessor(EdgeKind::trueEdge()) }
|
||||
|
||||
/**
|
||||
* Gets the instruction to which control will flow if the condition is false.
|
||||
*/
|
||||
final Instruction getFalseSuccessor() { result = getSuccessor(EdgeKind::falseEdge()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the exit point of a function.
|
||||
*
|
||||
* Each `IRFunction` has exactly one `ExitFunction` instruction, unless the function neither returns
|
||||
* nor throws an exception. Control flows to the `ExitFunction` instruction from both normal returns
|
||||
* (`ReturnVoid`, `ReturnValue`) and propagated exceptions (`Unwind`). This instruction has no
|
||||
* successors.
|
||||
*/
|
||||
class ExitFunctionInstruction extends Instruction {
|
||||
ExitFunctionInstruction() { getOpcode() instanceof Opcode::ExitFunction }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is a constant value.
|
||||
*/
|
||||
class ConstantInstruction extends ConstantValueInstruction {
|
||||
ConstantInstruction() { getOpcode() instanceof Opcode::Constant }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is a constant value of integer or Boolean type.
|
||||
*/
|
||||
class IntegerConstantInstruction extends ConstantInstruction {
|
||||
IntegerConstantInstruction() {
|
||||
exists(IRType resultType |
|
||||
@@ -618,27 +852,53 @@ class IntegerConstantInstruction extends ConstantInstruction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is a constant value of floating-point type.
|
||||
*/
|
||||
class FloatConstantInstruction extends ConstantInstruction {
|
||||
FloatConstantInstruction() { getResultIRType() instanceof IRFloatingPointType }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is the address of a string literal.
|
||||
*/
|
||||
class StringConstantInstruction extends VariableInstruction {
|
||||
override IRStringLiteral var;
|
||||
|
||||
final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) }
|
||||
|
||||
/**
|
||||
* Gets the string literal whose address is returned by this instruction.
|
||||
*/
|
||||
final Language::StringLiteral getValue() { result = var.getLiteral() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is computed from two operands.
|
||||
*/
|
||||
class BinaryInstruction extends Instruction {
|
||||
BinaryInstruction() { getOpcode() instanceof BinaryOpcode }
|
||||
|
||||
/**
|
||||
* Gets the left operand of this binary instruction.
|
||||
*/
|
||||
final LeftOperand getLeftOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the right operand of this binary instruction.
|
||||
*/
|
||||
final RightOperand getRightOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the value of the left operand of this binary
|
||||
* instruction.
|
||||
*/
|
||||
final Instruction getLeft() { result = getLeftOperand().getDef() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the value of the right operand of this binary
|
||||
* instruction.
|
||||
*/
|
||||
final Instruction getRight() { result = getRightOperand().getDef() }
|
||||
|
||||
/**
|
||||
@@ -651,66 +911,161 @@ class BinaryInstruction extends Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the result of an arithmetic operation.
|
||||
*/
|
||||
class ArithmeticInstruction extends Instruction {
|
||||
ArithmeticInstruction() { getOpcode() instanceof ArithmeticOpcode }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that performs an arithmetic operation on two numeric operands.
|
||||
*/
|
||||
class BinaryArithmeticInstruction extends ArithmeticInstruction, BinaryInstruction { }
|
||||
|
||||
/**
|
||||
* An instruction whose result is computed by performing an arithmetic operation on a single
|
||||
* numeric operand.
|
||||
*/
|
||||
class UnaryArithmeticInstruction extends ArithmeticInstruction, UnaryInstruction { }
|
||||
|
||||
/**
|
||||
* An instruction that computes the sum of two numeric operands.
|
||||
*
|
||||
* Both operands must have the same numeric type, which will also be the result type. The result of
|
||||
* integer overflow is the infinite-precision result modulo 2^n. Floating-point addition is
|
||||
* performed according to IEEE-754.
|
||||
*/
|
||||
class AddInstruction extends BinaryArithmeticInstruction {
|
||||
AddInstruction() { getOpcode() instanceof Opcode::Add }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the difference of two numeric operands.
|
||||
*
|
||||
* Both operands must have the same numeric type, which will also be the result type. The result of
|
||||
* integer overflow is the infinite-precision result modulo 2^n. Floating-point subtraction is performed
|
||||
* according to IEEE-754.
|
||||
*/
|
||||
class SubInstruction extends BinaryArithmeticInstruction {
|
||||
SubInstruction() { getOpcode() instanceof Opcode::Sub }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the product of two numeric operands.
|
||||
*
|
||||
* Both operands must have the same numeric type, which will also be the result type. The result of
|
||||
* integer overflow is the infinite-precision result modulo 2^n. Floating-point multiplication is
|
||||
* performed according to IEEE-754.
|
||||
*/
|
||||
class MulInstruction extends BinaryArithmeticInstruction {
|
||||
MulInstruction() { getOpcode() instanceof Opcode::Mul }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the quotient of two numeric operands.
|
||||
*
|
||||
* Both operands must have the same numeric type, which will also be the result type. The result of
|
||||
* division by zero or integer overflow is undefined. Floating-point division is performed according
|
||||
* to IEEE-754.
|
||||
*/
|
||||
class DivInstruction extends BinaryArithmeticInstruction {
|
||||
DivInstruction() { getOpcode() instanceof Opcode::Div }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the remainder of two integer operands.
|
||||
*
|
||||
* Both operands must have the same integer type, which will also be the result type. The result of
|
||||
* division by zero or integer overflow is undefined.
|
||||
*/
|
||||
class RemInstruction extends BinaryArithmeticInstruction {
|
||||
RemInstruction() { getOpcode() instanceof Opcode::Rem }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that negates a single numeric operand.
|
||||
*
|
||||
* The operand must have a numeric type, which will also be the result type. The result of integer
|
||||
* negation uses two's complement, and is computed modulo 2^n. The result of floating-point negation
|
||||
* is performed according to IEEE-754.
|
||||
*/
|
||||
class NegateInstruction extends UnaryArithmeticInstruction {
|
||||
NegateInstruction() { getOpcode() instanceof Opcode::Negate }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the result of a bitwise operation.
|
||||
*/
|
||||
class BitwiseInstruction extends Instruction {
|
||||
BitwiseInstruction() { getOpcode() instanceof BitwiseOpcode }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that performs a bitwise operation on two integer operands.
|
||||
*/
|
||||
class BinaryBitwiseInstruction extends BitwiseInstruction, BinaryInstruction { }
|
||||
|
||||
/**
|
||||
* An instruction that performs a bitwise operation on a single integer operand.
|
||||
*/
|
||||
class UnaryBitwiseInstruction extends BitwiseInstruction, UnaryInstruction { }
|
||||
|
||||
/**
|
||||
* An instruction that computes the bitwise "and" of two integer operands.
|
||||
*
|
||||
* Both operands must have the same integer type, which will also be the result type.
|
||||
*/
|
||||
class BitAndInstruction extends BinaryBitwiseInstruction {
|
||||
BitAndInstruction() { getOpcode() instanceof Opcode::BitAnd }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the bitwise "or" of two integer operands.
|
||||
*
|
||||
* Both operands must have the same integer type, which will also be the result type.
|
||||
*/
|
||||
class BitOrInstruction extends BinaryBitwiseInstruction {
|
||||
BitOrInstruction() { getOpcode() instanceof Opcode::BitOr }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the bitwise "xor" of two integer operands.
|
||||
*
|
||||
* Both operands must have the same integer type, which will also be the result type.
|
||||
*/
|
||||
class BitXorInstruction extends BinaryBitwiseInstruction {
|
||||
BitXorInstruction() { getOpcode() instanceof Opcode::BitXor }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that shifts its left operand to the left by the number of bits specified by its
|
||||
* right operand.
|
||||
*
|
||||
* Both operands must have an integer type. The result has the same type as the left operand. The
|
||||
* rightmost bits are zero-filled.
|
||||
*/
|
||||
class ShiftLeftInstruction extends BinaryBitwiseInstruction {
|
||||
ShiftLeftInstruction() { getOpcode() instanceof Opcode::ShiftLeft }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that shifts its left operand to the right by the number of bits specified by its
|
||||
* right operand.
|
||||
*
|
||||
* Both operands must have an integer type. The result has the same type as the left operand. If the
|
||||
* left operand has an unsigned integer type, the leftmost bits are zero-filled. If the left operand
|
||||
* has a signed integer type, the leftmost bits are filled by duplicating the most significant bit
|
||||
* of the left operand.
|
||||
*/
|
||||
class ShiftRightInstruction extends BinaryBitwiseInstruction {
|
||||
ShiftRightInstruction() { getOpcode() instanceof Opcode::ShiftRight }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that performs a binary arithmetic operation involving at least one pointer
|
||||
* operand.
|
||||
*/
|
||||
class PointerArithmeticInstruction extends BinaryInstruction {
|
||||
int elementSize;
|
||||
|
||||
@@ -721,25 +1076,64 @@ class PointerArithmeticInstruction extends BinaryInstruction {
|
||||
|
||||
final override string getImmediateString() { result = elementSize.toString() }
|
||||
|
||||
/**
|
||||
* Gets the size of the elements pointed to by the pointer operands, in bytes.
|
||||
*
|
||||
* When adding an integer offset to a pointer (`PointerAddInstruction`) or subtracting an integer
|
||||
* offset from a pointer (`PointerSubInstruction`), the integer offset is multiplied by the
|
||||
* element size to compute the actual number of bytes added to or subtracted from the pointer
|
||||
* address. When computing the integer difference between two pointers (`PointerDiffInstruction`),
|
||||
* the result is computed by computing the difference between the two pointer byte addresses, then
|
||||
* dividing that byte count by the element size.
|
||||
*/
|
||||
final int getElementSize() { result = elementSize }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that adds or subtracts an integer offset from a pointer.
|
||||
*/
|
||||
class PointerOffsetInstruction extends PointerArithmeticInstruction {
|
||||
PointerOffsetInstruction() { getOpcode() instanceof PointerOffsetOpcode }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that adds an integer offset to a pointer.
|
||||
*
|
||||
* The result is the byte address computed by adding the value of the right (integer) operand,
|
||||
* multiplied by the element size, to the value of the left (pointer) operand. The result of pointer
|
||||
* overflow is undefined.
|
||||
*/
|
||||
class PointerAddInstruction extends PointerOffsetInstruction {
|
||||
PointerAddInstruction() { getOpcode() instanceof Opcode::PointerAdd }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that subtracts an integer offset from a pointer.
|
||||
*
|
||||
* The result is the byte address computed by subtracting the value of the right (integer) operand,
|
||||
* multiplied by the element size, from the value of the left (pointer) operand. The result of
|
||||
* pointer underflow is undefined.
|
||||
*/
|
||||
class PointerSubInstruction extends PointerOffsetInstruction {
|
||||
PointerSubInstruction() { getOpcode() instanceof Opcode::PointerSub }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the difference between two pointers.
|
||||
*
|
||||
* Both operands must have the same pointer type. The result must have an integer type whose size is
|
||||
* the same as that of the pointer operands. The result is computed by subtracting the byte address
|
||||
* in the right operand from the byte address in the left operand, and dividing by the element size.
|
||||
* If the difference in byte addresses is not divisible by the element size, the result is
|
||||
* undefined.
|
||||
*/
|
||||
class PointerDiffInstruction extends PointerArithmeticInstruction {
|
||||
PointerDiffInstruction() { getOpcode() instanceof Opcode::PointerDiff }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is computed from a single operand.
|
||||
*/
|
||||
class UnaryInstruction extends Instruction {
|
||||
UnaryInstruction() { getOpcode() instanceof UnaryOpcode }
|
||||
|
||||
@@ -748,17 +1142,44 @@ class UnaryInstruction extends Instruction {
|
||||
final Instruction getUnary() { result = getUnaryOperand().getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that converts the value of its operand to a value of a different type.
|
||||
*/
|
||||
class ConvertInstruction extends UnaryInstruction {
|
||||
ConvertInstruction() { getOpcode() instanceof Opcode::Convert }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that converts the address of a polymorphic object to the address of a different
|
||||
* subobject of the same polymorphic object, returning a null address if the dynamic type of the
|
||||
* object is not compatible with the result type.
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*
|
||||
* This instruction is used to represent a C++ `dynamic_cast<>` to a pointer type, or a C# `is` or
|
||||
* `as` expression.
|
||||
*/
|
||||
class CheckedConvertOrNullInstruction extends UnaryInstruction {
|
||||
CheckedConvertOrNullInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrNull }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instruction that converts between two addresses
|
||||
* related by inheritance.
|
||||
* An instruction that converts the address of a polymorphic object to the address of a different
|
||||
* subobject of the same polymorphic object, throwing an exception if the dynamic type of the object
|
||||
* is not compatible with the result type.
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*
|
||||
* This instruction is used to represent a C++ `dynamic_cast<>` to a reference type, or a C# cast
|
||||
* expression.
|
||||
*/
|
||||
class CheckedConvertOrThrowInstruction extends UnaryInstruction {
|
||||
CheckedConvertOrThrowInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrThrow }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that converts the address of an object to the address of a different subobject of
|
||||
* the same object, without any type checking at runtime.
|
||||
*/
|
||||
class InheritanceConversionInstruction extends UnaryInstruction {
|
||||
Language::Class baseClass;
|
||||
@@ -795,59 +1216,91 @@ class InheritanceConversionInstruction extends UnaryInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instruction that converts from the address of a derived class
|
||||
* to the address of a base class.
|
||||
* An instruction that converts from the address of a derived class to the address of a base class.
|
||||
*/
|
||||
class ConvertToBaseInstruction extends InheritanceConversionInstruction {
|
||||
ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instruction that converts from the address of a derived class
|
||||
* to the address of a direct non-virtual base class.
|
||||
* An instruction that converts from the address of a derived class to the address of a direct
|
||||
* non-virtual base class.
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*/
|
||||
class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction {
|
||||
ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instruction that converts from the address of a derived class
|
||||
* to the address of a virtual base class.
|
||||
* An instruction that converts from the address of a derived class to the address of a virtual base
|
||||
* class.
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*/
|
||||
class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction {
|
||||
ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instruction that converts from the address of a base class
|
||||
* to the address of a direct non-virtual derived class.
|
||||
* An instruction that converts from the address of a base class to the address of a direct
|
||||
* non-virtual derived class.
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*/
|
||||
class ConvertToDerivedInstruction extends InheritanceConversionInstruction {
|
||||
ConvertToDerivedInstruction() { getOpcode() instanceof Opcode::ConvertToDerived }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the bitwise complement of its operand.
|
||||
*
|
||||
* The operand must have an integer type, which will also be the result type.
|
||||
*/
|
||||
class BitComplementInstruction extends UnaryBitwiseInstruction {
|
||||
BitComplementInstruction() { getOpcode() instanceof Opcode::BitComplement }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the logical complement of its operand.
|
||||
*
|
||||
* The operand must have a Boolean type, which will also be the result type.
|
||||
*/
|
||||
class LogicalNotInstruction extends UnaryInstruction {
|
||||
LogicalNotInstruction() { getOpcode() instanceof Opcode::LogicalNot }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that compares two numeric operands.
|
||||
*/
|
||||
class CompareInstruction extends BinaryInstruction {
|
||||
CompareInstruction() { getOpcode() instanceof CompareOpcode }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a `true` result if its operands are equal.
|
||||
*
|
||||
* Both operands must have the same numeric or address type. The result must have a Boolean type.
|
||||
* The result is `true` if `left == right`, and `false` if `left != right` or the two operands are
|
||||
* unordered. Floating-point comparison is performed according to IEEE-754.
|
||||
*/
|
||||
class CompareEQInstruction extends CompareInstruction {
|
||||
CompareEQInstruction() { getOpcode() instanceof Opcode::CompareEQ }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a `true` result if its operands are not equal.
|
||||
*
|
||||
* Both operands must have the same numeric or address type. The result must have a Boolean type.
|
||||
* The result is `true` if `left != right` or if the two operands are unordered, and `false` if
|
||||
* `left == right`. Floating-point comparison is performed according to IEEE-754.
|
||||
*/
|
||||
class CompareNEInstruction extends CompareInstruction {
|
||||
CompareNEInstruction() { getOpcode() instanceof Opcode::CompareNE }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instruction that does a relative comparison of two values, such as `<` or `>=`.
|
||||
* An instruction that does a relative comparison of two values, such as `<` or `>=`.
|
||||
*/
|
||||
class RelationalInstruction extends CompareInstruction {
|
||||
RelationalInstruction() { getOpcode() instanceof RelationalOpcode }
|
||||
@@ -874,6 +1327,13 @@ class RelationalInstruction extends CompareInstruction {
|
||||
predicate isStrict() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a `true` result if its left operand is less than its right operand.
|
||||
*
|
||||
* Both operands must have the same numeric or address type. The result must have a Boolean type.
|
||||
* The result is `true` if the `left < right`, and `false` if `left >= right` or if the two operands
|
||||
* are unordered. Floating-point comparison is performed according to IEEE-754.
|
||||
*/
|
||||
class CompareLTInstruction extends RelationalInstruction {
|
||||
CompareLTInstruction() { getOpcode() instanceof Opcode::CompareLT }
|
||||
|
||||
@@ -884,6 +1344,13 @@ class CompareLTInstruction extends RelationalInstruction {
|
||||
override predicate isStrict() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a `true` result if its left operand is greater than its right operand.
|
||||
*
|
||||
* Both operands must have the same numeric or address type. The result must have a Boolean type.
|
||||
* The result is `true` if the `left > right`, and `false` if `left <= right` or if the two operands
|
||||
* are unordered. Floating-point comparison is performed according to IEEE-754.
|
||||
*/
|
||||
class CompareGTInstruction extends RelationalInstruction {
|
||||
CompareGTInstruction() { getOpcode() instanceof Opcode::CompareGT }
|
||||
|
||||
@@ -894,6 +1361,14 @@ class CompareGTInstruction extends RelationalInstruction {
|
||||
override predicate isStrict() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a `true` result if its left operand is less than or equal to its
|
||||
* right operand.
|
||||
*
|
||||
* Both operands must have the same numeric or address type. The result must have a Boolean type.
|
||||
* The result is `true` if the `left <= right`, and `false` if `left > right` or if the two operands
|
||||
* are unordered. Floating-point comparison is performed according to IEEE-754.
|
||||
*/
|
||||
class CompareLEInstruction extends RelationalInstruction {
|
||||
CompareLEInstruction() { getOpcode() instanceof Opcode::CompareLE }
|
||||
|
||||
@@ -904,6 +1379,14 @@ class CompareLEInstruction extends RelationalInstruction {
|
||||
override predicate isStrict() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a `true` result if its left operand is greater than or equal to its
|
||||
* right operand.
|
||||
*
|
||||
* Both operands must have the same numeric or address type. The result must have a Boolean type.
|
||||
* The result is `true` if the `left >= right`, and `false` if `left < right` or if the two operands
|
||||
* are unordered. Floating-point comparison is performed according to IEEE-754.
|
||||
*/
|
||||
class CompareGEInstruction extends RelationalInstruction {
|
||||
CompareGEInstruction() { getOpcode() instanceof Opcode::CompareGE }
|
||||
|
||||
@@ -914,15 +1397,32 @@ class CompareGEInstruction extends RelationalInstruction {
|
||||
override predicate isStrict() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that branches to one of multiple successor instructions based on the value of an
|
||||
* integer operand.
|
||||
*
|
||||
* This instruction will have zero or more successors whose edge kind is `CaseEdge`, each
|
||||
* representing the branch that will be taken if the controlling expression is within the range
|
||||
* specified for that case edge. The range of a case edge must be disjoint from the range of each
|
||||
* other case edge.
|
||||
*
|
||||
* The instruction may optionally have a successor edge whose edge kind is `DefaultEdge`,
|
||||
* representing the branch that will be taken if the controlling expression is not within the range
|
||||
* of any case edge.
|
||||
*/
|
||||
class SwitchInstruction extends Instruction {
|
||||
SwitchInstruction() { getOpcode() instanceof Opcode::Switch }
|
||||
|
||||
/** Gets the operand that provides the integer value controlling the switch. */
|
||||
final ConditionOperand getExpressionOperand() { result = getAnOperand() }
|
||||
|
||||
/** Gets the instruction whose result provides the integer value controlling the switch. */
|
||||
final Instruction getExpression() { result = getExpressionOperand().getDef() }
|
||||
|
||||
/** Gets the successor instructions along the case edges of the switch. */
|
||||
final Instruction getACaseSuccessor() { exists(CaseEdge edge | result = getSuccessor(edge)) }
|
||||
|
||||
/** Gets the successor instruction along the default edge of the switch, if any. */
|
||||
final Instruction getDefaultSuccessor() { result = getSuccessor(EdgeKind::defaultEdge()) }
|
||||
}
|
||||
|
||||
@@ -998,6 +1498,9 @@ class CallInstruction extends Instruction {
|
||||
class SideEffectInstruction extends Instruction {
|
||||
SideEffectInstruction() { getOpcode() instanceof SideEffectOpcode }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose execution causes this side effect.
|
||||
*/
|
||||
final Instruction getPrimaryInstruction() {
|
||||
result = Construction::getPrimaryInstructionForSideEffect(this)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes that represent the individual instructions in the IR for a function.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
import IRFunction
|
||||
import IRBlock
|
||||
@@ -27,7 +31,7 @@ private Instruction getAnInstructionAtLine(IRFunction irFunc, Language::File fil
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a single operation in the IR.
|
||||
* A single instruction in the IR.
|
||||
*/
|
||||
class Instruction extends Construction::TStageInstruction {
|
||||
Instruction() {
|
||||
@@ -36,6 +40,7 @@ class Instruction extends Construction::TStageInstruction {
|
||||
Construction::hasInstruction(this)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
final string toString() { result = getOpcode().toString() + ": " + getAST().toString() }
|
||||
|
||||
/**
|
||||
@@ -247,10 +252,12 @@ class Instruction extends Construction::TStageInstruction {
|
||||
* given by `getResultType()`.
|
||||
*
|
||||
* For example, the statement `y = x;` generates the following IR:
|
||||
* ```
|
||||
* r1_0(glval: int) = VariableAddress[x]
|
||||
* r1_1(int) = Load r1_0, mu0_1
|
||||
* r1_2(glval: int) = VariableAddress[y]
|
||||
* mu1_3(int) = Store r1_2, r1_1
|
||||
* ```
|
||||
*
|
||||
* The result of each `VariableAddress` instruction is a glvalue of type
|
||||
* `int`, representing the address of the corresponding integer variable. The
|
||||
@@ -399,6 +406,17 @@ class Instruction extends Construction::TStageInstruction {
|
||||
final Instruction getAPredecessor() { result = getPredecessor(_) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that refers to a variable.
|
||||
*
|
||||
* This class is used for any instruction whose operation fundamentally depends on a specific
|
||||
* variable. For example, it is used for `VariableAddress`, which returns the address of a specific
|
||||
* variable, and `InitializeParameter`, which returns the value that was passed to the specified
|
||||
* parameter by the caller. `VariableInstruction` is not used for `Load` or `Store` instructions
|
||||
* that happen to load from or store to a particular variable; in those cases, the memory location
|
||||
* being accessed is specified by the `AddressOperand` on the instruction, which may or may not be
|
||||
* defined by the result of a `VariableAddress` instruction.
|
||||
*/
|
||||
class VariableInstruction extends Instruction {
|
||||
IRVariable var;
|
||||
|
||||
@@ -406,6 +424,9 @@ class VariableInstruction extends Instruction {
|
||||
|
||||
override string getImmediateString() { result = var.toString() }
|
||||
|
||||
/**
|
||||
* Gets the variable that this instruction references.
|
||||
*/
|
||||
final IRVariable getIRVariable() { result = var }
|
||||
|
||||
/**
|
||||
@@ -414,6 +435,16 @@ class VariableInstruction extends Instruction {
|
||||
final Language::Variable getASTVariable() { result = var.(IRUserVariable).getVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that refers to a field of a class, struct, or union.
|
||||
*
|
||||
* This class is used for any instruction whose operation fundamentally depends on a specific
|
||||
* field. For example, it is used for `FieldAddress`, which computes the address of a specific
|
||||
* field on an object. `FieldInstruction` is not used for `Load` or `Store` instructions that happen
|
||||
* to load from or store to a particular field; in those cases, the memory location being accessed
|
||||
* is specified by the `AddressOperand` on the instruction, which may or may not be defined by the
|
||||
* result of a `FieldAddress` instruction.
|
||||
*/
|
||||
class FieldInstruction extends Instruction {
|
||||
Language::Field field;
|
||||
|
||||
@@ -421,9 +452,22 @@ class FieldInstruction extends Instruction {
|
||||
|
||||
final override string getImmediateString() { result = field.toString() }
|
||||
|
||||
/**
|
||||
* Gets the field that this instruction references.
|
||||
*/
|
||||
final Language::Field getField() { result = field }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that refers to a function.
|
||||
*
|
||||
* This class is used for any instruction whose operation fundamentally depends on a specific
|
||||
* function. For example, it is used for `FunctionAddress`, which returns the address of a specific
|
||||
* function. `FunctionInstruction` is not used for `Call` instructions that happen to call a
|
||||
* particular function; in that case, the function being called is specified by the
|
||||
* `CallTargetOperand` on the instruction, which may or may not be defined by the result of a
|
||||
* `FunctionAddress` instruction.
|
||||
*/
|
||||
class FunctionInstruction extends Instruction {
|
||||
Language::Function funcSymbol;
|
||||
|
||||
@@ -431,9 +475,15 @@ class FunctionInstruction extends Instruction {
|
||||
|
||||
final override string getImmediateString() { result = funcSymbol.toString() }
|
||||
|
||||
/**
|
||||
* Gets the function that this instruction references.
|
||||
*/
|
||||
final Language::Function getFunctionSymbol() { result = funcSymbol }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is a compile-time constant value.
|
||||
*/
|
||||
class ConstantValueInstruction extends Instruction {
|
||||
string value;
|
||||
|
||||
@@ -441,9 +491,18 @@ class ConstantValueInstruction extends Instruction {
|
||||
|
||||
final override string getImmediateString() { result = value }
|
||||
|
||||
/**
|
||||
* Gets the constant value of this instruction's result.
|
||||
*/
|
||||
final string getValue() { result = value }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that refers to an argument of a `Call` instruction.
|
||||
*
|
||||
* This instruction is used for side effects of a `Call` instruction that read or write memory
|
||||
* pointed to by one of the arguments of the call.
|
||||
*/
|
||||
class IndexedInstruction extends Instruction {
|
||||
int index;
|
||||
|
||||
@@ -451,26 +510,59 @@ class IndexedInstruction extends Instruction {
|
||||
|
||||
final override string getImmediateString() { result = index.toString() }
|
||||
|
||||
/**
|
||||
* Gets the zero-based index of the argument that this instruction references.
|
||||
*/
|
||||
final int getIndex() { result = index }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the entry point to a function.
|
||||
*
|
||||
* Each `IRFunction` has exactly one `EnterFunction` instruction. Execution of the function begins
|
||||
* at this instruction. This instruction has no predecessors.
|
||||
*/
|
||||
class EnterFunctionInstruction extends Instruction {
|
||||
EnterFunctionInstruction() { getOpcode() instanceof Opcode::EnterFunction }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns the address of a variable.
|
||||
*
|
||||
* This instruction returns the address of a local variable, parameter, static field,
|
||||
* namespace-scope variable, or global variable. For the address of a non-static field of a class,
|
||||
* struct, or union, see `FieldAddressInstruction`.
|
||||
*/
|
||||
class VariableAddressInstruction extends VariableInstruction {
|
||||
VariableAddressInstruction() { getOpcode() instanceof Opcode::VariableAddress }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that initializes a parameter of the enclosing function with the value of the
|
||||
* corresponding argument passed by the caller.
|
||||
*
|
||||
* Each parameter of a function will have exactly one `InitializeParameter` instruction that
|
||||
* initializes that parameter.
|
||||
*/
|
||||
class InitializeParameterInstruction extends VariableInstruction {
|
||||
InitializeParameterInstruction() { getOpcode() instanceof Opcode::InitializeParameter }
|
||||
|
||||
/**
|
||||
* Gets the parameter initialized by this instruction.
|
||||
*/
|
||||
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that initializes the memory pointed to by a parameter of the enclosing function
|
||||
* with the value of that memory on entry to the function.
|
||||
*/
|
||||
class InitializeIndirectionInstruction extends VariableInstruction {
|
||||
InitializeIndirectionInstruction() { getOpcode() instanceof Opcode::InitializeIndirection }
|
||||
|
||||
/**
|
||||
* Gets the parameter initialized by this instruction.
|
||||
*/
|
||||
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
|
||||
}
|
||||
|
||||
@@ -481,11 +573,20 @@ class InitializeThisInstruction extends Instruction {
|
||||
InitializeThisInstruction() { getOpcode() instanceof Opcode::InitializeThis }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the address of a non-static field of an object.
|
||||
*/
|
||||
class FieldAddressInstruction extends FieldInstruction {
|
||||
FieldAddressInstruction() { getOpcode() instanceof Opcode::FieldAddress }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the address of the object containing the field.
|
||||
*/
|
||||
final UnaryOperand getObjectAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the address of the object containing the field.
|
||||
*/
|
||||
final Instruction getObjectAddress() { result = getObjectAddressOperand().getDef() }
|
||||
}
|
||||
|
||||
@@ -503,6 +604,12 @@ class ErrorInstruction extends Instruction {
|
||||
ErrorInstruction() { getOpcode() instanceof Opcode::Error }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns an uninitialized value.
|
||||
*
|
||||
* This instruction is used to provide an initial definition for a stack variable that does not have
|
||||
* an initializer, or whose initializer only partially initializes the variable.
|
||||
*/
|
||||
class UninitializedInstruction extends VariableInstruction {
|
||||
UninitializedInstruction() { getOpcode() instanceof Opcode::Uninitialized }
|
||||
|
||||
@@ -512,35 +619,94 @@ class UninitializedInstruction extends VariableInstruction {
|
||||
final Language::Variable getLocalVariable() { result = var.(IRUserVariable).getVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that has no effect.
|
||||
*
|
||||
* This instruction is typically inserted to ensure that a particular AST is associated with at
|
||||
* least one instruction, even when the AST has no semantic effect.
|
||||
*/
|
||||
class NoOpInstruction extends Instruction {
|
||||
NoOpInstruction() { getOpcode() instanceof Opcode::NoOp }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns control to the caller of the function.
|
||||
*
|
||||
* This instruction represents the normal (non-exception) return from a function, either from an
|
||||
* explicit `return` statement or from control flow reaching the end of the function's body.
|
||||
*
|
||||
* Each function has exactly one `ReturnInstruction`. Each `return` statement in a function is
|
||||
* represented as an initialization of the temporary variable that holds the return value, with
|
||||
* control then flowing to the common `ReturnInstruction` for that function. Exception: A function
|
||||
* that never returns will not have a `ReturnInstruction`.
|
||||
*
|
||||
* The `ReturnInstruction` for a function will have a control-flow successor edge to a block
|
||||
* containing the `ExitFunction` instruction for that function.
|
||||
*
|
||||
* There are two differet return instructions: `ReturnValueInstruction`, for returning a value from
|
||||
* a non-`void`-returning function, and `ReturnVoidInstruction`, for returning from a
|
||||
* `void`-returning function.
|
||||
*/
|
||||
class ReturnInstruction extends Instruction {
|
||||
ReturnInstruction() { getOpcode() instanceof ReturnOpcode }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns control to the caller of the function, without returning a value.
|
||||
*/
|
||||
class ReturnVoidInstruction extends ReturnInstruction {
|
||||
ReturnVoidInstruction() { getOpcode() instanceof Opcode::ReturnVoid }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns control to the caller of the function, including a return value.
|
||||
*/
|
||||
class ReturnValueInstruction extends ReturnInstruction {
|
||||
ReturnValueInstruction() { getOpcode() instanceof Opcode::ReturnValue }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the value being returned by the function.
|
||||
*/
|
||||
final LoadOperand getReturnValueOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the value being returned by the function, if an
|
||||
* exact definition is available.
|
||||
*/
|
||||
final Instruction getReturnValue() { result = getReturnValueOperand().getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that represents the use of the value pointed to by a parameter of the function
|
||||
* after the function returns control to its caller.
|
||||
*
|
||||
* This instruction does not itself return control to the caller. It merely represents the potential
|
||||
* for a caller to use the memory pointed to by the parameter sometime after the call returns. This
|
||||
* is the counterpart to the `InitializeIndirection` instruction, which represents the possibility
|
||||
* that the caller initialized the memory pointed to by the parameter before the call.
|
||||
*/
|
||||
class ReturnIndirectionInstruction extends VariableInstruction {
|
||||
ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the value of the pointed-to memory.
|
||||
*/
|
||||
final SideEffectOperand getSideEffectOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the value of the pointed-to memory, if an exact
|
||||
* definition is available.
|
||||
*/
|
||||
final Instruction getSideEffect() { result = getSideEffectOperand().getDef() }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the address of the pointed-to memory.
|
||||
*/
|
||||
final AddressOperand getSourceAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the address of the pointed-to memory.
|
||||
*/
|
||||
final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() }
|
||||
|
||||
/**
|
||||
@@ -555,60 +721,128 @@ class ReturnIndirectionInstruction extends VariableInstruction {
|
||||
final predicate isThisIndirection() { var instanceof IRThisVariable }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a copy of its operand.
|
||||
*
|
||||
* There are several different copy instructions, depending on the source and destination of the
|
||||
* copy operation:
|
||||
* - `CopyInstruction` - Copies a register operand to a register result.
|
||||
* - `LoadInstruction` - Copies a memory operand to a register result.
|
||||
* - `StoreInstruction` - Copies a register operand to a memory result.
|
||||
*/
|
||||
class CopyInstruction extends Instruction {
|
||||
CopyInstruction() { getOpcode() instanceof CopyOpcode }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the input value of the copy.
|
||||
*/
|
||||
Operand getSourceValueOperand() { none() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the input value of the copy, if an exact definition
|
||||
* is available.
|
||||
*/
|
||||
final Instruction getSourceValue() { result = getSourceValueOperand().getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a register result containing a copy of its register operand.
|
||||
*/
|
||||
class CopyValueInstruction extends CopyInstruction, UnaryInstruction {
|
||||
CopyValueInstruction() { getOpcode() instanceof Opcode::CopyValue }
|
||||
|
||||
final override UnaryOperand getSourceValueOperand() { result = getAnOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a register result containing a copy of its memory operand.
|
||||
*/
|
||||
class LoadInstruction extends CopyInstruction {
|
||||
LoadInstruction() { getOpcode() instanceof Opcode::Load }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the address of the value being loaded.
|
||||
*/
|
||||
final AddressOperand getSourceAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the address of the value being loaded.
|
||||
*/
|
||||
final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() }
|
||||
|
||||
final override LoadOperand getSourceValueOperand() { result = getAnOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a memory result containing a copy of its register operand.
|
||||
*/
|
||||
class StoreInstruction extends CopyInstruction {
|
||||
StoreInstruction() { getOpcode() instanceof Opcode::Store }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the address of the location to which the value will be stored.
|
||||
*/
|
||||
final AddressOperand getDestinationAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the address of the location to which the value will
|
||||
* be stored, if an exact definition is available.
|
||||
*/
|
||||
final Instruction getDestinationAddress() { result = getDestinationAddressOperand().getDef() }
|
||||
|
||||
final override StoreValueOperand getSourceValueOperand() { result = getAnOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that branches to one of two successor instructions based on the value of a Boolean
|
||||
* operand.
|
||||
*/
|
||||
class ConditionalBranchInstruction extends Instruction {
|
||||
ConditionalBranchInstruction() { getOpcode() instanceof Opcode::ConditionalBranch }
|
||||
|
||||
/**
|
||||
* Gets the operand that provides the Boolean condition controlling the branch.
|
||||
*/
|
||||
final ConditionOperand getConditionOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the Boolean condition controlling the branch.
|
||||
*/
|
||||
final Instruction getCondition() { result = getConditionOperand().getDef() }
|
||||
|
||||
/**
|
||||
* Gets the instruction to which control will flow if the condition is true.
|
||||
*/
|
||||
final Instruction getTrueSuccessor() { result = getSuccessor(EdgeKind::trueEdge()) }
|
||||
|
||||
/**
|
||||
* Gets the instruction to which control will flow if the condition is false.
|
||||
*/
|
||||
final Instruction getFalseSuccessor() { result = getSuccessor(EdgeKind::falseEdge()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the exit point of a function.
|
||||
*
|
||||
* Each `IRFunction` has exactly one `ExitFunction` instruction, unless the function neither returns
|
||||
* nor throws an exception. Control flows to the `ExitFunction` instruction from both normal returns
|
||||
* (`ReturnVoid`, `ReturnValue`) and propagated exceptions (`Unwind`). This instruction has no
|
||||
* successors.
|
||||
*/
|
||||
class ExitFunctionInstruction extends Instruction {
|
||||
ExitFunctionInstruction() { getOpcode() instanceof Opcode::ExitFunction }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is a constant value.
|
||||
*/
|
||||
class ConstantInstruction extends ConstantValueInstruction {
|
||||
ConstantInstruction() { getOpcode() instanceof Opcode::Constant }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is a constant value of integer or Boolean type.
|
||||
*/
|
||||
class IntegerConstantInstruction extends ConstantInstruction {
|
||||
IntegerConstantInstruction() {
|
||||
exists(IRType resultType |
|
||||
@@ -618,27 +852,53 @@ class IntegerConstantInstruction extends ConstantInstruction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is a constant value of floating-point type.
|
||||
*/
|
||||
class FloatConstantInstruction extends ConstantInstruction {
|
||||
FloatConstantInstruction() { getResultIRType() instanceof IRFloatingPointType }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is the address of a string literal.
|
||||
*/
|
||||
class StringConstantInstruction extends VariableInstruction {
|
||||
override IRStringLiteral var;
|
||||
|
||||
final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) }
|
||||
|
||||
/**
|
||||
* Gets the string literal whose address is returned by this instruction.
|
||||
*/
|
||||
final Language::StringLiteral getValue() { result = var.getLiteral() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is computed from two operands.
|
||||
*/
|
||||
class BinaryInstruction extends Instruction {
|
||||
BinaryInstruction() { getOpcode() instanceof BinaryOpcode }
|
||||
|
||||
/**
|
||||
* Gets the left operand of this binary instruction.
|
||||
*/
|
||||
final LeftOperand getLeftOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the right operand of this binary instruction.
|
||||
*/
|
||||
final RightOperand getRightOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the value of the left operand of this binary
|
||||
* instruction.
|
||||
*/
|
||||
final Instruction getLeft() { result = getLeftOperand().getDef() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the value of the right operand of this binary
|
||||
* instruction.
|
||||
*/
|
||||
final Instruction getRight() { result = getRightOperand().getDef() }
|
||||
|
||||
/**
|
||||
@@ -651,66 +911,161 @@ class BinaryInstruction extends Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the result of an arithmetic operation.
|
||||
*/
|
||||
class ArithmeticInstruction extends Instruction {
|
||||
ArithmeticInstruction() { getOpcode() instanceof ArithmeticOpcode }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that performs an arithmetic operation on two numeric operands.
|
||||
*/
|
||||
class BinaryArithmeticInstruction extends ArithmeticInstruction, BinaryInstruction { }
|
||||
|
||||
/**
|
||||
* An instruction whose result is computed by performing an arithmetic operation on a single
|
||||
* numeric operand.
|
||||
*/
|
||||
class UnaryArithmeticInstruction extends ArithmeticInstruction, UnaryInstruction { }
|
||||
|
||||
/**
|
||||
* An instruction that computes the sum of two numeric operands.
|
||||
*
|
||||
* Both operands must have the same numeric type, which will also be the result type. The result of
|
||||
* integer overflow is the infinite-precision result modulo 2^n. Floating-point addition is
|
||||
* performed according to IEEE-754.
|
||||
*/
|
||||
class AddInstruction extends BinaryArithmeticInstruction {
|
||||
AddInstruction() { getOpcode() instanceof Opcode::Add }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the difference of two numeric operands.
|
||||
*
|
||||
* Both operands must have the same numeric type, which will also be the result type. The result of
|
||||
* integer overflow is the infinite-precision result modulo 2^n. Floating-point subtraction is performed
|
||||
* according to IEEE-754.
|
||||
*/
|
||||
class SubInstruction extends BinaryArithmeticInstruction {
|
||||
SubInstruction() { getOpcode() instanceof Opcode::Sub }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the product of two numeric operands.
|
||||
*
|
||||
* Both operands must have the same numeric type, which will also be the result type. The result of
|
||||
* integer overflow is the infinite-precision result modulo 2^n. Floating-point multiplication is
|
||||
* performed according to IEEE-754.
|
||||
*/
|
||||
class MulInstruction extends BinaryArithmeticInstruction {
|
||||
MulInstruction() { getOpcode() instanceof Opcode::Mul }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the quotient of two numeric operands.
|
||||
*
|
||||
* Both operands must have the same numeric type, which will also be the result type. The result of
|
||||
* division by zero or integer overflow is undefined. Floating-point division is performed according
|
||||
* to IEEE-754.
|
||||
*/
|
||||
class DivInstruction extends BinaryArithmeticInstruction {
|
||||
DivInstruction() { getOpcode() instanceof Opcode::Div }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the remainder of two integer operands.
|
||||
*
|
||||
* Both operands must have the same integer type, which will also be the result type. The result of
|
||||
* division by zero or integer overflow is undefined.
|
||||
*/
|
||||
class RemInstruction extends BinaryArithmeticInstruction {
|
||||
RemInstruction() { getOpcode() instanceof Opcode::Rem }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that negates a single numeric operand.
|
||||
*
|
||||
* The operand must have a numeric type, which will also be the result type. The result of integer
|
||||
* negation uses two's complement, and is computed modulo 2^n. The result of floating-point negation
|
||||
* is performed according to IEEE-754.
|
||||
*/
|
||||
class NegateInstruction extends UnaryArithmeticInstruction {
|
||||
NegateInstruction() { getOpcode() instanceof Opcode::Negate }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the result of a bitwise operation.
|
||||
*/
|
||||
class BitwiseInstruction extends Instruction {
|
||||
BitwiseInstruction() { getOpcode() instanceof BitwiseOpcode }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that performs a bitwise operation on two integer operands.
|
||||
*/
|
||||
class BinaryBitwiseInstruction extends BitwiseInstruction, BinaryInstruction { }
|
||||
|
||||
/**
|
||||
* An instruction that performs a bitwise operation on a single integer operand.
|
||||
*/
|
||||
class UnaryBitwiseInstruction extends BitwiseInstruction, UnaryInstruction { }
|
||||
|
||||
/**
|
||||
* An instruction that computes the bitwise "and" of two integer operands.
|
||||
*
|
||||
* Both operands must have the same integer type, which will also be the result type.
|
||||
*/
|
||||
class BitAndInstruction extends BinaryBitwiseInstruction {
|
||||
BitAndInstruction() { getOpcode() instanceof Opcode::BitAnd }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the bitwise "or" of two integer operands.
|
||||
*
|
||||
* Both operands must have the same integer type, which will also be the result type.
|
||||
*/
|
||||
class BitOrInstruction extends BinaryBitwiseInstruction {
|
||||
BitOrInstruction() { getOpcode() instanceof Opcode::BitOr }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the bitwise "xor" of two integer operands.
|
||||
*
|
||||
* Both operands must have the same integer type, which will also be the result type.
|
||||
*/
|
||||
class BitXorInstruction extends BinaryBitwiseInstruction {
|
||||
BitXorInstruction() { getOpcode() instanceof Opcode::BitXor }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that shifts its left operand to the left by the number of bits specified by its
|
||||
* right operand.
|
||||
*
|
||||
* Both operands must have an integer type. The result has the same type as the left operand. The
|
||||
* rightmost bits are zero-filled.
|
||||
*/
|
||||
class ShiftLeftInstruction extends BinaryBitwiseInstruction {
|
||||
ShiftLeftInstruction() { getOpcode() instanceof Opcode::ShiftLeft }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that shifts its left operand to the right by the number of bits specified by its
|
||||
* right operand.
|
||||
*
|
||||
* Both operands must have an integer type. The result has the same type as the left operand. If the
|
||||
* left operand has an unsigned integer type, the leftmost bits are zero-filled. If the left operand
|
||||
* has a signed integer type, the leftmost bits are filled by duplicating the most significant bit
|
||||
* of the left operand.
|
||||
*/
|
||||
class ShiftRightInstruction extends BinaryBitwiseInstruction {
|
||||
ShiftRightInstruction() { getOpcode() instanceof Opcode::ShiftRight }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that performs a binary arithmetic operation involving at least one pointer
|
||||
* operand.
|
||||
*/
|
||||
class PointerArithmeticInstruction extends BinaryInstruction {
|
||||
int elementSize;
|
||||
|
||||
@@ -721,25 +1076,64 @@ class PointerArithmeticInstruction extends BinaryInstruction {
|
||||
|
||||
final override string getImmediateString() { result = elementSize.toString() }
|
||||
|
||||
/**
|
||||
* Gets the size of the elements pointed to by the pointer operands, in bytes.
|
||||
*
|
||||
* When adding an integer offset to a pointer (`PointerAddInstruction`) or subtracting an integer
|
||||
* offset from a pointer (`PointerSubInstruction`), the integer offset is multiplied by the
|
||||
* element size to compute the actual number of bytes added to or subtracted from the pointer
|
||||
* address. When computing the integer difference between two pointers (`PointerDiffInstruction`),
|
||||
* the result is computed by computing the difference between the two pointer byte addresses, then
|
||||
* dividing that byte count by the element size.
|
||||
*/
|
||||
final int getElementSize() { result = elementSize }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that adds or subtracts an integer offset from a pointer.
|
||||
*/
|
||||
class PointerOffsetInstruction extends PointerArithmeticInstruction {
|
||||
PointerOffsetInstruction() { getOpcode() instanceof PointerOffsetOpcode }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that adds an integer offset to a pointer.
|
||||
*
|
||||
* The result is the byte address computed by adding the value of the right (integer) operand,
|
||||
* multiplied by the element size, to the value of the left (pointer) operand. The result of pointer
|
||||
* overflow is undefined.
|
||||
*/
|
||||
class PointerAddInstruction extends PointerOffsetInstruction {
|
||||
PointerAddInstruction() { getOpcode() instanceof Opcode::PointerAdd }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that subtracts an integer offset from a pointer.
|
||||
*
|
||||
* The result is the byte address computed by subtracting the value of the right (integer) operand,
|
||||
* multiplied by the element size, from the value of the left (pointer) operand. The result of
|
||||
* pointer underflow is undefined.
|
||||
*/
|
||||
class PointerSubInstruction extends PointerOffsetInstruction {
|
||||
PointerSubInstruction() { getOpcode() instanceof Opcode::PointerSub }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the difference between two pointers.
|
||||
*
|
||||
* Both operands must have the same pointer type. The result must have an integer type whose size is
|
||||
* the same as that of the pointer operands. The result is computed by subtracting the byte address
|
||||
* in the right operand from the byte address in the left operand, and dividing by the element size.
|
||||
* If the difference in byte addresses is not divisible by the element size, the result is
|
||||
* undefined.
|
||||
*/
|
||||
class PointerDiffInstruction extends PointerArithmeticInstruction {
|
||||
PointerDiffInstruction() { getOpcode() instanceof Opcode::PointerDiff }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose result is computed from a single operand.
|
||||
*/
|
||||
class UnaryInstruction extends Instruction {
|
||||
UnaryInstruction() { getOpcode() instanceof UnaryOpcode }
|
||||
|
||||
@@ -748,17 +1142,44 @@ class UnaryInstruction extends Instruction {
|
||||
final Instruction getUnary() { result = getUnaryOperand().getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that converts the value of its operand to a value of a different type.
|
||||
*/
|
||||
class ConvertInstruction extends UnaryInstruction {
|
||||
ConvertInstruction() { getOpcode() instanceof Opcode::Convert }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that converts the address of a polymorphic object to the address of a different
|
||||
* subobject of the same polymorphic object, returning a null address if the dynamic type of the
|
||||
* object is not compatible with the result type.
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*
|
||||
* This instruction is used to represent a C++ `dynamic_cast<>` to a pointer type, or a C# `is` or
|
||||
* `as` expression.
|
||||
*/
|
||||
class CheckedConvertOrNullInstruction extends UnaryInstruction {
|
||||
CheckedConvertOrNullInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrNull }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instruction that converts between two addresses
|
||||
* related by inheritance.
|
||||
* An instruction that converts the address of a polymorphic object to the address of a different
|
||||
* subobject of the same polymorphic object, throwing an exception if the dynamic type of the object
|
||||
* is not compatible with the result type.
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*
|
||||
* This instruction is used to represent a C++ `dynamic_cast<>` to a reference type, or a C# cast
|
||||
* expression.
|
||||
*/
|
||||
class CheckedConvertOrThrowInstruction extends UnaryInstruction {
|
||||
CheckedConvertOrThrowInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrThrow }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that converts the address of an object to the address of a different subobject of
|
||||
* the same object, without any type checking at runtime.
|
||||
*/
|
||||
class InheritanceConversionInstruction extends UnaryInstruction {
|
||||
Language::Class baseClass;
|
||||
@@ -795,59 +1216,91 @@ class InheritanceConversionInstruction extends UnaryInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instruction that converts from the address of a derived class
|
||||
* to the address of a base class.
|
||||
* An instruction that converts from the address of a derived class to the address of a base class.
|
||||
*/
|
||||
class ConvertToBaseInstruction extends InheritanceConversionInstruction {
|
||||
ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instruction that converts from the address of a derived class
|
||||
* to the address of a direct non-virtual base class.
|
||||
* An instruction that converts from the address of a derived class to the address of a direct
|
||||
* non-virtual base class.
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*/
|
||||
class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction {
|
||||
ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instruction that converts from the address of a derived class
|
||||
* to the address of a virtual base class.
|
||||
* An instruction that converts from the address of a derived class to the address of a virtual base
|
||||
* class.
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*/
|
||||
class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction {
|
||||
ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instruction that converts from the address of a base class
|
||||
* to the address of a direct non-virtual derived class.
|
||||
* An instruction that converts from the address of a base class to the address of a direct
|
||||
* non-virtual derived class.
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*/
|
||||
class ConvertToDerivedInstruction extends InheritanceConversionInstruction {
|
||||
ConvertToDerivedInstruction() { getOpcode() instanceof Opcode::ConvertToDerived }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the bitwise complement of its operand.
|
||||
*
|
||||
* The operand must have an integer type, which will also be the result type.
|
||||
*/
|
||||
class BitComplementInstruction extends UnaryBitwiseInstruction {
|
||||
BitComplementInstruction() { getOpcode() instanceof Opcode::BitComplement }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that computes the logical complement of its operand.
|
||||
*
|
||||
* The operand must have a Boolean type, which will also be the result type.
|
||||
*/
|
||||
class LogicalNotInstruction extends UnaryInstruction {
|
||||
LogicalNotInstruction() { getOpcode() instanceof Opcode::LogicalNot }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that compares two numeric operands.
|
||||
*/
|
||||
class CompareInstruction extends BinaryInstruction {
|
||||
CompareInstruction() { getOpcode() instanceof CompareOpcode }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a `true` result if its operands are equal.
|
||||
*
|
||||
* Both operands must have the same numeric or address type. The result must have a Boolean type.
|
||||
* The result is `true` if `left == right`, and `false` if `left != right` or the two operands are
|
||||
* unordered. Floating-point comparison is performed according to IEEE-754.
|
||||
*/
|
||||
class CompareEQInstruction extends CompareInstruction {
|
||||
CompareEQInstruction() { getOpcode() instanceof Opcode::CompareEQ }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a `true` result if its operands are not equal.
|
||||
*
|
||||
* Both operands must have the same numeric or address type. The result must have a Boolean type.
|
||||
* The result is `true` if `left != right` or if the two operands are unordered, and `false` if
|
||||
* `left == right`. Floating-point comparison is performed according to IEEE-754.
|
||||
*/
|
||||
class CompareNEInstruction extends CompareInstruction {
|
||||
CompareNEInstruction() { getOpcode() instanceof Opcode::CompareNE }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instruction that does a relative comparison of two values, such as `<` or `>=`.
|
||||
* An instruction that does a relative comparison of two values, such as `<` or `>=`.
|
||||
*/
|
||||
class RelationalInstruction extends CompareInstruction {
|
||||
RelationalInstruction() { getOpcode() instanceof RelationalOpcode }
|
||||
@@ -874,6 +1327,13 @@ class RelationalInstruction extends CompareInstruction {
|
||||
predicate isStrict() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a `true` result if its left operand is less than its right operand.
|
||||
*
|
||||
* Both operands must have the same numeric or address type. The result must have a Boolean type.
|
||||
* The result is `true` if the `left < right`, and `false` if `left >= right` or if the two operands
|
||||
* are unordered. Floating-point comparison is performed according to IEEE-754.
|
||||
*/
|
||||
class CompareLTInstruction extends RelationalInstruction {
|
||||
CompareLTInstruction() { getOpcode() instanceof Opcode::CompareLT }
|
||||
|
||||
@@ -884,6 +1344,13 @@ class CompareLTInstruction extends RelationalInstruction {
|
||||
override predicate isStrict() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a `true` result if its left operand is greater than its right operand.
|
||||
*
|
||||
* Both operands must have the same numeric or address type. The result must have a Boolean type.
|
||||
* The result is `true` if the `left > right`, and `false` if `left <= right` or if the two operands
|
||||
* are unordered. Floating-point comparison is performed according to IEEE-754.
|
||||
*/
|
||||
class CompareGTInstruction extends RelationalInstruction {
|
||||
CompareGTInstruction() { getOpcode() instanceof Opcode::CompareGT }
|
||||
|
||||
@@ -894,6 +1361,14 @@ class CompareGTInstruction extends RelationalInstruction {
|
||||
override predicate isStrict() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a `true` result if its left operand is less than or equal to its
|
||||
* right operand.
|
||||
*
|
||||
* Both operands must have the same numeric or address type. The result must have a Boolean type.
|
||||
* The result is `true` if the `left <= right`, and `false` if `left > right` or if the two operands
|
||||
* are unordered. Floating-point comparison is performed according to IEEE-754.
|
||||
*/
|
||||
class CompareLEInstruction extends RelationalInstruction {
|
||||
CompareLEInstruction() { getOpcode() instanceof Opcode::CompareLE }
|
||||
|
||||
@@ -904,6 +1379,14 @@ class CompareLEInstruction extends RelationalInstruction {
|
||||
override predicate isStrict() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that returns a `true` result if its left operand is greater than or equal to its
|
||||
* right operand.
|
||||
*
|
||||
* Both operands must have the same numeric or address type. The result must have a Boolean type.
|
||||
* The result is `true` if the `left >= right`, and `false` if `left < right` or if the two operands
|
||||
* are unordered. Floating-point comparison is performed according to IEEE-754.
|
||||
*/
|
||||
class CompareGEInstruction extends RelationalInstruction {
|
||||
CompareGEInstruction() { getOpcode() instanceof Opcode::CompareGE }
|
||||
|
||||
@@ -914,15 +1397,32 @@ class CompareGEInstruction extends RelationalInstruction {
|
||||
override predicate isStrict() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that branches to one of multiple successor instructions based on the value of an
|
||||
* integer operand.
|
||||
*
|
||||
* This instruction will have zero or more successors whose edge kind is `CaseEdge`, each
|
||||
* representing the branch that will be taken if the controlling expression is within the range
|
||||
* specified for that case edge. The range of a case edge must be disjoint from the range of each
|
||||
* other case edge.
|
||||
*
|
||||
* The instruction may optionally have a successor edge whose edge kind is `DefaultEdge`,
|
||||
* representing the branch that will be taken if the controlling expression is not within the range
|
||||
* of any case edge.
|
||||
*/
|
||||
class SwitchInstruction extends Instruction {
|
||||
SwitchInstruction() { getOpcode() instanceof Opcode::Switch }
|
||||
|
||||
/** Gets the operand that provides the integer value controlling the switch. */
|
||||
final ConditionOperand getExpressionOperand() { result = getAnOperand() }
|
||||
|
||||
/** Gets the instruction whose result provides the integer value controlling the switch. */
|
||||
final Instruction getExpression() { result = getExpressionOperand().getDef() }
|
||||
|
||||
/** Gets the successor instructions along the case edges of the switch. */
|
||||
final Instruction getACaseSuccessor() { exists(CaseEdge edge | result = getSuccessor(edge)) }
|
||||
|
||||
/** Gets the successor instruction along the default edge of the switch, if any. */
|
||||
final Instruction getDefaultSuccessor() { result = getSuccessor(EdgeKind::defaultEdge()) }
|
||||
}
|
||||
|
||||
@@ -998,6 +1498,9 @@ class CallInstruction extends Instruction {
|
||||
class SideEffectInstruction extends Instruction {
|
||||
SideEffectInstruction() { getOpcode() instanceof SideEffectOpcode }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose execution causes this side effect.
|
||||
*/
|
||||
final Instruction getPrimaryInstruction() {
|
||||
result = Construction::getPrimaryInstructionForSideEffect(this)
|
||||
}
|
||||
|
||||
@@ -196,16 +196,17 @@ private predicate operandReturned(Operand operand, IntValue bitOffset) {
|
||||
bitOffset = Ints::unknown()
|
||||
}
|
||||
|
||||
private predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instruction init) {
|
||||
private predicate isArgumentForParameter(
|
||||
CallInstruction ci, Operand operand, InitializeParameterInstruction init
|
||||
) {
|
||||
exists(Language::Function f |
|
||||
ci = operand.getUse() and
|
||||
f = ci.getStaticCallTarget() and
|
||||
(
|
||||
init.(InitializeParameterInstruction).getParameter() =
|
||||
f.getParameter(operand.(PositionalArgumentOperand).getIndex())
|
||||
init.getParameter() = f.getParameter(operand.(PositionalArgumentOperand).getIndex())
|
||||
or
|
||||
init.(InitializeParameterInstruction).getIRVariable() instanceof IRThisVariable and
|
||||
init.getEnclosingFunction() = f and
|
||||
init.getIRVariable() instanceof IRThisVariable and
|
||||
unique( | | init.getEnclosingFunction()) = f and
|
||||
operand instanceof ThisArgumentOperand
|
||||
) and
|
||||
not Language::isFunctionVirtual(f) and
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Provides implementation classes modelling various methods of allocation
|
||||
* Provides implementation classes modeling various methods of allocation
|
||||
* (`malloc`, `new` etc). See `semmle.code.cpp.models.interfaces.Allocation`
|
||||
* for usage information.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Provides implementation classes modelling various methods of deallocation
|
||||
* Provides implementation classes modeling various methods of deallocation
|
||||
* (`free`, `delete` etc). See `semmle.code.cpp.models.interfaces.Deallocation`
|
||||
* for usage information.
|
||||
*/
|
||||
|
||||
@@ -48,4 +48,17 @@ class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, Alias
|
||||
output.isParameterDeref(0) and
|
||||
description = "String read by " + this.getName()
|
||||
}
|
||||
|
||||
override predicate hasArrayWithVariableSize(int bufParam, int countParam) {
|
||||
not hasGlobalOrStdName("gets") and
|
||||
bufParam = 0 and
|
||||
countParam = 1
|
||||
}
|
||||
|
||||
override predicate hasArrayWithUnknownSize(int bufParam) {
|
||||
hasGlobalOrStdName("gets") and
|
||||
bufParam = 0
|
||||
}
|
||||
|
||||
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
|
||||
}
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/**
|
||||
* Provides implementation classes modeling various standard formatting
|
||||
* functions (`printf`, `snprintf` etc).
|
||||
* See `semmle.code.cpp.models.interfaces.FormattingFunction` for usage
|
||||
* information.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.models.interfaces.FormattingFunction
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Provides implementation classes modeling `strcat` and various similar functions.
|
||||
* See `semmle.code.cpp.models.Models` for usage information.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
import semmle.code.cpp.models.interfaces.DataFlow
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Provides an abstract class for modelling functions and expressions that
|
||||
* Provides an abstract class for modeling functions and expressions that
|
||||
* allocate memory, such as the standard `malloc` function. To use this QL
|
||||
* library, create one or more QL classes extending a class here with a
|
||||
* characteristic predicate that selects the functions or expressions you are
|
||||
|
||||
@@ -19,5 +19,10 @@ import semmle.code.cpp.models.Models
|
||||
* to destinations; that is covered by `TaintModel.qll`.
|
||||
*/
|
||||
abstract class DataFlowFunction extends Function {
|
||||
/**
|
||||
* Holds if data can be copied from the argument, qualifier, or buffer
|
||||
* represented by `input` to the return value or buffer represented by
|
||||
* `output`
|
||||
*/
|
||||
abstract predicate hasDataFlow(FunctionInput input, FunctionOutput output);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Provides an abstract class for modelling functions and expressions that
|
||||
* Provides an abstract class for modeling functions and expressions that
|
||||
* deallocate memory, such as the standard `free` function. To use this QL
|
||||
* library, create one or more QL classes extending a class here with a
|
||||
* characteristic predicate that selects the functions or expressions you are
|
||||
|
||||
@@ -44,7 +44,7 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
|
||||
/** Gets the position at which the format parameter occurs. */
|
||||
abstract int getFormatParameterIndex();
|
||||
|
||||
override string getCanonicalQLClass() { result = "FormattingFunction" }
|
||||
override string getAPrimaryQlClass() { result = "FormattingFunction" }
|
||||
|
||||
/**
|
||||
* Holds if this `FormattingFunction` is in a context that supports
|
||||
|
||||
@@ -108,6 +108,20 @@ class FunctionInput extends TFunctionInput {
|
||||
predicate isQualifierAddress() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The input value of a parameter.
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
* void func(int n, char* p, float& r);
|
||||
* ```
|
||||
* - There is an `InParameter` representing the value of `n` (with type `int`) on entry to the
|
||||
* function.
|
||||
* - There is an `InParameter` representing the value of `p` (with type `char*`) on entry to the
|
||||
* function.
|
||||
* - There is an `InParameter` representing the "value" of the reference `r` (with type `float&`) on
|
||||
* entry to the function, _not_ the value of the referred-to `float`.
|
||||
*/
|
||||
class InParameter extends FunctionInput, TInParameter {
|
||||
ParameterIndex index;
|
||||
|
||||
@@ -121,6 +135,21 @@ class InParameter extends FunctionInput, TInParameter {
|
||||
override predicate isParameter(ParameterIndex i) { i = index }
|
||||
}
|
||||
|
||||
/**
|
||||
* The input value pointed to by a pointer parameter to a function, or the input value referred to
|
||||
* by a reference parameter to a function.
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
* void func(int n, char* p, float& r);
|
||||
* ```
|
||||
* - There is an `InParameterDeref` with `getIndex() = 1` that represents the value of `*p` (with
|
||||
* type `char`) on entry to the function.
|
||||
* - There is an `InParameterDeref` with `getIndex() = 2` that represents the value of `r` (with
|
||||
* type `float`) on entry to the function.
|
||||
* - There is no `InParameterDeref` representing the value of `n`, because `n` is neither a pointer
|
||||
* nor a reference.
|
||||
*/
|
||||
class InParameterDeref extends FunctionInput, TInParameterDeref {
|
||||
ParameterIndex index;
|
||||
|
||||
@@ -134,12 +163,36 @@ class InParameterDeref extends FunctionInput, TInParameterDeref {
|
||||
override predicate isParameterDeref(ParameterIndex i) { i = index }
|
||||
}
|
||||
|
||||
/**
|
||||
* The input value pointed to by the `this` pointer of an instance member function.
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
* struct C {
|
||||
* void mfunc(int n, char* p, float& r) const;
|
||||
* };
|
||||
* ```
|
||||
* - `InQualifierObject` represents the value of `*this` (with type `C const`) on entry to the
|
||||
* function.
|
||||
*/
|
||||
class InQualifierObject extends FunctionInput, TInQualifierObject {
|
||||
override string toString() { result = "InQualifierObject" }
|
||||
|
||||
override predicate isQualifierObject() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The input value of the `this` pointer of an instance member function.
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
* struct C {
|
||||
* void mfunc(int n, char* p, float& r) const;
|
||||
* };
|
||||
* ```
|
||||
* - `InQualifierAddress` represents the value of `this` (with type `C const *`) on entry to the
|
||||
* function.
|
||||
*/
|
||||
class InQualifierAddress extends FunctionInput, TInQualifierAddress {
|
||||
override string toString() { result = "InQualifierAddress" }
|
||||
|
||||
@@ -265,6 +318,21 @@ class FunctionOutput extends TFunctionOutput {
|
||||
deprecated final predicate isOutReturnPointer() { isReturnValueDeref() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The output value pointed to by a pointer parameter to a function, or the output value referred to
|
||||
* by a reference parameter to a function.
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
* void func(int n, char* p, float& r);
|
||||
* ```
|
||||
* - There is an `OutParameterDeref` with `getIndex()=1` that represents the value of `*p` (with
|
||||
* type `char`) on return from the function.
|
||||
* - There is an `OutParameterDeref` with `getIndex()=2` that represents the value of `r` (with
|
||||
* type `float`) on return from the function.
|
||||
* - There is no `OutParameterDeref` representing the value of `n`, because `n` is neither a
|
||||
* pointer nor a reference.
|
||||
*/
|
||||
class OutParameterDeref extends FunctionOutput, TOutParameterDeref {
|
||||
ParameterIndex index;
|
||||
|
||||
@@ -277,18 +345,62 @@ class OutParameterDeref extends FunctionOutput, TOutParameterDeref {
|
||||
override predicate isParameterDeref(ParameterIndex i) { i = index }
|
||||
}
|
||||
|
||||
/**
|
||||
* The output value pointed to by the `this` pointer of an instance member function.
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
* struct C {
|
||||
* void mfunc(int n, char* p, float& r);
|
||||
* };
|
||||
* ```
|
||||
* - The `OutQualifierObject` represents the value of `*this` (with type `C`) on return from the
|
||||
* function.
|
||||
*/
|
||||
class OutQualifierObject extends FunctionOutput, TOutQualifierObject {
|
||||
override string toString() { result = "OutQualifierObject" }
|
||||
|
||||
override predicate isQualifierObject() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The value returned by a function.
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
* int getInt();
|
||||
* char* getPointer();
|
||||
* float& getReference();
|
||||
* ```
|
||||
* - `OutReturnValue` represents the value returned by
|
||||
* `getInt()` (with type `int`).
|
||||
* - `OutReturnValue` represents the value returned by
|
||||
* `getPointer()` (with type `char*`).
|
||||
* - `OutReturnValue` represents the "value" of the reference returned by `getReference()` (with
|
||||
* type `float&`), _not_ the value of the referred-to `float`.
|
||||
*/
|
||||
class OutReturnValue extends FunctionOutput, TOutReturnValue {
|
||||
override string toString() { result = "OutReturnValue" }
|
||||
|
||||
override predicate isReturnValue() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The output value pointed to by the return value of a function, if the function returns a pointer,
|
||||
* or the output value referred to by the return value of a function, if the function returns a
|
||||
* reference.
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
* char* getPointer();
|
||||
* float& getReference();
|
||||
* int getInt();
|
||||
* ```
|
||||
* - `OutReturnValueDeref` represents the value of `*getPointer()` (with type `char`).
|
||||
* - `OutReturnValueDeref` represents the value of `getReference()` (with type `float`).
|
||||
* - `OutReturnValueDeref` does not represent the return value of `getInt()` because the return type
|
||||
* of `getInt()` is neither a pointer nor a reference.
|
||||
*/
|
||||
class OutReturnValueDeref extends FunctionOutput, TOutReturnValueDeref {
|
||||
override string toString() { result = "OutReturnValueDeref" }
|
||||
|
||||
|
||||
@@ -24,5 +24,9 @@ import semmle.code.cpp.models.Models
|
||||
* data flow.
|
||||
*/
|
||||
abstract class TaintFunction extends Function {
|
||||
/**
|
||||
* Holds if data passed into the argument, qualifier, or buffer represented by
|
||||
* `input` influences the return value or buffer represented by `output`
|
||||
*/
|
||||
abstract predicate hasTaintFlow(FunctionInput input, FunctionOutput output);
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -146,6 +146,9 @@ class StrCopyBW extends BufferWriteCall {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of the parameter that is the maximum size of the copy (in characters).
|
||||
*/
|
||||
int getParamSize() {
|
||||
exists(TopLevelFunction fn, string name |
|
||||
fn = getTarget() and
|
||||
@@ -161,6 +164,9 @@ class StrCopyBW extends BufferWriteCall {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of the parameter that is the source of the copy.
|
||||
*/
|
||||
int getParamSrc() {
|
||||
exists(TopLevelFunction fn, string name |
|
||||
fn = getTarget() and
|
||||
@@ -194,8 +200,14 @@ class StrCopyBW extends BufferWriteCall {
|
||||
class StrCatBW extends BufferWriteCall {
|
||||
StrCatBW() { exists(TopLevelFunction fn | fn = getTarget() and fn instanceof StrcatFunction) }
|
||||
|
||||
/**
|
||||
* Gets the index of the parameter that is the maximum size of the copy (in characters).
|
||||
*/
|
||||
int getParamSize() { if exists(getArgument(2)) then result = 2 else none() }
|
||||
|
||||
/**
|
||||
* Gets the index of the parameter that is the source of the copy.
|
||||
*/
|
||||
int getParamSrc() { result = 1 }
|
||||
|
||||
override Type getBufferType() {
|
||||
@@ -349,6 +361,9 @@ class SnprintfBW extends BufferWriteCall {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of the parameter that is the size of the destination (in characters).
|
||||
*/
|
||||
int getParamSize() { result = 1 }
|
||||
|
||||
override Type getBufferType() {
|
||||
@@ -399,6 +414,9 @@ class GetsBW extends BufferWriteCall {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of the parameter that is the maximum number of characters to be read.
|
||||
*/
|
||||
int getParamSize() { if exists(getArgument(1)) then result = 1 else none() }
|
||||
|
||||
override Type getBufferType() { result = this.getTarget().getParameter(0).getUnspecifiedType() }
|
||||
@@ -434,6 +452,9 @@ class ScanfBW extends BufferWrite {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of the parameter that is the first format argument.
|
||||
*/
|
||||
int getParamArgs() {
|
||||
exists(FunctionCall fc |
|
||||
this = fc.getArgument(_) and
|
||||
|
||||
@@ -2,21 +2,44 @@
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.security.FunctionWithWrappers
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
|
||||
/**
|
||||
* A function for running a command using a command interpreter.
|
||||
*/
|
||||
class SystemFunction extends FunctionWithWrappers {
|
||||
class SystemFunction extends FunctionWithWrappers, ArrayFunction, AliasFunction, SideEffectFunction {
|
||||
SystemFunction() {
|
||||
hasGlobalOrStdName("system") or
|
||||
hasGlobalName("popen") or
|
||||
hasGlobalOrStdName("system") or // system(command)
|
||||
hasGlobalName("popen") or // popen(command, mode)
|
||||
// Windows variants
|
||||
hasGlobalName("_popen") or
|
||||
hasGlobalName("_wpopen") or
|
||||
hasGlobalName("_wsystem")
|
||||
hasGlobalName("_popen") or // _popen(command, mode)
|
||||
hasGlobalName("_wpopen") or // _wpopen(command, mode)
|
||||
hasGlobalName("_wsystem") // _wsystem(command)
|
||||
}
|
||||
|
||||
override predicate interestingArg(int arg) { arg = 0 }
|
||||
|
||||
override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 or bufParam = 1 }
|
||||
|
||||
override predicate hasArrayInput(int bufParam) { bufParam = 0 or bufParam = 1 }
|
||||
|
||||
override predicate parameterNeverEscapes(int index) { index = 0 or index = 1 }
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||
|
||||
override predicate parameterIsAlwaysReturned(int index) { none() }
|
||||
|
||||
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||
|
||||
override predicate hasOnlySpecificWriteSideEffects() {
|
||||
hasGlobalOrStdName("system") or
|
||||
hasGlobalName("_wsystem")
|
||||
}
|
||||
|
||||
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||
(i = 0 or i = 1) and
|
||||
buffer = true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,13 +1,23 @@
|
||||
/**
|
||||
* Provides classes for modeling writing of data to files through various standard mechanisms such as `fprintf`, `fwrite` and `operator<<`.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/**
|
||||
* A function call that writes to a file
|
||||
* A function call that writes to a file.
|
||||
*/
|
||||
class FileWrite extends Expr {
|
||||
FileWrite() { fileWrite(this, _, _) }
|
||||
|
||||
/**
|
||||
* Gets a source expression of this write.
|
||||
*/
|
||||
Expr getASource() { fileWrite(this, result, _) }
|
||||
|
||||
/**
|
||||
* Gets the expression for the object being written to.
|
||||
*/
|
||||
Expr getDest() { fileWrite(this, _, result) }
|
||||
}
|
||||
|
||||
@@ -44,17 +54,17 @@ class BasicOStreamCall extends FunctionCall {
|
||||
*/
|
||||
abstract class ChainedOutputCall extends BasicOStreamCall {
|
||||
/**
|
||||
* The source expression of this output.
|
||||
* Gets the source expression of this output.
|
||||
*/
|
||||
abstract Expr getSource();
|
||||
|
||||
/**
|
||||
* The immediate destination expression of this output.
|
||||
* Gets the immediate destination expression of this output.
|
||||
*/
|
||||
abstract Expr getDest();
|
||||
|
||||
/**
|
||||
* The destination at the far left-hand end of the output chain.
|
||||
* Gets the destination at the far left-hand end of the output chain.
|
||||
*/
|
||||
Expr getEndDest() {
|
||||
// recurse into the destination
|
||||
@@ -108,7 +118,7 @@ class WriteFunctionCall extends ChainedOutputCall {
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the function call is a call to << that eventually starts at the given file stream.
|
||||
* Whether the function call is a call to `operator<<` or a similar function, that eventually starts at the given file stream.
|
||||
*/
|
||||
private predicate fileStreamChain(ChainedOutputCall out, Expr source, Expr dest) {
|
||||
source = out.getSource() and
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
/**
|
||||
* Provides classes for modeling output to standard output / standard error through various mechanisms such as `printf`, `puts` and `operator<<`.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import FileWrite
|
||||
|
||||
/**
|
||||
* A function call that writes to standard output or standard error
|
||||
* A function call that writes to standard output or standard error.
|
||||
*/
|
||||
class OutputWrite extends Expr {
|
||||
OutputWrite() { outputWrite(this, _) }
|
||||
|
||||
/**
|
||||
* Gets a source expression for this output.
|
||||
*/
|
||||
Expr getASource() { outputWrite(this, result) }
|
||||
}
|
||||
|
||||
@@ -49,7 +56,7 @@ private predicate outputFile(Expr e) {
|
||||
}
|
||||
|
||||
/**
|
||||
* is the function call a write to standard output or standard error from 'source'
|
||||
* Holds if the function call is a write to standard output or standard error from 'source'.
|
||||
*/
|
||||
private predicate outputWrite(Expr write, Expr source) {
|
||||
exists(Function f, int arg |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Security pack options.
|
||||
*
|
||||
* see https://semmle.com/wiki/display/SD/_Configuring+SecurityOptions+for+your+code+base
|
||||
@@ -9,6 +9,10 @@
|
||||
|
||||
import semmle.code.cpp.security.Security
|
||||
|
||||
/**
|
||||
* This class overrides `SecurityOptions` and can be used to add project
|
||||
* specific customization.
|
||||
*/
|
||||
class CustomSecurityOptions extends SecurityOptions {
|
||||
override predicate sqlArgument(string function, int arg) {
|
||||
SecurityOptions.super.sqlArgument(function, arg)
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides a class to model C/C++ block statements, enclosed by `{` and `}`.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Element
|
||||
import semmle.code.cpp.stmts.Stmt
|
||||
|
||||
@@ -14,7 +18,7 @@ import semmle.code.cpp.stmts.Stmt
|
||||
* ```
|
||||
*/
|
||||
class Block extends Stmt, @stmt_block {
|
||||
override string getCanonicalQLClass() { result = "Block" }
|
||||
override string getAPrimaryQlClass() { result = "Block" }
|
||||
|
||||
/**
|
||||
* Gets a child declaration of this block.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides a hierarchy of classes for modeling C/C++ statements.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Element
|
||||
private import semmle.code.cpp.Enclosing
|
||||
private import semmle.code.cpp.internal.ResolveClass
|
||||
@@ -150,7 +154,7 @@ abstract class StmtParent extends ControlFlowNode { }
|
||||
* is an assignment expression inside an 'expression' statement.
|
||||
*/
|
||||
class ExprStmt extends Stmt, @stmt_expr {
|
||||
override string getCanonicalQLClass() { result = "ExprStmt" }
|
||||
override string getAPrimaryQlClass() { result = "ExprStmt" }
|
||||
|
||||
/**
|
||||
* Gets the expression of this 'expression' statement.
|
||||
@@ -208,7 +212,7 @@ abstract class ConditionalStmt extends ControlStructure { }
|
||||
* ```
|
||||
*/
|
||||
class IfStmt extends ConditionalStmt, @stmt_if {
|
||||
override string getCanonicalQLClass() { result = "IfStmt" }
|
||||
override string getAPrimaryQlClass() { result = "IfStmt" }
|
||||
|
||||
/**
|
||||
* Gets the condition expression of this 'if' statement.
|
||||
@@ -294,7 +298,7 @@ class IfStmt extends ConditionalStmt, @stmt_if {
|
||||
* ```
|
||||
*/
|
||||
class ConstexprIfStmt extends ConditionalStmt, @stmt_constexpr_if {
|
||||
override string getCanonicalQLClass() { result = "ConstexprIfStmt" }
|
||||
override string getAPrimaryQlClass() { result = "ConstexprIfStmt" }
|
||||
|
||||
/**
|
||||
* Gets the condition expression of this 'constexpr if' statement.
|
||||
@@ -393,7 +397,7 @@ abstract class Loop extends ControlStructure {
|
||||
* ```
|
||||
*/
|
||||
class WhileStmt extends Loop, @stmt_while {
|
||||
override string getCanonicalQLClass() { result = "WhileStmt" }
|
||||
override string getAPrimaryQlClass() { result = "WhileStmt" }
|
||||
|
||||
override Expr getCondition() { result = this.getChild(0) }
|
||||
|
||||
@@ -458,7 +462,7 @@ class WhileStmt extends Loop, @stmt_while {
|
||||
* A C/C++ jump statement.
|
||||
*/
|
||||
abstract class JumpStmt extends Stmt, @jump {
|
||||
override string getCanonicalQLClass() { result = "JumpStmt" }
|
||||
override string getAPrimaryQlClass() { result = "JumpStmt" }
|
||||
|
||||
/** Gets the target of this jump statement. */
|
||||
Stmt getTarget() { jumpinfo(underlyingElement(this), _, unresolveElement(result)) }
|
||||
@@ -475,7 +479,7 @@ abstract class JumpStmt extends Stmt, @jump {
|
||||
* ```
|
||||
*/
|
||||
class GotoStmt extends JumpStmt, @stmt_goto {
|
||||
override string getCanonicalQLClass() { result = "GotoStmt" }
|
||||
override string getAPrimaryQlClass() { result = "GotoStmt" }
|
||||
|
||||
/**
|
||||
* Gets the name of the label this 'goto' statement refers to.
|
||||
@@ -570,7 +574,7 @@ class ComputedGotoStmt extends Stmt, @stmt_assigned_goto {
|
||||
* ```
|
||||
*/
|
||||
class ContinueStmt extends JumpStmt, @stmt_continue {
|
||||
override string getCanonicalQLClass() { result = "ContinueStmt" }
|
||||
override string getAPrimaryQlClass() { result = "ContinueStmt" }
|
||||
|
||||
override string toString() { result = "continue;" }
|
||||
|
||||
@@ -602,7 +606,7 @@ private Stmt getEnclosingContinuable(Stmt s) {
|
||||
* ```
|
||||
*/
|
||||
class BreakStmt extends JumpStmt, @stmt_break {
|
||||
override string getCanonicalQLClass() { result = "BreakStmt" }
|
||||
override string getAPrimaryQlClass() { result = "BreakStmt" }
|
||||
|
||||
override string toString() { result = "break;" }
|
||||
|
||||
@@ -635,7 +639,7 @@ private Stmt getEnclosingBreakable(Stmt s) {
|
||||
* ```
|
||||
*/
|
||||
class LabelStmt extends Stmt, @stmt_label {
|
||||
override string getCanonicalQLClass() { result = "LabelStmt" }
|
||||
override string getAPrimaryQlClass() { result = "LabelStmt" }
|
||||
|
||||
/** Gets the name of this 'label' statement. */
|
||||
string getName() { jumpinfo(underlyingElement(this), result, _) and result != "" }
|
||||
@@ -663,7 +667,7 @@ class LabelStmt extends Stmt, @stmt_label {
|
||||
* ```
|
||||
*/
|
||||
class ReturnStmt extends Stmt, @stmt_return {
|
||||
override string getCanonicalQLClass() { result = "ReturnStmt" }
|
||||
override string getAPrimaryQlClass() { result = "ReturnStmt" }
|
||||
|
||||
/**
|
||||
* Gets the expression of this 'return' statement.
|
||||
@@ -711,7 +715,7 @@ class ReturnStmt extends Stmt, @stmt_return {
|
||||
* ```
|
||||
*/
|
||||
class DoStmt extends Loop, @stmt_end_test_while {
|
||||
override string getCanonicalQLClass() { result = "DoStmt" }
|
||||
override string getAPrimaryQlClass() { result = "DoStmt" }
|
||||
|
||||
override Expr getCondition() { result = this.getChild(0) }
|
||||
|
||||
@@ -760,7 +764,7 @@ class DoStmt extends Loop, @stmt_end_test_while {
|
||||
* where `begin_expr` and `end_expr` depend on the type of `xs`.
|
||||
*/
|
||||
class RangeBasedForStmt extends Loop, @stmt_range_based_for {
|
||||
override string getCanonicalQLClass() { result = "RangeBasedForStmt" }
|
||||
override string getAPrimaryQlClass() { result = "RangeBasedForStmt" }
|
||||
|
||||
/**
|
||||
* Gets the 'body' statement of this range-based 'for' statement.
|
||||
@@ -847,7 +851,7 @@ class RangeBasedForStmt extends Loop, @stmt_range_based_for {
|
||||
* ```
|
||||
*/
|
||||
class ForStmt extends Loop, @stmt_for {
|
||||
override string getCanonicalQLClass() { result = "ForStmt" }
|
||||
override string getAPrimaryQlClass() { result = "ForStmt" }
|
||||
|
||||
/**
|
||||
* Gets the initialization statement of this 'for' statement.
|
||||
@@ -1078,7 +1082,7 @@ private predicate inForUpdate(Expr forUpdate, Expr child) {
|
||||
* ```
|
||||
*/
|
||||
class SwitchCase extends Stmt, @stmt_switch_case {
|
||||
override string getCanonicalQLClass() { result = "SwitchCase" }
|
||||
override string getAPrimaryQlClass() { result = "SwitchCase" }
|
||||
|
||||
/**
|
||||
* Gets the expression of this 'switch case' statement (or the start of
|
||||
@@ -1431,7 +1435,7 @@ class DefaultCase extends SwitchCase {
|
||||
* ```
|
||||
*/
|
||||
class SwitchStmt extends ConditionalStmt, @stmt_switch {
|
||||
override string getCanonicalQLClass() { result = "SwitchStmt" }
|
||||
override string getAPrimaryQlClass() { result = "SwitchStmt" }
|
||||
|
||||
/**
|
||||
* Gets the expression that this 'switch' statement switches on.
|
||||
@@ -1642,7 +1646,7 @@ class EnumSwitch extends SwitchStmt {
|
||||
class Handler extends Stmt, @stmt_handler {
|
||||
override string toString() { result = "<handler>" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "Handler" }
|
||||
override string getAPrimaryQlClass() { result = "Handler" }
|
||||
|
||||
/**
|
||||
* Gets the block containing the implementation of this handler.
|
||||
@@ -1695,7 +1699,7 @@ deprecated class FinallyEnd extends Stmt {
|
||||
* ```
|
||||
*/
|
||||
class TryStmt extends Stmt, @stmt_try_block {
|
||||
override string getCanonicalQLClass() { result = "TryStmt" }
|
||||
override string getAPrimaryQlClass() { result = "TryStmt" }
|
||||
|
||||
override string toString() { result = "try { ... }" }
|
||||
|
||||
@@ -1770,7 +1774,7 @@ class TryStmt extends Stmt, @stmt_try_block {
|
||||
class FunctionTryStmt extends TryStmt {
|
||||
FunctionTryStmt() { not exists(this.getEnclosingBlock()) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "FunctionTryStmt" }
|
||||
override string getAPrimaryQlClass() { result = "FunctionTryStmt" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1787,7 +1791,7 @@ class FunctionTryStmt extends TryStmt {
|
||||
* ```
|
||||
*/
|
||||
class CatchBlock extends Block {
|
||||
override string getCanonicalQLClass() { result = "CatchBlock" }
|
||||
override string getAPrimaryQlClass() { result = "CatchBlock" }
|
||||
|
||||
CatchBlock() { ishandler(underlyingElement(this)) }
|
||||
|
||||
@@ -1818,7 +1822,7 @@ class CatchBlock extends Block {
|
||||
class CatchAnyBlock extends CatchBlock {
|
||||
CatchAnyBlock() { not exists(this.getParameter()) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "CatchAnyBlock" }
|
||||
override string getAPrimaryQlClass() { result = "CatchAnyBlock" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1855,7 +1859,7 @@ class MicrosoftTryExceptStmt extends MicrosoftTryStmt {
|
||||
/** Gets the `__except` statement (usually a `Block`). */
|
||||
Stmt getExcept() { result = getChild(2) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "MicrosoftTryExceptStmt" }
|
||||
override string getAPrimaryQlClass() { result = "MicrosoftTryExceptStmt" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1879,7 +1883,7 @@ class MicrosoftTryFinallyStmt extends MicrosoftTryStmt {
|
||||
/** Gets the `__finally` statement (usually a `Block`). */
|
||||
Stmt getFinally() { result = getChild(1) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "MicrosoftTryFinallyStmt" }
|
||||
override string getAPrimaryQlClass() { result = "MicrosoftTryFinallyStmt" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1891,7 +1895,7 @@ class MicrosoftTryFinallyStmt extends MicrosoftTryStmt {
|
||||
* ```
|
||||
*/
|
||||
class DeclStmt extends Stmt, @stmt_decl {
|
||||
override string getCanonicalQLClass() { result = "DeclStmt" }
|
||||
override string getAPrimaryQlClass() { result = "DeclStmt" }
|
||||
|
||||
/**
|
||||
* Gets the `i`th declaration entry declared by this 'declaration' statement.
|
||||
@@ -1972,7 +1976,7 @@ class DeclStmt extends Stmt, @stmt_decl {
|
||||
* ```
|
||||
*/
|
||||
class EmptyStmt extends Stmt, @stmt_empty {
|
||||
override string getCanonicalQLClass() { result = "EmptyStmt" }
|
||||
override string getAPrimaryQlClass() { result = "EmptyStmt" }
|
||||
|
||||
override string toString() { result = ";" }
|
||||
|
||||
@@ -1992,7 +1996,7 @@ class EmptyStmt extends Stmt, @stmt_empty {
|
||||
class AsmStmt extends Stmt, @stmt_asm {
|
||||
override string toString() { result = "asm statement" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "AsmStmt" }
|
||||
override string getAPrimaryQlClass() { result = "AsmStmt" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2009,7 +2013,7 @@ class AsmStmt extends Stmt, @stmt_asm {
|
||||
class VlaDimensionStmt extends Stmt, @stmt_set_vla_size {
|
||||
override string toString() { result = "VLA dimension size" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "VlaDimensionStmt" }
|
||||
override string getAPrimaryQlClass() { result = "VlaDimensionStmt" }
|
||||
|
||||
/** Gets the expression which gives the size. */
|
||||
Expr getDimensionExpr() { result = this.getChild(0) }
|
||||
@@ -2028,7 +2032,7 @@ class VlaDimensionStmt extends Stmt, @stmt_set_vla_size {
|
||||
class VlaDeclStmt extends Stmt, @stmt_vla_decl {
|
||||
override string toString() { result = "VLA declaration" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "VlaDeclStmt" }
|
||||
override string getAPrimaryQlClass() { result = "VlaDeclStmt" }
|
||||
|
||||
/**
|
||||
* Gets the number of VLA dimension statements in this VLA
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import semmle.code.cpp.rangeanalysis.RangeAnalysis
|
||||
import experimental.semmle.code.cpp.rangeanalysis.RangeAnalysis
|
||||
import semmle.code.cpp.ir.IR
|
||||
import semmle.code.cpp.controlflow.IRGuards
|
||||
import semmle.code.cpp.ir.ValueNumbering
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user