Skip to content

Commit b39398b

Browse files
committed
C++: Add call side effects for default field initializations to the IR
1 parent e79d1aa commit b39398b

File tree

4 files changed

+77
-24
lines changed

4 files changed

+77
-24
lines changed

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

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ private predicate hasDefaultSideEffect(Call call, ParameterIndex i, boolean buff
133133
* An expression that can have call side effects.
134134
*
135135
* All kinds of expressions invoke a function as part of their evaluation. This class provides a
136-
* way to treat those functions similarly, and to get the invoked `Function`.
136+
* way to treat those expressions similarly, and to get the invoked `Declaration`.
137137
*/
138138
class ExprWithCallSizeEffects extends Expr {
139139
ExprWithCallSizeEffects() {
@@ -142,15 +142,19 @@ class ExprWithCallSizeEffects extends Expr {
142142
this instanceof NewOrNewArrayExpr
143143
or
144144
this instanceof DeleteOrDeleteArrayExpr
145+
or
146+
this instanceof ConstructorDefaultFieldInit
145147
}
146148

147-
/** Gets the `Function` invoked by this expression, if known. */
148-
final Function getTarget() {
149+
/** Gets the `Declaration` invoked by this expression, if known. */
150+
final Declaration getTarget() {
149151
result = this.(Call).getTarget()
150152
or
151153
result = this.(NewOrNewArrayExpr).getAllocator()
152154
or
153155
result = this.(DeleteOrDeleteArrayExpr).getDeallocator()
156+
or
157+
result = this.(ConstructorDefaultFieldInit).getTarget()
154158
}
155159
}
156160

@@ -175,7 +179,7 @@ Opcode getCallSideEffectOpcode(ExprWithCallSizeEffects expr) {
175179
/**
176180
* Returns a side effect opcode for parameter index `i` of the specified call.
177181
*
178-
* This predicate will return at most two results: one read side effect, and one write side effect.
182+
* This predicate will yield at most two results: one read side effect, and one write side effect.
179183
*/
180184
Opcode getASideEffectOpcode(Call call, ParameterIndex i) {
181185
exists(boolean buffer |
@@ -228,3 +232,14 @@ Opcode getASideEffectOpcode(Call call, ParameterIndex i) {
228232
)
229233
)
230234
}
235+
236+
/**
237+
* Returns a side effect opcode for a default field initialization.
238+
*
239+
* This predicate will yield two results: one read side effect, and one write side effect.
240+
*/
241+
Opcode getDefaultFieldInitSideEffectOpcode() {
242+
result instanceof Opcode::IndirectReadSideEffect
243+
or
244+
result instanceof Opcode::IndirectMayWriteSideEffect
245+
}

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

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ private import SideEffects
1010
private import TranslatedElement
1111
private import TranslatedExpr
1212
private import TranslatedFunction
13+
private import TranslatedInitialization
1314
private import DefaultOptions as DefaultOptions
1415

1516
/**
@@ -429,6 +430,9 @@ class TranslatedCallSideEffects extends TranslatedSideEffects, TTranslatedCallSi
429430
or
430431
expr instanceof DeleteOrDeleteArrayExpr and
431432
result = getTranslatedDeleteOrDeleteArray(expr).getInstruction(CallTag())
433+
or
434+
expr instanceof ConstructorDefaultFieldInit and
435+
result = getTranslatedConstructorFieldInitialization(expr).getInstruction(CallTag())
432436
}
433437
}
434438

@@ -504,11 +508,25 @@ abstract class TranslatedSideEffect extends TranslatedElement {
504508
abstract predicate sideEffectInstruction(Opcode opcode, CppType type);
505509
}
506510

511+
private class CallOrDefaultFieldInit extends Expr {
512+
CallOrDefaultFieldInit() {
513+
this instanceof Call
514+
or
515+
this instanceof ConstructorDefaultFieldInit
516+
}
517+
518+
Declaration getTarget() {
519+
result = this.(Call).getTarget()
520+
or
521+
result = this.(ConstructorDefaultFieldInit).getTarget()
522+
}
523+
}
524+
507525
/**
508526
* The IR translation of a single argument side effect for a call.
509527
*/
510528
abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
511-
Call call;
529+
CallOrDefaultFieldInit callOrInit;
512530
int index;
513531
SideEffectOpcode sideEffectOpcode;
514532

@@ -524,7 +542,7 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
524542
result = "(read side effect for " + this.getArgString() + ")"
525543
}
526544

527-
override Call getPrimaryExpr() { result = call }
545+
override Expr getPrimaryExpr() { result = callOrInit }
528546

529547
override predicate sortOrder(int group, int indexInGroup) {
530548
indexInGroup = index and
@@ -586,9 +604,10 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
586604
tag instanceof OnlyInstructionTag and
587605
operandTag instanceof BufferSizeOperandTag and
588606
result =
589-
getTranslatedExpr(call.getArgument(call.getTarget()
590-
.(SideEffectFunction)
591-
.getParameterSizeIndex(index)).getFullyConverted()).getResult()
607+
getTranslatedExpr(callOrInit
608+
.(Call)
609+
.getArgument(callOrInit.getTarget().(SideEffectFunction).getParameterSizeIndex(index))
610+
.getFullyConverted()).getResult()
592611
}
593612

594613
/** Holds if this side effect is a write side effect, rather than a read side effect. */
@@ -616,7 +635,7 @@ class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect,
616635
Expr arg;
617636

618637
TranslatedArgumentExprSideEffect() {
619-
this = TTranslatedArgumentExprSideEffect(call, arg, index, sideEffectOpcode)
638+
this = TTranslatedArgumentExprSideEffect(callOrInit, arg, index, sideEffectOpcode)
620639
}
621640

622641
final override Locatable getAst() { result = arg }
@@ -640,28 +659,31 @@ class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect,
640659
* The IR translation of an argument side effect for `*this` on a call, where there is no `Expr`
641660
* object that represents the `this` argument.
642661
*
643-
* The applies only to constructor calls, as the AST has exploit qualifier `Expr`s for all other
644-
* calls to non-static member functions.
662+
* The applies to constructor calls and default field initializations, as the AST has explicit
663+
* qualifier `Expr`s for all other calls to non-static member functions.
645664
*/
646-
class TranslatedStructorQualifierSideEffect extends TranslatedArgumentSideEffect,
647-
TTranslatedStructorQualifierSideEffect
665+
class TranslatedImplicitThisQualifierSideEffect extends TranslatedArgumentSideEffect,
666+
TTranslatedImplicitThisQualifierSideEffect
648667
{
649-
TranslatedStructorQualifierSideEffect() {
650-
this = TTranslatedStructorQualifierSideEffect(call, sideEffectOpcode) and
668+
TranslatedImplicitThisQualifierSideEffect() {
669+
this = TTranslatedImplicitThisQualifierSideEffect(callOrInit, sideEffectOpcode) and
651670
index = -1
652671
}
653672

654-
final override Locatable getAst() { result = call }
673+
final override Locatable getAst() { result = callOrInit }
655674

656-
final override Type getIndirectionType() { result = call.getTarget().getDeclaringType() }
675+
final override Type getIndirectionType() { result = callOrInit.getTarget().getDeclaringType() }
657676

658677
final override string getArgString() { result = "this" }
659678

660679
final override Instruction getArgInstruction() {
661680
exists(TranslatedStructorCall structorCall |
662-
structorCall.getExpr() = call and
681+
structorCall.getExpr() = callOrInit and
663682
result = structorCall.getQualifierResult()
664683
)
684+
or
685+
callOrInit instanceof ConstructorDefaultFieldInit and
686+
result = getTranslatedFunction(callOrInit.getEnclosingFunction()).getLoadThisInstruction()
665687
}
666688
}
667689

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -918,11 +918,16 @@ newtype TTranslatedElement =
918918
} or
919919
// Constructor calls lack a qualifier (`this`) expression, so we need to handle the side effects
920920
// on `*this` without an `Expr`.
921-
TTranslatedStructorQualifierSideEffect(Call call, SideEffectOpcode opcode) {
921+
TTranslatedImplicitThisQualifierSideEffect(ExprWithCallSizeEffects call, SideEffectOpcode opcode) {
922922
not ignoreExpr(call) and
923923
not ignoreSideEffects(call) and
924-
call instanceof ConstructorCall and
925-
opcode = getASideEffectOpcode(call, -1)
924+
(
925+
call instanceof ConstructorCall and
926+
opcode = getASideEffectOpcode(call, -1)
927+
or
928+
call instanceof ConstructorFieldInit and
929+
opcode = getDefaultFieldInitSideEffectOpcode()
930+
)
926931
} or
927932
// The side effect that initializes newly-allocated memory.
928933
TTranslatedAllocationSideEffect(AllocationExpr expr) { not ignoreSideEffects(expr) } or

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -634,13 +634,22 @@ class TranslatedDefaultFieldInitialization extends TranslatedFieldInitialization
634634
kind instanceof GotoEdge
635635
}
636636

637-
override Instruction getALastInstructionInternal() { result = this.getInstruction(CallTag()) }
637+
override Instruction getALastInstructionInternal() {
638+
result = this.getSideEffects().getALastInstruction()
639+
}
640+
641+
override TranslatedElement getLastChild() { result = this.getSideEffects() }
638642

639643
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
640644
tag = CallTargetTag() and
641645
result = this.getInstruction(CallTag())
642646
or
643647
tag = CallTag() and
648+
result = this.getSideEffects().getFirstInstruction(kind)
649+
}
650+
651+
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
652+
child = this.getSideEffects() and
644653
result = this.getParent().getChildSuccessor(this, kind)
645654
}
646655

@@ -670,7 +679,9 @@ class TranslatedDefaultFieldInitialization extends TranslatedFieldInitialization
670679
result = field
671680
}
672681

673-
override TranslatedElement getChild(int id) { none() }
682+
override TranslatedElement getChild(int id) { id = 0 and result = this.getSideEffects() }
683+
684+
final TranslatedSideEffects getSideEffects() { result.getExpr() = ast }
674685
}
675686

676687
private string getZeroValue(Type type) {

0 commit comments

Comments
 (0)