Merge pull request #14038 from alexet/delete-ir

CPP: Add delete/delete[] calls to the IR.
This commit is contained in:
Mathias Vorreiter Pedersen
2023-08-31 09:22:34 +01:00
committed by GitHub
22 changed files with 915 additions and 125 deletions

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* `delete` and `delete[]` are now modeled as calls to the relevant `operator delete` in the IR. In the case of a dynamic delete call a new instruction `VirtualDeleteFunctionAddress` is used to represent a function that dispatches to the correct delete implementation.

View File

@@ -55,6 +55,7 @@ private newtype TOpcode =
TVariableAddress() or
TFieldAddress() or
TFunctionAddress() or
TVirtualDeleteFunctionAddress() or
TElementsAddress() or
TConstant() or
TStringConstant() or
@@ -887,6 +888,15 @@ module Opcode {
final override string toString() { result = "FunctionAddress" }
}
/**
* The `Opcode` for a `VirtualDeleteFunctionAddress`.
*
* See the `VirtualDeleteFunctionAddressInstruction` documentation for more details.
*/
class VirtualDeleteFunctionAddress extends Opcode, TVirtualDeleteFunctionAddress {
final override string toString() { result = "VirtualDeleteFunctionAddress" }
}
/**
* The `Opcode` for a `ConstantInstruction`.
*

View File

@@ -576,6 +576,22 @@ class FunctionAddressInstruction extends FunctionInstruction {
FunctionAddressInstruction() { this.getOpcode() instanceof Opcode::FunctionAddress }
}
/**
* An instruction that returns the address of a "virtual" delete function.
*
* This function, which does not actually exist in the source code, is used to
* delete objects of a class with a virtual destructor. In that case the deacllocation
* function is selected at runtime based on the dynamic type of the object. So this
* function dynamically dispatches to the correct deallocation function.
* It also should pass in the required extra arguments to the deallocation function
* which may differ dynamically depending on the type of the object.
*/
class VirtualDeleteFunctionAddressInstruction extends Instruction {
VirtualDeleteFunctionAddressInstruction() {
this.getOpcode() instanceof Opcode::VirtualDeleteFunctionAddress
}
}
/**
* An instruction that initializes a parameter of the enclosing function with the value of the
* corresponding argument passed by the caller.

View File

@@ -576,6 +576,22 @@ class FunctionAddressInstruction extends FunctionInstruction {
FunctionAddressInstruction() { this.getOpcode() instanceof Opcode::FunctionAddress }
}
/**
* An instruction that returns the address of a "virtual" delete function.
*
* This function, which does not actually exist in the source code, is used to
* delete objects of a class with a virtual destructor. In that case the deacllocation
* function is selected at runtime based on the dynamic type of the object. So this
* function dynamically dispatches to the correct deallocation function.
* It also should pass in the required extra arguments to the deallocation function
* which may differ dynamically depending on the type of the object.
*/
class VirtualDeleteFunctionAddressInstruction extends Instruction {
VirtualDeleteFunctionAddressInstruction() {
this.getOpcode() instanceof Opcode::VirtualDeleteFunctionAddress
}
}
/**
* An instruction that initializes a parameter of the enclosing function with the value of the
* corresponding argument passed by the caller.

View File

@@ -120,9 +120,9 @@ private predicate hasDefaultSideEffect(Call call, ParameterIndex i, boolean buff
}
/**
* A `Call` or `NewOrNewArrayExpr`.
* A `Call` or `NewOrNewArrayExpr` or `DeleteOrDeleteArrayExpr`.
*
* Both kinds of expression invoke a function as part of their evaluation. This class provides a
* All kinds of expression invoke a function as part of their evaluation. This class provides a
* way to treat both kinds of function similarly, and to get the invoked `Function`.
*/
class CallOrAllocationExpr extends Expr {
@@ -130,6 +130,8 @@ class CallOrAllocationExpr extends Expr {
this instanceof Call
or
this instanceof NewOrNewArrayExpr
or
this instanceof DeleteOrDeleteArrayExpr
}
/** Gets the `Function` invoked by this expression, if known. */
@@ -137,6 +139,8 @@ class CallOrAllocationExpr extends Expr {
result = this.(Call).getTarget()
or
result = this.(NewOrNewArrayExpr).getAllocator()
or
result = this.(DeleteOrDeleteArrayExpr).getDeallocator()
}
}

View File

@@ -350,6 +350,9 @@ class TranslatedCallSideEffects extends TranslatedSideEffects, TTranslatedCallSi
or
expr instanceof NewOrNewArrayExpr and
result = getTranslatedAllocatorCall(expr).getInstruction(CallTag())
or
expr instanceof DeleteOrDeleteArrayExpr and
result = getTranslatedDeleteOrDeleteArray(expr).getInstruction(CallTag())
}
}

View File

@@ -77,17 +77,17 @@ private predicate ignoreExprAndDescendants(Expr expr) {
newExpr.getInitializer().getFullyConverted() = expr
)
or
exists(DeleteOrDeleteArrayExpr deleteExpr |
// Ignore the deallocator call, because we always synthesize it.
deleteExpr.getDeallocatorCall() = expr
)
or
// Do not translate input/output variables in GNU asm statements
// getRealParent(expr) instanceof AsmStmt
// or
ignoreExprAndDescendants(getRealParent(expr)) // recursive case
or
// We do not yet translate destructors properly, so for now we ignore any
// custom deallocator call, if present.
exists(DeleteExpr deleteExpr | deleteExpr.getDeallocatorCall() = expr)
or
exists(DeleteArrayExpr deleteArrayExpr | deleteArrayExpr.getDeallocatorCall() = expr)
or
// va_start doesn't evaluate its argument, so we don't need to translate it.
exists(BuiltInVarArgsStart vaStartExpr |
vaStartExpr.getLastNamedParameter().getFullyConverted() = expr
)
@@ -104,6 +104,12 @@ private predicate ignoreExprOnly(Expr expr) {
newExpr.getAllocatorCall() = expr
)
or
exists(DeleteOrDeleteArrayExpr deleteExpr |
// Ignore the destructor call as we don't model it yet. Don't ignore
// its arguments, though, as they are the arguments to the deallocator.
deleteExpr.getDestructorCall() = expr
)
or
// The extractor deliberately emits an `ErrorExpr` as the first argument to
// the allocator call, if any, of a `NewOrNewArrayExpr`. That `ErrorExpr`
// should not be translated.
@@ -111,13 +117,6 @@ private predicate ignoreExprOnly(Expr expr) {
or
not translateFunction(getEnclosingFunction(expr)) and
not Raw::varHasIRFunc(getEnclosingVariable(expr))
or
// We do not yet translate destructors properly, so for now we ignore the
// destructor call. We do, however, translate the expression being
// destructed, and that expression can be a child of the destructor call.
exists(DeleteExpr deleteExpr | deleteExpr.getDestructorCall() = expr)
or
exists(DeleteArrayExpr deleteArrayExpr | deleteArrayExpr.getDestructorCall() = expr)
}
/**

View File

@@ -2017,6 +2017,66 @@ TranslatedAllocatorCall getTranslatedAllocatorCall(NewOrNewArrayExpr newExpr) {
result.getAst() = newExpr
}
/**
* The IR translation of a `delete` or `delete[]`
* expression.
*/
class TranslatedDeleteOrDeleteArrayExpr extends TranslatedNonConstantExpr, TranslatedCall {
override DeleteOrDeleteArrayExpr expr;
final override Instruction getFirstCallTargetInstruction() {
result = this.getInstruction(CallTargetTag())
}
final override Instruction getCallTargetResult() { result = this.getInstruction(CallTargetTag()) }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
TranslatedCall.super.hasInstruction(opcode, tag, resultType)
or
tag = CallTargetTag() and
resultType = getFunctionGLValueType() and
if exists(expr.getDeallocator())
then opcode instanceof Opcode::FunctionAddress
else opcode instanceof Opcode::VirtualDeleteFunctionAddress
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
result = TranslatedCall.super.getInstructionSuccessor(tag, kind)
or
tag = CallTargetTag() and
kind instanceof GotoEdge and
result = this.getFirstArgumentOrCallInstruction()
}
override Function getInstructionFunction(InstructionTag tag) {
tag = CallTargetTag() and result = expr.getDeallocator()
}
final override Type getCallResultType() { result = expr.getType() }
final override TranslatedExpr getQualifier() { none() }
final override predicate hasArguments() {
// All deallocator calls have at least one argument.
any()
}
final override int getNumberOfArguments() {
// We ignore the other arguments for now as we would have to synthesize them.
result = 1
}
final override TranslatedExpr getArgument(int index) {
// The only argument we define is the pointer to be deallocated.
index = 0 and
result = getTranslatedExpr(expr.getExpr().getFullyConverted())
}
}
TranslatedDeleteOrDeleteArrayExpr getTranslatedDeleteOrDeleteArray(DeleteOrDeleteArrayExpr newExpr) {
result.getAst() = newExpr
}
/**
* Abstract class implemented by any `TranslatedElement` that has a child
* expression that is a call to a constructor or destructor, in order to
@@ -2954,78 +3014,6 @@ class TranslatedNewArrayExpr extends TranslatedNewOrNewArrayExpr {
}
}
/**
* A placeholder for the translation of a `delete[]` expression.
*
* Proper translation is not yet implemented, but this stub implementation
* ensures that code following a `delete[]` is not unreachable.
*/
class TranslatedDeleteArrayExprPlaceHolder extends TranslatedSingleInstructionExpr {
override DeleteArrayExpr expr;
final override Instruction getFirstInstruction() {
result = this.getOperand().getFirstInstruction()
}
final override TranslatedElement getChild(int id) { id = 0 and result = this.getOperand() }
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
result = this.getParent().getChildSuccessor(this) and
kind instanceof GotoEdge
}
final override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getOperand() and result = this.getInstruction(OnlyInstructionTag())
}
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
none()
}
final override Opcode getOpcode() { result instanceof Opcode::NoOp }
private TranslatedExpr getOperand() {
result = getTranslatedExpr(expr.getExpr().getFullyConverted())
}
}
/**
* A placeholder for the translation of a `delete` expression.
*
* Proper translation is not yet implemented, but this stub implementation
* ensures that code following a `delete` is not unreachable.
*/
class TranslatedDeleteExprPlaceHolder extends TranslatedSingleInstructionExpr {
override DeleteExpr expr;
final override Instruction getFirstInstruction() {
result = this.getOperand().getFirstInstruction()
}
final override TranslatedElement getChild(int id) { id = 0 and result = this.getOperand() }
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
result = this.getParent().getChildSuccessor(this) and
kind instanceof GotoEdge
}
final override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getOperand() and result = this.getInstruction(OnlyInstructionTag())
}
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
none()
}
final override Opcode getOpcode() { result instanceof Opcode::NoOp }
private TranslatedExpr getOperand() {
result = getTranslatedExpr(expr.getExpr().getFullyConverted())
}
}
/**
* The IR translation of a `ConditionDeclExpr`, which represents the value of the declared variable
* after conversion to `bool` in code such as:

View File

@@ -576,6 +576,22 @@ class FunctionAddressInstruction extends FunctionInstruction {
FunctionAddressInstruction() { this.getOpcode() instanceof Opcode::FunctionAddress }
}
/**
* An instruction that returns the address of a "virtual" delete function.
*
* This function, which does not actually exist in the source code, is used to
* delete objects of a class with a virtual destructor. In that case the deacllocation
* function is selected at runtime based on the dynamic type of the object. So this
* function dynamically dispatches to the correct deallocation function.
* It also should pass in the required extra arguments to the deallocation function
* which may differ dynamically depending on the type of the object.
*/
class VirtualDeleteFunctionAddressInstruction extends Instruction {
VirtualDeleteFunctionAddressInstruction() {
this.getOpcode() instanceof Opcode::VirtualDeleteFunctionAddress
}
}
/**
* An instruction that initializes a parameter of the enclosing function with the value of the
* corresponding argument passed by the caller.

View File

@@ -15553,6 +15553,169 @@ ir.cpp:
# 2030| Type = [IntType] int
# 2030| ValueCategory = prvalue
# 2031| getStmt(2): [ReturnStmt] return ...
# 2033| [TopLevelFunction] void NewDeleteMem()
# 2033| <params>:
# 2033| getEntryPoint(): [BlockStmt] { ... }
# 2034| getStmt(0): [DeclStmt] declaration
# 2034| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
# 2034| Type = [IntPointerType] int *
# 2034| getVariable().getInitializer(): [Initializer] initializer for x
# 2034| getExpr(): [NewExpr] new
# 2034| Type = [IntPointerType] int *
# 2034| ValueCategory = prvalue
# 2035| getStmt(1): [ExprStmt] ExprStmt
# 2035| getExpr(): [AssignExpr] ... = ...
# 2035| Type = [IntType] int
# 2035| ValueCategory = lvalue
# 2035| getLValue(): [PointerDereferenceExpr] * ...
# 2035| Type = [IntType] int
# 2035| ValueCategory = lvalue
# 2035| getOperand(): [VariableAccess] x
# 2035| Type = [IntPointerType] int *
# 2035| ValueCategory = prvalue(load)
# 2035| getRValue(): [Literal] 6
# 2035| Type = [IntType] int
# 2035| Value = [Literal] 6
# 2035| ValueCategory = prvalue
# 2036| getStmt(2): [ExprStmt] ExprStmt
# 2036| getExpr(): [DeleteExpr] delete
# 2036| Type = [VoidType] void
# 2036| ValueCategory = prvalue
# 2036| getExpr(): [VariableAccess] x
# 2036| Type = [IntPointerType] int *
# 2036| ValueCategory = prvalue(load)
# 2037| getStmt(3): [ReturnStmt] return ...
# 2039| [CopyAssignmentOperator] Base2& Base2::operator=(Base2 const&)
# 2039| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Base2 &
# 2039| [Constructor] void Base2::Base2()
# 2039| <params>:
# 2039| <initializations>:
# 2039| getEntryPoint(): [BlockStmt] { ... }
# 2039| getStmt(0): [ReturnStmt] return ...
# 2039| [CopyConstructor] void Base2::Base2(Base2 const&)
# 2039| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Base2 &
# 2041| [MemberFunction] void Base2::operator delete(void*)
# 2041| <params>:
# 2041| getParameter(0): [Parameter] p
# 2041| Type = [VoidPointerType] void *
# 2041| getEntryPoint(): [BlockStmt] { ... }
# 2042| getStmt(0): [ReturnStmt] return ...
# 2043| [Destructor,VirtualFunction] void Base2::~Base2()
# 2043| <params>:
# 2043| getEntryPoint(): [BlockStmt] { ... }
# 2043| getStmt(0): [ReturnStmt] return ...
# 2043| <destructions>:
# 2046| [CopyAssignmentOperator] Derived2& Derived2::operator=(Derived2 const&)
# 2046| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Derived2 &
# 2046| [Constructor] void Derived2::Derived2()
# 2046| <params>:
# 2046| <initializations>:
# 2046| getInitializer(0): [ConstructorDirectInit] call to Base2
# 2046| Type = [VoidType] void
# 2046| ValueCategory = prvalue
# 2046| getEntryPoint(): [BlockStmt] { ... }
# 2046| getStmt(0): [ReturnStmt] return ...
# 2046| [CopyConstructor] void Derived2::Derived2(Derived2 const&)
# 2046| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Derived2 &
# 2049| [Destructor,VirtualFunction] void Derived2::~Derived2()
# 2049| <params>:
# 2049| getEntryPoint(): [BlockStmt] { ... }
# 2049| getStmt(0): [ReturnStmt] return ...
# 2049| <destructions>:
# 2049| getDestruction(0): [DestructorDirectDestruction] call to ~Base2
# 2049| Type = [VoidType] void
# 2049| ValueCategory = prvalue
# 2051| [MemberFunction] void Derived2::operator delete(void*)
# 2051| <params>:
# 2051| getParameter(0): [Parameter] p
# 2051| Type = [VoidPointerType] void *
# 2051| getEntryPoint(): [BlockStmt] { ... }
# 2052| getStmt(0): [ReturnStmt] return ...
# 2056| [TopLevelFunction] int virtual_delete()
# 2056| <params>:
# 2057| getEntryPoint(): [BlockStmt] { ... }
# 2058| getStmt(0): [DeclStmt] declaration
# 2058| getDeclarationEntry(0): [VariableDeclarationEntry] definition of b1
# 2058| Type = [PointerType] Base2 *
# 2058| getVariable().getInitializer(): [Initializer] initializer for b1
# 2058| getExpr(): [NewExpr] new
# 2058| Type = [PointerType] Base2 *
# 2058| ValueCategory = prvalue
# 2058| getInitializer(): [ConstructorCall] call to Base2
# 2058| Type = [VoidType] void
# 2058| ValueCategory = prvalue
# 2059| getStmt(1): [ExprStmt] ExprStmt
# 2059| getExpr(): [DeleteExpr] delete
# 2059| Type = [VoidType] void
# 2059| ValueCategory = prvalue
# 2059| getDeallocatorCall(): [FunctionCall] call to operator delete
# 2059| Type = [VoidType] void
# 2059| ValueCategory = prvalue
# 2059| getDestructorCall(): [DestructorCall] call to ~Base2
# 2059| Type = [VoidType] void
# 2059| ValueCategory = prvalue
# 2059| getQualifier(): [VariableAccess] b1
# 2059| Type = [PointerType] Base2 *
# 2059| ValueCategory = prvalue(load)
# 2061| getStmt(2): [DeclStmt] declaration
# 2061| getDeclarationEntry(0): [VariableDeclarationEntry] definition of b2
# 2061| Type = [PointerType] Base2 *
# 2061| getVariable().getInitializer(): [Initializer] initializer for b2
# 2061| getExpr(): [NewExpr] new
# 2061| Type = [PointerType] Derived2 *
# 2061| ValueCategory = prvalue
# 2061| getInitializer(): [ConstructorCall] call to Derived2
# 2061| Type = [VoidType] void
# 2061| ValueCategory = prvalue
# 2061| getExpr().getFullyConverted(): [CStyleCast] (Base2 *)...
# 2061| Conversion = [BaseClassConversion] base class conversion
# 2061| Type = [PointerType] Base2 *
# 2061| ValueCategory = prvalue
# 2062| getStmt(3): [ExprStmt] ExprStmt
# 2062| getExpr(): [DeleteExpr] delete
# 2062| Type = [VoidType] void
# 2062| ValueCategory = prvalue
# 2062| getDeallocatorCall(): [FunctionCall] call to operator delete
# 2062| Type = [VoidType] void
# 2062| ValueCategory = prvalue
# 2062| getDestructorCall(): [DestructorCall] call to ~Base2
# 2062| Type = [VoidType] void
# 2062| ValueCategory = prvalue
# 2062| getQualifier(): [VariableAccess] b2
# 2062| Type = [PointerType] Base2 *
# 2062| ValueCategory = prvalue(load)
# 2064| getStmt(4): [DeclStmt] declaration
# 2064| getDeclarationEntry(0): [VariableDeclarationEntry] definition of d
# 2064| Type = [PointerType] Derived2 *
# 2064| getVariable().getInitializer(): [Initializer] initializer for d
# 2064| getExpr(): [NewExpr] new
# 2064| Type = [PointerType] Derived2 *
# 2064| ValueCategory = prvalue
# 2064| getInitializer(): [ConstructorCall] call to Derived2
# 2064| Type = [VoidType] void
# 2064| ValueCategory = prvalue
# 2065| getStmt(5): [ExprStmt] ExprStmt
# 2065| getExpr(): [DeleteExpr] delete
# 2065| Type = [VoidType] void
# 2065| ValueCategory = prvalue
# 2065| getDeallocatorCall(): [FunctionCall] call to operator delete
# 2065| Type = [VoidType] void
# 2065| ValueCategory = prvalue
# 2065| getDestructorCall(): [DestructorCall] call to ~Derived2
# 2065| Type = [VoidType] void
# 2065| ValueCategory = prvalue
# 2065| getQualifier(): [VariableAccess] d
# 2065| Type = [PointerType] Derived2 *
# 2065| ValueCategory = prvalue(load)
# 2066| getStmt(6): [ReturnStmt] return ...
perf-regression.cpp:
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
# 4| <params>:

View File

@@ -2030,4 +2030,40 @@ unsigned int CommaTest(unsigned int x) {
(CommaTestHelper(x), 10);
}
void NewDeleteMem() {
int* x = new int; // No constructor
*x = 6;
delete x;
}
class Base2 {
public:
void operator delete(void* p) {
}
virtual ~Base2() {};
};
class Derived2 : public Base2 {
int i;
public:
~Derived2() {};
void operator delete(void* p) {
}
};
// Delete is kind-of virtual in these cases
int virtual_delete()
{
Base2* b1 = new Base2{};
delete b1;
Base2* b2 = new Derived2{};
delete b2;
Derived2* d = new Derived2{};
delete d;
}
// semmle-extractor-options: -std=c++17 --clang

View File

@@ -4887,10 +4887,60 @@
| ir.cpp:1011:12:1011:12 | Unary | r1011_3 |
| ir.cpp:1015:6:1015:19 | ChiPartial | partial:m1015_3 |
| ir.cpp:1015:6:1015:19 | ChiTotal | total:m1015_2 |
| ir.cpp:1015:6:1015:19 | SideEffect | m1015_3 |
| ir.cpp:1015:6:1015:19 | SideEffect | ~m1020_5 |
| ir.cpp:1016:3:1016:35 | CallTarget | func:r1016_1 |
| ir.cpp:1016:3:1016:35 | ChiPartial | partial:m1016_4 |
| ir.cpp:1016:3:1016:35 | ChiTotal | total:m1015_4 |
| ir.cpp:1016:3:1016:35 | SideEffect | ~m1015_4 |
| ir.cpp:1016:10:1016:35 | Arg(0) | 0:r1016_2 |
| ir.cpp:1017:3:1017:38 | CallTarget | func:r1017_1 |
| ir.cpp:1017:3:1017:38 | ChiPartial | partial:m1017_4 |
| ir.cpp:1017:3:1017:38 | ChiTotal | total:m1016_5 |
| ir.cpp:1017:3:1017:38 | SideEffect | ~m1016_5 |
| ir.cpp:1017:10:1017:38 | Arg(0) | 0:r1017_2 |
| ir.cpp:1018:3:1018:44 | CallTarget | func:r1018_1 |
| ir.cpp:1018:3:1018:44 | ChiPartial | partial:m1018_4 |
| ir.cpp:1018:3:1018:44 | ChiTotal | total:m1017_5 |
| ir.cpp:1018:3:1018:44 | SideEffect | ~m1017_5 |
| ir.cpp:1018:10:1018:44 | Arg(0) | 0:r1018_2 |
| ir.cpp:1019:3:1019:43 | CallTarget | func:r1019_1 |
| ir.cpp:1019:3:1019:43 | ChiPartial | partial:m1019_4 |
| ir.cpp:1019:3:1019:43 | ChiTotal | total:m1018_5 |
| ir.cpp:1019:3:1019:43 | SideEffect | ~m1018_5 |
| ir.cpp:1019:10:1019:43 | Arg(0) | 0:r1019_2 |
| ir.cpp:1020:3:1020:47 | CallTarget | func:r1020_1 |
| ir.cpp:1020:3:1020:47 | ChiPartial | partial:m1020_4 |
| ir.cpp:1020:3:1020:47 | ChiTotal | total:m1019_5 |
| ir.cpp:1020:3:1020:47 | SideEffect | ~m1019_5 |
| ir.cpp:1020:10:1020:47 | Arg(0) | 0:r1020_2 |
| ir.cpp:1024:6:1024:24 | ChiPartial | partial:m1024_3 |
| ir.cpp:1024:6:1024:24 | ChiTotal | total:m1024_2 |
| ir.cpp:1024:6:1024:24 | SideEffect | m1024_3 |
| ir.cpp:1024:6:1024:24 | SideEffect | ~m1029_5 |
| ir.cpp:1025:3:1025:37 | CallTarget | func:r1025_1 |
| ir.cpp:1025:3:1025:37 | ChiPartial | partial:m1025_4 |
| ir.cpp:1025:3:1025:37 | ChiTotal | total:m1024_4 |
| ir.cpp:1025:3:1025:37 | SideEffect | ~m1024_4 |
| ir.cpp:1025:12:1025:37 | Arg(0) | 0:r1025_2 |
| ir.cpp:1026:3:1026:40 | CallTarget | func:r1026_1 |
| ir.cpp:1026:3:1026:40 | ChiPartial | partial:m1026_4 |
| ir.cpp:1026:3:1026:40 | ChiTotal | total:m1025_5 |
| ir.cpp:1026:3:1026:40 | SideEffect | ~m1025_5 |
| ir.cpp:1026:12:1026:40 | Arg(0) | 0:r1026_2 |
| ir.cpp:1027:3:1027:46 | CallTarget | func:r1027_1 |
| ir.cpp:1027:3:1027:46 | ChiPartial | partial:m1027_4 |
| ir.cpp:1027:3:1027:46 | ChiTotal | total:m1026_5 |
| ir.cpp:1027:3:1027:46 | SideEffect | ~m1026_5 |
| ir.cpp:1027:12:1027:46 | Arg(0) | 0:r1027_2 |
| ir.cpp:1028:3:1028:45 | CallTarget | func:r1028_1 |
| ir.cpp:1028:3:1028:45 | ChiPartial | partial:m1028_4 |
| ir.cpp:1028:3:1028:45 | ChiTotal | total:m1027_5 |
| ir.cpp:1028:3:1028:45 | SideEffect | ~m1027_5 |
| ir.cpp:1028:12:1028:45 | Arg(0) | 0:r1028_2 |
| ir.cpp:1029:3:1029:49 | CallTarget | func:r1029_1 |
| ir.cpp:1029:3:1029:49 | ChiPartial | partial:m1029_4 |
| ir.cpp:1029:3:1029:49 | ChiTotal | total:m1028_5 |
| ir.cpp:1029:3:1029:49 | SideEffect | ~m1028_5 |
| ir.cpp:1029:12:1029:49 | Arg(0) | 0:r1029_2 |
| ir.cpp:1034:6:1034:20 | ChiPartial | partial:m1034_3 |
| ir.cpp:1034:6:1034:20 | ChiTotal | total:m1034_2 |
| ir.cpp:1034:6:1034:20 | SideEffect | m1034_3 |
@@ -9576,6 +9626,176 @@
| ir.cpp:2030:22:2030:22 | Arg(0) | 0:r2030_3 |
| ir.cpp:2030:22:2030:22 | Load | m2026_6 |
| ir.cpp:2030:26:2030:27 | Unary | r2030_7 |
| ir.cpp:2033:6:2033:17 | ChiPartial | partial:m2033_3 |
| ir.cpp:2033:6:2033:17 | ChiTotal | total:m2033_2 |
| ir.cpp:2033:6:2033:17 | SideEffect | ~m2036_6 |
| ir.cpp:2034:8:2034:8 | Address | &:r2034_1 |
| ir.cpp:2034:12:2034:18 | Address | &:r2034_4 |
| ir.cpp:2034:12:2034:18 | Arg(0) | 0:r2034_3 |
| ir.cpp:2034:12:2034:18 | CallTarget | func:r2034_2 |
| ir.cpp:2034:12:2034:18 | ChiPartial | partial:m2034_5 |
| ir.cpp:2034:12:2034:18 | ChiTotal | total:m2033_4 |
| ir.cpp:2034:12:2034:18 | SideEffect | ~m2033_4 |
| ir.cpp:2034:12:2034:18 | StoreValue | r2034_8 |
| ir.cpp:2034:12:2034:18 | Unary | r2034_4 |
| ir.cpp:2035:3:2035:4 | Address | &:r2035_4 |
| ir.cpp:2035:3:2035:8 | ChiPartial | partial:m2035_5 |
| ir.cpp:2035:3:2035:8 | ChiTotal | total:m2034_7 |
| ir.cpp:2035:4:2035:4 | Address | &:r2035_2 |
| ir.cpp:2035:4:2035:4 | Load | m2034_9 |
| ir.cpp:2035:4:2035:4 | Unary | r2035_3 |
| ir.cpp:2035:8:2035:8 | StoreValue | r2035_1 |
| ir.cpp:2036:3:2036:10 | CallTarget | func:r2036_1 |
| ir.cpp:2036:3:2036:10 | ChiPartial | partial:m2036_5 |
| ir.cpp:2036:3:2036:10 | ChiTotal | total:m2034_6 |
| ir.cpp:2036:3:2036:10 | SideEffect | ~m2034_6 |
| ir.cpp:2036:10:2036:10 | Address | &:r2036_2 |
| ir.cpp:2036:10:2036:10 | Arg(0) | 0:r2036_3 |
| ir.cpp:2036:10:2036:10 | Load | m2034_9 |
| ir.cpp:2039:7:2039:7 | Address | &:r2039_5 |
| ir.cpp:2039:7:2039:7 | Address | &:r2039_5 |
| ir.cpp:2039:7:2039:7 | Address | &:r2039_7 |
| ir.cpp:2039:7:2039:7 | Address | &:r2039_7 |
| ir.cpp:2039:7:2039:7 | ChiPartial | partial:m2039_3 |
| ir.cpp:2039:7:2039:7 | ChiTotal | total:m2039_2 |
| ir.cpp:2039:7:2039:7 | Load | m2039_6 |
| ir.cpp:2039:7:2039:7 | SideEffect | m2039_3 |
| ir.cpp:2039:7:2039:7 | SideEffect | m2039_8 |
| ir.cpp:2041:10:2041:24 | ChiPartial | partial:m2041_3 |
| ir.cpp:2041:10:2041:24 | ChiTotal | total:m2041_2 |
| ir.cpp:2041:10:2041:24 | SideEffect | m2041_3 |
| ir.cpp:2041:32:2041:32 | Address | &:r2041_5 |
| ir.cpp:2041:32:2041:32 | Address | &:r2041_5 |
| ir.cpp:2041:32:2041:32 | Address | &:r2041_7 |
| ir.cpp:2041:32:2041:32 | Address | &:r2041_7 |
| ir.cpp:2041:32:2041:32 | Load | m2041_6 |
| ir.cpp:2041:32:2041:32 | SideEffect | m2041_8 |
| ir.cpp:2043:13:2043:18 | Address | &:r2043_5 |
| ir.cpp:2043:13:2043:18 | Address | &:r2043_5 |
| ir.cpp:2043:13:2043:18 | Address | &:r2043_7 |
| ir.cpp:2043:13:2043:18 | Address | &:r2043_7 |
| ir.cpp:2043:13:2043:18 | ChiPartial | partial:m2043_3 |
| ir.cpp:2043:13:2043:18 | ChiTotal | total:m2043_2 |
| ir.cpp:2043:13:2043:18 | Load | m2043_6 |
| ir.cpp:2043:13:2043:18 | SideEffect | m2043_3 |
| ir.cpp:2043:13:2043:18 | SideEffect | m2043_8 |
| ir.cpp:2046:7:2046:7 | Address | &:r2046_5 |
| ir.cpp:2046:7:2046:7 | Address | &:r2046_5 |
| ir.cpp:2046:7:2046:7 | Address | &:r2046_7 |
| ir.cpp:2046:7:2046:7 | Address | &:r2046_7 |
| ir.cpp:2046:7:2046:7 | Address | &:r2046_9 |
| ir.cpp:2046:7:2046:7 | Arg(this) | this:r2046_9 |
| ir.cpp:2046:7:2046:7 | CallTarget | func:r2046_10 |
| ir.cpp:2046:7:2046:7 | ChiPartial | partial:m2046_3 |
| ir.cpp:2046:7:2046:7 | ChiPartial | partial:m2046_12 |
| ir.cpp:2046:7:2046:7 | ChiPartial | partial:m2046_14 |
| ir.cpp:2046:7:2046:7 | ChiTotal | total:m2046_2 |
| ir.cpp:2046:7:2046:7 | ChiTotal | total:m2046_4 |
| ir.cpp:2046:7:2046:7 | ChiTotal | total:m2046_8 |
| ir.cpp:2046:7:2046:7 | Load | m2046_6 |
| ir.cpp:2046:7:2046:7 | SideEffect | m2046_15 |
| ir.cpp:2046:7:2046:7 | SideEffect | ~m2046_4 |
| ir.cpp:2046:7:2046:7 | SideEffect | ~m2046_13 |
| ir.cpp:2046:7:2046:7 | Unary | m2046_6 |
| ir.cpp:2049:5:2049:13 | Address | &:r2049_5 |
| ir.cpp:2049:5:2049:13 | Address | &:r2049_5 |
| ir.cpp:2049:5:2049:13 | Address | &:r2049_7 |
| ir.cpp:2049:5:2049:13 | Address | &:r2049_7 |
| ir.cpp:2049:5:2049:13 | ChiPartial | partial:m2049_3 |
| ir.cpp:2049:5:2049:13 | ChiTotal | total:m2049_2 |
| ir.cpp:2049:5:2049:13 | Load | m2049_6 |
| ir.cpp:2049:5:2049:13 | SideEffect | m2049_8 |
| ir.cpp:2049:5:2049:13 | SideEffect | ~m2049_14 |
| ir.cpp:2049:5:2049:13 | Unary | m2049_6 |
| ir.cpp:2049:18:2049:18 | Arg(this) | this:r2049_10 |
| ir.cpp:2049:18:2049:18 | CallTarget | func:r2049_11 |
| ir.cpp:2049:18:2049:18 | ChiPartial | partial:m2049_13 |
| ir.cpp:2049:18:2049:18 | ChiTotal | total:m2049_4 |
| ir.cpp:2049:18:2049:18 | SideEffect | ~m2049_4 |
| ir.cpp:2051:10:2051:24 | ChiPartial | partial:m2051_3 |
| ir.cpp:2051:10:2051:24 | ChiTotal | total:m2051_2 |
| ir.cpp:2051:10:2051:24 | SideEffect | m2051_3 |
| ir.cpp:2051:32:2051:32 | Address | &:r2051_5 |
| ir.cpp:2051:32:2051:32 | Address | &:r2051_5 |
| ir.cpp:2051:32:2051:32 | Address | &:r2051_7 |
| ir.cpp:2051:32:2051:32 | Address | &:r2051_7 |
| ir.cpp:2051:32:2051:32 | Load | m2051_6 |
| ir.cpp:2051:32:2051:32 | SideEffect | m2051_8 |
| ir.cpp:2056:5:2056:18 | ChiPartial | partial:m2056_3 |
| ir.cpp:2056:5:2056:18 | ChiTotal | total:m2056_2 |
| ir.cpp:2058:12:2058:13 | Address | &:r2058_1 |
| ir.cpp:2058:17:2058:27 | Address | &:r2058_4 |
| ir.cpp:2058:17:2058:27 | Address | &:r2058_8 |
| ir.cpp:2058:17:2058:27 | Arg(0) | 0:r2058_3 |
| ir.cpp:2058:17:2058:27 | Arg(this) | this:r2058_8 |
| ir.cpp:2058:17:2058:27 | CallTarget | func:r2058_2 |
| ir.cpp:2058:17:2058:27 | CallTarget | func:r2058_9 |
| ir.cpp:2058:17:2058:27 | ChiPartial | partial:m2058_5 |
| ir.cpp:2058:17:2058:27 | ChiPartial | partial:m2058_11 |
| ir.cpp:2058:17:2058:27 | ChiPartial | partial:m2058_13 |
| ir.cpp:2058:17:2058:27 | ChiTotal | total:m2056_4 |
| ir.cpp:2058:17:2058:27 | ChiTotal | total:m2058_6 |
| ir.cpp:2058:17:2058:27 | ChiTotal | total:m2058_7 |
| ir.cpp:2058:17:2058:27 | SideEffect | ~m2056_4 |
| ir.cpp:2058:17:2058:27 | SideEffect | ~m2058_6 |
| ir.cpp:2058:17:2058:27 | StoreValue | r2058_8 |
| ir.cpp:2058:17:2058:27 | Unary | r2058_4 |
| ir.cpp:2059:5:2059:13 | CallTarget | func:r2059_1 |
| ir.cpp:2059:5:2059:13 | ChiPartial | partial:m2059_5 |
| ir.cpp:2059:5:2059:13 | ChiTotal | total:m2058_12 |
| ir.cpp:2059:5:2059:13 | SideEffect | ~m2058_12 |
| ir.cpp:2059:12:2059:13 | Address | &:r2059_2 |
| ir.cpp:2059:12:2059:13 | Arg(0) | 0:r2059_3 |
| ir.cpp:2059:12:2059:13 | Load | m2058_15 |
| ir.cpp:2061:12:2061:13 | Address | &:r2061_1 |
| ir.cpp:2061:17:2061:30 | Address | &:r2061_4 |
| ir.cpp:2061:17:2061:30 | Address | &:r2061_8 |
| ir.cpp:2061:17:2061:30 | Arg(0) | 0:r2061_3 |
| ir.cpp:2061:17:2061:30 | Arg(this) | this:r2061_8 |
| ir.cpp:2061:17:2061:30 | CallTarget | func:r2061_2 |
| ir.cpp:2061:17:2061:30 | CallTarget | func:r2061_9 |
| ir.cpp:2061:17:2061:30 | ChiPartial | partial:m2061_5 |
| ir.cpp:2061:17:2061:30 | ChiPartial | partial:m2061_11 |
| ir.cpp:2061:17:2061:30 | ChiPartial | partial:m2061_13 |
| ir.cpp:2061:17:2061:30 | ChiTotal | total:m2059_6 |
| ir.cpp:2061:17:2061:30 | ChiTotal | total:m2061_6 |
| ir.cpp:2061:17:2061:30 | ChiTotal | total:m2061_7 |
| ir.cpp:2061:17:2061:30 | SideEffect | ~m2059_6 |
| ir.cpp:2061:17:2061:30 | SideEffect | ~m2061_6 |
| ir.cpp:2061:17:2061:30 | StoreValue | r2061_15 |
| ir.cpp:2061:17:2061:30 | Unary | r2061_4 |
| ir.cpp:2061:17:2061:30 | Unary | r2061_8 |
| ir.cpp:2062:5:2062:13 | CallTarget | func:r2062_1 |
| ir.cpp:2062:5:2062:13 | ChiPartial | partial:m2062_5 |
| ir.cpp:2062:5:2062:13 | ChiTotal | total:m2061_12 |
| ir.cpp:2062:5:2062:13 | SideEffect | ~m2061_12 |
| ir.cpp:2062:12:2062:13 | Address | &:r2062_2 |
| ir.cpp:2062:12:2062:13 | Arg(0) | 0:r2062_3 |
| ir.cpp:2062:12:2062:13 | Load | m2061_16 |
| ir.cpp:2064:15:2064:15 | Address | &:r2064_1 |
| ir.cpp:2064:19:2064:32 | Address | &:r2064_4 |
| ir.cpp:2064:19:2064:32 | Address | &:r2064_8 |
| ir.cpp:2064:19:2064:32 | Arg(0) | 0:r2064_3 |
| ir.cpp:2064:19:2064:32 | Arg(this) | this:r2064_8 |
| ir.cpp:2064:19:2064:32 | CallTarget | func:r2064_2 |
| ir.cpp:2064:19:2064:32 | CallTarget | func:r2064_9 |
| ir.cpp:2064:19:2064:32 | ChiPartial | partial:m2064_5 |
| ir.cpp:2064:19:2064:32 | ChiPartial | partial:m2064_11 |
| ir.cpp:2064:19:2064:32 | ChiPartial | partial:m2064_13 |
| ir.cpp:2064:19:2064:32 | ChiTotal | total:m2062_6 |
| ir.cpp:2064:19:2064:32 | ChiTotal | total:m2064_6 |
| ir.cpp:2064:19:2064:32 | ChiTotal | total:m2064_7 |
| ir.cpp:2064:19:2064:32 | SideEffect | ~m2062_6 |
| ir.cpp:2064:19:2064:32 | SideEffect | ~m2064_6 |
| ir.cpp:2064:19:2064:32 | StoreValue | r2064_8 |
| ir.cpp:2064:19:2064:32 | Unary | r2064_4 |
| ir.cpp:2065:5:2065:12 | CallTarget | func:r2065_1 |
| ir.cpp:2065:5:2065:12 | ChiPartial | partial:m2065_5 |
| ir.cpp:2065:5:2065:12 | ChiTotal | total:m2064_12 |
| ir.cpp:2065:5:2065:12 | SideEffect | ~m2064_12 |
| ir.cpp:2065:12:2065:12 | Address | &:r2065_2 |
| ir.cpp:2065:12:2065:12 | Arg(0) | 0:r2065_3 |
| ir.cpp:2065:12:2065:12 | Load | m2064_15 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_7 |

View File

@@ -5663,43 +5663,63 @@ ir.cpp:
# 1015| void OperatorDelete()
# 1015| Block 0
# 1015| v1015_1(void) = EnterFunction :
# 1015| mu1015_2(unknown) = AliasedDefinition :
# 1015| mu1015_3(unknown) = InitializeNonLocal :
# 1016| r1016_1(int *) = Constant[0] :
# 1016| v1016_2(void) = NoOp :
# 1017| r1017_1(String *) = Constant[0] :
# 1017| v1017_2(void) = NoOp :
# 1018| r1018_1(SizedDealloc *) = Constant[0] :
# 1018| v1018_2(void) = NoOp :
# 1019| r1019_1(Overaligned *) = Constant[0] :
# 1019| v1019_2(void) = NoOp :
# 1020| r1020_1(PolymorphicBase *) = Constant[0] :
# 1020| v1020_2(void) = NoOp :
# 1021| v1021_1(void) = NoOp :
# 1015| v1015_4(void) = ReturnVoid :
# 1015| v1015_5(void) = AliasedUse : ~m?
# 1015| v1015_6(void) = ExitFunction :
# 1015| v1015_1(void) = EnterFunction :
# 1015| mu1015_2(unknown) = AliasedDefinition :
# 1015| mu1015_3(unknown) = InitializeNonLocal :
# 1016| r1016_1(glval<unknown>) = FunctionAddress[operator delete] :
# 1016| r1016_2(int *) = Constant[0] :
# 1016| v1016_3(void) = Call[operator delete] : func:r1016_1, 0:r1016_2
# 1016| mu1016_4(unknown) = ^CallSideEffect : ~m?
# 1017| r1017_1(glval<unknown>) = FunctionAddress[operator delete] :
# 1017| r1017_2(String *) = Constant[0] :
# 1017| v1017_3(void) = Call[operator delete] : func:r1017_1, 0:r1017_2
# 1017| mu1017_4(unknown) = ^CallSideEffect : ~m?
# 1018| r1018_1(glval<unknown>) = FunctionAddress[operator delete] :
# 1018| r1018_2(SizedDealloc *) = Constant[0] :
# 1018| v1018_3(void) = Call[operator delete] : func:r1018_1, 0:r1018_2
# 1018| mu1018_4(unknown) = ^CallSideEffect : ~m?
# 1019| r1019_1(glval<unknown>) = FunctionAddress[operator delete] :
# 1019| r1019_2(Overaligned *) = Constant[0] :
# 1019| v1019_3(void) = Call[operator delete] : func:r1019_1, 0:r1019_2
# 1019| mu1019_4(unknown) = ^CallSideEffect : ~m?
# 1020| r1020_1(glval<unknown>) = VirtualDeleteFunctionAddress :
# 1020| r1020_2(PolymorphicBase *) = Constant[0] :
# 1020| v1020_3(void) = Call[?] : func:r1020_1, 0:r1020_2
# 1020| mu1020_4(unknown) = ^CallSideEffect : ~m?
# 1021| v1021_1(void) = NoOp :
# 1015| v1015_4(void) = ReturnVoid :
# 1015| v1015_5(void) = AliasedUse : ~m?
# 1015| v1015_6(void) = ExitFunction :
# 1024| void OperatorDeleteArray()
# 1024| Block 0
# 1024| v1024_1(void) = EnterFunction :
# 1024| mu1024_2(unknown) = AliasedDefinition :
# 1024| mu1024_3(unknown) = InitializeNonLocal :
# 1025| r1025_1(int *) = Constant[0] :
# 1025| v1025_2(void) = NoOp :
# 1026| r1026_1(String *) = Constant[0] :
# 1026| v1026_2(void) = NoOp :
# 1027| r1027_1(SizedDealloc *) = Constant[0] :
# 1027| v1027_2(void) = NoOp :
# 1028| r1028_1(Overaligned *) = Constant[0] :
# 1028| v1028_2(void) = NoOp :
# 1029| r1029_1(PolymorphicBase *) = Constant[0] :
# 1029| v1029_2(void) = NoOp :
# 1030| v1030_1(void) = NoOp :
# 1024| v1024_4(void) = ReturnVoid :
# 1024| v1024_5(void) = AliasedUse : ~m?
# 1024| v1024_6(void) = ExitFunction :
# 1024| v1024_1(void) = EnterFunction :
# 1024| mu1024_2(unknown) = AliasedDefinition :
# 1024| mu1024_3(unknown) = InitializeNonLocal :
# 1025| r1025_1(glval<unknown>) = FunctionAddress[operator delete[]] :
# 1025| r1025_2(int *) = Constant[0] :
# 1025| v1025_3(void) = Call[operator delete[]] : func:r1025_1, 0:r1025_2
# 1025| mu1025_4(unknown) = ^CallSideEffect : ~m?
# 1026| r1026_1(glval<unknown>) = FunctionAddress[operator delete[]] :
# 1026| r1026_2(String *) = Constant[0] :
# 1026| v1026_3(void) = Call[operator delete[]] : func:r1026_1, 0:r1026_2
# 1026| mu1026_4(unknown) = ^CallSideEffect : ~m?
# 1027| r1027_1(glval<unknown>) = FunctionAddress[operator delete[]] :
# 1027| r1027_2(SizedDealloc *) = Constant[0] :
# 1027| v1027_3(void) = Call[operator delete[]] : func:r1027_1, 0:r1027_2
# 1027| mu1027_4(unknown) = ^CallSideEffect : ~m?
# 1028| r1028_1(glval<unknown>) = FunctionAddress[operator delete[]] :
# 1028| r1028_2(Overaligned *) = Constant[0] :
# 1028| v1028_3(void) = Call[operator delete[]] : func:r1028_1, 0:r1028_2
# 1028| mu1028_4(unknown) = ^CallSideEffect : ~m?
# 1029| r1029_1(glval<unknown>) = FunctionAddress[operator delete[]] :
# 1029| r1029_2(PolymorphicBase *) = Constant[0] :
# 1029| v1029_3(void) = Call[operator delete[]] : func:r1029_1, 0:r1029_2
# 1029| mu1029_4(unknown) = ^CallSideEffect : ~m?
# 1030| v1030_1(void) = NoOp :
# 1024| v1024_4(void) = ReturnVoid :
# 1024| v1024_5(void) = AliasedUse : ~m?
# 1024| v1024_6(void) = ExitFunction :
# 1034| void EmptyStructInit()
# 1034| Block 0
@@ -11091,6 +11111,198 @@ ir.cpp:
# 2028| mu2028_13(unsigned int) = Store[#temp2028:7] : &:r2028_12, r2030_8
#-----| Goto -> Block 2
# 2033| void NewDeleteMem()
# 2033| Block 0
# 2033| v2033_1(void) = EnterFunction :
# 2033| mu2033_2(unknown) = AliasedDefinition :
# 2033| mu2033_3(unknown) = InitializeNonLocal :
# 2034| r2034_1(glval<int *>) = VariableAddress[x] :
# 2034| r2034_2(glval<unknown>) = FunctionAddress[operator new] :
# 2034| r2034_3(unsigned long) = Constant[4] :
# 2034| r2034_4(void *) = Call[operator new] : func:r2034_2, 0:r2034_3
# 2034| mu2034_5(unknown) = ^CallSideEffect : ~m?
# 2034| mu2034_6(unknown) = ^InitializeDynamicAllocation : &:r2034_4
# 2034| r2034_7(int *) = Convert : r2034_4
# 2034| mu2034_8(int *) = Store[x] : &:r2034_1, r2034_7
# 2035| r2035_1(int) = Constant[6] :
# 2035| r2035_2(glval<int *>) = VariableAddress[x] :
# 2035| r2035_3(int *) = Load[x] : &:r2035_2, ~m?
# 2035| r2035_4(glval<int>) = CopyValue : r2035_3
# 2035| mu2035_5(int) = Store[?] : &:r2035_4, r2035_1
# 2036| r2036_1(glval<unknown>) = FunctionAddress[operator delete] :
# 2036| r2036_2(glval<int *>) = VariableAddress[x] :
# 2036| r2036_3(int *) = Load[x] : &:r2036_2, ~m?
# 2036| v2036_4(void) = Call[operator delete] : func:r2036_1, 0:r2036_3
# 2036| mu2036_5(unknown) = ^CallSideEffect : ~m?
# 2037| v2037_1(void) = NoOp :
# 2033| v2033_4(void) = ReturnVoid :
# 2033| v2033_5(void) = AliasedUse : ~m?
# 2033| v2033_6(void) = ExitFunction :
# 2039| void Base2::Base2()
# 2039| Block 0
# 2039| v2039_1(void) = EnterFunction :
# 2039| mu2039_2(unknown) = AliasedDefinition :
# 2039| mu2039_3(unknown) = InitializeNonLocal :
# 2039| r2039_4(glval<unknown>) = VariableAddress[#this] :
# 2039| mu2039_5(glval<Base2>) = InitializeParameter[#this] : &:r2039_4
# 2039| r2039_6(glval<Base2>) = Load[#this] : &:r2039_4, ~m?
# 2039| mu2039_7(Base2) = InitializeIndirection[#this] : &:r2039_6
# 2039| v2039_8(void) = NoOp :
# 2039| v2039_9(void) = ReturnIndirection[#this] : &:r2039_6, ~m?
# 2039| v2039_10(void) = ReturnVoid :
# 2039| v2039_11(void) = AliasedUse : ~m?
# 2039| v2039_12(void) = ExitFunction :
# 2041| void Base2::operator delete(void*)
# 2041| Block 0
# 2041| v2041_1(void) = EnterFunction :
# 2041| mu2041_2(unknown) = AliasedDefinition :
# 2041| mu2041_3(unknown) = InitializeNonLocal :
# 2041| r2041_4(glval<void *>) = VariableAddress[p] :
# 2041| mu2041_5(void *) = InitializeParameter[p] : &:r2041_4
# 2041| r2041_6(void *) = Load[p] : &:r2041_4, ~m?
# 2041| mu2041_7(unknown) = InitializeIndirection[p] : &:r2041_6
# 2042| v2042_1(void) = NoOp :
# 2041| v2041_8(void) = ReturnIndirection[p] : &:r2041_6, ~m?
# 2041| v2041_9(void) = ReturnVoid :
# 2041| v2041_10(void) = AliasedUse : ~m?
# 2041| v2041_11(void) = ExitFunction :
# 2043| void Base2::~Base2()
# 2043| Block 0
# 2043| v2043_1(void) = EnterFunction :
# 2043| mu2043_2(unknown) = AliasedDefinition :
# 2043| mu2043_3(unknown) = InitializeNonLocal :
# 2043| r2043_4(glval<unknown>) = VariableAddress[#this] :
# 2043| mu2043_5(glval<Base2>) = InitializeParameter[#this] : &:r2043_4
# 2043| r2043_6(glval<Base2>) = Load[#this] : &:r2043_4, ~m?
# 2043| mu2043_7(Base2) = InitializeIndirection[#this] : &:r2043_6
# 2043| v2043_8(void) = NoOp :
# 2043| v2043_9(void) = ReturnIndirection[#this] : &:r2043_6, ~m?
# 2043| v2043_10(void) = ReturnVoid :
# 2043| v2043_11(void) = AliasedUse : ~m?
# 2043| v2043_12(void) = ExitFunction :
# 2046| void Derived2::Derived2()
# 2046| Block 0
# 2046| v2046_1(void) = EnterFunction :
# 2046| mu2046_2(unknown) = AliasedDefinition :
# 2046| mu2046_3(unknown) = InitializeNonLocal :
# 2046| r2046_4(glval<unknown>) = VariableAddress[#this] :
# 2046| mu2046_5(glval<Derived2>) = InitializeParameter[#this] : &:r2046_4
# 2046| r2046_6(glval<Derived2>) = Load[#this] : &:r2046_4, ~m?
# 2046| mu2046_7(Derived2) = InitializeIndirection[#this] : &:r2046_6
# 2046| r2046_8(glval<Base2>) = ConvertToNonVirtualBase[Derived2 : Base2] : mu2046_5
# 2046| r2046_9(glval<unknown>) = FunctionAddress[Base2] :
# 2046| v2046_10(void) = Call[Base2] : func:r2046_9, this:r2046_8
# 2046| mu2046_11(unknown) = ^CallSideEffect : ~m?
# 2046| mu2046_12(Base2) = ^IndirectMayWriteSideEffect[-1] : &:r2046_8
# 2046| v2046_13(void) = NoOp :
# 2046| v2046_14(void) = ReturnIndirection[#this] : &:r2046_6, ~m?
# 2046| v2046_15(void) = ReturnVoid :
# 2046| v2046_16(void) = AliasedUse : ~m?
# 2046| v2046_17(void) = ExitFunction :
# 2049| void Derived2::~Derived2()
# 2049| Block 0
# 2049| v2049_1(void) = EnterFunction :
# 2049| mu2049_2(unknown) = AliasedDefinition :
# 2049| mu2049_3(unknown) = InitializeNonLocal :
# 2049| r2049_4(glval<unknown>) = VariableAddress[#this] :
# 2049| mu2049_5(glval<Derived2>) = InitializeParameter[#this] : &:r2049_4
# 2049| r2049_6(glval<Derived2>) = Load[#this] : &:r2049_4, ~m?
# 2049| mu2049_7(Derived2) = InitializeIndirection[#this] : &:r2049_6
# 2049| v2049_8(void) = NoOp :
# 2049| r2049_9(glval<Base2>) = ConvertToNonVirtualBase[Derived2 : Base2] : mu2049_5
# 2049| r2049_10(glval<unknown>) = FunctionAddress[~Base2] :
# 2049| v2049_11(void) = Call[~Base2] : func:r2049_10, this:r2049_9
# 2049| mu2049_12(unknown) = ^CallSideEffect : ~m?
# 2049| v2049_13(void) = ReturnIndirection[#this] : &:r2049_6, ~m?
# 2049| v2049_14(void) = ReturnVoid :
# 2049| v2049_15(void) = AliasedUse : ~m?
# 2049| v2049_16(void) = ExitFunction :
# 2051| void Derived2::operator delete(void*)
# 2051| Block 0
# 2051| v2051_1(void) = EnterFunction :
# 2051| mu2051_2(unknown) = AliasedDefinition :
# 2051| mu2051_3(unknown) = InitializeNonLocal :
# 2051| r2051_4(glval<void *>) = VariableAddress[p] :
# 2051| mu2051_5(void *) = InitializeParameter[p] : &:r2051_4
# 2051| r2051_6(void *) = Load[p] : &:r2051_4, ~m?
# 2051| mu2051_7(unknown) = InitializeIndirection[p] : &:r2051_6
# 2052| v2052_1(void) = NoOp :
# 2051| v2051_8(void) = ReturnIndirection[p] : &:r2051_6, ~m?
# 2051| v2051_9(void) = ReturnVoid :
# 2051| v2051_10(void) = AliasedUse : ~m?
# 2051| v2051_11(void) = ExitFunction :
# 2056| int virtual_delete()
# 2056| Block 0
# 2056| v2056_1(void) = EnterFunction :
# 2056| mu2056_2(unknown) = AliasedDefinition :
# 2056| mu2056_3(unknown) = InitializeNonLocal :
# 2058| r2058_1(glval<Base2 *>) = VariableAddress[b1] :
# 2058| r2058_2(glval<unknown>) = FunctionAddress[operator new] :
# 2058| r2058_3(unsigned long) = Constant[8] :
# 2058| r2058_4(void *) = Call[operator new] : func:r2058_2, 0:r2058_3
# 2058| mu2058_5(unknown) = ^CallSideEffect : ~m?
# 2058| mu2058_6(unknown) = ^InitializeDynamicAllocation : &:r2058_4
# 2058| r2058_7(Base2 *) = Convert : r2058_4
# 2058| r2058_8(glval<unknown>) = FunctionAddress[Base2] :
# 2058| v2058_9(void) = Call[Base2] : func:r2058_8, this:r2058_7
# 2058| mu2058_10(unknown) = ^CallSideEffect : ~m?
# 2058| mu2058_11(Base2) = ^IndirectMayWriteSideEffect[-1] : &:r2058_7
# 2058| mu2058_12(Base2 *) = Store[b1] : &:r2058_1, r2058_7
# 2059| r2059_1(glval<unknown>) = VirtualDeleteFunctionAddress :
# 2059| r2059_2(glval<Base2 *>) = VariableAddress[b1] :
# 2059| r2059_3(Base2 *) = Load[b1] : &:r2059_2, ~m?
# 2059| v2059_4(void) = Call[?] : func:r2059_1, 0:r2059_3
# 2059| mu2059_5(unknown) = ^CallSideEffect : ~m?
# 2061| r2061_1(glval<Base2 *>) = VariableAddress[b2] :
# 2061| r2061_2(glval<unknown>) = FunctionAddress[operator new] :
# 2061| r2061_3(unsigned long) = Constant[16] :
# 2061| r2061_4(void *) = Call[operator new] : func:r2061_2, 0:r2061_3
# 2061| mu2061_5(unknown) = ^CallSideEffect : ~m?
# 2061| mu2061_6(unknown) = ^InitializeDynamicAllocation : &:r2061_4
# 2061| r2061_7(Derived2 *) = Convert : r2061_4
# 2061| r2061_8(glval<unknown>) = FunctionAddress[Derived2] :
# 2061| v2061_9(void) = Call[Derived2] : func:r2061_8, this:r2061_7
# 2061| mu2061_10(unknown) = ^CallSideEffect : ~m?
# 2061| mu2061_11(Derived2) = ^IndirectMayWriteSideEffect[-1] : &:r2061_7
# 2061| r2061_12(Base2 *) = ConvertToNonVirtualBase[Derived2 : Base2] : r2061_7
# 2061| mu2061_13(Base2 *) = Store[b2] : &:r2061_1, r2061_12
# 2062| r2062_1(glval<unknown>) = VirtualDeleteFunctionAddress :
# 2062| r2062_2(glval<Base2 *>) = VariableAddress[b2] :
# 2062| r2062_3(Base2 *) = Load[b2] : &:r2062_2, ~m?
# 2062| v2062_4(void) = Call[?] : func:r2062_1, 0:r2062_3
# 2062| mu2062_5(unknown) = ^CallSideEffect : ~m?
# 2064| r2064_1(glval<Derived2 *>) = VariableAddress[d] :
# 2064| r2064_2(glval<unknown>) = FunctionAddress[operator new] :
# 2064| r2064_3(unsigned long) = Constant[16] :
# 2064| r2064_4(void *) = Call[operator new] : func:r2064_2, 0:r2064_3
# 2064| mu2064_5(unknown) = ^CallSideEffect : ~m?
# 2064| mu2064_6(unknown) = ^InitializeDynamicAllocation : &:r2064_4
# 2064| r2064_7(Derived2 *) = Convert : r2064_4
# 2064| r2064_8(glval<unknown>) = FunctionAddress[Derived2] :
# 2064| v2064_9(void) = Call[Derived2] : func:r2064_8, this:r2064_7
# 2064| mu2064_10(unknown) = ^CallSideEffect : ~m?
# 2064| mu2064_11(Derived2) = ^IndirectMayWriteSideEffect[-1] : &:r2064_7
# 2064| mu2064_12(Derived2 *) = Store[d] : &:r2064_1, r2064_7
# 2065| r2065_1(glval<unknown>) = VirtualDeleteFunctionAddress :
# 2065| r2065_2(glval<Derived2 *>) = VariableAddress[d] :
# 2065| r2065_3(Derived2 *) = Load[d] : &:r2065_2, ~m?
# 2065| v2065_4(void) = Call[?] : func:r2065_1, 0:r2065_3
# 2065| mu2065_5(unknown) = ^CallSideEffect : ~m?
# 2066| v2066_1(void) = Unreached :
# 2056| Block 1
# 2056| r2056_4(glval<int>) = VariableAddress[#return] :
# 2056| v2056_5(void) = ReturnValue : &:r2056_4, ~m?
# 2056| v2056_6(void) = AliasedUse : ~m?
# 2056| v2056_7(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0

View File

@@ -18,6 +18,7 @@ edges
| test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a |
| test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a |
| test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a |
| test_free.cpp:83:12:83:12 | a | test_free.cpp:85:12:85:12 | a |
| test_free.cpp:101:10:101:10 | a | test_free.cpp:103:10:103:10 | a |
| test_free.cpp:128:10:128:11 | * ... | test_free.cpp:129:10:129:11 | * ... |
| test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a |
@@ -28,6 +29,8 @@ edges
| test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a |
| test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a |
| test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a |
| test_free.cpp:252:7:252:7 | p | test_free.cpp:255:10:255:10 | p |
| test_free.cpp:260:9:260:9 | p | test_free.cpp:263:12:263:12 | p |
nodes
| test_free.cpp:11:10:11:10 | a | semmle.label | a |
| test_free.cpp:11:10:11:10 | a | semmle.label | a |
@@ -51,6 +54,8 @@ nodes
| test_free.cpp:69:10:69:10 | a | semmle.label | a |
| test_free.cpp:72:14:72:14 | a | semmle.label | a |
| test_free.cpp:72:14:72:14 | a | semmle.label | a |
| test_free.cpp:83:12:83:12 | a | semmle.label | a |
| test_free.cpp:85:12:85:12 | a | semmle.label | a |
| test_free.cpp:101:10:101:10 | a | semmle.label | a |
| test_free.cpp:103:10:103:10 | a | semmle.label | a |
| test_free.cpp:128:10:128:11 | * ... | semmle.label | * ... |
@@ -63,6 +68,10 @@ nodes
| test_free.cpp:207:10:207:10 | a | semmle.label | a |
| test_free.cpp:209:10:209:10 | a | semmle.label | a |
| test_free.cpp:209:10:209:10 | a | semmle.label | a |
| test_free.cpp:252:7:252:7 | p | semmle.label | p |
| test_free.cpp:255:10:255:10 | p | semmle.label | p |
| test_free.cpp:260:9:260:9 | p | semmle.label | p |
| test_free.cpp:263:12:263:12 | p | semmle.label | p |
subpaths
#select
| test_free.cpp:14:10:14:10 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
@@ -84,6 +93,7 @@ subpaths
| test_free.cpp:72:14:72:14 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
| test_free.cpp:72:14:72:14 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
| test_free.cpp:72:14:72:14 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
| test_free.cpp:85:12:85:12 | a | test_free.cpp:83:12:83:12 | a | test_free.cpp:85:12:85:12 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:83:5:83:13 | delete | delete |
| test_free.cpp:103:10:103:10 | a | test_free.cpp:101:10:101:10 | a | test_free.cpp:103:10:103:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:101:5:101:8 | call to free | call to free |
| test_free.cpp:129:10:129:11 | * ... | test_free.cpp:128:10:128:11 | * ... | test_free.cpp:129:10:129:11 | * ... | Memory pointed to by '* ...' may already have been freed by $@. | test_free.cpp:128:5:128:8 | call to free | call to free |
| test_free.cpp:154:10:154:10 | a | test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:152:22:152:25 | call to free | call to free |
@@ -94,3 +104,5 @@ subpaths
| test_free.cpp:209:10:209:10 | a | test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:207:5:207:8 | call to free | call to free |
| test_free.cpp:209:10:209:10 | a | test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:207:5:207:8 | call to free | call to free |
| test_free.cpp:209:10:209:10 | a | test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:207:5:207:8 | call to free | call to free |
| test_free.cpp:255:10:255:10 | p | test_free.cpp:252:7:252:7 | p | test_free.cpp:255:10:255:10 | p | Memory pointed to by 'p' may already have been freed by $@. | test_free.cpp:252:2:252:5 | call to free | call to free |
| test_free.cpp:263:12:263:12 | p | test_free.cpp:260:9:260:9 | p | test_free.cpp:263:12:263:12 | p | Memory pointed to by 'p' may already have been freed by $@. | test_free.cpp:260:2:260:9 | delete | delete |

View File

@@ -92,6 +92,10 @@
| test_free.cpp:233:14:233:15 | * ... |
| test_free.cpp:239:14:239:15 | * ... |
| test_free.cpp:245:10:245:11 | * ... |
| test_free.cpp:252:7:252:7 | p |
| test_free.cpp:255:10:255:10 | p |
| test_free.cpp:260:9:260:9 | p |
| test_free.cpp:263:12:263:12 | p |
| virtual.cpp:18:10:18:10 | a |
| virtual.cpp:19:10:19:10 | c |
| virtual.cpp:38:10:38:10 | b |

View File

@@ -12,3 +12,5 @@
| test.cpp:157:3:157:26 | new[] | This memory is never freed. |
| test.cpp:169:14:169:19 | call to strdup | This memory is never freed. |
| test_free.cpp:167:15:167:21 | call to realloc | This memory is never freed. |
| test_free.cpp:253:14:253:19 | call to malloc | This memory is never freed. |
| test_free.cpp:261:6:261:12 | new | This memory is never freed. |

View File

@@ -9,6 +9,7 @@ edges
| test_free.cpp:44:27:44:27 | a | test_free.cpp:45:5:45:5 | a |
| test_free.cpp:69:10:69:10 | a | test_free.cpp:71:9:71:9 | a |
| test_free.cpp:69:10:69:10 | a | test_free.cpp:71:9:71:9 | a |
| test_free.cpp:83:12:83:12 | a | test_free.cpp:84:5:84:5 | a |
| test_free.cpp:90:10:90:10 | a | test_free.cpp:91:5:91:5 | a |
| test_free.cpp:90:10:90:10 | a | test_free.cpp:91:5:91:5 | a |
| test_free.cpp:95:10:95:10 | a | test_free.cpp:96:9:96:9 | a |
@@ -27,6 +28,8 @@ edges
| test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... |
| test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... |
| test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... |
| test_free.cpp:252:7:252:7 | p | test_free.cpp:254:6:254:6 | p |
| test_free.cpp:260:9:260:9 | p | test_free.cpp:262:6:262:6 | p |
nodes
| test_free.cpp:11:10:11:10 | a | semmle.label | a |
| test_free.cpp:11:10:11:10 | a | semmle.label | a |
@@ -41,6 +44,8 @@ nodes
| test_free.cpp:69:10:69:10 | a | semmle.label | a |
| test_free.cpp:69:10:69:10 | a | semmle.label | a |
| test_free.cpp:71:9:71:9 | a | semmle.label | a |
| test_free.cpp:83:12:83:12 | a | semmle.label | a |
| test_free.cpp:84:5:84:5 | a | semmle.label | a |
| test_free.cpp:90:10:90:10 | a | semmle.label | a |
| test_free.cpp:90:10:90:10 | a | semmle.label | a |
| test_free.cpp:91:5:91:5 | a | semmle.label | a |
@@ -63,6 +68,10 @@ nodes
| test_free.cpp:245:10:245:11 | * ... | semmle.label | * ... |
| test_free.cpp:246:9:246:10 | * ... | semmle.label | * ... |
| test_free.cpp:246:9:246:10 | * ... | semmle.label | * ... |
| test_free.cpp:252:7:252:7 | p | semmle.label | p |
| test_free.cpp:254:6:254:6 | p | semmle.label | p |
| test_free.cpp:260:9:260:9 | p | semmle.label | p |
| test_free.cpp:262:6:262:6 | p | semmle.label | p |
subpaths
#select
| test_free.cpp:12:5:12:5 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:12:5:12:5 | a | Memory may have been previously freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
@@ -75,6 +84,7 @@ subpaths
| test_free.cpp:45:5:45:5 | a | test_free.cpp:44:27:44:27 | a | test_free.cpp:45:5:45:5 | a | Memory may have been previously freed by $@. | test_free.cpp:44:22:44:25 | call to free | call to free |
| test_free.cpp:71:9:71:9 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:71:9:71:9 | a | Memory may have been previously freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
| test_free.cpp:71:9:71:9 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:71:9:71:9 | a | Memory may have been previously freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
| test_free.cpp:84:5:84:5 | a | test_free.cpp:83:12:83:12 | a | test_free.cpp:84:5:84:5 | a | Memory may have been previously freed by $@. | test_free.cpp:83:5:83:13 | delete | delete |
| test_free.cpp:91:5:91:5 | a | test_free.cpp:90:10:90:10 | a | test_free.cpp:91:5:91:5 | a | Memory may have been previously freed by $@. | test_free.cpp:90:5:90:8 | call to free | call to free |
| test_free.cpp:91:5:91:5 | a | test_free.cpp:90:10:90:10 | a | test_free.cpp:91:5:91:5 | a | Memory may have been previously freed by $@. | test_free.cpp:90:5:90:8 | call to free | call to free |
| test_free.cpp:96:9:96:9 | a | test_free.cpp:95:10:95:10 | a | test_free.cpp:96:9:96:9 | a | Memory may have been previously freed by $@. | test_free.cpp:95:5:95:8 | call to free | call to free |
@@ -93,3 +103,5 @@ subpaths
| test_free.cpp:246:9:246:10 | * ... | test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:245:5:245:8 | call to free | call to free |
| test_free.cpp:246:9:246:10 | * ... | test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:245:5:245:8 | call to free | call to free |
| test_free.cpp:246:9:246:10 | * ... | test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:245:5:245:8 | call to free | call to free |
| test_free.cpp:254:6:254:6 | p | test_free.cpp:252:7:252:7 | p | test_free.cpp:254:6:254:6 | p | Memory may have been previously freed by $@. | test_free.cpp:252:2:252:5 | call to free | call to free |
| test_free.cpp:262:6:262:6 | p | test_free.cpp:260:9:260:9 | p | test_free.cpp:262:6:262:6 | p | Memory may have been previously freed by $@. | test_free.cpp:260:2:260:9 | delete | delete |

View File

@@ -81,8 +81,8 @@ public:
void test_new1() {
A *a = new A();
delete(a);
a->f(); // BAD [NOT DETECTED]
delete(a); // BAD [NOT DETECTED]
a->f(); // BAD
delete(a); // BAD
}
void test_dereference1(A *a) {
@@ -244,4 +244,21 @@ void test_loop3(char ** a, char ** b) {
void test_deref(char **a) {
free(*a);
use(*a); // GOOD [FALSE POSITIVE]
}
// Refs
void test_ref(char *&p) {
free(p);
p = (char *)malloc(sizeof(char)*10);
use(p); // GOOD [FALSE POSITIVE]
free(p); // GOOD [FALSE POSITIVE]
}
void test_ref_delete(int *&p) {
delete p;
p = new int;
use(p); // GOOD [FALSE POSITIVE]
delete p; // GOOD [FALSE POSITIVE]
}

View File

@@ -11,6 +11,9 @@ edges
| test.cpp:127:7:127:10 | data | test.cpp:130:6:130:9 | data |
| test.cpp:138:7:138:10 | data | test.cpp:141:6:141:9 | data |
| test.cpp:138:7:138:10 | data | test.cpp:141:6:141:9 | data |
| test.cpp:164:9:164:9 | c | test.cpp:165:2:165:2 | c |
| test.cpp:164:9:164:9 | c | test.cpp:166:3:166:4 | * ... |
| test.cpp:164:9:164:9 | c | test.cpp:166:4:166:4 | c |
| test.cpp:181:7:181:10 | data | test.cpp:186:6:186:9 | data |
| test.cpp:181:7:181:10 | data | test.cpp:186:6:186:9 | data |
| test.cpp:192:7:192:10 | data | test.cpp:197:6:197:9 | data |
@@ -19,6 +22,7 @@ edges
| test.cpp:203:7:203:10 | data | test.cpp:209:6:209:9 | data |
| test.cpp:207:8:207:11 | data | test.cpp:209:6:209:9 | data |
| test.cpp:207:8:207:11 | data | test.cpp:209:6:209:9 | data |
| test.cpp:216:9:216:9 | x | test.cpp:217:6:217:6 | x |
nodes
| test.cpp:39:7:39:10 | data | semmle.label | data |
| test.cpp:39:7:39:10 | data | semmle.label | data |
@@ -38,6 +42,10 @@ nodes
| test.cpp:138:7:138:10 | data | semmle.label | data |
| test.cpp:138:7:138:10 | data | semmle.label | data |
| test.cpp:141:6:141:9 | data | semmle.label | data |
| test.cpp:164:9:164:9 | c | semmle.label | c |
| test.cpp:165:2:165:2 | c | semmle.label | c |
| test.cpp:166:3:166:4 | * ... | semmle.label | * ... |
| test.cpp:166:4:166:4 | c | semmle.label | c |
| test.cpp:181:7:181:10 | data | semmle.label | data |
| test.cpp:181:7:181:10 | data | semmle.label | data |
| test.cpp:186:6:186:9 | data | semmle.label | data |
@@ -50,6 +58,8 @@ nodes
| test.cpp:207:8:207:11 | data | semmle.label | data |
| test.cpp:209:6:209:9 | data | semmle.label | data |
| test.cpp:209:6:209:9 | data | semmle.label | data |
| test.cpp:216:9:216:9 | x | semmle.label | x |
| test.cpp:217:6:217:6 | x | semmle.label | x |
subpaths
#select
| test.cpp:41:6:41:9 | data | test.cpp:39:7:39:10 | data | test.cpp:41:6:41:9 | data | Memory may have been previously freed by $@. | test.cpp:39:2:39:5 | call to free | call to free |
@@ -64,6 +74,9 @@ subpaths
| test.cpp:130:6:130:9 | data | test.cpp:127:7:127:10 | data | test.cpp:130:6:130:9 | data | Memory may have been previously freed by $@. | test.cpp:127:2:127:5 | call to free | call to free |
| test.cpp:141:6:141:9 | data | test.cpp:138:7:138:10 | data | test.cpp:141:6:141:9 | data | Memory may have been previously freed by $@. | test.cpp:138:2:138:5 | call to free | call to free |
| test.cpp:141:6:141:9 | data | test.cpp:138:7:138:10 | data | test.cpp:141:6:141:9 | data | Memory may have been previously freed by $@. | test.cpp:138:2:138:5 | call to free | call to free |
| test.cpp:165:2:165:2 | c | test.cpp:164:9:164:9 | c | test.cpp:165:2:165:2 | c | Memory may have been previously freed by $@. | test.cpp:164:2:164:10 | delete | delete |
| test.cpp:166:3:166:4 | * ... | test.cpp:164:9:164:9 | c | test.cpp:166:3:166:4 | * ... | Memory may have been previously freed by $@. | test.cpp:164:2:164:10 | delete | delete |
| test.cpp:166:4:166:4 | c | test.cpp:164:9:164:9 | c | test.cpp:166:4:166:4 | c | Memory may have been previously freed by $@. | test.cpp:164:2:164:10 | delete | delete |
| test.cpp:186:6:186:9 | data | test.cpp:181:7:181:10 | data | test.cpp:186:6:186:9 | data | Memory may have been previously freed by $@. | test.cpp:181:2:181:5 | call to free | call to free |
| test.cpp:186:6:186:9 | data | test.cpp:181:7:181:10 | data | test.cpp:186:6:186:9 | data | Memory may have been previously freed by $@. | test.cpp:181:2:181:5 | call to free | call to free |
| test.cpp:197:6:197:9 | data | test.cpp:192:7:192:10 | data | test.cpp:197:6:197:9 | data | Memory may have been previously freed by $@. | test.cpp:192:2:192:5 | call to free | call to free |
@@ -72,3 +85,4 @@ subpaths
| test.cpp:209:6:209:9 | data | test.cpp:203:7:203:10 | data | test.cpp:209:6:209:9 | data | Memory may have been previously freed by $@. | test.cpp:203:2:203:5 | call to free | call to free |
| test.cpp:209:6:209:9 | data | test.cpp:207:8:207:11 | data | test.cpp:209:6:209:9 | data | Memory may have been previously freed by $@. | test.cpp:207:3:207:6 | call to free | call to free |
| test.cpp:209:6:209:9 | data | test.cpp:207:8:207:11 | data | test.cpp:209:6:209:9 | data | Memory may have been previously freed by $@. | test.cpp:207:3:207:6 | call to free | call to free |
| test.cpp:217:6:217:6 | x | test.cpp:216:9:216:9 | x | test.cpp:217:6:217:6 | x | Memory may have been previously freed by $@. | test.cpp:216:2:216:9 | delete | delete |