Merge branch 'master' into master

This commit is contained in:
Raul Garcia
2018-09-20 16:30:48 -07:00
committed by GitHub
85 changed files with 4546 additions and 164 deletions

View File

@@ -29,7 +29,7 @@ from BufferAccess ba, string bufferDesc, int accessSize, int accessType,
where accessSize = ba.getSize()
and bufferSize = getBufferSize(ba.getBuffer(bufferDesc, accessType),
bufferAlloc)
and accessSize > bufferSize
and (accessSize > bufferSize or (accessSize <= 0 and accessType = 3))
and if accessType = 1 then (
message = "This '" + ba.getName() + "' operation accesses "
+ plural(accessSize, " byte", " bytes")
@@ -41,8 +41,13 @@ where accessSize = ba.getSize()
+ " but the $@ is only "
+ plural(bufferSize, " byte", " bytes") + "."
) else (
message = "This array indexing operation accesses byte offset "
+ (accessSize - 1) + " but the $@ is only "
+ plural(bufferSize, " byte", " bytes") + "."
if accessSize > 0 then (
message = "This array indexing operation accesses byte offset "
+ (accessSize - 1) + " but the $@ is only "
+ plural(bufferSize, " byte", " bytes") + "."
) else (
message = "This array indexing operation accesses a negative index "
+ ((accessSize/ba.getActualType().getSize()) - 1) + " on the $@."
)
)
select ba, message, bufferAlloc, bufferDesc

View File

@@ -14,6 +14,7 @@ import semmle.code.cpp.dataflow.DataFlow2
import semmle.code.cpp.dataflow.DataFlow3
import semmle.code.cpp.dataflow.DataFlow4
import semmle.code.cpp.dataflow.TaintTracking
import semmle.code.cpp.valuenumbering.HashCons
from File f, string tag
where none()

View File

@@ -0,0 +1 @@
import implementation.aliased_ssa.PrintIR

View File

@@ -0,0 +1 @@
import implementation.aliased_ssa.gvn.ValueNumbering

View File

@@ -5,3 +5,30 @@ import IRVariable
import OperandTag
import semmle.code.cpp.ir.implementation.EdgeKind
import semmle.code.cpp.ir.implementation.MemoryAccessKind
private newtype TIRPropertyProvider = MkIRPropertyProvider()
/**
* Class that provides additional properties to be dumped for IR instructions and blocks when using
* the PrintIR module. Libraries that compute additional facts about IR elements can extend the
* single instance of this class to specify the additional properties computed by the library.
*/
class IRPropertyProvider extends TIRPropertyProvider {
string toString() {
result = "IRPropertyProvider"
}
/**
* Gets the value of the property named `key` for the specified instruction.
*/
string getInstructionProperty(Instruction instruction, string key) {
none()
}
/**
* Gets the value of the property named `key` for the specified block.
*/
string getBlockProperty(IRBlock block, string key) {
none()
}
}

View File

@@ -107,6 +107,14 @@ module InstructionSanity {
operand = op.getOperand(tag) and
operand.getFunctionIR() != op.getFunctionIR()
}
/**
* Holds if instruction `instr` is not in exactly one block.
*/
query predicate instructionWithoutUniqueBlock(Instruction instr, int blockCount) {
blockCount = count(instr.getBlock()) and
blockCount != 1
}
}
/**
@@ -301,6 +309,13 @@ class Instruction extends Construction::TInstruction {
result = ast.getLocation()
}
/**
* Gets the `Expr` whose results is computed by this instruction, if any.
*/
final Expr getResultExpression() {
result = Construction::getInstructionResultExpression(this)
}
/**
* Gets the type of the result produced by this instruction. If the
* instruction does not produce a result, its result type will be `VoidType`.
@@ -554,6 +569,15 @@ class InitializeParameterInstruction extends VariableInstruction {
}
}
/**
* An instruction that initializes the `this` pointer parameter of the enclosing function.
*/
class InitializeThisInstruction extends Instruction {
InitializeThisInstruction() {
opcode instanceof Opcode::InitializeThis
}
}
class FieldAddressInstruction extends FieldInstruction {
FieldAddressInstruction() {
opcode instanceof Opcode::FieldAddress

View File

@@ -1,6 +1,18 @@
private import IR
import cpp
private string getAdditionalInstructionProperty(Instruction instr, string key) {
exists(IRPropertyProvider provider |
result = provider.getInstructionProperty(instr, key)
)
}
private string getAdditionalBlockProperty(IRBlock block, string key) {
exists(IRPropertyProvider provider |
result = provider.getBlockProperty(block, key)
)
}
private newtype TPrintableIRNode =
TPrintableFunctionIR(FunctionIR funcIR) or
TPrintableIRBlock(IRBlock block) or
@@ -135,6 +147,11 @@ class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
result.getFunctionIR() = block.getFunctionIR()
}
override string getProperty(string key) {
result = PrintableIRNode.super.getProperty(key) or
result = getAdditionalBlockProperty(block, key)
}
final IRBlock getBlock() {
result = block
}
@@ -185,6 +202,11 @@ class PrintableInstruction extends PrintableIRNode, TPrintableInstruction {
final Instruction getInstruction() {
result = instr
}
override string getProperty(string key) {
result = PrintableIRNode.super.getProperty(key) or
result = getAdditionalInstructionProperty(instr, key)
}
}
private predicate columnWidths(IRBlock block, int resultWidth, int operationWidth) {

View File

@@ -0,0 +1,274 @@
private import internal.ValueNumberingInternal
import cpp
private import IR
/**
* Provides additional information about value numbering in IR dumps.
*/
class ValueNumberPropertyProvider extends IRPropertyProvider {
override string getInstructionProperty(Instruction instr, string key) {
exists(ValueNumber vn |
vn = valueNumber(instr) and
key = "valnum" and
if strictcount(vn.getAnInstruction()) > 1 then
result = vn.toString()
else
result = "unique"
)
}
}
newtype TValueNumber =
TVariableAddressValueNumber(FunctionIR funcIR, IRVariable var) {
variableAddressValueNumber(_, funcIR, var)
} or
TInitializeParameterValueNumber(FunctionIR funcIR, IRVariable var) {
initializeParameterValueNumber(_, funcIR, var)
} or
TInitializeThisValueNumber(FunctionIR funcIR) {
initializeThisValueNumber(_, funcIR)
} or
TConstantValueNumber(FunctionIR funcIR, Type type, string value) {
constantValueNumber(_, funcIR, type, value)
} or
TFieldAddressValueNumber(FunctionIR funcIR, Field field, ValueNumber objectAddress) {
fieldAddressValueNumber(_, funcIR, field, objectAddress)
} or
TBinaryValueNumber(FunctionIR funcIR, Opcode opcode, Type type, ValueNumber leftOperand,
ValueNumber rightOperand) {
binaryValueNumber(_, funcIR, opcode, type, leftOperand, rightOperand)
} or
TPointerArithmeticValueNumber(FunctionIR funcIR, Opcode opcode, Type type, int elementSize,
ValueNumber leftOperand, ValueNumber rightOperand) {
pointerArithmeticValueNumber(_, funcIR, opcode, type, elementSize, leftOperand, rightOperand)
} or
TUnaryValueNumber(FunctionIR funcIR, Opcode opcode, Type type, ValueNumber operand) {
unaryValueNumber(_, funcIR, opcode, type, operand)
} or
TInheritanceConversionValueNumber(FunctionIR funcIR, Opcode opcode, Class baseClass,
Class derivedClass, ValueNumber operand) {
inheritanceConversionValueNumber(_, funcIR, opcode, baseClass, derivedClass, operand)
} or
TUniqueValueNumber(FunctionIR funcIR, Instruction instr) {
uniqueValueNumber(instr, funcIR)
}
/**
* The value number assigned to a particular set of instructions that produce equivalent results.
*/
class ValueNumber extends TValueNumber {
final string toString() {
result = getExampleInstruction().getResultId()
}
final Location getLocation() {
result = getExampleInstruction().getLocation()
}
/**
* Gets the instructions that have been assigned this value number. This will always produce at
* least one result.
*/
final Instruction getAnInstruction() {
this = valueNumber(result)
}
/**
* Gets one of the instructions that was assigned this value number. The chosen instuction is
* deterministic but arbitrary. Intended for use only in debugging.
*/
final Instruction getExampleInstruction() {
result = min(Instruction instr |
instr = getAnInstruction() |
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
)
}
}
/**
* A `CopyInstruction` whose source operand's value is congruent to the definition of that source
* operand.
* For example:
* ```
* Point p = { 1, 2 };
* Point q = p;
* int a = p.x;
* ```
* The use of `p` on line 2 is linked to the definition of `p` on line 1, and is congruent to that
* definition because it accesses the exact same memory.
* The use of `p.x` on line 3 is linked to the definition of `p` on line 1 as well, but is not
* congruent to that definition because `p.x` accesses only a subset of the memory defined by `p`.
*
* This concept should probably be exposed in the public IR API.
*/
private class CongruentCopyInstruction extends CopyInstruction {
CongruentCopyInstruction() {
exists(Instruction def |
def = this.getSourceValue() and
(
def.getResultMemoryAccess() instanceof IndirectMemoryAccess or
not def.hasMemoryResult()
)
)
}
}
/**
* Holds if this library knows how to assign a value number to the specified instruction, other than
* a `unique` value number that is never shared by multiple instructions.
*/
private predicate numberableInstruction(Instruction instr) {
instr instanceof VariableAddressInstruction or
instr instanceof InitializeParameterInstruction or
instr instanceof InitializeThisInstruction or
instr instanceof ConstantInstruction or
instr instanceof FieldAddressInstruction or
instr instanceof BinaryInstruction or
instr instanceof UnaryInstruction or
instr instanceof PointerArithmeticInstruction or
instr instanceof CongruentCopyInstruction
}
private predicate variableAddressValueNumber(VariableAddressInstruction instr, FunctionIR funcIR,
IRVariable var) {
instr.getFunctionIR() = funcIR and
instr.getVariable() = var
}
private predicate initializeParameterValueNumber(InitializeParameterInstruction instr,
FunctionIR funcIR, IRVariable var) {
instr.getFunctionIR() = funcIR and
instr.getVariable() = var
}
private predicate initializeThisValueNumber(InitializeThisInstruction instr, FunctionIR funcIR) {
instr.getFunctionIR() = funcIR
}
private predicate constantValueNumber(ConstantInstruction instr, FunctionIR funcIR, Type type,
string value) {
instr.getFunctionIR() = funcIR and
instr.getResultType() = type and
instr.getValue() = value
}
private predicate fieldAddressValueNumber(FieldAddressInstruction instr, FunctionIR funcIR,
Field field, ValueNumber objectAddress) {
instr.getFunctionIR() = funcIR and
instr.getField() = field and
valueNumber(instr.getObjectAddress()) = objectAddress
}
private predicate binaryValueNumber(BinaryInstruction instr, FunctionIR funcIR, Opcode opcode,
Type type, ValueNumber leftOperand, ValueNumber rightOperand) {
instr.getFunctionIR() = funcIR and
(not instr instanceof PointerArithmeticInstruction) and
instr.getOpcode() = opcode and
instr.getResultType() = type and
valueNumber(instr.getLeftOperand()) = leftOperand and
valueNumber(instr.getRightOperand()) = rightOperand
}
private predicate pointerArithmeticValueNumber(PointerArithmeticInstruction instr,
FunctionIR funcIR, Opcode opcode, Type type, int elementSize, ValueNumber leftOperand,
ValueNumber rightOperand) {
instr.getFunctionIR() = funcIR and
instr.getOpcode() = opcode and
instr.getResultType() = type and
instr.getElementSize() = elementSize and
valueNumber(instr.getLeftOperand()) = leftOperand and
valueNumber(instr.getRightOperand()) = rightOperand
}
private predicate unaryValueNumber(UnaryInstruction instr, FunctionIR funcIR, Opcode opcode,
Type type, ValueNumber operand) {
instr.getFunctionIR() = funcIR and
(not instr instanceof InheritanceConversionInstruction) and
instr.getOpcode() = opcode and
instr.getResultType() = type and
valueNumber(instr.getOperand()) = operand
}
private predicate inheritanceConversionValueNumber(InheritanceConversionInstruction instr,
FunctionIR funcIR, Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand) {
instr.getFunctionIR() = funcIR and
instr.getOpcode() = opcode and
instr.getBaseClass() = baseClass and
instr.getDerivedClass() = derivedClass and
valueNumber(instr.getOperand()) = operand
}
/**
* Holds if `instr` should be assigned a unique value number because this library does not know how
* to determine if two instances of that instruction are equivalent.
*/
private predicate uniqueValueNumber(Instruction instr, FunctionIR funcIR) {
instr.getFunctionIR() = funcIR and
(not instr.getResultType() instanceof VoidType) and
not numberableInstruction(instr)
}
/**
* Gets the value number assigned to `instr`, if any. Returns at most one result.
*/
ValueNumber valueNumber(Instruction instr) {
result = nonUniqueValueNumber(instr) or
exists(FunctionIR funcIR |
uniqueValueNumber(instr, funcIR) and
result = TUniqueValueNumber(funcIR, instr)
)
}
/**
* Gets the value number assigned to `instr`, if any, unless that instruction is assigned a unique
* value number.
*/
private ValueNumber nonUniqueValueNumber(Instruction instr) {
exists(FunctionIR funcIR |
funcIR = instr.getFunctionIR() and
(
exists(IRVariable var |
variableAddressValueNumber(instr, funcIR, var) and
result = TVariableAddressValueNumber(funcIR, var)
) or
exists(IRVariable var |
initializeParameterValueNumber(instr, funcIR, var) and
result = TInitializeParameterValueNumber(funcIR, var)
) or
(
initializeThisValueNumber(instr, funcIR) and
result = TInitializeThisValueNumber(funcIR)
) or
exists(Type type, string value |
constantValueNumber(instr, funcIR, type, value) and
result = TConstantValueNumber(funcIR, type, value)
) or
exists(Field field, ValueNumber objectAddress |
fieldAddressValueNumber(instr, funcIR, field, objectAddress) and
result = TFieldAddressValueNumber(funcIR, field, objectAddress)
) or
exists(Opcode opcode, Type type, ValueNumber leftOperand, ValueNumber rightOperand |
binaryValueNumber(instr, funcIR, opcode, type, leftOperand, rightOperand) and
result = TBinaryValueNumber(funcIR, opcode, type, leftOperand, rightOperand)
) or
exists(Opcode opcode, Type type, ValueNumber operand |
unaryValueNumber(instr, funcIR, opcode, type, operand) and
result = TUnaryValueNumber(funcIR, opcode, type, operand)
) or
exists(Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand |
inheritanceConversionValueNumber(instr, funcIR, opcode, baseClass, derivedClass,
operand) and
result = TInheritanceConversionValueNumber(funcIR, opcode, baseClass, derivedClass, operand)
) or
exists(Opcode opcode, Type type, int elementSize, ValueNumber leftOperand,
ValueNumber rightOperand |
pointerArithmeticValueNumber(instr, funcIR, opcode, type, elementSize, leftOperand,
rightOperand) and
result = TPointerArithmeticValueNumber(funcIR, opcode, type, elementSize, leftOperand,
rightOperand)
) or
// The value number of a copy is just the value number of its source value.
result = valueNumber(instr.(CongruentCopyInstruction).getSourceValue())
)
)
}

View File

@@ -0,0 +1 @@
import semmle.code.cpp.ir.implementation.aliased_ssa.IR as IR

View File

@@ -30,7 +30,9 @@ cached private module Cached {
}
cached newtype TInstructionTag =
WrappedInstructionTag(OldIR::Instruction oldInstruction) or
WrappedInstructionTag(OldIR::Instruction oldInstruction) {
not oldInstruction instanceof OldIR::PhiInstruction
} or
PhiTag(Alias::VirtualVariable vvar, OldIR::IRBlock block) {
hasPhiNode(vvar, block)
}
@@ -195,6 +197,10 @@ cached private module Cached {
)
}
cached Expr getInstructionResultExpression(Instruction instruction) {
result = getOldInstruction(instruction).getResultExpression()
}
cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
result = getNewInstruction(getOldInstruction(instruction).getSuccessor(kind))
}

View File

@@ -5,3 +5,30 @@ import IRVariable
import OperandTag
import semmle.code.cpp.ir.implementation.EdgeKind
import semmle.code.cpp.ir.implementation.MemoryAccessKind
private newtype TIRPropertyProvider = MkIRPropertyProvider()
/**
* Class that provides additional properties to be dumped for IR instructions and blocks when using
* the PrintIR module. Libraries that compute additional facts about IR elements can extend the
* single instance of this class to specify the additional properties computed by the library.
*/
class IRPropertyProvider extends TIRPropertyProvider {
string toString() {
result = "IRPropertyProvider"
}
/**
* Gets the value of the property named `key` for the specified instruction.
*/
string getInstructionProperty(Instruction instruction, string key) {
none()
}
/**
* Gets the value of the property named `key` for the specified block.
*/
string getBlockProperty(IRBlock block, string key) {
none()
}
}

View File

@@ -107,6 +107,14 @@ module InstructionSanity {
operand = op.getOperand(tag) and
operand.getFunctionIR() != op.getFunctionIR()
}
/**
* Holds if instruction `instr` is not in exactly one block.
*/
query predicate instructionWithoutUniqueBlock(Instruction instr, int blockCount) {
blockCount = count(instr.getBlock()) and
blockCount != 1
}
}
/**
@@ -301,6 +309,13 @@ class Instruction extends Construction::TInstruction {
result = ast.getLocation()
}
/**
* Gets the `Expr` whose results is computed by this instruction, if any.
*/
final Expr getResultExpression() {
result = Construction::getInstructionResultExpression(this)
}
/**
* Gets the type of the result produced by this instruction. If the
* instruction does not produce a result, its result type will be `VoidType`.
@@ -554,6 +569,15 @@ class InitializeParameterInstruction extends VariableInstruction {
}
}
/**
* An instruction that initializes the `this` pointer parameter of the enclosing function.
*/
class InitializeThisInstruction extends Instruction {
InitializeThisInstruction() {
opcode instanceof Opcode::InitializeThis
}
}
class FieldAddressInstruction extends FieldInstruction {
FieldAddressInstruction() {
opcode instanceof Opcode::FieldAddress

View File

@@ -1,6 +1,18 @@
private import IR
import cpp
private string getAdditionalInstructionProperty(Instruction instr, string key) {
exists(IRPropertyProvider provider |
result = provider.getInstructionProperty(instr, key)
)
}
private string getAdditionalBlockProperty(IRBlock block, string key) {
exists(IRPropertyProvider provider |
result = provider.getBlockProperty(block, key)
)
}
private newtype TPrintableIRNode =
TPrintableFunctionIR(FunctionIR funcIR) or
TPrintableIRBlock(IRBlock block) or
@@ -135,6 +147,11 @@ class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
result.getFunctionIR() = block.getFunctionIR()
}
override string getProperty(string key) {
result = PrintableIRNode.super.getProperty(key) or
result = getAdditionalBlockProperty(block, key)
}
final IRBlock getBlock() {
result = block
}
@@ -185,6 +202,11 @@ class PrintableInstruction extends PrintableIRNode, TPrintableInstruction {
final Instruction getInstruction() {
result = instr
}
override string getProperty(string key) {
result = PrintableIRNode.super.getProperty(key) or
result = getAdditionalInstructionProperty(instr, key)
}
}
private predicate columnWidths(IRBlock block, int resultWidth, int operationWidth) {

View File

@@ -0,0 +1,274 @@
private import internal.ValueNumberingInternal
import cpp
private import IR
/**
* Provides additional information about value numbering in IR dumps.
*/
class ValueNumberPropertyProvider extends IRPropertyProvider {
override string getInstructionProperty(Instruction instr, string key) {
exists(ValueNumber vn |
vn = valueNumber(instr) and
key = "valnum" and
if strictcount(vn.getAnInstruction()) > 1 then
result = vn.toString()
else
result = "unique"
)
}
}
newtype TValueNumber =
TVariableAddressValueNumber(FunctionIR funcIR, IRVariable var) {
variableAddressValueNumber(_, funcIR, var)
} or
TInitializeParameterValueNumber(FunctionIR funcIR, IRVariable var) {
initializeParameterValueNumber(_, funcIR, var)
} or
TInitializeThisValueNumber(FunctionIR funcIR) {
initializeThisValueNumber(_, funcIR)
} or
TConstantValueNumber(FunctionIR funcIR, Type type, string value) {
constantValueNumber(_, funcIR, type, value)
} or
TFieldAddressValueNumber(FunctionIR funcIR, Field field, ValueNumber objectAddress) {
fieldAddressValueNumber(_, funcIR, field, objectAddress)
} or
TBinaryValueNumber(FunctionIR funcIR, Opcode opcode, Type type, ValueNumber leftOperand,
ValueNumber rightOperand) {
binaryValueNumber(_, funcIR, opcode, type, leftOperand, rightOperand)
} or
TPointerArithmeticValueNumber(FunctionIR funcIR, Opcode opcode, Type type, int elementSize,
ValueNumber leftOperand, ValueNumber rightOperand) {
pointerArithmeticValueNumber(_, funcIR, opcode, type, elementSize, leftOperand, rightOperand)
} or
TUnaryValueNumber(FunctionIR funcIR, Opcode opcode, Type type, ValueNumber operand) {
unaryValueNumber(_, funcIR, opcode, type, operand)
} or
TInheritanceConversionValueNumber(FunctionIR funcIR, Opcode opcode, Class baseClass,
Class derivedClass, ValueNumber operand) {
inheritanceConversionValueNumber(_, funcIR, opcode, baseClass, derivedClass, operand)
} or
TUniqueValueNumber(FunctionIR funcIR, Instruction instr) {
uniqueValueNumber(instr, funcIR)
}
/**
* The value number assigned to a particular set of instructions that produce equivalent results.
*/
class ValueNumber extends TValueNumber {
final string toString() {
result = getExampleInstruction().getResultId()
}
final Location getLocation() {
result = getExampleInstruction().getLocation()
}
/**
* Gets the instructions that have been assigned this value number. This will always produce at
* least one result.
*/
final Instruction getAnInstruction() {
this = valueNumber(result)
}
/**
* Gets one of the instructions that was assigned this value number. The chosen instuction is
* deterministic but arbitrary. Intended for use only in debugging.
*/
final Instruction getExampleInstruction() {
result = min(Instruction instr |
instr = getAnInstruction() |
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
)
}
}
/**
* A `CopyInstruction` whose source operand's value is congruent to the definition of that source
* operand.
* For example:
* ```
* Point p = { 1, 2 };
* Point q = p;
* int a = p.x;
* ```
* The use of `p` on line 2 is linked to the definition of `p` on line 1, and is congruent to that
* definition because it accesses the exact same memory.
* The use of `p.x` on line 3 is linked to the definition of `p` on line 1 as well, but is not
* congruent to that definition because `p.x` accesses only a subset of the memory defined by `p`.
*
* This concept should probably be exposed in the public IR API.
*/
private class CongruentCopyInstruction extends CopyInstruction {
CongruentCopyInstruction() {
exists(Instruction def |
def = this.getSourceValue() and
(
def.getResultMemoryAccess() instanceof IndirectMemoryAccess or
not def.hasMemoryResult()
)
)
}
}
/**
* Holds if this library knows how to assign a value number to the specified instruction, other than
* a `unique` value number that is never shared by multiple instructions.
*/
private predicate numberableInstruction(Instruction instr) {
instr instanceof VariableAddressInstruction or
instr instanceof InitializeParameterInstruction or
instr instanceof InitializeThisInstruction or
instr instanceof ConstantInstruction or
instr instanceof FieldAddressInstruction or
instr instanceof BinaryInstruction or
instr instanceof UnaryInstruction or
instr instanceof PointerArithmeticInstruction or
instr instanceof CongruentCopyInstruction
}
private predicate variableAddressValueNumber(VariableAddressInstruction instr, FunctionIR funcIR,
IRVariable var) {
instr.getFunctionIR() = funcIR and
instr.getVariable() = var
}
private predicate initializeParameterValueNumber(InitializeParameterInstruction instr,
FunctionIR funcIR, IRVariable var) {
instr.getFunctionIR() = funcIR and
instr.getVariable() = var
}
private predicate initializeThisValueNumber(InitializeThisInstruction instr, FunctionIR funcIR) {
instr.getFunctionIR() = funcIR
}
private predicate constantValueNumber(ConstantInstruction instr, FunctionIR funcIR, Type type,
string value) {
instr.getFunctionIR() = funcIR and
instr.getResultType() = type and
instr.getValue() = value
}
private predicate fieldAddressValueNumber(FieldAddressInstruction instr, FunctionIR funcIR,
Field field, ValueNumber objectAddress) {
instr.getFunctionIR() = funcIR and
instr.getField() = field and
valueNumber(instr.getObjectAddress()) = objectAddress
}
private predicate binaryValueNumber(BinaryInstruction instr, FunctionIR funcIR, Opcode opcode,
Type type, ValueNumber leftOperand, ValueNumber rightOperand) {
instr.getFunctionIR() = funcIR and
(not instr instanceof PointerArithmeticInstruction) and
instr.getOpcode() = opcode and
instr.getResultType() = type and
valueNumber(instr.getLeftOperand()) = leftOperand and
valueNumber(instr.getRightOperand()) = rightOperand
}
private predicate pointerArithmeticValueNumber(PointerArithmeticInstruction instr,
FunctionIR funcIR, Opcode opcode, Type type, int elementSize, ValueNumber leftOperand,
ValueNumber rightOperand) {
instr.getFunctionIR() = funcIR and
instr.getOpcode() = opcode and
instr.getResultType() = type and
instr.getElementSize() = elementSize and
valueNumber(instr.getLeftOperand()) = leftOperand and
valueNumber(instr.getRightOperand()) = rightOperand
}
private predicate unaryValueNumber(UnaryInstruction instr, FunctionIR funcIR, Opcode opcode,
Type type, ValueNumber operand) {
instr.getFunctionIR() = funcIR and
(not instr instanceof InheritanceConversionInstruction) and
instr.getOpcode() = opcode and
instr.getResultType() = type and
valueNumber(instr.getOperand()) = operand
}
private predicate inheritanceConversionValueNumber(InheritanceConversionInstruction instr,
FunctionIR funcIR, Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand) {
instr.getFunctionIR() = funcIR and
instr.getOpcode() = opcode and
instr.getBaseClass() = baseClass and
instr.getDerivedClass() = derivedClass and
valueNumber(instr.getOperand()) = operand
}
/**
* Holds if `instr` should be assigned a unique value number because this library does not know how
* to determine if two instances of that instruction are equivalent.
*/
private predicate uniqueValueNumber(Instruction instr, FunctionIR funcIR) {
instr.getFunctionIR() = funcIR and
(not instr.getResultType() instanceof VoidType) and
not numberableInstruction(instr)
}
/**
* Gets the value number assigned to `instr`, if any. Returns at most one result.
*/
ValueNumber valueNumber(Instruction instr) {
result = nonUniqueValueNumber(instr) or
exists(FunctionIR funcIR |
uniqueValueNumber(instr, funcIR) and
result = TUniqueValueNumber(funcIR, instr)
)
}
/**
* Gets the value number assigned to `instr`, if any, unless that instruction is assigned a unique
* value number.
*/
private ValueNumber nonUniqueValueNumber(Instruction instr) {
exists(FunctionIR funcIR |
funcIR = instr.getFunctionIR() and
(
exists(IRVariable var |
variableAddressValueNumber(instr, funcIR, var) and
result = TVariableAddressValueNumber(funcIR, var)
) or
exists(IRVariable var |
initializeParameterValueNumber(instr, funcIR, var) and
result = TInitializeParameterValueNumber(funcIR, var)
) or
(
initializeThisValueNumber(instr, funcIR) and
result = TInitializeThisValueNumber(funcIR)
) or
exists(Type type, string value |
constantValueNumber(instr, funcIR, type, value) and
result = TConstantValueNumber(funcIR, type, value)
) or
exists(Field field, ValueNumber objectAddress |
fieldAddressValueNumber(instr, funcIR, field, objectAddress) and
result = TFieldAddressValueNumber(funcIR, field, objectAddress)
) or
exists(Opcode opcode, Type type, ValueNumber leftOperand, ValueNumber rightOperand |
binaryValueNumber(instr, funcIR, opcode, type, leftOperand, rightOperand) and
result = TBinaryValueNumber(funcIR, opcode, type, leftOperand, rightOperand)
) or
exists(Opcode opcode, Type type, ValueNumber operand |
unaryValueNumber(instr, funcIR, opcode, type, operand) and
result = TUnaryValueNumber(funcIR, opcode, type, operand)
) or
exists(Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand |
inheritanceConversionValueNumber(instr, funcIR, opcode, baseClass, derivedClass,
operand) and
result = TInheritanceConversionValueNumber(funcIR, opcode, baseClass, derivedClass, operand)
) or
exists(Opcode opcode, Type type, int elementSize, ValueNumber leftOperand,
ValueNumber rightOperand |
pointerArithmeticValueNumber(instr, funcIR, opcode, type, elementSize, leftOperand,
rightOperand) and
result = TPointerArithmeticValueNumber(funcIR, opcode, type, elementSize, leftOperand,
rightOperand)
) or
// The value number of a copy is just the value number of its source value.
result = valueNumber(instr.(CongruentCopyInstruction).getSourceValue())
)
)
}

View File

@@ -0,0 +1 @@
import semmle.code.cpp.ir.implementation.raw.IR as IR

View File

@@ -4,6 +4,7 @@ import IRBlockConstruction as BlockConstruction
private import semmle.code.cpp.ir.internal.TempVariableTag
private import InstructionTag
private import TranslatedElement
private import TranslatedExpr
private import TranslatedFunction
class InstructionTagType extends TInstructionTag {
@@ -73,6 +74,13 @@ cached private module Cached {
none()
}
cached Expr getInstructionResultExpression(Instruction instruction) {
exists(TranslatedExpr translatedExpr |
translatedExpr = getTranslatedExpr(result) and
instruction = translatedExpr.getResult()
)
}
cached Instruction getInstructionOperand(Instruction instruction, OperandTag tag) {
result = getInstructionTranslatedElement(instruction).getInstructionOperand(
instruction.getTag(), tag)

View File

@@ -5,3 +5,30 @@ import IRVariable
import OperandTag
import semmle.code.cpp.ir.implementation.EdgeKind
import semmle.code.cpp.ir.implementation.MemoryAccessKind
private newtype TIRPropertyProvider = MkIRPropertyProvider()
/**
* Class that provides additional properties to be dumped for IR instructions and blocks when using
* the PrintIR module. Libraries that compute additional facts about IR elements can extend the
* single instance of this class to specify the additional properties computed by the library.
*/
class IRPropertyProvider extends TIRPropertyProvider {
string toString() {
result = "IRPropertyProvider"
}
/**
* Gets the value of the property named `key` for the specified instruction.
*/
string getInstructionProperty(Instruction instruction, string key) {
none()
}
/**
* Gets the value of the property named `key` for the specified block.
*/
string getBlockProperty(IRBlock block, string key) {
none()
}
}

View File

@@ -107,6 +107,14 @@ module InstructionSanity {
operand = op.getOperand(tag) and
operand.getFunctionIR() != op.getFunctionIR()
}
/**
* Holds if instruction `instr` is not in exactly one block.
*/
query predicate instructionWithoutUniqueBlock(Instruction instr, int blockCount) {
blockCount = count(instr.getBlock()) and
blockCount != 1
}
}
/**
@@ -301,6 +309,13 @@ class Instruction extends Construction::TInstruction {
result = ast.getLocation()
}
/**
* Gets the `Expr` whose results is computed by this instruction, if any.
*/
final Expr getResultExpression() {
result = Construction::getInstructionResultExpression(this)
}
/**
* Gets the type of the result produced by this instruction. If the
* instruction does not produce a result, its result type will be `VoidType`.
@@ -554,6 +569,15 @@ class InitializeParameterInstruction extends VariableInstruction {
}
}
/**
* An instruction that initializes the `this` pointer parameter of the enclosing function.
*/
class InitializeThisInstruction extends Instruction {
InitializeThisInstruction() {
opcode instanceof Opcode::InitializeThis
}
}
class FieldAddressInstruction extends FieldInstruction {
FieldAddressInstruction() {
opcode instanceof Opcode::FieldAddress

View File

@@ -1,6 +1,18 @@
private import IR
import cpp
private string getAdditionalInstructionProperty(Instruction instr, string key) {
exists(IRPropertyProvider provider |
result = provider.getInstructionProperty(instr, key)
)
}
private string getAdditionalBlockProperty(IRBlock block, string key) {
exists(IRPropertyProvider provider |
result = provider.getBlockProperty(block, key)
)
}
private newtype TPrintableIRNode =
TPrintableFunctionIR(FunctionIR funcIR) or
TPrintableIRBlock(IRBlock block) or
@@ -135,6 +147,11 @@ class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
result.getFunctionIR() = block.getFunctionIR()
}
override string getProperty(string key) {
result = PrintableIRNode.super.getProperty(key) or
result = getAdditionalBlockProperty(block, key)
}
final IRBlock getBlock() {
result = block
}
@@ -185,6 +202,11 @@ class PrintableInstruction extends PrintableIRNode, TPrintableInstruction {
final Instruction getInstruction() {
result = instr
}
override string getProperty(string key) {
result = PrintableIRNode.super.getProperty(key) or
result = getAdditionalInstructionProperty(instr, key)
}
}
private predicate columnWidths(IRBlock block, int resultWidth, int operationWidth) {

View File

@@ -0,0 +1,274 @@
private import internal.ValueNumberingInternal
import cpp
private import IR
/**
* Provides additional information about value numbering in IR dumps.
*/
class ValueNumberPropertyProvider extends IRPropertyProvider {
override string getInstructionProperty(Instruction instr, string key) {
exists(ValueNumber vn |
vn = valueNumber(instr) and
key = "valnum" and
if strictcount(vn.getAnInstruction()) > 1 then
result = vn.toString()
else
result = "unique"
)
}
}
newtype TValueNumber =
TVariableAddressValueNumber(FunctionIR funcIR, IRVariable var) {
variableAddressValueNumber(_, funcIR, var)
} or
TInitializeParameterValueNumber(FunctionIR funcIR, IRVariable var) {
initializeParameterValueNumber(_, funcIR, var)
} or
TInitializeThisValueNumber(FunctionIR funcIR) {
initializeThisValueNumber(_, funcIR)
} or
TConstantValueNumber(FunctionIR funcIR, Type type, string value) {
constantValueNumber(_, funcIR, type, value)
} or
TFieldAddressValueNumber(FunctionIR funcIR, Field field, ValueNumber objectAddress) {
fieldAddressValueNumber(_, funcIR, field, objectAddress)
} or
TBinaryValueNumber(FunctionIR funcIR, Opcode opcode, Type type, ValueNumber leftOperand,
ValueNumber rightOperand) {
binaryValueNumber(_, funcIR, opcode, type, leftOperand, rightOperand)
} or
TPointerArithmeticValueNumber(FunctionIR funcIR, Opcode opcode, Type type, int elementSize,
ValueNumber leftOperand, ValueNumber rightOperand) {
pointerArithmeticValueNumber(_, funcIR, opcode, type, elementSize, leftOperand, rightOperand)
} or
TUnaryValueNumber(FunctionIR funcIR, Opcode opcode, Type type, ValueNumber operand) {
unaryValueNumber(_, funcIR, opcode, type, operand)
} or
TInheritanceConversionValueNumber(FunctionIR funcIR, Opcode opcode, Class baseClass,
Class derivedClass, ValueNumber operand) {
inheritanceConversionValueNumber(_, funcIR, opcode, baseClass, derivedClass, operand)
} or
TUniqueValueNumber(FunctionIR funcIR, Instruction instr) {
uniqueValueNumber(instr, funcIR)
}
/**
* The value number assigned to a particular set of instructions that produce equivalent results.
*/
class ValueNumber extends TValueNumber {
final string toString() {
result = getExampleInstruction().getResultId()
}
final Location getLocation() {
result = getExampleInstruction().getLocation()
}
/**
* Gets the instructions that have been assigned this value number. This will always produce at
* least one result.
*/
final Instruction getAnInstruction() {
this = valueNumber(result)
}
/**
* Gets one of the instructions that was assigned this value number. The chosen instuction is
* deterministic but arbitrary. Intended for use only in debugging.
*/
final Instruction getExampleInstruction() {
result = min(Instruction instr |
instr = getAnInstruction() |
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
)
}
}
/**
* A `CopyInstruction` whose source operand's value is congruent to the definition of that source
* operand.
* For example:
* ```
* Point p = { 1, 2 };
* Point q = p;
* int a = p.x;
* ```
* The use of `p` on line 2 is linked to the definition of `p` on line 1, and is congruent to that
* definition because it accesses the exact same memory.
* The use of `p.x` on line 3 is linked to the definition of `p` on line 1 as well, but is not
* congruent to that definition because `p.x` accesses only a subset of the memory defined by `p`.
*
* This concept should probably be exposed in the public IR API.
*/
private class CongruentCopyInstruction extends CopyInstruction {
CongruentCopyInstruction() {
exists(Instruction def |
def = this.getSourceValue() and
(
def.getResultMemoryAccess() instanceof IndirectMemoryAccess or
not def.hasMemoryResult()
)
)
}
}
/**
* Holds if this library knows how to assign a value number to the specified instruction, other than
* a `unique` value number that is never shared by multiple instructions.
*/
private predicate numberableInstruction(Instruction instr) {
instr instanceof VariableAddressInstruction or
instr instanceof InitializeParameterInstruction or
instr instanceof InitializeThisInstruction or
instr instanceof ConstantInstruction or
instr instanceof FieldAddressInstruction or
instr instanceof BinaryInstruction or
instr instanceof UnaryInstruction or
instr instanceof PointerArithmeticInstruction or
instr instanceof CongruentCopyInstruction
}
private predicate variableAddressValueNumber(VariableAddressInstruction instr, FunctionIR funcIR,
IRVariable var) {
instr.getFunctionIR() = funcIR and
instr.getVariable() = var
}
private predicate initializeParameterValueNumber(InitializeParameterInstruction instr,
FunctionIR funcIR, IRVariable var) {
instr.getFunctionIR() = funcIR and
instr.getVariable() = var
}
private predicate initializeThisValueNumber(InitializeThisInstruction instr, FunctionIR funcIR) {
instr.getFunctionIR() = funcIR
}
private predicate constantValueNumber(ConstantInstruction instr, FunctionIR funcIR, Type type,
string value) {
instr.getFunctionIR() = funcIR and
instr.getResultType() = type and
instr.getValue() = value
}
private predicate fieldAddressValueNumber(FieldAddressInstruction instr, FunctionIR funcIR,
Field field, ValueNumber objectAddress) {
instr.getFunctionIR() = funcIR and
instr.getField() = field and
valueNumber(instr.getObjectAddress()) = objectAddress
}
private predicate binaryValueNumber(BinaryInstruction instr, FunctionIR funcIR, Opcode opcode,
Type type, ValueNumber leftOperand, ValueNumber rightOperand) {
instr.getFunctionIR() = funcIR and
(not instr instanceof PointerArithmeticInstruction) and
instr.getOpcode() = opcode and
instr.getResultType() = type and
valueNumber(instr.getLeftOperand()) = leftOperand and
valueNumber(instr.getRightOperand()) = rightOperand
}
private predicate pointerArithmeticValueNumber(PointerArithmeticInstruction instr,
FunctionIR funcIR, Opcode opcode, Type type, int elementSize, ValueNumber leftOperand,
ValueNumber rightOperand) {
instr.getFunctionIR() = funcIR and
instr.getOpcode() = opcode and
instr.getResultType() = type and
instr.getElementSize() = elementSize and
valueNumber(instr.getLeftOperand()) = leftOperand and
valueNumber(instr.getRightOperand()) = rightOperand
}
private predicate unaryValueNumber(UnaryInstruction instr, FunctionIR funcIR, Opcode opcode,
Type type, ValueNumber operand) {
instr.getFunctionIR() = funcIR and
(not instr instanceof InheritanceConversionInstruction) and
instr.getOpcode() = opcode and
instr.getResultType() = type and
valueNumber(instr.getOperand()) = operand
}
private predicate inheritanceConversionValueNumber(InheritanceConversionInstruction instr,
FunctionIR funcIR, Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand) {
instr.getFunctionIR() = funcIR and
instr.getOpcode() = opcode and
instr.getBaseClass() = baseClass and
instr.getDerivedClass() = derivedClass and
valueNumber(instr.getOperand()) = operand
}
/**
* Holds if `instr` should be assigned a unique value number because this library does not know how
* to determine if two instances of that instruction are equivalent.
*/
private predicate uniqueValueNumber(Instruction instr, FunctionIR funcIR) {
instr.getFunctionIR() = funcIR and
(not instr.getResultType() instanceof VoidType) and
not numberableInstruction(instr)
}
/**
* Gets the value number assigned to `instr`, if any. Returns at most one result.
*/
ValueNumber valueNumber(Instruction instr) {
result = nonUniqueValueNumber(instr) or
exists(FunctionIR funcIR |
uniqueValueNumber(instr, funcIR) and
result = TUniqueValueNumber(funcIR, instr)
)
}
/**
* Gets the value number assigned to `instr`, if any, unless that instruction is assigned a unique
* value number.
*/
private ValueNumber nonUniqueValueNumber(Instruction instr) {
exists(FunctionIR funcIR |
funcIR = instr.getFunctionIR() and
(
exists(IRVariable var |
variableAddressValueNumber(instr, funcIR, var) and
result = TVariableAddressValueNumber(funcIR, var)
) or
exists(IRVariable var |
initializeParameterValueNumber(instr, funcIR, var) and
result = TInitializeParameterValueNumber(funcIR, var)
) or
(
initializeThisValueNumber(instr, funcIR) and
result = TInitializeThisValueNumber(funcIR)
) or
exists(Type type, string value |
constantValueNumber(instr, funcIR, type, value) and
result = TConstantValueNumber(funcIR, type, value)
) or
exists(Field field, ValueNumber objectAddress |
fieldAddressValueNumber(instr, funcIR, field, objectAddress) and
result = TFieldAddressValueNumber(funcIR, field, objectAddress)
) or
exists(Opcode opcode, Type type, ValueNumber leftOperand, ValueNumber rightOperand |
binaryValueNumber(instr, funcIR, opcode, type, leftOperand, rightOperand) and
result = TBinaryValueNumber(funcIR, opcode, type, leftOperand, rightOperand)
) or
exists(Opcode opcode, Type type, ValueNumber operand |
unaryValueNumber(instr, funcIR, opcode, type, operand) and
result = TUnaryValueNumber(funcIR, opcode, type, operand)
) or
exists(Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand |
inheritanceConversionValueNumber(instr, funcIR, opcode, baseClass, derivedClass,
operand) and
result = TInheritanceConversionValueNumber(funcIR, opcode, baseClass, derivedClass, operand)
) or
exists(Opcode opcode, Type type, int elementSize, ValueNumber leftOperand,
ValueNumber rightOperand |
pointerArithmeticValueNumber(instr, funcIR, opcode, type, elementSize, leftOperand,
rightOperand) and
result = TPointerArithmeticValueNumber(funcIR, opcode, type, elementSize, leftOperand,
rightOperand)
) or
// The value number of a copy is just the value number of its source value.
result = valueNumber(instr.(CongruentCopyInstruction).getSourceValue())
)
)
}

View File

@@ -0,0 +1 @@
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as IR

View File

@@ -30,7 +30,9 @@ cached private module Cached {
}
cached newtype TInstructionTag =
WrappedInstructionTag(OldIR::Instruction oldInstruction) or
WrappedInstructionTag(OldIR::Instruction oldInstruction) {
not oldInstruction instanceof OldIR::PhiInstruction
} or
PhiTag(Alias::VirtualVariable vvar, OldIR::IRBlock block) {
hasPhiNode(vvar, block)
}
@@ -195,6 +197,10 @@ cached private module Cached {
)
}
cached Expr getInstructionResultExpression(Instruction instruction) {
result = getOldInstruction(instruction).getResultExpression()
}
cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
result = getNewInstruction(getOldInstruction(instruction).getSuccessor(kind))
}

File diff suppressed because it is too large Load Diff

View File

@@ -5,3 +5,4 @@ missingPhiOperand
instructionWithoutSuccessor
unnecessaryPhiInstruction
operandAcrossFunctions
instructionWithoutUniqueBlock

View File

@@ -5,3 +5,4 @@ missingPhiOperand
instructionWithoutSuccessor
unnecessaryPhiInstruction
operandAcrossFunctions
instructionWithoutUniqueBlock

View File

@@ -5,3 +5,4 @@ missingPhiOperand
instructionWithoutSuccessor
unnecessaryPhiInstruction
operandAcrossFunctions
instructionWithoutUniqueBlock

View File

@@ -27,3 +27,6 @@
| test.cpp:62:5:62:10 | result | 62:c5-c10 65:c10-c15 |
| test.cpp:77:20:77:30 | (signed short)... | 77:c20-c30 79:c7-c7 |
| test.cpp:79:11:79:14 | vals | 79:c11-c14 79:c24-c27 |
| test.cpp:105:11:105:12 | (Base *)... | 105:c11-c12 106:c14-c35 107:c11-c12 |
| test.cpp:105:11:105:12 | pd | 105:c11-c12 106:c33-c34 |
| test.cpp:105:15:105:15 | b | 105:c15-c15 107:c15-c15 109:c10-c10 |

View File

@@ -0,0 +1,714 @@
test.cpp:
# 1| test00(int, int) -> int
# 1| Block 0
# 1| v0_0(void) = EnterFunction :
# 1| mu0_1(unknown) = UnmodeledDefinition :
# 1| valnum = unique
# 1| r0_2(glval<int>) = VariableAddress[p0] :
# 1| valnum = r0_2
# 1| m0_3(int) = InitializeParameter[p0] : r0_2
# 1| valnum = m0_3
# 1| r0_4(glval<int>) = VariableAddress[p1] :
# 1| valnum = r0_4
# 1| m0_5(int) = InitializeParameter[p1] : r0_4
# 1| valnum = m0_5
# 2| r0_6(glval<int>) = VariableAddress[x] :
# 2| valnum = r0_6
# 2| m0_7(int) = Uninitialized : r0_6
# 2| valnum = unique
# 2| r0_8(glval<int>) = VariableAddress[y] :
# 2| valnum = r0_8
# 2| m0_9(int) = Uninitialized : r0_8
# 2| valnum = unique
# 3| r0_10(glval<unsigned char>) = VariableAddress[b] :
# 3| valnum = unique
# 3| m0_11(unsigned char) = Uninitialized : r0_10
# 3| valnum = unique
# 5| r0_12(glval<int>) = VariableAddress[p0] :
# 5| valnum = r0_2
# 5| r0_13(int) = Load : r0_12, m0_3
# 5| valnum = m0_3
# 5| r0_14(glval<int>) = VariableAddress[p1] :
# 5| valnum = r0_4
# 5| r0_15(int) = Load : r0_14, m0_5
# 5| valnum = m0_5
# 5| r0_16(int) = Add : r0_13, r0_15
# 5| valnum = r0_16
# 5| r0_17(glval<int>) = VariableAddress[x] :
# 5| valnum = r0_6
# 5| m0_18(int) = Store : r0_17, r0_16
# 5| valnum = r0_16
# 6| r0_19(glval<int>) = VariableAddress[p0] :
# 6| valnum = r0_2
# 6| r0_20(int) = Load : r0_19, m0_3
# 6| valnum = m0_3
# 6| r0_21(glval<int>) = VariableAddress[p1] :
# 6| valnum = r0_4
# 6| r0_22(int) = Load : r0_21, m0_5
# 6| valnum = m0_5
# 6| r0_23(int) = Add : r0_20, r0_22
# 6| valnum = r0_16
# 6| r0_24(glval<int>) = VariableAddress[x] :
# 6| valnum = r0_6
# 6| m0_25(int) = Store : r0_24, r0_23
# 6| valnum = r0_16
# 7| r0_26(glval<int>) = VariableAddress[x] :
# 7| valnum = r0_6
# 7| r0_27(int) = Load : r0_26, m0_25
# 7| valnum = r0_16
# 7| r0_28(glval<int>) = VariableAddress[y] :
# 7| valnum = r0_8
# 7| m0_29(int) = Store : r0_28, r0_27
# 7| valnum = r0_16
# 8| v0_30(void) = NoOp :
# 1| r0_31(glval<int>) = VariableAddress[#return] :
# 1| valnum = unique
# 1| v0_32(void) = ReturnValue : r0_31
# 1| v0_33(void) = UnmodeledUse : mu*
# 1| v0_34(void) = ExitFunction :
# 12| test01(int, int) -> int
# 12| Block 0
# 12| v0_0(void) = EnterFunction :
# 12| mu0_1(unknown) = UnmodeledDefinition :
# 12| valnum = unique
# 12| r0_2(glval<int>) = VariableAddress[p0] :
# 12| valnum = r0_2
# 12| m0_3(int) = InitializeParameter[p0] : r0_2
# 12| valnum = m0_3
# 12| r0_4(glval<int>) = VariableAddress[p1] :
# 12| valnum = r0_4
# 12| m0_5(int) = InitializeParameter[p1] : r0_4
# 12| valnum = m0_5
# 13| r0_6(glval<int>) = VariableAddress[x] :
# 13| valnum = r0_6
# 13| m0_7(int) = Uninitialized : r0_6
# 13| valnum = unique
# 13| r0_8(glval<int>) = VariableAddress[y] :
# 13| valnum = r0_8
# 13| m0_9(int) = Uninitialized : r0_8
# 13| valnum = unique
# 14| r0_10(glval<unsigned char>) = VariableAddress[b] :
# 14| valnum = unique
# 14| m0_11(unsigned char) = Uninitialized : r0_10
# 14| valnum = unique
# 16| r0_12(glval<int>) = VariableAddress[p0] :
# 16| valnum = r0_2
# 16| r0_13(int) = Load : r0_12, m0_3
# 16| valnum = m0_3
# 16| r0_14(glval<int>) = VariableAddress[p1] :
# 16| valnum = r0_4
# 16| r0_15(int) = Load : r0_14, m0_5
# 16| valnum = m0_5
# 16| r0_16(int) = Add : r0_13, r0_15
# 16| valnum = r0_16
# 16| r0_17(glval<int>) = VariableAddress[global01] :
# 16| valnum = r0_17
# 16| r0_18(int) = Load : r0_17, mu0_1
# 16| valnum = unique
# 16| r0_19(int) = Add : r0_16, r0_18
# 16| valnum = r0_19
# 16| r0_20(glval<int>) = VariableAddress[x] :
# 16| valnum = r0_6
# 16| m0_21(int) = Store : r0_20, r0_19
# 16| valnum = r0_19
# 17| r0_22(glval<int>) = VariableAddress[p0] :
# 17| valnum = r0_2
# 17| r0_23(int) = Load : r0_22, m0_3
# 17| valnum = m0_3
# 17| r0_24(glval<int>) = VariableAddress[p1] :
# 17| valnum = r0_4
# 17| r0_25(int) = Load : r0_24, m0_5
# 17| valnum = m0_5
# 17| r0_26(int) = Add : r0_23, r0_25
# 17| valnum = r0_16
# 17| r0_27(glval<int>) = VariableAddress[global01] :
# 17| valnum = r0_17
# 17| r0_28(int) = Load : r0_27, mu0_1
# 17| valnum = unique
# 17| r0_29(int) = Add : r0_26, r0_28
# 17| valnum = r0_29
# 17| r0_30(glval<int>) = VariableAddress[x] :
# 17| valnum = r0_6
# 17| m0_31(int) = Store : r0_30, r0_29
# 17| valnum = r0_29
# 18| r0_32(glval<int>) = VariableAddress[x] :
# 18| valnum = r0_6
# 18| r0_33(int) = Load : r0_32, m0_31
# 18| valnum = r0_29
# 18| r0_34(glval<int>) = VariableAddress[y] :
# 18| valnum = r0_8
# 18| m0_35(int) = Store : r0_34, r0_33
# 18| valnum = r0_29
# 19| v0_36(void) = NoOp :
# 12| r0_37(glval<int>) = VariableAddress[#return] :
# 12| valnum = unique
# 12| v0_38(void) = ReturnValue : r0_37
# 12| v0_39(void) = UnmodeledUse : mu*
# 12| v0_40(void) = ExitFunction :
# 25| test02(int, int) -> int
# 25| Block 0
# 25| v0_0(void) = EnterFunction :
# 25| mu0_1(unknown) = UnmodeledDefinition :
# 25| valnum = unique
# 25| r0_2(glval<int>) = VariableAddress[p0] :
# 25| valnum = r0_2
# 25| m0_3(int) = InitializeParameter[p0] : r0_2
# 25| valnum = m0_3
# 25| r0_4(glval<int>) = VariableAddress[p1] :
# 25| valnum = r0_4
# 25| m0_5(int) = InitializeParameter[p1] : r0_4
# 25| valnum = m0_5
# 26| r0_6(glval<int>) = VariableAddress[x] :
# 26| valnum = r0_6
# 26| m0_7(int) = Uninitialized : r0_6
# 26| valnum = unique
# 26| r0_8(glval<int>) = VariableAddress[y] :
# 26| valnum = r0_8
# 26| m0_9(int) = Uninitialized : r0_8
# 26| valnum = unique
# 27| r0_10(glval<unsigned char>) = VariableAddress[b] :
# 27| valnum = unique
# 27| m0_11(unsigned char) = Uninitialized : r0_10
# 27| valnum = unique
# 29| r0_12(glval<int>) = VariableAddress[p0] :
# 29| valnum = r0_2
# 29| r0_13(int) = Load : r0_12, m0_3
# 29| valnum = m0_3
# 29| r0_14(glval<int>) = VariableAddress[p1] :
# 29| valnum = r0_4
# 29| r0_15(int) = Load : r0_14, m0_5
# 29| valnum = m0_5
# 29| r0_16(int) = Add : r0_13, r0_15
# 29| valnum = r0_16
# 29| r0_17(glval<int>) = VariableAddress[global02] :
# 29| valnum = r0_17
# 29| r0_18(int) = Load : r0_17, mu0_1
# 29| valnum = unique
# 29| r0_19(int) = Add : r0_16, r0_18
# 29| valnum = r0_19
# 29| r0_20(glval<int>) = VariableAddress[x] :
# 29| valnum = r0_6
# 29| m0_21(int) = Store : r0_20, r0_19
# 29| valnum = r0_19
# 30| r0_22(glval<unknown>) = FunctionAddress[change_global02] :
# 30| valnum = unique
# 30| v0_23(void) = Call : r0_22
# 31| r0_24(glval<int>) = VariableAddress[p0] :
# 31| valnum = r0_2
# 31| r0_25(int) = Load : r0_24, m0_3
# 31| valnum = m0_3
# 31| r0_26(glval<int>) = VariableAddress[p1] :
# 31| valnum = r0_4
# 31| r0_27(int) = Load : r0_26, m0_5
# 31| valnum = m0_5
# 31| r0_28(int) = Add : r0_25, r0_27
# 31| valnum = r0_16
# 31| r0_29(glval<int>) = VariableAddress[global02] :
# 31| valnum = r0_17
# 31| r0_30(int) = Load : r0_29, mu0_1
# 31| valnum = unique
# 31| r0_31(int) = Add : r0_28, r0_30
# 31| valnum = r0_31
# 31| r0_32(glval<int>) = VariableAddress[x] :
# 31| valnum = r0_6
# 31| m0_33(int) = Store : r0_32, r0_31
# 31| valnum = r0_31
# 32| r0_34(glval<int>) = VariableAddress[x] :
# 32| valnum = r0_6
# 32| r0_35(int) = Load : r0_34, m0_33
# 32| valnum = r0_31
# 32| r0_36(glval<int>) = VariableAddress[y] :
# 32| valnum = r0_8
# 32| m0_37(int) = Store : r0_36, r0_35
# 32| valnum = r0_31
# 33| v0_38(void) = NoOp :
# 25| r0_39(glval<int>) = VariableAddress[#return] :
# 25| valnum = unique
# 25| v0_40(void) = ReturnValue : r0_39
# 25| v0_41(void) = UnmodeledUse : mu*
# 25| v0_42(void) = ExitFunction :
# 39| test03(int, int, int *) -> int
# 39| Block 0
# 39| v0_0(void) = EnterFunction :
# 39| mu0_1(unknown) = UnmodeledDefinition :
# 39| valnum = unique
# 39| r0_2(glval<int>) = VariableAddress[p0] :
# 39| valnum = r0_2
# 39| m0_3(int) = InitializeParameter[p0] : r0_2
# 39| valnum = m0_3
# 39| r0_4(glval<int>) = VariableAddress[p1] :
# 39| valnum = r0_4
# 39| m0_5(int) = InitializeParameter[p1] : r0_4
# 39| valnum = m0_5
# 39| r0_6(glval<int *>) = VariableAddress[p2] :
# 39| valnum = r0_6
# 39| m0_7(int *) = InitializeParameter[p2] : r0_6
# 39| valnum = m0_7
# 40| r0_8(glval<int>) = VariableAddress[x] :
# 40| valnum = r0_8
# 40| m0_9(int) = Uninitialized : r0_8
# 40| valnum = unique
# 40| r0_10(glval<int>) = VariableAddress[y] :
# 40| valnum = r0_10
# 40| m0_11(int) = Uninitialized : r0_10
# 40| valnum = unique
# 41| r0_12(glval<unsigned char>) = VariableAddress[b] :
# 41| valnum = unique
# 41| m0_13(unsigned char) = Uninitialized : r0_12
# 41| valnum = unique
# 43| r0_14(glval<int>) = VariableAddress[p0] :
# 43| valnum = r0_2
# 43| r0_15(int) = Load : r0_14, m0_3
# 43| valnum = m0_3
# 43| r0_16(glval<int>) = VariableAddress[p1] :
# 43| valnum = r0_4
# 43| r0_17(int) = Load : r0_16, m0_5
# 43| valnum = m0_5
# 43| r0_18(int) = Add : r0_15, r0_17
# 43| valnum = r0_18
# 43| r0_19(glval<int>) = VariableAddress[global03] :
# 43| valnum = r0_19
# 43| r0_20(int) = Load : r0_19, mu0_1
# 43| valnum = unique
# 43| r0_21(int) = Add : r0_18, r0_20
# 43| valnum = r0_21
# 43| r0_22(glval<int>) = VariableAddress[x] :
# 43| valnum = r0_8
# 43| m0_23(int) = Store : r0_22, r0_21
# 43| valnum = r0_21
# 44| r0_24(int) = Constant[0] :
# 44| valnum = r0_24
# 44| r0_25(glval<int *>) = VariableAddress[p2] :
# 44| valnum = r0_6
# 44| r0_26(int *) = Load : r0_25, m0_7
# 44| valnum = m0_7
# 44| mu0_27(int) = Store : r0_26, r0_24
# 44| valnum = r0_24
# 45| r0_28(glval<int>) = VariableAddress[p0] :
# 45| valnum = r0_2
# 45| r0_29(int) = Load : r0_28, m0_3
# 45| valnum = m0_3
# 45| r0_30(glval<int>) = VariableAddress[p1] :
# 45| valnum = r0_4
# 45| r0_31(int) = Load : r0_30, m0_5
# 45| valnum = m0_5
# 45| r0_32(int) = Add : r0_29, r0_31
# 45| valnum = r0_18
# 45| r0_33(glval<int>) = VariableAddress[global03] :
# 45| valnum = r0_19
# 45| r0_34(int) = Load : r0_33, mu0_1
# 45| valnum = unique
# 45| r0_35(int) = Add : r0_32, r0_34
# 45| valnum = r0_35
# 45| r0_36(glval<int>) = VariableAddress[x] :
# 45| valnum = r0_8
# 45| m0_37(int) = Store : r0_36, r0_35
# 45| valnum = r0_35
# 46| r0_38(glval<int>) = VariableAddress[x] :
# 46| valnum = r0_8
# 46| r0_39(int) = Load : r0_38, m0_37
# 46| valnum = r0_35
# 46| r0_40(glval<int>) = VariableAddress[y] :
# 46| valnum = r0_10
# 46| m0_41(int) = Store : r0_40, r0_39
# 46| valnum = r0_35
# 47| v0_42(void) = NoOp :
# 39| r0_43(glval<int>) = VariableAddress[#return] :
# 39| valnum = unique
# 39| v0_44(void) = ReturnValue : r0_43
# 39| v0_45(void) = UnmodeledUse : mu*
# 39| v0_46(void) = ExitFunction :
# 49| my_strspn(const char *, const char *) -> unsigned int
# 49| Block 0
# 49| v0_0(void) = EnterFunction :
# 49| mu0_1(unknown) = UnmodeledDefinition :
# 49| valnum = unique
# 49| r0_2(glval<char *>) = VariableAddress[str] :
# 49| valnum = r0_2
# 49| m0_3(char *) = InitializeParameter[str] : r0_2
# 49| valnum = m0_3
# 49| r0_4(glval<char *>) = VariableAddress[chars] :
# 49| valnum = r0_4
# 49| m0_5(char *) = InitializeParameter[chars] : r0_4
# 49| valnum = m0_5
# 50| r0_6(glval<char *>) = VariableAddress[ptr] :
# 50| valnum = r0_6
# 50| m0_7(char *) = Uninitialized : r0_6
# 50| valnum = unique
# 51| r0_8(glval<unsigned int>) = VariableAddress[result] :
# 51| valnum = r0_8
# 51| r0_9(unsigned int) = Constant[0] :
# 51| valnum = r0_9
# 51| m0_10(unsigned int) = Store : r0_8, r0_9
# 51| valnum = r0_9
#-----| Goto -> Block 1
# 53| Block 1
# 53| m1_0(unsigned int) = Phi : from 0:m0_10, from 8:m8_4
# 53| valnum = unique
# 53| r1_1(glval<char *>) = VariableAddress[str] :
# 53| valnum = r0_2
# 53| r1_2(char *) = Load : r1_1, m0_3
# 53| valnum = m0_3
# 53| r1_3(char) = Load : r1_2, mu0_1
# 53| valnum = unique
# 53| r1_4(int) = Convert : r1_3
# 53| valnum = unique
# 53| r1_5(int) = Constant[0] :
# 53| valnum = r1_5
# 53| r1_6(bool) = CompareNE : r1_4, r1_5
# 53| valnum = unique
# 53| v1_7(void) = ConditionalBranch : r1_6
#-----| False -> Block 9
#-----| True -> Block 2
# 55| Block 2
# 55| r2_0(glval<char *>) = VariableAddress[chars] :
# 55| valnum = r0_4
# 55| r2_1(char *) = Load : r2_0, m0_5
# 55| valnum = m0_5
# 55| r2_2(glval<char *>) = VariableAddress[ptr] :
# 55| valnum = r0_6
# 55| m2_3(char *) = Store : r2_2, r2_1
# 55| valnum = m0_5
#-----| Goto -> Block 3
# 56| Block 3
# 56| m3_0(char *) = Phi : from 2:m2_3, from 5:m5_4
# 56| valnum = unique
# 56| r3_1(glval<char *>) = VariableAddress[ptr] :
# 56| valnum = r0_6
# 56| r3_2(char *) = Load : r3_1, m3_0
# 56| valnum = unique
# 56| r3_3(char) = Load : r3_2, mu0_1
# 56| valnum = unique
# 56| r3_4(int) = Convert : r3_3
# 56| valnum = unique
# 56| r3_5(glval<char *>) = VariableAddress[str] :
# 56| valnum = r0_2
# 56| r3_6(char *) = Load : r3_5, m0_3
# 56| valnum = m0_3
# 56| r3_7(char) = Load : r3_6, mu0_1
# 56| valnum = unique
# 56| r3_8(int) = Convert : r3_7
# 56| valnum = unique
# 56| r3_9(bool) = CompareNE : r3_4, r3_8
# 56| valnum = unique
# 56| v3_10(void) = ConditionalBranch : r3_9
#-----| False -> Block 6
#-----| True -> Block 4
# 56| Block 4
# 56| r4_0(glval<char *>) = VariableAddress[ptr] :
# 56| valnum = r0_6
# 56| r4_1(char *) = Load : r4_0, m3_0
# 56| valnum = unique
# 56| r4_2(char) = Load : r4_1, mu0_1
# 56| valnum = unique
# 56| r4_3(int) = Convert : r4_2
# 56| valnum = unique
# 56| r4_4(int) = Constant[0] :
# 56| valnum = r1_5
# 56| r4_5(bool) = CompareNE : r4_3, r4_4
# 56| valnum = unique
# 56| v4_6(void) = ConditionalBranch : r4_5
#-----| False -> Block 6
#-----| True -> Block 5
# 56| Block 5
# 56| r5_0(glval<char *>) = VariableAddress[ptr] :
# 56| valnum = r0_6
# 56| r5_1(char *) = Load : r5_0, m3_0
# 56| valnum = unique
# 56| r5_2(int) = Constant[1] :
# 56| valnum = unique
# 56| r5_3(char *) = PointerAdd[1] : r5_1, r5_2
# 56| valnum = r5_3
# 56| m5_4(char *) = Store : r5_0, r5_3
# 56| valnum = r5_3
#-----| Goto -> Block 3
# 59| Block 6
# 59| r6_0(glval<char *>) = VariableAddress[ptr] :
# 59| valnum = r0_6
# 59| r6_1(char *) = Load : r6_0, m3_0
# 59| valnum = unique
# 59| r6_2(char) = Load : r6_1, mu0_1
# 59| valnum = unique
# 59| r6_3(int) = Convert : r6_2
# 59| valnum = unique
# 59| r6_4(int) = Constant[0] :
# 59| valnum = r1_5
# 59| r6_5(bool) = CompareEQ : r6_3, r6_4
# 59| valnum = unique
# 59| v6_6(void) = ConditionalBranch : r6_5
#-----| False -> Block 8
#-----| True -> Block 7
# 60| Block 7
# 60| v7_0(void) = NoOp :
#-----| Goto -> Block 9
# 62| Block 8
# 62| r8_0(glval<unsigned int>) = VariableAddress[result] :
# 62| valnum = r0_8
# 62| r8_1(unsigned int) = Load : r8_0, m1_0
# 62| valnum = unique
# 62| r8_2(unsigned int) = Constant[1] :
# 62| valnum = unique
# 62| r8_3(unsigned int) = Add : r8_1, r8_2
# 62| valnum = r8_3
# 62| m8_4(unsigned int) = Store : r8_0, r8_3
# 62| valnum = r8_3
#-----| Goto -> Block 1
# 63| Block 9
# 63| v9_0(void) = NoOp :
# 65| r9_1(glval<unsigned int>) = VariableAddress[#return] :
# 65| valnum = r9_1
# 65| r9_2(glval<unsigned int>) = VariableAddress[result] :
# 65| valnum = r0_8
# 65| r9_3(unsigned int) = Load : r9_2, m1_0
# 65| valnum = r9_3
# 65| m9_4(unsigned int) = Store : r9_1, r9_3
# 65| valnum = r9_3
# 49| r9_5(glval<unsigned int>) = VariableAddress[#return] :
# 49| valnum = r9_1
# 49| v9_6(void) = ReturnValue : r9_5, m9_4
# 49| v9_7(void) = UnmodeledUse : mu*
# 49| v9_8(void) = ExitFunction :
# 75| test04(two_values *) -> void
# 75| Block 0
# 75| v0_0(void) = EnterFunction :
# 75| mu0_1(unknown) = UnmodeledDefinition :
# 75| valnum = unique
# 75| r0_2(glval<two_values *>) = VariableAddress[vals] :
# 75| valnum = r0_2
# 75| m0_3(two_values *) = InitializeParameter[vals] : r0_2
# 75| valnum = m0_3
# 77| r0_4(glval<signed short>) = VariableAddress[v] :
# 77| valnum = r0_4
# 77| r0_5(glval<unknown>) = FunctionAddress[getAValue] :
# 77| valnum = unique
# 77| r0_6(int) = Call : r0_5
# 77| valnum = unique
# 77| r0_7(signed short) = Convert : r0_6
# 77| valnum = r0_7
# 77| m0_8(signed short) = Store : r0_4, r0_7
# 77| valnum = r0_7
# 79| r0_9(glval<signed short>) = VariableAddress[v] :
# 79| valnum = r0_4
# 79| r0_10(signed short) = Load : r0_9, m0_8
# 79| valnum = r0_7
# 79| r0_11(int) = Convert : r0_10
# 79| valnum = unique
# 79| r0_12(glval<two_values *>) = VariableAddress[vals] :
# 79| valnum = r0_2
# 79| r0_13(two_values *) = Load : r0_12, m0_3
# 79| valnum = m0_3
# 79| r0_14(glval<signed short>) = FieldAddress[val1] : r0_13
# 79| valnum = unique
# 79| r0_15(signed short) = Load : r0_14, mu0_1
# 79| valnum = unique
# 79| r0_16(int) = Convert : r0_15
# 79| valnum = unique
# 79| r0_17(glval<two_values *>) = VariableAddress[vals] :
# 79| valnum = r0_2
# 79| r0_18(two_values *) = Load : r0_17, m0_3
# 79| valnum = m0_3
# 79| r0_19(glval<signed short>) = FieldAddress[val2] : r0_18
# 79| valnum = unique
# 79| r0_20(signed short) = Load : r0_19, mu0_1
# 79| valnum = unique
# 79| r0_21(int) = Convert : r0_20
# 79| valnum = unique
# 79| r0_22(int) = Add : r0_16, r0_21
# 79| valnum = unique
# 79| r0_23(bool) = CompareLT : r0_11, r0_22
# 79| valnum = unique
# 79| v0_24(void) = ConditionalBranch : r0_23
#-----| False -> Block 2
#-----| True -> Block 1
# 80| Block 1
# 80| r1_0(glval<unknown>) = FunctionAddress[getAValue] :
# 80| valnum = unique
# 80| r1_1(int) = Call : r1_0
# 80| valnum = unique
# 80| r1_2(signed short) = Convert : r1_1
# 80| valnum = r1_2
# 80| r1_3(glval<signed short>) = VariableAddress[v] :
# 80| valnum = r0_4
# 80| m1_4(signed short) = Store : r1_3, r1_2
# 80| valnum = r1_2
#-----| Goto -> Block 2
# 82| Block 2
# 82| v2_0(void) = NoOp :
# 75| v2_1(void) = ReturnVoid :
# 75| v2_2(void) = UnmodeledUse : mu*
# 75| v2_3(void) = ExitFunction :
# 84| test05(int, int, void *) -> void
# 84| Block 0
# 84| v0_0(void) = EnterFunction :
# 84| mu0_1(unknown) = UnmodeledDefinition :
# 84| valnum = unique
# 84| r0_2(glval<int>) = VariableAddress[x] :
# 84| valnum = r0_2
# 84| m0_3(int) = InitializeParameter[x] : r0_2
# 84| valnum = m0_3
# 84| r0_4(glval<int>) = VariableAddress[y] :
# 84| valnum = r0_4
# 84| m0_5(int) = InitializeParameter[y] : r0_4
# 84| valnum = m0_5
# 84| r0_6(glval<void *>) = VariableAddress[p] :
# 84| valnum = r0_6
# 84| m0_7(void *) = InitializeParameter[p] : r0_6
# 84| valnum = m0_7
# 86| r0_8(glval<int>) = VariableAddress[v] :
# 86| valnum = r0_8
# 86| m0_9(int) = Uninitialized : r0_8
# 86| valnum = unique
# 88| r0_10(glval<void *>) = VariableAddress[p] :
# 88| valnum = r0_6
# 88| r0_11(void *) = Load : r0_10, m0_7
# 88| valnum = m0_7
# 88| r0_12(void *) = Constant[0] :
# 88| valnum = unique
# 88| r0_13(bool) = CompareNE : r0_11, r0_12
# 88| valnum = unique
# 88| v0_14(void) = ConditionalBranch : r0_13
#-----| False -> Block 2
#-----| True -> Block 1
# 88| Block 1
# 88| r1_0(glval<int>) = VariableAddress[x] :
# 88| valnum = r0_2
# 88| r1_1(int) = Load : r1_0, m0_3
# 88| valnum = m0_3
# 88| r1_2(glval<int>) = VariableAddress[#temp88:7] :
# 88| valnum = r1_2
# 88| m1_3(int) = Store : r1_2, r1_1
# 88| valnum = m0_3
#-----| Goto -> Block 3
# 88| Block 2
# 88| r2_0(glval<int>) = VariableAddress[y] :
# 88| valnum = r0_4
# 88| r2_1(int) = Load : r2_0, m0_5
# 88| valnum = m0_5
# 88| r2_2(glval<int>) = VariableAddress[#temp88:7] :
# 88| valnum = r1_2
# 88| m2_3(int) = Store : r2_2, r2_1
# 88| valnum = m0_5
#-----| Goto -> Block 3
# 88| Block 3
# 88| m3_0(int) = Phi : from 1:m1_3, from 2:m2_3
# 88| valnum = unique
# 88| r3_1(glval<int>) = VariableAddress[#temp88:7] :
# 88| valnum = r1_2
# 88| r3_2(int) = Load : r3_1, m3_0
# 88| valnum = r3_2
# 88| r3_3(glval<int>) = VariableAddress[v] :
# 88| valnum = r0_8
# 88| m3_4(int) = Store : r3_3, r3_2
# 88| valnum = r3_2
# 89| v3_5(void) = NoOp :
# 84| v3_6(void) = ReturnVoid :
# 84| v3_7(void) = UnmodeledUse : mu*
# 84| v3_8(void) = ExitFunction :
# 91| regression_test00() -> int
# 91| Block 0
# 91| v0_0(void) = EnterFunction :
# 91| mu0_1(unknown) = UnmodeledDefinition :
# 91| valnum = unique
# 92| r0_2(glval<int>) = VariableAddress[x] :
# 92| valnum = r0_2
# 92| r0_3(int) = Constant[10] :
# 92| valnum = r0_3
# 92| r0_4(glval<int>) = VariableAddress[x] :
# 92| valnum = r0_2
# 92| m0_5(int) = Store : r0_4, r0_3
# 92| valnum = r0_3
# 92| m0_6(int) = Store : r0_2, r0_3
# 92| valnum = r0_3
# 93| r0_7(glval<int>) = VariableAddress[#return] :
# 93| valnum = r0_7
# 93| r0_8(glval<int>) = VariableAddress[x] :
# 93| valnum = r0_2
# 93| r0_9(int) = Load : r0_8, m0_6
# 93| valnum = r0_3
# 93| m0_10(int) = Store : r0_7, r0_9
# 93| valnum = r0_3
# 91| r0_11(glval<int>) = VariableAddress[#return] :
# 91| valnum = r0_7
# 91| v0_12(void) = ReturnValue : r0_11, m0_10
# 91| v0_13(void) = UnmodeledUse : mu*
# 91| v0_14(void) = ExitFunction :
# 104| inheritanceConversions(Derived *) -> int
# 104| Block 0
# 104| v0_0(void) = EnterFunction :
# 104| mu0_1(unknown) = UnmodeledDefinition :
# 104| valnum = unique
# 104| r0_2(glval<Derived *>) = VariableAddress[pd] :
# 104| valnum = r0_2
# 104| m0_3(Derived *) = InitializeParameter[pd] : r0_2
# 104| valnum = m0_3
# 105| r0_4(glval<int>) = VariableAddress[x] :
# 105| valnum = unique
# 105| r0_5(glval<Derived *>) = VariableAddress[pd] :
# 105| valnum = r0_2
# 105| r0_6(Derived *) = Load : r0_5, m0_3
# 105| valnum = m0_3
# 105| r0_7(Base *) = ConvertToBase[Derived : Base] : r0_6
# 105| valnum = r0_7
# 105| r0_8(glval<int>) = FieldAddress[b] : r0_7
# 105| valnum = r0_8
# 105| r0_9(int) = Load : r0_8, mu0_1
# 105| valnum = r0_9
# 105| m0_10(int) = Store : r0_4, r0_9
# 105| valnum = r0_9
# 106| r0_11(glval<Base *>) = VariableAddress[pb] :
# 106| valnum = r0_11
# 106| r0_12(glval<Derived *>) = VariableAddress[pd] :
# 106| valnum = r0_2
# 106| r0_13(Derived *) = Load : r0_12, m0_3
# 106| valnum = m0_3
# 106| r0_14(Base *) = ConvertToBase[Derived : Base] : r0_13
# 106| valnum = r0_7
# 106| m0_15(Base *) = Store : r0_11, r0_14
# 106| valnum = r0_7
# 107| r0_16(glval<int>) = VariableAddress[y] :
# 107| valnum = r0_16
# 107| r0_17(glval<Base *>) = VariableAddress[pb] :
# 107| valnum = r0_11
# 107| r0_18(Base *) = Load : r0_17, m0_15
# 107| valnum = r0_7
# 107| r0_19(glval<int>) = FieldAddress[b] : r0_18
# 107| valnum = r0_8
# 107| r0_20(int) = Load : r0_19, mu0_1
# 107| valnum = r0_20
# 107| m0_21(int) = Store : r0_16, r0_20
# 107| valnum = r0_20
# 109| r0_22(glval<int>) = VariableAddress[#return] :
# 109| valnum = r0_22
# 109| r0_23(glval<int>) = VariableAddress[y] :
# 109| valnum = r0_16
# 109| r0_24(int) = Load : r0_23, m0_21
# 109| valnum = r0_20
# 109| m0_25(int) = Store : r0_22, r0_24
# 109| valnum = r0_20
# 104| r0_26(glval<int>) = VariableAddress[#return] :
# 104| valnum = r0_22
# 104| v0_27(void) = ReturnValue : r0_26, m0_25
# 104| v0_28(void) = UnmodeledUse : mu*
# 104| v0_29(void) = ExitFunction :

View File

@@ -0,0 +1,6 @@
/**
* @kind graph
*/
import semmle.code.cpp.ir.PrintIR
import semmle.code.cpp.ir.IR
import semmle.code.cpp.ir.ValueNumbering

View File

@@ -92,3 +92,19 @@ int regression_test00() {
int x = x = 10;
return x;
}
struct Base {
int b;
};
struct Derived : Base {
int d;
};
int inheritanceConversions(Derived* pd) {
int x = pd->b;
Base* pb = static_cast<Base*>(pd);
int y = pb->b;
return y;
}

View File

@@ -0,0 +1,131 @@
| test.cpp:5:3:5:3 | x | 5:c3-c3 6:c3-c3 7:c7-c7 |
| test.cpp:5:7:5:8 | p0 | 5:c7-c8 6:c7-c8 |
| test.cpp:5:7:5:13 | ... + ... | 5:c7-c13 6:c7-c13 |
| test.cpp:5:12:5:13 | p1 | 5:c12-c13 6:c12-c13 |
| test.cpp:16:3:16:3 | x | 16:c3-c3 17:c3-c3 18:c7-c7 |
| test.cpp:16:7:16:8 | p0 | 16:c7-c8 17:c7-c8 |
| test.cpp:16:7:16:13 | ... + ... | 16:c7-c13 17:c7-c13 |
| test.cpp:16:7:16:24 | ... + ... | 16:c7-c24 17:c7-c24 |
| test.cpp:16:12:16:13 | p1 | 16:c12-c13 17:c12-c13 |
| test.cpp:16:17:16:24 | global01 | 16:c17-c24 17:c17-c24 |
| test.cpp:29:3:29:3 | x | 29:c3-c3 31:c3-c3 32:c7-c7 |
| test.cpp:29:7:29:8 | p0 | 29:c7-c8 31:c7-c8 |
| test.cpp:29:7:29:13 | ... + ... | 29:c7-c13 31:c7-c13 |
| test.cpp:29:7:29:24 | ... + ... | 29:c7-c24 31:c7-c24 |
| test.cpp:29:12:29:13 | p1 | 29:c12-c13 31:c12-c13 |
| test.cpp:29:17:29:24 | global02 | 29:c17-c24 31:c17-c24 |
| test.cpp:43:3:43:3 | x | 43:c3-c3 45:c3-c3 46:c7-c7 |
| test.cpp:43:7:43:8 | p0 | 43:c7-c8 45:c7-c8 |
| test.cpp:43:7:43:13 | ... + ... | 43:c7-c13 45:c7-c13 |
| test.cpp:43:7:43:24 | ... + ... | 43:c7-c24 45:c7-c24 |
| test.cpp:43:12:43:13 | p1 | 43:c12-c13 45:c12-c13 |
| test.cpp:43:17:43:24 | global03 | 43:c17-c24 45:c17-c24 |
| test.cpp:53:10:53:13 | (int)... | 53:c10-c13 56:c21-c24 |
| test.cpp:53:10:53:13 | * ... | 53:c10-c13 56:c21-c24 |
| test.cpp:53:11:53:13 | str | 53:c11-c13 56:c22-c24 |
| test.cpp:55:5:55:7 | ptr | 55:c5-c7 56:c14-c16 56:c32-c34 56:c47-c49 59:c10-c12 |
| test.cpp:59:9:59:12 | (int)... | 56:c13-c16 56:c31-c34 59:c9-c12 |
| test.cpp:59:9:59:12 | * ... | 56:c13-c16 56:c31-c34 59:c9-c12 |
| test.cpp:59:17:59:20 | 0 | 53:c18-c21 56:c39-c42 59:c17-c20 |
| test.cpp:59:17:59:20 | (int)... | 53:c18-c21 56:c39-c42 59:c17-c20 |
| test.cpp:62:5:62:10 | result | 62:c5-c10 65:c10-c15 |
| test.cpp:79:11:79:14 | vals | 79:c11-c14 79:c24-c27 |
| test.cpp:80:5:80:5 | v | 79:c7-c7 80:c5-c5 |
| test.cpp:80:9:80:17 | call to getAValue | 77:c20-c28 80:c9-c17 |
| test.cpp:80:9:80:19 | (signed short)... | 77:c20-c30 80:c9-c19 |
| test.cpp:92:15:92:16 | 10 | 260:c21-c22 261:c21-c22 92:c15-c16 |
| test.cpp:93:10:93:10 | x | 92:c11-c11 93:c10-c10 |
| test.cpp:97:3:97:3 | x | 97:c3-c3 98:c3-c3 |
| test.cpp:97:3:97:5 | ... ++ | 97:c3-c5 98:c3-c5 |
| test.cpp:104:3:104:3 | x | 104:c3-c3 105:c3-c3 106:c3-c3 107:c3-c3 108:c3-c3 |
| test.cpp:107:7:107:11 | ... + ... | 107:c7-c11 108:c7-c11 |
| test.cpp:111:3:111:5 | str | 111:c3-c5 112:c3-c5 113:c3-c5 |
| test.cpp:111:9:111:11 | 1 | 110:c15-c17 111:c9-c11 |
| test.cpp:111:9:111:11 | (char *)... | 110:c15-c17 111:c9-c11 |
| test.cpp:111:9:111:11 | array to pointer conversion | 110:c15-c17 111:c9-c11 |
| test.cpp:112:9:112:11 | 2 | 112:c9-c11 113:c9-c11 |
| test.cpp:112:9:112:11 | (char *)... | 112:c9-c11 113:c9-c11 |
| test.cpp:112:9:112:11 | array to pointer conversion | 112:c9-c11 113:c9-c11 |
| test.cpp:116:3:116:3 | y | 116:c3-c3 117:c3-c3 118:c3-c3 |
| test.cpp:116:7:116:9 | 0.0 | 115:c13-c15 116:c7-c9 |
| test.cpp:116:7:116:9 | (float)... | 115:c13-c15 116:c7-c9 |
| test.cpp:117:7:117:9 | 0.5 | 117:c7-c9 118:c7-c9 |
| test.cpp:117:7:117:9 | (float)... | 117:c7-c9 118:c7-c9 |
| test.cpp:122:3:122:8 | call to test07 | 122:c3-c8 123:c3-c8 |
| test.cpp:125:3:125:11 | call to my_strspn | 125:c3-c11 126:c3-c11 |
| test.cpp:125:13:125:17 | array to pointer conversion | 125:c13-c17 126:c13-c17 129:c20-c24 |
| test.cpp:125:13:125:17 | foo | 125:c13-c17 126:c13-c17 129:c20-c24 |
| test.cpp:129:13:129:17 | array to pointer conversion | 125:c20-c24 126:c20-c24 129:c13-c17 |
| test.cpp:129:13:129:17 | bar | 125:c20-c24 126:c20-c24 129:c13-c17 |
| test.cpp:141:12:141:17 | call to getInt | 141:c12-c17 141:c29-c34 |
| test.cpp:141:23:141:26 | this | 0:c0-c0 141:c23-c26 |
| test.cpp:146:10:146:11 | ih | 146:c10-c11 146:c31-c32 |
| test.cpp:146:13:146:25 | call to getDoubledInt | 146:c13-c25 146:c34-c46 |
| test.cpp:150:3:150:3 | x | 150:c3-c3 150:c9-c9 151:c3-c3 151:c9-c9 152:c12-c12 |
| test.cpp:150:3:150:5 | ... ++ | 150:c3-c5 150:c9-c11 151:c3-c5 151:c9-c11 152:c10-c12 |
| test.cpp:150:3:150:11 | ... + ... | 150:c3-c11 151:c3-c11 |
| test.cpp:156:3:156:9 | 0 | 156:c14-c20 156:c3-c9 157:c10-c16 |
| test.cpp:171:3:171:6 | (int)... | 171:c3-c6 172:c3-c6 |
| test.cpp:171:3:171:6 | e1x1 | 171:c3-c6 172:c3-c6 |
| test.cpp:179:10:179:22 | (...) | 179:c10-c22 179:c10-c22 |
| test.cpp:179:17:179:17 | y | 179:c17-c17 179:c17-c17 |
| test.cpp:179:17:179:21 | ... + ... | 179:c17-c21 179:c17-c21 |
| test.cpp:185:17:185:17 | y | 185:c17-c17 185:c17-c17 |
| test.cpp:202:3:202:18 | sizeof(padded_t) | 202:c3-c18 204:c3-c18 |
| test.cpp:205:24:205:34 | sizeof(int) | 205:c24-c34 245:c25-c35 246:c25-c35 |
| test.cpp:206:3:206:21 | alignof(int_holder) | 206:c25-c43 206:c3-c21 |
| test.cpp:209:3:209:18 | sizeof(<expr>) | 209:c22-c37 209:c3-c18 |
| test.cpp:209:10:209:15 | holder | 209:c10-c15 209:c29-c34 |
| test.cpp:209:10:209:18 | (...) | 209:c10-c18 209:c29-c37 |
| test.cpp:209:17:209:17 | x | 209:c17-c17 209:c36-c36 |
| test.cpp:210:10:210:10 | x | 208:c27-c27 210:c10-c10 211:c11-c11 211:c24-c24 |
| test.cpp:210:10:210:11 | (...) | 210:c10-c11 211:c11-c12 211:c24-c25 |
| test.cpp:211:3:211:12 | alignof(<expr>) | 211:c16-c25 211:c3-c12 |
| test.cpp:239:3:239:12 | new | 239:c3-c12 240:c3-c12 |
| test.cpp:245:16:245:36 | new[] | 245:c16-c36 246:c16-c36 |
| test.cpp:248:3:248:28 | delete | 248:c3-c28 249:c3-c28 |
| test.cpp:248:10:248:28 | call to operator new | 248:c10-c28 249:c10-c28 |
| test.cpp:248:10:248:28 | new | 248:c10-c28 249:c10-c28 |
| test.cpp:252:10:252:32 | call to operator new | 252:c10-c32 253:c12-c34 |
| test.cpp:252:10:252:32 | new | 252:c10-c32 253:c12-c34 |
| test.cpp:254:3:254:25 | <error expr> | 248:c10-c28 249:c10-c28 250:c10-c28 252:c10-c32 253:c12-c34 254:c3-c25 255:c3-c25 257:c3-c19 258:c3-c19 260:c3-c23 261:c3-c23 |
| test.cpp:254:7:254:8 | 32 | 252:c14-c15 253:c16-c17 254:c7-c8 257:c7-c8 258:c7-c8 260:c7-c8 261:c7-c8 263:c16-c17 264:c16-c17 265:c16-c17 266:c7-c8 267:c7-c8 269:c7-c8 270:c7-c8 271:c7-c8 |
| test.cpp:254:7:254:8 | (size_t)... | 252:c14-c15 253:c16-c17 254:c7-c8 257:c7-c8 258:c7-c8 260:c7-c8 261:c7-c8 263:c16-c17 264:c16-c17 265:c16-c17 266:c7-c8 267:c7-c8 269:c7-c8 270:c7-c8 271:c7-c8 |
| test.cpp:254:11:254:14 | (void *)... | 250:c14-c17 254:c11-c14 |
| test.cpp:254:11:254:14 | ptr2 | 250:c14-c17 254:c11-c14 |
| test.cpp:255:11:255:14 | (void *)... | 248:c14-c17 249:c14-c17 252:c18-c21 253:c20-c23 255:c11-c14 |
| test.cpp:255:11:255:14 | ptr1 | 248:c14-c17 249:c14-c17 252:c18-c21 253:c20-c23 255:c11-c14 |
| test.cpp:257:3:257:19 | call to operator new | 257:c3-c19 258:c3-c19 |
| test.cpp:257:3:257:19 | new | 257:c3-c19 258:c3-c19 |
| test.cpp:260:3:260:23 | call to operator new[] | 260:c3-c23 261:c3-c23 |
| test.cpp:260:3:260:23 | new[] | 260:c3-c23 261:c3-c23 |
| test.cpp:263:3:263:32 | delete[] | 263:c3-c32 264:c3-c32 |
| test.cpp:263:12:263:32 | new[] | 263:c12-c32 264:c12-c32 |
| test.cpp:263:12:263:32 | {...} | 263:c12-c32 264:c12-c32 |
| test.cpp:266:3:266:23 | <error expr> | 263:c12-c32 264:c12-c32 265:c12-c32 266:c3-c23 267:c3-c23 269:c3-c19 270:c3-c19 271:c3-c19 |
| test.cpp:266:3:266:23 | call to operator new[] | 263:c12-c32 264:c12-c32 265:c12-c32 266:c3-c23 267:c3-c23 269:c3-c19 270:c3-c19 271:c3-c19 |
| test.cpp:269:3:269:19 | new[] | 269:c3-c19 270:c3-c19 |
| test.cpp:269:3:269:19 | {...} | 269:c3-c19 270:c3-c19 |
| test.cpp:271:15:271:15 | 3 | 265:c28-c28 271:c15-c15 35:c16-c16 |
| test.cpp:273:3:273:12 | new[] | 273:c3-c12 274:c3-c12 |
| test.cpp:273:11:273:11 | x | 273:c11-c11 274:c11-c11 |
| test.cpp:285:5:285:5 | 1 | 103:c10-c11 104:c7-c7 107:c7-c7 108:c7-c7 10:c16-c16 179:c21-c21 239:c11-c11 240:c11-c11 263:c28-c28 264:c28-c28 266:c19-c19 266:c22-c22 285:c5-c5 289:c5-c5 294:c5-c5 299:c9-c9 300:c9-c9 310:c5-c5 311:c5-c5 313:c5-c5 |
| test.cpp:286:5:286:5 | 2 | 105:c7-c7 106:c7-c7 107:c11-c11 108:c11-c11 21:c16-c16 241:c11-c11 263:c24-c24 263:c31-c31 264:c24-c24 264:c31-c31 265:c24-c24 266:c15-c15 267:c15-c15 267:c19-c19 267:c22-c22 269:c15-c15 270:c15-c15 286:c5-c5 290:c5-c5 293:c5-c5 301:c9-c9 302:c9-c9 |
| test.cpp:299:3:299:9 | throw ... | 299:c3-c9 300:c3-c9 |
| test.cpp:301:3:301:9 | throw ... | 301:c3-c9 302:c3-c9 |
| test.cpp:303:3:303:7 | re-throw exception | 303:c3-c7 304:c3-c7 |
| test.cpp:308:3:308:3 | x | 308:c3-c3 309:c3-c3 310:c3-c3 311:c3-c3 |
| test.cpp:308:3:308:6 | access to array | 308:c3-c6 309:c3-c6 |
| test.cpp:308:5:308:5 | 0 | 308:c5-c5 309:c5-c5 312:c5-c5 44:c9-c9 51:c25-c25 88:c12-c12 |
| test.cpp:310:3:310:6 | access to array | 310:c3-c6 311:c3-c6 |
| test.cpp:312:3:312:3 | y | 312:c3-c3 313:c3-c3 |
| test.cpp:320:3:320:11 | test_18_p | 320:c3-c11 321:c3-c11 |
| test.cpp:320:3:320:13 | call to expression | 320:c3-c13 321:c3-c13 |
| test.cpp:324:3:324:11 | test_19_p | 324:c3-c11 325:c3-c11 326:c3-c11 |
| test.cpp:324:3:324:17 | call to expression | 324:c3-c17 325:c3-c17 |
| test.cpp:324:13:324:13 | x | 324:c13-c13 325:c13-c13 326:c16-c16 |
| test.cpp:326:13:326:13 | y | 324:c16-c16 325:c16-c16 326:c13-c13 |
| test.cpp:330:3:330:3 | x | 330:c12-c12 330:c3-c3 331:c12-c12 331:c3-c3 332:c12-c12 332:c8-c8 333:c16-c16 333:c3-c3 |
| test.cpp:330:3:330:8 | ... == ... | 330:c3-c8 331:c3-c8 333:c3-c8 |
| test.cpp:330:3:330:16 | ... ? ... : ... | 330:c3-c16 331:c3-c16 |
| test.cpp:332:3:332:3 | y | 330:c16-c16 330:c8-c8 331:c16-c16 331:c8-c8 332:c16-c16 332:c3-c3 333:c12-c12 333:c8-c8 |

View File

@@ -0,0 +1,12 @@
import cpp
import semmle.code.cpp.valuenumbering.HashCons
from HashCons h
where strictcount(h.getAnExpr()) > 1
select
h,
strictconcat(Location loc
| loc = h.getAnExpr().getLocation()
| loc.getStartLine() +
":c" + loc.getStartColumn() + "-c" + loc.getEndColumn()
, " ")

View File

@@ -0,0 +1,8 @@
import cpp
import semmle.code.cpp.valuenumbering.HashCons
// Every expression should have exactly one HC.
// So this query should have zero results.
from Expr e
where count(hashCons(e)) != 1
select e, concat(HashCons h | h = hashCons(e) | h.getKind(), ", ")

View File

@@ -0,0 +1,334 @@
int test00(int p0, int p1) {
int x, y;
unsigned char b;
x = p0 + p1;
x = p0 + p1; // Same value as previous line. Should the assignment also be matched?
y = x;
}
int global01 = 1;
int test01(int p0, int p1) {
int x, y;
unsigned char b;
x = p0 + p1 + global01;
x = p0 + p1 + global01; // Same structure as previous line.
y = x; // x is the same as x above
}
int global02 = 2;
void change_global02(); // Just a declaration
int test02(int p0, int p1) {
int x, y;
unsigned char b;
x = p0 + p1 + global02;
change_global02();
x = p0 + p1 + global02; // same HashCons as above
y = x;
}
int global03 = 3;
void change_global03(); // Just a declaration
int test03(int p0, int p1, int* p2) {
int x, y;
unsigned char b;
x = p0 + p1 + global03;
*p2 = 0;
x = p0 + p1 + global03; // same HashCons as 43
y = x;
}
unsigned int my_strspn(const char *str, const char *chars) {
const char *ptr;
unsigned int result = 0;
while (*str != '\0') {
// check *str against chars
ptr = chars;
while ((*ptr != *str) && (*ptr != '\0')) {ptr++;}
// update
if (*ptr == '\0') { // ptr same as ptr on lines 53 and 56
break;
}
result++;
}
return result; // result same as result on line 62
}
int getAValue();
struct two_values {
signed short val1;
signed short val2;
};
void test04(two_values *vals)
{
signed short v = getAValue(); // should this match getAValue() on line 80?
if (v < vals->val1 + vals->val2) {
v = getAValue(); // should this match getAValue() on line 77?
}
}
void test05(int x, int y, void *p)
{
int v;
v = p != 0 ? x : y;
}
int regression_test00() {
int x = x = 10;
return x;
}
void test06(int x) {
x++;
x++; // x++ is matched
}
// literals
void test07() {
int x = 1;
x = 1;
x = 2;
x = 2;
x = 1 + 2;
x = 1 + 2;
char *str = "1";
str = "1";
str = "2";
str = "2";
float y = 0.0;
y = 0.0;
y = 0.5;
y = 0.5;
}
void test08() {
test07();
test07();
my_strspn("foo", "bar");
my_strspn("foo", "bar");
my_strspn("bar", "foo");
}
class IntHolder {
int myInt;
int getInt() {
return myInt;
}
public:
int getDoubledInt() {
return getInt() + this->getInt(); // getInt() and this->getInt() should be the same
}
};
int test09(IntHolder ih) {
return ih.getDoubledInt() + ih.getDoubledInt();
}
int test10(int x) {
x++ + x++;
x++ + x++; // same as above
return ++x; // ++x is not the same as x++
}
void* test11() {
nullptr == nullptr;
return nullptr;
}
enum t1 {
e1x1 = 1,
e1x2 = 2
};
enum t2 {
e2x1 = 1,
e2x2 = 2
};
int test12() {
e1x1 == e2x1;
e1x1 == e2x2;
return e1x2;
}
#define SQUARE(x) ((x) * (x))
int test13(int y) {
return SQUARE(y + 1);
}
#define SQUARE(x) x * x
int test14(int y) {
return SQUARE(y);
}
typedef struct {
int x;
char y;
} padded_t;
typedef struct {
int x;
} int_holder;
typedef unsigned long size_t;
void *malloc(size_t size);
int test15(int x) {
sizeof(padded_t);
alignof(padded_t);
sizeof(padded_t);
sizeof(int_holder) + sizeof(int);
alignof(int_holder) + alignof(int_holder);
int_holder holder = {x: x};
sizeof(holder.x) + sizeof(holder.x);
sizeof(x);
alignof(x) + alignof(x);
}
static void *operator new(size_t size, void *placement) {
return placement;
}
static void *operator new(size_t size, size_t alignment, void *placement) {
return placement;
}
static void *operator new(size_t size, size_t alignment) {
return malloc(size);
}
static void *operator new[](size_t size, void *placement) {
return placement;
}
static void *operator new[](size_t size, size_t alignment, void *placement) {
return placement;
}
static void *operator new[](size_t size, size_t alignment) {
return malloc(size);
}
void test16(int y, int z) {
new int(1);
new int(1);
new int(2);
int x;
char *ptr1 = new char[sizeof(int)];
char *ptr2 = new char[sizeof(int)];
delete new(ptr1) IntHolder;
delete new(ptr1) IntHolder;
delete new(ptr2) IntHolder;
delete new(32, ptr1) IntHolder;
delete[] new(32, ptr1) IntHolder;
new(32, ptr2) IntHolder;
new(16, ptr1) IntHolder;
new(32) IntHolder;
new(32) IntHolder;
new(32) IntHolder[10];
new(32) IntHolder[10];
delete[] new(32) int[2] {1, 2};
delete[] new(32) int[2] {1, 2};
delete[] new(32) int[2] {3, 4};
new(32) int[2] {1, 1};
new(32) int[2] {2, 2};
new(32) int[2] {};
new(32) int[2] {};
new(32) int[3] {};
new int[x];
new int[x];
new int[z];
}
typedef struct point{
int x;
int y;
} point_t;
void test17() {
point_t p1 = {
1,
2
};
point_t p2 = {
1,
2
};
point_t p3 = {
2,
1
};
}
void test18() {
throw 1;
throw 1;
throw 2;
throw 2;
throw;
throw;
}
void test19(int *x, int *y) {
x[0];
x[0];
x[1];
x[1];
y[0];
y[1];
}
void test20(int *x, int *y) {
void (*test_18_p)() = &test18;
void (*test_17_p)() = &test17;
void (*test_19_p)(int *, int *) = &test19;
test_18_p();
test_18_p();
test_17_p();
test_19_p(x, y);
test_19_p(x, y);
test_19_p(y, x);
}
void test21(int x, int y) {
x == y ? x : y;
x == y ? x : y;
y == x ? x : y;
x == y ? y : x;
}