Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 85d1d07

Browse files
author
Robert Marsh
committed
C++: Add implicit named destructosrs to the IR CFG
1 parent 3a404ce commit 85d1d07

14 files changed

Lines changed: 1291 additions & 469 deletions

cpp/ql/lib/semmle/code/cpp/Enclosing.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,6 @@ Element exprEnclosingElement(Expr e) {
6060
)
6161
else result = de.getDeclaration()
6262
)
63+
or
64+
result.(Stmt).getAnImplicitDestructorCall() = e
6365
}

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ private import InstructionTag
1111
private import TranslatedCondition
1212
private import TranslatedElement
1313
private import TranslatedExpr
14+
private import TranslatedCall
1415
private import TranslatedStmt
1516
private import TranslatedFunction
1617
private import TranslatedGlobalVar
@@ -266,7 +267,7 @@ CppType getInstructionOperandType(Instruction instruction, TypedOperandTag tag)
266267
Instruction getPhiInstructionBlockStart(PhiInstruction instr) { none() }
267268

268269
Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
269-
result =
270+
result =
270271
getInstructionTranslatedElement(instruction)
271272
.getInstructionSuccessor(getInstructionTag(instruction), kind)
272273
}

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,14 @@ newtype TInstructionTag =
8585
// The next three cases handle generation of branching for __except handling.
8686
TryExceptCompareNegativeOneBranch() or
8787
TryExceptCompareZeroBranch() or
88-
TryExceptCompareOneBranch()
88+
TryExceptCompareOneBranch() or
89+
ImplicitDestructorTag(int index) {
90+
exists(Expr e | exists(e.getImplicitDestructorCall(index))) or
91+
exists(Stmt s | exists(s.getImplicitDestructorCall(index)))
92+
}
8993

9094
class InstructionTag extends TInstructionTag {
91-
final string toString() { result = "Tag" }
95+
final string toString() { result = getInstructionTagId(this) }
9296
}
9397

9498
/**
@@ -255,4 +259,8 @@ string getInstructionTagId(TInstructionTag tag) {
255259
tag = TryExceptCompareZeroBranch() and result = "TryExceptCompareZeroBranch"
256260
or
257261
tag = TryExceptCompareOneBranch() and result = "TryExceptCompareOneBranch"
262+
or
263+
exists(int index |
264+
tag = ImplicitDestructorTag(index) and result = "ImplicitDestructor(" + index + ")"
265+
)
258266
}

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,19 @@ abstract class TranslatedCall extends TranslatedExpr {
4747
else result = this.getFirstCallTargetInstruction(kind)
4848
}
4949

50-
override Instruction getLastInstruction() { result = this.getSideEffects().getLastInstruction() }
50+
override Instruction getLastInstructionInternal() {
51+
result = this.getSideEffects().getLastInstruction()
52+
}
53+
54+
override TranslatedElement getLastChild() { result = this.getSideEffects() }
5155

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

58-
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
62+
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
5963
child = this.getQualifier() and
6064
result = this.getFirstCallTargetInstruction(kind)
6165
or
@@ -89,7 +93,8 @@ abstract class TranslatedCall extends TranslatedExpr {
8993
)
9094
}
9195

92-
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
96+
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
97+
kind instanceof GotoEdge and
9398
tag = CallTag() and
9499
result = this.getSideEffects().getFirstInstruction(kind)
95100
}
@@ -227,7 +232,7 @@ abstract class TranslatedSideEffects extends TranslatedElement {
227232
)
228233
}
229234

230-
final override Instruction getChildSuccessor(TranslatedElement te, EdgeKind kind) {
235+
final override Instruction getChildSuccessorInternal(TranslatedElement te, EdgeKind kind) {
231236
exists(int i |
232237
this.getChild(i) = te and
233238
if exists(this.getChild(i + 1))
@@ -236,6 +241,10 @@ abstract class TranslatedSideEffects extends TranslatedElement {
236241
)
237242
}
238243

244+
override TranslatedElement getLastChild() {
245+
result = this.getChild(max(int i | exists(this.getChild(i))))
246+
}
247+
239248
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
240249
none()
241250
}
@@ -248,7 +257,7 @@ abstract class TranslatedSideEffects extends TranslatedElement {
248257
result = this.getParent().getChildSuccessor(this, kind)
249258
}
250259

251-
override Instruction getLastInstruction() {
260+
override Instruction getLastInstructionInternal() {
252261
if exists(this.getAChild())
253262
then result = this.getChild(max(int i | exists(this.getChild(i)))).getLastInstruction()
254263
else
@@ -257,7 +266,9 @@ abstract class TranslatedSideEffects extends TranslatedElement {
257266
result = this.getParent().getInstruction(CallTag())
258267
}
259268

260-
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
269+
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
270+
none()
271+
}
261272

262273
/** Gets the primary instruction to be associated with each side effect instruction. */
263274
abstract Instruction getPrimaryInstruction();
@@ -284,8 +295,8 @@ abstract class TranslatedDirectCall extends TranslatedCall {
284295
resultType = getFunctionGLValueType()
285296
}
286297

287-
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
288-
result = TranslatedCall.super.getInstructionSuccessor(tag, kind)
298+
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
299+
result = TranslatedCall.super.getInstructionSuccessorInternal(tag, kind)
289300
or
290301
tag = CallTargetTag() and
291302
result = this.getFirstArgumentOrCallInstruction(kind)
@@ -378,6 +389,16 @@ class TranslatedStructorCall extends TranslatedFunctionCall {
378389
context = this.getParent() and
379390
result = context.getReceiver()
380391
)
392+
or
393+
exists(Stmt parent |
394+
expr = parent.getAnImplicitDestructorCall() and
395+
result = getTranslatedExpr(expr.getQualifier().getFullyConverted()).getResult()
396+
)
397+
or
398+
exists(Expr parent |
399+
expr = parent.getAnImplicitDestructorCall() and
400+
result = getTranslatedExpr(expr.getQualifier().getFullyConverted()).getResult()
401+
)
381402
}
382403

383404
override predicate hasQualifier() { any() }
@@ -427,21 +448,23 @@ private int initializeAllocationGroup() { result = 3 }
427448
abstract class TranslatedSideEffect extends TranslatedElement {
428449
final override TranslatedElement getChild(int n) { none() }
429450

430-
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
451+
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
431452

432453
final override Instruction getFirstInstruction(EdgeKind kind) {
433454
result = this.getInstruction(OnlyInstructionTag()) and
434455
kind instanceof GotoEdge
435456
}
436457

437-
override Instruction getLastInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
458+
override Instruction getLastInstructionInternal() {
459+
result = this.getInstruction(OnlyInstructionTag())
460+
}
438461

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

444-
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
467+
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
445468
result = this.getParent().getChildSuccessor(this, kind) and
446469
tag = OnlyInstructionTag()
447470
}

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCondition.qll

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,21 +50,25 @@ abstract class TranslatedFlexibleCondition extends TranslatedCondition, Conditio
5050
{
5151
TranslatedFlexibleCondition() { this = TTranslatedFlexibleCondition(expr) }
5252

53+
final override predicate handlesDestructorsExplicitly() { none() } // TODO: this needs to be revisted when we get unnamed destructors
54+
5355
final override TranslatedElement getChild(int id) { id = 0 and result = this.getOperand() }
5456

5557
final override Instruction getFirstInstruction(EdgeKind kind) {
5658
result = this.getOperand().getFirstInstruction(kind)
5759
}
5860

59-
final override Instruction getLastInstruction() {
61+
final override Instruction getLastInstructionInternal() {
6062
result = this.getOperand().getLastInstruction()
6163
}
6264

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

67-
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
69+
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
70+
none()
71+
}
6872

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

@@ -98,6 +102,8 @@ abstract class TranslatedNativeCondition extends TranslatedCondition, TTranslate
98102
abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeCondition, ConditionContext {
99103
override BinaryLogicalOperation expr;
100104

105+
final override predicate handlesDestructorsExplicitly() { none() } // TODO: this needs to be revisted when we get unnamed destructors
106+
101107
final override TranslatedElement getChild(int id) {
102108
id = 0 and result = this.getLeftOperand()
103109
or
@@ -108,7 +114,7 @@ abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeConditio
108114
result = this.getLeftOperand().getFirstInstruction(kind)
109115
}
110116

111-
final override Instruction getLastInstruction() {
117+
final override Instruction getLastInstructionInternal() {
112118
result = this.getLeftOperand().getLastInstruction()
113119
or
114120
result = this.getRightOperand().getLastInstruction()
@@ -118,7 +124,9 @@ abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeConditio
118124
none()
119125
}
120126

121-
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
127+
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
128+
none()
129+
}
122130

123131
final TranslatedCondition getLeftOperand() {
124132
result = getTranslatedCondition(expr.getLeftOperand().getFullyConverted())
@@ -172,10 +180,12 @@ class TranslatedValueCondition extends TranslatedCondition, TTranslatedValueCond
172180
result = this.getValueExpr().getFirstInstruction(kind)
173181
}
174182

175-
override Instruction getLastInstruction() {
183+
override Instruction getLastInstructionInternal() {
176184
result = this.getInstruction(ValueConditionConditionalBranchTag())
177185
}
178186

187+
final override predicate handlesDestructorsExplicitly() { none() } // TODO: this needs to be revisted when we get unnamed destructors
188+
179189
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
180190
tag = ValueConditionConditionalBranchTag() and
181191
opcode instanceof Opcode::ConditionalBranch and
@@ -188,7 +198,7 @@ class TranslatedValueCondition extends TranslatedCondition, TTranslatedValueCond
188198
kind instanceof GotoEdge
189199
}
190200

191-
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
201+
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
192202
tag = ValueConditionConditionalBranchTag() and
193203
(
194204
kind instanceof TrueEdge and

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,13 +156,13 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
156156
kind instanceof GotoEdge
157157
}
158158

159-
final override Instruction getLastInstruction() {
159+
final override Instruction getLastInstructionInternal() {
160160
result = this.getInstruction(DynamicInitializationConditionalBranchTag())
161161
or
162162
result = this.getInstruction(DynamicInitializationFlagStoreTag())
163163
}
164164

165-
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
165+
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
166166
tag = DynamicInitializationFlagAddressTag() and
167167
kind instanceof GotoEdge and
168168
result = this.getInstruction(DynamicInitializationFlagLoadTag())

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,18 @@ private import SideEffects
2020
* they were explicit nodes in the expression tree, rather than as implicit
2121
* nodes as in the regular AST representation.
2222
*/
23-
private Element getRealParent(Expr expr) {
23+
Element getRealParent(Expr expr) {
2424
result = expr.getParentWithConversions()
2525
or
26+
/*
27+
* exists(Stmt destructorParent, DestructorCall dc |
28+
* destructorParent.getAnImplicitDestructorCall() = dc and
29+
* dc.getQualifier() = expr and
30+
* result = dc
31+
* )
32+
* or
33+
*/
34+
2635
result.(Destructor).getADestruction() = expr
2736
or
2837
result.(Expr).getAnImplicitDestructorCall() = expr
@@ -748,12 +757,7 @@ newtype TTranslatedElement =
748757
// on `*this` without an `Expr`.
749758
TTranslatedStructorQualifierSideEffect(Call call, SideEffectOpcode opcode) {
750759
not ignoreSideEffects(call) and
751-
// Don't bother with destructor calls for now, since we won't see very many of them in the IR
752-
// until we start injecting implicit destructor calls.
753-
(
754-
call instanceof ConstructorCall or
755-
call instanceof DestructorCall
756-
) and
760+
call instanceof ConstructorCall and
757761
opcode = getASideEffectOpcode(call, -1)
758762
} or
759763
// The side effect that initializes newly-allocated memory.
@@ -866,6 +870,17 @@ abstract class TranslatedElement extends TTranslatedElement {
866870
1 + sum(TranslatedElement child | child = this.getChildByRank(_) | child.getDescendantCount())
867871
}
868872

873+
/**
874+
* Holds if this element has implicit destructor calls that should follow it.
875+
*/
876+
predicate hasImplicitDestructorCalls() { none() }
877+
878+
/**
879+
*/
880+
int getFirstDestructorCallIndex() { none() }
881+
882+
predicate handlesDestructorsExplicitly() { none() }
883+
869884
private int getUniqueId() {
870885
if not exists(this.getParent())
871886
then result = 0
@@ -902,16 +917,56 @@ abstract class TranslatedElement extends TTranslatedElement {
902917
* Gets the successor instruction of the instruction that was generated by
903918
* this element for tag `tag`. The successor edge kind is specified by `kind`.
904919
*/
905-
abstract Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind);
920+
abstract Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind);
921+
922+
Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
923+
if
924+
this.hasImplicitDestructorCalls() and
925+
this.getInstruction(tag) = this.getLastInstructionInternal() and
926+
not this.handlesDestructorsExplicitly()
927+
then
928+
result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind) and
929+
kind instanceof GotoEdge
930+
else result = this.getInstructionSuccessorInternal(tag, kind)
931+
}
932+
933+
final Instruction getLastInstruction() {
934+
if this.hasImplicitDestructorCalls() and not this.handlesDestructorsExplicitly()
935+
then result = this.getChild(max(int n | exists(this.getChild(n)))).getLastInstruction() // last destructor
936+
else result = this.getLastInstructionInternal()
937+
}
906938

907-
abstract Instruction getLastInstruction();
939+
abstract Instruction getLastInstructionInternal();
940+
941+
TranslatedElement getLastChild() { none() }
908942

909943
/**
910944
* Gets the successor instruction to which control should flow after the
911945
* child element specified by `child` has finished execution. The successor
912946
* edge kind is specified by `kind`.
913947
*/
914-
abstract Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind);
948+
Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
949+
950+
Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
951+
(
952+
if
953+
// this is the last child and we need to handle destructors for it
954+
this.hasImplicitDestructorCalls() and
955+
not this.handlesDestructorsExplicitly() and
956+
child = this.getLastChild()
957+
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
958+
else result = this.getChildSuccessorInternal(child, kind)
959+
)
960+
or
961+
not this.handlesDestructorsExplicitly() and
962+
exists(int id |
963+
id >= this.getFirstDestructorCallIndex() and
964+
child = this.getChild(id) and
965+
if id = max(int n | exists(this.getChild(n)))
966+
then result = this.getParent().getChildSuccessor(this, kind)
967+
else result = this.getChild(id + 1).getFirstInstruction(kind)
968+
)
969+
}
915970

916971
/**
917972
* Gets the instruction to which control should flow if an exception is thrown

0 commit comments

Comments
 (0)