mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge branch 'master' of github.com:github/codeql into SharedDataflow
to receive updates from data flow library
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
- [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
|
||||
- [bluebird](http://bluebirdjs.com/)
|
||||
- [express](https://www.npmjs.com/package/express)
|
||||
- [fancy-log](https://www.npmjs.com/package/fancy-log)
|
||||
- [fastify](https://www.npmjs.com/package/fastify)
|
||||
- [fstream](https://www.npmjs.com/package/fstream)
|
||||
- [jGrowl](https://github.com/stanlemon/jGrowl)
|
||||
@@ -22,6 +23,7 @@
|
||||
- [sqlite](https://www.npmjs.com/package/sqlite)
|
||||
- [ssh2-streams](https://www.npmjs.com/package/ssh2-streams)
|
||||
- [ssh2](https://www.npmjs.com/package/ssh2)
|
||||
- [vue](https://www.npmjs.com/package/vue)
|
||||
- [yargs](https://www.npmjs.com/package/yargs)
|
||||
- [webpack-dev-server](https://www.npmjs.com/package/webpack-dev-server)
|
||||
|
||||
|
||||
102
config/opcode-qldoc.py
Normal file
102
config/opcode-qldoc.py
Normal file
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import re
|
||||
path = os.path
|
||||
|
||||
needs_an_re = re.compile(r'^(?!Unary)[AEIOU]') # Name requiring "an" instead of "a".
|
||||
start_qldoc_re = re.compile(r'^\s*/\*\*') # Start of a QLDoc comment
|
||||
end_qldoc_re = re.compile(r'\*/\s*$') # End of a QLDoc comment
|
||||
blank_qldoc_line_re = re.compile(r'^\s*\*\s*$') # A line in a QLDoc comment with only the '*'
|
||||
instruction_class_re = re.compile(r'^class (?P<name>[A-aa-z0-9]+)Instruction\s') # Declaration of an `Instruction` class
|
||||
opcode_base_class_re = re.compile(r'^abstract class (?P<name>[A-aa-z0-9]+)Opcode\s') # Declaration of an `Opcode` base class
|
||||
opcode_class_re = re.compile(r'^ class (?P<name>[A-aa-z0-9]+)\s') # Declaration of an `Opcode` class
|
||||
|
||||
script_dir = path.realpath(path.dirname(__file__))
|
||||
instruction_path = path.realpath(path.join(script_dir, '../cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll'))
|
||||
opcode_path = path.realpath(path.join(script_dir, '../cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll'))
|
||||
|
||||
# Scan `Instruction.qll`, keeping track of the QLDoc comment attached to each declaration of a class
|
||||
# whose name ends with `Instruction`.
|
||||
instruction_comments = {}
|
||||
in_qldoc = False
|
||||
saw_blank_line_in_qldoc = False
|
||||
qldoc_lines = []
|
||||
with open(instruction_path, 'r', encoding='utf-8') as instr:
|
||||
for line in instr:
|
||||
if in_qldoc:
|
||||
if end_qldoc_re.search(line):
|
||||
qldoc_lines.append(line)
|
||||
in_qldoc = False
|
||||
elif blank_qldoc_line_re.search(line):
|
||||
# We're going to skip any lines after the first blank line, to avoid duplicating all
|
||||
# of the verbose description.
|
||||
saw_blank_line_in_qldoc = True
|
||||
elif not saw_blank_line_in_qldoc:
|
||||
qldoc_lines.append(line)
|
||||
else:
|
||||
if start_qldoc_re.search(line):
|
||||
# Starting a new QLDoc comment.
|
||||
saw_blank_line_in_qldoc = False
|
||||
qldoc_lines.append(line)
|
||||
if not end_qldoc_re.search(line):
|
||||
in_qldoc = True
|
||||
else:
|
||||
instruction_match = instruction_class_re.search(line)
|
||||
if instruction_match:
|
||||
# Found the declaration of an `Instruction` class. Record the QLDoc comments.
|
||||
instruction_comments[instruction_match.group('name')] = qldoc_lines
|
||||
qldoc_lines = []
|
||||
|
||||
# Scan `Opcode.qll`. Whenever we see the declaration of an `Opcode` class for which we have a
|
||||
# corresponding `Instruction` class, we'll attach a copy of the `Instruction`'s QLDoc comment.
|
||||
in_qldoc = False
|
||||
qldoc_lines = []
|
||||
output_lines = []
|
||||
with open(opcode_path, 'r', encoding='utf-8') as opcode:
|
||||
for line in opcode:
|
||||
if in_qldoc:
|
||||
qldoc_lines.append(line)
|
||||
if end_qldoc_re.search(line):
|
||||
in_qldoc = False
|
||||
else:
|
||||
if start_qldoc_re.search(line):
|
||||
qldoc_lines.append(line)
|
||||
if not end_qldoc_re.search(line):
|
||||
in_qldoc = True
|
||||
else:
|
||||
name_without_suffix = None
|
||||
name = None
|
||||
indent = ''
|
||||
opcode_base_match = opcode_base_class_re.search(line)
|
||||
if opcode_base_match:
|
||||
name_without_suffix = opcode_base_match.group('name')
|
||||
name = name_without_suffix + 'Opcode'
|
||||
else:
|
||||
opcode_match = opcode_class_re.search(line)
|
||||
if opcode_match:
|
||||
name_without_suffix = opcode_match.group('name')
|
||||
name = name_without_suffix
|
||||
# Indent by two additional spaces, since opcodes are declared in the
|
||||
# `Opcode` module.
|
||||
indent = ' '
|
||||
|
||||
if name_without_suffix:
|
||||
# Found an `Opcode` that matches a known `Instruction`. Replace the QLDoc with
|
||||
# a copy of the one from the `Instruction`.
|
||||
if instruction_comments.get(name_without_suffix):
|
||||
article = 'an' if needs_an_re.search(name_without_suffix) else 'a'
|
||||
qldoc_lines = [
|
||||
indent + '/**\n',
|
||||
indent + ' * The `Opcode` for ' + article + ' `' + name_without_suffix + 'Instruction`.\n',
|
||||
indent + ' *\n',
|
||||
indent + ' * See the `' + name_without_suffix + 'Instruction` documentation for more details.\n',
|
||||
indent + ' */\n'
|
||||
]
|
||||
output_lines.extend(qldoc_lines)
|
||||
qldoc_lines = []
|
||||
output_lines.append(line)
|
||||
|
||||
# Write out the updated `Opcode.qll`
|
||||
with open(opcode_path, 'w', encoding='utf-8') as opcode:
|
||||
opcode.writelines(output_lines)
|
||||
@@ -18,7 +18,7 @@ abstract class InsecureCryptoSpec extends Locatable {
|
||||
}
|
||||
|
||||
Function getAnInsecureFunction() {
|
||||
result.getName().regexpMatch(algorithmBlacklistRegex()) and
|
||||
result.getName().regexpMatch(getInsecureAlgorithmRegex()) and
|
||||
exists(result.getACallToThisFunction())
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ class InsecureFunctionCall extends InsecureCryptoSpec, FunctionCall {
|
||||
}
|
||||
|
||||
Macro getAnInsecureMacro() {
|
||||
result.getName().regexpMatch(algorithmBlacklistRegex()) and
|
||||
result.getName().regexpMatch(getInsecureAlgorithmRegex()) and
|
||||
exists(result.getAnInvocation())
|
||||
}
|
||||
|
||||
|
||||
@@ -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() }
|
||||
|
||||
@@ -124,7 +124,7 @@ class Declaration extends Locatable, @declaration {
|
||||
* To test whether this declaration has a particular name in the global
|
||||
* namespace, use `hasGlobalName`.
|
||||
*/
|
||||
abstract string getName();
|
||||
string getName() { none() } // overridden in subclasses
|
||||
|
||||
/** Holds if this declaration has the given name. */
|
||||
predicate hasName(string name) { name = this.getName() }
|
||||
@@ -140,7 +140,7 @@ class Declaration extends Locatable, @declaration {
|
||||
}
|
||||
|
||||
/** Gets a specifier of this declaration. */
|
||||
abstract Specifier getASpecifier();
|
||||
Specifier getASpecifier() { none() } // overridden in subclasses
|
||||
|
||||
/** Holds if this declaration has a specifier with the given name. */
|
||||
predicate hasSpecifier(string name) { this.getASpecifier().hasName(name) }
|
||||
@@ -156,7 +156,7 @@ class Declaration extends Locatable, @declaration {
|
||||
* Gets the location of a declaration entry corresponding to this
|
||||
* declaration.
|
||||
*/
|
||||
abstract Location getADeclarationLocation();
|
||||
Location getADeclarationLocation() { none() } // overridden in subclasses
|
||||
|
||||
/**
|
||||
* Gets the declaration entry corresponding to this declaration that is a
|
||||
@@ -165,7 +165,7 @@ class Declaration extends Locatable, @declaration {
|
||||
DeclarationEntry getDefinition() { none() }
|
||||
|
||||
/** Gets the location of the definition, if any. */
|
||||
abstract Location getDefinitionLocation();
|
||||
Location getDefinitionLocation() { none() } // overridden in subclasses
|
||||
|
||||
/** Holds if the declaration has a definition. */
|
||||
predicate hasDefinition() { exists(this.getDefinition()) }
|
||||
@@ -289,6 +289,8 @@ class Declaration extends Locatable, @declaration {
|
||||
}
|
||||
}
|
||||
|
||||
private class TDeclarationEntry = @var_decl or @type_decl or @fun_decl;
|
||||
|
||||
/**
|
||||
* A C/C++ declaration entry. For example the following code contains five
|
||||
* declaration entries:
|
||||
@@ -304,9 +306,9 @@ class Declaration extends Locatable, @declaration {
|
||||
* See the comment above `Declaration` for an explanation of the relationship
|
||||
* between `Declaration` and `DeclarationEntry`.
|
||||
*/
|
||||
abstract class DeclarationEntry extends Locatable {
|
||||
class DeclarationEntry extends Locatable, TDeclarationEntry {
|
||||
/** Gets a specifier associated with this declaration entry. */
|
||||
abstract string getASpecifier();
|
||||
string getASpecifier() { none() } // overridden in subclasses
|
||||
|
||||
/**
|
||||
* Gets the name associated with the corresponding definition (where
|
||||
@@ -329,10 +331,10 @@ abstract class DeclarationEntry extends Locatable {
|
||||
* `I.getADeclarationEntry()` returns `D`
|
||||
* but `D.getDeclaration()` only returns `C`
|
||||
*/
|
||||
abstract Declaration getDeclaration();
|
||||
Declaration getDeclaration() { none() } // overridden in subclasses
|
||||
|
||||
/** Gets the name associated with this declaration entry, if any. */
|
||||
abstract string getName();
|
||||
string getName() { none() } // overridden in subclasses
|
||||
|
||||
/**
|
||||
* Gets the type associated with this declaration entry.
|
||||
@@ -341,7 +343,7 @@ abstract class DeclarationEntry extends Locatable {
|
||||
* For function declarations, get the return type of the function.
|
||||
* For type declarations, get the type being declared.
|
||||
*/
|
||||
abstract Type getType();
|
||||
Type getType() { none() } // overridden in subclasses
|
||||
|
||||
/**
|
||||
* Gets the type associated with this declaration entry after specifiers
|
||||
@@ -359,7 +361,7 @@ abstract class DeclarationEntry extends Locatable {
|
||||
predicate hasSpecifier(string specifier) { getASpecifier() = specifier }
|
||||
|
||||
/** Holds if this declaration entry is a definition. */
|
||||
abstract predicate isDefinition();
|
||||
predicate isDefinition() { none() } // overridden in subclasses
|
||||
|
||||
override string toString() {
|
||||
if isDefinition()
|
||||
@@ -371,6 +373,8 @@ abstract class DeclarationEntry extends Locatable {
|
||||
}
|
||||
}
|
||||
|
||||
private class TAccessHolder = @function or @usertype;
|
||||
|
||||
/**
|
||||
* A declaration that can potentially have more C++ access rights than its
|
||||
* enclosing element. This comprises `Class` (they have access to their own
|
||||
@@ -392,7 +396,7 @@ abstract class DeclarationEntry extends Locatable {
|
||||
* the informal phrase "_R_ occurs in a member or friend of class C", where
|
||||
* `AccessHolder` corresponds to this _R_.
|
||||
*/
|
||||
abstract class AccessHolder extends Declaration {
|
||||
class AccessHolder extends Declaration, TAccessHolder {
|
||||
/**
|
||||
* Holds if `this` can access private members of class `c`.
|
||||
*
|
||||
@@ -410,7 +414,7 @@ abstract class AccessHolder extends Declaration {
|
||||
/**
|
||||
* Gets the nearest enclosing `AccessHolder`.
|
||||
*/
|
||||
abstract AccessHolder getEnclosingAccessHolder();
|
||||
AccessHolder getEnclosingAccessHolder() { none() } // overridden in subclasses
|
||||
|
||||
/**
|
||||
* Holds if a base class `base` of `derived` _is accessible at_ `this` (N4140
|
||||
|
||||
@@ -55,12 +55,21 @@ class ElementBase extends @element {
|
||||
cached
|
||||
string toString() { none() }
|
||||
|
||||
/** DEPRECATED: use `getAPrimaryQlClass` instead. */
|
||||
deprecated string getCanonicalQLClass() { result = this.getAPrimaryQlClass() }
|
||||
|
||||
/**
|
||||
* Canonical QL class corresponding to this element.
|
||||
* Gets the name of a primary CodeQL class to which this element belongs.
|
||||
*
|
||||
* ElementBase is the root class for this predicate.
|
||||
* For most elements, this is simply the most precise syntactic category to
|
||||
* which they belong; for example, `AddExpr` is a primary class, but
|
||||
* `BinaryOperation` is not.
|
||||
*
|
||||
* This predicate always has a result. If no primary class can be
|
||||
* determined, the result is `"???"`. If multiple primary classes match,
|
||||
* this predicate can have multiple results.
|
||||
*/
|
||||
string getCanonicalQLClass() { result = "???" }
|
||||
string getAPrimaryQlClass() { result = "???" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,7 +38,7 @@ class Enum extends UserType, IntegralOrEnumType {
|
||||
enumconstants(unresolveElement(result), underlyingElement(this), index, _, _, _)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Enum" }
|
||||
override string getAPrimaryQlClass() { result = "Enum" }
|
||||
|
||||
/**
|
||||
* Gets a descriptive string for the enum. This method is only intended to
|
||||
@@ -87,7 +87,7 @@ class Enum extends UserType, IntegralOrEnumType {
|
||||
class LocalEnum extends Enum {
|
||||
LocalEnum() { isLocal() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "LocalEnum" }
|
||||
override string getAPrimaryQlClass() { result = "LocalEnum" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,7 +105,7 @@ class LocalEnum extends Enum {
|
||||
class NestedEnum extends Enum {
|
||||
NestedEnum() { this.isMember() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "NestedEnum" }
|
||||
override string getAPrimaryQlClass() { result = "NestedEnum" }
|
||||
|
||||
/** Holds if this member is private. */
|
||||
predicate isPrivate() { this.hasSpecifier("private") }
|
||||
@@ -130,7 +130,7 @@ class NestedEnum extends Enum {
|
||||
class ScopedEnum extends Enum {
|
||||
ScopedEnum() { usertypes(underlyingElement(this), _, 13) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ScopedEnum" }
|
||||
override string getAPrimaryQlClass() { result = "ScopedEnum" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,7 +153,7 @@ class EnumConstant extends Declaration, @enumconstant {
|
||||
enumconstants(underlyingElement(this), unresolveElement(result), _, _, _, _)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "EnumConstant" }
|
||||
override string getAPrimaryQlClass() { result = "EnumConstant" }
|
||||
|
||||
override Class getDeclaringType() { result = this.getDeclaringEnum().getDeclaringType() }
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import semmle.code.cpp.exprs.Access
|
||||
class Field extends MemberVariable {
|
||||
Field() { fieldoffsets(underlyingElement(this), _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "Field" }
|
||||
override string getAPrimaryQlClass() { result = "Field" }
|
||||
|
||||
/**
|
||||
* Gets the offset of this field in bytes from the start of its declaring
|
||||
@@ -90,7 +90,7 @@ class Field extends MemberVariable {
|
||||
class BitField extends Field {
|
||||
BitField() { bitfield(underlyingElement(this), _, _) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BitField" }
|
||||
override string getAPrimaryQlClass() { result = "BitField" }
|
||||
|
||||
/**
|
||||
* Gets the size of this bitfield in bits (on the machine where facts
|
||||
|
||||
@@ -178,7 +178,7 @@ class Folder extends Container, @folder {
|
||||
result.hasLocationInfo(_, 0, 0, 0, 0)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Folder" }
|
||||
override string getAPrimaryQlClass() { result = "Folder" }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getLocation` instead.
|
||||
@@ -246,7 +246,7 @@ class File extends Container, @file {
|
||||
|
||||
override string toString() { result = Container.super.toString() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "File" }
|
||||
override string getAPrimaryQlClass() { result = "File" }
|
||||
|
||||
override Location getLocation() {
|
||||
result.getContainer() = this and
|
||||
@@ -382,7 +382,7 @@ class HeaderFile extends File {
|
||||
exists(Include i | i.getIncludedFile() = this)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "HeaderFile" }
|
||||
override string getAPrimaryQlClass() { result = "HeaderFile" }
|
||||
|
||||
/**
|
||||
* Holds if this header file does not contain any declaration entries or top level
|
||||
@@ -408,7 +408,7 @@ class HeaderFile extends File {
|
||||
class CFile extends File {
|
||||
CFile() { exists(string ext | ext = this.getExtension().toLowerCase() | ext = "c" or ext = "i") }
|
||||
|
||||
override string getCanonicalQLClass() { result = "CFile" }
|
||||
override string getAPrimaryQlClass() { result = "CFile" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -436,7 +436,7 @@ class CppFile extends File {
|
||||
)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "CppFile" }
|
||||
override string getAPrimaryQlClass() { result = "CppFile" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,7 +27,7 @@ class FriendDecl extends Declaration, @frienddecl {
|
||||
*/
|
||||
override Location getADeclarationLocation() { result = this.getLocation() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "FriendDecl" }
|
||||
override string getAPrimaryQlClass() { result = "FriendDecl" }
|
||||
|
||||
/**
|
||||
* Implements the abstract method `Declaration.getDefinitionLocation`. A
|
||||
|
||||
@@ -513,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), _, _, _) }
|
||||
@@ -698,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -707,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"
|
||||
}
|
||||
}
|
||||
@@ -738,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.
|
||||
@@ -778,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.
|
||||
@@ -823,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
|
||||
|
||||
@@ -22,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 }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
@@ -70,6 +70,14 @@ class MemberFunction extends Function {
|
||||
result = getADeclarationEntry() and result != getDefinition()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the `this` parameter associated with this member function, if any. The type
|
||||
* may have `const` and/or `volatile` qualifiers, matching the function declaration.
|
||||
*/
|
||||
PointerType getTypeOfThis() {
|
||||
member_function_this_type(underlyingElement(this), unresolveElement(result))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,7 +101,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 +133,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 +155,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 +173,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.
|
||||
@@ -224,7 +232,7 @@ class ConversionConstructor extends Constructor, ImplicitConversionFunction {
|
||||
not this instanceof CopyConstructor
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not this instanceof MoveConstructor and result = "ConversionConstructor"
|
||||
}
|
||||
|
||||
@@ -282,7 +290,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
|
||||
@@ -339,7 +347,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
|
||||
@@ -390,7 +398,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
|
||||
@@ -421,7 +429,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() }
|
||||
|
||||
@@ -457,7 +465,7 @@ class CopyAssignmentOperator extends Operator {
|
||||
not exists(getATemplateArgument())
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "CopyAssignmentOperator" }
|
||||
override string getAPrimaryQlClass() { result = "CopyAssignmentOperator" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -483,5 +491,5 @@ class MoveAssignmentOperator extends Operator {
|
||||
not exists(getATemplateArgument())
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "MoveAssignmentOperator" }
|
||||
override string getAPrimaryQlClass() { result = "MoveAssignmentOperator" }
|
||||
}
|
||||
|
||||
@@ -131,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -49,7 +49,7 @@ class Parameter extends LocalScopeVariable, @parameter {
|
||||
result = "p#" + this.getIndex().toString()
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Parameter" }
|
||||
override string getAPrimaryQlClass() { result = "Parameter" }
|
||||
|
||||
/**
|
||||
* Gets the name of this parameter, including it's type.
|
||||
|
||||
@@ -152,7 +152,7 @@ class PreprocessorIf extends PreprocessorBranch, @ppd_if {
|
||||
class PreprocessorIfdef extends PreprocessorBranch, @ppd_ifdef {
|
||||
override string toString() { result = "#ifdef " + this.getHead() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "PreprocessorIfdef" }
|
||||
override string getAPrimaryQlClass() { result = "PreprocessorIfdef" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
/**
|
||||
* Provides queries to pretty-print a C++ AST as a graph.
|
||||
*
|
||||
* By default, this will print the AST for all functions in the database. To change this behavior,
|
||||
* extend `PrintASTConfiguration` and override `shouldPrintFunction` to hold for only the functions
|
||||
* you wish to view the AST for.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
private import semmle.code.cpp.Print
|
||||
|
||||
@@ -7,6 +15,9 @@ private newtype TPrintASTConfiguration = MkPrintASTConfiguration()
|
||||
* The query can extend this class to control which functions are printed.
|
||||
*/
|
||||
class PrintASTConfiguration extends TPrintASTConfiguration {
|
||||
/**
|
||||
* Gets a textual representation of this `PrintASTConfiguration`.
|
||||
*/
|
||||
string toString() { result = "PrintASTConfiguration" }
|
||||
|
||||
/**
|
||||
@@ -96,6 +107,9 @@ private newtype TPrintASTNode =
|
||||
* A node in the output tree.
|
||||
*/
|
||||
class PrintASTNode extends TPrintASTNode {
|
||||
/**
|
||||
* Gets a textual representation of this node in the PrintAST output tree.
|
||||
*/
|
||||
abstract string toString();
|
||||
|
||||
/**
|
||||
@@ -155,7 +169,7 @@ class PrintASTNode extends TPrintASTNode {
|
||||
* Retrieves the canonical QL class(es) for entity `el`
|
||||
*/
|
||||
private string qlClass(ElementBase el) {
|
||||
result = "[" + concat(el.getCanonicalQLClass(), ",") + "] "
|
||||
result = "[" + concat(el.getAPrimaryQlClass(), ",") + "] "
|
||||
// Alternative implementation -- do not delete. It is useful for QL class discovery.
|
||||
//result = "["+ concat(el.getAQlClass(), ",") + "] "
|
||||
}
|
||||
@@ -208,6 +222,9 @@ class ExprNode extends ASTNode {
|
||||
result = expr.getValueCategoryString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of this expression, if it is a constant.
|
||||
*/
|
||||
string getValue() { result = expr.getValue() }
|
||||
}
|
||||
|
||||
@@ -373,6 +390,9 @@ class ParametersNode extends PrintASTNode, TParametersNode {
|
||||
|
||||
override ASTNode getChild(int childIndex) { result.getAST() = func.getParameter(childIndex) }
|
||||
|
||||
/**
|
||||
* Gets the `Function` for which this node represents the parameters.
|
||||
*/
|
||||
final Function getFunction() { result = func }
|
||||
}
|
||||
|
||||
@@ -392,6 +412,9 @@ class ConstructorInitializersNode extends PrintASTNode, TConstructorInitializers
|
||||
result.getAST() = ctor.getInitializer(childIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `Constructor` for which this node represents the initializer list.
|
||||
*/
|
||||
final Constructor getConstructor() { result = ctor }
|
||||
}
|
||||
|
||||
@@ -411,6 +434,9 @@ class DestructorDestructionsNode extends PrintASTNode, TDestructorDestructionsNo
|
||||
result.getAST() = dtor.getDestruction(childIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `Destructor` for which this node represents the destruction list.
|
||||
*/
|
||||
final Destructor getDestructor() { result = dtor }
|
||||
}
|
||||
|
||||
@@ -464,6 +490,9 @@ class FunctionNode extends ASTNode {
|
||||
key = "semmle.order" and result = getOrder().toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `Function` this node represents.
|
||||
*/
|
||||
final Function getFunction() { result = func }
|
||||
}
|
||||
|
||||
@@ -499,11 +528,16 @@ class ArrayAggregateLiteralNode extends ExprNode {
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if `node` belongs to the output tree, and its property `key` has the given `value`. */
|
||||
query predicate nodes(PrintASTNode node, string key, string value) {
|
||||
node.shouldPrint() and
|
||||
value = node.getProperty(key)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `target` is a child of `source` in the AST, and property `key` of the edge has the
|
||||
* given `value`.
|
||||
*/
|
||||
query predicate edges(PrintASTNode source, PrintASTNode target, string key, string value) {
|
||||
exists(int childIndex |
|
||||
source.shouldPrint() and
|
||||
@@ -517,6 +551,7 @@ query predicate edges(PrintASTNode source, PrintASTNode target, string key, stri
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if property `key` of the graph has the given `value`. */
|
||||
query predicate graphProperties(string key, string value) {
|
||||
key = "semmle.graphKind" and value = "tree"
|
||||
}
|
||||
|
||||
@@ -16,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) }
|
||||
@@ -37,7 +37,7 @@ class FunctionSpecifier extends Specifier {
|
||||
this.hasName("explicit")
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "FunctionSpecifier)" }
|
||||
override string getAPrimaryQlClass() { result = "FunctionSpecifier)" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,7 +53,7 @@ class StorageClassSpecifier extends Specifier {
|
||||
this.hasName("mutable")
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "StorageClassSpecifier" }
|
||||
override string getAPrimaryQlClass() { result = "StorageClassSpecifier" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,7 +108,7 @@ class AccessSpecifier extends Specifier {
|
||||
)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "AccessSpecifier" }
|
||||
override string getAPrimaryQlClass() { result = "AccessSpecifier" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -238,7 +238,7 @@ class FormatAttribute extends GnuAttribute {
|
||||
)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "FormatAttribute" }
|
||||
override string getAPrimaryQlClass() { result = "FormatAttribute" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,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() }
|
||||
|
||||
@@ -43,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,7 +60,7 @@ class LocalStruct extends Struct {
|
||||
class NestedStruct extends Struct {
|
||||
NestedStruct() { this.isMember() }
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not this instanceof NestedUnion and result = "NestedStruct"
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Provides classes for identifying files that contain test cases. It is often
|
||||
* desirable to exclude these files from analysis.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.File
|
||||
|
||||
/**
|
||||
|
||||
@@ -325,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -345,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) {
|
||||
@@ -364,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) {
|
||||
@@ -564,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -589,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -602,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -615,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -632,7 +632,7 @@ class ShortType extends IntegralType {
|
||||
builtintypes(underlyingElement(this), _, 10, _, _, _)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "ShortType" }
|
||||
override string getAPrimaryQlClass() { result = "ShortType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -649,7 +649,7 @@ class IntType extends IntegralType {
|
||||
builtintypes(underlyingElement(this), _, 13, _, _, _)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "IntType" }
|
||||
override string getAPrimaryQlClass() { result = "IntType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -666,7 +666,7 @@ class LongType extends IntegralType {
|
||||
builtintypes(underlyingElement(this), _, 16, _, _, _)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "LongType" }
|
||||
override string getAPrimaryQlClass() { result = "LongType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -683,7 +683,7 @@ class LongLongType extends IntegralType {
|
||||
builtintypes(underlyingElement(this), _, 19, _, _, _)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "LongLongType" }
|
||||
override string getAPrimaryQlClass() { result = "LongLongType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -701,7 +701,7 @@ class Int128Type extends IntegralType {
|
||||
builtintypes(underlyingElement(this), _, 37, _, _, _)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Int128Type" }
|
||||
override string getAPrimaryQlClass() { result = "Int128Type" }
|
||||
}
|
||||
|
||||
private newtype TTypeDomain =
|
||||
@@ -897,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -909,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -921,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -933,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -945,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -957,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -969,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -981,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -997,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1009,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1021,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1033,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1048,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1136,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.
|
||||
@@ -1209,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()
|
||||
@@ -1235,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() }
|
||||
|
||||
@@ -1262,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1278,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() }
|
||||
}
|
||||
@@ -1293,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() }
|
||||
|
||||
@@ -1341,7 +1341,7 @@ 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
|
||||
@@ -1412,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.
|
||||
@@ -1443,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 }
|
||||
|
||||
@@ -1461,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() }
|
||||
|
||||
@@ -1550,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 = "..:: *" }
|
||||
@@ -1595,7 +1595,7 @@ 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 = "..()(..)" }
|
||||
|
||||
@@ -1672,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() }
|
||||
}
|
||||
@@ -1690,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1702,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
|
||||
@@ -1738,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.
|
||||
|
||||
@@ -59,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() + "\""
|
||||
@@ -75,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() + "\""
|
||||
@@ -92,7 +92,7 @@ class UsingAliasTypedefType extends TypedefType {
|
||||
class LocalTypedefType extends TypedefType {
|
||||
LocalTypedefType() { isLocal() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "LocalTypedefType" }
|
||||
override string getAPrimaryQlClass() { result = "LocalTypedefType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,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.
|
||||
|
||||
@@ -17,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() }
|
||||
|
||||
@@ -39,7 +39,7 @@ class Union extends Struct {
|
||||
class LocalUnion extends Union {
|
||||
LocalUnion() { isLocal() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "LocalUnion" }
|
||||
override string getAPrimaryQlClass() { result = "LocalUnion" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,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") }
|
||||
|
||||
@@ -24,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
|
||||
@@ -111,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.
|
||||
|
||||
@@ -32,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 }
|
||||
@@ -190,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.
|
||||
@@ -249,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
|
||||
@@ -325,7 +325,7 @@ class ParameterDeclarationEntry extends VariableDeclarationEntry {
|
||||
*/
|
||||
class LocalScopeVariable extends Variable, @localscopevariable {
|
||||
/** Gets the function to which this variable belongs. */
|
||||
/*abstract*/ Function getFunction() { none() }
|
||||
Function getFunction() { none() } // overridden in subclasses
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -363,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) }
|
||||
|
||||
@@ -464,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -485,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -505,7 +505,7 @@ class GlobalVariable extends GlobalOrNamespaceVariable {
|
||||
class MemberVariable extends Variable, @membervariable {
|
||||
MemberVariable() { this.isMember() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "MemberVariable" }
|
||||
override string getAPrimaryQlClass() { result = "MemberVariable" }
|
||||
|
||||
/** Holds if this member is private. */
|
||||
predicate isPrivate() { this.hasSpecifier("private") }
|
||||
|
||||
@@ -6,7 +6,7 @@ import semmle.code.cpp.Type
|
||||
class CharPointerType extends PointerType {
|
||||
CharPointerType() { this.getBaseType() instanceof CharType }
|
||||
|
||||
override string getCanonicalQLClass() { result = "CharPointerType" }
|
||||
override string getAPrimaryQlClass() { result = "CharPointerType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -15,7 +15,7 @@ class CharPointerType extends PointerType {
|
||||
class IntPointerType extends PointerType {
|
||||
IntPointerType() { this.getBaseType() instanceof IntType }
|
||||
|
||||
override string getCanonicalQLClass() { result = "IntPointerType" }
|
||||
override string getAPrimaryQlClass() { result = "IntPointerType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -24,7 +24,7 @@ class IntPointerType extends PointerType {
|
||||
class VoidPointerType extends PointerType {
|
||||
VoidPointerType() { this.getBaseType() instanceof VoidType }
|
||||
|
||||
override string getCanonicalQLClass() { result = "VoidPointerType" }
|
||||
override string getAPrimaryQlClass() { result = "VoidPointerType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,7 +36,7 @@ class Size_t extends Type {
|
||||
this.hasName("size_t")
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Size_t" }
|
||||
override string getAPrimaryQlClass() { result = "Size_t" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,7 +48,7 @@ class Ssize_t extends Type {
|
||||
this.hasName("ssize_t")
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Ssize_t" }
|
||||
override string getAPrimaryQlClass() { result = "Ssize_t" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,7 +60,7 @@ class Ptrdiff_t extends Type {
|
||||
this.hasName("ptrdiff_t")
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Ptrdiff_t" }
|
||||
override string getAPrimaryQlClass() { result = "Ptrdiff_t" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,7 +72,7 @@ class Intmax_t extends Type {
|
||||
this.hasName("intmax_t")
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Intmax_t" }
|
||||
override string getAPrimaryQlClass() { result = "Intmax_t" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,7 +84,7 @@ class Uintmax_t extends Type {
|
||||
this.hasName("uintmax_t")
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Uintmax_t" }
|
||||
override string getAPrimaryQlClass() { result = "Uintmax_t" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,7 +100,7 @@ class Wchar_t extends Type {
|
||||
this.hasName("wchar_t")
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "Wchar_t" }
|
||||
override string getAPrimaryQlClass() { result = "Wchar_t" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,5 +176,5 @@ class MicrosoftInt64Type extends IntegralType {
|
||||
class BuiltInVarArgsList extends Type {
|
||||
BuiltInVarArgsList() { this.hasName("__builtin_va_list") }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInVarArgsList" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInVarArgsList" }
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides a class for calculating the possible length of string expressions.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.exprs.Expr
|
||||
import semmle.code.cpp.controlflow.SSA
|
||||
|
||||
|
||||
@@ -23,8 +23,7 @@ abstract class MutexType extends Type {
|
||||
abstract predicate trylockAccess(FunctionCall fc, Expr arg);
|
||||
|
||||
/**
|
||||
* Holds if `fc` is a call that unlocks mutex `arg`
|
||||
* of this type.
|
||||
* Holds if `fc` is a call that unlocks mutex `arg` of this type.
|
||||
*/
|
||||
abstract predicate unlockAccess(FunctionCall fc, Expr arg);
|
||||
|
||||
@@ -38,8 +37,7 @@ abstract class MutexType extends Type {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `fc` is a call that locks or tries to lock any
|
||||
* mutex of this type.
|
||||
* Gets a call that locks or tries to lock any mutex of this type.
|
||||
*/
|
||||
FunctionCall getLockAccess() {
|
||||
result = getMustlockAccess() or
|
||||
@@ -47,44 +45,44 @@ abstract class MutexType extends Type {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `fc` is a call that always locks any mutex of this type.
|
||||
* Gets a call that always locks any mutex of this type.
|
||||
*/
|
||||
FunctionCall getMustlockAccess() { this.mustlockAccess(result, _) }
|
||||
|
||||
/**
|
||||
* Holds if `fc` is a call that tries to lock any mutex of this type,
|
||||
* Gets a call that tries to lock any mutex of this type,
|
||||
* by may return without success.
|
||||
*/
|
||||
FunctionCall getTrylockAccess() { this.trylockAccess(result, _) }
|
||||
|
||||
/**
|
||||
* Holds if `fc` is a call that unlocks any mutex of this type.
|
||||
* Gets a call that unlocks any mutex of this type.
|
||||
*/
|
||||
FunctionCall getUnlockAccess() { this.unlockAccess(result, _) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use mustlockAccess(fc, arg) instead
|
||||
* DEPRECATED: use mustlockAccess(fc, arg) instead.
|
||||
*/
|
||||
deprecated Function getMustlockFunction() { result = getMustlockAccess().getTarget() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use trylockAccess(fc, arg) instead
|
||||
* DEPRECATED: use trylockAccess(fc, arg) instead.
|
||||
*/
|
||||
deprecated Function getTrylockFunction() { result = getTrylockAccess().getTarget() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use lockAccess(fc, arg) instead
|
||||
* DEPRECATED: use lockAccess(fc, arg) instead.
|
||||
*/
|
||||
deprecated Function getLockFunction() { result = getLockAccess().getTarget() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use unlockAccess(fc, arg) instead
|
||||
* DEPRECATED: use unlockAccess(fc, arg) instead.
|
||||
*/
|
||||
deprecated Function getUnlockFunction() { result = getUnlockAccess().getTarget() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A function that looks like a lock function.
|
||||
* Gets a function that looks like a lock function.
|
||||
*/
|
||||
private Function mustlockCandidate() {
|
||||
exists(string name | name = result.getName() |
|
||||
@@ -94,7 +92,7 @@ private Function mustlockCandidate() {
|
||||
}
|
||||
|
||||
/**
|
||||
* A function that looks like a try-lock function.
|
||||
* Gets a function that looks like a try-lock function.
|
||||
*/
|
||||
private Function trylockCandidate() {
|
||||
exists(string name | name = result.getName() |
|
||||
@@ -104,7 +102,7 @@ private Function trylockCandidate() {
|
||||
}
|
||||
|
||||
/**
|
||||
* A function that looks like an unlock function.
|
||||
* Gets a function that looks like an unlock function.
|
||||
*/
|
||||
private Function unlockCandidate() {
|
||||
exists(string name | name = result.getName() |
|
||||
@@ -171,7 +169,10 @@ class DefaultMutexType extends MutexType {
|
||||
}
|
||||
}
|
||||
|
||||
/** Get the mutex argument of a call to lock or unlock. */
|
||||
/**
|
||||
* Holds if `arg` is the mutex argument of a call to lock or unlock and
|
||||
* `argType` is the type of the mutex.
|
||||
*/
|
||||
private predicate lockArg(Expr arg, MutexType argType, FunctionCall call) {
|
||||
argType = arg.getUnderlyingType().stripType() and
|
||||
(
|
||||
@@ -184,18 +185,31 @@ private predicate lockArg(Expr arg, MutexType argType, FunctionCall call) {
|
||||
// `MutexType.mustlockAccess`.
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `call` is a call that locks or tries to lock its argument `arg`.
|
||||
*/
|
||||
predicate lockCall(Expr arg, FunctionCall call) {
|
||||
exists(MutexType t | lockArg(arg, t, call) and call = t.getLockAccess())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `call` is a call that always locks its argument `arg`.
|
||||
*/
|
||||
predicate mustlockCall(Expr arg, FunctionCall call) {
|
||||
exists(MutexType t | lockArg(arg, t, call) and call = t.getMustlockAccess())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `call` is a call that tries to lock its argument `arg`, but may
|
||||
* return without success.
|
||||
*/
|
||||
predicate trylockCall(Expr arg, FunctionCall call) {
|
||||
exists(MutexType t | lockArg(arg, t, call) and call = t.getTrylockAccess())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `call` is a call that unlocks its argument `arg`.
|
||||
*/
|
||||
predicate unlockCall(Expr arg, FunctionCall call) {
|
||||
exists(MutexType t | lockArg(arg, t, call) and call = t.getUnlockAccess())
|
||||
}
|
||||
|
||||
@@ -53,26 +53,13 @@ private predicate functionSignature(Function f, string qualifiedName, int nparam
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the call context `ctx` reduces the set of viable dispatch
|
||||
* targets of `ma` in `c`.
|
||||
* Holds if the set of viable implementations that can be called by `call`
|
||||
* might be improved by knowing the call context.
|
||||
*/
|
||||
predicate reducedViableImplInCallContext(Call call, Function f, Call ctx) { none() }
|
||||
predicate mayBenefitFromCallContext(Call call, Function f) { none() }
|
||||
|
||||
/**
|
||||
* Gets a viable dispatch target of `ma` in the context `ctx`. This is
|
||||
* restricted to those `ma`s for which the context makes a difference.
|
||||
* Gets a viable dispatch target of `call` in the context `ctx`. This is
|
||||
* restricted to those `call`s for which a context might make a difference.
|
||||
*/
|
||||
Function prunedViableImplInCallContext(Call call, Call ctx) { none() }
|
||||
|
||||
/**
|
||||
* Holds if flow returning from `m` to `ma` might return further and if
|
||||
* this path restricts the set of call sites that can be returned to.
|
||||
*/
|
||||
predicate reducedViableImplInReturn(Function f, Call call) { none() }
|
||||
|
||||
/**
|
||||
* Gets a viable dispatch target of `ma` in the context `ctx`. This is
|
||||
* restricted to those `ma`s and results for which the return flow from the
|
||||
* result to `ma` restricts the possible context `ctx`.
|
||||
*/
|
||||
Function prunedViableImplInCallContextReverse(Call call, Call ctx) { none() }
|
||||
Function viableImplInCallContext(Call call, Call ctx) { none() }
|
||||
|
||||
@@ -330,6 +330,67 @@ private module Cached {
|
||||
import Final
|
||||
}
|
||||
|
||||
import FlowThrough
|
||||
|
||||
cached
|
||||
private module DispatchWithCallContext {
|
||||
/**
|
||||
* Holds if the call context `ctx` reduces the set of viable run-time
|
||||
* dispatch targets of call `call` in `c`.
|
||||
*/
|
||||
cached
|
||||
predicate reducedViableImplInCallContext(DataFlowCall call, DataFlowCallable c, DataFlowCall ctx) {
|
||||
exists(int tgts, int ctxtgts |
|
||||
mayBenefitFromCallContext(call, c) and
|
||||
c = viableCallable(ctx) and
|
||||
ctxtgts = count(viableImplInCallContext(call, ctx)) and
|
||||
tgts = strictcount(viableCallable(call)) and
|
||||
ctxtgts < tgts
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a viable run-time dispatch target for the call `call` in the
|
||||
* context `ctx`. This is restricted to those calls for which a context
|
||||
* makes a difference.
|
||||
*/
|
||||
cached
|
||||
DataFlowCallable prunedViableImplInCallContext(DataFlowCall call, DataFlowCall ctx) {
|
||||
result = viableImplInCallContext(call, ctx) and
|
||||
reducedViableImplInCallContext(call, _, ctx)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if flow returning from callable `c` to call `call` might return
|
||||
* further and if this path restricts the set of call sites that can be
|
||||
* returned to.
|
||||
*/
|
||||
cached
|
||||
predicate reducedViableImplInReturn(DataFlowCallable c, DataFlowCall call) {
|
||||
exists(int tgts, int ctxtgts |
|
||||
mayBenefitFromCallContext(call, _) and
|
||||
c = viableCallable(call) and
|
||||
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContext(call, ctx)) and
|
||||
tgts = strictcount(DataFlowCall ctx | viableCallable(ctx) = call.getEnclosingCallable()) and
|
||||
ctxtgts < tgts
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a viable run-time dispatch target for the call `call` in the
|
||||
* context `ctx`. This is restricted to those calls and results for which
|
||||
* the return flow from the result to `call` restricts the possible context
|
||||
* `ctx`.
|
||||
*/
|
||||
cached
|
||||
DataFlowCallable prunedViableImplInCallContextReverse(DataFlowCall call, DataFlowCall ctx) {
|
||||
result = viableImplInCallContext(call, ctx) and
|
||||
reducedViableImplInReturn(result, call)
|
||||
}
|
||||
}
|
||||
|
||||
import DispatchWithCallContext
|
||||
|
||||
/**
|
||||
* Holds if `p` can flow to the pre-update node associated with post-update
|
||||
* node `n`, in the same callable, using only value-preserving steps.
|
||||
@@ -371,8 +432,6 @@ private module Cached {
|
||||
store(node1, tc.getContent(), node2, contentType, tc.getContainerType())
|
||||
}
|
||||
|
||||
import FlowThrough
|
||||
|
||||
/**
|
||||
* Holds if the call context `call` either improves virtual dispatch in
|
||||
* `callable` or if it allows us to prune unreachable nodes in `callable`.
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Provides classes for modeling accesses including variable accesses, enum
|
||||
* constant accesses and function accesses.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.exprs.Expr
|
||||
import semmle.code.cpp.Variable
|
||||
import semmle.code.cpp.Enum
|
||||
@@ -36,7 +41,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 +66,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 +171,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 +199,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 +216,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 +237,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 +258,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 +312,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 +337,7 @@ class PointerToFieldLiteral extends ImplicitThisFieldAccess {
|
||||
|
||||
override predicate isConstant() { any() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "PointerToFieldLiteral" }
|
||||
override string getAPrimaryQlClass() { result = "PointerToFieldLiteral" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -349,7 +354,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 +404,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 +423,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.
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Provides classes for modeling arithmetic operations such as `+`, `-`, `*`
|
||||
* and `++`.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.exprs.Expr
|
||||
|
||||
/**
|
||||
@@ -14,7 +19,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 +33,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 +50,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 +112,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 +128,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 +144,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 +162,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 +180,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 +194,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 +213,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 +227,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 +241,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 +255,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 +269,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 +286,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 +303,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 +321,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 +339,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 +357,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 +375,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 +389,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 +401,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 +419,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 +434,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 +449,7 @@ class PointerSubExpr extends PointerArithmeticOperation, @psubexpr {
|
||||
class PointerDiffExpr extends PointerArithmeticOperation, @pdiffexpr {
|
||||
override string getOperator() { result = "-" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "PointerDiffExpr" }
|
||||
override string getAPrimaryQlClass() { result = "PointerDiffExpr" }
|
||||
|
||||
override int getPrecedence() { result = 13 }
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ class Assignment extends Operation, @assign_expr {
|
||||
class AssignExpr extends Assignment, @assignexpr {
|
||||
override string getOperator() { result = "=" }
|
||||
|
||||
override string getCanonicalQLClass() { result = "AssignExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignExpr" }
|
||||
|
||||
/** Gets a textual representation of this assignment. */
|
||||
override string toString() { result = "... = ..." }
|
||||
@@ -64,7 +64,7 @@ class AssignArithmeticOperation extends AssignOperation, @assign_arith_expr { }
|
||||
* ```
|
||||
*/
|
||||
class AssignAddExpr extends AssignArithmeticOperation, @assignaddexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignAddExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignAddExpr" }
|
||||
|
||||
override string getOperator() { result = "+=" }
|
||||
}
|
||||
@@ -76,7 +76,7 @@ class AssignAddExpr extends AssignArithmeticOperation, @assignaddexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignSubExpr extends AssignArithmeticOperation, @assignsubexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignSubExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignSubExpr" }
|
||||
|
||||
override string getOperator() { result = "-=" }
|
||||
}
|
||||
@@ -88,7 +88,7 @@ class AssignSubExpr extends AssignArithmeticOperation, @assignsubexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignMulExpr extends AssignArithmeticOperation, @assignmulexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignMulExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignMulExpr" }
|
||||
|
||||
override string getOperator() { result = "*=" }
|
||||
}
|
||||
@@ -100,7 +100,7 @@ class AssignMulExpr extends AssignArithmeticOperation, @assignmulexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignDivExpr extends AssignArithmeticOperation, @assigndivexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignDivExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignDivExpr" }
|
||||
|
||||
override string getOperator() { result = "/=" }
|
||||
}
|
||||
@@ -112,7 +112,7 @@ class AssignDivExpr extends AssignArithmeticOperation, @assigndivexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignRemExpr extends AssignArithmeticOperation, @assignremexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignRemExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignRemExpr" }
|
||||
|
||||
override string getOperator() { result = "%=" }
|
||||
}
|
||||
@@ -130,7 +130,7 @@ class AssignBitwiseOperation extends AssignOperation, @assign_bitwise_expr { }
|
||||
* ```
|
||||
*/
|
||||
class AssignAndExpr extends AssignBitwiseOperation, @assignandexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignAndExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignAndExpr" }
|
||||
|
||||
override string getOperator() { result = "&=" }
|
||||
}
|
||||
@@ -142,7 +142,7 @@ class AssignAndExpr extends AssignBitwiseOperation, @assignandexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignOrExpr extends AssignBitwiseOperation, @assignorexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignOrExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignOrExpr" }
|
||||
|
||||
override string getOperator() { result = "|=" }
|
||||
}
|
||||
@@ -154,7 +154,7 @@ class AssignOrExpr extends AssignBitwiseOperation, @assignorexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignXorExpr extends AssignBitwiseOperation, @assignxorexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignXorExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignXorExpr" }
|
||||
|
||||
override string getOperator() { result = "^=" }
|
||||
}
|
||||
@@ -166,7 +166,7 @@ class AssignXorExpr extends AssignBitwiseOperation, @assignxorexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignLShiftExpr extends AssignBitwiseOperation, @assignlshiftexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignLShiftExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignLShiftExpr" }
|
||||
|
||||
override string getOperator() { result = "<<=" }
|
||||
}
|
||||
@@ -178,7 +178,7 @@ class AssignLShiftExpr extends AssignBitwiseOperation, @assignlshiftexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignRShiftExpr extends AssignBitwiseOperation, @assignrshiftexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignRShiftExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignRShiftExpr" }
|
||||
|
||||
override string getOperator() { result = ">>=" }
|
||||
}
|
||||
@@ -190,7 +190,7 @@ class AssignRShiftExpr extends AssignBitwiseOperation, @assignrshiftexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignPointerAddExpr extends AssignOperation, @assignpaddexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignPointerAddExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignPointerAddExpr" }
|
||||
|
||||
override string getOperator() { result = "+=" }
|
||||
}
|
||||
@@ -202,7 +202,7 @@ class AssignPointerAddExpr extends AssignOperation, @assignpaddexpr {
|
||||
* ```
|
||||
*/
|
||||
class AssignPointerSubExpr extends AssignOperation, @assignpsubexpr {
|
||||
override string getCanonicalQLClass() { result = "AssignPointerSubExpr" }
|
||||
override string getAPrimaryQlClass() { result = "AssignPointerSubExpr" }
|
||||
|
||||
override string getOperator() { result = "-=" }
|
||||
}
|
||||
@@ -227,7 +227,7 @@ class ConditionDeclExpr extends Expr, @condition_decl {
|
||||
*/
|
||||
deprecated Expr getExpr() { result = this.getChild(0) }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ConditionDeclExpr" }
|
||||
override string getAPrimaryQlClass() { result = "ConditionDeclExpr" }
|
||||
|
||||
/**
|
||||
* Gets the compiler-generated variable access that conceptually occurs after
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Provides classes for modeling bitwise operations such as `~`, `<<`, `&` and
|
||||
* `|`.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.exprs.Expr
|
||||
|
||||
/**
|
||||
@@ -16,7 +21,7 @@ class ComplementExpr extends UnaryBitwiseOperation, @complementexpr {
|
||||
|
||||
override int getPrecedence() { result = 16 }
|
||||
|
||||
override string getCanonicalQLClass() { result = "ComplementExpr" }
|
||||
override string getAPrimaryQlClass() { result = "ComplementExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,7 +40,7 @@ class LShiftExpr extends BinaryBitwiseOperation, @lshiftexpr {
|
||||
|
||||
override int getPrecedence() { result = 12 }
|
||||
|
||||
override string getCanonicalQLClass() { result = "LShiftExpr" }
|
||||
override string getAPrimaryQlClass() { result = "LShiftExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,7 +54,7 @@ class RShiftExpr extends BinaryBitwiseOperation, @rshiftexpr {
|
||||
|
||||
override int getPrecedence() { result = 12 }
|
||||
|
||||
override string getCanonicalQLClass() { result = "RShiftExpr" }
|
||||
override string getAPrimaryQlClass() { result = "RShiftExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,7 +68,7 @@ class BitwiseAndExpr extends BinaryBitwiseOperation, @andexpr {
|
||||
|
||||
override int getPrecedence() { result = 8 }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BitwiseAndExpr" }
|
||||
override string getAPrimaryQlClass() { result = "BitwiseAndExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,7 +82,7 @@ class BitwiseOrExpr extends BinaryBitwiseOperation, @orexpr {
|
||||
|
||||
override int getPrecedence() { result = 6 }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BitwiseOrExpr" }
|
||||
override string getAPrimaryQlClass() { result = "BitwiseOrExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,5 +96,5 @@ class BitwiseXorExpr extends BinaryBitwiseOperation, @xorexpr {
|
||||
|
||||
override int getPrecedence() { result = 7 }
|
||||
|
||||
override string getCanonicalQLClass() { result = "BitwiseXorExpr" }
|
||||
override string getAPrimaryQlClass() { result = "BitwiseXorExpr" }
|
||||
}
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
/**
|
||||
* Provides classes for modeling built-in operations. Built-in operations are
|
||||
* typically compiler specific and are used by libraries and generated code.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.exprs.Expr
|
||||
|
||||
/**
|
||||
* A C/C++ builtin operation. This is the root QL class encompassing
|
||||
* A C/C++ built-in operation. This is the root QL class encompassing
|
||||
* built-in functionality.
|
||||
*/
|
||||
class BuiltInOperation extends Expr, @builtin_op {
|
||||
override string getCanonicalQLClass() { result = "BuiltInOperation" }
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperation" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -25,7 +30,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 +55,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 +73,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 +93,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 +115,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 +137,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 +154,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 +169,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 +184,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 +200,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 +216,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 +231,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 +247,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 +262,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 +277,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 +292,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 +307,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 +325,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 +340,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 +355,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 +370,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 +385,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 +400,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 +415,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 +432,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 +447,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 +462,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 +501,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 +521,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 +543,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 +565,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 +582,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 +599,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 +615,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 +634,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 +650,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 +670,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 +684,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 +704,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 +722,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 +740,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 +756,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 +775,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 +791,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 +806,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 +820,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 +833,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 +850,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 +867,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 +885,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 +904,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 +921,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 +939,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 +954,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 +971,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 +980,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) }
|
||||
|
||||
@@ -1,13 +1,29 @@
|
||||
/**
|
||||
* Provides classes for modeling call expressions including direct calls to
|
||||
* functions, constructor and destructor calls, and calls made through function
|
||||
* pointers.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.exprs.Expr
|
||||
import semmle.code.cpp.Function
|
||||
private import semmle.code.cpp.dataflow.EscapesTree
|
||||
|
||||
private class TCall = @funbindexpr or @callexpr;
|
||||
|
||||
/**
|
||||
* A C/C++ call.
|
||||
*
|
||||
* This is the abstract root QL class for all types of calls.
|
||||
*/
|
||||
abstract class Call extends Expr, NameQualifiableElement {
|
||||
class Call extends Expr, NameQualifiableElement, TCall {
|
||||
// `@funbindexpr` (which is the dbscheme type for FunctionCall) is a union type that includes
|
||||
// `@routineexpr. This dbscheme type includes accesses to functions that are not necessarily calls to
|
||||
// that function. That's why the charpred for `FunctionCall` requires:
|
||||
// ```
|
||||
// iscall(underlyingElement(this), _)
|
||||
// ```
|
||||
// So for the charpred for `Call` we include the requirement that if this is an instance of
|
||||
// `@funbindexpr` it must be a _call_ to the function.
|
||||
Call() { this instanceof @callexpr or iscall(underlyingElement(this), _) }
|
||||
|
||||
/**
|
||||
* Gets the number of arguments (actual parameters) of this call. The count
|
||||
* does _not_ include the qualifier of the call, if any.
|
||||
@@ -74,7 +90,7 @@ abstract class Call extends Expr, NameQualifiableElement {
|
||||
* method, and it might not exist.
|
||||
* - For a variable call, it never exists.
|
||||
*/
|
||||
abstract Function getTarget();
|
||||
Function getTarget() { none() } // overridden in subclasses
|
||||
|
||||
override int getPrecedence() { result = 17 }
|
||||
|
||||
@@ -148,7 +164,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 +313,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 +361,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 +393,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 +417,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 +435,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 +454,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 +470,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 +485,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 +509,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 +522,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 +530,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 +547,7 @@ class ConstructorBaseInit extends ConstructorInit, ConstructorCall {
|
||||
* ```
|
||||
*/
|
||||
class ConstructorDirectInit extends ConstructorBaseInit, @ctordirectinit {
|
||||
override string getCanonicalQLClass() { result = "ConstructorDirectInit" }
|
||||
override string getAPrimaryQlClass() { result = "ConstructorDirectInit" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -551,7 +567,7 @@ class ConstructorDirectInit extends ConstructorBaseInit, @ctordirectinit {
|
||||
* ```
|
||||
*/
|
||||
class ConstructorVirtualInit extends ConstructorBaseInit, @ctorvirtualinit {
|
||||
override string getCanonicalQLClass() { result = "ConstructorVirtualInit" }
|
||||
override string getAPrimaryQlClass() { result = "ConstructorVirtualInit" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -566,7 +582,7 @@ class ConstructorVirtualInit extends ConstructorBaseInit, @ctorvirtualinit {
|
||||
* ```
|
||||
*/
|
||||
class ConstructorDelegationInit extends ConstructorBaseInit, @ctordelegatinginit {
|
||||
override string getCanonicalQLClass() { result = "ConstructorDelegationInit" }
|
||||
override string getAPrimaryQlClass() { result = "ConstructorDelegationInit" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -585,7 +601,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 +623,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 +631,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 +645,7 @@ class DestructorBaseDestruction extends DestructorCall, DestructorDestruction {
|
||||
* ```
|
||||
*/
|
||||
class DestructorDirectDestruction extends DestructorBaseDestruction, @dtordirectdestruct {
|
||||
override string getCanonicalQLClass() { result = "DestructorDirectDestruction" }
|
||||
override string getAPrimaryQlClass() { result = "DestructorDirectDestruction" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -646,7 +662,7 @@ class DestructorDirectDestruction extends DestructorBaseDestruction, @dtordirect
|
||||
* ```
|
||||
*/
|
||||
class DestructorVirtualDestruction extends DestructorBaseDestruction, @dtorvirtualdestruct {
|
||||
override string getCanonicalQLClass() { result = "DestructorVirtualDestruction" }
|
||||
override string getAPrimaryQlClass() { result = "DestructorVirtualDestruction" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -664,7 +680,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) }
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Provides classes for modeling C/C++ casts and conversions, as well as some
|
||||
* type-related operators such as `sizeof` and `alignof`.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.exprs.Expr
|
||||
private import semmle.code.cpp.internal.ResolveClass
|
||||
|
||||
@@ -92,7 +97,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 +116,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 +134,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 +152,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 +208,7 @@ class IntegralConversion extends ArithmeticConversion {
|
||||
isIntegralOrEnum(getExpr().getUnspecifiedType())
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not exists(qlCast(this)) and result = "IntegralConversion"
|
||||
}
|
||||
|
||||
@@ -223,7 +228,7 @@ class FloatingPointConversion extends ArithmeticConversion {
|
||||
getExpr().getUnspecifiedType() instanceof FloatingPointType
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not exists(qlCast(this)) and result = "FloatingPointConversion"
|
||||
}
|
||||
|
||||
@@ -243,7 +248,7 @@ class FloatingPointToIntegralConversion extends ArithmeticConversion {
|
||||
getExpr().getUnspecifiedType() instanceof FloatingPointType
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not exists(qlCast(this)) and result = "FloatingPointToIntegralConversion"
|
||||
}
|
||||
|
||||
@@ -263,7 +268,7 @@ class IntegralToFloatingPointConversion extends ArithmeticConversion {
|
||||
isIntegralOrEnum(getExpr().getUnspecifiedType())
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not exists(qlCast(this)) and result = "IntegralToFloatingPointConversion"
|
||||
}
|
||||
|
||||
@@ -289,9 +294,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 +328,7 @@ class PointerToMemberConversion extends Cast {
|
||||
)
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not exists(qlCast(this)) and result = "PointerToMemberConversion"
|
||||
}
|
||||
|
||||
@@ -346,7 +349,7 @@ class PointerToIntegralConversion extends Cast {
|
||||
isPointerOrNullPointer(getExpr().getUnspecifiedType())
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not exists(qlCast(this)) and result = "PointerToIntegralConversion"
|
||||
}
|
||||
|
||||
@@ -367,7 +370,7 @@ class IntegralToPointerConversion extends Cast {
|
||||
isIntegralOrEnum(getExpr().getUnspecifiedType())
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() {
|
||||
override string getAPrimaryQlClass() {
|
||||
not exists(qlCast(this)) and result = "IntegralToPointerConversion"
|
||||
}
|
||||
|
||||
@@ -385,7 +388,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 +406,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 +482,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 +509,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 +531,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 +551,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 +572,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 +598,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 +621,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" }
|
||||
}
|
||||
@@ -660,6 +661,9 @@ class UuidofOperator extends Expr, @uuidof {
|
||||
* ```
|
||||
*/
|
||||
class TypeidOperator extends Expr, @type_id {
|
||||
/**
|
||||
* Gets the type that is returned by this typeid expression.
|
||||
*/
|
||||
Type getResultType() { typeid_bind(underlyingElement(this), unresolveElement(result)) }
|
||||
|
||||
/**
|
||||
@@ -669,7 +673,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 +703,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 +726,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 +754,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 +833,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() }
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes for modeling comparisons such as `==`, `!=` and `<`.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.exprs.Expr
|
||||
|
||||
/**
|
||||
@@ -21,7 +25,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 +37,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 +82,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 +98,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 +114,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 +130,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 = "<=" }
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes modeling C/C++ expressions.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Element
|
||||
private import semmle.code.cpp.Enclosing
|
||||
private import semmle.code.cpp.internal.ResolveClass
|
||||
@@ -565,7 +569,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 +584,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 +595,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 +610,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 +625,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 +660,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 +692,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 +706,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 +744,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 +850,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 +880,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 +928,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 +1002,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 +1082,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 +1107,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 +1143,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 +1175,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 +1251,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 }
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes for modeling lambda expressions and their captures.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.exprs.Expr
|
||||
import semmle.code.cpp.Class
|
||||
|
||||
@@ -15,7 +19,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 +79,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 +105,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.
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Provides classes for modeling literals in the source code such as `0`, `'c'`
|
||||
* or `"string"`.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.exprs.Expr
|
||||
|
||||
/**
|
||||
@@ -14,7 +19,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 +40,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 +98,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 +120,7 @@ class StringLiteral extends TextLiteral {
|
||||
// @aggregateliteral rather than @literal.
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "StringLiteral" }
|
||||
override string getAPrimaryQlClass() { result = "StringLiteral" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,7 +133,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 +145,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 +184,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 +304,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 +328,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() }
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Provides classes for modeling logical operations such as `!`, `&&`, `||`, and
|
||||
* the ternary `? :` expression.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.exprs.Expr
|
||||
|
||||
/**
|
||||
@@ -14,7 +19,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 +51,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 +72,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 +94,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() {
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.exprs.Expr
|
||||
import semmle.code.cpp.Class
|
||||
import semmle.code.cpp.ObjectiveC
|
||||
|
||||
@@ -1,3 +1,47 @@
|
||||
/**
|
||||
* Provides classes that describe the Intermediate Representation (IR) of the program.
|
||||
*
|
||||
* The IR is a representation of the semantics of the program, with very little dependence on the
|
||||
* syntax that was used to write the program. For example, in C++, the statements `i += 1;`, `i++`,
|
||||
* and `++i` all have the same semantic effect, but appear in the AST as three different types of
|
||||
* `Expr` node. In the IR, all three statements are broken down into a sequence of fundamental
|
||||
* operations similar to:
|
||||
*
|
||||
* ```
|
||||
* r1(int*) = VariableAddress[i] // Compute the address of variable `i`
|
||||
* r2(int) = Load &:r1, m0 // Load the value of `i`
|
||||
* r3(int) = Constant[1] // An integer constant with the value `1`
|
||||
* r4(int) = Add r2, r3 // Add `1` to the value of `i`
|
||||
* r5(int) = Store &r1, r4 // Store the new value back into the variable `i`
|
||||
* ```
|
||||
*
|
||||
* This allows IR-based analysis to focus on the fundamental operations, rather than having to be
|
||||
* concerned with the various ways of expressing those operations in source code.
|
||||
*
|
||||
* The key classes in the IR are:
|
||||
*
|
||||
* - `IRFunction` - Contains the IR for an entire function definition, including all of that
|
||||
* function's `Instruction`s, `IRBlock`s, and `IRVariables`.
|
||||
* - `Instruction` - A single operation in the IR. An instruction specifies the operation to be
|
||||
* performed, the operands that produce the inputs to that operation, and the type of the result
|
||||
* of the operation. Control flows from an `Instruction` to one of a set of successor
|
||||
* `Instruction`s.
|
||||
* - `Operand` - An input value of an `Instruction`. All inputs of an `Instruction` are explicitly
|
||||
* represented as `Operand`s, even if the input was implicit in the source code. An `Operand` has
|
||||
* a link to the `Instruction` that consumes its value (its "use") and a link to the `Instruction`
|
||||
* that produces its value (its "definition").
|
||||
* - `IRVariable` - A variable accessed by the IR for a particular function. An `IRVariable` is
|
||||
* created for each variable directly accessed by the function. In addition, `IRVariable`s are
|
||||
* created to represent certain temporary storage locations that do not have explicitly declared
|
||||
* variables in the source code, such as the return value of the function.
|
||||
* - `IRBlock` - A "basic block" in the control flow graph of a function. An `IRBlock` contains a
|
||||
* sequence of instructions such that control flow can only enter the block at the first
|
||||
* instruction, and can only leave the block from the last instruction.
|
||||
* - `IRType` - The type of a value accessed in the IR. Unlike the `Type` class in the AST, `IRType`
|
||||
* is language-neutral. For example, in C++, `unsigned int`, `char32_t`, and `wchar_t` might all
|
||||
* be represented as the `IRType` `uint4`, a four-byte unsigned integer.
|
||||
*/
|
||||
|
||||
// Most queries should operate on the aliased SSA IR, so that's what we expose
|
||||
// publically as the "IR".
|
||||
// publicly as the "IR".
|
||||
import implementation.aliased_ssa.IR
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
/**
|
||||
* Module used to configure the IR generation process.
|
||||
*/
|
||||
|
||||
import implementation.IRConfiguration
|
||||
|
||||
@@ -1 +1,11 @@
|
||||
/**
|
||||
* Outputs a representation of the IR as a control flow graph.
|
||||
*
|
||||
* This file contains the actual implementation of `PrintIR.ql`. For test cases and very small
|
||||
* databases, `PrintIR.ql` can be run directly to dump the IR for the entire database. For most
|
||||
* uses, however, it is better to write a query that imports `PrintIR.qll`, extends
|
||||
* `PrintIRConfiguration`, and overrides `shouldPrintFunction()` to select a subset of functions to
|
||||
* dump.
|
||||
*/
|
||||
|
||||
import implementation.aliased_ssa.PrintIR
|
||||
|
||||
@@ -226,28 +226,13 @@ private predicate functionSignature(Function f, string qualifiedName, int nparam
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the call context `ctx` reduces the set of viable dispatch
|
||||
* targets of `ma` in `c`.
|
||||
* Holds if the set of viable implementations that can be called by `call`
|
||||
* might be improved by knowing the call context.
|
||||
*/
|
||||
predicate reducedViableImplInCallContext(CallInstruction call, Function f, CallInstruction ctx) {
|
||||
none()
|
||||
}
|
||||
predicate mayBenefitFromCallContext(CallInstruction call, Function f) { none() }
|
||||
|
||||
/**
|
||||
* Gets a viable dispatch target of `ma` in the context `ctx`. This is
|
||||
* restricted to those `ma`s for which the context makes a difference.
|
||||
* Gets a viable dispatch target of `call` in the context `ctx`. This is
|
||||
* restricted to those `call`s for which a context might make a difference.
|
||||
*/
|
||||
Function prunedViableImplInCallContext(CallInstruction call, CallInstruction ctx) { none() }
|
||||
|
||||
/**
|
||||
* Holds if flow returning from `m` to `ma` might return further and if
|
||||
* this path restricts the set of call sites that can be returned to.
|
||||
*/
|
||||
predicate reducedViableImplInReturn(Function f, CallInstruction call) { none() }
|
||||
|
||||
/**
|
||||
* Gets a viable dispatch target of `ma` in the context `ctx`. This is
|
||||
* restricted to those `ma`s and results for which the return flow from the
|
||||
* result to `ma` restricts the possible context `ctx`.
|
||||
*/
|
||||
Function prunedViableImplInCallContextReverse(CallInstruction call, CallInstruction ctx) { none() }
|
||||
Function viableImplInCallContext(CallInstruction call, CallInstruction ctx) { none() }
|
||||
|
||||
@@ -330,6 +330,67 @@ private module Cached {
|
||||
import Final
|
||||
}
|
||||
|
||||
import FlowThrough
|
||||
|
||||
cached
|
||||
private module DispatchWithCallContext {
|
||||
/**
|
||||
* Holds if the call context `ctx` reduces the set of viable run-time
|
||||
* dispatch targets of call `call` in `c`.
|
||||
*/
|
||||
cached
|
||||
predicate reducedViableImplInCallContext(DataFlowCall call, DataFlowCallable c, DataFlowCall ctx) {
|
||||
exists(int tgts, int ctxtgts |
|
||||
mayBenefitFromCallContext(call, c) and
|
||||
c = viableCallable(ctx) and
|
||||
ctxtgts = count(viableImplInCallContext(call, ctx)) and
|
||||
tgts = strictcount(viableCallable(call)) and
|
||||
ctxtgts < tgts
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a viable run-time dispatch target for the call `call` in the
|
||||
* context `ctx`. This is restricted to those calls for which a context
|
||||
* makes a difference.
|
||||
*/
|
||||
cached
|
||||
DataFlowCallable prunedViableImplInCallContext(DataFlowCall call, DataFlowCall ctx) {
|
||||
result = viableImplInCallContext(call, ctx) and
|
||||
reducedViableImplInCallContext(call, _, ctx)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if flow returning from callable `c` to call `call` might return
|
||||
* further and if this path restricts the set of call sites that can be
|
||||
* returned to.
|
||||
*/
|
||||
cached
|
||||
predicate reducedViableImplInReturn(DataFlowCallable c, DataFlowCall call) {
|
||||
exists(int tgts, int ctxtgts |
|
||||
mayBenefitFromCallContext(call, _) and
|
||||
c = viableCallable(call) and
|
||||
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContext(call, ctx)) and
|
||||
tgts = strictcount(DataFlowCall ctx | viableCallable(ctx) = call.getEnclosingCallable()) and
|
||||
ctxtgts < tgts
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a viable run-time dispatch target for the call `call` in the
|
||||
* context `ctx`. This is restricted to those calls and results for which
|
||||
* the return flow from the result to `call` restricts the possible context
|
||||
* `ctx`.
|
||||
*/
|
||||
cached
|
||||
DataFlowCallable prunedViableImplInCallContextReverse(DataFlowCall call, DataFlowCall ctx) {
|
||||
result = viableImplInCallContext(call, ctx) and
|
||||
reducedViableImplInReturn(result, call)
|
||||
}
|
||||
}
|
||||
|
||||
import DispatchWithCallContext
|
||||
|
||||
/**
|
||||
* Holds if `p` can flow to the pre-update node associated with post-update
|
||||
* node `n`, in the same callable, using only value-preserving steps.
|
||||
@@ -371,8 +432,6 @@ private module Cached {
|
||||
store(node1, tc.getContent(), node2, contentType, tc.getContainerType())
|
||||
}
|
||||
|
||||
import FlowThrough
|
||||
|
||||
/**
|
||||
* Holds if the call context `call` either improves virtual dispatch in
|
||||
* `callable` or if it allows us to prune unreachable nodes in `callable`.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes that specify the conditions under which control flows along a given edge.
|
||||
*/
|
||||
|
||||
private import internal.EdgeKindInternal
|
||||
|
||||
private newtype TEdgeKind =
|
||||
@@ -77,9 +81,15 @@ class CaseEdge extends EdgeKind, TCaseEdge {
|
||||
else result = "Case[" + minValue + ".." + maxValue + "]"
|
||||
}
|
||||
|
||||
string getMinValue() { result = minValue }
|
||||
/**
|
||||
* Gets the smallest value of the switch expression for which control will flow along this edge.
|
||||
*/
|
||||
final string getMinValue() { result = minValue }
|
||||
|
||||
string getMaxValue() { result = maxValue }
|
||||
/**
|
||||
* Gets the largest value of the switch expression for which control will flow along this edge.
|
||||
*/
|
||||
final string getMaxValue() { result = maxValue }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,6 +10,7 @@ private newtype TIRConfiguration = MkIRConfiguration()
|
||||
* The query can extend this class to control which functions have IR generated for them.
|
||||
*/
|
||||
class IRConfiguration extends TIRConfiguration {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "IRConfiguration" }
|
||||
|
||||
/**
|
||||
@@ -17,6 +18,13 @@ class IRConfiguration extends TIRConfiguration {
|
||||
*/
|
||||
predicate shouldCreateIRForFunction(Language::Function func) { any() }
|
||||
|
||||
/**
|
||||
* Holds if the strings used as part of an IR dump should be generated for function `func`.
|
||||
*
|
||||
* This predicate is overridden in `PrintIR.qll` to avoid the expense of generating a large number
|
||||
* of debug strings for IR that will not be dumped. We still generate the actual IR for these
|
||||
* functions, however, to preserve the results of any interprocedural analysis.
|
||||
*/
|
||||
predicate shouldEvaluateDebugStringsForFunction(Language::Function func) { any() }
|
||||
}
|
||||
|
||||
@@ -26,6 +34,7 @@ private newtype TIREscapeAnalysisConfiguration = MkIREscapeAnalysisConfiguration
|
||||
* The query can extend this class to control what escape analysis is used when generating SSA.
|
||||
*/
|
||||
class IREscapeAnalysisConfiguration extends TIREscapeAnalysisConfiguration {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "IREscapeAnalysisConfiguration" }
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,6 +32,7 @@ private newtype TIRType =
|
||||
* all pointer types map to the same instance of `IRAddressType`.
|
||||
*/
|
||||
class IRType extends TIRType {
|
||||
/** Gets a textual representation of this type. */
|
||||
string toString() { none() }
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
/**
|
||||
* Provides classes that describe how a particular `Instruction` or its operands access memory.
|
||||
*/
|
||||
|
||||
private import IRConfiguration
|
||||
|
||||
private newtype TMemoryAccessKind =
|
||||
TIndirectMemoryAccess() or
|
||||
TBufferMemoryAccess() or
|
||||
@@ -14,6 +20,7 @@ private newtype TMemoryAccessKind =
|
||||
* memory result.
|
||||
*/
|
||||
class MemoryAccessKind extends TMemoryAccessKind {
|
||||
/** Gets a textual representation of this access kind. */
|
||||
string toString() { none() }
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Provides `Opcode`s that specify the operation performed by an `Instruction`, as well as metadata
|
||||
* about those opcodes, such as operand kinds and memory accesses.
|
||||
*/
|
||||
|
||||
private import internal.OpcodeImports as Imports
|
||||
private import internal.OperandTag
|
||||
import Imports::MemoryAccessKind
|
||||
@@ -45,7 +50,7 @@ private newtype TOpcode =
|
||||
TConvertToDerived() or
|
||||
TCheckedConvertOrNull() or
|
||||
TCheckedConvertOrThrow() or
|
||||
TDynamicCastToVoid() or
|
||||
TCompleteObjectAddress() or
|
||||
TVariableAddress() or
|
||||
TFieldAddress() or
|
||||
TFunctionAddress() or
|
||||
@@ -86,7 +91,11 @@ private newtype TOpcode =
|
||||
TUnreached() or
|
||||
TNewObj()
|
||||
|
||||
/**
|
||||
* An opcode that specifies the operation performed by an `Instruction`.
|
||||
*/
|
||||
class Opcode extends TOpcode {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "UnknownOpcode" }
|
||||
|
||||
/**
|
||||
@@ -139,10 +148,20 @@ class Opcode extends TOpcode {
|
||||
predicate hasOperandInternal(OperandTag tag) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `UnaryInstruction`.
|
||||
*
|
||||
* See the `UnaryInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class UnaryOpcode extends Opcode {
|
||||
final override predicate hasOperandInternal(OperandTag tag) { tag instanceof UnaryOperandTag }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `BinaryInstruction`.
|
||||
*
|
||||
* See the `BinaryInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class BinaryOpcode extends Opcode {
|
||||
final override predicate hasOperandInternal(OperandTag tag) {
|
||||
tag instanceof LeftOperandTag or
|
||||
@@ -150,44 +169,127 @@ abstract class BinaryOpcode extends Opcode {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `PointerArithmeticInstruction`.
|
||||
*
|
||||
* See the `PointerArithmeticInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class PointerArithmeticOpcode extends BinaryOpcode { }
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `PointerOffsetInstruction`.
|
||||
*
|
||||
* See the `PointerOffsetInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class PointerOffsetOpcode extends PointerArithmeticOpcode { }
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `ArithmeticInstruction`.
|
||||
*
|
||||
* See the `ArithmeticInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class ArithmeticOpcode extends Opcode { }
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `BinaryArithmeticInstruction`.
|
||||
*
|
||||
* See the `BinaryArithmeticInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class BinaryArithmeticOpcode extends BinaryOpcode, ArithmeticOpcode { }
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `UnaryArithmeticInstruction`.
|
||||
*
|
||||
* See the `UnaryArithmeticInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class UnaryArithmeticOpcode extends UnaryOpcode, ArithmeticOpcode { }
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `BitwiseInstruction`.
|
||||
*
|
||||
* See the `BitwiseInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class BitwiseOpcode extends Opcode { }
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `BinaryBitwiseInstruction`.
|
||||
*
|
||||
* See the `BinaryBitwiseInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class BinaryBitwiseOpcode extends BinaryOpcode, BitwiseOpcode { }
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `UnaryBitwiseInstruction`.
|
||||
*
|
||||
* See the `UnaryBitwiseInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class UnaryBitwiseOpcode extends UnaryOpcode, BitwiseOpcode { }
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `CompareInstruction`.
|
||||
*
|
||||
* See the `CompareInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class CompareOpcode extends BinaryOpcode { }
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `RelationalInstruction`.
|
||||
*
|
||||
* See the `RelationalInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class RelationalOpcode extends CompareOpcode { }
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `CopyInstruction`.
|
||||
*
|
||||
* See the `CopyInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class CopyOpcode extends Opcode { }
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `ConvertToBaseInstruction`.
|
||||
*
|
||||
* See the `ConvertToBaseInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class ConvertToBaseOpcode extends UnaryOpcode { }
|
||||
|
||||
abstract class MemoryAccessOpcode extends Opcode { }
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `ReturnInstruction`.
|
||||
*
|
||||
* See the `ReturnInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class ReturnOpcode extends Opcode { }
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `ThrowInstruction`.
|
||||
*
|
||||
* See the `ThrowInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class ThrowOpcode extends Opcode { }
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `CatchInstruction`.
|
||||
*
|
||||
* See the `CatchInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class CatchOpcode extends Opcode { }
|
||||
|
||||
abstract class OpcodeWithCondition extends Opcode {
|
||||
abstract private class OpcodeWithCondition extends Opcode {
|
||||
final override predicate hasOperandInternal(OperandTag tag) { tag instanceof ConditionOperandTag }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `BuiltInOperationInstruction`.
|
||||
*
|
||||
* See the `BuiltInOperationInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class BuiltInOperationOpcode extends Opcode { }
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `SideEffectInstruction`.
|
||||
*
|
||||
* See the `SideEffectInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class SideEffectOpcode extends Opcode { }
|
||||
|
||||
/**
|
||||
@@ -323,7 +425,9 @@ abstract class OpcodeWithLoad extends IndirectReadOpcode {
|
||||
}
|
||||
|
||||
/**
|
||||
* An opcode that reads from a set of memory locations as a side effect.
|
||||
* The `Opcode` for a `ReadSideEffectInstruction`.
|
||||
*
|
||||
* See the `ReadSideEffectInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class ReadSideEffectOpcode extends SideEffectOpcode {
|
||||
final override predicate hasOperandInternal(OperandTag tag) {
|
||||
@@ -332,51 +436,111 @@ abstract class ReadSideEffectOpcode extends SideEffectOpcode {
|
||||
}
|
||||
|
||||
/**
|
||||
* An opcode that writes to a set of memory locations as a side effect.
|
||||
* The `Opcode` for a `WriteSideEffectInstruction`.
|
||||
*
|
||||
* See the `WriteSideEffectInstruction` documentation for more details.
|
||||
*/
|
||||
abstract class WriteSideEffectOpcode extends SideEffectOpcode { }
|
||||
|
||||
/**
|
||||
* Provides `Opcode`s that specify the operation performed by an `Instruction`.
|
||||
*/
|
||||
module Opcode {
|
||||
/**
|
||||
* The `Opcode` for a `NoOpInstruction`.
|
||||
*
|
||||
* See the `NoOpInstruction` documentation for more details.
|
||||
*/
|
||||
class NoOp extends Opcode, TNoOp {
|
||||
final override string toString() { result = "NoOp" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `UninitializedInstruction`.
|
||||
*
|
||||
* See the `UninitializedInstruction` documentation for more details.
|
||||
*/
|
||||
class Uninitialized extends IndirectWriteOpcode, TUninitialized {
|
||||
final override string toString() { result = "Uninitialized" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `ErrorInstruction`.
|
||||
*
|
||||
* See the `ErrorInstruction` documentation for more details.
|
||||
*/
|
||||
class Error extends Opcode, TError {
|
||||
final override string toString() { result = "Error" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `InitializeParameterInstruction`.
|
||||
*
|
||||
* See the `InitializeParameterInstruction` documentation for more details.
|
||||
*/
|
||||
class InitializeParameter extends IndirectWriteOpcode, TInitializeParameter {
|
||||
final override string toString() { result = "InitializeParameter" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `InitializeIndirectionInstruction`.
|
||||
*
|
||||
* See the `InitializeIndirectionInstruction` documentation for more details.
|
||||
*/
|
||||
class InitializeIndirection extends EntireAllocationWriteOpcode, TInitializeIndirection {
|
||||
final override string toString() { result = "InitializeIndirection" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `InitializeThisInstruction`.
|
||||
*
|
||||
* See the `InitializeThisInstruction` documentation for more details.
|
||||
*/
|
||||
class InitializeThis extends Opcode, TInitializeThis {
|
||||
final override string toString() { result = "InitializeThis" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `EnterFunctionInstruction`.
|
||||
*
|
||||
* See the `EnterFunctionInstruction` documentation for more details.
|
||||
*/
|
||||
class EnterFunction extends Opcode, TEnterFunction {
|
||||
final override string toString() { result = "EnterFunction" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `ExitFunctionInstruction`.
|
||||
*
|
||||
* See the `ExitFunctionInstruction` documentation for more details.
|
||||
*/
|
||||
class ExitFunction extends Opcode, TExitFunction {
|
||||
final override string toString() { result = "ExitFunction" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `ReturnValueInstruction`.
|
||||
*
|
||||
* See the `ReturnValueInstruction` documentation for more details.
|
||||
*/
|
||||
class ReturnValue extends ReturnOpcode, OpcodeWithLoad, TReturnValue {
|
||||
final override string toString() { result = "ReturnValue" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `ReturnVoidInstruction`.
|
||||
*
|
||||
* See the `ReturnVoidInstruction` documentation for more details.
|
||||
*/
|
||||
class ReturnVoid extends ReturnOpcode, TReturnVoid {
|
||||
final override string toString() { result = "ReturnVoid" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `ReturnIndirectionInstruction`.
|
||||
*
|
||||
* See the `ReturnIndirectionInstruction` documentation for more details.
|
||||
*/
|
||||
class ReturnIndirection extends EntireAllocationReadOpcode, TReturnIndirection {
|
||||
final override string toString() { result = "ReturnIndirection" }
|
||||
|
||||
@@ -385,14 +549,29 @@ module Opcode {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `CopyValueInstruction`.
|
||||
*
|
||||
* See the `CopyValueInstruction` documentation for more details.
|
||||
*/
|
||||
class CopyValue extends UnaryOpcode, CopyOpcode, TCopyValue {
|
||||
final override string toString() { result = "CopyValue" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `LoadInstruction`.
|
||||
*
|
||||
* See the `LoadInstruction` documentation for more details.
|
||||
*/
|
||||
class Load extends CopyOpcode, OpcodeWithLoad, TLoad {
|
||||
final override string toString() { result = "Load" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `StoreInstruction`.
|
||||
*
|
||||
* See the `StoreInstruction` documentation for more details.
|
||||
*/
|
||||
class Store extends CopyOpcode, IndirectWriteOpcode, TStore {
|
||||
final override string toString() { result = "Store" }
|
||||
|
||||
@@ -401,154 +580,344 @@ module Opcode {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `AddInstruction`.
|
||||
*
|
||||
* See the `AddInstruction` documentation for more details.
|
||||
*/
|
||||
class Add extends BinaryArithmeticOpcode, TAdd {
|
||||
final override string toString() { result = "Add" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `SubInstruction`.
|
||||
*
|
||||
* See the `SubInstruction` documentation for more details.
|
||||
*/
|
||||
class Sub extends BinaryArithmeticOpcode, TSub {
|
||||
final override string toString() { result = "Sub" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `MulInstruction`.
|
||||
*
|
||||
* See the `MulInstruction` documentation for more details.
|
||||
*/
|
||||
class Mul extends BinaryArithmeticOpcode, TMul {
|
||||
final override string toString() { result = "Mul" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `DivInstruction`.
|
||||
*
|
||||
* See the `DivInstruction` documentation for more details.
|
||||
*/
|
||||
class Div extends BinaryArithmeticOpcode, TDiv {
|
||||
final override string toString() { result = "Div" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `RemInstruction`.
|
||||
*
|
||||
* See the `RemInstruction` documentation for more details.
|
||||
*/
|
||||
class Rem extends BinaryArithmeticOpcode, TRem {
|
||||
final override string toString() { result = "Rem" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `NegateInstruction`.
|
||||
*
|
||||
* See the `NegateInstruction` documentation for more details.
|
||||
*/
|
||||
class Negate extends UnaryArithmeticOpcode, TNegate {
|
||||
final override string toString() { result = "Negate" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `ShiftLeftInstruction`.
|
||||
*
|
||||
* See the `ShiftLeftInstruction` documentation for more details.
|
||||
*/
|
||||
class ShiftLeft extends BinaryBitwiseOpcode, TShiftLeft {
|
||||
final override string toString() { result = "ShiftLeft" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `ShiftRightInstruction`.
|
||||
*
|
||||
* See the `ShiftRightInstruction` documentation for more details.
|
||||
*/
|
||||
class ShiftRight extends BinaryBitwiseOpcode, TShiftRight {
|
||||
final override string toString() { result = "ShiftRight" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `BitAndInstruction`.
|
||||
*
|
||||
* See the `BitAndInstruction` documentation for more details.
|
||||
*/
|
||||
class BitAnd extends BinaryBitwiseOpcode, TBitAnd {
|
||||
final override string toString() { result = "BitAnd" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `BitOrInstruction`.
|
||||
*
|
||||
* See the `BitOrInstruction` documentation for more details.
|
||||
*/
|
||||
class BitOr extends BinaryBitwiseOpcode, TBitOr {
|
||||
final override string toString() { result = "BitOr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `BitXorInstruction`.
|
||||
*
|
||||
* See the `BitXorInstruction` documentation for more details.
|
||||
*/
|
||||
class BitXor extends BinaryBitwiseOpcode, TBitXor {
|
||||
final override string toString() { result = "BitXor" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `BitComplementInstruction`.
|
||||
*
|
||||
* See the `BitComplementInstruction` documentation for more details.
|
||||
*/
|
||||
class BitComplement extends UnaryBitwiseOpcode, TBitComplement {
|
||||
final override string toString() { result = "BitComplement" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `LogicalNotInstruction`.
|
||||
*
|
||||
* See the `LogicalNotInstruction` documentation for more details.
|
||||
*/
|
||||
class LogicalNot extends UnaryOpcode, TLogicalNot {
|
||||
final override string toString() { result = "LogicalNot" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `CompareEQInstruction`.
|
||||
*
|
||||
* See the `CompareEQInstruction` documentation for more details.
|
||||
*/
|
||||
class CompareEQ extends CompareOpcode, TCompareEQ {
|
||||
final override string toString() { result = "CompareEQ" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `CompareNEInstruction`.
|
||||
*
|
||||
* See the `CompareNEInstruction` documentation for more details.
|
||||
*/
|
||||
class CompareNE extends CompareOpcode, TCompareNE {
|
||||
final override string toString() { result = "CompareNE" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `CompareLTInstruction`.
|
||||
*
|
||||
* See the `CompareLTInstruction` documentation for more details.
|
||||
*/
|
||||
class CompareLT extends RelationalOpcode, TCompareLT {
|
||||
final override string toString() { result = "CompareLT" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `CompareGTInstruction`.
|
||||
*
|
||||
* See the `CompareGTInstruction` documentation for more details.
|
||||
*/
|
||||
class CompareGT extends RelationalOpcode, TCompareGT {
|
||||
final override string toString() { result = "CompareGT" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `CompareLEInstruction`.
|
||||
*
|
||||
* See the `CompareLEInstruction` documentation for more details.
|
||||
*/
|
||||
class CompareLE extends RelationalOpcode, TCompareLE {
|
||||
final override string toString() { result = "CompareLE" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `CompareGEInstruction`.
|
||||
*
|
||||
* See the `CompareGEInstruction` documentation for more details.
|
||||
*/
|
||||
class CompareGE extends RelationalOpcode, TCompareGE {
|
||||
final override string toString() { result = "CompareGE" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `PointerAddInstruction`.
|
||||
*
|
||||
* See the `PointerAddInstruction` documentation for more details.
|
||||
*/
|
||||
class PointerAdd extends PointerOffsetOpcode, TPointerAdd {
|
||||
final override string toString() { result = "PointerAdd" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `PointerSubInstruction`.
|
||||
*
|
||||
* See the `PointerSubInstruction` documentation for more details.
|
||||
*/
|
||||
class PointerSub extends PointerOffsetOpcode, TPointerSub {
|
||||
final override string toString() { result = "PointerSub" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `PointerDiffInstruction`.
|
||||
*
|
||||
* See the `PointerDiffInstruction` documentation for more details.
|
||||
*/
|
||||
class PointerDiff extends PointerArithmeticOpcode, TPointerDiff {
|
||||
final override string toString() { result = "PointerDiff" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `ConvertInstruction`.
|
||||
*
|
||||
* See the `ConvertInstruction` documentation for more details.
|
||||
*/
|
||||
class Convert extends UnaryOpcode, TConvert {
|
||||
final override string toString() { result = "Convert" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `ConvertToNonVirtualBaseInstruction`.
|
||||
*
|
||||
* See the `ConvertToNonVirtualBaseInstruction` documentation for more details.
|
||||
*/
|
||||
class ConvertToNonVirtualBase extends ConvertToBaseOpcode, TConvertToNonVirtualBase {
|
||||
final override string toString() { result = "ConvertToNonVirtualBase" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `ConvertToVirtualBaseInstruction`.
|
||||
*
|
||||
* See the `ConvertToVirtualBaseInstruction` documentation for more details.
|
||||
*/
|
||||
class ConvertToVirtualBase extends ConvertToBaseOpcode, TConvertToVirtualBase {
|
||||
final override string toString() { result = "ConvertToVirtualBase" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `ConvertToDerivedInstruction`.
|
||||
*
|
||||
* See the `ConvertToDerivedInstruction` documentation for more details.
|
||||
*/
|
||||
class ConvertToDerived extends UnaryOpcode, TConvertToDerived {
|
||||
final override string toString() { result = "ConvertToDerived" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `CheckedConvertOrNullInstruction`.
|
||||
*
|
||||
* See the `CheckedConvertOrNullInstruction` documentation for more details.
|
||||
*/
|
||||
class CheckedConvertOrNull extends UnaryOpcode, TCheckedConvertOrNull {
|
||||
final override string toString() { result = "CheckedConvertOrNull" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `CheckedConvertOrThrowInstruction`.
|
||||
*
|
||||
* See the `CheckedConvertOrThrowInstruction` documentation for more details.
|
||||
*/
|
||||
class CheckedConvertOrThrow extends UnaryOpcode, TCheckedConvertOrThrow {
|
||||
final override string toString() { result = "CheckedConvertOrThrow" }
|
||||
}
|
||||
|
||||
class DynamicCastToVoid extends UnaryOpcode, TDynamicCastToVoid {
|
||||
final override string toString() { result = "DynamicCastToVoid" }
|
||||
/**
|
||||
* The `Opcode` for a `CompleteObjectAddressInstruction`.
|
||||
*
|
||||
* See the `CompleteObjectAddressInstruction` documentation for more details.
|
||||
*/
|
||||
class CompleteObjectAddress extends UnaryOpcode, TCompleteObjectAddress {
|
||||
final override string toString() { result = "CompleteObjectAddress" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `VariableAddressInstruction`.
|
||||
*
|
||||
* See the `VariableAddressInstruction` documentation for more details.
|
||||
*/
|
||||
class VariableAddress extends Opcode, TVariableAddress {
|
||||
final override string toString() { result = "VariableAddress" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `FieldAddressInstruction`.
|
||||
*
|
||||
* See the `FieldAddressInstruction` documentation for more details.
|
||||
*/
|
||||
class FieldAddress extends UnaryOpcode, TFieldAddress {
|
||||
final override string toString() { result = "FieldAddress" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `ElementsAddressInstruction`.
|
||||
*
|
||||
* See the `ElementsAddressInstruction` documentation for more details.
|
||||
*/
|
||||
class ElementsAddress extends UnaryOpcode, TElementsAddress {
|
||||
final override string toString() { result = "ElementsAddress" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `FunctionAddressInstruction`.
|
||||
*
|
||||
* See the `FunctionAddressInstruction` documentation for more details.
|
||||
*/
|
||||
class FunctionAddress extends Opcode, TFunctionAddress {
|
||||
final override string toString() { result = "FunctionAddress" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `ConstantInstruction`.
|
||||
*
|
||||
* See the `ConstantInstruction` documentation for more details.
|
||||
*/
|
||||
class Constant extends Opcode, TConstant {
|
||||
final override string toString() { result = "Constant" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `StringConstantInstruction`.
|
||||
*
|
||||
* See the `StringConstantInstruction` documentation for more details.
|
||||
*/
|
||||
class StringConstant extends Opcode, TStringConstant {
|
||||
final override string toString() { result = "StringConstant" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `ConditionalBranchInstruction`.
|
||||
*
|
||||
* See the `ConditionalBranchInstruction` documentation for more details.
|
||||
*/
|
||||
class ConditionalBranch extends OpcodeWithCondition, TConditionalBranch {
|
||||
final override string toString() { result = "ConditionalBranch" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `SwitchInstruction`.
|
||||
*
|
||||
* See the `SwitchInstruction` documentation for more details.
|
||||
*/
|
||||
class Switch extends OpcodeWithCondition, TSwitch {
|
||||
final override string toString() { result = "Switch" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `CallInstruction`.
|
||||
*
|
||||
* See the `CallInstruction` documentation for more details.
|
||||
*/
|
||||
class Call extends Opcode, TCall {
|
||||
final override string toString() { result = "Call" }
|
||||
|
||||
@@ -557,32 +926,67 @@ module Opcode {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `CatchByTypeInstruction`.
|
||||
*
|
||||
* See the `CatchByTypeInstruction` documentation for more details.
|
||||
*/
|
||||
class CatchByType extends CatchOpcode, TCatchByType {
|
||||
final override string toString() { result = "CatchByType" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `CatchAnyInstruction`.
|
||||
*
|
||||
* See the `CatchAnyInstruction` documentation for more details.
|
||||
*/
|
||||
class CatchAny extends CatchOpcode, TCatchAny {
|
||||
final override string toString() { result = "CatchAny" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `ThrowValueInstruction`.
|
||||
*
|
||||
* See the `ThrowValueInstruction` documentation for more details.
|
||||
*/
|
||||
class ThrowValue extends ThrowOpcode, OpcodeWithLoad, TThrowValue {
|
||||
final override string toString() { result = "ThrowValue" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `ReThrowInstruction`.
|
||||
*
|
||||
* See the `ReThrowInstruction` documentation for more details.
|
||||
*/
|
||||
class ReThrow extends ThrowOpcode, TReThrow {
|
||||
final override string toString() { result = "ReThrow" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `UnwindInstruction`.
|
||||
*
|
||||
* See the `UnwindInstruction` documentation for more details.
|
||||
*/
|
||||
class Unwind extends Opcode, TUnwind {
|
||||
final override string toString() { result = "Unwind" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `AliasedDefinitionInstruction`.
|
||||
*
|
||||
* See the `AliasedDefinitionInstruction` documentation for more details.
|
||||
*/
|
||||
class AliasedDefinition extends Opcode, TAliasedDefinition {
|
||||
final override string toString() { result = "AliasedDefinition" }
|
||||
|
||||
final override MemoryAccessKind getWriteMemoryAccess() { result instanceof EscapedMemoryAccess }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `InitializeNonLocalInstruction`.
|
||||
*
|
||||
* See the `InitializeNonLocalInstruction` documentation for more details.
|
||||
*/
|
||||
class InitializeNonLocal extends Opcode, TInitializeNonLocal {
|
||||
final override string toString() { result = "InitializeNonLocal" }
|
||||
|
||||
@@ -591,6 +995,11 @@ module Opcode {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `AliasedUseInstruction`.
|
||||
*
|
||||
* See the `AliasedUseInstruction` documentation for more details.
|
||||
*/
|
||||
class AliasedUse extends Opcode, TAliasedUse {
|
||||
final override string toString() { result = "AliasedUse" }
|
||||
|
||||
@@ -601,92 +1010,187 @@ module Opcode {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `PhiInstruction`.
|
||||
*
|
||||
* See the `PhiInstruction` documentation for more details.
|
||||
*/
|
||||
class Phi extends Opcode, TPhi {
|
||||
final override string toString() { result = "Phi" }
|
||||
|
||||
final override MemoryAccessKind getWriteMemoryAccess() { result instanceof PhiMemoryAccess }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `BuiltInInstruction`.
|
||||
*
|
||||
* See the `BuiltInInstruction` documentation for more details.
|
||||
*/
|
||||
class BuiltIn extends BuiltInOperationOpcode, TBuiltIn {
|
||||
final override string toString() { result = "BuiltIn" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `VarArgsStartInstruction`.
|
||||
*
|
||||
* See the `VarArgsStartInstruction` documentation for more details.
|
||||
*/
|
||||
class VarArgsStart extends UnaryOpcode, TVarArgsStart {
|
||||
final override string toString() { result = "VarArgsStart" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `VarArgsEndInstruction`.
|
||||
*
|
||||
* See the `VarArgsEndInstruction` documentation for more details.
|
||||
*/
|
||||
class VarArgsEnd extends UnaryOpcode, TVarArgsEnd {
|
||||
final override string toString() { result = "VarArgsEnd" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `VarArgInstruction`.
|
||||
*
|
||||
* See the `VarArgInstruction` documentation for more details.
|
||||
*/
|
||||
class VarArg extends UnaryOpcode, TVarArg {
|
||||
final override string toString() { result = "VarArg" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `NextVarArgInstruction`.
|
||||
*
|
||||
* See the `NextVarArgInstruction` documentation for more details.
|
||||
*/
|
||||
class NextVarArg extends UnaryOpcode, TNextVarArg {
|
||||
final override string toString() { result = "NextVarArg" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `CallSideEffectInstruction`.
|
||||
*
|
||||
* See the `CallSideEffectInstruction` documentation for more details.
|
||||
*/
|
||||
class CallSideEffect extends WriteSideEffectOpcode, EscapedWriteOpcode, MayWriteOpcode,
|
||||
ReadSideEffectOpcode, EscapedReadOpcode, MayReadOpcode, TCallSideEffect {
|
||||
final override string toString() { result = "CallSideEffect" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `CallReadSideEffectInstruction`.
|
||||
*
|
||||
* See the `CallReadSideEffectInstruction` documentation for more details.
|
||||
*/
|
||||
class CallReadSideEffect extends ReadSideEffectOpcode, EscapedReadOpcode, MayReadOpcode,
|
||||
TCallReadSideEffect {
|
||||
final override string toString() { result = "CallReadSideEffect" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `IndirectReadSideEffectInstruction`.
|
||||
*
|
||||
* See the `IndirectReadSideEffectInstruction` documentation for more details.
|
||||
*/
|
||||
class IndirectReadSideEffect extends ReadSideEffectOpcode, IndirectReadOpcode,
|
||||
TIndirectReadSideEffect {
|
||||
final override string toString() { result = "IndirectReadSideEffect" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `IndirectMustWriteSideEffectInstruction`.
|
||||
*
|
||||
* See the `IndirectMustWriteSideEffectInstruction` documentation for more details.
|
||||
*/
|
||||
class IndirectMustWriteSideEffect extends WriteSideEffectOpcode, IndirectWriteOpcode,
|
||||
TIndirectMustWriteSideEffect {
|
||||
final override string toString() { result = "IndirectMustWriteSideEffect" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `IndirectMayWriteSideEffectInstruction`.
|
||||
*
|
||||
* See the `IndirectMayWriteSideEffectInstruction` documentation for more details.
|
||||
*/
|
||||
class IndirectMayWriteSideEffect extends WriteSideEffectOpcode, IndirectWriteOpcode,
|
||||
MayWriteOpcode, TIndirectMayWriteSideEffect {
|
||||
final override string toString() { result = "IndirectMayWriteSideEffect" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `BufferReadSideEffectInstruction`.
|
||||
*
|
||||
* See the `BufferReadSideEffectInstruction` documentation for more details.
|
||||
*/
|
||||
class BufferReadSideEffect extends ReadSideEffectOpcode, UnsizedBufferReadOpcode,
|
||||
TBufferReadSideEffect {
|
||||
final override string toString() { result = "BufferReadSideEffect" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `BufferMustWriteSideEffectInstruction`.
|
||||
*
|
||||
* See the `BufferMustWriteSideEffectInstruction` documentation for more details.
|
||||
*/
|
||||
class BufferMustWriteSideEffect extends WriteSideEffectOpcode, UnsizedBufferWriteOpcode,
|
||||
TBufferMustWriteSideEffect {
|
||||
final override string toString() { result = "BufferMustWriteSideEffect" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `BufferMayWriteSideEffectInstruction`.
|
||||
*
|
||||
* See the `BufferMayWriteSideEffectInstruction` documentation for more details.
|
||||
*/
|
||||
class BufferMayWriteSideEffect extends WriteSideEffectOpcode, UnsizedBufferWriteOpcode,
|
||||
MayWriteOpcode, TBufferMayWriteSideEffect {
|
||||
final override string toString() { result = "BufferMayWriteSideEffect" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `SizedBufferReadSideEffectInstruction`.
|
||||
*
|
||||
* See the `SizedBufferReadSideEffectInstruction` documentation for more details.
|
||||
*/
|
||||
class SizedBufferReadSideEffect extends ReadSideEffectOpcode, SizedBufferReadOpcode,
|
||||
TSizedBufferReadSideEffect {
|
||||
final override string toString() { result = "SizedBufferReadSideEffect" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `SizedBufferMustWriteSideEffectInstruction`.
|
||||
*
|
||||
* See the `SizedBufferMustWriteSideEffectInstruction` documentation for more details.
|
||||
*/
|
||||
class SizedBufferMustWriteSideEffect extends WriteSideEffectOpcode, SizedBufferWriteOpcode,
|
||||
TSizedBufferMustWriteSideEffect {
|
||||
final override string toString() { result = "SizedBufferMustWriteSideEffect" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `SizedBufferMayWriteSideEffectInstruction`.
|
||||
*
|
||||
* See the `SizedBufferMayWriteSideEffectInstruction` documentation for more details.
|
||||
*/
|
||||
class SizedBufferMayWriteSideEffect extends WriteSideEffectOpcode, SizedBufferWriteOpcode,
|
||||
MayWriteOpcode, TSizedBufferMayWriteSideEffect {
|
||||
final override string toString() { result = "SizedBufferMayWriteSideEffect" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `InitializeDynamicAllocationInstruction`.
|
||||
*
|
||||
* See the `InitializeDynamicAllocationInstruction` documentation for more details.
|
||||
*/
|
||||
class InitializeDynamicAllocation extends SideEffectOpcode, EntireAllocationWriteOpcode,
|
||||
TInitializeDynamicAllocation {
|
||||
final override string toString() { result = "InitializeDynamicAllocation" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `ChiInstruction`.
|
||||
*
|
||||
* See the `ChiInstruction` documentation for more details.
|
||||
*/
|
||||
class Chi extends Opcode, TChi {
|
||||
final override string toString() { result = "Chi" }
|
||||
|
||||
@@ -701,6 +1205,11 @@ module Opcode {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `InlineAsmInstruction`.
|
||||
*
|
||||
* See the `InlineAsmInstruction` documentation for more details.
|
||||
*/
|
||||
class InlineAsm extends Opcode, EscapedWriteOpcode, MayWriteOpcode, EscapedReadOpcode,
|
||||
MayReadOpcode, TInlineAsm {
|
||||
final override string toString() { result = "InlineAsm" }
|
||||
@@ -710,10 +1219,20 @@ module Opcode {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for an `UnreachedInstruction`.
|
||||
*
|
||||
* See the `UnreachedInstruction` documentation for more details.
|
||||
*/
|
||||
class Unreached extends Opcode, TUnreached {
|
||||
final override string toString() { result = "Unreached" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Opcode` for a `NewObjInstruction`.
|
||||
*
|
||||
* See the `NewObjInstruction` documentation for more details.
|
||||
*/
|
||||
class NewObj extends Opcode, TNewObj {
|
||||
final override string toString() { result = "NewObj" }
|
||||
}
|
||||
|
||||
@@ -12,5 +12,6 @@ private import Imports::TempVariableTag
|
||||
* computed on each branch. The set of possible `TempVariableTag`s is language-dependent.
|
||||
*/
|
||||
class TempVariableTag extends TTempVariableTag {
|
||||
/** Gets a textual representation of this tag. */
|
||||
string toString() { result = getTempVariableTagId(this) }
|
||||
}
|
||||
|
||||
@@ -1,3 +1,47 @@
|
||||
/**
|
||||
* Provides classes that describe the Intermediate Representation (IR) of the program.
|
||||
*
|
||||
* The IR is a representation of the semantics of the program, with very little dependence on the
|
||||
* syntax that was used to write the program. For example, in C++, the statements `i += 1;`, `i++`,
|
||||
* and `++i` all have the same semantic effect, but appear in the AST as three different types of
|
||||
* `Expr` node. In the IR, all three statements are broken down into a sequence of fundamental
|
||||
* operations similar to:
|
||||
*
|
||||
* ```
|
||||
* r1(int*) = VariableAddress[i] // Compute the address of variable `i`
|
||||
* r2(int) = Load &:r1, m0 // Load the value of `i`
|
||||
* r3(int) = Constant[1] // An integer constant with the value `1`
|
||||
* r4(int) = Add r2, r3 // Add `1` to the value of `i`
|
||||
* r5(int) = Store &r1, r4 // Store the new value back into the variable `i`
|
||||
* ```
|
||||
*
|
||||
* This allows IR-based analysis to focus on the fundamental operations, rather than having to be
|
||||
* concerned with the various ways of expressing those operations in source code.
|
||||
*
|
||||
* The key classes in the IR are:
|
||||
*
|
||||
* - `IRFunction` - Contains the IR for an entire function definition, including all of that
|
||||
* function's `Instruction`s, `IRBlock`s, and `IRVariables`.
|
||||
* - `Instruction` - A single operation in the IR. An instruction specifies the operation to be
|
||||
* performed, the operands that produce the inputs to that operation, and the type of the result
|
||||
* of the operation. Control flows from an `Instruction` to one of a set of successor
|
||||
* `Instruction`s.
|
||||
* - `Operand` - An input value of an `Instruction`. All inputs of an `Instruction` are explicitly
|
||||
* represented as `Operand`s, even if the input was implicit in the source code. An `Operand` has
|
||||
* a link to the `Instruction` that consumes its value (its "use") and a link to the `Instruction`
|
||||
* that produces its value (its "definition").
|
||||
* - `IRVariable` - A variable accessed by the IR for a particular function. An `IRVariable` is
|
||||
* created for each variable directly accessed by the function. In addition, `IRVariable`s are
|
||||
* created to represent certain temporary storage locations that do not have explicitly declared
|
||||
* variables in the source code, such as the return value of the function.
|
||||
* - `IRBlock` - A "basic block" in the control flow graph of a function. An `IRBlock` contains a
|
||||
* sequence of instructions such that control flow can only enter the block at the first
|
||||
* instruction, and can only leave the block from the last instruction.
|
||||
* - `IRType` - The type of a value accessed in the IR. Unlike the `Type` class in the AST, `IRType`
|
||||
* is language-neutral. For example, in C++, `unsigned int`, `char32_t`, and `wchar_t` might all
|
||||
* be represented as the `IRType` `uint4`, a four-byte unsigned integer.
|
||||
*/
|
||||
|
||||
import IRFunction
|
||||
import Instruction
|
||||
import IRBlock
|
||||
@@ -11,11 +55,12 @@ import Imports::MemoryAccessKind
|
||||
private newtype TIRPropertyProvider = MkIRPropertyProvider()
|
||||
|
||||
/**
|
||||
* Class that provides additional properties to be dumped for IR instructions and blocks when using
|
||||
* A class that provides additional properties to be dumped for IR instructions and blocks when using
|
||||
* the PrintIR module. Libraries that compute additional facts about IR elements can extend the
|
||||
* single instance of this class to specify the additional properties computed by the library.
|
||||
*/
|
||||
class IRPropertyProvider extends TIRPropertyProvider {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "IRPropertyProvider" }
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes describing basic blocks in the IR of a function.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
import Instruction
|
||||
private import internal.IRBlockImports as Imports
|
||||
@@ -16,15 +20,23 @@ private import Cached
|
||||
* Most consumers should use the class `IRBlock`.
|
||||
*/
|
||||
class IRBlockBase extends TIRBlock {
|
||||
/** Gets a textual representation of this block. */
|
||||
final string toString() { result = getFirstInstruction(this).toString() }
|
||||
|
||||
/** Gets the source location of the first non-`Phi` instruction in this block. */
|
||||
final Language::Location getLocation() { result = getFirstInstruction().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets a string that uniquely identifies this block within its enclosing function.
|
||||
*
|
||||
* This predicate is used by debugging and printing code only.
|
||||
*/
|
||||
final string getUniqueId() { result = getFirstInstruction(this).getUniqueId() }
|
||||
|
||||
/**
|
||||
* Gets the zero-based index of the block within its function. This is used
|
||||
* by debugging and printing code only.
|
||||
* Gets the zero-based index of the block within its function.
|
||||
*
|
||||
* This predicate is used by debugging and printing code only.
|
||||
*/
|
||||
int getDisplayIndex() {
|
||||
exists(IRConfiguration::IRConfiguration config |
|
||||
@@ -42,27 +54,51 @@ class IRBlockBase extends TIRBlock {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `index`th non-`Phi` instruction in this block.
|
||||
*/
|
||||
final Instruction getInstruction(int index) { result = getInstruction(this, index) }
|
||||
|
||||
/**
|
||||
* Get the `Phi` instructions that appear at the start of this block.
|
||||
*/
|
||||
final PhiInstruction getAPhiInstruction() {
|
||||
Construction::getPhiInstructionBlockStart(result) = getFirstInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the instructions in this block, including `Phi` instructions.
|
||||
*/
|
||||
final Instruction getAnInstruction() {
|
||||
result = getInstruction(_) or
|
||||
result = getAPhiInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the first non-`Phi` instruction in this block.
|
||||
*/
|
||||
final Instruction getFirstInstruction() { result = getFirstInstruction(this) }
|
||||
|
||||
/**
|
||||
* Gets the last instruction in this block.
|
||||
*/
|
||||
final Instruction getLastInstruction() { result = getInstruction(getInstructionCount() - 1) }
|
||||
|
||||
/**
|
||||
* Gets the number of non-`Phi` instructions in this block.
|
||||
*/
|
||||
final int getInstructionCount() { result = getInstructionCount(this) }
|
||||
|
||||
/**
|
||||
* Gets the `IRFunction` that contains this block.
|
||||
*/
|
||||
final IRFunction getEnclosingIRFunction() {
|
||||
result = getFirstInstruction(this).getEnclosingIRFunction()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `Function` that contains this block.
|
||||
*/
|
||||
final Language::Function getEnclosingFunction() {
|
||||
result = getFirstInstruction(this).getEnclosingFunction()
|
||||
}
|
||||
@@ -74,20 +110,57 @@ class IRBlockBase extends TIRBlock {
|
||||
* instruction of another block.
|
||||
*/
|
||||
class IRBlock extends IRBlockBase {
|
||||
/**
|
||||
* Gets the blocks to which control flows directly from this block.
|
||||
*/
|
||||
final IRBlock getASuccessor() { blockSuccessor(this, result) }
|
||||
|
||||
/**
|
||||
* Gets the blocks from which control flows directly to this block.
|
||||
*/
|
||||
final IRBlock getAPredecessor() { blockSuccessor(result, this) }
|
||||
|
||||
/**
|
||||
* Gets the block to which control flows directly from this block along an edge of kind `kind`.
|
||||
*/
|
||||
final IRBlock getSuccessor(EdgeKind kind) { blockSuccessor(this, result, kind) }
|
||||
|
||||
/**
|
||||
* Gets the block to which control flows directly from this block along a back edge of kind
|
||||
* `kind`.
|
||||
*/
|
||||
final IRBlock getBackEdgeSuccessor(EdgeKind kind) { backEdgeSuccessor(this, result, kind) }
|
||||
|
||||
/**
|
||||
* Holds if this block immediately dominates `block`.
|
||||
*
|
||||
* Block `A` immediate dominates block `B` if block `A` strictly dominates block `B` and block `B`
|
||||
* is a direct successor of block `A`.
|
||||
*/
|
||||
final predicate immediatelyDominates(IRBlock block) { blockImmediatelyDominates(this, block) }
|
||||
|
||||
/**
|
||||
* Holds if this block strictly dominates `block`.
|
||||
*
|
||||
* Block `A` strictly dominates block `B` if block `A` dominates block `B` and blocks `A` and `B`
|
||||
* are not the same block.
|
||||
*/
|
||||
final predicate strictlyDominates(IRBlock block) { blockImmediatelyDominates+(this, block) }
|
||||
|
||||
/**
|
||||
* Holds if this block dominates `block`.
|
||||
*
|
||||
* Block `A` dominates block `B` if any control flow path from the entry block of the function to
|
||||
* block `B` must pass through block `A`. A block always dominates itself.
|
||||
*/
|
||||
final predicate dominates(IRBlock block) { strictlyDominates(block) or this = block }
|
||||
|
||||
/**
|
||||
* Gets the set of blocks on the dominance frontier of this block.
|
||||
*
|
||||
* The dominance frontier of block `A` is the set of blocks `B` such that block `A` does not
|
||||
* dominate block `B`, but block `A` does dominate an immediate predecessor of block `B`.
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock dominanceFrontier() {
|
||||
dominates(result.getAPredecessor()) and
|
||||
@@ -95,7 +168,7 @@ class IRBlock extends IRBlockBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this block is reachable from the entry point of its function
|
||||
* Holds if this block is reachable from the entry block of its function.
|
||||
*/
|
||||
final predicate isReachableFromFunctionEntry() {
|
||||
this = getEnclosingIRFunction().getEntryBlock() or
|
||||
@@ -210,4 +283,4 @@ private module Cached {
|
||||
idominance(isEntryBlock/1, blockSuccessor/2)(_, dominator, block)
|
||||
}
|
||||
|
||||
Instruction getFirstInstruction(TIRBlock block) { block = MkIRBlock(result) }
|
||||
private Instruction getFirstInstruction(TIRBlock block) { block = MkIRBlock(result) }
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Provides the class `IRFunction`, which represents the Intermediate Representation for the
|
||||
* definition of a function.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
private import internal.IRFunctionImports as Imports
|
||||
import Imports::IRFunctionBase
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes that represent variables accessed by the IR.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
import IRFunction
|
||||
private import internal.IRVariableImports as Imports
|
||||
@@ -7,15 +11,11 @@ private import Imports::TTempVariableTag
|
||||
private import Imports::TIRVariable
|
||||
private import Imports::IRType
|
||||
|
||||
IRUserVariable getIRUserVariable(Language::Function func, Language::Variable var) {
|
||||
result.getVariable() = var and
|
||||
result.getEnclosingFunction() = func
|
||||
}
|
||||
|
||||
/**
|
||||
* A variable referenced by the IR for a function. The variable may be a user-declared variable
|
||||
* (`IRUserVariable`) or a temporary variable generated by the AST-to-IR translation
|
||||
* (`IRTempVariable`).
|
||||
* A variable referenced by the IR for a function.
|
||||
*
|
||||
* The variable may be a user-declared variable (`IRUserVariable`) or a temporary variable generated
|
||||
* by the AST-to-IR translation (`IRTempVariable`).
|
||||
*/
|
||||
class IRVariable extends TIRVariable {
|
||||
Language::Function func;
|
||||
@@ -27,6 +27,7 @@ class IRVariable extends TIRVariable {
|
||||
this = TIRDynamicInitializationFlag(func, _, _)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { none() }
|
||||
|
||||
/**
|
||||
@@ -162,20 +163,26 @@ class IRGeneratedVariable extends IRVariable {
|
||||
|
||||
override string getUniqueId() { none() }
|
||||
|
||||
/**
|
||||
* Gets a string containing the source code location of the AST that generated this variable.
|
||||
*
|
||||
* This is used by debugging and printing code only.
|
||||
*/
|
||||
final string getLocationString() {
|
||||
result =
|
||||
ast.getLocation().getStartLine().toString() + ":" +
|
||||
ast.getLocation().getStartColumn().toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string that is combined with the location of the variable to generate the string
|
||||
* representation of this variable.
|
||||
*
|
||||
* This is used by debugging and printing code only.
|
||||
*/
|
||||
string getBaseString() { none() }
|
||||
}
|
||||
|
||||
IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
|
||||
result.getAST() = ast and
|
||||
result.getTag() = tag
|
||||
}
|
||||
|
||||
/**
|
||||
* A temporary variable introduced by IR construction. The most common examples are the variable
|
||||
* generated to hold the return value of a function, or the variable generated to hold the result of
|
||||
@@ -190,6 +197,10 @@ class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVa
|
||||
result = "Temp: " + Construction::getTempVariableUniqueId(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the "tag" object that differentiates this temporary variable from other temporary
|
||||
* variables generated for the same AST.
|
||||
*/
|
||||
final TempVariableTag getTag() { result = tag }
|
||||
|
||||
override string getBaseString() { result = "#temp" }
|
||||
@@ -253,6 +264,9 @@ class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
|
||||
final override string getBaseString() { result = "#string" }
|
||||
|
||||
/**
|
||||
* Gets the AST of the string literal represented by this `IRStringLiteral`.
|
||||
*/
|
||||
final Language::StringLiteral getLiteral() { result = literal }
|
||||
}
|
||||
|
||||
@@ -270,6 +284,9 @@ class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitial
|
||||
|
||||
final override string toString() { result = var.toString() + "#init" }
|
||||
|
||||
/**
|
||||
* Gets variable whose initialization is guarded by this flag.
|
||||
*/
|
||||
final Language::Variable getVariable() { result = var }
|
||||
|
||||
final override string getUniqueId() {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes that represent the input values of IR instructions.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
private import Instruction
|
||||
private import IRBlock
|
||||
@@ -78,10 +82,17 @@ private PhiOperandBase phiOperand(
|
||||
* A source operand of an `Instruction`. The operand represents a value consumed by the instruction.
|
||||
*/
|
||||
class Operand extends TOperand {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Operand" }
|
||||
|
||||
/**
|
||||
* Gets the location of the source code for this operand.
|
||||
*/
|
||||
final Language::Location getLocation() { result = getUse().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the function that contains this operand.
|
||||
*/
|
||||
final IRFunction getEnclosingIRFunction() { result = getUse().getEnclosingIRFunction() }
|
||||
|
||||
/**
|
||||
@@ -270,6 +281,9 @@ class NonPhiOperand extends Operand {
|
||||
|
||||
final override int getDumpSortOrder() { result = tag.getSortOrder() }
|
||||
|
||||
/**
|
||||
* Gets the `OperandTag` that specifies how this operand is used by its `Instruction`.
|
||||
*/
|
||||
final OperandTag getOperandTag() { result = tag }
|
||||
}
|
||||
|
||||
@@ -292,6 +306,9 @@ class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A memory operand other than the operand of a `Phi` instruction.
|
||||
*/
|
||||
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase {
|
||||
override MemoryOperandTag tag;
|
||||
|
||||
@@ -313,6 +330,9 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOper
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A memory operand whose type may be different from the type of the result of its definition.
|
||||
*/
|
||||
class TypedOperand extends NonPhiMemoryOperand {
|
||||
override TypedOperandTag tag;
|
||||
|
||||
@@ -416,6 +436,9 @@ class PositionalArgumentOperand extends ArgumentOperand {
|
||||
final int getIndex() { result = tag.getArgIndex() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An operand representing memory read as a side effect of evaluating another instruction.
|
||||
*/
|
||||
class SideEffectOperand extends TypedOperand {
|
||||
override SideEffectOperandTag tag;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* Outputs a representation of the IR as a control flow graph.
|
||||
*
|
||||
* This file contains the actual implementation of `PrintIR.ql`. For test cases and very small
|
||||
* databases, `PrintIR.ql` can be run directly to dump the IR for the entire database. For most
|
||||
* uses, however, it is better to write a query that imports `PrintIR.qll`, extends
|
||||
* `PrintIRConfiguration`, and overrides `shouldPrintFunction()` to select a subset of functions to
|
||||
* dump.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
private import IR
|
||||
private import internal.PrintIRImports as Imports
|
||||
@@ -9,6 +19,7 @@ private newtype TPrintIRConfiguration = MkPrintIRConfiguration()
|
||||
* The query can extend this class to control which functions are printed.
|
||||
*/
|
||||
class PrintIRConfiguration extends TPrintIRConfiguration {
|
||||
/** Gets a textual representation of this configuration. */
|
||||
string toString() { result = "PrintIRConfiguration" }
|
||||
|
||||
/**
|
||||
@@ -47,7 +58,7 @@ private newtype TPrintableIRNode =
|
||||
/**
|
||||
* A node to be emitted in the IR graph.
|
||||
*/
|
||||
abstract class PrintableIRNode extends TPrintableIRNode {
|
||||
abstract private class PrintableIRNode extends TPrintableIRNode {
|
||||
abstract string toString();
|
||||
|
||||
/**
|
||||
@@ -98,7 +109,7 @@ abstract class PrintableIRNode extends TPrintableIRNode {
|
||||
/**
|
||||
* An IR graph node representing a `IRFunction` object.
|
||||
*/
|
||||
class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
|
||||
private class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
|
||||
IRFunction irFunc;
|
||||
|
||||
PrintableIRFunction() { this = TPrintableIRFunction(irFunc) }
|
||||
@@ -129,7 +140,7 @@ class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
|
||||
/**
|
||||
* An IR graph node representing an `IRBlock` object.
|
||||
*/
|
||||
class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
|
||||
private class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
|
||||
IRBlock block;
|
||||
|
||||
PrintableIRBlock() { this = TPrintableIRBlock(block) }
|
||||
@@ -161,7 +172,7 @@ class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
|
||||
/**
|
||||
* An IR graph node representing an `Instruction`.
|
||||
*/
|
||||
class PrintableInstruction extends PrintableIRNode, TPrintableInstruction {
|
||||
private class PrintableInstruction extends PrintableIRNode, TPrintableInstruction {
|
||||
Instruction instr;
|
||||
|
||||
PrintableInstruction() { this = TPrintableInstruction(instr) }
|
||||
@@ -224,6 +235,9 @@ private string getPaddingString(int n) {
|
||||
n > 0 and n <= maxColumnWidth() and result = getPaddingString(n - 1) + " "
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` belongs to the output graph, and its property `key` has the given `value`.
|
||||
*/
|
||||
query predicate nodes(PrintableIRNode node, string key, string value) {
|
||||
value = node.getProperty(key)
|
||||
}
|
||||
@@ -237,6 +251,10 @@ private int getSuccessorIndex(IRBlock pred, IRBlock succ) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the output graph contains an edge from `pred` to `succ`, and that edge's property `key`
|
||||
* has the given `value`.
|
||||
*/
|
||||
query predicate edges(PrintableIRBlock pred, PrintableIRBlock succ, string key, string value) {
|
||||
exists(EdgeKind kind, IRBlock predBlock, IRBlock succBlock |
|
||||
predBlock = pred.getBlock() and
|
||||
@@ -256,6 +274,9 @@ query predicate edges(PrintableIRBlock pred, PrintableIRBlock succ, string key,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `parent` is the parent node of `child` in the output graph.
|
||||
*/
|
||||
query predicate parents(PrintableIRNode child, PrintableIRNode parent) {
|
||||
parent = child.getParent()
|
||||
}
|
||||
|
||||
@@ -1,3 +1,47 @@
|
||||
/**
|
||||
* Provides classes that describe the Intermediate Representation (IR) of the program.
|
||||
*
|
||||
* The IR is a representation of the semantics of the program, with very little dependence on the
|
||||
* syntax that was used to write the program. For example, in C++, the statements `i += 1;`, `i++`,
|
||||
* and `++i` all have the same semantic effect, but appear in the AST as three different types of
|
||||
* `Expr` node. In the IR, all three statements are broken down into a sequence of fundamental
|
||||
* operations similar to:
|
||||
*
|
||||
* ```
|
||||
* r1(int*) = VariableAddress[i] // Compute the address of variable `i`
|
||||
* r2(int) = Load &:r1, m0 // Load the value of `i`
|
||||
* r3(int) = Constant[1] // An integer constant with the value `1`
|
||||
* r4(int) = Add r2, r3 // Add `1` to the value of `i`
|
||||
* r5(int) = Store &r1, r4 // Store the new value back into the variable `i`
|
||||
* ```
|
||||
*
|
||||
* This allows IR-based analysis to focus on the fundamental operations, rather than having to be
|
||||
* concerned with the various ways of expressing those operations in source code.
|
||||
*
|
||||
* The key classes in the IR are:
|
||||
*
|
||||
* - `IRFunction` - Contains the IR for an entire function definition, including all of that
|
||||
* function's `Instruction`s, `IRBlock`s, and `IRVariables`.
|
||||
* - `Instruction` - A single operation in the IR. An instruction specifies the operation to be
|
||||
* performed, the operands that produce the inputs to that operation, and the type of the result
|
||||
* of the operation. Control flows from an `Instruction` to one of a set of successor
|
||||
* `Instruction`s.
|
||||
* - `Operand` - An input value of an `Instruction`. All inputs of an `Instruction` are explicitly
|
||||
* represented as `Operand`s, even if the input was implicit in the source code. An `Operand` has
|
||||
* a link to the `Instruction` that consumes its value (its "use") and a link to the `Instruction`
|
||||
* that produces its value (its "definition").
|
||||
* - `IRVariable` - A variable accessed by the IR for a particular function. An `IRVariable` is
|
||||
* created for each variable directly accessed by the function. In addition, `IRVariable`s are
|
||||
* created to represent certain temporary storage locations that do not have explicitly declared
|
||||
* variables in the source code, such as the return value of the function.
|
||||
* - `IRBlock` - A "basic block" in the control flow graph of a function. An `IRBlock` contains a
|
||||
* sequence of instructions such that control flow can only enter the block at the first
|
||||
* instruction, and can only leave the block from the last instruction.
|
||||
* - `IRType` - The type of a value accessed in the IR. Unlike the `Type` class in the AST, `IRType`
|
||||
* is language-neutral. For example, in C++, `unsigned int`, `char32_t`, and `wchar_t` might all
|
||||
* be represented as the `IRType` `uint4`, a four-byte unsigned integer.
|
||||
*/
|
||||
|
||||
import IRFunction
|
||||
import Instruction
|
||||
import IRBlock
|
||||
@@ -11,11 +55,12 @@ import Imports::MemoryAccessKind
|
||||
private newtype TIRPropertyProvider = MkIRPropertyProvider()
|
||||
|
||||
/**
|
||||
* Class that provides additional properties to be dumped for IR instructions and blocks when using
|
||||
* A class that provides additional properties to be dumped for IR instructions and blocks when using
|
||||
* the PrintIR module. Libraries that compute additional facts about IR elements can extend the
|
||||
* single instance of this class to specify the additional properties computed by the library.
|
||||
*/
|
||||
class IRPropertyProvider extends TIRPropertyProvider {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "IRPropertyProvider" }
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes describing basic blocks in the IR of a function.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
import Instruction
|
||||
private import internal.IRBlockImports as Imports
|
||||
@@ -16,15 +20,23 @@ private import Cached
|
||||
* Most consumers should use the class `IRBlock`.
|
||||
*/
|
||||
class IRBlockBase extends TIRBlock {
|
||||
/** Gets a textual representation of this block. */
|
||||
final string toString() { result = getFirstInstruction(this).toString() }
|
||||
|
||||
/** Gets the source location of the first non-`Phi` instruction in this block. */
|
||||
final Language::Location getLocation() { result = getFirstInstruction().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets a string that uniquely identifies this block within its enclosing function.
|
||||
*
|
||||
* This predicate is used by debugging and printing code only.
|
||||
*/
|
||||
final string getUniqueId() { result = getFirstInstruction(this).getUniqueId() }
|
||||
|
||||
/**
|
||||
* Gets the zero-based index of the block within its function. This is used
|
||||
* by debugging and printing code only.
|
||||
* Gets the zero-based index of the block within its function.
|
||||
*
|
||||
* This predicate is used by debugging and printing code only.
|
||||
*/
|
||||
int getDisplayIndex() {
|
||||
exists(IRConfiguration::IRConfiguration config |
|
||||
@@ -42,27 +54,51 @@ class IRBlockBase extends TIRBlock {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `index`th non-`Phi` instruction in this block.
|
||||
*/
|
||||
final Instruction getInstruction(int index) { result = getInstruction(this, index) }
|
||||
|
||||
/**
|
||||
* Get the `Phi` instructions that appear at the start of this block.
|
||||
*/
|
||||
final PhiInstruction getAPhiInstruction() {
|
||||
Construction::getPhiInstructionBlockStart(result) = getFirstInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the instructions in this block, including `Phi` instructions.
|
||||
*/
|
||||
final Instruction getAnInstruction() {
|
||||
result = getInstruction(_) or
|
||||
result = getAPhiInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the first non-`Phi` instruction in this block.
|
||||
*/
|
||||
final Instruction getFirstInstruction() { result = getFirstInstruction(this) }
|
||||
|
||||
/**
|
||||
* Gets the last instruction in this block.
|
||||
*/
|
||||
final Instruction getLastInstruction() { result = getInstruction(getInstructionCount() - 1) }
|
||||
|
||||
/**
|
||||
* Gets the number of non-`Phi` instructions in this block.
|
||||
*/
|
||||
final int getInstructionCount() { result = getInstructionCount(this) }
|
||||
|
||||
/**
|
||||
* Gets the `IRFunction` that contains this block.
|
||||
*/
|
||||
final IRFunction getEnclosingIRFunction() {
|
||||
result = getFirstInstruction(this).getEnclosingIRFunction()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `Function` that contains this block.
|
||||
*/
|
||||
final Language::Function getEnclosingFunction() {
|
||||
result = getFirstInstruction(this).getEnclosingFunction()
|
||||
}
|
||||
@@ -74,20 +110,57 @@ class IRBlockBase extends TIRBlock {
|
||||
* instruction of another block.
|
||||
*/
|
||||
class IRBlock extends IRBlockBase {
|
||||
/**
|
||||
* Gets the blocks to which control flows directly from this block.
|
||||
*/
|
||||
final IRBlock getASuccessor() { blockSuccessor(this, result) }
|
||||
|
||||
/**
|
||||
* Gets the blocks from which control flows directly to this block.
|
||||
*/
|
||||
final IRBlock getAPredecessor() { blockSuccessor(result, this) }
|
||||
|
||||
/**
|
||||
* Gets the block to which control flows directly from this block along an edge of kind `kind`.
|
||||
*/
|
||||
final IRBlock getSuccessor(EdgeKind kind) { blockSuccessor(this, result, kind) }
|
||||
|
||||
/**
|
||||
* Gets the block to which control flows directly from this block along a back edge of kind
|
||||
* `kind`.
|
||||
*/
|
||||
final IRBlock getBackEdgeSuccessor(EdgeKind kind) { backEdgeSuccessor(this, result, kind) }
|
||||
|
||||
/**
|
||||
* Holds if this block immediately dominates `block`.
|
||||
*
|
||||
* Block `A` immediate dominates block `B` if block `A` strictly dominates block `B` and block `B`
|
||||
* is a direct successor of block `A`.
|
||||
*/
|
||||
final predicate immediatelyDominates(IRBlock block) { blockImmediatelyDominates(this, block) }
|
||||
|
||||
/**
|
||||
* Holds if this block strictly dominates `block`.
|
||||
*
|
||||
* Block `A` strictly dominates block `B` if block `A` dominates block `B` and blocks `A` and `B`
|
||||
* are not the same block.
|
||||
*/
|
||||
final predicate strictlyDominates(IRBlock block) { blockImmediatelyDominates+(this, block) }
|
||||
|
||||
/**
|
||||
* Holds if this block dominates `block`.
|
||||
*
|
||||
* Block `A` dominates block `B` if any control flow path from the entry block of the function to
|
||||
* block `B` must pass through block `A`. A block always dominates itself.
|
||||
*/
|
||||
final predicate dominates(IRBlock block) { strictlyDominates(block) or this = block }
|
||||
|
||||
/**
|
||||
* Gets the set of blocks on the dominance frontier of this block.
|
||||
*
|
||||
* The dominance frontier of block `A` is the set of blocks `B` such that block `A` does not
|
||||
* dominate block `B`, but block `A` does dominate an immediate predecessor of block `B`.
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock dominanceFrontier() {
|
||||
dominates(result.getAPredecessor()) and
|
||||
@@ -95,7 +168,7 @@ class IRBlock extends IRBlockBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this block is reachable from the entry point of its function
|
||||
* Holds if this block is reachable from the entry block of its function.
|
||||
*/
|
||||
final predicate isReachableFromFunctionEntry() {
|
||||
this = getEnclosingIRFunction().getEntryBlock() or
|
||||
@@ -210,4 +283,4 @@ private module Cached {
|
||||
idominance(isEntryBlock/1, blockSuccessor/2)(_, dominator, block)
|
||||
}
|
||||
|
||||
Instruction getFirstInstruction(TIRBlock block) { block = MkIRBlock(result) }
|
||||
private Instruction getFirstInstruction(TIRBlock block) { block = MkIRBlock(result) }
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Provides the class `IRFunction`, which represents the Intermediate Representation for the
|
||||
* definition of a function.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
private import internal.IRFunctionImports as Imports
|
||||
import Imports::IRFunctionBase
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes that represent variables accessed by the IR.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
import IRFunction
|
||||
private import internal.IRVariableImports as Imports
|
||||
@@ -7,15 +11,11 @@ private import Imports::TTempVariableTag
|
||||
private import Imports::TIRVariable
|
||||
private import Imports::IRType
|
||||
|
||||
IRUserVariable getIRUserVariable(Language::Function func, Language::Variable var) {
|
||||
result.getVariable() = var and
|
||||
result.getEnclosingFunction() = func
|
||||
}
|
||||
|
||||
/**
|
||||
* A variable referenced by the IR for a function. The variable may be a user-declared variable
|
||||
* (`IRUserVariable`) or a temporary variable generated by the AST-to-IR translation
|
||||
* (`IRTempVariable`).
|
||||
* A variable referenced by the IR for a function.
|
||||
*
|
||||
* The variable may be a user-declared variable (`IRUserVariable`) or a temporary variable generated
|
||||
* by the AST-to-IR translation (`IRTempVariable`).
|
||||
*/
|
||||
class IRVariable extends TIRVariable {
|
||||
Language::Function func;
|
||||
@@ -27,6 +27,7 @@ class IRVariable extends TIRVariable {
|
||||
this = TIRDynamicInitializationFlag(func, _, _)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { none() }
|
||||
|
||||
/**
|
||||
@@ -162,20 +163,26 @@ class IRGeneratedVariable extends IRVariable {
|
||||
|
||||
override string getUniqueId() { none() }
|
||||
|
||||
/**
|
||||
* Gets a string containing the source code location of the AST that generated this variable.
|
||||
*
|
||||
* This is used by debugging and printing code only.
|
||||
*/
|
||||
final string getLocationString() {
|
||||
result =
|
||||
ast.getLocation().getStartLine().toString() + ":" +
|
||||
ast.getLocation().getStartColumn().toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string that is combined with the location of the variable to generate the string
|
||||
* representation of this variable.
|
||||
*
|
||||
* This is used by debugging and printing code only.
|
||||
*/
|
||||
string getBaseString() { none() }
|
||||
}
|
||||
|
||||
IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
|
||||
result.getAST() = ast and
|
||||
result.getTag() = tag
|
||||
}
|
||||
|
||||
/**
|
||||
* A temporary variable introduced by IR construction. The most common examples are the variable
|
||||
* generated to hold the return value of a function, or the variable generated to hold the result of
|
||||
@@ -190,6 +197,10 @@ class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVa
|
||||
result = "Temp: " + Construction::getTempVariableUniqueId(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the "tag" object that differentiates this temporary variable from other temporary
|
||||
* variables generated for the same AST.
|
||||
*/
|
||||
final TempVariableTag getTag() { result = tag }
|
||||
|
||||
override string getBaseString() { result = "#temp" }
|
||||
@@ -253,6 +264,9 @@ class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
|
||||
final override string getBaseString() { result = "#string" }
|
||||
|
||||
/**
|
||||
* Gets the AST of the string literal represented by this `IRStringLiteral`.
|
||||
*/
|
||||
final Language::StringLiteral getLiteral() { result = literal }
|
||||
}
|
||||
|
||||
@@ -270,6 +284,9 @@ class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitial
|
||||
|
||||
final override string toString() { result = var.toString() + "#init" }
|
||||
|
||||
/**
|
||||
* Gets variable whose initialization is guarded by this flag.
|
||||
*/
|
||||
final Language::Variable getVariable() { result = var }
|
||||
|
||||
final override string getUniqueId() {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes that represent the input values of IR instructions.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
private import Instruction
|
||||
private import IRBlock
|
||||
@@ -78,10 +82,17 @@ private PhiOperandBase phiOperand(
|
||||
* A source operand of an `Instruction`. The operand represents a value consumed by the instruction.
|
||||
*/
|
||||
class Operand extends TOperand {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Operand" }
|
||||
|
||||
/**
|
||||
* Gets the location of the source code for this operand.
|
||||
*/
|
||||
final Language::Location getLocation() { result = getUse().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the function that contains this operand.
|
||||
*/
|
||||
final IRFunction getEnclosingIRFunction() { result = getUse().getEnclosingIRFunction() }
|
||||
|
||||
/**
|
||||
@@ -270,6 +281,9 @@ class NonPhiOperand extends Operand {
|
||||
|
||||
final override int getDumpSortOrder() { result = tag.getSortOrder() }
|
||||
|
||||
/**
|
||||
* Gets the `OperandTag` that specifies how this operand is used by its `Instruction`.
|
||||
*/
|
||||
final OperandTag getOperandTag() { result = tag }
|
||||
}
|
||||
|
||||
@@ -292,6 +306,9 @@ class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A memory operand other than the operand of a `Phi` instruction.
|
||||
*/
|
||||
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase {
|
||||
override MemoryOperandTag tag;
|
||||
|
||||
@@ -313,6 +330,9 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOper
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A memory operand whose type may be different from the type of the result of its definition.
|
||||
*/
|
||||
class TypedOperand extends NonPhiMemoryOperand {
|
||||
override TypedOperandTag tag;
|
||||
|
||||
@@ -416,6 +436,9 @@ class PositionalArgumentOperand extends ArgumentOperand {
|
||||
final int getIndex() { result = tag.getArgIndex() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An operand representing memory read as a side effect of evaluating another instruction.
|
||||
*/
|
||||
class SideEffectOperand extends TypedOperand {
|
||||
override SideEffectOperandTag tag;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* Outputs a representation of the IR as a control flow graph.
|
||||
*
|
||||
* This file contains the actual implementation of `PrintIR.ql`. For test cases and very small
|
||||
* databases, `PrintIR.ql` can be run directly to dump the IR for the entire database. For most
|
||||
* uses, however, it is better to write a query that imports `PrintIR.qll`, extends
|
||||
* `PrintIRConfiguration`, and overrides `shouldPrintFunction()` to select a subset of functions to
|
||||
* dump.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
private import IR
|
||||
private import internal.PrintIRImports as Imports
|
||||
@@ -9,6 +19,7 @@ private newtype TPrintIRConfiguration = MkPrintIRConfiguration()
|
||||
* The query can extend this class to control which functions are printed.
|
||||
*/
|
||||
class PrintIRConfiguration extends TPrintIRConfiguration {
|
||||
/** Gets a textual representation of this configuration. */
|
||||
string toString() { result = "PrintIRConfiguration" }
|
||||
|
||||
/**
|
||||
@@ -47,7 +58,7 @@ private newtype TPrintableIRNode =
|
||||
/**
|
||||
* A node to be emitted in the IR graph.
|
||||
*/
|
||||
abstract class PrintableIRNode extends TPrintableIRNode {
|
||||
abstract private class PrintableIRNode extends TPrintableIRNode {
|
||||
abstract string toString();
|
||||
|
||||
/**
|
||||
@@ -98,7 +109,7 @@ abstract class PrintableIRNode extends TPrintableIRNode {
|
||||
/**
|
||||
* An IR graph node representing a `IRFunction` object.
|
||||
*/
|
||||
class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
|
||||
private class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
|
||||
IRFunction irFunc;
|
||||
|
||||
PrintableIRFunction() { this = TPrintableIRFunction(irFunc) }
|
||||
@@ -129,7 +140,7 @@ class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
|
||||
/**
|
||||
* An IR graph node representing an `IRBlock` object.
|
||||
*/
|
||||
class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
|
||||
private class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
|
||||
IRBlock block;
|
||||
|
||||
PrintableIRBlock() { this = TPrintableIRBlock(block) }
|
||||
@@ -161,7 +172,7 @@ class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
|
||||
/**
|
||||
* An IR graph node representing an `Instruction`.
|
||||
*/
|
||||
class PrintableInstruction extends PrintableIRNode, TPrintableInstruction {
|
||||
private class PrintableInstruction extends PrintableIRNode, TPrintableInstruction {
|
||||
Instruction instr;
|
||||
|
||||
PrintableInstruction() { this = TPrintableInstruction(instr) }
|
||||
@@ -224,6 +235,9 @@ private string getPaddingString(int n) {
|
||||
n > 0 and n <= maxColumnWidth() and result = getPaddingString(n - 1) + " "
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` belongs to the output graph, and its property `key` has the given `value`.
|
||||
*/
|
||||
query predicate nodes(PrintableIRNode node, string key, string value) {
|
||||
value = node.getProperty(key)
|
||||
}
|
||||
@@ -237,6 +251,10 @@ private int getSuccessorIndex(IRBlock pred, IRBlock succ) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the output graph contains an edge from `pred` to `succ`, and that edge's property `key`
|
||||
* has the given `value`.
|
||||
*/
|
||||
query predicate edges(PrintableIRBlock pred, PrintableIRBlock succ, string key, string value) {
|
||||
exists(EdgeKind kind, IRBlock predBlock, IRBlock succBlock |
|
||||
predBlock = pred.getBlock() and
|
||||
@@ -256,6 +274,9 @@ query predicate edges(PrintableIRBlock pred, PrintableIRBlock succ, string key,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `parent` is the parent node of `child` in the output graph.
|
||||
*/
|
||||
query predicate parents(PrintableIRNode child, PrintableIRNode parent) {
|
||||
parent = child.getParent()
|
||||
}
|
||||
|
||||
@@ -24,6 +24,16 @@ private Element getRealParent(Expr expr) {
|
||||
result.(Destructor).getADestruction() = expr
|
||||
}
|
||||
|
||||
IRUserVariable getIRUserVariable(Function func, Variable var) {
|
||||
result.getVariable() = var and
|
||||
result.getEnclosingFunction() = func
|
||||
}
|
||||
|
||||
IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) {
|
||||
result.getAST() = ast and
|
||||
result.getTag() = tag
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `expr` is a constant of a type that can be replaced directly with
|
||||
* its value in the IR. This does not include address constants as we have no
|
||||
|
||||
@@ -1011,7 +1011,7 @@ class TranslatedDynamicCast extends TranslatedSingleInstructionConversion {
|
||||
if resultType instanceof PointerType
|
||||
then
|
||||
if resultType.(PointerType).getBaseType() instanceof VoidType
|
||||
then result instanceof Opcode::DynamicCastToVoid
|
||||
then result instanceof Opcode::CompleteObjectAddress
|
||||
else result instanceof Opcode::CheckedConvertOrNull
|
||||
else result instanceof Opcode::CheckedConvertOrThrow
|
||||
)
|
||||
|
||||
@@ -1,3 +1,47 @@
|
||||
/**
|
||||
* Provides classes that describe the Intermediate Representation (IR) of the program.
|
||||
*
|
||||
* The IR is a representation of the semantics of the program, with very little dependence on the
|
||||
* syntax that was used to write the program. For example, in C++, the statements `i += 1;`, `i++`,
|
||||
* and `++i` all have the same semantic effect, but appear in the AST as three different types of
|
||||
* `Expr` node. In the IR, all three statements are broken down into a sequence of fundamental
|
||||
* operations similar to:
|
||||
*
|
||||
* ```
|
||||
* r1(int*) = VariableAddress[i] // Compute the address of variable `i`
|
||||
* r2(int) = Load &:r1, m0 // Load the value of `i`
|
||||
* r3(int) = Constant[1] // An integer constant with the value `1`
|
||||
* r4(int) = Add r2, r3 // Add `1` to the value of `i`
|
||||
* r5(int) = Store &r1, r4 // Store the new value back into the variable `i`
|
||||
* ```
|
||||
*
|
||||
* This allows IR-based analysis to focus on the fundamental operations, rather than having to be
|
||||
* concerned with the various ways of expressing those operations in source code.
|
||||
*
|
||||
* The key classes in the IR are:
|
||||
*
|
||||
* - `IRFunction` - Contains the IR for an entire function definition, including all of that
|
||||
* function's `Instruction`s, `IRBlock`s, and `IRVariables`.
|
||||
* - `Instruction` - A single operation in the IR. An instruction specifies the operation to be
|
||||
* performed, the operands that produce the inputs to that operation, and the type of the result
|
||||
* of the operation. Control flows from an `Instruction` to one of a set of successor
|
||||
* `Instruction`s.
|
||||
* - `Operand` - An input value of an `Instruction`. All inputs of an `Instruction` are explicitly
|
||||
* represented as `Operand`s, even if the input was implicit in the source code. An `Operand` has
|
||||
* a link to the `Instruction` that consumes its value (its "use") and a link to the `Instruction`
|
||||
* that produces its value (its "definition").
|
||||
* - `IRVariable` - A variable accessed by the IR for a particular function. An `IRVariable` is
|
||||
* created for each variable directly accessed by the function. In addition, `IRVariable`s are
|
||||
* created to represent certain temporary storage locations that do not have explicitly declared
|
||||
* variables in the source code, such as the return value of the function.
|
||||
* - `IRBlock` - A "basic block" in the control flow graph of a function. An `IRBlock` contains a
|
||||
* sequence of instructions such that control flow can only enter the block at the first
|
||||
* instruction, and can only leave the block from the last instruction.
|
||||
* - `IRType` - The type of a value accessed in the IR. Unlike the `Type` class in the AST, `IRType`
|
||||
* is language-neutral. For example, in C++, `unsigned int`, `char32_t`, and `wchar_t` might all
|
||||
* be represented as the `IRType` `uint4`, a four-byte unsigned integer.
|
||||
*/
|
||||
|
||||
import IRFunction
|
||||
import Instruction
|
||||
import IRBlock
|
||||
@@ -11,11 +55,12 @@ import Imports::MemoryAccessKind
|
||||
private newtype TIRPropertyProvider = MkIRPropertyProvider()
|
||||
|
||||
/**
|
||||
* Class that provides additional properties to be dumped for IR instructions and blocks when using
|
||||
* A class that provides additional properties to be dumped for IR instructions and blocks when using
|
||||
* the PrintIR module. Libraries that compute additional facts about IR elements can extend the
|
||||
* single instance of this class to specify the additional properties computed by the library.
|
||||
*/
|
||||
class IRPropertyProvider extends TIRPropertyProvider {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "IRPropertyProvider" }
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes describing basic blocks in the IR of a function.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
import Instruction
|
||||
private import internal.IRBlockImports as Imports
|
||||
@@ -16,15 +20,23 @@ private import Cached
|
||||
* Most consumers should use the class `IRBlock`.
|
||||
*/
|
||||
class IRBlockBase extends TIRBlock {
|
||||
/** Gets a textual representation of this block. */
|
||||
final string toString() { result = getFirstInstruction(this).toString() }
|
||||
|
||||
/** Gets the source location of the first non-`Phi` instruction in this block. */
|
||||
final Language::Location getLocation() { result = getFirstInstruction().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets a string that uniquely identifies this block within its enclosing function.
|
||||
*
|
||||
* This predicate is used by debugging and printing code only.
|
||||
*/
|
||||
final string getUniqueId() { result = getFirstInstruction(this).getUniqueId() }
|
||||
|
||||
/**
|
||||
* Gets the zero-based index of the block within its function. This is used
|
||||
* by debugging and printing code only.
|
||||
* Gets the zero-based index of the block within its function.
|
||||
*
|
||||
* This predicate is used by debugging and printing code only.
|
||||
*/
|
||||
int getDisplayIndex() {
|
||||
exists(IRConfiguration::IRConfiguration config |
|
||||
@@ -42,27 +54,51 @@ class IRBlockBase extends TIRBlock {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `index`th non-`Phi` instruction in this block.
|
||||
*/
|
||||
final Instruction getInstruction(int index) { result = getInstruction(this, index) }
|
||||
|
||||
/**
|
||||
* Get the `Phi` instructions that appear at the start of this block.
|
||||
*/
|
||||
final PhiInstruction getAPhiInstruction() {
|
||||
Construction::getPhiInstructionBlockStart(result) = getFirstInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the instructions in this block, including `Phi` instructions.
|
||||
*/
|
||||
final Instruction getAnInstruction() {
|
||||
result = getInstruction(_) or
|
||||
result = getAPhiInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the first non-`Phi` instruction in this block.
|
||||
*/
|
||||
final Instruction getFirstInstruction() { result = getFirstInstruction(this) }
|
||||
|
||||
/**
|
||||
* Gets the last instruction in this block.
|
||||
*/
|
||||
final Instruction getLastInstruction() { result = getInstruction(getInstructionCount() - 1) }
|
||||
|
||||
/**
|
||||
* Gets the number of non-`Phi` instructions in this block.
|
||||
*/
|
||||
final int getInstructionCount() { result = getInstructionCount(this) }
|
||||
|
||||
/**
|
||||
* Gets the `IRFunction` that contains this block.
|
||||
*/
|
||||
final IRFunction getEnclosingIRFunction() {
|
||||
result = getFirstInstruction(this).getEnclosingIRFunction()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `Function` that contains this block.
|
||||
*/
|
||||
final Language::Function getEnclosingFunction() {
|
||||
result = getFirstInstruction(this).getEnclosingFunction()
|
||||
}
|
||||
@@ -74,20 +110,57 @@ class IRBlockBase extends TIRBlock {
|
||||
* instruction of another block.
|
||||
*/
|
||||
class IRBlock extends IRBlockBase {
|
||||
/**
|
||||
* Gets the blocks to which control flows directly from this block.
|
||||
*/
|
||||
final IRBlock getASuccessor() { blockSuccessor(this, result) }
|
||||
|
||||
/**
|
||||
* Gets the blocks from which control flows directly to this block.
|
||||
*/
|
||||
final IRBlock getAPredecessor() { blockSuccessor(result, this) }
|
||||
|
||||
/**
|
||||
* Gets the block to which control flows directly from this block along an edge of kind `kind`.
|
||||
*/
|
||||
final IRBlock getSuccessor(EdgeKind kind) { blockSuccessor(this, result, kind) }
|
||||
|
||||
/**
|
||||
* Gets the block to which control flows directly from this block along a back edge of kind
|
||||
* `kind`.
|
||||
*/
|
||||
final IRBlock getBackEdgeSuccessor(EdgeKind kind) { backEdgeSuccessor(this, result, kind) }
|
||||
|
||||
/**
|
||||
* Holds if this block immediately dominates `block`.
|
||||
*
|
||||
* Block `A` immediate dominates block `B` if block `A` strictly dominates block `B` and block `B`
|
||||
* is a direct successor of block `A`.
|
||||
*/
|
||||
final predicate immediatelyDominates(IRBlock block) { blockImmediatelyDominates(this, block) }
|
||||
|
||||
/**
|
||||
* Holds if this block strictly dominates `block`.
|
||||
*
|
||||
* Block `A` strictly dominates block `B` if block `A` dominates block `B` and blocks `A` and `B`
|
||||
* are not the same block.
|
||||
*/
|
||||
final predicate strictlyDominates(IRBlock block) { blockImmediatelyDominates+(this, block) }
|
||||
|
||||
/**
|
||||
* Holds if this block dominates `block`.
|
||||
*
|
||||
* Block `A` dominates block `B` if any control flow path from the entry block of the function to
|
||||
* block `B` must pass through block `A`. A block always dominates itself.
|
||||
*/
|
||||
final predicate dominates(IRBlock block) { strictlyDominates(block) or this = block }
|
||||
|
||||
/**
|
||||
* Gets the set of blocks on the dominance frontier of this block.
|
||||
*
|
||||
* The dominance frontier of block `A` is the set of blocks `B` such that block `A` does not
|
||||
* dominate block `B`, but block `A` does dominate an immediate predecessor of block `B`.
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock dominanceFrontier() {
|
||||
dominates(result.getAPredecessor()) and
|
||||
@@ -95,7 +168,7 @@ class IRBlock extends IRBlockBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this block is reachable from the entry point of its function
|
||||
* Holds if this block is reachable from the entry block of its function.
|
||||
*/
|
||||
final predicate isReachableFromFunctionEntry() {
|
||||
this = getEnclosingIRFunction().getEntryBlock() or
|
||||
@@ -210,4 +283,4 @@ private module Cached {
|
||||
idominance(isEntryBlock/1, blockSuccessor/2)(_, dominator, block)
|
||||
}
|
||||
|
||||
Instruction getFirstInstruction(TIRBlock block) { block = MkIRBlock(result) }
|
||||
private Instruction getFirstInstruction(TIRBlock block) { block = MkIRBlock(result) }
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Provides the class `IRFunction`, which represents the Intermediate Representation for the
|
||||
* definition of a function.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
private import internal.IRFunctionImports as Imports
|
||||
import Imports::IRFunctionBase
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes that represent variables accessed by the IR.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
import IRFunction
|
||||
private import internal.IRVariableImports as Imports
|
||||
@@ -7,15 +11,11 @@ private import Imports::TTempVariableTag
|
||||
private import Imports::TIRVariable
|
||||
private import Imports::IRType
|
||||
|
||||
IRUserVariable getIRUserVariable(Language::Function func, Language::Variable var) {
|
||||
result.getVariable() = var and
|
||||
result.getEnclosingFunction() = func
|
||||
}
|
||||
|
||||
/**
|
||||
* A variable referenced by the IR for a function. The variable may be a user-declared variable
|
||||
* (`IRUserVariable`) or a temporary variable generated by the AST-to-IR translation
|
||||
* (`IRTempVariable`).
|
||||
* A variable referenced by the IR for a function.
|
||||
*
|
||||
* The variable may be a user-declared variable (`IRUserVariable`) or a temporary variable generated
|
||||
* by the AST-to-IR translation (`IRTempVariable`).
|
||||
*/
|
||||
class IRVariable extends TIRVariable {
|
||||
Language::Function func;
|
||||
@@ -27,6 +27,7 @@ class IRVariable extends TIRVariable {
|
||||
this = TIRDynamicInitializationFlag(func, _, _)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { none() }
|
||||
|
||||
/**
|
||||
@@ -162,20 +163,26 @@ class IRGeneratedVariable extends IRVariable {
|
||||
|
||||
override string getUniqueId() { none() }
|
||||
|
||||
/**
|
||||
* Gets a string containing the source code location of the AST that generated this variable.
|
||||
*
|
||||
* This is used by debugging and printing code only.
|
||||
*/
|
||||
final string getLocationString() {
|
||||
result =
|
||||
ast.getLocation().getStartLine().toString() + ":" +
|
||||
ast.getLocation().getStartColumn().toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string that is combined with the location of the variable to generate the string
|
||||
* representation of this variable.
|
||||
*
|
||||
* This is used by debugging and printing code only.
|
||||
*/
|
||||
string getBaseString() { none() }
|
||||
}
|
||||
|
||||
IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
|
||||
result.getAST() = ast and
|
||||
result.getTag() = tag
|
||||
}
|
||||
|
||||
/**
|
||||
* A temporary variable introduced by IR construction. The most common examples are the variable
|
||||
* generated to hold the return value of a function, or the variable generated to hold the result of
|
||||
@@ -190,6 +197,10 @@ class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVa
|
||||
result = "Temp: " + Construction::getTempVariableUniqueId(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the "tag" object that differentiates this temporary variable from other temporary
|
||||
* variables generated for the same AST.
|
||||
*/
|
||||
final TempVariableTag getTag() { result = tag }
|
||||
|
||||
override string getBaseString() { result = "#temp" }
|
||||
@@ -253,6 +264,9 @@ class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
|
||||
final override string getBaseString() { result = "#string" }
|
||||
|
||||
/**
|
||||
* Gets the AST of the string literal represented by this `IRStringLiteral`.
|
||||
*/
|
||||
final Language::StringLiteral getLiteral() { result = literal }
|
||||
}
|
||||
|
||||
@@ -270,6 +284,9 @@ class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitial
|
||||
|
||||
final override string toString() { result = var.toString() + "#init" }
|
||||
|
||||
/**
|
||||
* Gets variable whose initialization is guarded by this flag.
|
||||
*/
|
||||
final Language::Variable getVariable() { result = var }
|
||||
|
||||
final override string getUniqueId() {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes that represent the input values of IR instructions.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
private import Instruction
|
||||
private import IRBlock
|
||||
@@ -78,10 +82,17 @@ private PhiOperandBase phiOperand(
|
||||
* A source operand of an `Instruction`. The operand represents a value consumed by the instruction.
|
||||
*/
|
||||
class Operand extends TOperand {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Operand" }
|
||||
|
||||
/**
|
||||
* Gets the location of the source code for this operand.
|
||||
*/
|
||||
final Language::Location getLocation() { result = getUse().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the function that contains this operand.
|
||||
*/
|
||||
final IRFunction getEnclosingIRFunction() { result = getUse().getEnclosingIRFunction() }
|
||||
|
||||
/**
|
||||
@@ -270,6 +281,9 @@ class NonPhiOperand extends Operand {
|
||||
|
||||
final override int getDumpSortOrder() { result = tag.getSortOrder() }
|
||||
|
||||
/**
|
||||
* Gets the `OperandTag` that specifies how this operand is used by its `Instruction`.
|
||||
*/
|
||||
final OperandTag getOperandTag() { result = tag }
|
||||
}
|
||||
|
||||
@@ -292,6 +306,9 @@ class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A memory operand other than the operand of a `Phi` instruction.
|
||||
*/
|
||||
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase {
|
||||
override MemoryOperandTag tag;
|
||||
|
||||
@@ -313,6 +330,9 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOper
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A memory operand whose type may be different from the type of the result of its definition.
|
||||
*/
|
||||
class TypedOperand extends NonPhiMemoryOperand {
|
||||
override TypedOperandTag tag;
|
||||
|
||||
@@ -416,6 +436,9 @@ class PositionalArgumentOperand extends ArgumentOperand {
|
||||
final int getIndex() { result = tag.getArgIndex() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An operand representing memory read as a side effect of evaluating another instruction.
|
||||
*/
|
||||
class SideEffectOperand extends TypedOperand {
|
||||
override SideEffectOperandTag tag;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* Outputs a representation of the IR as a control flow graph.
|
||||
*
|
||||
* This file contains the actual implementation of `PrintIR.ql`. For test cases and very small
|
||||
* databases, `PrintIR.ql` can be run directly to dump the IR for the entire database. For most
|
||||
* uses, however, it is better to write a query that imports `PrintIR.qll`, extends
|
||||
* `PrintIRConfiguration`, and overrides `shouldPrintFunction()` to select a subset of functions to
|
||||
* dump.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
private import IR
|
||||
private import internal.PrintIRImports as Imports
|
||||
@@ -9,6 +19,7 @@ private newtype TPrintIRConfiguration = MkPrintIRConfiguration()
|
||||
* The query can extend this class to control which functions are printed.
|
||||
*/
|
||||
class PrintIRConfiguration extends TPrintIRConfiguration {
|
||||
/** Gets a textual representation of this configuration. */
|
||||
string toString() { result = "PrintIRConfiguration" }
|
||||
|
||||
/**
|
||||
@@ -47,7 +58,7 @@ private newtype TPrintableIRNode =
|
||||
/**
|
||||
* A node to be emitted in the IR graph.
|
||||
*/
|
||||
abstract class PrintableIRNode extends TPrintableIRNode {
|
||||
abstract private class PrintableIRNode extends TPrintableIRNode {
|
||||
abstract string toString();
|
||||
|
||||
/**
|
||||
@@ -98,7 +109,7 @@ abstract class PrintableIRNode extends TPrintableIRNode {
|
||||
/**
|
||||
* An IR graph node representing a `IRFunction` object.
|
||||
*/
|
||||
class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
|
||||
private class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
|
||||
IRFunction irFunc;
|
||||
|
||||
PrintableIRFunction() { this = TPrintableIRFunction(irFunc) }
|
||||
@@ -129,7 +140,7 @@ class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
|
||||
/**
|
||||
* An IR graph node representing an `IRBlock` object.
|
||||
*/
|
||||
class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
|
||||
private class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
|
||||
IRBlock block;
|
||||
|
||||
PrintableIRBlock() { this = TPrintableIRBlock(block) }
|
||||
@@ -161,7 +172,7 @@ class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
|
||||
/**
|
||||
* An IR graph node representing an `Instruction`.
|
||||
*/
|
||||
class PrintableInstruction extends PrintableIRNode, TPrintableInstruction {
|
||||
private class PrintableInstruction extends PrintableIRNode, TPrintableInstruction {
|
||||
Instruction instr;
|
||||
|
||||
PrintableInstruction() { this = TPrintableInstruction(instr) }
|
||||
@@ -224,6 +235,9 @@ private string getPaddingString(int n) {
|
||||
n > 0 and n <= maxColumnWidth() and result = getPaddingString(n - 1) + " "
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` belongs to the output graph, and its property `key` has the given `value`.
|
||||
*/
|
||||
query predicate nodes(PrintableIRNode node, string key, string value) {
|
||||
value = node.getProperty(key)
|
||||
}
|
||||
@@ -237,6 +251,10 @@ private int getSuccessorIndex(IRBlock pred, IRBlock succ) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the output graph contains an edge from `pred` to `succ`, and that edge's property `key`
|
||||
* has the given `value`.
|
||||
*/
|
||||
query predicate edges(PrintableIRBlock pred, PrintableIRBlock succ, string key, string value) {
|
||||
exists(EdgeKind kind, IRBlock predBlock, IRBlock succBlock |
|
||||
predBlock = pred.getBlock() and
|
||||
@@ -256,6 +274,9 @@ query predicate edges(PrintableIRBlock pred, PrintableIRBlock succ, string key,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `parent` is the parent node of `child` in the output graph.
|
||||
*/
|
||||
query predicate parents(PrintableIRNode child, PrintableIRNode parent) {
|
||||
parent = child.getParent()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes and predicates for recognizing floating point expressions which cannot be NaN.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
private import semmle.code.cpp.rangeanalysis.RangeSSA
|
||||
|
||||
|
||||
@@ -11,8 +11,17 @@ private float lowerBoundFC(Expr expr) { result = lowerBound(expr.getFullyConvert
|
||||
/** Gets the upper bound of the fully converted expression. */
|
||||
private float upperBoundFC(Expr expr) { result = upperBound(expr.getFullyConverted()) }
|
||||
|
||||
/**
|
||||
* Describes which side of a pointless comparison is known to be smaller.
|
||||
*/
|
||||
newtype SmallSide =
|
||||
/**
|
||||
* Represents that the left side of a pointless comparison is known to be smaller.
|
||||
*/
|
||||
LeftIsSmaller() or
|
||||
/**
|
||||
* Represents that the right side of a pointless comparison is known to be smaller.
|
||||
*/
|
||||
RightIsSmaller()
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,13 @@ import cpp
|
||||
* relation) or 'non-strict' (a `<=` or `>=` relation).
|
||||
*/
|
||||
newtype RelationStrictness =
|
||||
/**
|
||||
* Represents that a relation is 'strict' (that is, a `<` or `>` relation).
|
||||
*/
|
||||
Strict() or
|
||||
/**
|
||||
* Represents that a relation is 'non-strict' (that is, a `<=` or `>=` relation)
|
||||
*/
|
||||
Nonstrict()
|
||||
|
||||
/**
|
||||
@@ -13,7 +19,13 @@ newtype RelationStrictness =
|
||||
* relation) or 'lesser' (a `<` or `<=` relation).
|
||||
*/
|
||||
newtype RelationDirection =
|
||||
/**
|
||||
* Represents that a relation is 'greater' (that is, a `>` or `>=` relation).
|
||||
*/
|
||||
Greater() or
|
||||
/**
|
||||
* Represents that a relation is 'lesser' (that is, a `<` or `<=` relation).
|
||||
*/
|
||||
Lesser()
|
||||
|
||||
private RelationStrictness negateStrictness(RelationStrictness strict) {
|
||||
@@ -28,12 +40,18 @@ private RelationDirection negateDirection(RelationDirection dir) {
|
||||
dir = Lesser() and result = Greater()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `dir` is `Greater` (that is, a `>` or `>=` relation)
|
||||
*/
|
||||
boolean directionIsGreater(RelationDirection dir) {
|
||||
dir = Greater() and result = true
|
||||
or
|
||||
dir = Lesser() and result = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `dir` is `Lesser` (that is, a `<` or `<=` relation)
|
||||
*/
|
||||
boolean directionIsLesser(RelationDirection dir) {
|
||||
dir = Greater() and result = false
|
||||
or
|
||||
|
||||
@@ -25,6 +25,10 @@ import semmle.code.cpp.controlflow.Dominance
|
||||
import semmle.code.cpp.controlflow.SSAUtils
|
||||
private import RangeAnalysisUtils
|
||||
|
||||
/**
|
||||
* The SSA logic comes in two versions: the standard SSA and range-analysis RangeSSA.
|
||||
* This class provides the range-analysis SSA logic.
|
||||
*/
|
||||
library class RangeSSA extends SSAHelper {
|
||||
RangeSSA() { this = 1 }
|
||||
|
||||
@@ -84,6 +88,7 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
|
||||
/** Gets the control flow node for this definition. */
|
||||
ControlFlowNode getDefinition() { result = this }
|
||||
|
||||
/** Gets the basic block containing this definition. */
|
||||
BasicBlock getBasicBlock() { result.contains(getDefinition()) }
|
||||
|
||||
/** Whether this definition is a phi node for variable `v`. */
|
||||
@@ -97,11 +102,13 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
|
||||
guard_defn(v, guard, this, branch)
|
||||
}
|
||||
|
||||
/** Gets the primary location of this definition. */
|
||||
Location getLocation() { result = this.(ControlFlowNode).getLocation() }
|
||||
|
||||
/** Whether this definition is from a parameter */
|
||||
predicate definedByParameter(Parameter p) { this = p.getFunction().getEntryPoint() }
|
||||
|
||||
/** Gets a definition of `v` that is a phi input for this basic block. */
|
||||
RangeSsaDefinition getAPhiInput(StackVariable v) {
|
||||
this.isPhiNode(v) and
|
||||
exists(BasicBlock pred |
|
||||
@@ -153,6 +160,9 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this definition of the variable `v` reached the end of the basic block `b`.
|
||||
*/
|
||||
predicate reachesEndOfBB(StackVariable v, BasicBlock b) {
|
||||
exists(RangeSSA x | x.ssaDefinitionReachesEndOfBB(v, this, b))
|
||||
}
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
// Common predicates relating to encryption in C and C++
|
||||
/**
|
||||
* Provides predicates relating to encryption in C and C++.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/** A blacklist of algorithms that are known to be insecure */
|
||||
string algorithmBlacklist() {
|
||||
/**
|
||||
* Gets the name of an algorithm that is known to be insecure.
|
||||
*/
|
||||
string getAnInsecureAlgorithmName() {
|
||||
result = "DES" or
|
||||
result = "RC2" or
|
||||
result = "RC4" or
|
||||
@@ -10,29 +15,36 @@ string algorithmBlacklist() {
|
||||
result = "ARCFOUR" // a variant of RC4
|
||||
}
|
||||
|
||||
// these are only bad if they're being used for encryption, and it's
|
||||
// hard to know when that's happening
|
||||
string hashAlgorithmBlacklist() {
|
||||
/**
|
||||
* Gets the name of a hash algorithm that is insecure if it is being used for
|
||||
* encryption (but it is hard to know when that is happening).
|
||||
*/
|
||||
string getAnInsecureHashAlgorithmName() {
|
||||
result = "SHA1" or
|
||||
result = "MD5"
|
||||
}
|
||||
|
||||
/** A regex for matching strings that look like they contain a blacklisted algorithm */
|
||||
string algorithmBlacklistRegex() {
|
||||
/**
|
||||
* Gets the regular expression used for matching strings that look like they
|
||||
* contain an algorithm that is known to be insecure.
|
||||
*/
|
||||
string getInsecureAlgorithmRegex() {
|
||||
result =
|
||||
// algorithms usually appear in names surrounded by characters that are not
|
||||
// alphabetical characters in the same case. This handles the upper and lower
|
||||
// case cases
|
||||
"(^|.*[^A-Z])(" + strictconcat(algorithmBlacklist(), "|") + ")([^A-Z].*|$)" + "|" +
|
||||
"(^|.*[^A-Z])(" + strictconcat(getAnInsecureAlgorithmName(), "|") + ")([^A-Z].*|$)" + "|" +
|
||||
// for lowercase, we want to be careful to avoid being confused by camelCase
|
||||
// hence we require two preceding uppercase letters to be sure of a case switch,
|
||||
// or a preceding non-alphabetic character
|
||||
"(^|.*[A-Z]{2}|.*[^a-zA-Z])(" + strictconcat(algorithmBlacklist().toLowerCase(), "|") +
|
||||
"(^|.*[A-Z]{2}|.*[^a-zA-Z])(" + strictconcat(getAnInsecureAlgorithmName().toLowerCase(), "|") +
|
||||
")([^a-z].*|$)"
|
||||
}
|
||||
|
||||
/** A whitelist of algorithms that are known to be secure */
|
||||
string algorithmWhitelist() {
|
||||
/**
|
||||
* Gets the name of an algorithm that is known to be secure.
|
||||
*/
|
||||
string getASecureAlgorithmName() {
|
||||
result = "RSA" or
|
||||
result = "SHA256" or
|
||||
result = "CCM" or
|
||||
@@ -42,17 +54,47 @@ string algorithmWhitelist() {
|
||||
result = "ECIES"
|
||||
}
|
||||
|
||||
/** A regex for matching strings that look like they contain a whitelisted algorithm */
|
||||
string algorithmWhitelistRegex() {
|
||||
// The implementation of this is a duplicate of algorithmBlacklistRegex, as it isn't
|
||||
// possible to have string -> string functions at the moment
|
||||
// algorithms usually appear in names surrounded by characters that are not
|
||||
// alphabetical characters in the same case. This handles the upper and lower
|
||||
// case cases
|
||||
result = "(^|.*[^A-Z])" + algorithmWhitelist() + "([^A-Z].*|$)"
|
||||
or
|
||||
// for lowercase, we want to be careful to avoid being confused by camelCase
|
||||
// hence we require two preceding uppercase letters to be sure of a case switch,
|
||||
// or a preceding non-alphabetic character
|
||||
result = "(^|.*[A-Z]{2}|.*[^a-zA-Z])" + algorithmWhitelist().toLowerCase() + "([^a-z].*|$)"
|
||||
/**
|
||||
* Gets a regular expression for matching strings that look like they
|
||||
* contain an algorithm that is known to be secure.
|
||||
*/
|
||||
string getSecureAlgorithmRegex() {
|
||||
result =
|
||||
// algorithms usually appear in names surrounded by characters that are not
|
||||
// alphabetical characters in the same case. This handles the upper and lower
|
||||
// case cases
|
||||
"(^|.*[^A-Z])(" + strictconcat(getASecureAlgorithmName(), "|") + ")([^A-Z].*|$)" + "|" +
|
||||
// for lowercase, we want to be careful to avoid being confused by camelCase
|
||||
// hence we require two preceding uppercase letters to be sure of a case
|
||||
// switch, or a preceding non-alphabetic character
|
||||
"(^|.*[A-Z]{2}|.*[^a-zA-Z])(" + strictconcat(getASecureAlgorithmName().toLowerCase(), "|") +
|
||||
")([^a-z].*|$)"
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Terminology has been updated. Use `getAnInsecureAlgorithmName()`
|
||||
* instead.
|
||||
*/
|
||||
deprecated string algorithmBlacklist() { result = getAnInsecureAlgorithmName() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Terminology has been updated. Use
|
||||
* `getAnInsecureHashAlgorithmName()` instead.
|
||||
*/
|
||||
deprecated string hashAlgorithmBlacklist() { result = getAnInsecureHashAlgorithmName() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Terminology has been updated. Use `getInsecureAlgorithmRegex()` instead.
|
||||
*/
|
||||
deprecated string algorithmBlacklistRegex() { result = getInsecureAlgorithmRegex() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Terminology has been updated. Use `getASecureAlgorithmName()`
|
||||
* instead.
|
||||
*/
|
||||
deprecated string algorithmWhitelist() { result = getASecureAlgorithmName() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Terminology has been updated. Use `getSecureAlgorithmRegex()` instead.
|
||||
*/
|
||||
deprecated string algorithmWhitelistRegex() { result = getSecureAlgorithmRegex() }
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
/**
|
||||
* Provides predicates for identifying functions that wrap other functions,
|
||||
* passing the same arguments from the outer call into the inner call. In the
|
||||
* following example `MyMalloc` wraps a call to `malloc`, passing in the `size`
|
||||
* parameter:
|
||||
* ```
|
||||
* void *MyMalloc(size_t size)
|
||||
* {
|
||||
* void *ptr = malloc(size);
|
||||
*
|
||||
* // ... additional logic?
|
||||
*
|
||||
* return ptr;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import PrintfLike
|
||||
private import TaintTracking
|
||||
@@ -152,6 +169,9 @@ abstract class FunctionWithWrappers extends Function {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A `printf`-like formatting function.
|
||||
*/
|
||||
class PrintfLikeFunction extends FunctionWithWrappers {
|
||||
PrintfLikeFunction() { printfLikeFunction(this, _) }
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
/**
|
||||
* Provides predicates for reasoning about when the value of an expression is
|
||||
* guarded by an operation such as `<`, which confines its range.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.controlflow.Dominance
|
||||
|
||||
/*
|
||||
* Guarding
|
||||
/**
|
||||
* Holds if the value of `use` is guarded using `abs`.
|
||||
*/
|
||||
|
||||
/** is the size of this use guarded using 'abs'? */
|
||||
predicate guardedAbs(Operation e, Expr use) {
|
||||
exists(FunctionCall fc | fc.getTarget().getName() = "abs" |
|
||||
fc.getArgument(0).getAChild*() = use and
|
||||
@@ -13,7 +16,10 @@ predicate guardedAbs(Operation e, Expr use) {
|
||||
)
|
||||
}
|
||||
|
||||
/** This is `BasicBlock.getNode`, restricted to `Stmt` for performance. */
|
||||
/**
|
||||
* Gets the position of `stmt` in basic block `block` (this is a thin layer
|
||||
* over `BasicBlock.getNode`, intended to improve performance).
|
||||
*/
|
||||
pragma[noinline]
|
||||
private int getStmtIndexInBlock(BasicBlock block, Stmt stmt) { block.getNode(result) = stmt }
|
||||
|
||||
@@ -30,7 +36,9 @@ private predicate stmtDominates(Stmt dominator, Stmt dominated) {
|
||||
bbStrictlyDominates(dominator.getBasicBlock(), dominated.getBasicBlock())
|
||||
}
|
||||
|
||||
/** is the size of this use guarded to be less than something? */
|
||||
/**
|
||||
* Holds if the value of `use` is guarded to be less than something.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate guardedLesser(Operation e, Expr use) {
|
||||
exists(IfStmt c, RelationalOperation guard |
|
||||
@@ -54,7 +62,9 @@ predicate guardedLesser(Operation e, Expr use) {
|
||||
guardedAbs(e, use)
|
||||
}
|
||||
|
||||
/** is the size of this use guarded to be greater than something? */
|
||||
/**
|
||||
* Holds if the value of `use` is guarded to be greater than something.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate guardedGreater(Operation e, Expr use) {
|
||||
exists(IfStmt c, RelationalOperation guard |
|
||||
@@ -78,10 +88,14 @@ predicate guardedGreater(Operation e, Expr use) {
|
||||
guardedAbs(e, use)
|
||||
}
|
||||
|
||||
/** a use of a given variable */
|
||||
/**
|
||||
* Gets a use of a given variable `v`.
|
||||
*/
|
||||
VariableAccess varUse(LocalScopeVariable v) { result = v.getAnAccess() }
|
||||
|
||||
/** is e not guarded against overflow by use? */
|
||||
/**
|
||||
* Holds if `e` is not guarded against overflow by `use`.
|
||||
*/
|
||||
predicate missingGuardAgainstOverflow(Operation e, VariableAccess use) {
|
||||
use = e.getAnOperand() and
|
||||
exists(LocalScopeVariable v | use.getTarget() = v |
|
||||
@@ -100,7 +114,9 @@ predicate missingGuardAgainstOverflow(Operation e, VariableAccess use) {
|
||||
)
|
||||
}
|
||||
|
||||
/** is e not guarded against underflow by use? */
|
||||
/**
|
||||
* Holds if `e` is not guarded against underflow by `use`.
|
||||
*/
|
||||
predicate missingGuardAgainstUnderflow(Operation e, VariableAccess use) {
|
||||
use = e.getAnOperand() and
|
||||
exists(LocalScopeVariable v | use.getTarget() = v |
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
/**
|
||||
* Provides a predicate for identifying formatting functions like `printf`.
|
||||
*
|
||||
* Consider using the newer model in
|
||||
* `semmle.code.cpp.models.interfaces.FormattingFunction` directly instead of
|
||||
* this library.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.commons.Printf
|
||||
import external.ExternalArtifact
|
||||
|
||||
/**
|
||||
* Holds if `func` is a `printf`-like formatting function and `formatArg` is
|
||||
* the index of the format string argument.
|
||||
*/
|
||||
predicate printfLikeFunction(Function func, int formatArg) {
|
||||
formatArg = func.(FormattingFunction).getFormatParameterIndex() and
|
||||
not func instanceof UserDefinedFormattingFunction
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
/**
|
||||
* Provides classes for heuristically identifying variables and functions that
|
||||
* might contain or return a password or other sensitive information.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/**
|
||||
* Holds if the name `s` suggests something might contain or return a password
|
||||
* or other sensitive information.
|
||||
*/
|
||||
bindingset[s]
|
||||
private predicate suspicious(string s) {
|
||||
(
|
||||
@@ -16,14 +25,23 @@ private predicate suspicious(string s) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A variable that might contain a password or other sensitive information.
|
||||
*/
|
||||
class SensitiveVariable extends Variable {
|
||||
SensitiveVariable() { suspicious(getName().toLowerCase()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A function that might return a password or other sensitive information.
|
||||
*/
|
||||
class SensitiveFunction extends Function {
|
||||
SensitiveFunction() { suspicious(getName().toLowerCase()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression whose value might be a password or other sensitive information.
|
||||
*/
|
||||
class SensitiveExpr extends Expr {
|
||||
SensitiveExpr() {
|
||||
this.(VariableAccess).getTarget() instanceof SensitiveVariable or
|
||||
|
||||
@@ -18,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.
|
||||
|
||||
@@ -154,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.
|
||||
@@ -212,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.
|
||||
@@ -298,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.
|
||||
@@ -397,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) }
|
||||
|
||||
@@ -462,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)) }
|
||||
@@ -479,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.
|
||||
@@ -574,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;" }
|
||||
|
||||
@@ -606,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;" }
|
||||
|
||||
@@ -639,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 != "" }
|
||||
@@ -667,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.
|
||||
@@ -715,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) }
|
||||
|
||||
@@ -764,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.
|
||||
@@ -851,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.
|
||||
@@ -1082,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
|
||||
@@ -1435,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.
|
||||
@@ -1646,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.
|
||||
@@ -1699,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 { ... }" }
|
||||
|
||||
@@ -1774,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1791,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)) }
|
||||
|
||||
@@ -1822,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1859,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1883,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1895,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.
|
||||
@@ -1976,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 = ";" }
|
||||
|
||||
@@ -1996,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" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2013,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) }
|
||||
@@ -2032,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
|
||||
|
||||
@@ -420,7 +420,7 @@ function_deleted(unique int id: @function ref);
|
||||
|
||||
function_defaulted(unique int id: @function ref);
|
||||
|
||||
|
||||
member_function_this_type(unique int id: @function ref, int this_type: @type ref);
|
||||
|
||||
#keyset[id, type_id]
|
||||
fun_decls(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
import cpp
|
||||
|
||||
from Expr e
|
||||
select e, e.getCanonicalQLClass()
|
||||
select e, e.getAPrimaryQlClass()
|
||||
|
||||
@@ -2,15 +2,7 @@ uniqueEnclosingCallable
|
||||
| C.cpp:37:24:37:33 | 0 | Node should have one enclosing callable but has 0. |
|
||||
| C.cpp:37:24:37:33 | new | Node should have one enclosing callable but has 0. |
|
||||
uniqueTypeBound
|
||||
| complex.cpp:22:11:22:17 | constructor init of field f [post-this] | Node should have one type bound but has 0. |
|
||||
| complex.cpp:22:11:22:17 | constructor init of field f [pre-this] | Node should have one type bound but has 0. |
|
||||
| complex.cpp:25:7:25:7 | constructor init of field inner [post-this] | Node should have one type bound but has 0. |
|
||||
| complex.cpp:25:7:25:7 | constructor init of field inner [pre-this] | Node should have one type bound but has 0. |
|
||||
uniqueTypeRepr
|
||||
| complex.cpp:22:11:22:17 | constructor init of field f [post-this] | Node should have one type representation but has 0. |
|
||||
| complex.cpp:22:11:22:17 | constructor init of field f [pre-this] | Node should have one type representation but has 0. |
|
||||
| complex.cpp:25:7:25:7 | constructor init of field inner [post-this] | Node should have one type representation but has 0. |
|
||||
| complex.cpp:25:7:25:7 | constructor init of field inner [pre-this] | Node should have one type representation but has 0. |
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
uniqueNodeToString
|
||||
|
||||
@@ -4867,12 +4867,12 @@ ir.cpp:
|
||||
# 863| r863_1(glval<void *>) = VariableAddress[pv] :
|
||||
# 863| r863_2(glval<PolymorphicBase *>) = VariableAddress[pb] :
|
||||
# 863| r863_3(PolymorphicBase *) = Load : &:r863_2, ~m?
|
||||
# 863| r863_4(void *) = DynamicCastToVoid : r863_3
|
||||
# 863| r863_4(void *) = CompleteObjectAddress : r863_3
|
||||
# 863| mu863_5(void *) = Store : &:r863_1, r863_4
|
||||
# 864| r864_1(glval<void *>) = VariableAddress[pcv] :
|
||||
# 864| r864_2(glval<PolymorphicDerived *>) = VariableAddress[pd] :
|
||||
# 864| r864_3(PolymorphicDerived *) = Load : &:r864_2, ~m?
|
||||
# 864| r864_4(void *) = DynamicCastToVoid : r864_3
|
||||
# 864| r864_4(void *) = CompleteObjectAddress : r864_3
|
||||
# 864| mu864_5(void *) = Store : &:r864_1, r864_4
|
||||
# 865| v865_1(void) = NoOp :
|
||||
# 849| v849_4(void) = ReturnVoid :
|
||||
|
||||
@@ -231,8 +231,10 @@
|
||||
| file://:0:0:0:0 | const lambda [] type at line 9, col. 5 * |
|
||||
| file://:0:0:0:0 | const lambda [] type at line 9, col. 15 |
|
||||
| file://:0:0:0:0 | const lambda [] type at line 9, col. 15 & |
|
||||
| file://:0:0:0:0 | const lambda [] type at line 9, col. 15 * |
|
||||
| file://:0:0:0:0 | const lambda [] type at line 15, col. 5 |
|
||||
| file://:0:0:0:0 | const lambda [] type at line 15, col. 5 & |
|
||||
| file://:0:0:0:0 | const lambda [] type at line 15, col. 5 * |
|
||||
| file://:0:0:0:0 | const lambda [] type at line 22, col. 19 |
|
||||
| file://:0:0:0:0 | const lambda [] type at line 22, col. 19 & |
|
||||
| file://:0:0:0:0 | const lambda [] type at line 22, col. 19 * |
|
||||
@@ -277,8 +279,10 @@
|
||||
| file://:0:0:0:0 | lambda [] type at line 9, col. 5 * |
|
||||
| file://:0:0:0:0 | lambda [] type at line 9, col. 15 & |
|
||||
| file://:0:0:0:0 | lambda [] type at line 9, col. 15 && |
|
||||
| file://:0:0:0:0 | lambda [] type at line 9, col. 15 * |
|
||||
| file://:0:0:0:0 | lambda [] type at line 15, col. 5 & |
|
||||
| file://:0:0:0:0 | lambda [] type at line 15, col. 5 && |
|
||||
| file://:0:0:0:0 | lambda [] type at line 15, col. 5 * |
|
||||
| file://:0:0:0:0 | lambda [] type at line 22, col. 19 & |
|
||||
| file://:0:0:0:0 | lambda [] type at line 22, col. 19 && |
|
||||
| file://:0:0:0:0 | lambda [] type at line 22, col. 19 * |
|
||||
|
||||
129
cpp/ql/test/library-tests/members/this/test.cpp
Normal file
129
cpp/ql/test/library-tests/members/this/test.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
|
||||
int global;
|
||||
|
||||
class C {
|
||||
int x;
|
||||
|
||||
public:
|
||||
|
||||
void f1() {
|
||||
// Implicit dereference of `this.`
|
||||
x++;
|
||||
}
|
||||
|
||||
void f2() {
|
||||
// Explicit dereference of `this.`
|
||||
this->x++;
|
||||
}
|
||||
|
||||
int f3() const {
|
||||
// We expect the type of `this` to be const-qualified.
|
||||
return x;
|
||||
}
|
||||
|
||||
int f4() volatile {
|
||||
// We expect the type of `this` to be volatile-qualified.
|
||||
return x;
|
||||
}
|
||||
|
||||
int f5() const volatile {
|
||||
// We expect the type of `this` to be qualified as both const and volatile.
|
||||
return x;
|
||||
}
|
||||
|
||||
void f6() {
|
||||
// No use of `this`, but we still expect to be able to get its type.
|
||||
global++;
|
||||
}
|
||||
|
||||
float f7() const & {
|
||||
// We expect the type of `this` to be const-qualified.
|
||||
return x;
|
||||
}
|
||||
|
||||
float f8() && {
|
||||
// We expect the type of `this` to be unqualified.
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
// We want to test that D* is in the database even when there's no use of it,
|
||||
// not even through an implicit dereference of `this`.
|
||||
class D {
|
||||
void f() {
|
||||
global++;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class InstantiatedTemplateClass {
|
||||
int x;
|
||||
|
||||
public:
|
||||
|
||||
void f1() {
|
||||
// Implicit dereference of `this.`
|
||||
x++;
|
||||
}
|
||||
|
||||
void f2() {
|
||||
// Explicit dereference of `this.`
|
||||
this->x++;
|
||||
}
|
||||
|
||||
int f3() const {
|
||||
// We expect the type of `this` to be const-qualified.
|
||||
return x;
|
||||
}
|
||||
|
||||
int f4() volatile {
|
||||
// We expect the type of `this` to be volatile-qualified.
|
||||
return x;
|
||||
}
|
||||
|
||||
int f5() const volatile {
|
||||
// We expect the type of `this` to be qualified as both const and volatile.
|
||||
return x;
|
||||
}
|
||||
|
||||
void f6() {
|
||||
// No use of `this`, but we still expect to be able to get its type.
|
||||
global++;
|
||||
}
|
||||
|
||||
float f7() const & {
|
||||
// We expect the type of `this` to be const-qualified.
|
||||
return x;
|
||||
}
|
||||
|
||||
float f8() && {
|
||||
// We expect the type of `this` to be unqualified.
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
void instantiate() {
|
||||
InstantiatedTemplateClass<int> x;
|
||||
x.f1();
|
||||
x.f2();
|
||||
x.f3();
|
||||
x.f4();
|
||||
x.f5();
|
||||
x.f6();
|
||||
x.f7();
|
||||
|
||||
float val = InstantiatedTemplateClass<int>().f8();
|
||||
}
|
||||
|
||||
// Since there are no instantiations of this class, we don't expect
|
||||
// MemberFunction::getTypeOfThis() to hold.
|
||||
template<typename T>
|
||||
class UninstantiatedTemplateClass {
|
||||
int x;
|
||||
|
||||
public:
|
||||
|
||||
void f1() {
|
||||
x++;
|
||||
}
|
||||
};
|
||||
48
cpp/ql/test/library-tests/members/this/this.expected
Normal file
48
cpp/ql/test/library-tests/members/this/this.expected
Normal file
@@ -0,0 +1,48 @@
|
||||
thisExprType
|
||||
| test.cpp:11:5:11:5 | this | file://:0:0:0:0 | C * |
|
||||
| test.cpp:16:5:16:8 | this | file://:0:0:0:0 | C * |
|
||||
| test.cpp:21:12:21:12 | this | file://:0:0:0:0 | const C * |
|
||||
| test.cpp:26:12:26:12 | this | file://:0:0:0:0 | volatile C * |
|
||||
| test.cpp:31:12:31:12 | this | file://:0:0:0:0 | const volatile C * |
|
||||
| test.cpp:41:12:41:12 | this | file://:0:0:0:0 | const C * |
|
||||
| test.cpp:46:12:46:12 | this | file://:0:0:0:0 | C * |
|
||||
| test.cpp:66:5:66:5 | this | file://:0:0:0:0 | InstantiatedTemplateClass<T> * |
|
||||
| test.cpp:66:5:66:5 | this | file://:0:0:0:0 | InstantiatedTemplateClass<int> * |
|
||||
| test.cpp:71:5:71:8 | this | file://:0:0:0:0 | InstantiatedTemplateClass<T> * |
|
||||
| test.cpp:71:5:71:8 | this | file://:0:0:0:0 | InstantiatedTemplateClass<int> * |
|
||||
| test.cpp:76:12:76:12 | this | file://:0:0:0:0 | const InstantiatedTemplateClass<T> * |
|
||||
| test.cpp:76:12:76:12 | this | file://:0:0:0:0 | const InstantiatedTemplateClass<int> * |
|
||||
| test.cpp:81:12:81:12 | this | file://:0:0:0:0 | volatile InstantiatedTemplateClass<T> * |
|
||||
| test.cpp:81:12:81:12 | this | file://:0:0:0:0 | volatile InstantiatedTemplateClass<int> * |
|
||||
| test.cpp:86:12:86:12 | this | file://:0:0:0:0 | const volatile InstantiatedTemplateClass<T> * |
|
||||
| test.cpp:86:12:86:12 | this | file://:0:0:0:0 | const volatile InstantiatedTemplateClass<int> * |
|
||||
| test.cpp:96:12:96:12 | this | file://:0:0:0:0 | const InstantiatedTemplateClass<T> * |
|
||||
| test.cpp:96:12:96:12 | this | file://:0:0:0:0 | const InstantiatedTemplateClass<int> * |
|
||||
| test.cpp:101:12:101:12 | this | file://:0:0:0:0 | InstantiatedTemplateClass<T> * |
|
||||
| test.cpp:101:12:101:12 | this | file://:0:0:0:0 | InstantiatedTemplateClass<int> * |
|
||||
#select
|
||||
| test.cpp:9:8:9:9 | f1 | file://:0:0:0:0 | C * |
|
||||
| test.cpp:14:8:14:9 | f2 | file://:0:0:0:0 | C * |
|
||||
| test.cpp:19:7:19:8 | f3 | file://:0:0:0:0 | const C * |
|
||||
| test.cpp:24:7:24:8 | f4 | file://:0:0:0:0 | volatile C * |
|
||||
| test.cpp:29:7:29:8 | f5 | file://:0:0:0:0 | const volatile C * |
|
||||
| test.cpp:34:8:34:9 | f6 | file://:0:0:0:0 | C * |
|
||||
| test.cpp:39:9:39:10 | f7 | file://:0:0:0:0 | const C * |
|
||||
| test.cpp:44:9:44:10 | f8 | file://:0:0:0:0 | C * |
|
||||
| test.cpp:53:8:53:8 | f | file://:0:0:0:0 | D * |
|
||||
| test.cpp:64:8:64:8 | f1 | file://:0:0:0:0 | InstantiatedTemplateClass<int> * |
|
||||
| test.cpp:64:8:64:9 | f1 | file://:0:0:0:0 | InstantiatedTemplateClass<T> * |
|
||||
| test.cpp:69:8:69:8 | f2 | file://:0:0:0:0 | InstantiatedTemplateClass<int> * |
|
||||
| test.cpp:69:8:69:9 | f2 | file://:0:0:0:0 | InstantiatedTemplateClass<T> * |
|
||||
| test.cpp:74:7:74:7 | f3 | file://:0:0:0:0 | const InstantiatedTemplateClass<int> * |
|
||||
| test.cpp:74:7:74:8 | f3 | file://:0:0:0:0 | const InstantiatedTemplateClass<T> * |
|
||||
| test.cpp:79:7:79:7 | f4 | file://:0:0:0:0 | volatile InstantiatedTemplateClass<int> * |
|
||||
| test.cpp:79:7:79:8 | f4 | file://:0:0:0:0 | volatile InstantiatedTemplateClass<T> * |
|
||||
| test.cpp:84:7:84:7 | f5 | file://:0:0:0:0 | const volatile InstantiatedTemplateClass<int> * |
|
||||
| test.cpp:84:7:84:8 | f5 | file://:0:0:0:0 | const volatile InstantiatedTemplateClass<T> * |
|
||||
| test.cpp:89:8:89:8 | f6 | file://:0:0:0:0 | InstantiatedTemplateClass<int> * |
|
||||
| test.cpp:89:8:89:9 | f6 | file://:0:0:0:0 | InstantiatedTemplateClass<T> * |
|
||||
| test.cpp:94:9:94:9 | f7 | file://:0:0:0:0 | const InstantiatedTemplateClass<int> * |
|
||||
| test.cpp:94:9:94:10 | f7 | file://:0:0:0:0 | const InstantiatedTemplateClass<T> * |
|
||||
| test.cpp:99:9:99:9 | f8 | file://:0:0:0:0 | InstantiatedTemplateClass<int> * |
|
||||
| test.cpp:99:9:99:10 | f8 | file://:0:0:0:0 | InstantiatedTemplateClass<T> * |
|
||||
6
cpp/ql/test/library-tests/members/this/this.ql
Normal file
6
cpp/ql/test/library-tests/members/this/this.ql
Normal file
@@ -0,0 +1,6 @@
|
||||
import cpp
|
||||
|
||||
query predicate thisExprType(ThisExpr e, Type t) { t = e.getType() }
|
||||
|
||||
from MemberFunction f
|
||||
select f, f.getTypeOfThis()
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user