Merge branch 'master' into copymove

This commit is contained in:
Geoffrey White
2020-06-30 16:20:41 +01:00
530 changed files with 15308 additions and 5266 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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() }

View File

@@ -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 = "???" }
}
/**

View File

@@ -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() }

View File

@@ -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

View File

@@ -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" }
}
/**

View File

@@ -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

View File

@@ -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

View File

@@ -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 }

View File

@@ -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) }
}

View File

@@ -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

View File

@@ -1,3 +1,7 @@
/**
* Provides classes and predicates for locations in the source code.
*/
import semmle.code.cpp.Element
import semmle.code.cpp.File

View 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()
}

View File

@@ -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

View File

@@ -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" }
}

View File

@@ -1,3 +1,8 @@
/**
* Provides classes for working with name qualifiers such as the `N::` in
* `N::f()`.
*/
import cpp
/**

View File

@@ -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" }
}
/**

View File

@@ -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 }
}

View File

@@ -1,3 +1,7 @@
/**
* DEPRECATED: Objective-C is no longer supported.
*/
import semmle.code.cpp.Class
private import semmle.code.cpp.internal.ResolveClass

View File

@@ -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.

View File

@@ -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" }
}
/**

View File

@@ -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"
}

View File

@@ -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" }
}
/**

View File

@@ -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"
}

View File

@@ -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.

View File

@@ -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.

View File

@@ -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") }

View File

@@ -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.

View File

@@ -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") }

View File

@@ -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" }
}

View File

@@ -1,3 +1,7 @@
/**
* Provides predicates for identifying function calls that open or close a file.
*/
import cpp
/**

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 {

View File

@@ -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

View File

@@ -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

View File

@@ -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))
* ```
*

View File

@@ -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))
* ```
*

View File

@@ -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.

View File

@@ -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 }
}

View File

@@ -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

View File

@@ -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" }
}

View File

@@ -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) }

View File

@@ -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) }

View File

@@ -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() }

View File

@@ -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 = "<=" }

View File

@@ -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 }

View File

@@ -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.

View File

@@ -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() }

View File

@@ -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() {

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 {

View File

@@ -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
}
/**

View File

@@ -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]

View File

@@ -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))
* ```
*

View File

@@ -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))
* ```
*

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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.
*/

View File

@@ -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.
*/

View File

@@ -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 }
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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" }

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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()
/**

View File

@@ -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

View File

@@ -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))
}

View File

@@ -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

View File

@@ -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
}
}
/**

View File

@@ -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 &lt;&lt; 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

View File

@@ -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 |

View File

@@ -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)

View File

@@ -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.

View File

@@ -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

View File

@@ -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