Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C++: Add implicit destructors for named variables to the IR #15506

Merged
merged 34 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
47720e0
C++: generate instructions for destructor calls in IR
rdmarsh2 Jan 12, 2024
3a404ce
C++: Add `getLastInstruction` to IR generation
rdmarsh2 Jan 24, 2024
85d1d07
C++: Add implicit named destructosrs to the IR CFG
rdmarsh2 Feb 1, 2024
820f4a5
C++: custom destructor handling for `for` loops
rdmarsh2 Feb 1, 2024
4513fd1
C++: test for destructors in range-based for
rdmarsh2 Feb 1, 2024
984c7ab
C++: test for declarations in `if` statement
rdmarsh2 Feb 1, 2024
2d010f6
C++: Test for destructors in declaration as `if` condition
rdmarsh2 Feb 1, 2024
bbabf1d
C++: add test for constructors in C++17 decl-in-if
rdmarsh2 Feb 5, 2024
8013c2a
C++: QLDoc and naming updates for implicit destructors in IR
rdmarsh2 Feb 5, 2024
40e06b7
C++: suppress destructor calls on delete in IR generation
rdmarsh2 Feb 6, 2024
5653c3f
C++: Update IR test expectations for named destructors
rdmarsh2 Feb 6, 2024
1749661
Merge branch 'main' into rdmarsh2/cpp/ir-synthetic-destructors
rdmarsh2 Feb 7, 2024
1b571f8
C++: Accept test changes
rdmarsh2 Feb 9, 2024
d1160f8
C++: Autoformat for named destructors in IR
rdmarsh2 Feb 9, 2024
bac7e46
C++: tests for destructors after a while-loop condition
rdmarsh2 Feb 12, 2024
b94c4a6
C++: fix for destructor of while-loop condition
rdmarsh2 Feb 13, 2024
6663420
C++: test for multiple for loop variables with destructors
rdmarsh2 Feb 13, 2024
7d8872b
C++: Fix for multiple for-loop variables with destructors
rdmarsh2 Feb 13, 2024
b6cf64c
C++: simplify TranslatedBlock::getLastChild
rdmarsh2 Feb 13, 2024
f791b0e
C++: Model for smart pointer destructors
rdmarsh2 Feb 13, 2024
b9785ea
C++: autoformat
rdmarsh2 Feb 13, 2024
128bc99
C++: delete some FIXMEs that turned out fine
rdmarsh2 Feb 13, 2024
7e23ccd
Merge branch 'main' into rdmarsh2/cpp/ir-synthetic-destructors
rdmarsh2 Feb 13, 2024
2c8ed64
C++: test for return in if
rdmarsh2 Feb 16, 2024
2494b7d
C++: fix for IR CFG problem with return in if
rdmarsh2 Feb 16, 2024
e0c7849
C++: fix incorrect use of getChildInternal
rdmarsh2 Feb 21, 2024
66743fb
C++: refactor TranslatedReturnStmt
rdmarsh2 Feb 21, 2024
875ab74
Merge branch 'main' into rdmarsh2/cpp/ir-synthetic-destructors
rdmarsh2 Feb 21, 2024
ebe6ee5
C++: accept test changes from extractor fixes
rdmarsh2 Feb 22, 2024
942a4ed
C++: move handlesDestructorsExplicitly up to TranslatedReturnStmt
rdmarsh2 Feb 22, 2024
6f7f68f
Merge branch 'main' into rdmarsh2/cpp/ir-synthetic-destructors
rdmarsh2 Feb 22, 2024
dd97584
C++: fix for duplicated parent of ReturnVoid statements
rdmarsh2 Feb 23, 2024
da5e3d6
C++: autoformat
rdmarsh2 Feb 23, 2024
a513598
C++: Change note for IR named destructors.
rdmarsh2 Feb 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cpp/ql/lib/semmle/code/cpp/Enclosing.qll
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,6 @@ Element exprEnclosingElement(Expr e) {
)
else result = de.getDeclaration()
)
or
result.(Stmt).getAnImplicitDestructorCall() = e
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
private import TranslatedCondition
private import TranslatedElement
private import TranslatedExpr
private import TranslatedCall

Check warning

Code scanning / CodeQL

Redundant import Warning

Redundant import, the module is already imported inside
TranslatedExpr
.
private import TranslatedStmt
private import TranslatedFunction
private import TranslatedGlobalVar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,14 @@ newtype TInstructionTag =
// The next three cases handle generation of branching for __except handling.
TryExceptCompareNegativeOneBranch() or
TryExceptCompareZeroBranch() or
TryExceptCompareOneBranch()
TryExceptCompareOneBranch() or
ImplicitDestructorTag(int index) {
exists(Expr e | exists(e.getImplicitDestructorCall(index))) or
exists(Stmt s | exists(s.getImplicitDestructorCall(index)))
}

class InstructionTag extends TInstructionTag {
final string toString() { result = "Tag" }
final string toString() { result = getInstructionTagId(this) }
MathiasVP marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down Expand Up @@ -255,4 +259,8 @@ string getInstructionTagId(TInstructionTag tag) {
tag = TryExceptCompareZeroBranch() and result = "TryExceptCompareZeroBranch"
or
tag = TryExceptCompareOneBranch() and result = "TryExceptCompareOneBranch"
or
exists(int index |
tag = ImplicitDestructorTag(index) and result = "ImplicitDestructor(" + index + ")"
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ private CallInstruction getTranslatedCallInstruction(Call call) {
* of a higher-level constructor (e.g. the allocator call in a `NewExpr`).
*/
abstract class TranslatedCall extends TranslatedExpr {
final override TranslatedElement getChild(int id) {
final override TranslatedElement getChildInternal(int id) {
// We choose the child's id in the order of evaluation.
// The qualifier is evaluated before the call target, because the value of
// the call target may depend on the value of the qualifier for virtual
Expand All @@ -47,13 +47,19 @@ abstract class TranslatedCall extends TranslatedExpr {
else result = this.getFirstCallTargetInstruction(kind)
}

override Instruction getALastInstructionInternal() {
result = this.getSideEffects().getALastInstruction()
}

override TranslatedElement getLastChild() { result = this.getSideEffects() }

override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = CallTag() and
opcode instanceof Opcode::Call and
resultType = getTypeForPRValue(this.getCallResultType())
}

override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
child = this.getQualifier() and
result = this.getFirstCallTargetInstruction(kind)
or
Expand Down Expand Up @@ -87,7 +93,7 @@ abstract class TranslatedCall extends TranslatedExpr {
)
}

override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
tag = CallTag() and
result = this.getSideEffects().getFirstInstruction(kind)
}
Expand Down Expand Up @@ -225,7 +231,7 @@ abstract class TranslatedSideEffects extends TranslatedElement {
)
}

final override Instruction getChildSuccessor(TranslatedElement te, EdgeKind kind) {
final override Instruction getChildSuccessorInternal(TranslatedElement te, EdgeKind kind) {
exists(int i |
this.getChild(i) = te and
if exists(this.getChild(i + 1))
Expand All @@ -234,6 +240,10 @@ abstract class TranslatedSideEffects extends TranslatedElement {
)
}

override TranslatedElement getLastChild() {
result = this.getChild(max(int i | exists(this.getChild(i))))
}

final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
none()
}
Expand All @@ -246,7 +256,18 @@ abstract class TranslatedSideEffects extends TranslatedElement {
result = this.getParent().getChildSuccessor(this, kind)
}

final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getALastInstructionInternal() {
if exists(this.getAChild())
then result = this.getChild(max(int i | exists(this.getChild(i)))).getALastInstruction()
else
// If there are no side effects, the "last" instruction should be the parent call's last
// instruction, so that implicit destructors can be inserted in the right place.
result = this.getParent().getInstruction(CallTag())
}

final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
none()
}

/** Gets the primary instruction to be associated with each side effect instruction. */
abstract Instruction getPrimaryInstruction();
Expand All @@ -273,8 +294,8 @@ abstract class TranslatedDirectCall extends TranslatedCall {
resultType = getFunctionGLValueType()
}

override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
result = TranslatedCall.super.getInstructionSuccessor(tag, kind)
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
result = TranslatedCall.super.getInstructionSuccessorInternal(tag, kind)
or
tag = CallTargetTag() and
result = this.getFirstArgumentOrCallInstruction(kind)
Expand Down Expand Up @@ -367,6 +388,16 @@ class TranslatedStructorCall extends TranslatedFunctionCall {
context = this.getParent() and
result = context.getReceiver()
)
or
exists(Stmt parent |
expr = parent.getAnImplicitDestructorCall() and
result = getTranslatedExpr(expr.getQualifier().getFullyConverted()).getResult()
)
or
exists(Expr parent |
expr = parent.getAnImplicitDestructorCall() and
result = getTranslatedExpr(expr.getQualifier().getFullyConverted()).getResult()
)
}

override predicate hasQualifier() { any() }
Expand Down Expand Up @@ -416,19 +447,25 @@ private int initializeAllocationGroup() { result = 3 }
abstract class TranslatedSideEffect extends TranslatedElement {
final override TranslatedElement getChild(int n) { none() }

final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
none()
}

final override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(OnlyInstructionTag()) and
kind instanceof GotoEdge
}

override Instruction getALastInstructionInternal() {
result = this.getInstruction(OnlyInstructionTag())
}

final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
tag = OnlyInstructionTag() and
this.sideEffectInstruction(opcode, type)
}

final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
result = this.getParent().getChildSuccessor(this, kind) and
tag = OnlyInstructionTag()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,29 @@ abstract class TranslatedFlexibleCondition extends TranslatedCondition, Conditio
{
TranslatedFlexibleCondition() { this = TTranslatedFlexibleCondition(expr) }

final override predicate handlesDestructorsExplicitly() { none() } // TODO: this needs to be revisted when we get unnamed destructors

final override TranslatedElement getChild(int id) { id = 0 and result = this.getOperand() }

final override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getOperand().getFirstInstruction(kind)
}

final override Instruction getALastInstructionInternal() {
result = this.getOperand().getALastInstruction()
}

final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
none()
}

final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
none()
}

final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
none()
}

abstract TranslatedCondition getOperand();
}
Expand All @@ -88,12 +98,16 @@ class TranslatedParenthesisCondition extends TranslatedFlexibleCondition {
abstract class TranslatedNativeCondition extends TranslatedCondition, TTranslatedNativeCondition {
TranslatedNativeCondition() { this = TTranslatedNativeCondition(expr) }

final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
none()
}
}

abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeCondition, ConditionContext {
override BinaryLogicalOperation expr;

final override predicate handlesDestructorsExplicitly() { none() } // TODO: this needs to be revisted when we get unnamed destructors

final override TranslatedElement getChild(int id) {
id = 0 and result = this.getLeftOperand()
or
Expand All @@ -104,11 +118,19 @@ abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeConditio
result = this.getLeftOperand().getFirstInstruction(kind)
}

final override Instruction getALastInstructionInternal() {
result = this.getLeftOperand().getALastInstruction()
or
result = this.getRightOperand().getALastInstruction()
}

final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
none()
}

final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
none()
}

final TranslatedCondition getLeftOperand() {
result = getTranslatedCondition(expr.getLeftOperand().getFullyConverted())
Expand Down Expand Up @@ -162,19 +184,25 @@ class TranslatedValueCondition extends TranslatedCondition, TTranslatedValueCond
result = this.getValueExpr().getFirstInstruction(kind)
}

override Instruction getALastInstructionInternal() {
result = this.getInstruction(ValueConditionConditionalBranchTag())
}

final override predicate handlesDestructorsExplicitly() { none() } // TODO: this needs to be revisted when we get unnamed destructors

override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = ValueConditionConditionalBranchTag() and
opcode instanceof Opcode::ConditionalBranch and
resultType = getVoidType()
}

override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
child = this.getValueExpr() and
result = this.getInstruction(ValueConditionConditionalBranchTag()) and
kind instanceof GotoEdge
}

override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
tag = ValueConditionConditionalBranchTag() and
(
kind instanceof TrueEdge and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ abstract class TranslatedLocalVariableDeclaration extends TranslatedVariableInit
*/
abstract LocalVariable getVariable();

final override TranslatedElement getChild(int id) {
result = TranslatedVariableInitialization.super.getChildInternal(id)
}

final override Type getTargetType() { result = getVariableType(this.getVariable()) }

final override TranslatedInitialization getInitialization() {
Expand Down Expand Up @@ -152,7 +156,13 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
kind instanceof GotoEdge
}

final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
final override Instruction getALastInstructionInternal() {
result = this.getInstruction(DynamicInitializationConditionalBranchTag())
or
result = this.getInstruction(DynamicInitializationFlagStoreTag())
}

final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
tag = DynamicInitializationFlagAddressTag() and
kind instanceof GotoEdge and
result = this.getInstruction(DynamicInitializationFlagLoadTag())
Expand All @@ -178,7 +188,7 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
result = this.getParent().getChildSuccessor(this, kind)
}

final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
child = this.getInitialization() and
result = this.getInstruction(DynamicInitializationFlagConstantTag()) and
kind instanceof GotoEdge
Expand Down
Loading
Loading