Skip to content

Commit a87ff80

Browse files
authored
Merge pull request github#3587 from rdmarsh2/ir-this-parameter-2
C++: IR return indirections for `this`
2 parents cd111fe + ef940e8 commit a87ff80

34 files changed

+934
-318
lines changed

cpp/ql/src/semmle/code/cpp/Parameter.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ class Parameter extends LocalScopeVariable, @parameter {
165165
class ParameterIndex extends int {
166166
ParameterIndex() {
167167
exists(Parameter p | this = p.getIndex()) or
168-
exists(Call c | exists(c.getArgument(this))) // permit indexing varargs
168+
exists(Call c | exists(c.getArgument(this))) or // permit indexing varargs
169+
this = -1 // used for `this`
169170
}
170171
}

cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,12 @@ class ReturnValueNode extends ReturnNode {
8686
class ReturnIndirectionNode extends ReturnNode {
8787
override ReturnIndirectionInstruction primary;
8888

89-
override ReturnKind getKind() { result = TIndirectReturnKind(primary.getParameter().getIndex()) }
89+
override ReturnKind getKind() {
90+
result = TIndirectReturnKind(-1) and
91+
primary.isThisIndirection()
92+
or
93+
result = TIndirectReturnKind(primary.getParameter().getIndex())
94+
}
9095
}
9196

9297
/** A data flow node that represents the output of a call. */

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,19 +217,23 @@ class IRThrowVariable extends IRTempVariable {
217217
* A temporary variable generated to hold the contents of all arguments passed to the `...` of a
218218
* function that accepts a variable number of arguments.
219219
*/
220-
class IREllipsisVariable extends IRTempVariable {
220+
class IREllipsisVariable extends IRTempVariable, IRParameter {
221221
IREllipsisVariable() { tag = EllipsisTempVar() }
222222

223223
final override string toString() { result = "#ellipsis" }
224+
225+
final override int getIndex() { result = func.getNumberOfParameters() }
224226
}
225227

226228
/**
227229
* A temporary variable generated to hold the `this` pointer.
228230
*/
229-
class IRThisVariable extends IRTempVariable {
231+
class IRThisVariable extends IRTempVariable, IRParameter {
230232
IRThisVariable() { tag = ThisTempVar() }
231233

232234
final override string toString() { result = "#this" }
235+
236+
final override int getIndex() { result = -1 }
233237
}
234238

235239
/**
@@ -274,3 +278,29 @@ class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitial
274278

275279
final override string getBaseString() { result = "#init:" + var.toString() + ":" }
276280
}
281+
282+
/**
283+
* An IR variable which acts like a function parameter, including positional parameters and the
284+
* temporary variables generated for `this` and ellipsis parameters.
285+
*/
286+
class IRParameter extends IRAutomaticVariable {
287+
IRParameter() {
288+
this.(IRAutomaticUserVariable).getVariable() instanceof Language::Parameter
289+
or
290+
this = TIRTempVariable(_, _, ThisTempVar(), _)
291+
or
292+
this = TIRTempVariable(_, _, EllipsisTempVar(), _)
293+
}
294+
295+
/**
296+
* Gets the zero-based index of this parameter. The `this` parameter has index -1.
297+
*/
298+
int getIndex() { none() }
299+
}
300+
301+
/**
302+
* An IR variable representing a positional parameter.
303+
*/
304+
class IRPositionalParameter extends IRParameter, IRAutomaticUserVariable {
305+
final override int getIndex() { result = getVariable().(Language::Parameter).getIndex() }
306+
}

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,11 @@ class ReturnIndirectionInstruction extends VariableInstruction {
541541
* function.
542542
*/
543543
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
544+
545+
/**
546+
* Holds if this instruction is the return indirection for `this`.
547+
*/
548+
final predicate isThisIndirection() { var instanceof IRThisVariable }
544549
}
545550

546551
class CopyInstruction extends Instruction {

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,19 +217,23 @@ class IRThrowVariable extends IRTempVariable {
217217
* A temporary variable generated to hold the contents of all arguments passed to the `...` of a
218218
* function that accepts a variable number of arguments.
219219
*/
220-
class IREllipsisVariable extends IRTempVariable {
220+
class IREllipsisVariable extends IRTempVariable, IRParameter {
221221
IREllipsisVariable() { tag = EllipsisTempVar() }
222222

223223
final override string toString() { result = "#ellipsis" }
224+
225+
final override int getIndex() { result = func.getNumberOfParameters() }
224226
}
225227

226228
/**
227229
* A temporary variable generated to hold the `this` pointer.
228230
*/
229-
class IRThisVariable extends IRTempVariable {
231+
class IRThisVariable extends IRTempVariable, IRParameter {
230232
IRThisVariable() { tag = ThisTempVar() }
231233

232234
final override string toString() { result = "#this" }
235+
236+
final override int getIndex() { result = -1 }
233237
}
234238

235239
/**
@@ -274,3 +278,29 @@ class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitial
274278

275279
final override string getBaseString() { result = "#init:" + var.toString() + ":" }
276280
}
281+
282+
/**
283+
* An IR variable which acts like a function parameter, including positional parameters and the
284+
* temporary variables generated for `this` and ellipsis parameters.
285+
*/
286+
class IRParameter extends IRAutomaticVariable {
287+
IRParameter() {
288+
this.(IRAutomaticUserVariable).getVariable() instanceof Language::Parameter
289+
or
290+
this = TIRTempVariable(_, _, ThisTempVar(), _)
291+
or
292+
this = TIRTempVariable(_, _, EllipsisTempVar(), _)
293+
}
294+
295+
/**
296+
* Gets the zero-based index of this parameter. The `this` parameter has index -1.
297+
*/
298+
int getIndex() { none() }
299+
}
300+
301+
/**
302+
* An IR variable representing a positional parameter.
303+
*/
304+
class IRPositionalParameter extends IRParameter, IRAutomaticUserVariable {
305+
final override int getIndex() { result = getVariable().(Language::Parameter).getIndex() }
306+
}

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,11 @@ class ReturnIndirectionInstruction extends VariableInstruction {
541541
* function.
542542
*/
543543
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
544+
545+
/**
546+
* Holds if this instruction is the return indirection for `this`.
547+
*/
548+
final predicate isThisIndirection() { var instanceof IRThisVariable }
544549
}
545550

546551
class CopyInstruction extends Instruction {

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,8 +415,11 @@ newtype TTranslatedElement =
415415
} or
416416
TTranslatedEllipsisParameter(Function func) { translateFunction(func) and func.isVarargs() } or
417417
TTranslatedReadEffects(Function func) { translateFunction(func) } or
418+
TTranslatedThisReadEffect(Function func) {
419+
translateFunction(func) and func.isMember() and not func.isStatic()
420+
} or
418421
// The read side effects in a function's return block
419-
TTranslatedReadEffect(Parameter param) {
422+
TTranslatedParameterReadEffect(Parameter param) {
420423
translateFunction(param.getFunction()) and
421424
exists(Type t | t = param.getUnspecifiedType() |
422425
t instanceof ArrayType or

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -676,14 +676,17 @@ class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
676676
override string toString() { result = "read effects: " + func.toString() }
677677

678678
override TranslatedElement getChild(int id) {
679-
result = getTranslatedReadEffect(func.getParameter(id))
679+
result = getTranslatedThisReadEffect(func) and
680+
id = -1
681+
or
682+
result = getTranslatedParameterReadEffect(func.getParameter(id))
680683
}
681684

682685
override Instruction getFirstInstruction() {
683686
if exists(getAChild())
684687
then
685688
result =
686-
min(TranslatedReadEffect child, int id | child = getChild(id) | child order by id)
689+
min(TranslatedElement child, int id | child = getChild(id) | child order by id)
687690
.getFirstInstruction()
688691
else result = getParent().getChildSuccessor(this)
689692
}
@@ -709,17 +712,15 @@ class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
709712
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
710713
}
711714

712-
private TranslatedReadEffect getTranslatedReadEffect(Parameter param) { result.getAST() = param }
713-
714-
class TranslatedReadEffect extends TranslatedElement, TTranslatedReadEffect {
715-
Parameter param;
716-
717-
TranslatedReadEffect() { this = TTranslatedReadEffect(param) }
718-
719-
override Locatable getAST() { result = param }
715+
private TranslatedThisReadEffect getTranslatedThisReadEffect(Function func) {
716+
result.getAST() = func
717+
}
720718

721-
override string toString() { result = "read effect: " + param.toString() }
719+
private TranslatedParameterReadEffect getTranslatedParameterReadEffect(Parameter param) {
720+
result.getAST() = param
721+
}
722722

723+
abstract class TranslatedReadEffect extends TranslatedElement {
723724
override TranslatedElement getChild(int id) { none() }
724725

725726
override Instruction getChildSuccessor(TranslatedElement child) { none() }
@@ -732,27 +733,60 @@ class TranslatedReadEffect extends TranslatedElement, TTranslatedReadEffect {
732733

733734
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
734735

735-
override Function getFunction() { result = param.getFunction() }
736-
737736
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
738737
opcode instanceof Opcode::ReturnIndirection and
739738
tag = OnlyInstructionTag() and
740739
resultType = getVoidType()
741740
}
742741

743-
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
744-
tag = OnlyInstructionTag() and
745-
operandTag = addressOperand() and
746-
result = getTranslatedParameter(param).getInstruction(InitializerIndirectAddressTag())
747-
}
748-
749742
final override CppType getInstructionMemoryOperandType(
750743
InstructionTag tag, TypedOperandTag operandTag
751744
) {
752745
tag = OnlyInstructionTag() and
753746
operandTag = sideEffectOperand() and
754747
result = getUnknownType()
755748
}
749+
}
750+
751+
class TranslatedThisReadEffect extends TranslatedReadEffect, TTranslatedThisReadEffect {
752+
Function func;
753+
754+
TranslatedThisReadEffect() { this = TTranslatedThisReadEffect(func) }
755+
756+
override Locatable getAST() { result = func }
757+
758+
override Function getFunction() { result = func }
759+
760+
override string toString() { result = "read effect: this" }
761+
762+
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
763+
tag = OnlyInstructionTag() and
764+
operandTag = addressOperand() and
765+
result = getTranslatedThisParameter(func).getInstruction(InitializerIndirectAddressTag())
766+
}
767+
768+
final override IRVariable getInstructionVariable(InstructionTag tag) {
769+
tag = OnlyInstructionTag() and
770+
result = getTranslatedFunction(func).getThisVariable()
771+
}
772+
}
773+
774+
class TranslatedParameterReadEffect extends TranslatedReadEffect, TTranslatedParameterReadEffect {
775+
Parameter param;
776+
777+
TranslatedParameterReadEffect() { this = TTranslatedParameterReadEffect(param) }
778+
779+
override Locatable getAST() { result = param }
780+
781+
override string toString() { result = "read effect: " + param.toString() }
782+
783+
override Function getFunction() { result = param.getFunction() }
784+
785+
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
786+
tag = OnlyInstructionTag() and
787+
operandTag = addressOperand() and
788+
result = getTranslatedParameter(param).getInstruction(InitializerIndirectAddressTag())
789+
}
756790

757791
final override IRVariable getInstructionVariable(InstructionTag tag) {
758792
tag = OnlyInstructionTag() and

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,19 +217,23 @@ class IRThrowVariable extends IRTempVariable {
217217
* A temporary variable generated to hold the contents of all arguments passed to the `...` of a
218218
* function that accepts a variable number of arguments.
219219
*/
220-
class IREllipsisVariable extends IRTempVariable {
220+
class IREllipsisVariable extends IRTempVariable, IRParameter {
221221
IREllipsisVariable() { tag = EllipsisTempVar() }
222222

223223
final override string toString() { result = "#ellipsis" }
224+
225+
final override int getIndex() { result = func.getNumberOfParameters() }
224226
}
225227

226228
/**
227229
* A temporary variable generated to hold the `this` pointer.
228230
*/
229-
class IRThisVariable extends IRTempVariable {
231+
class IRThisVariable extends IRTempVariable, IRParameter {
230232
IRThisVariable() { tag = ThisTempVar() }
231233

232234
final override string toString() { result = "#this" }
235+
236+
final override int getIndex() { result = -1 }
233237
}
234238

235239
/**
@@ -274,3 +278,29 @@ class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitial
274278

275279
final override string getBaseString() { result = "#init:" + var.toString() + ":" }
276280
}
281+
282+
/**
283+
* An IR variable which acts like a function parameter, including positional parameters and the
284+
* temporary variables generated for `this` and ellipsis parameters.
285+
*/
286+
class IRParameter extends IRAutomaticVariable {
287+
IRParameter() {
288+
this.(IRAutomaticUserVariable).getVariable() instanceof Language::Parameter
289+
or
290+
this = TIRTempVariable(_, _, ThisTempVar(), _)
291+
or
292+
this = TIRTempVariable(_, _, EllipsisTempVar(), _)
293+
}
294+
295+
/**
296+
* Gets the zero-based index of this parameter. The `this` parameter has index -1.
297+
*/
298+
int getIndex() { none() }
299+
}
300+
301+
/**
302+
* An IR variable representing a positional parameter.
303+
*/
304+
class IRPositionalParameter extends IRParameter, IRAutomaticUserVariable {
305+
final override int getIndex() { result = getVariable().(Language::Parameter).getIndex() }
306+
}

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,11 @@ class ReturnIndirectionInstruction extends VariableInstruction {
541541
* function.
542542
*/
543543
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
544+
545+
/**
546+
* Holds if this instruction is the return indirection for `this`.
547+
*/
548+
final predicate isThisIndirection() { var instanceof IRThisVariable }
544549
}
545550

546551
class CopyInstruction extends Instruction {

0 commit comments

Comments
 (0)