Merge pull request #2008 from dave-bartolomeo/dave/IRType2

C++: Implement language-neutral IR type system
This commit is contained in:
Jonas Jensen
2019-10-25 09:42:23 +02:00
committed by GitHub
130 changed files with 3536 additions and 2177 deletions

View File

@@ -610,7 +610,9 @@ class FloatingPointType extends ArithmeticType {
(
kind >= 24 and kind <= 32
or
kind = 38
kind >= 38 and kind <= 42
or
kind >= 45 and kind <= 50
)
)
}

View File

@@ -540,6 +540,13 @@ class ErrorExpr extends Expr, @errorexpr {
*/
class AssumeExpr extends Expr, @assume {
override string toString() { result = "__assume(...)" }
override string getCanonicalQLClass() { result = "AssumeExpr" }
/**
* Gets the operand of the `__assume` expressions.
*/
Expr getOperand() { this.hasChild(result, 0) }
}
/**

View File

@@ -0,0 +1,247 @@
/**
* Minimal, language-neutral type system for the IR.
*/
private import internal.IRTypeInternal
private newtype TIRType =
TIRVoidType() or
TIRUnknownType() or
TIRErrorType() { Language::hasErrorType() } 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
TIROpaqueType(Language::OpaqueTypeTag tag, int byteSize) {
Language::hasOpaqueType(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 {
string toString() { none() }
/**
* 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`.
*/
int getByteSize() { none() }
/**
* Gets a single instance of `LanguageType` that maps to this `IRType`.
*/
Language::LanguageType getCanonicalLanguageType() { none() }
}
/**
* 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 = TIROpaqueType(_, byteSize)
}
final override int getByteSize() { result = byteSize }
}
/**
* 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)
}
}
/**
* 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 IROpaqueType extends IRSizedType, TIROpaqueType {
Language::OpaqueTypeTag tag;
IROpaqueType() { this = TIROpaqueType(tag, byteSize) }
final override string toString() {
result = "opaque" + byteSize.toString() + "{" + tag.toString() + "}"
}
final override string getIdentityString() {
result = "opaque" + byteSize.toString() + "{" + Language::getOpaqueTagIdentityString(tag) + "}"
}
final override Language::LanguageType getCanonicalLanguageType() {
result = Language::getCanonicalOpaqueType(tag, byteSize)
}
/**
* Gets the "tag" that differentiates this type from other incompatible opaque types that have the
* same size.
*/
final Language::OpaqueTypeTag 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(), ", ")
}
query predicate missingIRType(Language::LanguageType type, string message) {
not exists(type.getIRType()) and
message = "`LanguageType` does not have a corresponding `IRType`."
}
query predicate multipleIRTypes(Language::LanguageType type, string message) {
strictcount(type.getIRType()) > 1 and
message = "`LanguageType` " + type.getAQlClass() + " has multiple `IRType`s: " +
concat(type.getIRType().toString(), ", ")
}
import Language::LanguageTypeSanity
}

View File

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

View File

@@ -1,2 +1,3 @@
private import IR
import InstructionSanity
import IRTypeSanity

View File

@@ -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,17 @@ 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 +70,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 +82,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 +121,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 }

View File

@@ -5,6 +5,7 @@ import IRVariable
import Operand
private import internal.InstructionImports as Imports
import Imports::EdgeKind
import Imports::IRType
import Imports::MemoryAccessKind
import Imports::Opcode
private import Imports::OperandTag
@@ -113,10 +114,12 @@ 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) + "'."
)
}
@@ -321,7 +324,7 @@ class Instruction extends Construction::TInstruction {
}
private string getResultPrefix() {
if getResultType() instanceof Language::VoidType
if getResultIRType() instanceof IRVoidType
then result = "v"
else
if hasMemoryResult()
@@ -353,23 +356,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
@@ -389,7 +375,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
@@ -457,6 +445,16 @@ 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 `IRVoidType`.
*/
final IRType getResultIRType() { result = getResultLanguageType().getIRType() }
/**
* Gets the type of the result produced by this instruction. If the
* instruction does not produce a result, its result type will be `VoidType`.
@@ -464,7 +462,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 |
resultType = getResultLanguageType() and
(
resultType.hasUnspecifiedType(result, _)
or
not resultType.hasUnspecifiedType(_, _) and result instanceof Language::UnknownType
)
)
}
/**
* Holds if the result produced by this instruction is a glvalue. If this
@@ -484,7 +491,7 @@ 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
@@ -493,16 +500,7 @@ class Instruction extends Construction::TInstruction {
* If `this.isGLValue()` holds for this instruction, the value of
* `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())
}
final int getResultSize() { result = Construction::getInstructionResultType(this).getByteSize() }
/**
* Gets the opcode that specifies the operation performed by this instruction.
@@ -1384,7 +1382,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
@@ -1396,7 +1394,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 }
}
/**

View File

@@ -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)
}
}
@@ -381,12 +395,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

View File

@@ -1,5 +1,5 @@
private import internal.ValueNumberingInternal
private import cpp
private import internal.ValueNumberingImports
private import IR
/**
@@ -23,31 +23,32 @@ newtype TValueNumber =
initializeParameterValueNumber(_, irFunc, var)
} or
TInitializeThisValueNumber(IRFunction irFunc) { initializeThisValueNumber(_, irFunc) } or
TConstantValueNumber(IRFunction irFunc, Type type, string value) {
TConstantValueNumber(IRFunction irFunc, IRType type, string value) {
constantValueNumber(_, irFunc, type, value)
} or
TStringConstantValueNumber(IRFunction irFunc, Type type, string value) {
TStringConstantValueNumber(IRFunction irFunc, IRType type, string value) {
stringConstantValueNumber(_, irFunc, type, value)
} or
TFieldAddressValueNumber(IRFunction irFunc, Field field, ValueNumber objectAddress) {
TFieldAddressValueNumber(IRFunction irFunc, Language::Field field, ValueNumber objectAddress) {
fieldAddressValueNumber(_, irFunc, field, objectAddress)
} or
TBinaryValueNumber(
IRFunction irFunc, Opcode opcode, Type type, ValueNumber leftOperand, ValueNumber rightOperand
IRFunction irFunc, Opcode opcode, IRType type, ValueNumber leftOperand, ValueNumber rightOperand
) {
binaryValueNumber(_, irFunc, opcode, type, leftOperand, rightOperand)
} or
TPointerArithmeticValueNumber(
IRFunction irFunc, Opcode opcode, Type type, int elementSize, ValueNumber leftOperand,
IRFunction irFunc, Opcode opcode, IRType type, int elementSize, ValueNumber leftOperand,
ValueNumber rightOperand
) {
pointerArithmeticValueNumber(_, irFunc, opcode, type, elementSize, leftOperand, rightOperand)
} or
TUnaryValueNumber(IRFunction irFunc, Opcode opcode, Type type, ValueNumber operand) {
TUnaryValueNumber(IRFunction irFunc, Opcode opcode, IRType type, ValueNumber operand) {
unaryValueNumber(_, irFunc, opcode, type, operand)
} or
TInheritanceConversionValueNumber(
IRFunction irFunc, Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand
IRFunction irFunc, Opcode opcode, Language::Class baseClass, Language::Class derivedClass,
ValueNumber operand
) {
inheritanceConversionValueNumber(_, irFunc, opcode, baseClass, derivedClass, operand)
} or
@@ -59,7 +60,7 @@ newtype TValueNumber =
class ValueNumber extends TValueNumber {
final string toString() { result = getExampleInstruction().getResultId() }
final Location getLocation() { result = getExampleInstruction().getLocation() }
final Language::Location getLocation() { result = getExampleInstruction().getLocation() }
/**
* Gets the instructions that have been assigned this value number. This will always produce at
@@ -150,23 +151,23 @@ private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRF
}
private predicate constantValueNumber(
ConstantInstruction instr, IRFunction irFunc, Type type, string value
ConstantInstruction instr, IRFunction irFunc, IRType type, string value
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getResultType() = type and
instr.getResultIRType() = type and
instr.getValue() = value
}
private predicate stringConstantValueNumber(
StringConstantInstruction instr, IRFunction irFunc, Type type, string value
StringConstantInstruction instr, IRFunction irFunc, IRType type, string value
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getResultType() = type and
instr.getResultIRType() = type and
instr.getValue().getValue() = value
}
private predicate fieldAddressValueNumber(
FieldAddressInstruction instr, IRFunction irFunc, Field field, ValueNumber objectAddress
FieldAddressInstruction instr, IRFunction irFunc, Language::Field field, ValueNumber objectAddress
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getField() = field and
@@ -174,43 +175,43 @@ private predicate fieldAddressValueNumber(
}
private predicate binaryValueNumber(
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, Type type, ValueNumber leftOperand,
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, IRType type, ValueNumber leftOperand,
ValueNumber rightOperand
) {
instr.getEnclosingIRFunction() = irFunc and
not instr instanceof PointerArithmeticInstruction and
instr.getOpcode() = opcode and
instr.getResultType() = type and
instr.getResultIRType() = type and
valueNumber(instr.getLeft()) = leftOperand and
valueNumber(instr.getRight()) = rightOperand
}
private predicate pointerArithmeticValueNumber(
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, Type type, int elementSize,
ValueNumber leftOperand, ValueNumber rightOperand
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, IRType type,
int elementSize, ValueNumber leftOperand, ValueNumber rightOperand
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getOpcode() = opcode and
instr.getResultType() = type and
instr.getResultIRType() = type and
instr.getElementSize() = elementSize and
valueNumber(instr.getLeft()) = leftOperand and
valueNumber(instr.getRight()) = rightOperand
}
private predicate unaryValueNumber(
UnaryInstruction instr, IRFunction irFunc, Opcode opcode, Type type, ValueNumber operand
UnaryInstruction instr, IRFunction irFunc, Opcode opcode, IRType type, ValueNumber operand
) {
instr.getEnclosingIRFunction() = irFunc and
not instr instanceof InheritanceConversionInstruction and
not instr instanceof CopyInstruction and
instr.getOpcode() = opcode and
instr.getResultType() = type and
instr.getResultIRType() = type and
valueNumber(instr.getUnary()) = operand
}
private predicate inheritanceConversionValueNumber(
InheritanceConversionInstruction instr, IRFunction irFunc, Opcode opcode, Class baseClass,
Class derivedClass, ValueNumber operand
InheritanceConversionInstruction instr, IRFunction irFunc, Opcode opcode,
Language::Class baseClass, Language::Class derivedClass, ValueNumber operand
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getOpcode() = opcode and
@@ -225,7 +226,7 @@ private predicate inheritanceConversionValueNumber(
*/
private predicate uniqueValueNumber(Instruction instr, IRFunction irFunc) {
instr.getEnclosingIRFunction() = irFunc and
not instr.getResultType() instanceof VoidType and
not instr.getResultIRType() instanceof IRVoidType and
not numberableInstruction(instr)
}
@@ -269,38 +270,41 @@ private ValueNumber nonUniqueValueNumber(Instruction instr) {
initializeThisValueNumber(instr, irFunc) and
result = TInitializeThisValueNumber(irFunc)
or
exists(Type type, string value |
exists(IRType type, string value |
constantValueNumber(instr, irFunc, type, value) and
result = TConstantValueNumber(irFunc, type, value)
)
or
exists(Type type, string value |
exists(IRType type, string value |
stringConstantValueNumber(instr, irFunc, type, value) and
result = TStringConstantValueNumber(irFunc, type, value)
)
or
exists(Field field, ValueNumber objectAddress |
exists(Language::Field field, ValueNumber objectAddress |
fieldAddressValueNumber(instr, irFunc, field, objectAddress) and
result = TFieldAddressValueNumber(irFunc, field, objectAddress)
)
or
exists(Opcode opcode, Type type, ValueNumber leftOperand, ValueNumber rightOperand |
exists(Opcode opcode, IRType type, ValueNumber leftOperand, ValueNumber rightOperand |
binaryValueNumber(instr, irFunc, opcode, type, leftOperand, rightOperand) and
result = TBinaryValueNumber(irFunc, opcode, type, leftOperand, rightOperand)
)
or
exists(Opcode opcode, Type type, ValueNumber operand |
exists(Opcode opcode, IRType type, ValueNumber operand |
unaryValueNumber(instr, irFunc, opcode, type, operand) and
result = TUnaryValueNumber(irFunc, opcode, type, operand)
)
or
exists(Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand |
exists(
Opcode opcode, Language::Class baseClass, Language::Class derivedClass, ValueNumber operand
|
inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, operand) and
result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand)
)
or
exists(
Opcode opcode, Type type, int elementSize, ValueNumber leftOperand, ValueNumber rightOperand
Opcode opcode, IRType type, int elementSize, ValueNumber leftOperand,
ValueNumber rightOperand
|
pointerArithmeticValueNumber(instr, irFunc, opcode, type, elementSize, leftOperand,
rightOperand) and

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.internal.Overlap
import semmle.code.cpp.ir.internal.IRCppLanguage as Language

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,5 @@
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
import semmle.code.cpp.ir.implementation.Opcode as Opcode
import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag

View File

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

View File

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

View File

@@ -1,8 +1,5 @@
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
private import SSAConstructionImports
private import NewIR
private class OldBlock = Reachability::ReachableBlock;
@@ -18,7 +15,7 @@ private module Cached {
}
cached
predicate functionHasIR(Function func) {
predicate functionHasIR(Language::Function func) {
exists(OldIR::IRFunction irFunc | irFunc.getFunction() = func)
}
@@ -42,7 +39,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 +47,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 +134,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 +183,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 +240,7 @@ private module Cached {
}
cached
Locatable getInstructionAST(Instruction instruction) {
Language::AST getInstructionAST(Instruction instruction) {
exists(OldInstruction oldInstruction |
instruction = WrappedInstruction(oldInstruction)
or
@@ -270,29 +258,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,7 +322,7 @@ private module Cached {
}
cached
Field getInstructionField(Instruction instruction) {
Language::Field getInstructionField(Instruction instruction) {
result = getOldInstruction(instruction).(OldIR::FieldInstruction).getField()
}
@@ -348,7 +332,7 @@ private module Cached {
}
cached
Function getInstructionFunction(Instruction instruction) {
Language::Function getInstructionFunction(Instruction instruction) {
result = getOldInstruction(instruction).(OldIR::FunctionInstruction).getFunctionSymbol()
}
@@ -358,19 +342,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()
}
@@ -380,14 +364,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

View File

@@ -0,0 +1,3 @@
import semmle.code.cpp.ir.implementation.Opcode
import semmle.code.cpp.ir.implementation.internal.OperandTag
import semmle.code.cpp.ir.internal.Overlap

View File

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

View File

@@ -0,0 +1 @@
import semmle.code.cpp.ir.internal.IRCppLanguage as Language

View File

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

View File

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

View File

@@ -1,2 +1,3 @@
private import IR
import InstructionSanity
import IRTypeSanity

View File

@@ -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,17 @@ 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 +70,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 +82,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 +121,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 }

View File

@@ -5,6 +5,7 @@ import IRVariable
import Operand
private import internal.InstructionImports as Imports
import Imports::EdgeKind
import Imports::IRType
import Imports::MemoryAccessKind
import Imports::Opcode
private import Imports::OperandTag
@@ -113,10 +114,12 @@ 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) + "'."
)
}
@@ -321,7 +324,7 @@ class Instruction extends Construction::TInstruction {
}
private string getResultPrefix() {
if getResultType() instanceof Language::VoidType
if getResultIRType() instanceof IRVoidType
then result = "v"
else
if hasMemoryResult()
@@ -353,23 +356,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
@@ -389,7 +375,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
@@ -457,6 +445,16 @@ 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 `IRVoidType`.
*/
final IRType getResultIRType() { result = getResultLanguageType().getIRType() }
/**
* Gets the type of the result produced by this instruction. If the
* instruction does not produce a result, its result type will be `VoidType`.
@@ -464,7 +462,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 |
resultType = getResultLanguageType() and
(
resultType.hasUnspecifiedType(result, _)
or
not resultType.hasUnspecifiedType(_, _) and result instanceof Language::UnknownType
)
)
}
/**
* Holds if the result produced by this instruction is a glvalue. If this
@@ -484,7 +491,7 @@ 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
@@ -493,16 +500,7 @@ class Instruction extends Construction::TInstruction {
* If `this.isGLValue()` holds for this instruction, the value of
* `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())
}
final int getResultSize() { result = Construction::getInstructionResultType(this).getByteSize() }
/**
* Gets the opcode that specifies the operation performed by this instruction.
@@ -1384,7 +1382,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
@@ -1396,7 +1394,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 }
}
/**

View File

@@ -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)
}
}
@@ -381,12 +395,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

View File

@@ -1,5 +1,5 @@
private import internal.ValueNumberingInternal
private import cpp
private import internal.ValueNumberingImports
private import IR
/**
@@ -23,31 +23,32 @@ newtype TValueNumber =
initializeParameterValueNumber(_, irFunc, var)
} or
TInitializeThisValueNumber(IRFunction irFunc) { initializeThisValueNumber(_, irFunc) } or
TConstantValueNumber(IRFunction irFunc, Type type, string value) {
TConstantValueNumber(IRFunction irFunc, IRType type, string value) {
constantValueNumber(_, irFunc, type, value)
} or
TStringConstantValueNumber(IRFunction irFunc, Type type, string value) {
TStringConstantValueNumber(IRFunction irFunc, IRType type, string value) {
stringConstantValueNumber(_, irFunc, type, value)
} or
TFieldAddressValueNumber(IRFunction irFunc, Field field, ValueNumber objectAddress) {
TFieldAddressValueNumber(IRFunction irFunc, Language::Field field, ValueNumber objectAddress) {
fieldAddressValueNumber(_, irFunc, field, objectAddress)
} or
TBinaryValueNumber(
IRFunction irFunc, Opcode opcode, Type type, ValueNumber leftOperand, ValueNumber rightOperand
IRFunction irFunc, Opcode opcode, IRType type, ValueNumber leftOperand, ValueNumber rightOperand
) {
binaryValueNumber(_, irFunc, opcode, type, leftOperand, rightOperand)
} or
TPointerArithmeticValueNumber(
IRFunction irFunc, Opcode opcode, Type type, int elementSize, ValueNumber leftOperand,
IRFunction irFunc, Opcode opcode, IRType type, int elementSize, ValueNumber leftOperand,
ValueNumber rightOperand
) {
pointerArithmeticValueNumber(_, irFunc, opcode, type, elementSize, leftOperand, rightOperand)
} or
TUnaryValueNumber(IRFunction irFunc, Opcode opcode, Type type, ValueNumber operand) {
TUnaryValueNumber(IRFunction irFunc, Opcode opcode, IRType type, ValueNumber operand) {
unaryValueNumber(_, irFunc, opcode, type, operand)
} or
TInheritanceConversionValueNumber(
IRFunction irFunc, Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand
IRFunction irFunc, Opcode opcode, Language::Class baseClass, Language::Class derivedClass,
ValueNumber operand
) {
inheritanceConversionValueNumber(_, irFunc, opcode, baseClass, derivedClass, operand)
} or
@@ -59,7 +60,7 @@ newtype TValueNumber =
class ValueNumber extends TValueNumber {
final string toString() { result = getExampleInstruction().getResultId() }
final Location getLocation() { result = getExampleInstruction().getLocation() }
final Language::Location getLocation() { result = getExampleInstruction().getLocation() }
/**
* Gets the instructions that have been assigned this value number. This will always produce at
@@ -150,23 +151,23 @@ private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRF
}
private predicate constantValueNumber(
ConstantInstruction instr, IRFunction irFunc, Type type, string value
ConstantInstruction instr, IRFunction irFunc, IRType type, string value
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getResultType() = type and
instr.getResultIRType() = type and
instr.getValue() = value
}
private predicate stringConstantValueNumber(
StringConstantInstruction instr, IRFunction irFunc, Type type, string value
StringConstantInstruction instr, IRFunction irFunc, IRType type, string value
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getResultType() = type and
instr.getResultIRType() = type and
instr.getValue().getValue() = value
}
private predicate fieldAddressValueNumber(
FieldAddressInstruction instr, IRFunction irFunc, Field field, ValueNumber objectAddress
FieldAddressInstruction instr, IRFunction irFunc, Language::Field field, ValueNumber objectAddress
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getField() = field and
@@ -174,43 +175,43 @@ private predicate fieldAddressValueNumber(
}
private predicate binaryValueNumber(
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, Type type, ValueNumber leftOperand,
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, IRType type, ValueNumber leftOperand,
ValueNumber rightOperand
) {
instr.getEnclosingIRFunction() = irFunc and
not instr instanceof PointerArithmeticInstruction and
instr.getOpcode() = opcode and
instr.getResultType() = type and
instr.getResultIRType() = type and
valueNumber(instr.getLeft()) = leftOperand and
valueNumber(instr.getRight()) = rightOperand
}
private predicate pointerArithmeticValueNumber(
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, Type type, int elementSize,
ValueNumber leftOperand, ValueNumber rightOperand
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, IRType type,
int elementSize, ValueNumber leftOperand, ValueNumber rightOperand
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getOpcode() = opcode and
instr.getResultType() = type and
instr.getResultIRType() = type and
instr.getElementSize() = elementSize and
valueNumber(instr.getLeft()) = leftOperand and
valueNumber(instr.getRight()) = rightOperand
}
private predicate unaryValueNumber(
UnaryInstruction instr, IRFunction irFunc, Opcode opcode, Type type, ValueNumber operand
UnaryInstruction instr, IRFunction irFunc, Opcode opcode, IRType type, ValueNumber operand
) {
instr.getEnclosingIRFunction() = irFunc and
not instr instanceof InheritanceConversionInstruction and
not instr instanceof CopyInstruction and
instr.getOpcode() = opcode and
instr.getResultType() = type and
instr.getResultIRType() = type and
valueNumber(instr.getUnary()) = operand
}
private predicate inheritanceConversionValueNumber(
InheritanceConversionInstruction instr, IRFunction irFunc, Opcode opcode, Class baseClass,
Class derivedClass, ValueNumber operand
InheritanceConversionInstruction instr, IRFunction irFunc, Opcode opcode,
Language::Class baseClass, Language::Class derivedClass, ValueNumber operand
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getOpcode() = opcode and
@@ -225,7 +226,7 @@ private predicate inheritanceConversionValueNumber(
*/
private predicate uniqueValueNumber(Instruction instr, IRFunction irFunc) {
instr.getEnclosingIRFunction() = irFunc and
not instr.getResultType() instanceof VoidType and
not instr.getResultIRType() instanceof IRVoidType and
not numberableInstruction(instr)
}
@@ -269,38 +270,41 @@ private ValueNumber nonUniqueValueNumber(Instruction instr) {
initializeThisValueNumber(instr, irFunc) and
result = TInitializeThisValueNumber(irFunc)
or
exists(Type type, string value |
exists(IRType type, string value |
constantValueNumber(instr, irFunc, type, value) and
result = TConstantValueNumber(irFunc, type, value)
)
or
exists(Type type, string value |
exists(IRType type, string value |
stringConstantValueNumber(instr, irFunc, type, value) and
result = TStringConstantValueNumber(irFunc, type, value)
)
or
exists(Field field, ValueNumber objectAddress |
exists(Language::Field field, ValueNumber objectAddress |
fieldAddressValueNumber(instr, irFunc, field, objectAddress) and
result = TFieldAddressValueNumber(irFunc, field, objectAddress)
)
or
exists(Opcode opcode, Type type, ValueNumber leftOperand, ValueNumber rightOperand |
exists(Opcode opcode, IRType type, ValueNumber leftOperand, ValueNumber rightOperand |
binaryValueNumber(instr, irFunc, opcode, type, leftOperand, rightOperand) and
result = TBinaryValueNumber(irFunc, opcode, type, leftOperand, rightOperand)
)
or
exists(Opcode opcode, Type type, ValueNumber operand |
exists(Opcode opcode, IRType type, ValueNumber operand |
unaryValueNumber(instr, irFunc, opcode, type, operand) and
result = TUnaryValueNumber(irFunc, opcode, type, operand)
)
or
exists(Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand |
exists(
Opcode opcode, Language::Class baseClass, Language::Class derivedClass, ValueNumber operand
|
inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, operand) and
result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand)
)
or
exists(
Opcode opcode, Type type, int elementSize, ValueNumber leftOperand, ValueNumber rightOperand
Opcode opcode, IRType type, int elementSize, ValueNumber leftOperand,
ValueNumber rightOperand
|
pointerArithmeticValueNumber(instr, irFunc, opcode, type, elementSize, leftOperand,
rightOperand) and

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.internal.Overlap
import semmle.code.cpp.ir.internal.IRCppLanguage as Language

View File

@@ -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
@@ -280,7 +276,7 @@ private module Cached {
}
cached
Type getInstructionExceptionType(Instruction instruction) {
CppType getInstructionExceptionType(Instruction instruction) {
result = getInstructionTranslatedElement(instruction)
.getInstructionExceptionType(getInstructionTag(instruction))
}
@@ -307,6 +303,11 @@ private module Cached {
)
}
cached
predicate needsUnknownOpaqueType(int byteSize) {
exists(TranslatedElement element | element.needsUnknownOpaqueType(byteSize))
}
cached
int getInstructionResultSize(Instruction instruction) {
exists(TranslatedElement element, InstructionTag tag |

View File

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

View File

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

View File

@@ -1,4 +1,5 @@
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
import semmle.code.cpp.ir.implementation.Opcode as Opcode
import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag

View File

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

View File

@@ -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
@@ -33,13 +34,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
@@ -47,13 +45,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) {
@@ -118,11 +115,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()) }
@@ -224,18 +221,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) {
@@ -253,7 +244,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)) }
@@ -349,9 +340,7 @@ class TranslatedSideEffects extends TranslatedElement, TTranslatedSideEffects {
)
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, Type t, boolean isGLValue) {
none()
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) { none() }
override Instruction getFirstInstruction() { result = getChild(0).getFirstInstruction() }
@@ -359,7 +348,9 @@ class TranslatedSideEffects extends TranslatedElement, TTranslatedSideEffects {
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { none() }
override Type getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) { none() }
override CppType getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) {
none()
}
/**
* Gets the `TranslatedFunction` containing this expression.
@@ -406,34 +397,30 @@ class TranslatedSideEffect extends TranslatedElement, TTranslatedArgumentSideEff
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, Type t, boolean isGLValue) {
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
isWrite() and
hasSpecificWriteSideEffect(opcode) and
tag = OnlyInstructionTag() and
(
opcode instanceof BufferAccessOpcode and
t instanceof UnknownType
type = getUnknownType()
or
not opcode instanceof BufferAccessOpcode and
(
t = arg.getUnspecifiedType().(DerivedType).getBaseType() and
not t instanceof VoidType
or
arg.getUnspecifiedType().(DerivedType).getBaseType() instanceof VoidType and
t instanceof UnknownType
exists(Type baseType | baseType = arg.getUnspecifiedType().(DerivedType).getBaseType() |
if baseType instanceof VoidType
then type = getUnknownType()
else type = getTypeForPRValueOrUnknown(baseType)
)
or
index = -1 and
not arg.getUnspecifiedType() instanceof DerivedType and
t = arg.getUnspecifiedType()
) and
isGLValue = false
type = getTypeForPRValueOrUnknown(arg.getUnspecifiedType())
)
or
not isWrite() and
hasSpecificReadSideEffect(opcode) and
tag = OnlyInstructionTag() and
t instanceof VoidType and
isGLValue = false
type = getVoidType()
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
@@ -459,15 +446,21 @@ class TranslatedSideEffect extends TranslatedElement, TTranslatedArgumentSideEff
.getFullyConverted()).getResult()
}
override Type getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) {
tag instanceof OnlyInstructionTag and
result = arg.getType().getUnspecifiedType().(DerivedType).getBaseType() and
operandTag instanceof SideEffectOperandTag
or
tag instanceof OnlyInstructionTag and
result = arg.getType().getUnspecifiedType() and
not result instanceof DerivedType and
operandTag instanceof SideEffectOperandTag
override CppType getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) {
exists(Type operandType |
tag instanceof OnlyInstructionTag and
operandType = arg.getType().getUnspecifiedType().(DerivedType).getBaseType() and
operandTag instanceof SideEffectOperandTag
or
tag instanceof OnlyInstructionTag and
operandType = arg.getType().getUnspecifiedType() and
not operandType instanceof DerivedType and
operandTag instanceof SideEffectOperandTag
|
// If the type we select is an incomplete type (e.g. a forward-declared `struct`), there will
// not be a `CppType` that represents that type. In that case, fall back to `UnknownCppType`.
result = getTypeForPRValueOrUnknown(operandType)
)
}
predicate hasSpecificWriteSideEffect(Opcode op) {

View File

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

View File

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

View File

@@ -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
@@ -11,11 +12,6 @@ private import TranslatedStmt
private import IRConstruction
private import semmle.code.cpp.models.interfaces.SideEffect
/**
* 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
@@ -53,6 +49,9 @@ private predicate ignoreExprAndDescendants(Expr expr) {
// constant value.
isIRConstant(getRealParent(expr))
or
// Ignore descendants of `__assume` expressions, since we translated these to `NoOp`.
getRealParent(expr) instanceof AssumeExpr
or
// The `DestructorCall` node for a `DestructorFieldDestruction` has a `FieldAccess`
// node as its qualifier, but that `FieldAccess` does not have a child of its own.
// We'll ignore that `FieldAccess`, and supply the receiver as part of the calling
@@ -66,8 +65,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
@@ -532,9 +531,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.
@@ -574,7 +571,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
@@ -619,6 +616,8 @@ abstract class TranslatedElement extends TTranslatedElement {
*/
int getInstructionResultSize(InstructionTag tag) { none() }
predicate needsUnknownOpaqueType(int byteSize) { none() }
/**
* If the instruction specified by `tag` is a `StringConstantInstruction`,
* gets the `StringLiteral` for that instruction.
@@ -634,7 +633,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`,
@@ -653,7 +652,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`.

View File

@@ -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,22 @@ 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 +105,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 +115,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 +201,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 +251,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 +310,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 +325,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 +337,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 +348,34 @@ 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
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
) {
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()
)
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
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 +436,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 +445,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 +526,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 +545,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 +568,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()
}
@@ -640,13 +619,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 +683,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 +706,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 +733,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 +778,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 +827,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 +904,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 +952,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 +1010,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 +1148,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 +1233,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 +1313,16 @@ 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 +1351,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 +1381,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 +1463,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 +1499,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 +1572,7 @@ 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() }
@@ -1688,13 +1627,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) {
@@ -1741,9 +1677,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
(
(
@@ -1754,8 +1688,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()
@@ -1763,13 +1700,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()
)
}
@@ -1837,7 +1772,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()
@@ -1897,7 +1832,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.
@@ -1905,14 +1840,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 }
}
/**
@@ -1921,13 +1856,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) {
@@ -1954,15 +1886,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) {
@@ -1983,9 +1912,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) {
@@ -1999,10 +1928,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() {
@@ -2017,7 +1946,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() }
}
/**
@@ -2075,13 +2004,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) {
@@ -2148,13 +2074,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() {
@@ -2315,9 +2238,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()
}
@@ -2366,23 +2287,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) {
@@ -2408,16 +2324,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()) }
@@ -2448,13 +2364,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()) }
@@ -2489,3 +2402,26 @@ class TranslatedErrorExpr extends TranslatedSingleInstructionExpr {
final override Opcode getOpcode() { result instanceof Opcode::Error }
}
/**
* The IR translation of an `__assume` expression. We currently translate these as `NoOp`. In the
* future, we will probably want to do something better. At a minimum, we can model `__assume(0)` as
* `Unreached`.
*/
class TranslatedAssumeExpr extends TranslatedSingleInstructionExpr {
override AssumeExpr expr;
final override Opcode getOpcode() { result instanceof Opcode::NoOp }
final override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
final override TranslatedElement getChild(int id) { none() }
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
result = getParent().getChildSuccessor(this) and
kind instanceof GotoEdge
}
final override Instruction getChildSuccessor(TranslatedElement child) { none() }
}

View File

@@ -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,11 @@ 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 +266,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 +282,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 +330,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 +395,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 +458,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()
}

View File

@@ -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 = getUnknownOpaqueType(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 = getUnknownOpaqueType(elementCount * getElementType().getSize())
)
)
}
@@ -326,6 +314,13 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
)
}
override predicate needsUnknownOpaqueType(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 needsUnknownOpaqueType(int byteSize) {
elementCount != 0 and byteSize = elementCount * getElementType().getSize()
}
private InstructionTag getElementDefaultValueTag() {
result = InitializerElementDefaultValueTag()
}
@@ -734,8 +716,10 @@ 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 = getUnknownOpaqueType(elementCount * getElementType().getSize())
}
}
@@ -766,13 +750,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 +803,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()
}

View File

@@ -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,7 @@ 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 +179,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 +206,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 +248,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 +313,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 +342,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 +358,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 +413,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 +441,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 +570,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 +620,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 +661,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 +692,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 +716,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() }
}

View File

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

View File

@@ -1,2 +1,3 @@
private import IR
import InstructionSanity
import IRTypeSanity

View File

@@ -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,17 @@ 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 +70,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 +82,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 +121,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 }

View File

@@ -5,6 +5,7 @@ import IRVariable
import Operand
private import internal.InstructionImports as Imports
import Imports::EdgeKind
import Imports::IRType
import Imports::MemoryAccessKind
import Imports::Opcode
private import Imports::OperandTag
@@ -113,10 +114,12 @@ 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) + "'."
)
}
@@ -321,7 +324,7 @@ class Instruction extends Construction::TInstruction {
}
private string getResultPrefix() {
if getResultType() instanceof Language::VoidType
if getResultIRType() instanceof IRVoidType
then result = "v"
else
if hasMemoryResult()
@@ -353,23 +356,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
@@ -389,7 +375,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
@@ -457,6 +445,16 @@ 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 `IRVoidType`.
*/
final IRType getResultIRType() { result = getResultLanguageType().getIRType() }
/**
* Gets the type of the result produced by this instruction. If the
* instruction does not produce a result, its result type will be `VoidType`.
@@ -464,7 +462,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 |
resultType = getResultLanguageType() and
(
resultType.hasUnspecifiedType(result, _)
or
not resultType.hasUnspecifiedType(_, _) and result instanceof Language::UnknownType
)
)
}
/**
* Holds if the result produced by this instruction is a glvalue. If this
@@ -484,7 +491,7 @@ 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
@@ -493,16 +500,7 @@ class Instruction extends Construction::TInstruction {
* If `this.isGLValue()` holds for this instruction, the value of
* `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())
}
final int getResultSize() { result = Construction::getInstructionResultType(this).getByteSize() }
/**
* Gets the opcode that specifies the operation performed by this instruction.
@@ -1384,7 +1382,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
@@ -1396,7 +1394,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 }
}
/**

View File

@@ -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)
}
}
@@ -381,12 +395,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

View File

@@ -1,5 +1,5 @@
private import internal.ValueNumberingInternal
private import cpp
private import internal.ValueNumberingImports
private import IR
/**
@@ -23,31 +23,32 @@ newtype TValueNumber =
initializeParameterValueNumber(_, irFunc, var)
} or
TInitializeThisValueNumber(IRFunction irFunc) { initializeThisValueNumber(_, irFunc) } or
TConstantValueNumber(IRFunction irFunc, Type type, string value) {
TConstantValueNumber(IRFunction irFunc, IRType type, string value) {
constantValueNumber(_, irFunc, type, value)
} or
TStringConstantValueNumber(IRFunction irFunc, Type type, string value) {
TStringConstantValueNumber(IRFunction irFunc, IRType type, string value) {
stringConstantValueNumber(_, irFunc, type, value)
} or
TFieldAddressValueNumber(IRFunction irFunc, Field field, ValueNumber objectAddress) {
TFieldAddressValueNumber(IRFunction irFunc, Language::Field field, ValueNumber objectAddress) {
fieldAddressValueNumber(_, irFunc, field, objectAddress)
} or
TBinaryValueNumber(
IRFunction irFunc, Opcode opcode, Type type, ValueNumber leftOperand, ValueNumber rightOperand
IRFunction irFunc, Opcode opcode, IRType type, ValueNumber leftOperand, ValueNumber rightOperand
) {
binaryValueNumber(_, irFunc, opcode, type, leftOperand, rightOperand)
} or
TPointerArithmeticValueNumber(
IRFunction irFunc, Opcode opcode, Type type, int elementSize, ValueNumber leftOperand,
IRFunction irFunc, Opcode opcode, IRType type, int elementSize, ValueNumber leftOperand,
ValueNumber rightOperand
) {
pointerArithmeticValueNumber(_, irFunc, opcode, type, elementSize, leftOperand, rightOperand)
} or
TUnaryValueNumber(IRFunction irFunc, Opcode opcode, Type type, ValueNumber operand) {
TUnaryValueNumber(IRFunction irFunc, Opcode opcode, IRType type, ValueNumber operand) {
unaryValueNumber(_, irFunc, opcode, type, operand)
} or
TInheritanceConversionValueNumber(
IRFunction irFunc, Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand
IRFunction irFunc, Opcode opcode, Language::Class baseClass, Language::Class derivedClass,
ValueNumber operand
) {
inheritanceConversionValueNumber(_, irFunc, opcode, baseClass, derivedClass, operand)
} or
@@ -59,7 +60,7 @@ newtype TValueNumber =
class ValueNumber extends TValueNumber {
final string toString() { result = getExampleInstruction().getResultId() }
final Location getLocation() { result = getExampleInstruction().getLocation() }
final Language::Location getLocation() { result = getExampleInstruction().getLocation() }
/**
* Gets the instructions that have been assigned this value number. This will always produce at
@@ -150,23 +151,23 @@ private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRF
}
private predicate constantValueNumber(
ConstantInstruction instr, IRFunction irFunc, Type type, string value
ConstantInstruction instr, IRFunction irFunc, IRType type, string value
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getResultType() = type and
instr.getResultIRType() = type and
instr.getValue() = value
}
private predicate stringConstantValueNumber(
StringConstantInstruction instr, IRFunction irFunc, Type type, string value
StringConstantInstruction instr, IRFunction irFunc, IRType type, string value
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getResultType() = type and
instr.getResultIRType() = type and
instr.getValue().getValue() = value
}
private predicate fieldAddressValueNumber(
FieldAddressInstruction instr, IRFunction irFunc, Field field, ValueNumber objectAddress
FieldAddressInstruction instr, IRFunction irFunc, Language::Field field, ValueNumber objectAddress
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getField() = field and
@@ -174,43 +175,43 @@ private predicate fieldAddressValueNumber(
}
private predicate binaryValueNumber(
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, Type type, ValueNumber leftOperand,
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, IRType type, ValueNumber leftOperand,
ValueNumber rightOperand
) {
instr.getEnclosingIRFunction() = irFunc and
not instr instanceof PointerArithmeticInstruction and
instr.getOpcode() = opcode and
instr.getResultType() = type and
instr.getResultIRType() = type and
valueNumber(instr.getLeft()) = leftOperand and
valueNumber(instr.getRight()) = rightOperand
}
private predicate pointerArithmeticValueNumber(
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, Type type, int elementSize,
ValueNumber leftOperand, ValueNumber rightOperand
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, IRType type,
int elementSize, ValueNumber leftOperand, ValueNumber rightOperand
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getOpcode() = opcode and
instr.getResultType() = type and
instr.getResultIRType() = type and
instr.getElementSize() = elementSize and
valueNumber(instr.getLeft()) = leftOperand and
valueNumber(instr.getRight()) = rightOperand
}
private predicate unaryValueNumber(
UnaryInstruction instr, IRFunction irFunc, Opcode opcode, Type type, ValueNumber operand
UnaryInstruction instr, IRFunction irFunc, Opcode opcode, IRType type, ValueNumber operand
) {
instr.getEnclosingIRFunction() = irFunc and
not instr instanceof InheritanceConversionInstruction and
not instr instanceof CopyInstruction and
instr.getOpcode() = opcode and
instr.getResultType() = type and
instr.getResultIRType() = type and
valueNumber(instr.getUnary()) = operand
}
private predicate inheritanceConversionValueNumber(
InheritanceConversionInstruction instr, IRFunction irFunc, Opcode opcode, Class baseClass,
Class derivedClass, ValueNumber operand
InheritanceConversionInstruction instr, IRFunction irFunc, Opcode opcode,
Language::Class baseClass, Language::Class derivedClass, ValueNumber operand
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getOpcode() = opcode and
@@ -225,7 +226,7 @@ private predicate inheritanceConversionValueNumber(
*/
private predicate uniqueValueNumber(Instruction instr, IRFunction irFunc) {
instr.getEnclosingIRFunction() = irFunc and
not instr.getResultType() instanceof VoidType and
not instr.getResultIRType() instanceof IRVoidType and
not numberableInstruction(instr)
}
@@ -269,38 +270,41 @@ private ValueNumber nonUniqueValueNumber(Instruction instr) {
initializeThisValueNumber(instr, irFunc) and
result = TInitializeThisValueNumber(irFunc)
or
exists(Type type, string value |
exists(IRType type, string value |
constantValueNumber(instr, irFunc, type, value) and
result = TConstantValueNumber(irFunc, type, value)
)
or
exists(Type type, string value |
exists(IRType type, string value |
stringConstantValueNumber(instr, irFunc, type, value) and
result = TStringConstantValueNumber(irFunc, type, value)
)
or
exists(Field field, ValueNumber objectAddress |
exists(Language::Field field, ValueNumber objectAddress |
fieldAddressValueNumber(instr, irFunc, field, objectAddress) and
result = TFieldAddressValueNumber(irFunc, field, objectAddress)
)
or
exists(Opcode opcode, Type type, ValueNumber leftOperand, ValueNumber rightOperand |
exists(Opcode opcode, IRType type, ValueNumber leftOperand, ValueNumber rightOperand |
binaryValueNumber(instr, irFunc, opcode, type, leftOperand, rightOperand) and
result = TBinaryValueNumber(irFunc, opcode, type, leftOperand, rightOperand)
)
or
exists(Opcode opcode, Type type, ValueNumber operand |
exists(Opcode opcode, IRType type, ValueNumber operand |
unaryValueNumber(instr, irFunc, opcode, type, operand) and
result = TUnaryValueNumber(irFunc, opcode, type, operand)
)
or
exists(Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand |
exists(
Opcode opcode, Language::Class baseClass, Language::Class derivedClass, ValueNumber operand
|
inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, operand) and
result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand)
)
or
exists(
Opcode opcode, Type type, int elementSize, ValueNumber leftOperand, ValueNumber rightOperand
Opcode opcode, IRType type, int elementSize, ValueNumber leftOperand,
ValueNumber rightOperand
|
pointerArithmeticValueNumber(instr, irFunc, opcode, type, elementSize, leftOperand,
rightOperand) and

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.internal.Overlap
import semmle.code.cpp.ir.internal.IRCppLanguage as Language

View File

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

View File

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

View File

@@ -1,4 +1,5 @@
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
import semmle.code.cpp.ir.implementation.Opcode as Opcode
import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag

View File

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

View File

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

View File

@@ -1,8 +1,5 @@
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
private import SSAConstructionImports
private import NewIR
private class OldBlock = Reachability::ReachableBlock;
@@ -18,7 +15,7 @@ private module Cached {
}
cached
predicate functionHasIR(Function func) {
predicate functionHasIR(Language::Function func) {
exists(OldIR::IRFunction irFunc | irFunc.getFunction() = func)
}
@@ -42,7 +39,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 +47,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 +134,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 +183,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 +240,7 @@ private module Cached {
}
cached
Locatable getInstructionAST(Instruction instruction) {
Language::AST getInstructionAST(Instruction instruction) {
exists(OldInstruction oldInstruction |
instruction = WrappedInstruction(oldInstruction)
or
@@ -270,29 +258,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,7 +322,7 @@ private module Cached {
}
cached
Field getInstructionField(Instruction instruction) {
Language::Field getInstructionField(Instruction instruction) {
result = getOldInstruction(instruction).(OldIR::FieldInstruction).getField()
}
@@ -348,7 +332,7 @@ private module Cached {
}
cached
Function getInstructionFunction(Instruction instruction) {
Language::Function getInstructionFunction(Instruction instruction) {
result = getOldInstruction(instruction).(OldIR::FunctionInstruction).getFunctionSymbol()
}
@@ -358,19 +342,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()
}
@@ -380,14 +364,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

View File

@@ -0,0 +1,3 @@
import semmle.code.cpp.ir.implementation.Opcode
import semmle.code.cpp.ir.implementation.internal.OperandTag
import semmle.code.cpp.ir.internal.Overlap

View File

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

View File

@@ -1,24 +1,20 @@
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.Overlap
private import SimpleSSAImports
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 +26,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 +55,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() }
}

View File

@@ -0,0 +1,5 @@
import semmle.code.cpp.ir.implementation.raw.IR
import semmle.code.cpp.ir.internal.IntegerConstant as Ints
import semmle.code.cpp.ir.implementation.internal.OperandTag
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
import semmle.code.cpp.ir.internal.Overlap

View File

@@ -0,0 +1,507 @@
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
private int getPointerSize() { result = max(any(NullPointerType t).getSize()) }
/**
* 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 = getPointerSize()
or
exists(PointerToMemberType ptmType |
ptmType = unspecifiedType and
(
if ptmType.getBaseType().getUnspecifiedType() instanceof RoutineType
then result = getPointerSize() * 2
else result = getPointerSize()
)
)
or
exists(ArrayType arrayType |
// Treat `T[]` as `T*`.
arrayType = unspecifiedType and
not arrayType.hasArraySize() and
result = getPointerSize()
)
)
)
}
private int getTypeSize(Type type) {
if exists(getTypeSizeWorkaround(type))
then result = getTypeSizeWorkaround(type)
else result = type.getSize()
}
/**
* Holds if an `IRErrorType` should exist.
*/
predicate hasErrorType() { exists(ErroneousType t) }
/**
* 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 |
// If the enum has an explicit underlying type, we'll determine signedness from that. If not,
// we'll assume unsigned. The actual rules for the implicit underlying type of an enum vary
// between compilers, so we'll need an extractor change to get this 100% right. Until then,
// unsigned is a reasonable default.
enumType = type.getUnspecifiedType() and
enumType.getExplicitUnderlyingType().getUnspecifiedType().(IntegralType).isSigned()
)
}
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
or
// Treat `T[]` as a pointer. The only place we should see these is as the type of a parameter. If
// the corresponding decayed `T*` type is available, we'll use that, but if it's not available,
// we're stuck with `T[]`. Just treat it as a pointer.
type instanceof ArrayType and not exists(type.getSize())
}
/**
* 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 = getPointerSize() or // Covers function lvalues
byteSize = getTypeSize(any(FunctionPointerIshType type))
}
private predicate isOpaqueType(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 `IROpaqueType` with the specified `tag` and `byteSize` should exist.
*/
predicate hasOpaqueType(Type tag, int byteSize) {
isOpaqueType(tag) and byteSize = getTypeSize(tag)
or
tag instanceof UnknownType and IRConstruction::needsUnknownOpaqueType(byteSize)
}
/**
* Gets the `IRType` that represents a prvalue of the specified `Type`.
*/
private IRType getIRTypeForPRValue(Type type) {
exists(Type unspecifiedType | unspecifiedType = type.getUnspecifiedType() |
isOpaqueType(unspecifiedType) and
exists(IROpaqueType opaqueType | opaqueType = result |
opaqueType.getByteSize() = getTypeSize(type) and
opaqueType.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() = getTypeSize(type)
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) or
TUnknownOpaqueType(int byteSize) { IRConstruction::needsUnknownOpaqueType(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() { none() }
/** 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`.
*/
IRType getIRType() { none() }
/**
* 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`).
*/
predicate hasType(Type type, boolean isGLValue) { none() }
final predicate hasUnspecifiedType(Type type, boolean isGLValue) {
exists(Type specifiedType |
hasType(specifiedType, isGLValue) and
type = specifiedType.getUnspecifiedType()
)
}
}
/**
* 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)
}
}
/**
* A `CppType` that represents a prvalue of an existing `Type`.
*/
private class CppPRValueType extends CppWrappedType, TPRValueType {
final override string toString() { result = ctype.toString() }
final override string getDumpString() { result = ctype.getUnspecifiedType().toString() }
final override IRType getIRType() { result = getIRTypeForPRValue(ctype) }
final override 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 CppUnknownOpaqueType extends CppType, TUnknownOpaqueType {
int byteSize;
CppUnknownOpaqueType() { this = TUnknownOpaqueType(byteSize) }
final override string toString() { result = "unknown[" + byteSize.toString() + "]" }
final override IROpaqueType getIRType() {
result.getByteSize() = byteSize and result.getTag() instanceof UnknownType
}
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 {
final override string toString() { result = "glval<" + ctype.toString() + ">" }
final override string getDumpString() {
result = "glval<" + ctype.getUnspecifiedType().toString() + ">"
}
final override IRAddressType getIRType() { result.getByteSize() = getPointerSize() }
final override predicate hasType(Type type, boolean isGLValue) {
type = ctype and
isGLValue = true
}
}
/**
* A `CppType` that represents a function lvalue.
*/
private class CppFunctionGLValueType extends CppType, TFunctionGLValueType {
final override string toString() { result = "glval<unknown>" }
final override IRFunctionAddressType getIRType() { result.getByteSize() = getPointerSize() }
final override 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 {
final override string toString() { result = any(UnknownType type).toString() }
final override IRUnknownType getIRType() { any() }
final override 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 prvalue of type `type`, if such a `CppType` exists.
* Otherwise, gets `CppUnknownType`.
*/
CppType getTypeForPRValueOrUnknown(Type type) {
result = getTypeForPRValue(type)
or
not exists(getTypeForPRValue(type)) and result = getUnknownType()
}
/**
* 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 opaque of unknown type with size `byteSize`.
*/
CppUnknownOpaqueType getUnknownOpaqueType(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 `IROpaqueType` with the specified `tag` and
* `byteSize`.
*/
CppType getCanonicalOpaqueType(Type tag, int byteSize) {
isOpaqueType(tag) and
result = TPRValueType(tag.getUnspecifiedType()) and
getTypeSize(tag) = byteSize
or
tag instanceof UnknownType and result = getUnknownOpaqueType(byteSize)
}
/**
* Gets a string that uniquely identifies an `IROpaqueType` tag. This may be different from the usual
* `toString()` of the tag in order to ensure uniqueness.
*/
string getOpaqueTagIdentityString(Type tag) {
hasOpaqueType(tag, _) and
result = getTypeIdentityString(tag)
}
module LanguageTypeSanity {
query predicate missingCppType(Type type, string message) {
not exists(getTypeForPRValue(type)) and
exists(type.getSize()) and
// `ProxyClass`es have a size, but only appear in uninstantiated templates
not type instanceof ProxyClass and
message = "Type does not have an associated `CppType`."
}
}

View File

@@ -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 OpaqueTypeTag = Cpp::Type;
class Function = Cpp::Function;

View File

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

View File

@@ -14,3 +14,8 @@ containsLoopOfForwardEdges
lostReachability
backEdgeCountMismatch
useNotDominatedByDefinition
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType

View File

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

View File

@@ -2194,24 +2194,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)
@@ -2690,12 +2690,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] :
@@ -4637,7 +4637,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
@@ -4840,7 +4840,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
@@ -5240,28 +5240,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

View File

@@ -14,3 +14,8 @@ containsLoopOfForwardEdges
lostReachability
backEdgeCountMismatch
useNotDominatedByDefinition
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType

View File

@@ -14,3 +14,8 @@ containsLoopOfForwardEdges
lostReachability
backEdgeCountMismatch
useNotDominatedByDefinition
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType

View File

@@ -747,26 +747,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

View File

@@ -14,3 +14,8 @@ containsLoopOfForwardEdges
lostReachability
backEdgeCountMismatch
useNotDominatedByDefinition
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType

View File

@@ -714,22 +714,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

View File

@@ -14,3 +14,8 @@ containsLoopOfForwardEdges
lostReachability
backEdgeCountMismatch
useNotDominatedByDefinition
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType

View File

@@ -13,7 +13,6 @@ missingOperandType
sideEffectWithoutPrimary
instructionWithoutSuccessor
| VacuousDestructorCall.cpp:2:29:2:29 | InitializeParameter: y |
| assume0.cpp:7:2:7:2 | Chi: call to f |
| condition_decls.cpp:16:19:16:20 | Chi: call to BoxedInt |
| condition_decls.cpp:26:23:26:24 | Chi: call to BoxedInt |
| condition_decls.cpp:41:22:41:23 | Chi: call to BoxedInt |
@@ -546,3 +545,8 @@ lostReachability
| range_analysis.c:371:37:371:39 | Constant: 500 |
backEdgeCountMismatch
useNotDominatedByDefinition
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType

View File

@@ -8,6 +8,7 @@ missingOperand
| misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) |
| misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) |
| pointer_to_member.cpp:36:13:36:19 | FieldAddress: x1 | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
| pointer_to_member.cpp:36:22:36:28 | Store: f1 | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
| range_analysis.c:368:10:368:21 | Store: ... ? ... : ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | range_analysis.c:355:14:355:27 | IR: test_ternary01 | unsigned int test_ternary01(unsigned int) |
| range_analysis.c:369:10:369:36 | Store: ... ? ... : ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | range_analysis.c:355:14:355:27 | IR: test_ternary01 | unsigned int test_ternary01(unsigned int) |
| range_analysis.c:370:10:370:38 | Store: ... ? ... : ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | range_analysis.c:355:14:355:27 | IR: test_ternary01 | unsigned int test_ternary01(unsigned int) |
@@ -25,8 +26,6 @@ instructionWithoutSuccessor
| VacuousDestructorCall.cpp:2:29:2:29 | InitializeParameter: y |
| VacuousDestructorCall.cpp:3:3:3:3 | VariableAddress: x |
| VacuousDestructorCall.cpp:4:3:4:3 | Load: y |
| assume0.cpp:7:2:7:2 | CallSideEffect: call to f |
| assume0.cpp:9:11:9:11 | Constant: (bool)... |
| condition_decls.cpp:16:19:16:20 | CallSideEffect: call to BoxedInt |
| condition_decls.cpp:26:19:26:20 | IndirectMayWriteSideEffect: bi |
| condition_decls.cpp:26:23:26:24 | CallSideEffect: call to BoxedInt |
@@ -46,7 +45,6 @@ instructionWithoutSuccessor
| misc.c:219:47:219:48 | InitializeParameter: sp |
| misc.c:221:10:221:10 | Store: 1 |
| misc.c:222:10:222:10 | Store: 2 |
| ms_assume.cpp:20:12:20:12 | Constant: (bool)... |
| ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x |
| ms_try_except.cpp:7:13:7:17 | Store: ... = ... |
| ms_try_except.cpp:9:19:9:19 | Load: j |
@@ -68,6 +66,7 @@ instructionWithoutSuccessor
| ms_try_mix.cpp:51:5:51:11 | ThrowValue: throw ... |
| ms_try_mix.cpp:53:13:54:3 | NoOp: { ... } |
| pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} |
| pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} |
| static_init_templates.cpp:80:27:80:36 | Convert: (void *)... |
| static_init_templates.cpp:80:27:80:36 | Convert: (void *)... |
| static_init_templates.cpp:89:27:89:36 | Convert: (void *)... |
@@ -612,7 +611,6 @@ lostReachability
backEdgeCountMismatch
useNotDominatedByDefinition
| VacuousDestructorCall.cpp:4:3:4:3 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | IR: CallDestructor | void CallDestructor<int>(int, int*) |
| assume0.cpp:11:2:11:2 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | assume0.cpp:5:6:5:6 | IR: h | void h() |
| condition_decls.cpp:16:15:16:15 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | condition_decls.cpp:15:6:15:17 | IR: if_decl_bind | void if_decl_bind(int) |
| condition_decls.cpp:16:15:16:16 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | condition_decls.cpp:15:6:15:17 | IR: if_decl_bind | void if_decl_bind(int) |
| condition_decls.cpp:16:15:16:16 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | condition_decls.cpp:15:6:15:17 | IR: if_decl_bind | void if_decl_bind(int) |
@@ -681,6 +679,7 @@ useNotDominatedByDefinition
| ms_try_mix.cpp:51:5:51:11 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | ms_try_mix.cpp:47:6:47:28 | IR: ms_empty_finally_at_end | void ms_empty_finally_at_end() |
| pointer_to_member.cpp:36:11:36:30 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
| pointer_to_member.cpp:36:13:36:19 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
| pointer_to_member.cpp:36:22:36:28 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
| stmt_expr.cpp:30:20:30:21 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | stmt_expr.cpp:21:6:21:6 | IR: g | void stmtexpr::g(int) |
| stmt_expr.cpp:31:16:31:18 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | stmt_expr.cpp:21:6:21:6 | IR: g | void stmtexpr::g(int) |
| try_catch.cpp:21:13:21:24 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | try_catch.cpp:19:6:19:23 | IR: throw_from_nonstmt | void throw_from_nonstmt(int) |
@@ -694,3 +693,8 @@ 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
missingIRType
multipleIRTypes
missingCppType

View File

@@ -22,7 +22,6 @@ missingOperandType
sideEffectWithoutPrimary
instructionWithoutSuccessor
| VacuousDestructorCall.cpp:2:29:2:29 | InitializeParameter: y |
| assume0.cpp:7:2:7:2 | CallSideEffect: call to f |
| condition_decls.cpp:16:19:16:20 | CallSideEffect: call to BoxedInt |
| condition_decls.cpp:26:23:26:24 | CallSideEffect: call to BoxedInt |
| condition_decls.cpp:41:22:41:23 | CallSideEffect: call to BoxedInt |
@@ -555,3 +554,8 @@ lostReachability
| range_analysis.c:371:37:371:39 | Constant: 500 |
backEdgeCountMismatch
useNotDominatedByDefinition
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType

View File

@@ -394,27 +394,27 @@ test.cpp:
#-----| Goto -> Block 3
# 56| Block 3
# 56| m3_0(char *) = Phi : from 2:m2_3, from 5:m5_4
# 56| m3_0(decltype(nullptr)) = Phi : from 2:m2_3, from 5:m5_4
# 56| valnum = m3_0
# 56| r3_1(glval<char *>) = VariableAddress[ptr] :
# 56| r3_1(glval<char *>) = VariableAddress[ptr] :
# 56| valnum = r0_7
# 56| r3_2(char *) = Load : &:r3_1, m3_0
# 56| r3_2(char *) = Load : &:r3_1, m3_0
# 56| valnum = m3_0
# 56| r3_3(char) = Load : &:r3_2, ~m0_1
# 56| r3_3(char) = Load : &:r3_2, ~m0_1
# 56| valnum = unique
# 56| r3_4(int) = Convert : r3_3
# 56| r3_4(int) = Convert : r3_3
# 56| valnum = unique
# 56| r3_5(glval<char *>) = VariableAddress[str] :
# 56| r3_5(glval<char *>) = VariableAddress[str] :
# 56| valnum = r0_3
# 56| r3_6(char *) = Load : &:r3_5, m0_4
# 56| r3_6(char *) = Load : &:r3_5, m0_4
# 56| valnum = m0_4
# 56| r3_7(char) = Load : &:r3_6, ~m0_1
# 56| r3_7(char) = Load : &:r3_6, ~m0_1
# 56| valnum = unique
# 56| r3_8(int) = Convert : r3_7
# 56| r3_8(int) = Convert : r3_7
# 56| valnum = unique
# 56| r3_9(bool) = CompareNE : r3_4, r3_8
# 56| r3_9(bool) = CompareNE : r3_4, r3_8
# 56| valnum = unique
# 56| v3_10(void) = ConditionalBranch : r3_9
# 56| v3_10(void) = ConditionalBranch : r3_9
#-----| False -> Block 6
#-----| True -> Block 4

View File

@@ -1,18 +1,18 @@
| ..()(..) | RoutineType | | | | |
| ..(*)(..) | FunctionPointerType | | ..()(..) | | |
| _Complex __float128 | ArithmeticType | | | | |
| _Complex __float128 | FloatingPointType | | | | |
| _Complex double | FloatingPointType | | | | |
| _Complex float | FloatingPointType | | | | |
| _Complex long double | FloatingPointType | | | | |
| _Decimal32 | ArithmeticType | | | | |
| _Decimal64 | ArithmeticType | | | | |
| _Decimal128 | ArithmeticType | | | | |
| _Float32 | ArithmeticType | | | | |
| _Float32x | ArithmeticType | | | | |
| _Float64 | ArithmeticType | | | | |
| _Float64x | ArithmeticType | | | | |
| _Float128 | ArithmeticType | | | | |
| _Float128x | ArithmeticType | | | | |
| _Decimal32 | Decimal32Type | | | | |
| _Decimal64 | Decimal64Type | | | | |
| _Decimal128 | Decimal128Type | | | | |
| _Float32 | FloatingPointType | | | | |
| _Float32x | FloatingPointType | | | | |
| _Float64 | FloatingPointType | | | | |
| _Float64x | FloatingPointType | | | | |
| _Float128 | FloatingPointType | | | | |
| _Float128x | FloatingPointType | | | | |
| _Imaginary double | FloatingPointType | | | | |
| _Imaginary float | FloatingPointType | | | | |
| _Imaginary long double | FloatingPointType | | | | |