Merge branch 'master' of github.com:github/codeql into SharedDataflow

to receive updates from data flow library
This commit is contained in:
Rasmus Lerchedahl Petersen
2020-07-01 07:15:32 +02:00
275 changed files with 16386 additions and 1912 deletions

View File

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

View File

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

View File

@@ -33,7 +33,7 @@ private import semmle.code.cpp.internal.ResolveClass
class Class extends UserType {
Class() { isClass(underlyingElement(this)) }
override string getCanonicalQLClass() { result = "Class" }
override string getAPrimaryQlClass() { result = "Class" }
/** Gets a child declaration of this class, struct or union. */
override Declaration getADeclaration() { result = this.getAMember() }
@@ -768,7 +768,7 @@ class ClassDerivation extends Locatable, @derivation {
*/
Class getBaseClass() { result = getBaseType().getUnderlyingType() }
override string getCanonicalQLClass() { result = "ClassDerivation" }
override string getAPrimaryQlClass() { result = "ClassDerivation" }
/**
* Gets the type from which we are deriving, without resolving any
@@ -849,9 +849,7 @@ class ClassDerivation extends Locatable, @derivation {
class LocalClass extends Class {
LocalClass() { isLocal() }
override string getCanonicalQLClass() {
not this instanceof LocalStruct and result = "LocalClass"
}
override string getAPrimaryQlClass() { not this instanceof LocalStruct and result = "LocalClass" }
override Function getEnclosingAccessHolder() { result = this.getEnclosingFunction() }
}
@@ -872,7 +870,7 @@ class LocalClass extends Class {
class NestedClass extends Class {
NestedClass() { this.isMember() }
override string getCanonicalQLClass() {
override string getAPrimaryQlClass() {
not this instanceof NestedStruct and result = "NestedClass"
}
@@ -893,7 +891,7 @@ class NestedClass extends Class {
class AbstractClass extends Class {
AbstractClass() { exists(PureVirtualFunction f | this.getAMemberFunction() = f) }
override string getCanonicalQLClass() { result = "AbstractClass" }
override string getAPrimaryQlClass() { result = "AbstractClass" }
}
/**
@@ -934,7 +932,7 @@ class TemplateClass extends Class {
exists(result.getATemplateArgument())
}
override string getCanonicalQLClass() { result = "TemplateClass" }
override string getAPrimaryQlClass() { result = "TemplateClass" }
}
/**
@@ -955,7 +953,7 @@ class ClassTemplateInstantiation extends Class {
ClassTemplateInstantiation() { tc.getAnInstantiation() = this }
override string getCanonicalQLClass() { result = "ClassTemplateInstantiation" }
override string getAPrimaryQlClass() { result = "ClassTemplateInstantiation" }
/**
* Gets the class template from which this instantiation was instantiated.
@@ -996,7 +994,7 @@ abstract class ClassTemplateSpecialization extends Class {
count(int i | exists(result.getTemplateArgument(i)))
}
override string getCanonicalQLClass() { result = "ClassTemplateSpecialization" }
override string getAPrimaryQlClass() { result = "ClassTemplateSpecialization" }
}
/**
@@ -1025,7 +1023,7 @@ class FullClassTemplateSpecialization extends ClassTemplateSpecialization {
not this instanceof ClassTemplateInstantiation
}
override string getCanonicalQLClass() { result = "FullClassTemplateSpecialization" }
override string getAPrimaryQlClass() { result = "FullClassTemplateSpecialization" }
}
/**
@@ -1064,7 +1062,7 @@ class PartialClassTemplateSpecialization extends ClassTemplateSpecialization {
count(int i | exists(getTemplateArgument(i)))
}
override string getCanonicalQLClass() { result = "PartialClassTemplateSpecialization" }
override string getAPrimaryQlClass() { result = "PartialClassTemplateSpecialization" }
}
/**
@@ -1089,7 +1087,7 @@ deprecated class Interface extends Class {
)
}
override string getCanonicalQLClass() { result = "Interface" }
override string getAPrimaryQlClass() { result = "Interface" }
}
/**
@@ -1104,7 +1102,7 @@ deprecated class Interface extends Class {
class VirtualClassDerivation extends ClassDerivation {
VirtualClassDerivation() { hasSpecifier("virtual") }
override string getCanonicalQLClass() { result = "VirtualClassDerivation" }
override string getAPrimaryQlClass() { result = "VirtualClassDerivation" }
}
/**
@@ -1124,7 +1122,7 @@ class VirtualClassDerivation extends ClassDerivation {
class VirtualBaseClass extends Class {
VirtualBaseClass() { exists(VirtualClassDerivation cd | cd.getBaseClass() = this) }
override string getCanonicalQLClass() { result = "VirtualBaseClass" }
override string getAPrimaryQlClass() { result = "VirtualBaseClass" }
/** A virtual class derivation of which this class/struct is the base. */
VirtualClassDerivation getAVirtualDerivation() { result.getBaseClass() = this }
@@ -1146,7 +1144,7 @@ class VirtualBaseClass extends Class {
class ProxyClass extends UserType {
ProxyClass() { usertypes(underlyingElement(this), _, 9) }
override string getCanonicalQLClass() { result = "ProxyClass" }
override string getAPrimaryQlClass() { result = "ProxyClass" }
/** Gets the location of the proxy class. */
override Location getLocation() { result = getTemplateParameter().getDefinitionLocation() }

View File

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

View File

@@ -55,12 +55,21 @@ class ElementBase extends @element {
cached
string toString() { none() }
/** DEPRECATED: use `getAPrimaryQlClass` instead. */
deprecated string getCanonicalQLClass() { result = this.getAPrimaryQlClass() }
/**
* Canonical QL class corresponding to this element.
* Gets the name of a primary CodeQL class to which this element belongs.
*
* ElementBase is the root class for this predicate.
* For most elements, this is simply the most precise syntactic category to
* which they belong; for example, `AddExpr` is a primary class, but
* `BinaryOperation` is not.
*
* This predicate always has a result. If no primary class can be
* determined, the result is `"???"`. If multiple primary classes match,
* this predicate can have multiple results.
*/
string getCanonicalQLClass() { result = "???" }
string getAPrimaryQlClass() { result = "???" }
}
/**

View File

@@ -38,7 +38,7 @@ class Enum extends UserType, IntegralOrEnumType {
enumconstants(unresolveElement(result), underlyingElement(this), index, _, _, _)
}
override string getCanonicalQLClass() { result = "Enum" }
override string getAPrimaryQlClass() { result = "Enum" }
/**
* Gets a descriptive string for the enum. This method is only intended to
@@ -87,7 +87,7 @@ class Enum extends UserType, IntegralOrEnumType {
class LocalEnum extends Enum {
LocalEnum() { isLocal() }
override string getCanonicalQLClass() { result = "LocalEnum" }
override string getAPrimaryQlClass() { result = "LocalEnum" }
}
/**
@@ -105,7 +105,7 @@ class LocalEnum extends Enum {
class NestedEnum extends Enum {
NestedEnum() { this.isMember() }
override string getCanonicalQLClass() { result = "NestedEnum" }
override string getAPrimaryQlClass() { result = "NestedEnum" }
/** Holds if this member is private. */
predicate isPrivate() { this.hasSpecifier("private") }
@@ -130,7 +130,7 @@ class NestedEnum extends Enum {
class ScopedEnum extends Enum {
ScopedEnum() { usertypes(underlyingElement(this), _, 13) }
override string getCanonicalQLClass() { result = "ScopedEnum" }
override string getAPrimaryQlClass() { result = "ScopedEnum" }
}
/**
@@ -153,7 +153,7 @@ class EnumConstant extends Declaration, @enumconstant {
enumconstants(underlyingElement(this), unresolveElement(result), _, _, _, _)
}
override string getCanonicalQLClass() { result = "EnumConstant" }
override string getAPrimaryQlClass() { result = "EnumConstant" }
override Class getDeclaringType() { result = this.getDeclaringEnum().getDeclaringType() }

View File

@@ -23,7 +23,7 @@ import semmle.code.cpp.exprs.Access
class Field extends MemberVariable {
Field() { fieldoffsets(underlyingElement(this), _, _) }
override string getCanonicalQLClass() { result = "Field" }
override string getAPrimaryQlClass() { result = "Field" }
/**
* Gets the offset of this field in bytes from the start of its declaring
@@ -90,7 +90,7 @@ class Field extends MemberVariable {
class BitField extends Field {
BitField() { bitfield(underlyingElement(this), _, _) }
override string getCanonicalQLClass() { result = "BitField" }
override string getAPrimaryQlClass() { result = "BitField" }
/**
* Gets the size of this bitfield in bits (on the machine where facts

View File

@@ -178,7 +178,7 @@ class Folder extends Container, @folder {
result.hasLocationInfo(_, 0, 0, 0, 0)
}
override string getCanonicalQLClass() { result = "Folder" }
override string getAPrimaryQlClass() { result = "Folder" }
/**
* DEPRECATED: Use `getLocation` instead.
@@ -246,7 +246,7 @@ class File extends Container, @file {
override string toString() { result = Container.super.toString() }
override string getCanonicalQLClass() { result = "File" }
override string getAPrimaryQlClass() { result = "File" }
override Location getLocation() {
result.getContainer() = this and
@@ -382,7 +382,7 @@ class HeaderFile extends File {
exists(Include i | i.getIncludedFile() = this)
}
override string getCanonicalQLClass() { result = "HeaderFile" }
override string getAPrimaryQlClass() { result = "HeaderFile" }
/**
* Holds if this header file does not contain any declaration entries or top level
@@ -408,7 +408,7 @@ class HeaderFile extends File {
class CFile extends File {
CFile() { exists(string ext | ext = this.getExtension().toLowerCase() | ext = "c" or ext = "i") }
override string getCanonicalQLClass() { result = "CFile" }
override string getAPrimaryQlClass() { result = "CFile" }
}
/**
@@ -436,7 +436,7 @@ class CppFile extends File {
)
}
override string getCanonicalQLClass() { result = "CppFile" }
override string getAPrimaryQlClass() { result = "CppFile" }
}
/**

View File

@@ -27,7 +27,7 @@ class FriendDecl extends Declaration, @frienddecl {
*/
override Location getADeclarationLocation() { result = this.getLocation() }
override string getCanonicalQLClass() { result = "FriendDecl" }
override string getAPrimaryQlClass() { result = "FriendDecl" }
/**
* Implements the abstract method `Declaration.getDefinitionLocation`. A

View File

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

View File

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

View File

@@ -13,7 +13,7 @@ class Macro extends PreprocessorDirective, @ppd_define {
*/
override string getHead() { preproctext(underlyingElement(this), result, _) }
override string getCanonicalQLClass() { result = "Macro" }
override string getAPrimaryQlClass() { result = "Macro" }
/**
* Gets the body of this macro. For example, `(((x)>(y))?(x):(y))` in
@@ -74,7 +74,7 @@ class MacroAccess extends Locatable, @macroinvocation {
*/
override Location getLocation() { result = this.getOutermostMacroAccess().getActualLocation() }
override string getCanonicalQLClass() { result = "MacroAccess" }
override string getAPrimaryQlClass() { result = "MacroAccess" }
/**
* Gets the location of this macro access. For a nested access, where
@@ -147,7 +147,7 @@ class MacroAccess extends Locatable, @macroinvocation {
class MacroInvocation extends MacroAccess {
MacroInvocation() { macroinvocations(underlyingElement(this), _, _, 1) }
override string getCanonicalQLClass() { result = "MacroInvocation" }
override string getAPrimaryQlClass() { result = "MacroInvocation" }
/**
* Gets an element that occurs in this macro invocation or a nested macro

View File

@@ -25,7 +25,7 @@ import cpp
class MemberFunction extends Function {
MemberFunction() { this.isMember() }
override string getCanonicalQLClass() {
override string getAPrimaryQlClass() {
not this instanceof CopyAssignmentOperator and
not this instanceof MoveAssignmentOperator and
result = "MemberFunction"
@@ -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" }
}

View File

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

View File

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

View File

@@ -152,7 +152,7 @@ class PreprocessorIf extends PreprocessorBranch, @ppd_if {
class PreprocessorIfdef extends PreprocessorBranch, @ppd_ifdef {
override string toString() { result = "#ifdef " + this.getHead() }
override string getCanonicalQLClass() { result = "PreprocessorIfdef" }
override string getAPrimaryQlClass() { result = "PreprocessorIfdef" }
}
/**

View File

@@ -1,3 +1,11 @@
/**
* Provides queries to pretty-print a C++ AST as a graph.
*
* By default, this will print the AST for all functions in the database. To change this behavior,
* extend `PrintASTConfiguration` and override `shouldPrintFunction` to hold for only the functions
* you wish to view the AST for.
*/
import cpp
private import semmle.code.cpp.Print
@@ -7,6 +15,9 @@ private newtype TPrintASTConfiguration = MkPrintASTConfiguration()
* The query can extend this class to control which functions are printed.
*/
class PrintASTConfiguration extends TPrintASTConfiguration {
/**
* Gets a textual representation of this `PrintASTConfiguration`.
*/
string toString() { result = "PrintASTConfiguration" }
/**
@@ -96,6 +107,9 @@ private newtype TPrintASTNode =
* A node in the output tree.
*/
class PrintASTNode extends TPrintASTNode {
/**
* Gets a textual representation of this node in the PrintAST output tree.
*/
abstract string toString();
/**
@@ -155,7 +169,7 @@ class PrintASTNode extends TPrintASTNode {
* Retrieves the canonical QL class(es) for entity `el`
*/
private string qlClass(ElementBase el) {
result = "[" + concat(el.getCanonicalQLClass(), ",") + "] "
result = "[" + concat(el.getAPrimaryQlClass(), ",") + "] "
// Alternative implementation -- do not delete. It is useful for QL class discovery.
//result = "["+ concat(el.getAQlClass(), ",") + "] "
}
@@ -208,6 +222,9 @@ class ExprNode extends ASTNode {
result = expr.getValueCategoryString()
}
/**
* Gets the value of this expression, if it is a constant.
*/
string getValue() { result = expr.getValue() }
}
@@ -373,6 +390,9 @@ class ParametersNode extends PrintASTNode, TParametersNode {
override ASTNode getChild(int childIndex) { result.getAST() = func.getParameter(childIndex) }
/**
* Gets the `Function` for which this node represents the parameters.
*/
final Function getFunction() { result = func }
}
@@ -392,6 +412,9 @@ class ConstructorInitializersNode extends PrintASTNode, TConstructorInitializers
result.getAST() = ctor.getInitializer(childIndex)
}
/**
* Gets the `Constructor` for which this node represents the initializer list.
*/
final Constructor getConstructor() { result = ctor }
}
@@ -411,6 +434,9 @@ class DestructorDestructionsNode extends PrintASTNode, TDestructorDestructionsNo
result.getAST() = dtor.getDestruction(childIndex)
}
/**
* Gets the `Destructor` for which this node represents the destruction list.
*/
final Destructor getDestructor() { result = dtor }
}
@@ -464,6 +490,9 @@ class FunctionNode extends ASTNode {
key = "semmle.order" and result = getOrder().toString()
}
/**
* Gets the `Function` this node represents.
*/
final Function getFunction() { result = func }
}
@@ -499,11 +528,16 @@ class ArrayAggregateLiteralNode extends ExprNode {
}
}
/** Holds if `node` belongs to the output tree, and its property `key` has the given `value`. */
query predicate nodes(PrintASTNode node, string key, string value) {
node.shouldPrint() and
value = node.getProperty(key)
}
/**
* Holds if `target` is a child of `source` in the AST, and property `key` of the edge has the
* given `value`.
*/
query predicate edges(PrintASTNode source, PrintASTNode target, string key, string value) {
exists(int childIndex |
source.shouldPrint() and
@@ -517,6 +551,7 @@ query predicate edges(PrintASTNode source, PrintASTNode target, string key, stri
)
}
/** Holds if property `key` of the graph has the given `value`. */
query predicate graphProperties(string key, string value) {
key = "semmle.graphKind" and value = "tree"
}

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -6,7 +6,7 @@ import semmle.code.cpp.Type
class CharPointerType extends PointerType {
CharPointerType() { this.getBaseType() instanceof CharType }
override string getCanonicalQLClass() { result = "CharPointerType" }
override string getAPrimaryQlClass() { result = "CharPointerType" }
}
/**
@@ -15,7 +15,7 @@ class CharPointerType extends PointerType {
class IntPointerType extends PointerType {
IntPointerType() { this.getBaseType() instanceof IntType }
override string getCanonicalQLClass() { result = "IntPointerType" }
override string getAPrimaryQlClass() { result = "IntPointerType" }
}
/**
@@ -24,7 +24,7 @@ class IntPointerType extends PointerType {
class VoidPointerType extends PointerType {
VoidPointerType() { this.getBaseType() instanceof VoidType }
override string getCanonicalQLClass() { result = "VoidPointerType" }
override string getAPrimaryQlClass() { result = "VoidPointerType" }
}
/**
@@ -36,7 +36,7 @@ class Size_t extends Type {
this.hasName("size_t")
}
override string getCanonicalQLClass() { result = "Size_t" }
override string getAPrimaryQlClass() { result = "Size_t" }
}
/**
@@ -48,7 +48,7 @@ class Ssize_t extends Type {
this.hasName("ssize_t")
}
override string getCanonicalQLClass() { result = "Ssize_t" }
override string getAPrimaryQlClass() { result = "Ssize_t" }
}
/**
@@ -60,7 +60,7 @@ class Ptrdiff_t extends Type {
this.hasName("ptrdiff_t")
}
override string getCanonicalQLClass() { result = "Ptrdiff_t" }
override string getAPrimaryQlClass() { result = "Ptrdiff_t" }
}
/**
@@ -72,7 +72,7 @@ class Intmax_t extends Type {
this.hasName("intmax_t")
}
override string getCanonicalQLClass() { result = "Intmax_t" }
override string getAPrimaryQlClass() { result = "Intmax_t" }
}
/**
@@ -84,7 +84,7 @@ class Uintmax_t extends Type {
this.hasName("uintmax_t")
}
override string getCanonicalQLClass() { result = "Uintmax_t" }
override string getAPrimaryQlClass() { result = "Uintmax_t" }
}
/**
@@ -100,7 +100,7 @@ class Wchar_t extends Type {
this.hasName("wchar_t")
}
override string getCanonicalQLClass() { result = "Wchar_t" }
override string getAPrimaryQlClass() { result = "Wchar_t" }
}
/**
@@ -176,5 +176,5 @@ class MicrosoftInt64Type extends IntegralType {
class BuiltInVarArgsList extends Type {
BuiltInVarArgsList() { this.hasName("__builtin_va_list") }
override string getCanonicalQLClass() { result = "BuiltInVarArgsList" }
override string getAPrimaryQlClass() { result = "BuiltInVarArgsList" }
}

View File

@@ -20,7 +20,7 @@ class PrintfFormatAttribute extends FormatAttribute {
* function by its use of the GNU `format` attribute.
*/
class AttributeFormattingFunction extends FormattingFunction {
override string getCanonicalQLClass() { result = "AttributeFormattingFunction" }
override string getAPrimaryQlClass() { result = "AttributeFormattingFunction" }
AttributeFormattingFunction() {
exists(PrintfFormatAttribute printf_attrib |
@@ -73,7 +73,7 @@ predicate variadicFormatter(Function f, int formatParamIndex) {
* string and a variable number of arguments.
*/
class UserDefinedFormattingFunction extends FormattingFunction {
override string getCanonicalQLClass() { result = "UserDefinedFormattingFunction" }
override string getAPrimaryQlClass() { result = "UserDefinedFormattingFunction" }
UserDefinedFormattingFunction() { isVarargs() and callsVariadicFormatter(this, _) }
@@ -86,7 +86,7 @@ class UserDefinedFormattingFunction extends FormattingFunction {
class FormattingFunctionCall extends Expr {
FormattingFunctionCall() { this.(Call).getTarget() instanceof FormattingFunction }
override string getCanonicalQLClass() { result = "FormattingFunctionCall" }
override string getAPrimaryQlClass() { result = "FormattingFunctionCall" }
/**
* Gets the formatting function being called.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -38,7 +38,7 @@ class Assignment extends Operation, @assign_expr {
class AssignExpr extends Assignment, @assignexpr {
override string getOperator() { result = "=" }
override string getCanonicalQLClass() { result = "AssignExpr" }
override string getAPrimaryQlClass() { result = "AssignExpr" }
/** Gets a textual representation of this assignment. */
override string toString() { result = "... = ..." }
@@ -64,7 +64,7 @@ class AssignArithmeticOperation extends AssignOperation, @assign_arith_expr { }
* ```
*/
class AssignAddExpr extends AssignArithmeticOperation, @assignaddexpr {
override string getCanonicalQLClass() { result = "AssignAddExpr" }
override string getAPrimaryQlClass() { result = "AssignAddExpr" }
override string getOperator() { result = "+=" }
}
@@ -76,7 +76,7 @@ class AssignAddExpr extends AssignArithmeticOperation, @assignaddexpr {
* ```
*/
class AssignSubExpr extends AssignArithmeticOperation, @assignsubexpr {
override string getCanonicalQLClass() { result = "AssignSubExpr" }
override string getAPrimaryQlClass() { result = "AssignSubExpr" }
override string getOperator() { result = "-=" }
}
@@ -88,7 +88,7 @@ class AssignSubExpr extends AssignArithmeticOperation, @assignsubexpr {
* ```
*/
class AssignMulExpr extends AssignArithmeticOperation, @assignmulexpr {
override string getCanonicalQLClass() { result = "AssignMulExpr" }
override string getAPrimaryQlClass() { result = "AssignMulExpr" }
override string getOperator() { result = "*=" }
}
@@ -100,7 +100,7 @@ class AssignMulExpr extends AssignArithmeticOperation, @assignmulexpr {
* ```
*/
class AssignDivExpr extends AssignArithmeticOperation, @assigndivexpr {
override string getCanonicalQLClass() { result = "AssignDivExpr" }
override string getAPrimaryQlClass() { result = "AssignDivExpr" }
override string getOperator() { result = "/=" }
}
@@ -112,7 +112,7 @@ class AssignDivExpr extends AssignArithmeticOperation, @assigndivexpr {
* ```
*/
class AssignRemExpr extends AssignArithmeticOperation, @assignremexpr {
override string getCanonicalQLClass() { result = "AssignRemExpr" }
override string getAPrimaryQlClass() { result = "AssignRemExpr" }
override string getOperator() { result = "%=" }
}
@@ -130,7 +130,7 @@ class AssignBitwiseOperation extends AssignOperation, @assign_bitwise_expr { }
* ```
*/
class AssignAndExpr extends AssignBitwiseOperation, @assignandexpr {
override string getCanonicalQLClass() { result = "AssignAndExpr" }
override string getAPrimaryQlClass() { result = "AssignAndExpr" }
override string getOperator() { result = "&=" }
}
@@ -142,7 +142,7 @@ class AssignAndExpr extends AssignBitwiseOperation, @assignandexpr {
* ```
*/
class AssignOrExpr extends AssignBitwiseOperation, @assignorexpr {
override string getCanonicalQLClass() { result = "AssignOrExpr" }
override string getAPrimaryQlClass() { result = "AssignOrExpr" }
override string getOperator() { result = "|=" }
}
@@ -154,7 +154,7 @@ class AssignOrExpr extends AssignBitwiseOperation, @assignorexpr {
* ```
*/
class AssignXorExpr extends AssignBitwiseOperation, @assignxorexpr {
override string getCanonicalQLClass() { result = "AssignXorExpr" }
override string getAPrimaryQlClass() { result = "AssignXorExpr" }
override string getOperator() { result = "^=" }
}
@@ -166,7 +166,7 @@ class AssignXorExpr extends AssignBitwiseOperation, @assignxorexpr {
* ```
*/
class AssignLShiftExpr extends AssignBitwiseOperation, @assignlshiftexpr {
override string getCanonicalQLClass() { result = "AssignLShiftExpr" }
override string getAPrimaryQlClass() { result = "AssignLShiftExpr" }
override string getOperator() { result = "<<=" }
}
@@ -178,7 +178,7 @@ class AssignLShiftExpr extends AssignBitwiseOperation, @assignlshiftexpr {
* ```
*/
class AssignRShiftExpr extends AssignBitwiseOperation, @assignrshiftexpr {
override string getCanonicalQLClass() { result = "AssignRShiftExpr" }
override string getAPrimaryQlClass() { result = "AssignRShiftExpr" }
override string getOperator() { result = ">>=" }
}
@@ -190,7 +190,7 @@ class AssignRShiftExpr extends AssignBitwiseOperation, @assignrshiftexpr {
* ```
*/
class AssignPointerAddExpr extends AssignOperation, @assignpaddexpr {
override string getCanonicalQLClass() { result = "AssignPointerAddExpr" }
override string getAPrimaryQlClass() { result = "AssignPointerAddExpr" }
override string getOperator() { result = "+=" }
}
@@ -202,7 +202,7 @@ class AssignPointerAddExpr extends AssignOperation, @assignpaddexpr {
* ```
*/
class AssignPointerSubExpr extends AssignOperation, @assignpsubexpr {
override string getCanonicalQLClass() { result = "AssignPointerSubExpr" }
override string getAPrimaryQlClass() { result = "AssignPointerSubExpr" }
override string getOperator() { result = "-=" }
}
@@ -227,7 +227,7 @@ class ConditionDeclExpr extends Expr, @condition_decl {
*/
deprecated Expr getExpr() { result = this.getChild(0) }
override string getCanonicalQLClass() { result = "ConditionDeclExpr" }
override string getAPrimaryQlClass() { result = "ConditionDeclExpr" }
/**
* Gets the compiler-generated variable access that conceptually occurs after

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1 +1,5 @@
/**
* Module used to configure the IR generation process.
*/
import implementation.IRConfiguration

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -44,7 +44,7 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
/** Gets the position at which the format parameter occurs. */
abstract int getFormatParameterIndex();
override string getCanonicalQLClass() { result = "FormattingFunction" }
override string getAPrimaryQlClass() { result = "FormattingFunction" }
/**
* Holds if this `FormattingFunction` is in a context that supports

View File

@@ -1,3 +1,7 @@
/**
* Provides classes and predicates for recognizing floating point expressions which cannot be NaN.
*/
import cpp
private import semmle.code.cpp.rangeanalysis.RangeSSA

View File

@@ -11,8 +11,17 @@ private float lowerBoundFC(Expr expr) { result = lowerBound(expr.getFullyConvert
/** Gets the upper bound of the fully converted expression. */
private float upperBoundFC(Expr expr) { result = upperBound(expr.getFullyConverted()) }
/**
* Describes which side of a pointless comparison is known to be smaller.
*/
newtype SmallSide =
/**
* Represents that the left side of a pointless comparison is known to be smaller.
*/
LeftIsSmaller() or
/**
* Represents that the right side of a pointless comparison is known to be smaller.
*/
RightIsSmaller()
/**

View File

@@ -5,7 +5,13 @@ import cpp
* relation) or 'non-strict' (a `<=` or `>=` relation).
*/
newtype RelationStrictness =
/**
* Represents that a relation is 'strict' (that is, a `<` or `>` relation).
*/
Strict() or
/**
* Represents that a relation is 'non-strict' (that is, a `<=` or `>=` relation)
*/
Nonstrict()
/**
@@ -13,7 +19,13 @@ newtype RelationStrictness =
* relation) or 'lesser' (a `<` or `<=` relation).
*/
newtype RelationDirection =
/**
* Represents that a relation is 'greater' (that is, a `>` or `>=` relation).
*/
Greater() or
/**
* Represents that a relation is 'lesser' (that is, a `<` or `<=` relation).
*/
Lesser()
private RelationStrictness negateStrictness(RelationStrictness strict) {
@@ -28,12 +40,18 @@ private RelationDirection negateDirection(RelationDirection dir) {
dir = Lesser() and result = Greater()
}
/**
* Holds if `dir` is `Greater` (that is, a `>` or `>=` relation)
*/
boolean directionIsGreater(RelationDirection dir) {
dir = Greater() and result = true
or
dir = Lesser() and result = false
}
/**
* Holds if `dir` is `Lesser` (that is, a `<` or `<=` relation)
*/
boolean directionIsLesser(RelationDirection dir) {
dir = Greater() and result = false
or

View File

@@ -25,6 +25,10 @@ import semmle.code.cpp.controlflow.Dominance
import semmle.code.cpp.controlflow.SSAUtils
private import RangeAnalysisUtils
/**
* The SSA logic comes in two versions: the standard SSA and range-analysis RangeSSA.
* This class provides the range-analysis SSA logic.
*/
library class RangeSSA extends SSAHelper {
RangeSSA() { this = 1 }
@@ -84,6 +88,7 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
/** Gets the control flow node for this definition. */
ControlFlowNode getDefinition() { result = this }
/** Gets the basic block containing this definition. */
BasicBlock getBasicBlock() { result.contains(getDefinition()) }
/** Whether this definition is a phi node for variable `v`. */
@@ -97,11 +102,13 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
guard_defn(v, guard, this, branch)
}
/** Gets the primary location of this definition. */
Location getLocation() { result = this.(ControlFlowNode).getLocation() }
/** Whether this definition is from a parameter */
predicate definedByParameter(Parameter p) { this = p.getFunction().getEntryPoint() }
/** Gets a definition of `v` that is a phi input for this basic block. */
RangeSsaDefinition getAPhiInput(StackVariable v) {
this.isPhiNode(v) and
exists(BasicBlock pred |
@@ -153,6 +160,9 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
)
}
/**
* Holds if this definition of the variable `v` reached the end of the basic block `b`.
*/
predicate reachesEndOfBB(StackVariable v, BasicBlock b) {
exists(RangeSSA x | x.ssaDefinitionReachesEndOfBB(v, this, b))
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
import cpp
from Expr e
select e, e.getCanonicalQLClass()
select e, e.getAPrimaryQlClass()

View File

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

View File

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

View File

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

View 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++;
}
};

View 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> * |

View 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