mirror of
https://github.com/github/codeql.git
synced 2026-05-05 05:35:13 +02:00
C++: Implement language-neutral IR type system
The C++ IR currently has a very clunky way of specifying the type of an IR entity (`Instruction`, `Operand`, `IRVariable`, etc.). There are three separate predicates: `getType()`, `isGLValue()`, and `getSize()`. All three are necessary, rather than just having a `getType()` predicate, because some IR entities have types that are not represented via an existing `Type` object in the AST. Examples include the type for an lvalue returned from a `VariableAddress` instruction, the type for an array slice being zero-initialized in a variable initializer, and several others. It is very easy for QL code to just check the `getType()` predicate, while forgetting to use `isGLValue()` to determine if that type is the actual type of the entity (the prvalue case) or the type referred to by a glvalue entity. Furthermore, the C++ type system creates potentially many different `Type` objects for the same underlying type (e.g. typedefs, using declarations, `const`/`volatile` qualifiers, etc.), making it more difficult to tell when two entities have semantically equivalent types. In addition, other languages for which we want to enable the IR have somewhat different type systems. The various language type systems differ in their structure, although they tend to share the basic building blocks necessary for the IR. To address all of the above problems, I've introduced a new class hierarchy, rooted at the class `IRType`, that represents a bare-bones type system that is independent of source language (at least across C/C++/C#/Java). A type's identity is based on its kind (signed integer, unsigned integer, floating-point, Boolean, blob, etc.), size and in the case of blob types, a "tag" to differentiate between different classes and structs. No distinction is made between, say `signed int` and plain `int`, or between different language integer types that have the same signedness and size (e.g. `unsigned int` vs. `wchar_t` on Linux). `IRType` is intended for use by language-agnostic IR-based analyses, including range analysis, dataflow, SSA construction, and alias analysis. The set of available `IRType`s is determined by predicate provided by the language library implementation (e.g. `hasSignedIntegerType(int byteSize)`. In addition to `IRType`, each language now defines a type alias named `LanguageType`, representing the type of an IR entity in more language-specific terms. The only predicate requried on `LanguageType` is `getIRType()`, which returns the single `IRType` object for the language-neutral representation of that `LanguageType`. All other predicates on and subclasses of `LanguageType` are language-specific. There may be many instances of `LanguageType` that map to a given `IRType`, to allow for typedefs, etc. Most of the changes are mechanical changes in the IR construction code, to return the correct type for each IR entity. SSA construction has also been updated to avoid dependencies on language-specific types. I have not yet removed the original `getType()` predicates that just return `Type`. These can be removed once we move the remaining existing libraries to use `IRType`. Test results are, by design, pretty much unchanged. Once case changed for inline asm, because the previously IR generation for it played a little fast and loose with the input/output expressions. The test case now includes both input and output variables. The generated IR for `Conditional_LValue` is now more correct, because we now have a way to represent an lvalue of an lvalue. `syntax-zoo` is still a hot mess. Most of the changed outputs are due to wobble from having multiple functions with the same name, but with a slightly different order of evaluation due to the type changes. Others are wobble from already-invalid IR. A couple non-wobbly places have improved slightly, though. The C# part of this change is waiting for #2005 to be merged, since that has some of the necessary C# implementation.
This commit is contained in:
257
cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll
Normal file
257
cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll
Normal file
@@ -0,0 +1,257 @@
|
||||
/**
|
||||
* Minimal, language-neutral type system for the IR.
|
||||
*/
|
||||
|
||||
private import internal.IRTypeInternal
|
||||
|
||||
newtype TIRType =
|
||||
TIRVoidType() or
|
||||
TIRUnknownType() or
|
||||
TIRErrorType() or
|
||||
TIRBooleanType(int byteSize) {
|
||||
Language::hasBooleanType(byteSize)
|
||||
} or
|
||||
TIRSignedIntegerType(int byteSize) {
|
||||
Language::hasSignedIntegerType(byteSize)
|
||||
} or
|
||||
TIRUnsignedIntegerType(int byteSize) {
|
||||
Language::hasUnsignedIntegerType(byteSize)
|
||||
} or
|
||||
TIRFloatingPointType(int byteSize) {
|
||||
Language::hasFloatingPointType(byteSize)
|
||||
} or
|
||||
TIRAddressType(int byteSize) {
|
||||
Language::hasAddressType(byteSize)
|
||||
} or
|
||||
TIRFunctionAddressType(int byteSize) {
|
||||
Language::hasFunctionAddressType(byteSize)
|
||||
} or
|
||||
TIRBlobType(Language::BlobTypeTag tag, int byteSize) {
|
||||
Language::hasBlobType(tag, byteSize)
|
||||
}
|
||||
|
||||
/**
|
||||
* The language-neutral type of an IR `Instruction`, `Operand`, or `IRVariable`.
|
||||
* The interface to `IRType` and its subclasses is the same across all languages for which the IR
|
||||
* is supported, so analyses that expect to be used for multiple languages should generally use
|
||||
* `IRType` rather than a language-specific type.
|
||||
*
|
||||
* Many types from the language-specific type system will map to a single canonical `IRType`. Two
|
||||
* types that map to the same `IRType` are considered equivalent by the IR. As an example, in C++,
|
||||
* all pointer types map to the same instance of `IRAddressType`.
|
||||
*/
|
||||
class IRType extends TIRType {
|
||||
abstract string toString();
|
||||
|
||||
/**
|
||||
* Gets a string that uniquely identifies this `IRType`. This string is often the same as the
|
||||
* result of `IRType.toString()`, but for some types it may be more verbose to ensure uniqueness.
|
||||
*/
|
||||
string getIdentityString() {
|
||||
result = toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of the type, in bytes, if known.
|
||||
*
|
||||
* This will hold for all `IRType` objects except `IRUnknownType`.
|
||||
*/
|
||||
abstract int getByteSize();
|
||||
|
||||
/**
|
||||
* Gets a single instance of `LanguageType` that maps to this `IRType`.
|
||||
*/
|
||||
abstract Language::LanguageType getCanonicalLanguageType();
|
||||
}
|
||||
|
||||
/**
|
||||
* An unknown type. Generally used to represent results and operands that access an unknown set of
|
||||
* memory locations, such as the side effects of a function call.
|
||||
*/
|
||||
class IRUnknownType extends IRType, TIRUnknownType {
|
||||
final override string toString() { result = "unknown" }
|
||||
|
||||
final override int getByteSize() { none() }
|
||||
|
||||
final override Language::LanguageType getCanonicalLanguageType() {
|
||||
result = Language::getCanonicalUnknownType()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A void type, which has no values. Used to represent the result type of an instruction that does
|
||||
* not produce a result.
|
||||
*/
|
||||
class IRVoidType extends IRType, TIRVoidType {
|
||||
final override string toString() { result = "void" }
|
||||
|
||||
final override int getByteSize() { result = 0 }
|
||||
|
||||
final override Language::LanguageType getCanonicalLanguageType() {
|
||||
result = Language::getCanonicalVoidType()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An error type. Used when an error in the source code prevents the extractor from determining the
|
||||
* proper type.
|
||||
*/
|
||||
class IRErrorType extends IRType, TIRErrorType {
|
||||
final override string toString() { result = "error" }
|
||||
|
||||
final override int getByteSize() { result = 0 }
|
||||
|
||||
final override Language::LanguageType getCanonicalLanguageType() {
|
||||
result = Language::getCanonicalErrorType()
|
||||
}
|
||||
}
|
||||
|
||||
private class IRSizedType extends IRType {
|
||||
int byteSize;
|
||||
|
||||
IRSizedType() {
|
||||
this = TIRBooleanType(byteSize) or
|
||||
this = TIRSignedIntegerType(byteSize) or
|
||||
this = TIRUnsignedIntegerType(byteSize) or
|
||||
this = TIRFloatingPointType(byteSize) or
|
||||
this = TIRAddressType(byteSize) or
|
||||
this = TIRFunctionAddressType(byteSize) or
|
||||
this = TIRBlobType(_, byteSize)
|
||||
}
|
||||
|
||||
abstract override string toString();
|
||||
|
||||
final override int getByteSize() { result = byteSize }
|
||||
|
||||
abstract override Language::LanguageType getCanonicalLanguageType();
|
||||
}
|
||||
|
||||
/**
|
||||
* A Boolean type, which can hold the values `true` (non-zero) or `false` (zero).
|
||||
*/
|
||||
class IRBooleanType extends IRSizedType, TIRBooleanType {
|
||||
final override string toString() { result = "bool" + byteSize.toString() }
|
||||
|
||||
final override Language::LanguageType getCanonicalLanguageType() {
|
||||
result = Language::getCanonicalBooleanType(byteSize)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A numberic type. This includes `IRSignedIntegerType`, `IRUnsignedIntegerType`, and
|
||||
* `IRFloatingPointType`.
|
||||
*/
|
||||
class IRNumericType extends IRSizedType {
|
||||
IRNumericType() {
|
||||
this = TIRSignedIntegerType(byteSize) or
|
||||
this = TIRUnsignedIntegerType(byteSize) or
|
||||
this = TIRFloatingPointType(byteSize)
|
||||
}
|
||||
|
||||
abstract override string toString();
|
||||
|
||||
abstract override Language::LanguageType getCanonicalLanguageType();
|
||||
}
|
||||
|
||||
/**
|
||||
* A signed two's-complement integer. Also used to represent enums whose underlying type is a signed
|
||||
* integer, as well as character types whose representation is signed.
|
||||
*/
|
||||
class IRSignedIntegerType extends IRNumericType, TIRSignedIntegerType {
|
||||
final override string toString() { result = "int" + byteSize.toString() }
|
||||
|
||||
final override Language::LanguageType getCanonicalLanguageType() {
|
||||
result = Language::getCanonicalSignedIntegerType(byteSize)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An unsigned two's-complement integer. Also used to represent enums whose underlying type is an
|
||||
* unsigned integer, as well as character types whose representation is unsigned.
|
||||
*/
|
||||
class IRUnsignedIntegerType extends IRNumericType, TIRUnsignedIntegerType {
|
||||
final override string toString() { result = "uint" + byteSize.toString() }
|
||||
|
||||
final override Language::LanguageType getCanonicalLanguageType() {
|
||||
result = Language::getCanonicalUnsignedIntegerType(byteSize)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A floating-point type.
|
||||
*/
|
||||
class IRFloatingPointType extends IRNumericType, TIRFloatingPointType {
|
||||
final override string toString() { result = "float" + byteSize.toString() }
|
||||
|
||||
final override Language::LanguageType getCanonicalLanguageType() {
|
||||
result = Language::getCanonicalFloatingPointType(byteSize)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An address type, representing the memory address of data. Used to represent pointers, references,
|
||||
* and lvalues, include those that are garbage collected.
|
||||
*
|
||||
* The address of a function is represented by the separate `IRFunctionAddressType`.
|
||||
*/
|
||||
class IRAddressType extends IRSizedType, TIRAddressType {
|
||||
final override string toString() { result = "addr" + byteSize.toString() }
|
||||
|
||||
final override Language::LanguageType getCanonicalLanguageType() {
|
||||
result = Language::getCanonicalAddressType(byteSize)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An address type, representing the memory address of code. Used to represent function pointers,
|
||||
* function references, and the target of a direct function call.
|
||||
*/
|
||||
class IRFunctionAddressType extends IRSizedType, TIRFunctionAddressType {
|
||||
final override string toString() { result = "func" + byteSize.toString() }
|
||||
|
||||
final override Language::LanguageType getCanonicalLanguageType() {
|
||||
result = Language::getCanonicalFunctionAddressType(byteSize)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A type with known size that does not fit any of the other kinds of type. Used to represent
|
||||
* classes, structs, unions, fixed-size arrays, pointers-to-member, and more.
|
||||
*/
|
||||
class IRBlobType extends IRSizedType, TIRBlobType {
|
||||
Language::BlobTypeTag tag;
|
||||
|
||||
IRBlobType() {
|
||||
this = TIRBlobType(tag, byteSize)
|
||||
}
|
||||
|
||||
final override string toString() {
|
||||
result = "blob" + byteSize.toString() + "{" + tag.toString() + "}"
|
||||
}
|
||||
|
||||
final override string getIdentityString() {
|
||||
result = "blob" + byteSize.toString() + "{" + Language::getBlobTagIdentityString(tag) + "}"
|
||||
}
|
||||
|
||||
final override Language::LanguageType getCanonicalLanguageType() {
|
||||
result = Language::getCanonicalBlobType(tag, byteSize)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the "tag" that differentiates this type from other incompatible blob types that have the
|
||||
* same size.
|
||||
*/
|
||||
final Language::BlobTypeTag getTag() { result = tag }
|
||||
}
|
||||
|
||||
module IRTypeSanity {
|
||||
query predicate missingCanonicalLanguageType(IRType type, string message) {
|
||||
not exists(type.getCanonicalLanguageType()) and
|
||||
message = "Type does not have a canonical `LanguageType`"
|
||||
}
|
||||
|
||||
query predicate multipleCanonicalLanguageTypes(IRType type, string message) {
|
||||
strictcount(type.getCanonicalLanguageType()) > 1 and
|
||||
message = "Type has multiple canonical `LanguageType`s: " + concat(type.getCanonicalLanguageType().toString(), ", ")
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import IRVariable
|
||||
import Operand
|
||||
private import internal.IRImports as Imports
|
||||
import Imports::EdgeKind
|
||||
import Imports::IRType
|
||||
import Imports::MemoryAccessKind
|
||||
|
||||
private newtype TIRPropertyProvider = MkIRPropertyProvider()
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
private import IR
|
||||
import InstructionSanity
|
||||
import IRTypeSanity
|
||||
@@ -5,6 +5,7 @@ import Imports::TempVariableTag
|
||||
private import Imports::IRUtilities
|
||||
private import Imports::TTempVariableTag
|
||||
private import Imports::TIRVariable
|
||||
private import Imports::IRType
|
||||
|
||||
IRUserVariable getIRUserVariable(Language::Function func, Language::Variable var) {
|
||||
result.getVariable() = var and
|
||||
@@ -24,7 +25,21 @@ abstract class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
abstract Language::Type getType();
|
||||
final Language::Type getType() {
|
||||
getLanguageType().hasType(result, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the language-neutral type of the variable.
|
||||
*/
|
||||
final IRType getIRType() {
|
||||
result = getLanguageType().getIRType()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
abstract Language::LanguageType getLanguageType();
|
||||
|
||||
/**
|
||||
* Gets the AST node that declared this variable, or that introduced this
|
||||
@@ -59,7 +74,7 @@ abstract class IRVariable extends TIRVariable {
|
||||
*/
|
||||
class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
Language::Variable var;
|
||||
Language::Type type;
|
||||
Language::LanguageType type;
|
||||
|
||||
IRUserVariable() { this = TIRUserVariable(var, type, func) }
|
||||
|
||||
@@ -71,7 +86,7 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
result = getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
}
|
||||
|
||||
final override Language::Type getType() { result = type }
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
/**
|
||||
* Gets the original user-declared variable.
|
||||
@@ -110,11 +125,11 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
|
||||
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
|
||||
Language::AST ast;
|
||||
TempVariableTag tag;
|
||||
Language::Type type;
|
||||
Language::LanguageType type;
|
||||
|
||||
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }
|
||||
|
||||
final override Language::Type getType() { result = type }
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
final override Language::AST getAST() { result = ast }
|
||||
|
||||
|
||||
@@ -113,10 +113,13 @@ module InstructionSanity {
|
||||
}
|
||||
|
||||
query predicate missingOperandType(Operand operand, string message) {
|
||||
exists(Language::Function func |
|
||||
exists(Language::Function func, Instruction use |
|
||||
not exists(operand.getType()) and
|
||||
func = operand.getUse().getEnclosingFunction() and
|
||||
message = "Operand missing type in function '" + Language::getIdentityString(func) + "'."
|
||||
use = operand.getUse() and
|
||||
func = use.getEnclosingFunction() and
|
||||
message = "Operand '" + operand.toString() + "' of instruction '" +
|
||||
use.getOpcode().toString() + "' missing type in function '" +
|
||||
Language::getIdentityString(func) + "'."
|
||||
)
|
||||
}
|
||||
|
||||
@@ -344,23 +347,6 @@ class Instruction extends Construction::TInstruction {
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[type]
|
||||
private string getValueCategoryString(string type) {
|
||||
if isGLValue() then result = "glval<" + type + ">" else result = type
|
||||
}
|
||||
|
||||
string getResultTypeString() {
|
||||
exists(string valcat |
|
||||
valcat = getValueCategoryString(getResultType().toString()) and
|
||||
if
|
||||
getResultType() instanceof Language::UnknownType and
|
||||
not isGLValue() and
|
||||
exists(getResultSize())
|
||||
then result = valcat + "[" + getResultSize().toString() + "]"
|
||||
else result = valcat
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a human-readable string that uniquely identifies this instruction
|
||||
* within the function. This string is used to refer to this instruction when
|
||||
@@ -380,7 +366,9 @@ class Instruction extends Construction::TInstruction {
|
||||
*
|
||||
* Example: `r1_1(int*)`
|
||||
*/
|
||||
final string getResultString() { result = getResultId() + "(" + getResultTypeString() + ")" }
|
||||
final string getResultString() {
|
||||
result = getResultId() + "(" + getResultLanguageType().getDumpString() + ")"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string describing the operands of this instruction, suitable for
|
||||
@@ -448,6 +436,10 @@ class Instruction extends Construction::TInstruction {
|
||||
result = Construction::getInstructionUnconvertedResultExpression(this)
|
||||
}
|
||||
|
||||
final Language::LanguageType getResultLanguageType() {
|
||||
result = Construction::getInstructionResultType(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the result produced by this instruction. If the
|
||||
* instruction does not produce a result, its result type will be `VoidType`.
|
||||
@@ -455,7 +447,16 @@ class Instruction extends Construction::TInstruction {
|
||||
* If `isGLValue()` holds, then the result type of this instruction should be
|
||||
* thought of as "pointer to `getResultType()`".
|
||||
*/
|
||||
final Language::Type getResultType() { Construction::instructionHasType(this, result, _) }
|
||||
final Language::Type getResultType() {
|
||||
exists(Language::LanguageType resultType, Language::Type langType |
|
||||
resultType = getResultLanguageType() and
|
||||
(
|
||||
resultType.hasType(langType, _) or
|
||||
not resultType.hasType(_, _) and result instanceof Language::UnknownType
|
||||
) and
|
||||
result = langType.getUnspecifiedType()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the result produced by this instruction is a glvalue. If this
|
||||
@@ -475,7 +476,9 @@ class Instruction extends Construction::TInstruction {
|
||||
* result of the `Load` instruction is a prvalue of type `int`, representing
|
||||
* the integer value loaded from variable `x`.
|
||||
*/
|
||||
final predicate isGLValue() { Construction::instructionHasType(this, _, true) }
|
||||
final predicate isGLValue() {
|
||||
Construction::getInstructionResultType(this).hasType(_, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of the result produced by this instruction, in bytes. If the
|
||||
@@ -485,14 +488,7 @@ class Instruction extends Construction::TInstruction {
|
||||
* `getResultSize()` will always be the size of a pointer.
|
||||
*/
|
||||
final int getResultSize() {
|
||||
if isGLValue()
|
||||
then
|
||||
// a glvalue is always pointer-sized.
|
||||
result = Language::getPointerSize()
|
||||
else
|
||||
if getResultType() instanceof Language::UnknownType
|
||||
then result = Construction::getInstructionResultSize(this)
|
||||
else result = Language::getTypeSize(getResultType())
|
||||
result = Construction::getInstructionResultType(this).getByteSize()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1300,7 +1296,7 @@ class CatchInstruction extends Instruction {
|
||||
* An instruction that catches an exception of a specific type.
|
||||
*/
|
||||
class CatchByTypeInstruction extends CatchInstruction {
|
||||
Language::Type exceptionType;
|
||||
Language::LanguageType exceptionType;
|
||||
|
||||
CatchByTypeInstruction() {
|
||||
getOpcode() instanceof Opcode::CatchByType and
|
||||
@@ -1312,7 +1308,7 @@ class CatchByTypeInstruction extends CatchInstruction {
|
||||
/**
|
||||
* Gets the type of exception to be caught.
|
||||
*/
|
||||
final Language::Type getExceptionType() { result = exceptionType }
|
||||
final Language::LanguageType getExceptionType() { result = exceptionType }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
private import internal.IRInternal
|
||||
import Instruction
|
||||
import IRBlock
|
||||
private import Instruction
|
||||
private import IRBlock
|
||||
private import internal.OperandImports as Imports
|
||||
import Imports::MemoryAccessKind
|
||||
import Imports::Overlap
|
||||
private import Imports::MemoryAccessKind
|
||||
private import Imports::IRType
|
||||
private import Imports::Overlap
|
||||
private import Imports::OperandTag
|
||||
|
||||
cached
|
||||
@@ -143,22 +144,40 @@ class Operand extends TOperand {
|
||||
* the definition type, such as in the case of a partial read or a read from a pointer that
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
Language::Type getType() { result = getAnyDef().getResultType() }
|
||||
Language::LanguageType getLanguageType() { result = getAnyDef().getResultLanguageType() }
|
||||
|
||||
/**
|
||||
* Gets the language-neutral type of the value consumed by this operand. This is usually the same
|
||||
* as the result type of the definition instruction consumed by this operand. For register
|
||||
* operands, this is always the case. For some memory operands, the operand type may be different
|
||||
* from the definition type, such as in the case of a partial read or a read from a pointer that
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
final IRType getIRType() { result = getLanguageType().getIRType() }
|
||||
|
||||
/**
|
||||
* Gets the type of the value consumed by this operand. This is usually the same as the
|
||||
* result type of the definition instruction consumed by this operand. For register operands,
|
||||
* this is always the case. For some memory operands, the operand type may be different from
|
||||
* the definition type, such as in the case of a partial read or a read from a pointer that
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
final Language::Type getType() { getLanguageType().hasType(result, _) }
|
||||
|
||||
/**
|
||||
* Holds if the value consumed by this operand is a glvalue. If this
|
||||
* holds, the value of the operand represents the address of a location,
|
||||
* and the type of the location is given by `getType()`. If this does
|
||||
* not hold, the value of the operand represents a value whose type is
|
||||
* given by `getResultType()`.
|
||||
* given by `getType()`.
|
||||
*/
|
||||
predicate isGLValue() { getAnyDef().isGLValue() }
|
||||
final predicate isGLValue() { getLanguageType().hasType(_, true) }
|
||||
|
||||
/**
|
||||
* Gets the size of the value consumed by this operand, in bytes. If the operand does not have
|
||||
* a known constant size, this predicate does not hold.
|
||||
*/
|
||||
int getSize() { result = Language::getTypeSize(getType()) }
|
||||
final int getSize() { result = getLanguageType().getByteSize() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,11 +189,6 @@ class MemoryOperand extends Operand {
|
||||
this = TPhiOperand(_, _, _, _)
|
||||
}
|
||||
|
||||
override predicate isGLValue() {
|
||||
// A `MemoryOperand` can never be a glvalue
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the kind of memory access performed by the operand.
|
||||
*/
|
||||
@@ -239,7 +253,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
|
||||
class TypedOperand extends NonPhiMemoryOperand {
|
||||
override TypedOperandTag tag;
|
||||
|
||||
final override Language::Type getType() {
|
||||
final override Language::LanguageType getLanguageType() {
|
||||
result = Construction::getInstructionOperandType(useInstr, tag)
|
||||
}
|
||||
}
|
||||
@@ -371,12 +385,6 @@ class PositionalArgumentOperand extends ArgumentOperand {
|
||||
class SideEffectOperand extends TypedOperand {
|
||||
override SideEffectOperandTag tag;
|
||||
|
||||
final override int getSize() {
|
||||
if getType() instanceof Language::UnknownType
|
||||
then result = Construction::getInstructionOperandSize(useInstr, tag)
|
||||
else result = Language::getTypeSize(getType())
|
||||
}
|
||||
|
||||
override MemoryAccessKind getMemoryAccess() {
|
||||
useInstr instanceof CallSideEffectInstruction and
|
||||
result instanceof EscapedMayMemoryAccess
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
private import cpp
|
||||
import AliasAnalysis
|
||||
import semmle.code.cpp.ir.internal.Overlap
|
||||
private import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
private import semmle.code.cpp.Print
|
||||
private import semmle.code.cpp.ir.implementation.unaliased_ssa.IR
|
||||
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
|
||||
@@ -10,29 +10,39 @@ private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||
private class IntValue = Ints::IntValue;
|
||||
|
||||
private predicate hasResultMemoryAccess(
|
||||
Instruction instr, IRVariable var, Type type, IntValue startBitOffset, IntValue endBitOffset
|
||||
Instruction instr, IRVariable var, IRType type, Language::LanguageType languageType,
|
||||
IntValue startBitOffset, IntValue endBitOffset
|
||||
) {
|
||||
resultPointsTo(instr.getResultAddress(), var, startBitOffset) and
|
||||
type = instr.getResultType() and
|
||||
if exists(instr.getResultSize())
|
||||
then endBitOffset = Ints::add(startBitOffset, Ints::mul(instr.getResultSize(), 8))
|
||||
languageType = instr.getResultLanguageType() and
|
||||
type = languageType.getIRType() and
|
||||
if exists(type.getByteSize())
|
||||
then endBitOffset = Ints::add(startBitOffset, Ints::mul(type.getByteSize(), 8))
|
||||
else endBitOffset = Ints::unknown()
|
||||
}
|
||||
|
||||
private predicate hasOperandMemoryAccess(
|
||||
MemoryOperand operand, IRVariable var, Type type, IntValue startBitOffset, IntValue endBitOffset
|
||||
MemoryOperand operand, IRVariable var, IRType type, Language::LanguageType languageType,
|
||||
IntValue startBitOffset, IntValue endBitOffset
|
||||
) {
|
||||
resultPointsTo(operand.getAddressOperand().getAnyDef(), var, startBitOffset) and
|
||||
type = operand.getType() and
|
||||
if exists(operand.getSize())
|
||||
then endBitOffset = Ints::add(startBitOffset, Ints::mul(operand.getSize(), 8))
|
||||
languageType = operand.getLanguageType() and
|
||||
type = languageType.getIRType() and
|
||||
if exists(type.getByteSize())
|
||||
then endBitOffset = Ints::add(startBitOffset, Ints::mul(type.getByteSize(), 8))
|
||||
else endBitOffset = Ints::unknown()
|
||||
}
|
||||
|
||||
private newtype TMemoryLocation =
|
||||
TVariableMemoryLocation(IRVariable var, Type type, IntValue startBitOffset, IntValue endBitOffset) {
|
||||
hasResultMemoryAccess(_, var, type, startBitOffset, endBitOffset) or
|
||||
hasOperandMemoryAccess(_, var, type, startBitOffset, endBitOffset)
|
||||
TVariableMemoryLocation(
|
||||
IRVariable var, IRType type, Language::LanguageType languageType, IntValue startBitOffset,
|
||||
IntValue endBitOffset
|
||||
) {
|
||||
(
|
||||
hasResultMemoryAccess(_, var, type, _, startBitOffset, endBitOffset) or
|
||||
hasOperandMemoryAccess(_, var, type, _, startBitOffset, endBitOffset)
|
||||
) and
|
||||
languageType = type.getCanonicalLanguageType()
|
||||
} or
|
||||
TUnknownMemoryLocation(IRFunction irFunc) or
|
||||
TUnknownVirtualVariable(IRFunction irFunc)
|
||||
@@ -49,9 +59,11 @@ abstract class MemoryLocation extends TMemoryLocation {
|
||||
|
||||
abstract VirtualVariable getVirtualVariable();
|
||||
|
||||
abstract Type getType();
|
||||
abstract Language::LanguageType getType();
|
||||
|
||||
abstract string getUniqueId();
|
||||
|
||||
final IRType getIRType() { result = getType().getIRType() }
|
||||
}
|
||||
|
||||
abstract class VirtualVariable extends MemoryLocation { }
|
||||
@@ -62,20 +74,34 @@ abstract class VirtualVariable extends MemoryLocation { }
|
||||
*/
|
||||
class VariableMemoryLocation extends TVariableMemoryLocation, MemoryLocation {
|
||||
IRVariable var;
|
||||
Type type;
|
||||
IRType type;
|
||||
Language::LanguageType languageType;
|
||||
IntValue startBitOffset;
|
||||
IntValue endBitOffset;
|
||||
|
||||
VariableMemoryLocation() {
|
||||
this = TVariableMemoryLocation(var, type, startBitOffset, endBitOffset)
|
||||
this = TVariableMemoryLocation(var, type, languageType, startBitOffset, endBitOffset)
|
||||
}
|
||||
|
||||
final override string toString() {
|
||||
result = var.toString() + Interval::getIntervalString(startBitOffset, endBitOffset) + "<" +
|
||||
type.toString() + ">"
|
||||
type.toString() + ", " + languageType.toString() + ">"
|
||||
}
|
||||
|
||||
final override Type getType() { result = type }
|
||||
final override Language::LanguageType getType() {
|
||||
if
|
||||
strictcount(Language::LanguageType accessType |
|
||||
hasResultMemoryAccess(_, var, type, accessType, startBitOffset, endBitOffset) or
|
||||
hasOperandMemoryAccess(_, var, type, accessType, startBitOffset, endBitOffset)
|
||||
) = 1
|
||||
then
|
||||
// All of the accesses have the same `LanguageType`, so just use that.
|
||||
hasResultMemoryAccess(_, var, type, result, startBitOffset, endBitOffset) or
|
||||
hasOperandMemoryAccess(_, var, type, result, startBitOffset, endBitOffset)
|
||||
else
|
||||
// There is no single type for all accesses, so just use the canonical one for this `IRType`.
|
||||
result = type.getCanonicalLanguageType()
|
||||
}
|
||||
|
||||
final IntValue getStartBitOffset() { result = startBitOffset }
|
||||
|
||||
@@ -85,13 +111,14 @@ class VariableMemoryLocation extends TVariableMemoryLocation, MemoryLocation {
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = var.getUniqueId() + Interval::getIntervalString(startBitOffset, endBitOffset) + "<" +
|
||||
getTypeIdentityString(type) + ">"
|
||||
type.getIdentityString() + ">"
|
||||
}
|
||||
|
||||
final override VirtualVariable getVirtualVariable() {
|
||||
if variableAddressEscapes(var)
|
||||
then result = TUnknownVirtualVariable(var.getEnclosingIRFunction())
|
||||
else result = TVariableMemoryLocation(var, var.getType(), 0, var.getType().getSize() * 8)
|
||||
else
|
||||
result = TVariableMemoryLocation(var, var.getIRType(), _, 0, var.getIRType().getByteSize() * 8)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,7 +126,7 @@ class VariableMemoryLocation extends TVariableMemoryLocation, MemoryLocation {
|
||||
*/
|
||||
final predicate coversEntireVariable() {
|
||||
startBitOffset = 0 and
|
||||
endBitOffset = var.getType().getSize() * 8
|
||||
endBitOffset = var.getIRType().getByteSize() * 8
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +138,7 @@ class VariableMemoryLocation extends TVariableMemoryLocation, MemoryLocation {
|
||||
class VariableVirtualVariable extends VariableMemoryLocation, VirtualVariable {
|
||||
VariableVirtualVariable() {
|
||||
not variableAddressEscapes(var) and
|
||||
type = var.getType() and
|
||||
type = var.getIRType() and
|
||||
coversEntireVariable()
|
||||
}
|
||||
}
|
||||
@@ -128,7 +155,9 @@ class UnknownMemoryLocation extends TUnknownMemoryLocation, MemoryLocation {
|
||||
|
||||
final override VirtualVariable getVirtualVariable() { result = TUnknownVirtualVariable(irFunc) }
|
||||
|
||||
final override Type getType() { result instanceof UnknownType }
|
||||
final override Language::LanguageType getType() {
|
||||
result = any(IRUnknownType type).getCanonicalLanguageType()
|
||||
}
|
||||
|
||||
final override string getUniqueId() { result = "{Unknown}" }
|
||||
}
|
||||
@@ -143,7 +172,9 @@ class UnknownVirtualVariable extends TUnknownVirtualVariable, VirtualVariable {
|
||||
|
||||
final override string toString() { result = "{AllAliased}" }
|
||||
|
||||
final override Type getType() { result instanceof UnknownType }
|
||||
final override Language::LanguageType getType() {
|
||||
result = any(IRUnknownType type).getCanonicalLanguageType()
|
||||
}
|
||||
|
||||
final override string getUniqueId() { result = " " + toString() }
|
||||
|
||||
@@ -177,7 +208,7 @@ Overlap getOverlap(MemoryLocation def, MemoryLocation use) {
|
||||
intervalOverlap = getVariableMemoryLocationOverlap(def, use) and
|
||||
if intervalOverlap instanceof MustExactlyOverlap
|
||||
then
|
||||
if def.getType() = use.getType()
|
||||
if def.getIRType() = use.getIRType()
|
||||
then
|
||||
// The def and use types match, so it's an exact overlap.
|
||||
result instanceof MustExactlyOverlap
|
||||
@@ -282,11 +313,11 @@ MemoryLocation getResultMemoryLocation(Instruction instr) {
|
||||
(
|
||||
(
|
||||
kind.usesAddressOperand() and
|
||||
if hasResultMemoryAccess(instr, _, _, _, _)
|
||||
if hasResultMemoryAccess(instr, _, _, _, _, _)
|
||||
then
|
||||
exists(IRVariable var, Type type, IntValue startBitOffset, IntValue endBitOffset |
|
||||
hasResultMemoryAccess(instr, var, type, startBitOffset, endBitOffset) and
|
||||
result = TVariableMemoryLocation(var, type, startBitOffset, endBitOffset)
|
||||
exists(IRVariable var, IRType type, IntValue startBitOffset, IntValue endBitOffset |
|
||||
hasResultMemoryAccess(instr, var, type, _, startBitOffset, endBitOffset) and
|
||||
result = TVariableMemoryLocation(var, type, _, startBitOffset, endBitOffset)
|
||||
)
|
||||
else result = TUnknownMemoryLocation(instr.getEnclosingIRFunction())
|
||||
)
|
||||
@@ -306,11 +337,11 @@ MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
|
||||
(
|
||||
(
|
||||
kind.usesAddressOperand() and
|
||||
if hasOperandMemoryAccess(operand, _, _, _, _)
|
||||
if hasOperandMemoryAccess(operand, _, _, _, _, _)
|
||||
then
|
||||
exists(IRVariable var, Type type, IntValue startBitOffset, IntValue endBitOffset |
|
||||
hasOperandMemoryAccess(operand, var, type, startBitOffset, endBitOffset) and
|
||||
result = TVariableMemoryLocation(var, type, startBitOffset, endBitOffset)
|
||||
exists(IRVariable var, IRType type, IntValue startBitOffset, IntValue endBitOffset |
|
||||
hasOperandMemoryAccess(operand, var, type, _, startBitOffset, endBitOffset) and
|
||||
result = TVariableMemoryLocation(var, type, _, startBitOffset, endBitOffset)
|
||||
)
|
||||
else result = TUnknownMemoryLocation(operand.getEnclosingIRFunction())
|
||||
)
|
||||
@@ -323,3 +354,4 @@ MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
import semmle.code.cpp.ir.implementation.EdgeKind as EdgeKind
|
||||
import semmle.code.cpp.ir.implementation.IRType as IRType
|
||||
import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import semmle.code.cpp.ir.implementation.IRType as IRType
|
||||
import semmle.code.cpp.ir.implementation.TempVariableTag as TempVariableTag
|
||||
import semmle.code.cpp.ir.internal.IRUtilities as IRUtilities
|
||||
import semmle.code.cpp.ir.internal.TempVariableTag as TTempVariableTag
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind
|
||||
import semmle.code.cpp.ir.implementation.IRType as IRType
|
||||
import semmle.code.cpp.ir.internal.Overlap as Overlap
|
||||
import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag
|
||||
|
||||
@@ -4,34 +4,52 @@ private import Alias
|
||||
private import SSAConstruction
|
||||
private import DebugSSA
|
||||
|
||||
bindingset[offset]
|
||||
private string getKeySuffixForOffset(int offset) {
|
||||
if offset % 2 = 0 then result = "" else result = "_Chi"
|
||||
}
|
||||
|
||||
bindingset[offset]
|
||||
private int getIndexForOffset(int offset) { result = offset / 2 }
|
||||
|
||||
/**
|
||||
* Property provide that dumps the memory access of each result. Useful for debugging SSA
|
||||
* construction.
|
||||
*/
|
||||
class PropertyProvider extends IRPropertyProvider {
|
||||
override string getInstructionProperty(Instruction instruction, string key) {
|
||||
exists(MemoryLocation location |
|
||||
location = getResultMemoryLocation(instruction) and
|
||||
(
|
||||
key = "ResultMemoryLocation" and result = location.toString()
|
||||
or
|
||||
key = "ResultVirtualVariable" and result = location.getVirtualVariable().toString()
|
||||
key = "ResultMemoryLocation" and
|
||||
result = strictconcat(MemoryLocation loc |
|
||||
loc = getResultMemoryLocation(instruction)
|
||||
|
|
||||
loc.toString(), ","
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(MemoryLocation location |
|
||||
location = getOperandMemoryLocation(instruction.getAnOperand()) and
|
||||
(
|
||||
key = "OperandMemoryAccess" and result = location.toString()
|
||||
or
|
||||
key = "OperandVirtualVariable" and result = location.getVirtualVariable().toString()
|
||||
key = "ResultVirtualVariable" and
|
||||
result = strictconcat(MemoryLocation loc |
|
||||
loc = getResultMemoryLocation(instruction)
|
||||
|
|
||||
loc.getVirtualVariable().toString(), ","
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(MemoryLocation useLocation, IRBlock defBlock, int defRank, int defIndex |
|
||||
hasDefinitionAtRank(useLocation, _, defBlock, defRank, defIndex) and
|
||||
defBlock.getInstruction(defIndex) = instruction and
|
||||
key = "DefinitionRank[" + useLocation.toString() + "]" and
|
||||
key = "OperandMemoryLocation" and
|
||||
result = strictconcat(MemoryLocation loc |
|
||||
loc = getOperandMemoryLocation(instruction.getAnOperand())
|
||||
|
|
||||
loc.toString(), ","
|
||||
)
|
||||
or
|
||||
key = "OperandVirtualVariable" and
|
||||
result = strictconcat(MemoryLocation loc |
|
||||
loc = getOperandMemoryLocation(instruction.getAnOperand())
|
||||
|
|
||||
loc.getVirtualVariable().toString(), ","
|
||||
)
|
||||
or
|
||||
exists(MemoryLocation useLocation, IRBlock defBlock, int defRank, int defOffset |
|
||||
hasDefinitionAtRank(useLocation, _, defBlock, defRank, defOffset) and
|
||||
defBlock.getInstruction(getIndexForOffset(defOffset)) = instruction and
|
||||
key = "DefinitionRank" + getKeySuffixForOffset(defOffset) + "[" + useLocation.toString() + "]" and
|
||||
result = defRank.toString()
|
||||
)
|
||||
or
|
||||
@@ -41,10 +59,11 @@ class PropertyProvider extends IRPropertyProvider {
|
||||
result = useRank.toString()
|
||||
)
|
||||
or
|
||||
exists(MemoryLocation useLocation, IRBlock defBlock, int defRank, int defIndex |
|
||||
hasDefinitionAtRank(useLocation, _, defBlock, defRank, defIndex) and
|
||||
defBlock.getInstruction(defIndex) = instruction and
|
||||
key = "DefinitionReachesUse[" + useLocation.toString() + "]" and
|
||||
exists(MemoryLocation useLocation, IRBlock defBlock, int defRank, int defOffset |
|
||||
hasDefinitionAtRank(useLocation, _, defBlock, defRank, defOffset) and
|
||||
defBlock.getInstruction(getIndexForOffset(defOffset)) = instruction and
|
||||
key = "DefinitionReachesUse" + getKeySuffixForOffset(defOffset) + "[" + useLocation.toString()
|
||||
+ "]" and
|
||||
result = strictconcat(IRBlock useBlock, int useRank, int useIndex |
|
||||
exists(Instruction useInstruction |
|
||||
hasUseAtRank(useLocation, useBlock, useRank, useInstruction) and
|
||||
@@ -124,3 +143,4 @@ class PropertyProvider extends IRPropertyProvider {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import SSAConstructionInternal
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.implementation.Opcode
|
||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||
private import semmle.code.cpp.ir.internal.Overlap
|
||||
@@ -18,7 +17,7 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
predicate functionHasIR(Function func) {
|
||||
predicate functionHasIR(Language::Function func) {
|
||||
exists(OldIR::IRFunction irFunc | irFunc.getFunction() = func)
|
||||
}
|
||||
|
||||
@@ -42,7 +41,7 @@ private module Cached {
|
||||
not oldInstruction instanceof OldIR::PhiInstruction and
|
||||
hasChiNode(_, oldInstruction)
|
||||
} or
|
||||
Unreached(Function function) {
|
||||
Unreached(Language::Function function) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
function = oldInstruction.getEnclosingFunction() and
|
||||
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
|
||||
@@ -50,12 +49,14 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, Type type) {
|
||||
predicate hasTempVariable(
|
||||
Language::Function func, Language::AST ast, TempVariableTag tag, Language::LanguageType type
|
||||
) {
|
||||
exists(OldIR::IRTempVariable var |
|
||||
var.getEnclosingFunction() = func and
|
||||
var.getAST() = ast and
|
||||
var.getTag() = tag and
|
||||
var.getType() = type
|
||||
var.getLanguageType() = type
|
||||
)
|
||||
}
|
||||
|
||||
@@ -135,24 +136,12 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
Type getInstructionOperandType(Instruction instr, TypedOperandTag tag) {
|
||||
Language::LanguageType getInstructionOperandType(Instruction instr, TypedOperandTag tag) {
|
||||
exists(OldInstruction oldInstruction, OldIR::TypedOperand oldOperand |
|
||||
oldInstruction = getOldInstruction(instr) and
|
||||
oldOperand = oldInstruction.getAnOperand() and
|
||||
tag = oldOperand.getOperandTag() and
|
||||
result = oldOperand.getType()
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
int getInstructionOperandSize(Instruction instr, SideEffectOperandTag tag) {
|
||||
exists(OldInstruction oldInstruction, OldIR::SideEffectOperand oldOperand |
|
||||
oldInstruction = getOldInstruction(instr) and
|
||||
oldOperand = oldInstruction.getAnOperand() and
|
||||
tag = oldOperand.getOperandTag() and
|
||||
// Only return a result for operands that need an explicit result size.
|
||||
oldOperand.getType() instanceof UnknownType and
|
||||
result = oldOperand.getSize()
|
||||
result = oldOperand.getLanguageType()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -196,20 +185,21 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
Expr getInstructionConvertedResultExpression(Instruction instruction) {
|
||||
Language::Expr getInstructionConvertedResultExpression(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).getConvertedResultExpression()
|
||||
}
|
||||
|
||||
cached
|
||||
Expr getInstructionUnconvertedResultExpression(Instruction instruction) {
|
||||
Language::Expr getInstructionUnconvertedResultExpression(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).getUnconvertedResultExpression()
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* This adds Chi nodes to the instruction successor relation; if an instruction has a Chi node,
|
||||
* that node is its successor in the new successor relation, and the Chi node's successors are
|
||||
* the new instructions generated from the successors of the old instruction
|
||||
*/
|
||||
|
||||
cached
|
||||
Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
|
||||
if hasChiNode(_, getOldInstruction(instruction))
|
||||
@@ -252,7 +242,7 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
Locatable getInstructionAST(Instruction instruction) {
|
||||
Language::AST getInstructionAST(Instruction instruction) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = WrappedInstruction(oldInstruction)
|
||||
or
|
||||
@@ -270,29 +260,25 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
predicate instructionHasType(Instruction instruction, Type type, boolean isGLValue) {
|
||||
Language::LanguageType getInstructionResultType(Instruction instruction) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = WrappedInstruction(oldInstruction) and
|
||||
type = oldInstruction.getResultType() and
|
||||
if oldInstruction.isGLValue() then isGLValue = true else isGLValue = false
|
||||
result = oldInstruction.getResultLanguageType()
|
||||
)
|
||||
or
|
||||
exists(OldInstruction oldInstruction, Alias::VirtualVariable vvar |
|
||||
instruction = Chi(oldInstruction) and
|
||||
hasChiNode(vvar, oldInstruction) and
|
||||
type = vvar.getType() and
|
||||
isGLValue = false
|
||||
result = vvar.getType()
|
||||
)
|
||||
or
|
||||
exists(Alias::MemoryLocation location |
|
||||
instruction = Phi(_, location) and
|
||||
type = location.getType() and
|
||||
isGLValue = false
|
||||
result = location.getType()
|
||||
)
|
||||
or
|
||||
instruction = Unreached(_) and
|
||||
type instanceof VoidType and
|
||||
isGLValue = false
|
||||
result = Language::getVoidType()
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -338,12 +324,12 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
Field getInstructionField(Instruction instruction) {
|
||||
Language::Field getInstructionField(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::FieldInstruction).getField()
|
||||
}
|
||||
|
||||
cached
|
||||
Function getInstructionFunction(Instruction instruction) {
|
||||
Language::Function getInstructionFunction(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::FunctionInstruction).getFunctionSymbol()
|
||||
}
|
||||
|
||||
@@ -353,19 +339,19 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
StringLiteral getInstructionStringLiteral(Instruction instruction) {
|
||||
Language::StringLiteral getInstructionStringLiteral(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue()
|
||||
}
|
||||
|
||||
cached
|
||||
BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) {
|
||||
Language::BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) {
|
||||
result = getOldInstruction(instruction)
|
||||
.(OldIR::BuiltInOperationInstruction)
|
||||
.getBuiltInOperation()
|
||||
}
|
||||
|
||||
cached
|
||||
Type getInstructionExceptionType(Instruction instruction) {
|
||||
Language::LanguageType getInstructionExceptionType(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::CatchByTypeInstruction).getExceptionType()
|
||||
}
|
||||
|
||||
@@ -375,14 +361,9 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
int getInstructionResultSize(Instruction instruction) {
|
||||
// Only return a result for instructions that needed an explicit result size.
|
||||
instruction.getResultType() instanceof UnknownType and
|
||||
result = getOldInstruction(instruction).getResultSize()
|
||||
}
|
||||
|
||||
cached
|
||||
predicate getInstructionInheritance(Instruction instruction, Class baseClass, Class derivedClass) {
|
||||
predicate getInstructionInheritance(
|
||||
Instruction instruction, Language::Class baseClass, Language::Class derivedClass
|
||||
) {
|
||||
exists(OldIR::InheritanceConversionInstruction oldInstr |
|
||||
oldInstr = getOldInstruction(instruction) and
|
||||
baseClass = oldInstr.getBaseClass() and
|
||||
@@ -879,3 +860,4 @@ private module CachedForDebugging {
|
||||
result.getTag() = var.getTag()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,4 +2,5 @@ import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as OldIR
|
||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.reachability.ReachableBlock as Reachability
|
||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.reachability.Dominance as Dominance
|
||||
import semmle.code.cpp.ir.implementation.aliased_ssa.IR as NewIR
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
import AliasedSSA as Alias
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
@@ -2,11 +2,11 @@ private import TIRVariableInternal
|
||||
private import Imports::TempVariableTag
|
||||
|
||||
newtype TIRVariable =
|
||||
TIRUserVariable(Language::Variable var, Language::Type type, Language::Function func) {
|
||||
TIRUserVariable(Language::Variable var, Language::LanguageType type, Language::Function func) {
|
||||
Construction::hasUserVariable(func, var, type)
|
||||
} or
|
||||
TIRTempVariable(
|
||||
Language::Function func, Language::AST ast, TempVariableTag tag, Language::Type type
|
||||
Language::Function func, Language::AST ast, TempVariableTag tag, Language::LanguageType type
|
||||
) {
|
||||
Construction::hasTempVariable(func, ast, tag, type)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import IRVariable
|
||||
import Operand
|
||||
private import internal.IRImports as Imports
|
||||
import Imports::EdgeKind
|
||||
import Imports::IRType
|
||||
import Imports::MemoryAccessKind
|
||||
|
||||
private newtype TIRPropertyProvider = MkIRPropertyProvider()
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
private import IR
|
||||
import InstructionSanity
|
||||
import IRTypeSanity
|
||||
@@ -5,6 +5,7 @@ import Imports::TempVariableTag
|
||||
private import Imports::IRUtilities
|
||||
private import Imports::TTempVariableTag
|
||||
private import Imports::TIRVariable
|
||||
private import Imports::IRType
|
||||
|
||||
IRUserVariable getIRUserVariable(Language::Function func, Language::Variable var) {
|
||||
result.getVariable() = var and
|
||||
@@ -24,7 +25,21 @@ abstract class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
abstract Language::Type getType();
|
||||
final Language::Type getType() {
|
||||
getLanguageType().hasType(result, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the language-neutral type of the variable.
|
||||
*/
|
||||
final IRType getIRType() {
|
||||
result = getLanguageType().getIRType()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
abstract Language::LanguageType getLanguageType();
|
||||
|
||||
/**
|
||||
* Gets the AST node that declared this variable, or that introduced this
|
||||
@@ -59,7 +74,7 @@ abstract class IRVariable extends TIRVariable {
|
||||
*/
|
||||
class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
Language::Variable var;
|
||||
Language::Type type;
|
||||
Language::LanguageType type;
|
||||
|
||||
IRUserVariable() { this = TIRUserVariable(var, type, func) }
|
||||
|
||||
@@ -71,7 +86,7 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
result = getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
}
|
||||
|
||||
final override Language::Type getType() { result = type }
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
/**
|
||||
* Gets the original user-declared variable.
|
||||
@@ -110,11 +125,11 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
|
||||
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
|
||||
Language::AST ast;
|
||||
TempVariableTag tag;
|
||||
Language::Type type;
|
||||
Language::LanguageType type;
|
||||
|
||||
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }
|
||||
|
||||
final override Language::Type getType() { result = type }
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
final override Language::AST getAST() { result = ast }
|
||||
|
||||
|
||||
@@ -113,10 +113,13 @@ module InstructionSanity {
|
||||
}
|
||||
|
||||
query predicate missingOperandType(Operand operand, string message) {
|
||||
exists(Language::Function func |
|
||||
exists(Language::Function func, Instruction use |
|
||||
not exists(operand.getType()) and
|
||||
func = operand.getUse().getEnclosingFunction() and
|
||||
message = "Operand missing type in function '" + Language::getIdentityString(func) + "'."
|
||||
use = operand.getUse() and
|
||||
func = use.getEnclosingFunction() and
|
||||
message = "Operand '" + operand.toString() + "' of instruction '" +
|
||||
use.getOpcode().toString() + "' missing type in function '" +
|
||||
Language::getIdentityString(func) + "'."
|
||||
)
|
||||
}
|
||||
|
||||
@@ -344,23 +347,6 @@ class Instruction extends Construction::TInstruction {
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[type]
|
||||
private string getValueCategoryString(string type) {
|
||||
if isGLValue() then result = "glval<" + type + ">" else result = type
|
||||
}
|
||||
|
||||
string getResultTypeString() {
|
||||
exists(string valcat |
|
||||
valcat = getValueCategoryString(getResultType().toString()) and
|
||||
if
|
||||
getResultType() instanceof Language::UnknownType and
|
||||
not isGLValue() and
|
||||
exists(getResultSize())
|
||||
then result = valcat + "[" + getResultSize().toString() + "]"
|
||||
else result = valcat
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a human-readable string that uniquely identifies this instruction
|
||||
* within the function. This string is used to refer to this instruction when
|
||||
@@ -380,7 +366,9 @@ class Instruction extends Construction::TInstruction {
|
||||
*
|
||||
* Example: `r1_1(int*)`
|
||||
*/
|
||||
final string getResultString() { result = getResultId() + "(" + getResultTypeString() + ")" }
|
||||
final string getResultString() {
|
||||
result = getResultId() + "(" + getResultLanguageType().getDumpString() + ")"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string describing the operands of this instruction, suitable for
|
||||
@@ -448,6 +436,10 @@ class Instruction extends Construction::TInstruction {
|
||||
result = Construction::getInstructionUnconvertedResultExpression(this)
|
||||
}
|
||||
|
||||
final Language::LanguageType getResultLanguageType() {
|
||||
result = Construction::getInstructionResultType(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the result produced by this instruction. If the
|
||||
* instruction does not produce a result, its result type will be `VoidType`.
|
||||
@@ -455,7 +447,16 @@ class Instruction extends Construction::TInstruction {
|
||||
* If `isGLValue()` holds, then the result type of this instruction should be
|
||||
* thought of as "pointer to `getResultType()`".
|
||||
*/
|
||||
final Language::Type getResultType() { Construction::instructionHasType(this, result, _) }
|
||||
final Language::Type getResultType() {
|
||||
exists(Language::LanguageType resultType, Language::Type langType |
|
||||
resultType = getResultLanguageType() and
|
||||
(
|
||||
resultType.hasType(langType, _) or
|
||||
not resultType.hasType(_, _) and result instanceof Language::UnknownType
|
||||
) and
|
||||
result = langType.getUnspecifiedType()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the result produced by this instruction is a glvalue. If this
|
||||
@@ -475,7 +476,9 @@ class Instruction extends Construction::TInstruction {
|
||||
* result of the `Load` instruction is a prvalue of type `int`, representing
|
||||
* the integer value loaded from variable `x`.
|
||||
*/
|
||||
final predicate isGLValue() { Construction::instructionHasType(this, _, true) }
|
||||
final predicate isGLValue() {
|
||||
Construction::getInstructionResultType(this).hasType(_, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of the result produced by this instruction, in bytes. If the
|
||||
@@ -485,14 +488,7 @@ class Instruction extends Construction::TInstruction {
|
||||
* `getResultSize()` will always be the size of a pointer.
|
||||
*/
|
||||
final int getResultSize() {
|
||||
if isGLValue()
|
||||
then
|
||||
// a glvalue is always pointer-sized.
|
||||
result = Language::getPointerSize()
|
||||
else
|
||||
if getResultType() instanceof Language::UnknownType
|
||||
then result = Construction::getInstructionResultSize(this)
|
||||
else result = Language::getTypeSize(getResultType())
|
||||
result = Construction::getInstructionResultType(this).getByteSize()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1300,7 +1296,7 @@ class CatchInstruction extends Instruction {
|
||||
* An instruction that catches an exception of a specific type.
|
||||
*/
|
||||
class CatchByTypeInstruction extends CatchInstruction {
|
||||
Language::Type exceptionType;
|
||||
Language::LanguageType exceptionType;
|
||||
|
||||
CatchByTypeInstruction() {
|
||||
getOpcode() instanceof Opcode::CatchByType and
|
||||
@@ -1312,7 +1308,7 @@ class CatchByTypeInstruction extends CatchInstruction {
|
||||
/**
|
||||
* Gets the type of exception to be caught.
|
||||
*/
|
||||
final Language::Type getExceptionType() { result = exceptionType }
|
||||
final Language::LanguageType getExceptionType() { result = exceptionType }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
private import internal.IRInternal
|
||||
import Instruction
|
||||
import IRBlock
|
||||
private import Instruction
|
||||
private import IRBlock
|
||||
private import internal.OperandImports as Imports
|
||||
import Imports::MemoryAccessKind
|
||||
import Imports::Overlap
|
||||
private import Imports::MemoryAccessKind
|
||||
private import Imports::IRType
|
||||
private import Imports::Overlap
|
||||
private import Imports::OperandTag
|
||||
|
||||
cached
|
||||
@@ -143,22 +144,40 @@ class Operand extends TOperand {
|
||||
* the definition type, such as in the case of a partial read or a read from a pointer that
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
Language::Type getType() { result = getAnyDef().getResultType() }
|
||||
Language::LanguageType getLanguageType() { result = getAnyDef().getResultLanguageType() }
|
||||
|
||||
/**
|
||||
* Gets the language-neutral type of the value consumed by this operand. This is usually the same
|
||||
* as the result type of the definition instruction consumed by this operand. For register
|
||||
* operands, this is always the case. For some memory operands, the operand type may be different
|
||||
* from the definition type, such as in the case of a partial read or a read from a pointer that
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
final IRType getIRType() { result = getLanguageType().getIRType() }
|
||||
|
||||
/**
|
||||
* Gets the type of the value consumed by this operand. This is usually the same as the
|
||||
* result type of the definition instruction consumed by this operand. For register operands,
|
||||
* this is always the case. For some memory operands, the operand type may be different from
|
||||
* the definition type, such as in the case of a partial read or a read from a pointer that
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
final Language::Type getType() { getLanguageType().hasType(result, _) }
|
||||
|
||||
/**
|
||||
* Holds if the value consumed by this operand is a glvalue. If this
|
||||
* holds, the value of the operand represents the address of a location,
|
||||
* and the type of the location is given by `getType()`. If this does
|
||||
* not hold, the value of the operand represents a value whose type is
|
||||
* given by `getResultType()`.
|
||||
* given by `getType()`.
|
||||
*/
|
||||
predicate isGLValue() { getAnyDef().isGLValue() }
|
||||
final predicate isGLValue() { getLanguageType().hasType(_, true) }
|
||||
|
||||
/**
|
||||
* Gets the size of the value consumed by this operand, in bytes. If the operand does not have
|
||||
* a known constant size, this predicate does not hold.
|
||||
*/
|
||||
int getSize() { result = Language::getTypeSize(getType()) }
|
||||
final int getSize() { result = getLanguageType().getByteSize() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,11 +189,6 @@ class MemoryOperand extends Operand {
|
||||
this = TPhiOperand(_, _, _, _)
|
||||
}
|
||||
|
||||
override predicate isGLValue() {
|
||||
// A `MemoryOperand` can never be a glvalue
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the kind of memory access performed by the operand.
|
||||
*/
|
||||
@@ -239,7 +253,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
|
||||
class TypedOperand extends NonPhiMemoryOperand {
|
||||
override TypedOperandTag tag;
|
||||
|
||||
final override Language::Type getType() {
|
||||
final override Language::LanguageType getLanguageType() {
|
||||
result = Construction::getInstructionOperandType(useInstr, tag)
|
||||
}
|
||||
}
|
||||
@@ -371,12 +385,6 @@ class PositionalArgumentOperand extends ArgumentOperand {
|
||||
class SideEffectOperand extends TypedOperand {
|
||||
override SideEffectOperandTag tag;
|
||||
|
||||
final override int getSize() {
|
||||
if getType() instanceof Language::UnknownType
|
||||
then result = Construction::getInstructionOperandSize(useInstr, tag)
|
||||
else result = Language::getTypeSize(getType())
|
||||
}
|
||||
|
||||
override MemoryAccessKind getMemoryAccess() {
|
||||
useInstr instanceof CallSideEffectInstruction and
|
||||
result instanceof EscapedMayMemoryAccess
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
private import cpp
|
||||
import semmle.code.cpp.ir.implementation.raw.IR
|
||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||
private import semmle.code.cpp.ir.internal.CppType
|
||||
private import semmle.code.cpp.ir.internal.Overlap
|
||||
private import semmle.code.cpp.ir.internal.TempVariableTag
|
||||
private import InstructionTag
|
||||
private import TranslatedCondition
|
||||
@@ -25,16 +27,16 @@ private module Cached {
|
||||
cached
|
||||
newtype TInstruction =
|
||||
MkInstruction(TranslatedElement element, InstructionTag tag) {
|
||||
element.hasInstruction(_, tag, _, _)
|
||||
element.hasInstruction(_, tag, _)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasUserVariable(Function func, Variable var, Type type) {
|
||||
predicate hasUserVariable(Function func, Variable var, CppType type) {
|
||||
getTranslatedFunction(func).hasUserVariable(var, type)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, Type type) {
|
||||
predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, CppType type) {
|
||||
exists(TranslatedElement element |
|
||||
element.getAST() = ast and
|
||||
func = element.getFunction() and
|
||||
@@ -82,22 +84,16 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
Type getInstructionOperandType(Instruction instruction, TypedOperandTag tag) {
|
||||
CppType getInstructionOperandType(Instruction instruction, TypedOperandTag tag) {
|
||||
// For all `LoadInstruction`s, the operand type of the `LoadOperand` is the same as
|
||||
// the result type of the load.
|
||||
result = instruction.(LoadInstruction).getResultType()
|
||||
result = instruction.(LoadInstruction).getResultLanguageType()
|
||||
or
|
||||
not instruction instanceof LoadInstruction and
|
||||
result = getInstructionTranslatedElement(instruction)
|
||||
.getInstructionOperandType(getInstructionTag(instruction), tag)
|
||||
}
|
||||
|
||||
cached
|
||||
int getInstructionOperandSize(Instruction instruction, SideEffectOperandTag tag) {
|
||||
result = getInstructionTranslatedElement(instruction)
|
||||
.getInstructionOperandSize(getInstructionTag(instruction), tag)
|
||||
}
|
||||
|
||||
cached
|
||||
Instruction getPhiOperandDefinition(
|
||||
PhiInstruction instruction, IRBlock predecessorBlock, Overlap overlap
|
||||
@@ -217,15 +213,15 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
predicate instructionHasType(Instruction instruction, Type type, boolean isGLValue) {
|
||||
CppType getInstructionResultType(Instruction instruction) {
|
||||
getInstructionTranslatedElement(instruction)
|
||||
.hasInstruction(_, getInstructionTag(instruction), type, isGLValue)
|
||||
.hasInstruction(_, getInstructionTag(instruction), result)
|
||||
}
|
||||
|
||||
cached
|
||||
Opcode getInstructionOpcode(Instruction instruction) {
|
||||
getInstructionTranslatedElement(instruction)
|
||||
.hasInstruction(result, getInstructionTag(instruction), _, _)
|
||||
.hasInstruction(result, getInstructionTag(instruction), _)
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -272,7 +268,7 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
Type getInstructionExceptionType(Instruction instruction) {
|
||||
CppType getInstructionExceptionType(Instruction instruction) {
|
||||
result = getInstructionTranslatedElement(instruction)
|
||||
.getInstructionExceptionType(getInstructionTag(instruction))
|
||||
}
|
||||
@@ -299,6 +295,13 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate needsUnknownBlobType(int byteSize) {
|
||||
exists(TranslatedElement element |
|
||||
element.needsUnknownBlobType(byteSize)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
int getInstructionResultSize(Instruction instruction) {
|
||||
exists(TranslatedElement element, InstructionTag tag |
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
import semmle.code.cpp.ir.implementation.EdgeKind as EdgeKind
|
||||
import semmle.code.cpp.ir.implementation.IRType as IRType
|
||||
import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import semmle.code.cpp.ir.implementation.IRType as IRType
|
||||
import semmle.code.cpp.ir.implementation.TempVariableTag as TempVariableTag
|
||||
import semmle.code.cpp.ir.internal.IRUtilities as IRUtilities
|
||||
import semmle.code.cpp.ir.internal.TempVariableTag as TTempVariableTag
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind
|
||||
import semmle.code.cpp.ir.implementation.IRType as IRType
|
||||
import semmle.code.cpp.ir.internal.Overlap as Overlap
|
||||
import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.implementation.Opcode
|
||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||
private import semmle.code.cpp.ir.internal.CppType
|
||||
private import semmle.code.cpp.models.interfaces.SideEffect
|
||||
private import InstructionTag
|
||||
private import TranslatedElement
|
||||
@@ -30,13 +31,10 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
else result = getFirstCallTargetInstruction()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = CallTag() and
|
||||
opcode instanceof Opcode::Call and
|
||||
resultType = getCallResultType() and
|
||||
isGLValue = false
|
||||
resultType = getTypeForPRValue(getCallResultType())
|
||||
or
|
||||
hasSideEffect() and
|
||||
tag = CallSideEffectTag() and
|
||||
@@ -44,13 +42,12 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
if hasWriteSideEffect()
|
||||
then (
|
||||
opcode instanceof Opcode::CallSideEffect and
|
||||
resultType instanceof UnknownType
|
||||
resultType = getUnknownType()
|
||||
) else (
|
||||
opcode instanceof Opcode::CallReadSideEffect and
|
||||
resultType instanceof VoidType
|
||||
resultType = getVoidType()
|
||||
)
|
||||
) and
|
||||
isGLValue = false
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
@@ -105,11 +102,11 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
result = getEnclosingFunction().getUnmodeledDefinitionInstruction()
|
||||
}
|
||||
|
||||
final override Type getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) {
|
||||
final override CppType getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) {
|
||||
tag = CallSideEffectTag() and
|
||||
hasSideEffect() and
|
||||
operandTag instanceof SideEffectOperandTag and
|
||||
result instanceof UnknownType
|
||||
result = getUnknownType()
|
||||
}
|
||||
|
||||
final override Instruction getResult() { result = getInstruction(CallTag()) }
|
||||
@@ -205,18 +202,12 @@ abstract class TranslatedDirectCall extends TranslatedCall {
|
||||
|
||||
final override Instruction getCallTargetResult() { result = getInstruction(CallTargetTag()) }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
TranslatedCall.super.hasInstruction(opcode, tag, resultType, isGLValue)
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
TranslatedCall.super.hasInstruction(opcode, tag, resultType)
|
||||
or
|
||||
tag = CallTargetTag() and
|
||||
opcode instanceof Opcode::FunctionAddress and
|
||||
// The database does not contain a `FunctionType` for a function unless
|
||||
// its address was taken, so we'll just use glval<Unknown> instead of
|
||||
// glval<FunctionType>.
|
||||
resultType instanceof UnknownType and
|
||||
isGLValue = true
|
||||
resultType = getFunctionGLValueType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -234,7 +225,7 @@ abstract class TranslatedDirectCall extends TranslatedCall {
|
||||
abstract class TranslatedCallExpr extends TranslatedNonConstantExpr, TranslatedCall {
|
||||
override Call expr;
|
||||
|
||||
final override Type getCallResultType() { result = getResultType() }
|
||||
final override Type getCallResultType() { result = expr.getType() }
|
||||
|
||||
final override predicate hasArguments() { exists(expr.getArgument(0)) }
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.implementation.Opcode
|
||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||
private import semmle.code.cpp.ir.internal.CppType
|
||||
private import InstructionTag
|
||||
private import TranslatedElement
|
||||
private import TranslatedExpr
|
||||
@@ -37,9 +38,7 @@ abstract class TranslatedFlexibleCondition extends TranslatedCondition, Conditio
|
||||
|
||||
final override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() }
|
||||
|
||||
final override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
@@ -105,9 +104,7 @@ abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeConditio
|
||||
result = getLeftOperand().getFirstInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
@@ -163,13 +160,10 @@ class TranslatedValueCondition extends TranslatedCondition, TTranslatedValueCond
|
||||
|
||||
override Instruction getFirstInstruction() { result = getValueExpr().getFirstInstruction() }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
opcode instanceof Opcode::ConditionalBranch and
|
||||
resultType instanceof VoidType and
|
||||
isGLValue = false
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.implementation.Opcode
|
||||
private import semmle.code.cpp.ir.internal.IRUtilities
|
||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||
private import semmle.code.cpp.ir.internal.CppType
|
||||
private import semmle.code.cpp.ir.internal.IRUtilities
|
||||
private import InstructionTag
|
||||
private import TranslatedElement
|
||||
private import TranslatedExpr
|
||||
@@ -54,19 +55,15 @@ abstract class TranslatedVariableDeclaration extends TranslatedElement, Initiali
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getVariableType(getVariable()) and
|
||||
isGLValue = true
|
||||
resultType = getTypeForGLValue(getVariableType(getVariable()))
|
||||
or
|
||||
hasUninitializedInstruction() and
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Uninitialized and
|
||||
resultType = getVariableType(getVariable()) and
|
||||
isGLValue = false
|
||||
resultType = getTypeForPRValue(getVariableType(getVariable()))
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import semmle.code.cpp.ir.implementation.raw.IR
|
||||
private import semmle.code.cpp.ir.IRConfiguration
|
||||
private import semmle.code.cpp.ir.implementation.Opcode
|
||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||
private import semmle.code.cpp.ir.internal.CppType
|
||||
private import semmle.code.cpp.ir.internal.TempVariableTag
|
||||
private import InstructionTag
|
||||
private import TranslatedCondition
|
||||
@@ -10,11 +11,6 @@ private import TranslatedFunction
|
||||
private import TranslatedStmt
|
||||
private import IRConstruction
|
||||
|
||||
/**
|
||||
* Gets the built-in `int` type.
|
||||
*/
|
||||
Type getIntType() { result.(IntType).isImplicitlySigned() }
|
||||
|
||||
/**
|
||||
* Gets the "real" parent of `expr`. This predicate treats conversions as if
|
||||
* they were explicit nodes in the expression tree, rather than as implicit
|
||||
@@ -65,8 +61,8 @@ private predicate ignoreExprAndDescendants(Expr expr) {
|
||||
)
|
||||
or
|
||||
// Do not translate input/output variables in GNU asm statements
|
||||
getRealParent(expr) instanceof AsmStmt
|
||||
or
|
||||
// getRealParent(expr) instanceof AsmStmt
|
||||
// or
|
||||
ignoreExprAndDescendants(getRealParent(expr)) // recursive case
|
||||
or
|
||||
// We do not yet translate destructors properly, so for now we ignore any
|
||||
@@ -494,9 +490,7 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
* If the instruction does not return a result, `resultType` should be
|
||||
* `VoidType`.
|
||||
*/
|
||||
abstract predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
);
|
||||
abstract predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType);
|
||||
|
||||
/**
|
||||
* Gets the `Function` that contains this element.
|
||||
@@ -536,7 +530,7 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
* `tag` must be unique for each variable generated from the same AST node
|
||||
* (not just from the same `TranslatedElement`).
|
||||
*/
|
||||
predicate hasTempVariable(TempVariableTag tag, Type type) { none() }
|
||||
predicate hasTempVariable(TempVariableTag tag, CppType type) { none() }
|
||||
|
||||
/**
|
||||
* If the instruction specified by `tag` is a `FunctionInstruction`, gets the
|
||||
@@ -575,6 +569,8 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
*/
|
||||
int getInstructionResultSize(InstructionTag tag) { none() }
|
||||
|
||||
predicate needsUnknownBlobType(int byteSize) { none() }
|
||||
|
||||
/**
|
||||
* If the instruction specified by `tag` is a `StringConstantInstruction`,
|
||||
* gets the `StringLiteral` for that instruction.
|
||||
@@ -590,7 +586,7 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
* If the instruction specified by `tag` is a `CatchByTypeInstruction`,
|
||||
* gets the type of the exception to be caught.
|
||||
*/
|
||||
Type getInstructionExceptionType(InstructionTag tag) { none() }
|
||||
CppType getInstructionExceptionType(InstructionTag tag) { none() }
|
||||
|
||||
/**
|
||||
* If the instruction specified by `tag` is an `InheritanceConversionInstruction`,
|
||||
@@ -609,7 +605,7 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
/**
|
||||
* Gets the type of the memory operand specified by `operandTag` on the the instruction specified by `tag`.
|
||||
*/
|
||||
Type getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) { none() }
|
||||
CppType getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) { none() }
|
||||
|
||||
/**
|
||||
* Gets the size of the memory operand specified by `operandTag` on the the instruction specified by `tag`.
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.implementation.IRType
|
||||
private import semmle.code.cpp.ir.implementation.Opcode
|
||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||
private import semmle.code.cpp.ir.internal.CppType
|
||||
private import semmle.code.cpp.ir.internal.TempVariableTag
|
||||
private import InstructionTag
|
||||
private import TranslatedCondition
|
||||
@@ -51,10 +53,23 @@ abstract class TranslatedExpr extends TranslatedElement {
|
||||
*/
|
||||
abstract predicate producesExprResult();
|
||||
|
||||
final CppType getResultType() {
|
||||
if isResultGLValue() then
|
||||
result = getTypeForGLValue(expr.getType())
|
||||
else
|
||||
result = getTypeForPRValue(expr.getType())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the result produced by this expression.
|
||||
* Holds if the result of this `TranslatedExpr` is a glvalue.
|
||||
*/
|
||||
final Type getResultType() { result = expr.getUnspecifiedType() }
|
||||
private predicate isResultGLValue() {
|
||||
expr.isGLValueCategory()
|
||||
or
|
||||
// If this TranslatedExpr doesn't produce the result, then it must represent
|
||||
// a glvalue that is then loaded by a TranslatedLoad.
|
||||
not producesExprResult()
|
||||
}
|
||||
|
||||
final override Locatable getAST() { result = expr }
|
||||
|
||||
@@ -91,25 +106,6 @@ abstract class TranslatedCoreExpr extends TranslatedExpr {
|
||||
// is the only TranslatedExpr.
|
||||
ignoreLoad(expr)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if the result of this `TranslatedExpr` is a glvalue, or
|
||||
* `false` if the result is a prvalue.
|
||||
*
|
||||
* This predicate returns a `boolean` value instead of just a being a plain
|
||||
* predicate because all of the subclass predicates that call it require a
|
||||
* `boolean` value.
|
||||
*/
|
||||
final boolean isResultGLValue() {
|
||||
if
|
||||
expr.isGLValueCategory()
|
||||
or
|
||||
// If this TranslatedExpr doesn't produce the result, then it must represent
|
||||
// a glvalue that is then loaded by a TranslatedLoad.
|
||||
not producesExprResult()
|
||||
then result = true
|
||||
else result = false
|
||||
}
|
||||
}
|
||||
|
||||
class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext,
|
||||
@@ -120,38 +116,32 @@ class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext,
|
||||
|
||||
override Instruction getFirstInstruction() { result = getCondition().getFirstInstruction() }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
(
|
||||
tag = ConditionValueTrueTempAddressTag() or
|
||||
tag = ConditionValueFalseTempAddressTag() or
|
||||
tag = ConditionValueResultTempAddressTag()
|
||||
) and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getResultType() and
|
||||
isGLValue = true
|
||||
resultType = getTypeForGLValue(expr.getType())
|
||||
or
|
||||
(
|
||||
tag = ConditionValueTrueConstantTag() or
|
||||
tag = ConditionValueFalseConstantTag()
|
||||
) and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getResultType() and
|
||||
isGLValue = isResultGLValue()
|
||||
resultType = getResultType()
|
||||
or
|
||||
(
|
||||
tag = ConditionValueTrueStoreTag() or
|
||||
tag = ConditionValueFalseStoreTag()
|
||||
) and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getResultType() and
|
||||
isGLValue = isResultGLValue()
|
||||
resultType = getResultType()
|
||||
or
|
||||
tag = ConditionValueResultLoadTag() and
|
||||
opcode instanceof Opcode::Load and
|
||||
resultType = getResultType() and
|
||||
isGLValue = isResultGLValue()
|
||||
resultType = getResultType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -212,9 +202,9 @@ class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext,
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasTempVariable(TempVariableTag tag, Type type) {
|
||||
override predicate hasTempVariable(TempVariableTag tag, CppType type) {
|
||||
tag = ConditionValueTempVar() and
|
||||
type = getResultType()
|
||||
type = getTypeForPRValue(expr.getType())
|
||||
}
|
||||
|
||||
override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
@@ -262,13 +252,10 @@ class TranslatedLoad extends TranslatedExpr, TTranslatedLoad {
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getOperand() }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = LoadTag() and
|
||||
opcode instanceof Opcode::Load and
|
||||
resultType = expr.getUnspecifiedType() and
|
||||
if expr.isGLValueCategory() then isGLValue = true else isGLValue = false
|
||||
resultType = getResultType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -324,9 +311,7 @@ class TranslatedCommaExpr extends TranslatedNonConstantExpr {
|
||||
child = getRightOperand() and result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
@@ -341,6 +326,10 @@ class TranslatedCommaExpr extends TranslatedNonConstantExpr {
|
||||
}
|
||||
}
|
||||
|
||||
private int getElementSize(Type type) {
|
||||
result = max(type.getUnspecifiedType().(PointerType).getBaseType().getSize())
|
||||
}
|
||||
|
||||
abstract class TranslatedCrementOperation extends TranslatedNonConstantExpr {
|
||||
override CrementOperation expr;
|
||||
|
||||
@@ -349,9 +338,9 @@ abstract class TranslatedCrementOperation extends TranslatedNonConstantExpr {
|
||||
final override string getInstructionConstantValue(InstructionTag tag) {
|
||||
tag = CrementConstantTag() and
|
||||
exists(Type resultType |
|
||||
resultType = getResultType() and
|
||||
resultType = expr.getUnspecifiedType() and
|
||||
(
|
||||
resultType instanceof IntegralType and result = "1"
|
||||
resultType instanceof IntegralOrEnumType and result = "1"
|
||||
or
|
||||
resultType instanceof FloatingPointType and result = "1.0"
|
||||
or
|
||||
@@ -360,38 +349,37 @@ abstract class TranslatedCrementOperation extends TranslatedNonConstantExpr {
|
||||
)
|
||||
}
|
||||
|
||||
private Type getConstantType() {
|
||||
private CppType getConstantType() {
|
||||
exists(Type resultType |
|
||||
resultType = getResultType() and
|
||||
resultType = expr.getUnspecifiedType() and
|
||||
(
|
||||
resultType instanceof ArithmeticType and result = resultType
|
||||
or
|
||||
(
|
||||
resultType instanceof ArithmeticType and
|
||||
result = getTypeForPRValue(expr.getType())
|
||||
) or
|
||||
resultType instanceof PointerType and result = getIntType()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
Opcode opcode, InstructionTag tag, CppType resultType
|
||||
) {
|
||||
isGLValue = false and
|
||||
(
|
||||
tag = CrementLoadTag() and
|
||||
opcode instanceof Opcode::Load and
|
||||
resultType = getResultType()
|
||||
or
|
||||
tag = CrementConstantTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getConstantType()
|
||||
or
|
||||
tag = CrementOpTag() and
|
||||
opcode = getOpcode() and
|
||||
resultType = getResultType()
|
||||
or
|
||||
tag = CrementStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getResultType()
|
||||
)
|
||||
tag = CrementLoadTag() and
|
||||
opcode instanceof Opcode::Load and
|
||||
resultType = getTypeForPRValue(expr.getType())
|
||||
or
|
||||
tag = CrementConstantTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getConstantType()
|
||||
or
|
||||
tag = CrementOpTag() and
|
||||
opcode = getOpcode() and
|
||||
resultType = getTypeForPRValue(expr.getType())
|
||||
or
|
||||
tag = CrementStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getTypeForPRValue(expr.getType())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
@@ -452,7 +440,7 @@ abstract class TranslatedCrementOperation extends TranslatedNonConstantExpr {
|
||||
getOpcode() instanceof Opcode::PointerAdd or
|
||||
getOpcode() instanceof Opcode::PointerSub
|
||||
) and
|
||||
result = max(getResultType().(PointerType).getBaseType().getSize())
|
||||
result = getElementSize(expr.getType())
|
||||
}
|
||||
|
||||
final TranslatedExpr getOperand() {
|
||||
@@ -461,7 +449,7 @@ abstract class TranslatedCrementOperation extends TranslatedNonConstantExpr {
|
||||
|
||||
final Opcode getOpcode() {
|
||||
exists(Type resultType |
|
||||
resultType = getResultType() and
|
||||
resultType = expr.getUnspecifiedType() and
|
||||
(
|
||||
(
|
||||
expr instanceof IncrementOperation and
|
||||
@@ -542,13 +530,10 @@ class TranslatedArrayExpr extends TranslatedNonConstantExpr {
|
||||
|
||||
override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::PointerAdd and
|
||||
resultType = getResultType() and
|
||||
isGLValue = true
|
||||
resultType = getTypeForGLValue(expr.getType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
@@ -564,7 +549,7 @@ class TranslatedArrayExpr extends TranslatedNonConstantExpr {
|
||||
|
||||
override int getInstructionElementSize(InstructionTag tag) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = max(getResultType().getSize())
|
||||
result = max(expr.getUnspecifiedType().getSize())
|
||||
}
|
||||
|
||||
private TranslatedExpr getBaseOperand() {
|
||||
@@ -587,9 +572,7 @@ abstract class TranslatedTransparentExpr extends TranslatedNonConstantExpr {
|
||||
child = getOperand() and result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
@@ -632,7 +615,9 @@ class TranslatedTransparentConversion extends TranslatedTransparentExpr {
|
||||
)
|
||||
}
|
||||
|
||||
override TranslatedExpr getOperand() { result = getTranslatedExpr(expr.getExpr()) }
|
||||
override TranslatedExpr getOperand() {
|
||||
result = getTranslatedExpr(expr.getExpr())
|
||||
}
|
||||
}
|
||||
|
||||
class TranslatedThisExpr extends TranslatedNonConstantExpr {
|
||||
@@ -640,13 +625,10 @@ class TranslatedThisExpr extends TranslatedNonConstantExpr {
|
||||
|
||||
final override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
final override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::CopyValue and
|
||||
resultType = expr.getUnspecifiedType() and
|
||||
isGLValue = false
|
||||
resultType = getResultType()
|
||||
}
|
||||
|
||||
final override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) }
|
||||
@@ -707,13 +689,10 @@ class TranslatedNonFieldVariableAccess extends TranslatedVariableAccess {
|
||||
|
||||
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { none() }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getResultType() and
|
||||
isGLValue = true
|
||||
resultType = getTypeForGLValue(expr.getType())
|
||||
}
|
||||
|
||||
override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
@@ -733,13 +712,10 @@ class TranslatedFieldAccess extends TranslatedVariableAccess {
|
||||
result = getQualifier().getResult()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::FieldAddress and
|
||||
resultType = getResultType() and
|
||||
isGLValue = true
|
||||
resultType = getTypeForGLValue(expr.getType())
|
||||
}
|
||||
|
||||
override Field getInstructionField(InstructionTag tag) {
|
||||
@@ -763,13 +739,10 @@ class TranslatedFunctionAccess extends TranslatedNonConstantExpr {
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::FunctionAddress and
|
||||
resultType = expr.getUnspecifiedType() and
|
||||
isGLValue = true
|
||||
resultType = getResultType()
|
||||
}
|
||||
|
||||
override Function getInstructionFunction(InstructionTag tag) {
|
||||
@@ -811,15 +784,10 @@ abstract class TranslatedConstantExpr extends TranslatedCoreExpr, TTranslatedVal
|
||||
none()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode = getOpcode() and
|
||||
resultType = getResultType() and
|
||||
if expr.isGLValueCategory() or expr.hasLValueToRValueConversion()
|
||||
then isGLValue = true
|
||||
else isGLValue = false
|
||||
resultType = getResultType()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -865,13 +833,10 @@ abstract class TranslatedSingleInstructionExpr extends TranslatedNonConstantExpr
|
||||
*/
|
||||
abstract Opcode getOpcode();
|
||||
|
||||
final override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
opcode = getOpcode() and
|
||||
tag = OnlyInstructionTag() and
|
||||
resultType = getResultType() and
|
||||
isGLValue = isResultGLValue()
|
||||
resultType = getResultType()
|
||||
}
|
||||
|
||||
final override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) }
|
||||
@@ -945,13 +910,10 @@ abstract class TranslatedSingleInstructionConversion extends TranslatedConversio
|
||||
child = getOperand() and result = getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode = getOpcode() and
|
||||
resultType = getResultType() and
|
||||
isGLValue = isResultGLValue()
|
||||
resultType = getResultType()
|
||||
}
|
||||
|
||||
override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) }
|
||||
@@ -996,7 +958,7 @@ class TranslatedDynamicCast extends TranslatedSingleInstructionConversion {
|
||||
|
||||
override Opcode getOpcode() {
|
||||
exists(Type resultType |
|
||||
resultType = getResultType() and
|
||||
resultType = expr.getUnspecifiedType() and
|
||||
if resultType instanceof PointerType
|
||||
then
|
||||
if resultType.(PointerType).getBaseType() instanceof VoidType
|
||||
@@ -1054,19 +1016,14 @@ class TranslatedBoolConversion extends TranslatedConversion {
|
||||
child = getOperand() and result = getInstruction(BoolConversionConstantTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
isGLValue = false and
|
||||
(
|
||||
tag = BoolConversionConstantTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getOperand().getResultType()
|
||||
or
|
||||
tag = BoolConversionCompareTag() and
|
||||
opcode instanceof Opcode::CompareNE and
|
||||
resultType instanceof BoolType
|
||||
)
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = BoolConversionConstantTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getOperand().getResultType()
|
||||
or
|
||||
tag = BoolConversionCompareTag() and
|
||||
opcode instanceof Opcode::CompareNE and
|
||||
resultType = getBoolType()
|
||||
}
|
||||
|
||||
override Instruction getResult() { result = getInstruction(BoolConversionCompareTag()) }
|
||||
@@ -1197,7 +1154,7 @@ class TranslatedBinaryOperation extends TranslatedSingleInstructionExpr {
|
||||
opcode instanceof Opcode::PointerSub or
|
||||
opcode instanceof Opcode::PointerDiff
|
||||
) and
|
||||
result = max(getPointerOperand().getResultType().(PointerType).getBaseType().getSize())
|
||||
result = getElementSize(getPointerOperand().getExpr().getType())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1282,13 +1239,10 @@ class TranslatedAssignExpr extends TranslatedAssignment {
|
||||
result = getInstruction(AssignmentStoreTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = AssignmentStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getResultType() and
|
||||
isGLValue = false
|
||||
resultType = getTypeForPRValue(expr.getType()) // Always a prvalue
|
||||
}
|
||||
|
||||
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
@@ -1365,14 +1319,15 @@ class TranslatedAssignOperation extends TranslatedAssignment {
|
||||
// anyway. If we really want to model this case perfectly, we'll need the
|
||||
// extractor to tell us what the promoted type of the left operand would
|
||||
// be.
|
||||
result = getLeftOperand().getResultType()
|
||||
result = getLeftOperand().getExpr().getType()
|
||||
else
|
||||
// The right operand has already been converted to the type of the op.
|
||||
result = getRightOperand().getResultType()
|
||||
result = getRightOperand().getExpr().getType()
|
||||
}
|
||||
|
||||
private predicate leftOperandNeedsConversion() {
|
||||
getConvertedLeftOperandType() != getLeftOperand().getResultType()
|
||||
getConvertedLeftOperandType().getUnspecifiedType() !=
|
||||
getLeftOperand().getExpr().getUnspecifiedType()
|
||||
}
|
||||
|
||||
private Opcode getOpcode() {
|
||||
@@ -1401,32 +1356,27 @@ class TranslatedAssignOperation extends TranslatedAssignment {
|
||||
expr instanceof AssignPointerSubExpr and result instanceof Opcode::PointerSub
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
isGLValue = false and
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = AssignOperationLoadTag() and
|
||||
opcode instanceof Opcode::Load and
|
||||
resultType = getTypeForPRValue(getLeftOperand().getExpr().getType())
|
||||
or
|
||||
tag = AssignOperationOpTag() and
|
||||
opcode = getOpcode() and
|
||||
resultType = getTypeForPRValue(getConvertedLeftOperandType())
|
||||
or
|
||||
tag = AssignmentStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getTypeForPRValue(expr.getType()) // Always a prvalue
|
||||
or
|
||||
leftOperandNeedsConversion() and
|
||||
opcode instanceof Opcode::Convert and
|
||||
(
|
||||
tag = AssignOperationLoadTag() and
|
||||
opcode instanceof Opcode::Load and
|
||||
resultType = getLeftOperand().getResultType()
|
||||
tag = AssignOperationConvertLeftTag() and
|
||||
resultType = getTypeForPRValue(getConvertedLeftOperandType())
|
||||
or
|
||||
tag = AssignOperationOpTag() and
|
||||
opcode = getOpcode() and
|
||||
resultType = getConvertedLeftOperandType()
|
||||
or
|
||||
tag = AssignmentStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getResultType()
|
||||
or
|
||||
leftOperandNeedsConversion() and
|
||||
opcode instanceof Opcode::Convert and
|
||||
(
|
||||
tag = AssignOperationConvertLeftTag() and
|
||||
resultType = getConvertedLeftOperandType()
|
||||
or
|
||||
tag = AssignOperationConvertResultTag() and
|
||||
resultType = getLeftOperand().getResultType()
|
||||
)
|
||||
tag = AssignOperationConvertResultTag() and
|
||||
resultType = getTypeForPRValue(getLeftOperand().getExpr().getType())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1436,7 +1386,7 @@ class TranslatedAssignOperation extends TranslatedAssignment {
|
||||
opcode = getOpcode() and
|
||||
(opcode instanceof Opcode::PointerAdd or opcode instanceof Opcode::PointerSub)
|
||||
) and
|
||||
result = max(getResultType().(PointerType).getBaseType().getSize())
|
||||
result = getElementSize(expr.getType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
@@ -1518,13 +1468,10 @@ class TranslatedConstantAllocationSize extends TranslatedAllocationSize {
|
||||
|
||||
final override Instruction getFirstInstruction() { result = getInstruction(AllocationSizeTag()) }
|
||||
|
||||
final override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = AllocationSizeTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = expr.getAllocator().getParameter(0).getUnspecifiedType() and
|
||||
isGLValue = false
|
||||
resultType = getTypeForPRValue(expr.getAllocator().getParameter(0).getType())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -1557,11 +1504,8 @@ class TranslatedNonConstantAllocationSize extends TranslatedAllocationSize {
|
||||
|
||||
final override Instruction getFirstInstruction() { result = getExtent().getFirstInstruction() }
|
||||
|
||||
final override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
isGLValue = false and
|
||||
resultType = expr.getAllocator().getParameter(0).getUnspecifiedType() and
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
resultType = getTypeForPRValue(expr.getAllocator().getParameter(0).getType()) and
|
||||
(
|
||||
// Convert the extent to `size_t`, because the AST doesn't do this already.
|
||||
tag = AllocationExtentConvertTag() and opcode instanceof Opcode::Convert
|
||||
@@ -1633,7 +1577,9 @@ class TranslatedAllocatorCall extends TTranslatedAllocatorCall, TranslatedDirect
|
||||
tag = CallTargetTag() and result = expr.getAllocator()
|
||||
}
|
||||
|
||||
final override Type getCallResultType() { result = expr.getAllocator().getUnspecifiedType() }
|
||||
final override Type getCallResultType() {
|
||||
result = expr.getAllocator().getType()
|
||||
}
|
||||
|
||||
final override TranslatedExpr getQualifier() { none() }
|
||||
|
||||
@@ -1684,13 +1630,10 @@ class TranslatedDestructorFieldDestruction extends TranslatedNonConstantExpr, St
|
||||
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = getDestructorCall() }
|
||||
|
||||
final override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::FieldAddress and
|
||||
resultType = expr.getTarget().getUnspecifiedType() and
|
||||
isGLValue = true
|
||||
resultType = getTypeForGLValue(expr.getTarget().getType())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -1737,9 +1680,7 @@ class TranslatedConditionalExpr extends TranslatedNonConstantExpr, ConditionCont
|
||||
|
||||
override Instruction getFirstInstruction() { result = getCondition().getFirstInstruction() }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
not resultIsVoid() and
|
||||
(
|
||||
(
|
||||
@@ -1750,8 +1691,11 @@ class TranslatedConditionalExpr extends TranslatedNonConstantExpr, ConditionCont
|
||||
tag = ConditionValueResultTempAddressTag()
|
||||
) and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getResultType() and
|
||||
isGLValue = true
|
||||
(
|
||||
if expr.isGLValueCategory()
|
||||
then resultType = getTypeForGLValue(any(UnknownType t)) // glvalue to a glvalue
|
||||
else resultType = getTypeForGLValue(expr.getType()) // glvalue to the result type
|
||||
)
|
||||
or
|
||||
(
|
||||
not thenIsVoid() and tag = ConditionValueTrueStoreTag()
|
||||
@@ -1759,13 +1703,11 @@ class TranslatedConditionalExpr extends TranslatedNonConstantExpr, ConditionCont
|
||||
not elseIsVoid() and tag = ConditionValueFalseStoreTag()
|
||||
) and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getResultType() and
|
||||
isGLValue = false
|
||||
resultType = getResultType()
|
||||
or
|
||||
tag = ConditionValueResultLoadTag() and
|
||||
opcode instanceof Opcode::Load and
|
||||
resultType = getResultType() and
|
||||
isGLValue = isResultGLValue()
|
||||
resultType = getResultType()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1833,7 +1775,7 @@ class TranslatedConditionalExpr extends TranslatedNonConstantExpr, ConditionCont
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasTempVariable(TempVariableTag tag, Type type) {
|
||||
override predicate hasTempVariable(TempVariableTag tag, CppType type) {
|
||||
not resultIsVoid() and
|
||||
tag = ConditionValueTempVar() and
|
||||
type = getResultType()
|
||||
@@ -1893,7 +1835,7 @@ class TranslatedConditionalExpr extends TranslatedNonConstantExpr, ConditionCont
|
||||
}
|
||||
|
||||
private predicate thenIsVoid() {
|
||||
getThen().getResultType() instanceof VoidType
|
||||
getThen().getResultType().getIRType() instanceof IRVoidType
|
||||
or
|
||||
// A `ThrowExpr.getType()` incorrectly returns the type of exception being
|
||||
// thrown, rather than `void`. Handle that case here.
|
||||
@@ -1901,14 +1843,14 @@ class TranslatedConditionalExpr extends TranslatedNonConstantExpr, ConditionCont
|
||||
}
|
||||
|
||||
private predicate elseIsVoid() {
|
||||
getElse().getResultType() instanceof VoidType
|
||||
getElse().getResultType().getIRType() instanceof IRVoidType
|
||||
or
|
||||
// A `ThrowExpr.getType()` incorrectly returns the type of exception being
|
||||
// thrown, rather than `void`. Handle that case here.
|
||||
expr.getElse() instanceof ThrowExpr
|
||||
}
|
||||
|
||||
private predicate resultIsVoid() { getResultType() instanceof VoidType }
|
||||
private predicate resultIsVoid() { getResultType().getIRType() instanceof IRVoidType }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1917,13 +1859,10 @@ class TranslatedConditionalExpr extends TranslatedNonConstantExpr, ConditionCont
|
||||
abstract class TranslatedThrowExpr extends TranslatedNonConstantExpr {
|
||||
override ThrowExpr expr;
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = ThrowTag() and
|
||||
opcode = getThrowOpcode() and
|
||||
resultType instanceof VoidType and
|
||||
isGLValue = false
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -1950,15 +1889,12 @@ class TranslatedThrowValueExpr extends TranslatedThrowExpr, InitializationContex
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
TranslatedThrowExpr.super.hasInstruction(opcode, tag, resultType, isGLValue)
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
TranslatedThrowExpr.super.hasInstruction(opcode, tag, resultType)
|
||||
or
|
||||
tag = InitializerVariableAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getExceptionType() and
|
||||
isGLValue = true
|
||||
resultType = getTypeForGLValue(getExceptionType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -1979,9 +1915,9 @@ class TranslatedThrowValueExpr extends TranslatedThrowExpr, InitializationContex
|
||||
result = getIRTempVariable(expr, ThrowTempVar())
|
||||
}
|
||||
|
||||
final override predicate hasTempVariable(TempVariableTag tag, Type type) {
|
||||
final override predicate hasTempVariable(TempVariableTag tag, CppType type) {
|
||||
tag = ThrowTempVar() and
|
||||
type = getExceptionType()
|
||||
type = getTypeForPRValue(getExceptionType())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
@@ -1995,10 +1931,10 @@ class TranslatedThrowValueExpr extends TranslatedThrowExpr, InitializationContex
|
||||
)
|
||||
}
|
||||
|
||||
final override Type getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) {
|
||||
final override CppType getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) {
|
||||
tag = ThrowTag() and
|
||||
operandTag instanceof LoadOperandTag and
|
||||
result = getExceptionType()
|
||||
result = getTypeForPRValue(getExceptionType())
|
||||
}
|
||||
|
||||
override Instruction getTargetAddress() {
|
||||
@@ -2013,7 +1949,7 @@ class TranslatedThrowValueExpr extends TranslatedThrowExpr, InitializationContex
|
||||
|
||||
final override Opcode getThrowOpcode() { result instanceof Opcode::ThrowValue }
|
||||
|
||||
private Type getExceptionType() { result = expr.getUnspecifiedType() }
|
||||
private Type getExceptionType() { result = expr.getType() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2071,13 +2007,10 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr {
|
||||
)
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode = getOpcode() and
|
||||
resultType = getResultType() and
|
||||
isGLValue = isResultGLValue()
|
||||
resultType = getResultType()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
@@ -2144,13 +2077,10 @@ abstract class TranslatedNewOrNewArrayExpr extends TranslatedNonConstantExpr, In
|
||||
id = 1 and result = getInitialization()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::Convert and
|
||||
resultType = getResultType() and
|
||||
isGLValue = false
|
||||
resultType = getResultType()
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
@@ -2311,9 +2241,7 @@ class TranslatedConditionDeclExpr extends TranslatedNonConstantExpr {
|
||||
child = getConditionExpr() and result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
@@ -2362,23 +2290,18 @@ class TranslatedLambdaExpr extends TranslatedNonConstantExpr, InitializationCont
|
||||
result = getInstruction(LoadTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getResultType() and
|
||||
isGLValue = true
|
||||
resultType = getTypeForGLValue(expr.getType())
|
||||
or
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Uninitialized and
|
||||
resultType = getResultType() and
|
||||
isGLValue = false
|
||||
resultType = getTypeForPRValue(expr.getType())
|
||||
or
|
||||
tag = LoadTag() and
|
||||
opcode instanceof Opcode::Load and
|
||||
resultType = getResultType() and
|
||||
isGLValue = false
|
||||
resultType = getTypeForPRValue(expr.getType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
@@ -2404,16 +2327,16 @@ class TranslatedLambdaExpr extends TranslatedNonConstantExpr, InitializationCont
|
||||
result = getTempVariable(LambdaTempVar())
|
||||
}
|
||||
|
||||
override predicate hasTempVariable(TempVariableTag tag, Type type) {
|
||||
override predicate hasTempVariable(TempVariableTag tag, CppType type) {
|
||||
tag = LambdaTempVar() and
|
||||
type = getResultType()
|
||||
type = getTypeForPRValue(expr.getType())
|
||||
}
|
||||
|
||||
final override Instruction getTargetAddress() {
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
final override Type getTargetType() { result = getResultType() }
|
||||
final override Type getTargetType() { result = expr.getType() }
|
||||
|
||||
private predicate hasInitializer() { exists(getInitialization()) }
|
||||
|
||||
@@ -2444,13 +2367,10 @@ class TranslatedStmtExpr extends TranslatedNonConstantExpr {
|
||||
result = getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
opcode instanceof Opcode::CopyValue and
|
||||
tag instanceof OnlyInstructionTag and
|
||||
resultType = expr.getType() and
|
||||
isGLValue = false
|
||||
resultType = getResultType()
|
||||
}
|
||||
|
||||
override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
private import cpp
|
||||
import semmle.code.cpp.ir.implementation.raw.IR
|
||||
private import semmle.code.cpp.ir.implementation.Opcode
|
||||
private import semmle.code.cpp.ir.internal.CppType
|
||||
private import semmle.code.cpp.ir.internal.IRUtilities
|
||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||
private import semmle.code.cpp.ir.internal.TempVariableTag
|
||||
@@ -115,55 +116,46 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction {
|
||||
or
|
||||
(
|
||||
child = getDestructorDestructionList() and
|
||||
if getReturnType() instanceof VoidType
|
||||
then result = getInstruction(ReturnTag())
|
||||
else result = getInstruction(ReturnValueAddressTag())
|
||||
if hasReturnValue()
|
||||
then result = getInstruction(ReturnValueAddressTag())
|
||||
else result = getInstruction(ReturnTag())
|
||||
)
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
(
|
||||
tag = EnterFunctionTag() and
|
||||
opcode instanceof Opcode::EnterFunction and
|
||||
resultType instanceof VoidType and
|
||||
isGLValue = false
|
||||
resultType = getVoidType()
|
||||
or
|
||||
tag = UnmodeledDefinitionTag() and
|
||||
opcode instanceof Opcode::UnmodeledDefinition and
|
||||
resultType instanceof UnknownType and
|
||||
isGLValue = false
|
||||
resultType = getUnknownType()
|
||||
or
|
||||
tag = AliasedDefinitionTag() and
|
||||
opcode instanceof Opcode::AliasedDefinition and
|
||||
resultType instanceof UnknownType and
|
||||
isGLValue = false
|
||||
resultType = getUnknownType()
|
||||
or
|
||||
tag = InitializeThisTag() and
|
||||
opcode instanceof Opcode::InitializeThis and
|
||||
resultType = getThisType() and
|
||||
isGLValue = true
|
||||
resultType = getTypeForGLValue(getThisType())
|
||||
or
|
||||
tag = ReturnValueAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getReturnType() and
|
||||
not resultType instanceof VoidType and
|
||||
isGLValue = true
|
||||
resultType = getTypeForGLValue(getReturnType()) and
|
||||
hasReturnValue()
|
||||
or
|
||||
(
|
||||
tag = ReturnTag() and
|
||||
resultType instanceof VoidType and
|
||||
isGLValue = false and
|
||||
if getReturnType() instanceof VoidType
|
||||
then opcode instanceof Opcode::ReturnVoid
|
||||
else opcode instanceof Opcode::ReturnValue
|
||||
resultType = getVoidType() and
|
||||
if hasReturnValue()
|
||||
then opcode instanceof Opcode::ReturnValue
|
||||
else opcode instanceof Opcode::ReturnVoid
|
||||
)
|
||||
or
|
||||
tag = UnwindTag() and
|
||||
opcode instanceof Opcode::Unwind and
|
||||
resultType instanceof VoidType and
|
||||
isGLValue = false and
|
||||
resultType = getVoidType() and
|
||||
(
|
||||
// Only generate the `Unwind` instruction if there is any exception
|
||||
// handling present in the function.
|
||||
@@ -173,13 +165,11 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction {
|
||||
or
|
||||
tag = UnmodeledUseTag() and
|
||||
opcode instanceof Opcode::UnmodeledUse and
|
||||
resultType instanceof VoidType and
|
||||
isGLValue = false
|
||||
resultType = getVoidType()
|
||||
or
|
||||
tag = ExitFunctionTag() and
|
||||
opcode instanceof Opcode::ExitFunction and
|
||||
resultType instanceof VoidType and
|
||||
isGLValue = false
|
||||
resultType = getVoidType()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -198,7 +188,7 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction {
|
||||
result = getUnmodeledDefinitionInstruction()
|
||||
or
|
||||
tag = ReturnTag() and
|
||||
not getReturnType() instanceof VoidType and
|
||||
hasReturnValue() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInstruction(ReturnValueAddressTag())
|
||||
@@ -208,11 +198,11 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction {
|
||||
)
|
||||
}
|
||||
|
||||
final override Type getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) {
|
||||
final override CppType getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) {
|
||||
tag = ReturnTag() and
|
||||
not getReturnType() instanceof VoidType and
|
||||
hasReturnValue() and
|
||||
operandTag instanceof LoadOperandTag and
|
||||
result = getReturnType()
|
||||
result = getTypeForPRValue(getReturnType())
|
||||
}
|
||||
|
||||
final override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
@@ -220,10 +210,10 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction {
|
||||
result = getReturnVariable()
|
||||
}
|
||||
|
||||
final override predicate hasTempVariable(TempVariableTag tag, Type type) {
|
||||
final override predicate hasTempVariable(TempVariableTag tag, CppType type) {
|
||||
tag = ReturnValueTempVar() and
|
||||
type = getReturnType() and
|
||||
not type instanceof VoidType
|
||||
hasReturnValue() and
|
||||
type = getTypeForPRValue(getReturnType())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,6 +231,13 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction {
|
||||
result = getIRTempVariable(func, ReturnValueTempVar())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the function has a non-`void` return type.
|
||||
*/
|
||||
final predicate hasReturnValue() {
|
||||
not func.getUnspecifiedType() instanceof VoidType
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the single `UnmodeledDefinition` instruction for this function.
|
||||
*/
|
||||
@@ -271,7 +268,7 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction {
|
||||
* parameters and local variables, plus any global variables or static data members that are
|
||||
* directly accessed by the function.
|
||||
*/
|
||||
final predicate hasUserVariable(Variable var, Type type) {
|
||||
final predicate hasUserVariable(Variable var, CppType type) {
|
||||
(
|
||||
(
|
||||
var instanceof GlobalOrNamespaceVariable
|
||||
@@ -287,10 +284,10 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction {
|
||||
or
|
||||
var.(Parameter).getCatchBlock().getEnclosingFunction() = func
|
||||
) and
|
||||
type = getVariableType(var)
|
||||
type = getTypeForPRValue(getVariableType(var))
|
||||
}
|
||||
|
||||
final private Type getReturnType() { result = func.getUnspecifiedType() }
|
||||
final Type getReturnType() { result = func.getType() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -335,18 +332,14 @@ class TranslatedParameter extends TranslatedElement, TTranslatedParameter {
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child) { none() }
|
||||
|
||||
final override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getVariableType(param) and
|
||||
isGLValue = true
|
||||
resultType = getTypeForGLValue(getVariableType(param))
|
||||
or
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::InitializeParameter and
|
||||
resultType = getVariableType(param) and
|
||||
isGLValue = false
|
||||
resultType = getTypeForPRValue(getVariableType(param))
|
||||
}
|
||||
|
||||
final override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
@@ -404,9 +397,7 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
@@ -469,9 +460,7 @@ class TranslatedDestructorDestructionList extends TranslatedElement,
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.implementation.Opcode
|
||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||
private import semmle.code.cpp.ir.internal.CppType
|
||||
private import InstructionTag
|
||||
private import TranslatedElement
|
||||
private import TranslatedExpr
|
||||
@@ -79,9 +80,7 @@ abstract class TranslatedListInitialization extends TranslatedInitialization, In
|
||||
)
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
@@ -150,13 +149,10 @@ class TranslatedSimpleDirectInitialization extends TranslatedDirectInitializatio
|
||||
not expr instanceof StringLiteral
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getContext().getTargetType() and
|
||||
isGLValue = false
|
||||
resultType = getTypeForPRValue(getContext().getTargetType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -188,20 +184,16 @@ class TranslatedSimpleDirectInitialization extends TranslatedDirectInitializatio
|
||||
class TranslatedStringLiteralInitialization extends TranslatedDirectInitialization {
|
||||
override StringLiteral expr;
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
// Load the string literal to make it a prvalue of type `char[len]`
|
||||
tag = InitializerLoadStringTag() and
|
||||
opcode instanceof Opcode::Load and
|
||||
resultType = getInitializer().getResultType() and
|
||||
isGLValue = false
|
||||
resultType = getTypeForPRValue(expr.getType())
|
||||
or
|
||||
// Store the string into the target.
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getInitializer().getResultType() and
|
||||
isGLValue = false
|
||||
resultType = getTypeForPRValue(expr.getType())
|
||||
or
|
||||
exists(int startIndex, int elementCount |
|
||||
// If the initializer string isn't large enough to fill the target, then
|
||||
@@ -213,26 +205,22 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
// space in the target array.
|
||||
tag = ZeroPadStringConstantTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType instanceof UnknownType and
|
||||
isGLValue = false
|
||||
resultType = getUnknownBlobType(elementCount * getElementType().getSize())
|
||||
or
|
||||
// The index of the first element to be zero initialized.
|
||||
tag = ZeroPadStringElementIndexTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getIntType() and
|
||||
isGLValue = false
|
||||
resultType = getIntType()
|
||||
or
|
||||
// Compute the address of the first element to be zero initialized.
|
||||
tag = ZeroPadStringElementAddressTag() and
|
||||
opcode instanceof Opcode::PointerAdd and
|
||||
resultType = getElementType() and
|
||||
isGLValue = true
|
||||
resultType = getTypeForGLValue(getElementType())
|
||||
or
|
||||
// Store the constant zero into the remainder of the string.
|
||||
tag = ZeroPadStringStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType instanceof UnknownType and
|
||||
isGLValue = false
|
||||
resultType = getUnknownBlobType(elementCount * getElementType().getSize())
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -326,6 +314,13 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
)
|
||||
}
|
||||
|
||||
override predicate needsUnknownBlobType(int byteSize) {
|
||||
exists(int elementCount |
|
||||
zeroInitRange(_, elementCount) and
|
||||
byteSize = elementCount * getElementType().getSize()
|
||||
)
|
||||
}
|
||||
|
||||
override int getInstructionResultSize(InstructionTag tag) {
|
||||
exists(int elementCount |
|
||||
zeroInitRange(_, elementCount) and
|
||||
@@ -338,7 +333,7 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
}
|
||||
|
||||
private Type getElementType() {
|
||||
result = getContext().getTargetType().(ArrayType).getBaseType().getUnspecifiedType()
|
||||
result = getContext().getTargetType().getUnspecifiedType().(ArrayType).getBaseType()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -348,7 +343,7 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
private predicate zeroInitRange(int startIndex, int elementCount) {
|
||||
exists(int targetCount |
|
||||
startIndex = expr.getUnspecifiedType().(ArrayType).getArraySize() and
|
||||
targetCount = getContext().getTargetType().(ArrayType).getArraySize() and
|
||||
targetCount = getContext().getTargetType().getUnspecifiedType().(ArrayType).getArraySize() and
|
||||
elementCount = targetCount - startIndex and
|
||||
elementCount > 0
|
||||
)
|
||||
@@ -359,9 +354,7 @@ class TranslatedConstructorInitialization extends TranslatedDirectInitialization
|
||||
StructorCallContext {
|
||||
override ConstructorCall expr;
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
@@ -412,13 +405,10 @@ abstract class TranslatedFieldInitialization extends TranslatedElement {
|
||||
*/
|
||||
final int getOrder() { result = field.getInitializationOrder() }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = getFieldAddressTag() and
|
||||
opcode instanceof Opcode::FieldAddress and
|
||||
resultType = field.getUnspecifiedType() and
|
||||
isGLValue = true
|
||||
resultType = getTypeForGLValue(field.getType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
@@ -481,20 +471,16 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
TTranslatedFieldValueInitialization {
|
||||
TranslatedFieldValueInitialization() { this = TTranslatedFieldValueInitialization(ast, field) }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
TranslatedFieldInitialization.super.hasInstruction(opcode, tag, resultType, isGLValue)
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
TranslatedFieldInitialization.super.hasInstruction(opcode, tag, resultType)
|
||||
or
|
||||
tag = getFieldDefaultValueTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = field.getUnspecifiedType() and
|
||||
isGLValue = false
|
||||
resultType = getTypeForPRValue(field.getType())
|
||||
or
|
||||
tag = getFieldDefaultValueStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = field.getUnspecifiedType() and
|
||||
isGLValue = false
|
||||
resultType = getTypeForPRValue(field.getUnspecifiedType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -557,18 +543,14 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
|
||||
|
||||
final override Instruction getFirstInstruction() { result = getInstruction(getElementIndexTag()) }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = getElementIndexTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getIntType() and
|
||||
isGLValue = false
|
||||
resultType = getIntType()
|
||||
or
|
||||
tag = getElementAddressTag() and
|
||||
opcode instanceof Opcode::PointerAdd and
|
||||
resultType = getElementType() and
|
||||
isGLValue = true
|
||||
resultType = getTypeForGLValue(getElementType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -606,7 +588,7 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
|
||||
|
||||
final ArrayOrVectorAggregateLiteral getInitList() { result = initList }
|
||||
|
||||
final Type getElementType() { result = initList.getElementType().getUnspecifiedType() }
|
||||
final Type getElementType() { result = initList.getElementType() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -659,20 +641,16 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
this = TTranslatedElementValueInitialization(initList, elementIndex, elementCount)
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
TranslatedElementInitialization.super.hasInstruction(opcode, tag, resultType, isGLValue)
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
TranslatedElementInitialization.super.hasInstruction(opcode, tag, resultType)
|
||||
or
|
||||
tag = getElementDefaultValueTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getDefaultValueType() and
|
||||
isGLValue = false
|
||||
resultType = getDefaultValueType()
|
||||
or
|
||||
tag = getElementDefaultValueStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getDefaultValueType() and
|
||||
isGLValue = false
|
||||
resultType = getDefaultValueType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -726,6 +704,10 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
|
||||
override int getElementIndex() { result = elementIndex }
|
||||
|
||||
override predicate needsUnknownBlobType(int byteSize) {
|
||||
elementCount != 0 and byteSize = elementCount * getElementType().getSize()
|
||||
}
|
||||
|
||||
private InstructionTag getElementDefaultValueTag() {
|
||||
result = InitializerElementDefaultValueTag()
|
||||
}
|
||||
@@ -734,8 +716,11 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
result = InitializerElementDefaultValueStoreTag()
|
||||
}
|
||||
|
||||
private Type getDefaultValueType() {
|
||||
if elementCount = 1 then result = getElementType() else result instanceof UnknownType
|
||||
private CppType getDefaultValueType() {
|
||||
if elementCount = 1 then
|
||||
result = getTypeForPRValue(getElementType())
|
||||
else
|
||||
result = getUnknownBlobType(elementCount * getElementType().getSize())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -766,13 +751,10 @@ abstract class TranslatedStructorCallFromStructor extends TranslatedElement, Str
|
||||
abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStructor {
|
||||
final override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
final override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::ConvertToBase and
|
||||
resultType = call.getTarget().getDeclaringType().getUnspecifiedType() and
|
||||
isGLValue = true
|
||||
resultType = getTypeForGLValue(call.getTarget().getDeclaringType())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -822,9 +804,7 @@ class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromC
|
||||
result = getStructorCall().getFirstInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.internal.IRUtilities
|
||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||
private import semmle.code.cpp.ir.internal.CppType
|
||||
private import semmle.code.cpp.ir.internal.TempVariableTag
|
||||
private import InstructionTag
|
||||
private import TranslatedCondition
|
||||
@@ -35,13 +36,10 @@ class TranslatedEmptyStmt extends TranslatedStmt {
|
||||
|
||||
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::NoOp and
|
||||
resultType instanceof VoidType and
|
||||
isGLValue = false
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -63,9 +61,7 @@ class TranslatedDeclStmt extends TranslatedStmt {
|
||||
|
||||
override TranslatedElement getChild(int id) { result = getDeclarationEntry(id) }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
@@ -112,9 +108,7 @@ class TranslatedExprStmt extends TranslatedStmt {
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getExpr() }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
@@ -145,13 +139,10 @@ class TranslatedReturnValueStmt extends TranslatedReturnStmt, InitializationCont
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getEnclosingFunction().getReturnVariable().getType() and
|
||||
isGLValue = true
|
||||
resultType = getTypeForGLValue(getEnclosingFunction().getReturnType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -174,7 +165,9 @@ class TranslatedReturnValueStmt extends TranslatedReturnStmt, InitializationCont
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
override Type getTargetType() { result = getEnclosingFunction().getReturnVariable().getType() }
|
||||
override Type getTargetType() {
|
||||
result = getEnclosingFunction().getReturnType()
|
||||
}
|
||||
|
||||
TranslatedInitialization getInitialization() {
|
||||
result = getTranslatedInitialization(stmt.getExpr().getFullyConverted())
|
||||
@@ -188,13 +181,10 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt {
|
||||
|
||||
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::NoOp and
|
||||
resultType instanceof VoidType and
|
||||
isGLValue = false
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -218,9 +208,7 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
result = getHandler(id - 1)
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
@@ -262,14 +250,11 @@ class TranslatedBlock extends TranslatedStmt {
|
||||
|
||||
override TranslatedElement getChild(int id) { result = getStmt(id) }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
isEmpty() and
|
||||
opcode instanceof Opcode::NoOp and
|
||||
tag = OnlyInstructionTag() and
|
||||
resultType instanceof VoidType and
|
||||
isGLValue = false
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
@@ -330,13 +315,10 @@ abstract class TranslatedHandler extends TranslatedStmt {
|
||||
class TranslatedCatchByTypeHandler extends TranslatedHandler {
|
||||
TranslatedCatchByTypeHandler() { exists(stmt.getParameter()) }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = CatchTag() and
|
||||
opcode instanceof Opcode::CatchByType and
|
||||
resultType instanceof VoidType and
|
||||
isGLValue = false
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
@@ -362,9 +344,9 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler {
|
||||
)
|
||||
}
|
||||
|
||||
override Type getInstructionExceptionType(InstructionTag tag) {
|
||||
override CppType getInstructionExceptionType(InstructionTag tag) {
|
||||
tag = CatchTag() and
|
||||
result = stmt.getParameter().getType()
|
||||
result = getTypeForPRValue(stmt.getParameter().getType())
|
||||
}
|
||||
|
||||
private TranslatedParameter getParameter() {
|
||||
@@ -378,13 +360,10 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler {
|
||||
class TranslatedCatchAnyHandler extends TranslatedHandler {
|
||||
TranslatedCatchAnyHandler() { not exists(stmt.getParameter()) }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = CatchTag() and
|
||||
opcode instanceof Opcode::CatchAny and
|
||||
resultType instanceof VoidType and
|
||||
isGLValue = false
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -436,9 +415,7 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
}
|
||||
@@ -466,9 +443,7 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
id = 1 and result = getBody()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
@@ -597,9 +572,7 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
|
||||
result = getCondition().getFirstInstruction()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
@@ -649,13 +622,10 @@ class TranslatedJumpStmt extends TranslatedStmt {
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::NoOp and
|
||||
resultType instanceof VoidType and
|
||||
isGLValue = false
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -693,13 +663,10 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
id = 1 and result = getBody()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = SwitchBranchTag() and
|
||||
opcode instanceof Opcode::Switch and
|
||||
resultType instanceof VoidType and
|
||||
isGLValue = false
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
@@ -727,37 +694,20 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
class TranslatedAsmStmt extends TranslatedStmt {
|
||||
override AsmStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
override TranslatedExpr getChild(int id) {
|
||||
result = getTranslatedExpr(stmt.getChild(id).(Expr).getFullyConverted())
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if exists(stmt.getChild(0))
|
||||
then result = getInstruction(AsmInputTag(0))
|
||||
if exists(getChild(0))
|
||||
then result = getChild(0).getFirstInstruction()
|
||||
else result = getInstruction(AsmTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue
|
||||
) {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = AsmTag() and
|
||||
opcode instanceof Opcode::InlineAsm and
|
||||
resultType instanceof UnknownType and
|
||||
isGLValue = false
|
||||
or
|
||||
exists(int index, VariableAccess va |
|
||||
tag = AsmInputTag(index) and
|
||||
stmt.getChild(index) = va and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = va.getType().getUnspecifiedType() and
|
||||
isGLValue = true
|
||||
)
|
||||
}
|
||||
|
||||
override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
exists(int index |
|
||||
tag = AsmInputTag(index) and
|
||||
result = getIRUserVariable(stmt.getEnclosingFunction(),
|
||||
stmt.getChild(index).(VariableAccess).getTarget())
|
||||
)
|
||||
resultType = getUnknownType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
@@ -768,29 +718,28 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
exists(int index |
|
||||
tag = AsmTag() and
|
||||
operandTag = asmOperand(index) and
|
||||
result = getInstruction(AsmInputTag(index))
|
||||
result = getChild(index).getResult()
|
||||
)
|
||||
}
|
||||
|
||||
final override Type getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) {
|
||||
final override CppType getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) {
|
||||
tag = AsmTag() and
|
||||
operandTag instanceof SideEffectOperandTag and
|
||||
result instanceof UnknownType
|
||||
result = getUnknownType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = AsmTag() and
|
||||
result = getParent().getChildSuccessor(this) and
|
||||
kind instanceof GotoEdge
|
||||
or
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int index |
|
||||
tag = AsmInputTag(index) and
|
||||
kind instanceof GotoEdge and
|
||||
if exists(stmt.getChild(index + 1))
|
||||
then result = getInstruction(AsmInputTag(index + 1))
|
||||
child = getChild(index) and
|
||||
if exists(getChild(index + 1))
|
||||
then result = getChild(index + 1).getFirstInstruction()
|
||||
else result = getInstruction(AsmTag())
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) { none() }
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import IRVariable
|
||||
import Operand
|
||||
private import internal.IRImports as Imports
|
||||
import Imports::EdgeKind
|
||||
import Imports::IRType
|
||||
import Imports::MemoryAccessKind
|
||||
|
||||
private newtype TIRPropertyProvider = MkIRPropertyProvider()
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
private import IR
|
||||
import InstructionSanity
|
||||
import IRTypeSanity
|
||||
@@ -5,6 +5,7 @@ import Imports::TempVariableTag
|
||||
private import Imports::IRUtilities
|
||||
private import Imports::TTempVariableTag
|
||||
private import Imports::TIRVariable
|
||||
private import Imports::IRType
|
||||
|
||||
IRUserVariable getIRUserVariable(Language::Function func, Language::Variable var) {
|
||||
result.getVariable() = var and
|
||||
@@ -24,7 +25,21 @@ abstract class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
abstract Language::Type getType();
|
||||
final Language::Type getType() {
|
||||
getLanguageType().hasType(result, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the language-neutral type of the variable.
|
||||
*/
|
||||
final IRType getIRType() {
|
||||
result = getLanguageType().getIRType()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
abstract Language::LanguageType getLanguageType();
|
||||
|
||||
/**
|
||||
* Gets the AST node that declared this variable, or that introduced this
|
||||
@@ -59,7 +74,7 @@ abstract class IRVariable extends TIRVariable {
|
||||
*/
|
||||
class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
Language::Variable var;
|
||||
Language::Type type;
|
||||
Language::LanguageType type;
|
||||
|
||||
IRUserVariable() { this = TIRUserVariable(var, type, func) }
|
||||
|
||||
@@ -71,7 +86,7 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
result = getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
}
|
||||
|
||||
final override Language::Type getType() { result = type }
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
/**
|
||||
* Gets the original user-declared variable.
|
||||
@@ -110,11 +125,11 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
|
||||
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
|
||||
Language::AST ast;
|
||||
TempVariableTag tag;
|
||||
Language::Type type;
|
||||
Language::LanguageType type;
|
||||
|
||||
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }
|
||||
|
||||
final override Language::Type getType() { result = type }
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
final override Language::AST getAST() { result = ast }
|
||||
|
||||
|
||||
@@ -113,10 +113,13 @@ module InstructionSanity {
|
||||
}
|
||||
|
||||
query predicate missingOperandType(Operand operand, string message) {
|
||||
exists(Language::Function func |
|
||||
exists(Language::Function func, Instruction use |
|
||||
not exists(operand.getType()) and
|
||||
func = operand.getUse().getEnclosingFunction() and
|
||||
message = "Operand missing type in function '" + Language::getIdentityString(func) + "'."
|
||||
use = operand.getUse() and
|
||||
func = use.getEnclosingFunction() and
|
||||
message = "Operand '" + operand.toString() + "' of instruction '" +
|
||||
use.getOpcode().toString() + "' missing type in function '" +
|
||||
Language::getIdentityString(func) + "'."
|
||||
)
|
||||
}
|
||||
|
||||
@@ -344,23 +347,6 @@ class Instruction extends Construction::TInstruction {
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[type]
|
||||
private string getValueCategoryString(string type) {
|
||||
if isGLValue() then result = "glval<" + type + ">" else result = type
|
||||
}
|
||||
|
||||
string getResultTypeString() {
|
||||
exists(string valcat |
|
||||
valcat = getValueCategoryString(getResultType().toString()) and
|
||||
if
|
||||
getResultType() instanceof Language::UnknownType and
|
||||
not isGLValue() and
|
||||
exists(getResultSize())
|
||||
then result = valcat + "[" + getResultSize().toString() + "]"
|
||||
else result = valcat
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a human-readable string that uniquely identifies this instruction
|
||||
* within the function. This string is used to refer to this instruction when
|
||||
@@ -380,7 +366,9 @@ class Instruction extends Construction::TInstruction {
|
||||
*
|
||||
* Example: `r1_1(int*)`
|
||||
*/
|
||||
final string getResultString() { result = getResultId() + "(" + getResultTypeString() + ")" }
|
||||
final string getResultString() {
|
||||
result = getResultId() + "(" + getResultLanguageType().getDumpString() + ")"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string describing the operands of this instruction, suitable for
|
||||
@@ -448,6 +436,10 @@ class Instruction extends Construction::TInstruction {
|
||||
result = Construction::getInstructionUnconvertedResultExpression(this)
|
||||
}
|
||||
|
||||
final Language::LanguageType getResultLanguageType() {
|
||||
result = Construction::getInstructionResultType(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the result produced by this instruction. If the
|
||||
* instruction does not produce a result, its result type will be `VoidType`.
|
||||
@@ -455,7 +447,16 @@ class Instruction extends Construction::TInstruction {
|
||||
* If `isGLValue()` holds, then the result type of this instruction should be
|
||||
* thought of as "pointer to `getResultType()`".
|
||||
*/
|
||||
final Language::Type getResultType() { Construction::instructionHasType(this, result, _) }
|
||||
final Language::Type getResultType() {
|
||||
exists(Language::LanguageType resultType, Language::Type langType |
|
||||
resultType = getResultLanguageType() and
|
||||
(
|
||||
resultType.hasType(langType, _) or
|
||||
not resultType.hasType(_, _) and result instanceof Language::UnknownType
|
||||
) and
|
||||
result = langType.getUnspecifiedType()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the result produced by this instruction is a glvalue. If this
|
||||
@@ -475,7 +476,9 @@ class Instruction extends Construction::TInstruction {
|
||||
* result of the `Load` instruction is a prvalue of type `int`, representing
|
||||
* the integer value loaded from variable `x`.
|
||||
*/
|
||||
final predicate isGLValue() { Construction::instructionHasType(this, _, true) }
|
||||
final predicate isGLValue() {
|
||||
Construction::getInstructionResultType(this).hasType(_, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of the result produced by this instruction, in bytes. If the
|
||||
@@ -485,14 +488,7 @@ class Instruction extends Construction::TInstruction {
|
||||
* `getResultSize()` will always be the size of a pointer.
|
||||
*/
|
||||
final int getResultSize() {
|
||||
if isGLValue()
|
||||
then
|
||||
// a glvalue is always pointer-sized.
|
||||
result = Language::getPointerSize()
|
||||
else
|
||||
if getResultType() instanceof Language::UnknownType
|
||||
then result = Construction::getInstructionResultSize(this)
|
||||
else result = Language::getTypeSize(getResultType())
|
||||
result = Construction::getInstructionResultType(this).getByteSize()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1300,7 +1296,7 @@ class CatchInstruction extends Instruction {
|
||||
* An instruction that catches an exception of a specific type.
|
||||
*/
|
||||
class CatchByTypeInstruction extends CatchInstruction {
|
||||
Language::Type exceptionType;
|
||||
Language::LanguageType exceptionType;
|
||||
|
||||
CatchByTypeInstruction() {
|
||||
getOpcode() instanceof Opcode::CatchByType and
|
||||
@@ -1312,7 +1308,7 @@ class CatchByTypeInstruction extends CatchInstruction {
|
||||
/**
|
||||
* Gets the type of exception to be caught.
|
||||
*/
|
||||
final Language::Type getExceptionType() { result = exceptionType }
|
||||
final Language::LanguageType getExceptionType() { result = exceptionType }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
private import internal.IRInternal
|
||||
import Instruction
|
||||
import IRBlock
|
||||
private import Instruction
|
||||
private import IRBlock
|
||||
private import internal.OperandImports as Imports
|
||||
import Imports::MemoryAccessKind
|
||||
import Imports::Overlap
|
||||
private import Imports::MemoryAccessKind
|
||||
private import Imports::IRType
|
||||
private import Imports::Overlap
|
||||
private import Imports::OperandTag
|
||||
|
||||
cached
|
||||
@@ -143,22 +144,40 @@ class Operand extends TOperand {
|
||||
* the definition type, such as in the case of a partial read or a read from a pointer that
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
Language::Type getType() { result = getAnyDef().getResultType() }
|
||||
Language::LanguageType getLanguageType() { result = getAnyDef().getResultLanguageType() }
|
||||
|
||||
/**
|
||||
* Gets the language-neutral type of the value consumed by this operand. This is usually the same
|
||||
* as the result type of the definition instruction consumed by this operand. For register
|
||||
* operands, this is always the case. For some memory operands, the operand type may be different
|
||||
* from the definition type, such as in the case of a partial read or a read from a pointer that
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
final IRType getIRType() { result = getLanguageType().getIRType() }
|
||||
|
||||
/**
|
||||
* Gets the type of the value consumed by this operand. This is usually the same as the
|
||||
* result type of the definition instruction consumed by this operand. For register operands,
|
||||
* this is always the case. For some memory operands, the operand type may be different from
|
||||
* the definition type, such as in the case of a partial read or a read from a pointer that
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
final Language::Type getType() { getLanguageType().hasType(result, _) }
|
||||
|
||||
/**
|
||||
* Holds if the value consumed by this operand is a glvalue. If this
|
||||
* holds, the value of the operand represents the address of a location,
|
||||
* and the type of the location is given by `getType()`. If this does
|
||||
* not hold, the value of the operand represents a value whose type is
|
||||
* given by `getResultType()`.
|
||||
* given by `getType()`.
|
||||
*/
|
||||
predicate isGLValue() { getAnyDef().isGLValue() }
|
||||
final predicate isGLValue() { getLanguageType().hasType(_, true) }
|
||||
|
||||
/**
|
||||
* Gets the size of the value consumed by this operand, in bytes. If the operand does not have
|
||||
* a known constant size, this predicate does not hold.
|
||||
*/
|
||||
int getSize() { result = Language::getTypeSize(getType()) }
|
||||
final int getSize() { result = getLanguageType().getByteSize() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,11 +189,6 @@ class MemoryOperand extends Operand {
|
||||
this = TPhiOperand(_, _, _, _)
|
||||
}
|
||||
|
||||
override predicate isGLValue() {
|
||||
// A `MemoryOperand` can never be a glvalue
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the kind of memory access performed by the operand.
|
||||
*/
|
||||
@@ -239,7 +253,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
|
||||
class TypedOperand extends NonPhiMemoryOperand {
|
||||
override TypedOperandTag tag;
|
||||
|
||||
final override Language::Type getType() {
|
||||
final override Language::LanguageType getLanguageType() {
|
||||
result = Construction::getInstructionOperandType(useInstr, tag)
|
||||
}
|
||||
}
|
||||
@@ -371,12 +385,6 @@ class PositionalArgumentOperand extends ArgumentOperand {
|
||||
class SideEffectOperand extends TypedOperand {
|
||||
override SideEffectOperandTag tag;
|
||||
|
||||
final override int getSize() {
|
||||
if getType() instanceof Language::UnknownType
|
||||
then result = Construction::getInstructionOperandSize(useInstr, tag)
|
||||
else result = Language::getTypeSize(getType())
|
||||
}
|
||||
|
||||
override MemoryAccessKind getMemoryAccess() {
|
||||
useInstr instanceof CallSideEffectInstruction and
|
||||
result instanceof EscapedMayMemoryAccess
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
import semmle.code.cpp.ir.implementation.EdgeKind as EdgeKind
|
||||
import semmle.code.cpp.ir.implementation.IRType as IRType
|
||||
import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import semmle.code.cpp.ir.implementation.IRType as IRType
|
||||
import semmle.code.cpp.ir.implementation.TempVariableTag as TempVariableTag
|
||||
import semmle.code.cpp.ir.internal.IRUtilities as IRUtilities
|
||||
import semmle.code.cpp.ir.internal.TempVariableTag as TTempVariableTag
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind
|
||||
import semmle.code.cpp.ir.implementation.IRType as IRType
|
||||
import semmle.code.cpp.ir.internal.Overlap as Overlap
|
||||
import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag
|
||||
|
||||
@@ -4,34 +4,52 @@ private import Alias
|
||||
private import SSAConstruction
|
||||
private import DebugSSA
|
||||
|
||||
bindingset[offset]
|
||||
private string getKeySuffixForOffset(int offset) {
|
||||
if offset % 2 = 0 then result = "" else result = "_Chi"
|
||||
}
|
||||
|
||||
bindingset[offset]
|
||||
private int getIndexForOffset(int offset) { result = offset / 2 }
|
||||
|
||||
/**
|
||||
* Property provide that dumps the memory access of each result. Useful for debugging SSA
|
||||
* construction.
|
||||
*/
|
||||
class PropertyProvider extends IRPropertyProvider {
|
||||
override string getInstructionProperty(Instruction instruction, string key) {
|
||||
exists(MemoryLocation location |
|
||||
location = getResultMemoryLocation(instruction) and
|
||||
(
|
||||
key = "ResultMemoryLocation" and result = location.toString()
|
||||
or
|
||||
key = "ResultVirtualVariable" and result = location.getVirtualVariable().toString()
|
||||
key = "ResultMemoryLocation" and
|
||||
result = strictconcat(MemoryLocation loc |
|
||||
loc = getResultMemoryLocation(instruction)
|
||||
|
|
||||
loc.toString(), ","
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(MemoryLocation location |
|
||||
location = getOperandMemoryLocation(instruction.getAnOperand()) and
|
||||
(
|
||||
key = "OperandMemoryAccess" and result = location.toString()
|
||||
or
|
||||
key = "OperandVirtualVariable" and result = location.getVirtualVariable().toString()
|
||||
key = "ResultVirtualVariable" and
|
||||
result = strictconcat(MemoryLocation loc |
|
||||
loc = getResultMemoryLocation(instruction)
|
||||
|
|
||||
loc.getVirtualVariable().toString(), ","
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(MemoryLocation useLocation, IRBlock defBlock, int defRank, int defIndex |
|
||||
hasDefinitionAtRank(useLocation, _, defBlock, defRank, defIndex) and
|
||||
defBlock.getInstruction(defIndex) = instruction and
|
||||
key = "DefinitionRank[" + useLocation.toString() + "]" and
|
||||
key = "OperandMemoryLocation" and
|
||||
result = strictconcat(MemoryLocation loc |
|
||||
loc = getOperandMemoryLocation(instruction.getAnOperand())
|
||||
|
|
||||
loc.toString(), ","
|
||||
)
|
||||
or
|
||||
key = "OperandVirtualVariable" and
|
||||
result = strictconcat(MemoryLocation loc |
|
||||
loc = getOperandMemoryLocation(instruction.getAnOperand())
|
||||
|
|
||||
loc.getVirtualVariable().toString(), ","
|
||||
)
|
||||
or
|
||||
exists(MemoryLocation useLocation, IRBlock defBlock, int defRank, int defOffset |
|
||||
hasDefinitionAtRank(useLocation, _, defBlock, defRank, defOffset) and
|
||||
defBlock.getInstruction(getIndexForOffset(defOffset)) = instruction and
|
||||
key = "DefinitionRank" + getKeySuffixForOffset(defOffset) + "[" + useLocation.toString() + "]" and
|
||||
result = defRank.toString()
|
||||
)
|
||||
or
|
||||
@@ -41,10 +59,11 @@ class PropertyProvider extends IRPropertyProvider {
|
||||
result = useRank.toString()
|
||||
)
|
||||
or
|
||||
exists(MemoryLocation useLocation, IRBlock defBlock, int defRank, int defIndex |
|
||||
hasDefinitionAtRank(useLocation, _, defBlock, defRank, defIndex) and
|
||||
defBlock.getInstruction(defIndex) = instruction and
|
||||
key = "DefinitionReachesUse[" + useLocation.toString() + "]" and
|
||||
exists(MemoryLocation useLocation, IRBlock defBlock, int defRank, int defOffset |
|
||||
hasDefinitionAtRank(useLocation, _, defBlock, defRank, defOffset) and
|
||||
defBlock.getInstruction(getIndexForOffset(defOffset)) = instruction and
|
||||
key = "DefinitionReachesUse" + getKeySuffixForOffset(defOffset) + "[" + useLocation.toString()
|
||||
+ "]" and
|
||||
result = strictconcat(IRBlock useBlock, int useRank, int useIndex |
|
||||
exists(Instruction useInstruction |
|
||||
hasUseAtRank(useLocation, useBlock, useRank, useInstruction) and
|
||||
@@ -124,3 +143,4 @@ class PropertyProvider extends IRPropertyProvider {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import SSAConstructionInternal
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.implementation.Opcode
|
||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||
private import semmle.code.cpp.ir.internal.Overlap
|
||||
@@ -18,7 +17,7 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
predicate functionHasIR(Function func) {
|
||||
predicate functionHasIR(Language::Function func) {
|
||||
exists(OldIR::IRFunction irFunc | irFunc.getFunction() = func)
|
||||
}
|
||||
|
||||
@@ -42,7 +41,7 @@ private module Cached {
|
||||
not oldInstruction instanceof OldIR::PhiInstruction and
|
||||
hasChiNode(_, oldInstruction)
|
||||
} or
|
||||
Unreached(Function function) {
|
||||
Unreached(Language::Function function) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
function = oldInstruction.getEnclosingFunction() and
|
||||
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
|
||||
@@ -50,12 +49,14 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, Type type) {
|
||||
predicate hasTempVariable(
|
||||
Language::Function func, Language::AST ast, TempVariableTag tag, Language::LanguageType type
|
||||
) {
|
||||
exists(OldIR::IRTempVariable var |
|
||||
var.getEnclosingFunction() = func and
|
||||
var.getAST() = ast and
|
||||
var.getTag() = tag and
|
||||
var.getType() = type
|
||||
var.getLanguageType() = type
|
||||
)
|
||||
}
|
||||
|
||||
@@ -135,24 +136,12 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
Type getInstructionOperandType(Instruction instr, TypedOperandTag tag) {
|
||||
Language::LanguageType getInstructionOperandType(Instruction instr, TypedOperandTag tag) {
|
||||
exists(OldInstruction oldInstruction, OldIR::TypedOperand oldOperand |
|
||||
oldInstruction = getOldInstruction(instr) and
|
||||
oldOperand = oldInstruction.getAnOperand() and
|
||||
tag = oldOperand.getOperandTag() and
|
||||
result = oldOperand.getType()
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
int getInstructionOperandSize(Instruction instr, SideEffectOperandTag tag) {
|
||||
exists(OldInstruction oldInstruction, OldIR::SideEffectOperand oldOperand |
|
||||
oldInstruction = getOldInstruction(instr) and
|
||||
oldOperand = oldInstruction.getAnOperand() and
|
||||
tag = oldOperand.getOperandTag() and
|
||||
// Only return a result for operands that need an explicit result size.
|
||||
oldOperand.getType() instanceof UnknownType and
|
||||
result = oldOperand.getSize()
|
||||
result = oldOperand.getLanguageType()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -196,20 +185,21 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
Expr getInstructionConvertedResultExpression(Instruction instruction) {
|
||||
Language::Expr getInstructionConvertedResultExpression(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).getConvertedResultExpression()
|
||||
}
|
||||
|
||||
cached
|
||||
Expr getInstructionUnconvertedResultExpression(Instruction instruction) {
|
||||
Language::Expr getInstructionUnconvertedResultExpression(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).getUnconvertedResultExpression()
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* This adds Chi nodes to the instruction successor relation; if an instruction has a Chi node,
|
||||
* that node is its successor in the new successor relation, and the Chi node's successors are
|
||||
* the new instructions generated from the successors of the old instruction
|
||||
*/
|
||||
|
||||
cached
|
||||
Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
|
||||
if hasChiNode(_, getOldInstruction(instruction))
|
||||
@@ -252,7 +242,7 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
Locatable getInstructionAST(Instruction instruction) {
|
||||
Language::AST getInstructionAST(Instruction instruction) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = WrappedInstruction(oldInstruction)
|
||||
or
|
||||
@@ -270,29 +260,25 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
predicate instructionHasType(Instruction instruction, Type type, boolean isGLValue) {
|
||||
Language::LanguageType getInstructionResultType(Instruction instruction) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = WrappedInstruction(oldInstruction) and
|
||||
type = oldInstruction.getResultType() and
|
||||
if oldInstruction.isGLValue() then isGLValue = true else isGLValue = false
|
||||
result = oldInstruction.getResultLanguageType()
|
||||
)
|
||||
or
|
||||
exists(OldInstruction oldInstruction, Alias::VirtualVariable vvar |
|
||||
instruction = Chi(oldInstruction) and
|
||||
hasChiNode(vvar, oldInstruction) and
|
||||
type = vvar.getType() and
|
||||
isGLValue = false
|
||||
result = vvar.getType()
|
||||
)
|
||||
or
|
||||
exists(Alias::MemoryLocation location |
|
||||
instruction = Phi(_, location) and
|
||||
type = location.getType() and
|
||||
isGLValue = false
|
||||
result = location.getType()
|
||||
)
|
||||
or
|
||||
instruction = Unreached(_) and
|
||||
type instanceof VoidType and
|
||||
isGLValue = false
|
||||
result = Language::getVoidType()
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -338,12 +324,12 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
Field getInstructionField(Instruction instruction) {
|
||||
Language::Field getInstructionField(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::FieldInstruction).getField()
|
||||
}
|
||||
|
||||
cached
|
||||
Function getInstructionFunction(Instruction instruction) {
|
||||
Language::Function getInstructionFunction(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::FunctionInstruction).getFunctionSymbol()
|
||||
}
|
||||
|
||||
@@ -353,19 +339,19 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
StringLiteral getInstructionStringLiteral(Instruction instruction) {
|
||||
Language::StringLiteral getInstructionStringLiteral(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue()
|
||||
}
|
||||
|
||||
cached
|
||||
BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) {
|
||||
Language::BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) {
|
||||
result = getOldInstruction(instruction)
|
||||
.(OldIR::BuiltInOperationInstruction)
|
||||
.getBuiltInOperation()
|
||||
}
|
||||
|
||||
cached
|
||||
Type getInstructionExceptionType(Instruction instruction) {
|
||||
Language::LanguageType getInstructionExceptionType(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::CatchByTypeInstruction).getExceptionType()
|
||||
}
|
||||
|
||||
@@ -375,14 +361,9 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
int getInstructionResultSize(Instruction instruction) {
|
||||
// Only return a result for instructions that needed an explicit result size.
|
||||
instruction.getResultType() instanceof UnknownType and
|
||||
result = getOldInstruction(instruction).getResultSize()
|
||||
}
|
||||
|
||||
cached
|
||||
predicate getInstructionInheritance(Instruction instruction, Class baseClass, Class derivedClass) {
|
||||
predicate getInstructionInheritance(
|
||||
Instruction instruction, Language::Class baseClass, Language::Class derivedClass
|
||||
) {
|
||||
exists(OldIR::InheritanceConversionInstruction oldInstr |
|
||||
oldInstr = getOldInstruction(instruction) and
|
||||
baseClass = oldInstr.getBaseClass() and
|
||||
@@ -879,3 +860,4 @@ private module CachedForDebugging {
|
||||
result.getTag() = var.getTag()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,4 +2,5 @@ import semmle.code.cpp.ir.implementation.raw.IR as OldIR
|
||||
import semmle.code.cpp.ir.implementation.raw.internal.reachability.ReachableBlock as Reachability
|
||||
import semmle.code.cpp.ir.implementation.raw.internal.reachability.Dominance as Dominance
|
||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as NewIR
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
import SimpleSSA as Alias
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
import AliasAnalysis
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.implementation.raw.IR
|
||||
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
|
||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||
private import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
private import semmle.code.cpp.ir.internal.Overlap
|
||||
|
||||
private class IntValue = Ints::IntValue;
|
||||
|
||||
private predicate hasResultMemoryAccess(
|
||||
Instruction instr, IRVariable var, Type type, IntValue bitOffset
|
||||
Instruction instr, IRVariable var, Language::LanguageType type, IntValue bitOffset
|
||||
) {
|
||||
resultPointsTo(instr.getResultAddressOperand().getAnyDef(), var, bitOffset) and
|
||||
type = instr.getResultType()
|
||||
type = instr.getResultLanguageType()
|
||||
}
|
||||
|
||||
private predicate hasOperandMemoryAccess(
|
||||
MemoryOperand operand, IRVariable var, Type type, IntValue bitOffset
|
||||
MemoryOperand operand, IRVariable var, Language::LanguageType type, IntValue bitOffset
|
||||
) {
|
||||
resultPointsTo(operand.getAddressOperand().getAnyDef(), var, bitOffset) and
|
||||
type = operand.getType()
|
||||
type = operand.getLanguageType()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -30,17 +30,17 @@ private predicate isVariableModeled(IRVariable var) {
|
||||
not variableAddressEscapes(var) and
|
||||
// There's no need to check for the right size. An `IRVariable` never has an `UnknownType`, so the test for
|
||||
// `type = var.getType()` is sufficient.
|
||||
forall(Instruction instr, Type type, IntValue bitOffset |
|
||||
forall(Instruction instr, Language::LanguageType type, IntValue bitOffset |
|
||||
hasResultMemoryAccess(instr, var, type, bitOffset)
|
||||
|
|
||||
bitOffset = 0 and
|
||||
type = var.getType()
|
||||
type.getIRType() = var.getIRType()
|
||||
) and
|
||||
forall(MemoryOperand operand, Type type, IntValue bitOffset |
|
||||
forall(MemoryOperand operand, Language::LanguageType type, IntValue bitOffset |
|
||||
hasOperandMemoryAccess(operand, var, type, bitOffset)
|
||||
|
|
||||
bitOffset = 0 and
|
||||
type = var.getType()
|
||||
type.getIRType() = var.getIRType()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ class MemoryLocation extends TMemoryLocation {
|
||||
|
||||
final VirtualVariable getVirtualVariable() { result = this }
|
||||
|
||||
final Type getType() { result = var.getType() }
|
||||
final Language::LanguageType getType() { result = var.getLanguageType() }
|
||||
|
||||
final string getUniqueId() { result = var.getUniqueId() }
|
||||
}
|
||||
@@ -85,3 +85,4 @@ MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
|
||||
result = getMemoryLocation(var)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
500
cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll
Normal file
500
cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll
Normal file
@@ -0,0 +1,500 @@
|
||||
private import cpp
|
||||
private import semmle.code.cpp.Print
|
||||
private import semmle.code.cpp.ir.implementation.IRType
|
||||
private import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction
|
||||
|
||||
/**
|
||||
* Works around an extractor bug where a function reference gets a size of one byte.
|
||||
*/
|
||||
private int getTypeSizeWorkaround(Type type) {
|
||||
exists(Type unspecifiedType |
|
||||
unspecifiedType = type.getUnspecifiedType() and
|
||||
(
|
||||
unspecifiedType instanceof FunctionReferenceType and
|
||||
result = any(NullPointerType t).getSize()
|
||||
or
|
||||
exists(PointerToMemberType ptmType |
|
||||
ptmType = unspecifiedType and
|
||||
(
|
||||
if ptmType.getBaseType().getUnspecifiedType() instanceof RoutineType
|
||||
then result = any(NullPointerType t).getSize() * 2
|
||||
else result = any(NullPointerType t).getSize()
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private int getTypeSize(Type type) {
|
||||
if exists(getTypeSizeWorkaround(type))
|
||||
then result = getTypeSizeWorkaround(type)
|
||||
else result = type.getSize()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if an `IRBooleanType` with the specified `byteSize` should exist.
|
||||
*/
|
||||
predicate hasBooleanType(int byteSize) {
|
||||
byteSize = getTypeSize(any(BoolType type))
|
||||
}
|
||||
|
||||
private predicate isSigned(IntegralOrEnumType type) {
|
||||
type.(IntegralType).isSigned() or
|
||||
exists(Enum enumType |
|
||||
enumType = type.getUnspecifiedType() and
|
||||
(
|
||||
enumType.getExplicitUnderlyingType().getUnspecifiedType().(IntegralType).isSigned() or
|
||||
not exists(enumType.getExplicitUnderlyingType()) // Assume signed.
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isSignedIntegerType(IntegralOrEnumType type) {
|
||||
isSigned(type) and not type instanceof BoolType
|
||||
}
|
||||
|
||||
private predicate isUnsignedIntegerType(IntegralOrEnumType type) {
|
||||
not isSigned(type) and not type instanceof BoolType
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if an `IRSignedIntegerType` with the specified `byteSize` should exist.
|
||||
*/
|
||||
predicate hasSignedIntegerType(int byteSize) {
|
||||
byteSize = any(IntegralOrEnumType type | isSignedIntegerType(type)).getSize()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if an `IRUnsignedIntegerType` with the specified `byteSize` should exist.
|
||||
*/
|
||||
predicate hasUnsignedIntegerType(int byteSize) {
|
||||
byteSize = any(IntegralOrEnumType type | isUnsignedIntegerType(type)).getSize()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if an `IRFloatingPointType` with the specified `byteSize` should exist.
|
||||
*/
|
||||
predicate hasFloatingPointType(int byteSize) {
|
||||
byteSize = any(FloatingPointType type).getSize()
|
||||
}
|
||||
|
||||
private predicate isPointerIshType(Type type) {
|
||||
type instanceof PointerType or
|
||||
type instanceof ReferenceType or
|
||||
type instanceof NullPointerType
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if an `IRAddressType` with the specified `byteSize` should exist.
|
||||
*/
|
||||
predicate hasAddressType(int byteSize) {
|
||||
// This covers all pointers, all references, and because it also looks at `NullPointerType`, it
|
||||
// should always return a result that makes sense for arbitrary glvalues as well.
|
||||
byteSize = any(Type type | isPointerIshType(type)).getSize()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if an `IRFunctionAddressType` with the specified `byteSize` should exist.
|
||||
*/
|
||||
predicate hasFunctionAddressType(int byteSize) {
|
||||
byteSize = any(NullPointerType type).getSize() or // Covers function lvalues
|
||||
byteSize = getTypeSize(any(FunctionPointerIshType type))
|
||||
}
|
||||
|
||||
private predicate isBlobType(Type type) {
|
||||
(
|
||||
exists(type.getSize()) and // Only include complete types
|
||||
(
|
||||
type instanceof ArrayType or
|
||||
type instanceof Class or
|
||||
type instanceof GNUVectorType
|
||||
)
|
||||
) or
|
||||
type instanceof PointerToMemberType // PTMs are missing size info
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if an `IRBlobType` with the specified `tag` and `byteSize` should exist.
|
||||
*/
|
||||
predicate hasBlobType(Type tag, int byteSize) {
|
||||
isBlobType(tag) and byteSize = getTypeSize(tag)
|
||||
or
|
||||
tag instanceof UnknownType and IRConstruction::needsUnknownBlobType(byteSize)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `IRType` that represents a prvalue of the specified `Type`.
|
||||
*/
|
||||
private IRType getIRTypeForPRValue(Type type) {
|
||||
exists(Type unspecifiedType |
|
||||
unspecifiedType = type.getUnspecifiedType() |
|
||||
(
|
||||
isBlobType(unspecifiedType) and
|
||||
exists(IRBlobType blobType |
|
||||
blobType = result |
|
||||
blobType.getByteSize() = getTypeSize(type) and
|
||||
blobType.getTag() = unspecifiedType
|
||||
)
|
||||
) or
|
||||
unspecifiedType instanceof BoolType and result.(IRBooleanType).getByteSize() = type.getSize() or
|
||||
isSignedIntegerType(unspecifiedType) and result.(IRSignedIntegerType).getByteSize() = type.getSize() or
|
||||
isUnsignedIntegerType(unspecifiedType) and result.(IRUnsignedIntegerType).getByteSize() = type.getSize() or
|
||||
unspecifiedType instanceof FloatingPointType and result.(IRFloatingPointType).getByteSize() = type.getSize() or
|
||||
isPointerIshType(unspecifiedType) and result.(IRAddressType).getByteSize() = type.getSize() or
|
||||
unspecifiedType instanceof FunctionPointerIshType and result.(IRFunctionAddressType).getByteSize() = getTypeSize(type) or
|
||||
unspecifiedType instanceof VoidType and result instanceof IRVoidType or
|
||||
unspecifiedType instanceof ErroneousType and result instanceof IRErrorType or
|
||||
unspecifiedType instanceof UnknownType and result instanceof IRUnknownType
|
||||
)
|
||||
}
|
||||
|
||||
private newtype TCppType =
|
||||
TPRValueType(Type type) {
|
||||
exists(getIRTypeForPRValue(type))
|
||||
} or
|
||||
TFunctionGLValueType() or
|
||||
TGLValueAddressType(Type type) {
|
||||
any()
|
||||
} or
|
||||
TUnknownBlobType(int byteSize) {
|
||||
IRConstruction::needsUnknownBlobType(byteSize)
|
||||
} or
|
||||
TUnknownType()
|
||||
|
||||
/**
|
||||
* The C++ type of an IR entity.
|
||||
* This cannot just be `Type` for a couple reasons:
|
||||
* - Some types needed by the IR might not exist in the database (e.g. `RoutineType`s for functions
|
||||
* that are always called directly)
|
||||
* - Some types needed by the IR are not representable in the C++ type system (e.g. the result type
|
||||
* of a `VariableAddress` where the variable is of reference type)
|
||||
*/
|
||||
class CppType extends TCppType {
|
||||
string toString() {
|
||||
result = ""
|
||||
}
|
||||
|
||||
/** Gets a string used in IR dumps */
|
||||
string getDumpString() { result = toString() }
|
||||
|
||||
/** Gets the size of the type in bytes, if known. */
|
||||
final int getByteSize() { result = getIRType().getByteSize() }
|
||||
|
||||
/**
|
||||
* Gets the `IRType` that represents this `CppType`. Many different `CppType`s can map to a single
|
||||
* `IRType`.
|
||||
*/
|
||||
abstract IRType getIRType();
|
||||
|
||||
/**
|
||||
* Holds if the `CppType` represents a prvalue of type `Type` (if `isGLValue` is `false`), or if
|
||||
* it represents a glvalue of type `Type` (if `isGLValue` is `true`).
|
||||
*/
|
||||
abstract predicate hasType(Type type, boolean isGLValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* A `CppType` that wraps an existing `Type` (either as a prvalue or a glvalue).
|
||||
*/
|
||||
private class CppWrappedType extends CppType {
|
||||
Type ctype;
|
||||
|
||||
CppWrappedType() {
|
||||
this = TPRValueType(ctype) or
|
||||
this = TGLValueAddressType(ctype)
|
||||
}
|
||||
|
||||
abstract override IRType getIRType();
|
||||
abstract override predicate hasType(Type type, boolean isGLValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* A `CppType` that represents a prvalue of an existing `Type`.
|
||||
*/
|
||||
private class CppPRValueType extends CppWrappedType, TPRValueType {
|
||||
override final string toString() { result = ctype.toString() }
|
||||
|
||||
override final string getDumpString() { result = ctype.getUnspecifiedType().toString() }
|
||||
|
||||
override final IRType getIRType() { result = getIRTypeForPRValue(ctype) }
|
||||
|
||||
override final predicate hasType(Type type, boolean isGLValue) {
|
||||
type = ctype and
|
||||
isGLValue = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A `CppType` that has unknown type but a known size. Generally to represent synthesized types that
|
||||
* occur in certain cases during IR construction, such as the type of a zero-initialized segment of
|
||||
* a partially-initialized array.
|
||||
*/
|
||||
private class CppUnknownBlobType extends CppType, TUnknownBlobType {
|
||||
int byteSize;
|
||||
|
||||
CppUnknownBlobType() {
|
||||
this = TUnknownBlobType(byteSize)
|
||||
}
|
||||
|
||||
override final string toString() {
|
||||
result = "unknown[" + byteSize.toString() + "]"
|
||||
}
|
||||
|
||||
override final IRBlobType getIRType() {
|
||||
result.getByteSize() = byteSize
|
||||
}
|
||||
|
||||
override predicate hasType(Type type, boolean isGLValue) {
|
||||
type instanceof UnknownType and isGLValue = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A `CppType` that represents a glvalue of an existing `Type`.
|
||||
*/
|
||||
private class CppGLValueAddressType extends CppWrappedType, TGLValueAddressType {
|
||||
override final string toString() {
|
||||
result = "glval<" + ctype.toString() + ">"
|
||||
}
|
||||
|
||||
override final string getDumpString() {
|
||||
result = "glval<" + ctype.getUnspecifiedType().toString() + ">"
|
||||
}
|
||||
|
||||
override final IRAddressType getIRType() {
|
||||
result.getByteSize() = any(NullPointerType t).getSize()
|
||||
}
|
||||
|
||||
override final predicate hasType(Type type, boolean isGLValue) {
|
||||
type = ctype and
|
||||
isGLValue = true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A `CppType` that represents a function lvalue.
|
||||
*/
|
||||
private class CppFunctionGLValueType extends CppType, TFunctionGLValueType {
|
||||
override final string toString() {
|
||||
result = "glval<unknown>"
|
||||
}
|
||||
|
||||
override final IRFunctionAddressType getIRType() {
|
||||
result.getByteSize() = any(NullPointerType type).getSize()
|
||||
}
|
||||
|
||||
override final predicate hasType(Type type, boolean isGLValue) {
|
||||
type instanceof UnknownType and isGLValue = true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A `CppType` that represents an unknown type.
|
||||
*/
|
||||
private class CppUnknownType extends CppType, TUnknownType {
|
||||
override final string toString() {
|
||||
result = any(UnknownType type).toString()
|
||||
}
|
||||
|
||||
override final IRUnknownType getIRType() {
|
||||
any()
|
||||
}
|
||||
|
||||
override final predicate hasType(Type type, boolean isGLValue) {
|
||||
type instanceof UnknownType and isGLValue = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the single instance of `CppUnknownType`.
|
||||
*/
|
||||
CppUnknownType getUnknownType() {
|
||||
any()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `CppType` that represents a prvalue of type `void`.
|
||||
*/
|
||||
CppPRValueType getVoidType() {
|
||||
exists(VoidType voidType |
|
||||
result.hasType(voidType, false)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `CppType` that represents a prvalue of type `type`.
|
||||
*/
|
||||
CppType getTypeForPRValue(Type type) {
|
||||
if type instanceof UnknownType
|
||||
then result instanceof CppUnknownType
|
||||
else result.hasType(type, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `CppType` that represents a glvalue of type `type`.
|
||||
*/
|
||||
CppType getTypeForGLValue(Type type) {
|
||||
result.hasType(type, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `CppType` that represents a prvalue of type `int`.
|
||||
*/
|
||||
CppPRValueType getIntType() {
|
||||
exists(IntType type |
|
||||
type.isImplicitlySigned() and
|
||||
result.hasType(type, false)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `CppType` that represents a prvalue of type `bool`.
|
||||
*/
|
||||
CppPRValueType getBoolType() {
|
||||
exists(BoolType type |
|
||||
result.hasType(type, false)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `CppType` that represents a glvalue of function type.
|
||||
*/
|
||||
CppFunctionGLValueType getFunctionGLValueType() {
|
||||
any()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `CppType` that represents a blob of unknown type with size `byteSize`.
|
||||
*/
|
||||
CppUnknownBlobType getUnknownBlobType(int byteSize) {
|
||||
result.getByteSize() = byteSize
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `CppType` that is the canonical type for an `IRBooleanType` with the specified
|
||||
* `byteSize`.
|
||||
*/
|
||||
CppWrappedType getCanonicalBooleanType(int byteSize) {
|
||||
exists(BoolType type |
|
||||
result = TPRValueType(type) and byteSize = type.getSize()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the sorting priority of an `IntegralType` based on its signedness.
|
||||
*/
|
||||
private int getSignPriority(IntegralType type) {
|
||||
/*
|
||||
Explicitly unsigned types sort first. Explicitly signed types sort last. Types with no explicit
|
||||
signedness sort in between. This lets us always choose `int` over `signed int`, while also
|
||||
choosing `unsigned char`+`char` when `char` is signed, and `unsigned char`+`signed char` when
|
||||
`char` is unsigned.
|
||||
*/
|
||||
if type.isExplicitlyUnsigned()
|
||||
then result = 2
|
||||
else if type.isExplicitlySigned()
|
||||
then result = 0
|
||||
else result = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the sort priority of an `IntegralType` based on its kind.
|
||||
*/
|
||||
private int getKindPriority(IntegralType type) {
|
||||
/*
|
||||
`CharType` sorts lower so that we prefer the plain integer types when they have the same size as
|
||||
a `CharType`.
|
||||
*/
|
||||
if type instanceof CharType
|
||||
then result = 0
|
||||
else result = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `CppType` that is the canonical type for an `IRSignedIntegerType` with the specified
|
||||
* `byteSize`.
|
||||
*/
|
||||
CppPRValueType getCanonicalSignedIntegerType(int byteSize) {
|
||||
result = TPRValueType(max(IntegralType type | type.isSigned() and type.getSize() = byteSize |
|
||||
type order by getKindPriority(type), getSignPriority(type), type.toString() desc))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `CppType` that is the canonical type for an `IRUnsignedIntegerType` with the specified
|
||||
* `byteSize`.
|
||||
*/
|
||||
CppPRValueType getCanonicalUnsignedIntegerType(int byteSize) {
|
||||
result = TPRValueType(max(IntegralType type | type.isUnsigned() and type.getSize() = byteSize |
|
||||
type order by getKindPriority(type), getSignPriority(type), type.toString() desc))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `CppType` that is the canonical type for an `IRFloatingPointType` with the specified
|
||||
* `byteSize`.
|
||||
*/
|
||||
CppPRValueType getCanonicalFloatingPointType(int byteSize) {
|
||||
result = TPRValueType(max(FloatingPointType type | type.getSize() = byteSize |
|
||||
type order by type.toString() desc))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `CppType` that is the canonical type for an `IRAddressType` with the specified
|
||||
* `byteSize`.
|
||||
*/
|
||||
CppPRValueType getCanonicalAddressType(int byteSize) {
|
||||
// We just use `NullPointerType`, since it should be unique.
|
||||
exists(NullPointerType type |
|
||||
type.getSize() = byteSize and
|
||||
result = TPRValueType(type)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `CppType` that is the canonical type for an `IRFunctionAddressType` with the specified
|
||||
* `byteSize`.
|
||||
*/
|
||||
CppFunctionGLValueType getCanonicalFunctionAddressType(int byteSize) {
|
||||
result.getByteSize() = byteSize
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `CppType` that is the canonical type for `IRErrorType`.
|
||||
*/
|
||||
CppPRValueType getCanonicalErrorType() {
|
||||
result = TPRValueType(any(ErroneousType type))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `CppType` that is the canonical type for `IRUnknownType`.
|
||||
*/
|
||||
CppUnknownType getCanonicalUnknownType() {
|
||||
any()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `CppType` that is the canonical type for `IRVoidType`.
|
||||
*/
|
||||
CppPRValueType getCanonicalVoidType() {
|
||||
result = TPRValueType(any(VoidType type))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `CppType` that is the canonical type for an `IRBlobType` with the specified `tag` and
|
||||
* `byteSize`.
|
||||
*/
|
||||
CppType getCanonicalBlobType(Type tag, int byteSize) {
|
||||
isBlobType(tag) and
|
||||
result = TPRValueType(tag.getUnspecifiedType()) and
|
||||
getTypeSize(tag) = byteSize
|
||||
or
|
||||
tag instanceof UnknownType and result = getUnknownBlobType(byteSize)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string that uniquely identifies an `IRBlobType` tag. This may be different from the usual
|
||||
* `toString()` of the tag in order to ensure uniqueness.
|
||||
*/
|
||||
string getBlobTagIdentityString(Type tag) {
|
||||
hasBlobType(tag, _) and
|
||||
result = getTypeIdentityString(tag)
|
||||
}
|
||||
@@ -1,6 +1,13 @@
|
||||
private import cpp as Cpp
|
||||
private import semmle.code.cpp.Print as Print
|
||||
private import IRUtilities
|
||||
private import semmle.code.cpp.ir.implementation.IRType
|
||||
private import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction
|
||||
import CppType
|
||||
|
||||
class LanguageType = CppType;
|
||||
|
||||
class BlobTypeTag = Cpp::Type;
|
||||
|
||||
class Function = Cpp::Function;
|
||||
|
||||
|
||||
@@ -7795,16 +7795,16 @@ ir.cpp:
|
||||
# 1101| 0: [VariableAccess] x
|
||||
# 1101| Type = [IntType] int
|
||||
# 1101| ValueCategory = prvalue(load)
|
||||
# 1104| [TopLevelFunction] void AsmStmtWithOutputs(unsigned int&, unsigned int&, unsigned int&, unsigned int&)
|
||||
# 1104| [TopLevelFunction] void AsmStmtWithOutputs(unsigned int&, unsigned int, unsigned int&, unsigned int)
|
||||
# 1104| params:
|
||||
# 1104| 0: [Parameter] a
|
||||
# 1104| Type = [LValueReferenceType] unsigned int &
|
||||
# 1104| 1: [Parameter] b
|
||||
# 1104| Type = [LValueReferenceType] unsigned int &
|
||||
# 1104| Type = [IntType] unsigned int
|
||||
# 1104| 2: [Parameter] c
|
||||
# 1104| Type = [LValueReferenceType] unsigned int &
|
||||
# 1104| 3: [Parameter] d
|
||||
# 1104| Type = [LValueReferenceType] unsigned int &
|
||||
# 1104| Type = [IntType] unsigned int
|
||||
# 1105| body: [Block] { ... }
|
||||
# 1106| 0: [AsmStmt] asm statement
|
||||
# 1109| 0: [ReferenceDereferenceExpr] (reference dereference)
|
||||
@@ -7813,24 +7813,18 @@ ir.cpp:
|
||||
# 1109| expr: [VariableAccess] a
|
||||
# 1109| Type = [LValueReferenceType] unsigned int &
|
||||
# 1109| ValueCategory = prvalue(load)
|
||||
# 1109| 1: [ReferenceDereferenceExpr] (reference dereference)
|
||||
# 1109| 1: [VariableAccess] b
|
||||
# 1109| Type = [IntType] unsigned int
|
||||
# 1109| ValueCategory = lvalue
|
||||
# 1109| expr: [VariableAccess] b
|
||||
# 1109| Type = [LValueReferenceType] unsigned int &
|
||||
# 1109| ValueCategory = prvalue(load)
|
||||
# 1109| 2: [ReferenceDereferenceExpr] (reference dereference)
|
||||
# 1109| Type = [IntType] unsigned int
|
||||
# 1109| ValueCategory = lvalue
|
||||
# 1109| ValueCategory = prvalue(load)
|
||||
# 1109| expr: [VariableAccess] c
|
||||
# 1109| Type = [LValueReferenceType] unsigned int &
|
||||
# 1109| ValueCategory = prvalue(load)
|
||||
# 1109| 3: [ReferenceDereferenceExpr] (reference dereference)
|
||||
# 1109| 3: [VariableAccess] d
|
||||
# 1109| Type = [IntType] unsigned int
|
||||
# 1109| ValueCategory = lvalue
|
||||
# 1109| expr: [VariableAccess] d
|
||||
# 1109| Type = [LValueReferenceType] unsigned int &
|
||||
# 1109| ValueCategory = prvalue(load)
|
||||
# 1109| ValueCategory = prvalue(load)
|
||||
# 1111| 1: [ReturnStmt] return ...
|
||||
# 1113| [TopLevelFunction] void ExternDeclarations()
|
||||
# 1113| params:
|
||||
|
||||
@@ -13,3 +13,5 @@ containsLoopOfForwardEdges
|
||||
lostReachability
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -1101,12 +1101,12 @@ int AsmStmt(int x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
static void AsmStmtWithOutputs(unsigned int& a, unsigned int& b, unsigned int& c, unsigned int& d)
|
||||
static void AsmStmtWithOutputs(unsigned int& a, unsigned int b, unsigned int& c, unsigned int d)
|
||||
{
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"cpuid\n\t"
|
||||
: "+a" (a), "+b" (b), "+c" (c), "+d" (d)
|
||||
: "+a" (a), "+b" (b) : "c" (c), "d" (d)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -2192,24 +2192,24 @@ ir.cpp:
|
||||
#-----| True -> Block 2
|
||||
|
||||
# 489| Block 1
|
||||
# 489| r1_0(glval<int>) = VariableAddress[#temp489:6] :
|
||||
# 489| r1_1(glval<int>) = Load : &:r1_0, ~mu0_2
|
||||
# 489| mu1_2(int) = Store : &:r1_1, r0_9
|
||||
# 490| v1_3(void) = NoOp :
|
||||
# 486| v1_4(void) = ReturnVoid :
|
||||
# 486| v1_5(void) = UnmodeledUse : mu*
|
||||
# 486| v1_6(void) = ExitFunction :
|
||||
# 489| r1_0(glval<unknown>) = VariableAddress[#temp489:6] :
|
||||
# 489| r1_1(glval<int>) = Load : &:r1_0, ~mu0_2
|
||||
# 489| mu1_2(int) = Store : &:r1_1, r0_9
|
||||
# 490| v1_3(void) = NoOp :
|
||||
# 486| v1_4(void) = ReturnVoid :
|
||||
# 486| v1_5(void) = UnmodeledUse : mu*
|
||||
# 486| v1_6(void) = ExitFunction :
|
||||
|
||||
# 489| Block 2
|
||||
# 489| r2_0(glval<int>) = VariableAddress[x] :
|
||||
# 489| r2_1(glval<int>) = VariableAddress[#temp489:6] :
|
||||
# 489| mu2_2(int) = Store : &:r2_1, r2_0
|
||||
# 489| r2_0(glval<int>) = VariableAddress[x] :
|
||||
# 489| r2_1(glval<unknown>) = VariableAddress[#temp489:6] :
|
||||
# 489| mu2_2(glval<int>) = Store : &:r2_1, r2_0
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 489| Block 3
|
||||
# 489| r3_0(glval<int>) = VariableAddress[y] :
|
||||
# 489| r3_1(glval<int>) = VariableAddress[#temp489:6] :
|
||||
# 489| mu3_2(int) = Store : &:r3_1, r3_0
|
||||
# 489| r3_0(glval<int>) = VariableAddress[y] :
|
||||
# 489| r3_1(glval<unknown>) = VariableAddress[#temp489:6] :
|
||||
# 489| mu3_2(glval<int>) = Store : &:r3_1, r3_0
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 492| void Conditional_Void(bool)
|
||||
@@ -2684,12 +2684,12 @@ ir.cpp:
|
||||
# 590| mu0_1(unknown) = AliasedDefinition :
|
||||
# 590| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 591| r0_3(glval<..(*)(..)>) = VariableAddress[pfn] :
|
||||
# 591| r0_4(glval<..(*)(..)>) = FunctionAddress[FuncPtrTarget] :
|
||||
# 591| r0_4(..(*)(..)) = FunctionAddress[FuncPtrTarget] :
|
||||
# 591| mu0_5(..(*)(..)) = Store : &:r0_3, r0_4
|
||||
# 592| r0_6(glval<..()(..)>) = FunctionAddress[FuncPtrTarget] :
|
||||
# 592| r0_7(glval<..(*)(..)>) = VariableAddress[pfn] :
|
||||
# 592| mu0_8(..(*)(..)) = Store : &:r0_7, r0_6
|
||||
# 593| r0_9(glval<..(*)(..)>) = FunctionAddress[FuncPtrTarget] :
|
||||
# 593| r0_9(..(*)(..)) = FunctionAddress[FuncPtrTarget] :
|
||||
# 593| r0_10(glval<..(*)(..)>) = VariableAddress[pfn] :
|
||||
# 593| mu0_11(..(*)(..)) = Store : &:r0_10, r0_9
|
||||
# 594| r0_12(glval<..()(..)>) = FunctionAddress[FuncPtrTarget] :
|
||||
@@ -4535,7 +4535,7 @@ ir.cpp:
|
||||
# 1029| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 1029| r0_3(glval<decltype([...](...){...})>) = InitializeThis :
|
||||
# 1029| r0_4(glval<..(*)(..)>) = VariableAddress[#return] :
|
||||
# 1029| r0_5(glval<..(*)(..)>) = FunctionAddress[_FUN] :
|
||||
# 1029| r0_5(..(*)(..)) = FunctionAddress[_FUN] :
|
||||
# 1029| mu0_6(..(*)(..)) = Store : &:r0_4, r0_5
|
||||
# 1029| r0_7(glval<..(*)(..)>) = VariableAddress[#return] :
|
||||
# 1029| v0_8(void) = ReturnValue : &:r0_7, ~mu0_2
|
||||
@@ -4722,7 +4722,7 @@ ir.cpp:
|
||||
# 1032| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 1032| r0_3(glval<decltype([...](...){...})>) = InitializeThis :
|
||||
# 1032| r0_4(glval<..(*)(..)>) = VariableAddress[#return] :
|
||||
# 1032| r0_5(glval<..(*)(..)>) = FunctionAddress[_FUN] :
|
||||
# 1032| r0_5(..(*)(..)) = FunctionAddress[_FUN] :
|
||||
# 1032| mu0_6(..(*)(..)) = Store : &:r0_4, r0_5
|
||||
# 1032| r0_7(glval<..(*)(..)>) = VariableAddress[#return] :
|
||||
# 1032| v0_8(void) = ReturnValue : &:r0_7, ~mu0_2
|
||||
@@ -5090,28 +5090,32 @@ ir.cpp:
|
||||
# 1099| v0_12(void) = UnmodeledUse : mu*
|
||||
# 1099| v0_13(void) = ExitFunction :
|
||||
|
||||
# 1104| void AsmStmtWithOutputs(unsigned int&, unsigned int&, unsigned int&, unsigned int&)
|
||||
# 1104| void AsmStmtWithOutputs(unsigned int&, unsigned int, unsigned int&, unsigned int)
|
||||
# 1104| Block 0
|
||||
# 1104| v0_0(void) = EnterFunction :
|
||||
# 1104| mu0_1(unknown) = AliasedDefinition :
|
||||
# 1104| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 1104| r0_3(glval<unsigned int &>) = VariableAddress[a] :
|
||||
# 1104| mu0_4(unsigned int &) = InitializeParameter[a] : &:r0_3
|
||||
# 1104| r0_5(glval<unsigned int &>) = VariableAddress[b] :
|
||||
# 1104| mu0_6(unsigned int &) = InitializeParameter[b] : &:r0_5
|
||||
# 1104| r0_5(glval<unsigned int>) = VariableAddress[b] :
|
||||
# 1104| mu0_6(unsigned int) = InitializeParameter[b] : &:r0_5
|
||||
# 1104| r0_7(glval<unsigned int &>) = VariableAddress[c] :
|
||||
# 1104| mu0_8(unsigned int &) = InitializeParameter[c] : &:r0_7
|
||||
# 1104| r0_9(glval<unsigned int &>) = VariableAddress[d] :
|
||||
# 1104| mu0_10(unsigned int &) = InitializeParameter[d] : &:r0_9
|
||||
# 1106| r0_11(glval<unsigned int &>) = VariableAddress[a] :
|
||||
# 1106| r0_12(glval<unsigned int &>) = VariableAddress[b] :
|
||||
# 1106| r0_13(glval<unsigned int &>) = VariableAddress[c] :
|
||||
# 1106| r0_14(glval<unsigned int &>) = VariableAddress[d] :
|
||||
# 1106| mu0_15(unknown) = InlineAsm : ~mu0_2, 0:r0_11, 1:r0_12, 2:r0_13, 3:r0_14
|
||||
# 1111| v0_16(void) = NoOp :
|
||||
# 1104| v0_17(void) = ReturnVoid :
|
||||
# 1104| v0_18(void) = UnmodeledUse : mu*
|
||||
# 1104| v0_19(void) = ExitFunction :
|
||||
# 1104| r0_9(glval<unsigned int>) = VariableAddress[d] :
|
||||
# 1104| mu0_10(unsigned int) = InitializeParameter[d] : &:r0_9
|
||||
# 1109| r0_11(glval<unsigned int &>) = VariableAddress[a] :
|
||||
# 1109| r0_12(unsigned int &) = Load : &:r0_11, ~mu0_2
|
||||
# 1109| r0_13(glval<unsigned int>) = VariableAddress[b] :
|
||||
# 1109| r0_14(glval<unsigned int &>) = VariableAddress[c] :
|
||||
# 1109| r0_15(unsigned int &) = Load : &:r0_14, ~mu0_2
|
||||
# 1109| r0_16(unsigned int) = Load : &:r0_15, ~mu0_2
|
||||
# 1109| r0_17(glval<unsigned int>) = VariableAddress[d] :
|
||||
# 1109| r0_18(unsigned int) = Load : &:r0_17, ~mu0_2
|
||||
# 1106| mu0_19(unknown) = InlineAsm : ~mu0_2, 0:r0_12, 1:r0_13, 2:r0_16, 3:r0_18
|
||||
# 1111| v0_20(void) = NoOp :
|
||||
# 1104| v0_21(void) = ReturnVoid :
|
||||
# 1104| v0_22(void) = UnmodeledUse : mu*
|
||||
# 1104| v0_23(void) = ExitFunction :
|
||||
|
||||
# 1113| void ExternDeclarations()
|
||||
# 1113| Block 0
|
||||
|
||||
@@ -13,3 +13,5 @@ containsLoopOfForwardEdges
|
||||
lostReachability
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -13,3 +13,5 @@ containsLoopOfForwardEdges
|
||||
lostReachability
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -738,26 +738,28 @@ ssa.cpp:
|
||||
# 184| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 184| r0_3(glval<unsigned int &>) = VariableAddress[a] :
|
||||
# 184| m0_4(unsigned int &) = InitializeParameter[a] : &:r0_3
|
||||
# 184| m0_5(unknown) = Chi : total:m0_1, partial:m0_4
|
||||
# 184| r0_6(glval<unsigned int &>) = VariableAddress[b] :
|
||||
# 184| m0_7(unsigned int &) = InitializeParameter[b] : &:r0_6
|
||||
# 184| m0_8(unknown) = Chi : total:m0_5, partial:m0_7
|
||||
# 184| r0_9(glval<unsigned int &>) = VariableAddress[c] :
|
||||
# 184| m0_10(unsigned int &) = InitializeParameter[c] : &:r0_9
|
||||
# 184| m0_11(unknown) = Chi : total:m0_8, partial:m0_10
|
||||
# 184| r0_12(glval<unsigned int &>) = VariableAddress[d] :
|
||||
# 184| m0_13(unsigned int &) = InitializeParameter[d] : &:r0_12
|
||||
# 184| m0_14(unknown) = Chi : total:m0_11, partial:m0_13
|
||||
# 186| r0_15(glval<unsigned int &>) = VariableAddress[a] :
|
||||
# 186| r0_16(glval<unsigned int &>) = VariableAddress[b] :
|
||||
# 186| r0_17(glval<unsigned int &>) = VariableAddress[c] :
|
||||
# 186| r0_18(glval<unsigned int &>) = VariableAddress[d] :
|
||||
# 186| m0_19(unknown) = InlineAsm : ~mu0_2, 0:r0_15, 1:r0_16, 2:r0_17, 3:r0_18
|
||||
# 186| m0_20(unknown) = Chi : total:m0_14, partial:m0_19
|
||||
# 192| v0_21(void) = NoOp :
|
||||
# 184| v0_22(void) = ReturnVoid :
|
||||
# 184| v0_23(void) = UnmodeledUse : mu*
|
||||
# 184| v0_24(void) = ExitFunction :
|
||||
# 184| r0_5(glval<unsigned int &>) = VariableAddress[b] :
|
||||
# 184| m0_6(unsigned int &) = InitializeParameter[b] : &:r0_5
|
||||
# 184| r0_7(glval<unsigned int &>) = VariableAddress[c] :
|
||||
# 184| m0_8(unsigned int &) = InitializeParameter[c] : &:r0_7
|
||||
# 184| r0_9(glval<unsigned int &>) = VariableAddress[d] :
|
||||
# 184| m0_10(unsigned int &) = InitializeParameter[d] : &:r0_9
|
||||
# 189| r0_11(glval<unsigned int &>) = VariableAddress[a] :
|
||||
# 189| r0_12(unsigned int &) = Load : &:r0_11, m0_4
|
||||
# 189| r0_13(glval<unsigned int &>) = VariableAddress[b] :
|
||||
# 189| r0_14(unsigned int &) = Load : &:r0_13, m0_6
|
||||
# 190| r0_15(glval<unsigned int &>) = VariableAddress[c] :
|
||||
# 190| r0_16(unsigned int &) = Load : &:r0_15, m0_8
|
||||
# 190| r0_17(unsigned int) = Load : &:r0_16, ~m0_1
|
||||
# 190| r0_18(glval<unsigned int &>) = VariableAddress[d] :
|
||||
# 190| r0_19(unsigned int &) = Load : &:r0_18, m0_10
|
||||
# 190| r0_20(unsigned int) = Load : &:r0_19, ~m0_1
|
||||
# 186| m0_21(unknown) = InlineAsm : ~mu0_2, 0:r0_12, 1:r0_14, 2:r0_17, 3:r0_20
|
||||
# 186| m0_22(unknown) = Chi : total:m0_1, partial:m0_21
|
||||
# 192| v0_23(void) = NoOp :
|
||||
# 184| v0_24(void) = ReturnVoid :
|
||||
# 184| v0_25(void) = UnmodeledUse : mu*
|
||||
# 184| v0_26(void) = ExitFunction :
|
||||
|
||||
# 198| int PureFunctions(char*, char*, int)
|
||||
# 198| Block 0
|
||||
|
||||
@@ -13,3 +13,5 @@ containsLoopOfForwardEdges
|
||||
lostReachability
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -708,22 +708,28 @@ ssa.cpp:
|
||||
# 184| mu0_1(unknown) = AliasedDefinition :
|
||||
# 184| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 184| r0_3(glval<unsigned int &>) = VariableAddress[a] :
|
||||
# 184| mu0_4(unsigned int &) = InitializeParameter[a] : &:r0_3
|
||||
# 184| m0_4(unsigned int &) = InitializeParameter[a] : &:r0_3
|
||||
# 184| r0_5(glval<unsigned int &>) = VariableAddress[b] :
|
||||
# 184| mu0_6(unsigned int &) = InitializeParameter[b] : &:r0_5
|
||||
# 184| m0_6(unsigned int &) = InitializeParameter[b] : &:r0_5
|
||||
# 184| r0_7(glval<unsigned int &>) = VariableAddress[c] :
|
||||
# 184| mu0_8(unsigned int &) = InitializeParameter[c] : &:r0_7
|
||||
# 184| m0_8(unsigned int &) = InitializeParameter[c] : &:r0_7
|
||||
# 184| r0_9(glval<unsigned int &>) = VariableAddress[d] :
|
||||
# 184| mu0_10(unsigned int &) = InitializeParameter[d] : &:r0_9
|
||||
# 186| r0_11(glval<unsigned int &>) = VariableAddress[a] :
|
||||
# 186| r0_12(glval<unsigned int &>) = VariableAddress[b] :
|
||||
# 186| r0_13(glval<unsigned int &>) = VariableAddress[c] :
|
||||
# 186| r0_14(glval<unsigned int &>) = VariableAddress[d] :
|
||||
# 186| mu0_15(unknown) = InlineAsm : ~mu0_2, 0:r0_11, 1:r0_12, 2:r0_13, 3:r0_14
|
||||
# 192| v0_16(void) = NoOp :
|
||||
# 184| v0_17(void) = ReturnVoid :
|
||||
# 184| v0_18(void) = UnmodeledUse : mu*
|
||||
# 184| v0_19(void) = ExitFunction :
|
||||
# 184| m0_10(unsigned int &) = InitializeParameter[d] : &:r0_9
|
||||
# 189| r0_11(glval<unsigned int &>) = VariableAddress[a] :
|
||||
# 189| r0_12(unsigned int &) = Load : &:r0_11, m0_4
|
||||
# 189| r0_13(glval<unsigned int &>) = VariableAddress[b] :
|
||||
# 189| r0_14(unsigned int &) = Load : &:r0_13, m0_6
|
||||
# 190| r0_15(glval<unsigned int &>) = VariableAddress[c] :
|
||||
# 190| r0_16(unsigned int &) = Load : &:r0_15, m0_8
|
||||
# 190| r0_17(unsigned int) = Load : &:r0_16, ~mu0_2
|
||||
# 190| r0_18(glval<unsigned int &>) = VariableAddress[d] :
|
||||
# 190| r0_19(unsigned int &) = Load : &:r0_18, m0_10
|
||||
# 190| r0_20(unsigned int) = Load : &:r0_19, ~mu0_2
|
||||
# 186| mu0_21(unknown) = InlineAsm : ~mu0_2, 0:r0_12, 1:r0_14, 2:r0_17, 3:r0_20
|
||||
# 192| v0_22(void) = NoOp :
|
||||
# 184| v0_23(void) = ReturnVoid :
|
||||
# 184| v0_24(void) = UnmodeledUse : mu*
|
||||
# 184| v0_25(void) = ExitFunction :
|
||||
|
||||
# 198| int PureFunctions(char*, char*, int)
|
||||
# 198| Block 0
|
||||
|
||||
@@ -13,3 +13,5 @@ containsLoopOfForwardEdges
|
||||
lostReachability
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -14,7 +14,7 @@ instructionWithoutSuccessor
|
||||
| condition_decls.cpp:41:22:41:23 | Chi: call to BoxedInt |
|
||||
| condition_decls.cpp:48:52:48:53 | Chi: call to BoxedInt |
|
||||
| cpp17.cpp:15:11:15:21 | Convert: (void *)... |
|
||||
| misc.c:171:10:171:13 | Uninitialized: definition of str2 |
|
||||
| misc.c:171:10:171:13 | VariableAddress: definition of str2 |
|
||||
| misc.c:219:47:219:48 | InitializeParameter: sp |
|
||||
| ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x |
|
||||
| ms_try_mix.cpp:11:12:11:15 | Chi: call to C |
|
||||
@@ -22,7 +22,7 @@ instructionWithoutSuccessor
|
||||
| ms_try_mix.cpp:48:10:48:13 | Chi: call to C |
|
||||
| pointer_to_member.cpp:35:11:35:21 | FieldAddress: {...} |
|
||||
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... |
|
||||
| vla.c:5:9:5:14 | Uninitialized: definition of matrix |
|
||||
| vla.c:5:9:5:14 | VariableAddress: definition of matrix |
|
||||
| vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef |
|
||||
ambiguousSuccessors
|
||||
| allocators.cpp:14:5:14:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo |
|
||||
@@ -541,3 +541,5 @@ lostReachability
|
||||
| range_analysis.c:371:37:371:39 | Constant: 500 |
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -35,10 +35,12 @@ instructionWithoutSuccessor
|
||||
| file://:0:0:0:0 | CompareNE: (bool)... |
|
||||
| file://:0:0:0:0 | CompareNE: (bool)... |
|
||||
| file://:0:0:0:0 | CompareNE: (bool)... |
|
||||
| misc.c:171:10:171:13 | Uninitialized: definition of str2 |
|
||||
| misc.c:171:10:171:13 | VariableAddress: definition of str2 |
|
||||
| misc.c:171:15:171:31 | Add: ... + ... |
|
||||
| misc.c:173:10:173:12 | VariableAddress: definition of buf |
|
||||
| misc.c:173:14:173:26 | Mul: ... * ... |
|
||||
| misc.c:173:37:173:39 | Store: array to pointer conversion |
|
||||
| misc.c:174:10:174:15 | VariableAddress: definition of matrix |
|
||||
| misc.c:174:17:174:22 | CallSideEffect: call to getInt |
|
||||
| misc.c:174:30:174:35 | CallSideEffect: call to getInt |
|
||||
| misc.c:174:55:174:60 | Store: (char ****)... |
|
||||
@@ -78,7 +80,7 @@ instructionWithoutSuccessor
|
||||
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... |
|
||||
| stmt_expr.cpp:29:11:32:11 | CopyValue: (statement expression) |
|
||||
| stmt_in_type.cpp:5:53:5:53 | Constant: 1 |
|
||||
| vla.c:5:9:5:14 | Uninitialized: definition of matrix |
|
||||
| vla.c:5:9:5:14 | VariableAddress: definition of matrix |
|
||||
| vla.c:5:16:5:19 | Load: argc |
|
||||
| vla.c:5:22:5:25 | CallReadSideEffect: call to atoi |
|
||||
| vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef |
|
||||
@@ -87,6 +89,7 @@ instructionWithoutSuccessor
|
||||
| vla.c:13:12:13:14 | Uninitialized: definition of var |
|
||||
| vla.c:14:36:14:47 | Add: ... + ... |
|
||||
| vla.c:14:53:14:65 | Mul: ... * ... |
|
||||
| vla.c:14:69:14:72 | VariableAddress: definition of buf2 |
|
||||
| vla.c:14:74:14:79 | CallSideEffect: call to getInt |
|
||||
| vla.c:14:92:14:94 | Store: (char *)... |
|
||||
ambiguousSuccessors
|
||||
@@ -687,3 +690,5 @@ useNotDominatedByDefinition
|
||||
| vla.c:14:40:14:45 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | vla.c:11:6:11:16 | IR: vla_typedef | void vla_typedef() |
|
||||
| vla.c:14:58:14:63 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | vla.c:11:6:11:16 | IR: vla_typedef | void vla_typedef() |
|
||||
| vla.c:14:74:14:79 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | vla.c:11:6:11:16 | IR: vla_typedef | void vla_typedef() |
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -23,7 +23,7 @@ instructionWithoutSuccessor
|
||||
| condition_decls.cpp:41:22:41:23 | CallSideEffect: call to BoxedInt |
|
||||
| condition_decls.cpp:48:52:48:53 | CallSideEffect: call to BoxedInt |
|
||||
| cpp17.cpp:15:11:15:21 | Convert: (void *)... |
|
||||
| misc.c:171:10:171:13 | Uninitialized: definition of str2 |
|
||||
| misc.c:171:10:171:13 | VariableAddress: definition of str2 |
|
||||
| misc.c:219:47:219:48 | InitializeParameter: sp |
|
||||
| ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x |
|
||||
| ms_try_mix.cpp:11:12:11:15 | CallSideEffect: call to C |
|
||||
@@ -31,7 +31,7 @@ instructionWithoutSuccessor
|
||||
| ms_try_mix.cpp:48:10:48:13 | CallSideEffect: call to C |
|
||||
| pointer_to_member.cpp:35:11:35:21 | FieldAddress: {...} |
|
||||
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... |
|
||||
| vla.c:5:9:5:14 | Uninitialized: definition of matrix |
|
||||
| vla.c:5:9:5:14 | VariableAddress: definition of matrix |
|
||||
| vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef |
|
||||
ambiguousSuccessors
|
||||
| allocators.cpp:14:5:14:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo |
|
||||
@@ -550,3 +550,5 @@ lostReachability
|
||||
| range_analysis.c:371:37:371:39 | Constant: 500 |
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
Reference in New Issue
Block a user