Skip to content

Commit 75f6209

Browse files
authored
Merge pull request #10111 from github/redsun82/swift-add-methodrefexpr
Swift: synthesize `MethodRefExpr`
2 parents 812b6bd + 631d234 commit 75f6209

File tree

53 files changed

+938
-1157
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+938
-1157
lines changed

swift/codegen/generators/qlgen.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,21 +275,25 @@ def generate(opts, renderer):
275275
non_final_ipa_types = []
276276
constructor_imports = []
277277
ipa_constructor_imports = []
278+
stubs = {}
278279
for cls in sorted(data.classes.values(), key=lambda cls: (cls.dir, cls.name)):
279280
ipa_type = get_ql_ipa_class(cls)
280281
if ipa_type.is_final:
281282
final_ipa_types.append(ipa_type)
282283
if ipa_type.has_params:
283284
stub_file = stub_out / cls.dir / f"{cls.name}Constructor.qll"
284285
if not stub_file.is_file() or _is_generated_stub(stub_file):
285-
renderer.render(ql.Synth.ConstructorStub(ipa_type), stub_file)
286+
# stub rendering must be postponed as we might not have yet all subtracted ipa types in `ipa_type`
287+
stubs[stub_file] = ql.Synth.ConstructorStub(ipa_type)
286288
constructor_import = get_import(stub_file, opts.swift_dir)
287289
constructor_imports.append(constructor_import)
288290
if ipa_type.is_ipa:
289291
ipa_constructor_imports.append(constructor_import)
290292
else:
291293
non_final_ipa_types.append(ipa_type)
292294

295+
for stub_file, data in stubs.items():
296+
renderer.render(data, stub_file)
293297
renderer.render(ql.Synth.Types(schema.root_class_name, final_ipa_types, non_final_ipa_types), out / "Synth.qll")
294298
renderer.render(ql.ImportList(constructor_imports), out / "SynthConstructors.qll")
295299
renderer.render(ql.ImportList(ipa_constructor_imports), out / "PureSynthConstructors.qll")

swift/codegen/schema.yml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ DotSyntaxBaseIgnoredExpr:
419419
DynamicTypeExpr:
420420
_extends: Expr
421421
_children:
422-
base_expr: Expr
422+
base: Expr
423423

424424
EditorPlaceholderExpr:
425425
_extends: Expr
@@ -492,7 +492,7 @@ LiteralExpr:
492492
LookupExpr:
493493
_extends: Expr
494494
_children:
495-
base_expr: Expr
495+
base: Expr
496496
member: Decl?
497497

498498
MakeTemporarilyEscapableExpr:
@@ -835,7 +835,7 @@ PrefixUnaryExpr:
835835
SelfApplyExpr:
836836
_extends: ApplyExpr
837837
_children:
838-
base_expr: Expr
838+
base: Expr
839839

840840
ArrayExpr:
841841
_extends: CollectionExpr
@@ -990,6 +990,11 @@ MemberRefExpr:
990990
has_direct_to_implementation_semantics: predicate
991991
has_ordinary_semantics: predicate
992992

993+
MethodRefExpr:
994+
_extends: LookupExpr
995+
_synth:
996+
from: DotSyntaxCallExpr
997+
993998
SubscriptExpr:
994999
_extends:
9951000
- LookupExpr

swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,13 +1206,13 @@ module Exprs {
12061206
override SubscriptExpr ast;
12071207

12081208
final override predicate propagatesAbnormal(ControlFlowElement child) {
1209-
child.asAstNode() = ast.getBaseExpr().getFullyConverted()
1209+
child.asAstNode() = ast.getBase().getFullyConverted()
12101210
or
12111211
child.asAstNode() = ast.getAnArgument().getExpr().getFullyConverted()
12121212
}
12131213

12141214
final override predicate first(ControlFlowElement first) {
1215-
astFirst(ast.getBaseExpr().getFullyConverted(), first)
1215+
astFirst(ast.getBase().getFullyConverted(), first)
12161216
}
12171217

12181218
final override predicate last(ControlFlowElement last, Completion c) {
@@ -1230,7 +1230,7 @@ module Exprs {
12301230
}
12311231

12321232
override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
1233-
astLast(ast.getBaseExpr().getFullyConverted(), pred, c) and
1233+
astLast(ast.getBase().getFullyConverted(), pred, c) and
12341234
c instanceof NormalCompletion and
12351235
astFirst(ast.getFirstArgument().getExpr().getFullyConverted(), succ)
12361236
or
@@ -1296,7 +1296,7 @@ module Exprs {
12961296
override DynamicTypeExpr ast;
12971297

12981298
final override ControlFlowElement getChildElement(int i) {
1299-
result.asAstNode() = ast.getBaseExpr().getFullyConverted() and i = 0
1299+
result.asAstNode() = ast.getBase().getFullyConverted() and i = 0
13001300
}
13011301
}
13021302

@@ -1427,6 +1427,14 @@ module Exprs {
14271427
}
14281428
}
14291429

1430+
class MethodRefExprTree extends AstStandardPreOrderTree {
1431+
override MethodRefExpr ast;
1432+
1433+
override ControlFlowElement getChildElement(int i) {
1434+
i = 0 and result.asAstNode() = ast.getBase().getFullyConverted()
1435+
}
1436+
}
1437+
14301438
module MemberRefs {
14311439
/**
14321440
* The control-flow of a member reference expression.
@@ -1439,11 +1447,11 @@ module Exprs {
14391447
override MemberRefExpr ast;
14401448

14411449
final override predicate propagatesAbnormal(ControlFlowElement child) {
1442-
child.asAstNode() = ast.getBaseExpr().getFullyConverted()
1450+
child.asAstNode() = ast.getBase().getFullyConverted()
14431451
}
14441452

14451453
final override predicate first(ControlFlowElement first) {
1446-
astFirst(ast.getBaseExpr().getFullyConverted(), first)
1454+
astFirst(ast.getBase().getFullyConverted(), first)
14471455
}
14481456
}
14491457

@@ -1459,7 +1467,7 @@ module Exprs {
14591467
}
14601468

14611469
override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
1462-
astLast(ast.getBaseExpr().getFullyConverted(), pred, c) and
1470+
astLast(ast.getBase().getFullyConverted(), pred, c) and
14631471
c instanceof NormalCompletion and
14641472
succ.asAstNode() = ast
14651473
}
@@ -1489,7 +1497,7 @@ module Exprs {
14891497
}
14901498

14911499
override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
1492-
astLast(ast.getBaseExpr().getFullyConverted(), pred, c) and
1500+
astLast(ast.getBase().getFullyConverted(), pred, c) and
14931501
c instanceof NormalCompletion and
14941502
succ.asAstNode() = ast
14951503
}
@@ -1510,7 +1518,7 @@ module Exprs {
15101518
}
15111519

15121520
override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
1513-
astLast(ast.getBaseExpr().getFullyConverted(), pred, c) and
1521+
astLast(ast.getBase().getFullyConverted(), pred, c) and
15141522
c instanceof NormalCompletion and
15151523
isPropertyGetterElement(succ, accessor, ast)
15161524
}

swift/ql/lib/codeql/swift/dataflow/Ssa.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,11 @@ module Ssa {
8686
predicate isInoutDef(ExprCfgNode argument) {
8787
// TODO: This should probably not be only `ExprCfgNode`s.
8888
exists(
89-
ApplyExpr c, BasicBlock bb, int blockIndex, int argIndex, VarDecl v, InOutExpr argExpr // TODO: use CFG node for assignment expr
89+
ApplyExpr c, BasicBlock bb, int blockIndex, VarDecl v, InOutExpr argExpr // TODO: use CFG node for assignment expr
9090
|
9191
this.definesAt(v, bb, blockIndex) and
9292
bb.getNode(blockIndex).getNode().asAstNode() = c and
93-
c.getArgument(argIndex).getExpr() = argExpr and
93+
[c.getAnArgument().getExpr(), c.getQualifier()] = argExpr and
9494
argExpr = argument.getNode().asAstNode() and
9595
argExpr.getSubExpr() = v.getAnAccess() // TODO: fields?
9696
)

swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImplSpecific.qll

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,7 @@ class InterpretNode extends TInterpretNode {
154154
DataFlowCallable asCallable() { result.getUnderlyingCallable() = this.asElement() }
155155

156156
/** Gets the target of this call, if any. */
157-
AbstractFunctionDecl getCallTarget() {
158-
result = this.asCall().asCall().getFunction().(ApplyExpr).getStaticTarget()
159-
}
157+
AbstractFunctionDecl getCallTarget() { result = this.asCall().asCall().getStaticTarget() }
160158

161159
/** Gets a textual representation of this node. */
162160
string toString() {

swift/ql/lib/codeql/swift/dataflow/internal/SsaImplSpecific.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain)
2929
certain = true
3030
)
3131
or
32-
exists(ApplyExpr call, Argument arg |
33-
arg.getExpr().(InOutExpr).getSubExpr() = v.getAnAccess() and
34-
call.getAnArgument() = arg and
32+
exists(ApplyExpr call, InOutExpr expr |
33+
expr = [call.getAnArgument().getExpr(), call.getQualifier()] and
34+
expr.getSubExpr() = v.getAnAccess() and
3535
bb.getNode(i).getNode().asAstNode() = call and
3636
certain = false
3737
)

swift/ql/lib/codeql/swift/dataflow/internal/TaintTrackingPrivate.qll

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,10 @@ private module Cached {
2828
// appendInterpolation(&$interpolated, n)
2929
// appendLiteral(&$interpolated, " years old.")
3030
// ```
31-
exists(ApplyExpr apply1, ApplyExpr apply2, ExprCfgNode e |
32-
nodeFrom.asExpr() = [apply1, apply2].getAnArgument().getExpr() and
33-
apply1.getFunction() = apply2 and
34-
apply2.getStaticTarget().getName() = ["appendLiteral(_:)", "appendInterpolation(_:)"] and
35-
e.getExpr() = apply2.getAnArgument().getExpr() and
31+
exists(ApplyExpr apply, ExprCfgNode e |
32+
nodeFrom.asExpr() = [apply.getAnArgument().getExpr(), apply.getQualifier()] and
33+
apply.getStaticTarget().getName() = ["appendLiteral(_:)", "appendInterpolation(_:)"] and
34+
e.getExpr() = [apply.getAnArgument().getExpr(), apply.getQualifier()] and
3635
nodeTo.asDefinition().(Ssa::WriteDefinition).isInoutDef(e)
3736
)
3837
or

swift/ql/lib/codeql/swift/elements.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ import codeql.swift.elements.expr.MagicIdentifierLiteralExpr
137137
import codeql.swift.elements.expr.MakeTemporarilyEscapableExpr
138138
import codeql.swift.elements.expr.MemberRefExpr
139139
import codeql.swift.elements.expr.MetatypeConversionExpr
140+
import codeql.swift.elements.expr.MethodRefExpr
140141
import codeql.swift.elements.expr.NilLiteralExpr
141142
import codeql.swift.elements.expr.NumberLiteralExpr
142143
import codeql.swift.elements.expr.ObjCSelectorExpr
Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
11
private import codeql.swift.generated.expr.ApplyExpr
22
private import codeql.swift.elements.decl.AbstractFunctionDecl
33
private import codeql.swift.elements.expr.DeclRefExpr
4+
private import codeql.swift.elements.expr.MethodRefExpr
5+
private import codeql.swift.elements.expr.ConstructorRefCallExpr
46

57
class ApplyExpr extends ApplyExprBase {
6-
AbstractFunctionDecl getStaticTarget() { result = this.getFunction().(DeclRefExpr).getDecl() }
8+
AbstractFunctionDecl getStaticTarget() {
9+
exists(Expr f |
10+
f = this.getFunction() and
11+
(
12+
result = f.(DeclRefExpr).getDecl()
13+
or
14+
result = f.(ConstructorRefCallExpr).getFunction().(DeclRefExpr).getDecl()
15+
)
16+
)
17+
}
18+
19+
/** Gets the method qualifier, if this is applying a method */
20+
Expr getQualifier() { none() }
721

822
override string toString() {
923
result = "call to " + this.getStaticTarget().toString()
@@ -12,3 +26,13 @@ class ApplyExpr extends ApplyExprBase {
1226
result = "call to ..."
1327
}
1428
}
29+
30+
class MethodApplyExpr extends ApplyExpr {
31+
private MethodRefExpr method;
32+
33+
MethodApplyExpr() { method = this.getFunction() }
34+
35+
override AbstractFunctionDecl getStaticTarget() { result = method.getMethod() }
36+
37+
override Expr getQualifier() { result = method.getBase() }
38+
}

swift/ql/lib/codeql/swift/elements/expr/ArithmeticOperation.qll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class BinaryArithmeticOperation extends BinaryExpr {
4848
* ```
4949
*/
5050
class AddExpr extends BinaryExpr {
51-
AddExpr() { this.getFunction().(DotSyntaxCallExpr).getStaticTarget().getName() = "+(_:_:)" }
51+
AddExpr() { this.getStaticTarget().getName() = "+(_:_:)" }
5252
}
5353

5454
/**
@@ -58,7 +58,7 @@ class AddExpr extends BinaryExpr {
5858
* ```
5959
*/
6060
class SubExpr extends BinaryExpr {
61-
SubExpr() { this.getFunction().(DotSyntaxCallExpr).getStaticTarget().getName() = "-(_:_:)" }
61+
SubExpr() { this.getStaticTarget().getName() = "-(_:_:)" }
6262
}
6363

6464
/**
@@ -68,7 +68,7 @@ class SubExpr extends BinaryExpr {
6868
* ```
6969
*/
7070
class MulExpr extends BinaryExpr {
71-
MulExpr() { this.getFunction().(DotSyntaxCallExpr).getStaticTarget().getName() = "*(_:_:)" }
71+
MulExpr() { this.getStaticTarget().getName() = "*(_:_:)" }
7272
}
7373

7474
/**
@@ -78,7 +78,7 @@ class MulExpr extends BinaryExpr {
7878
* ```
7979
*/
8080
class DivExpr extends BinaryExpr {
81-
DivExpr() { this.getFunction().(DotSyntaxCallExpr).getStaticTarget().getName() = "/(_:_:)" }
81+
DivExpr() { this.getStaticTarget().getName() = "/(_:_:)" }
8282
}
8383

8484
/**
@@ -88,7 +88,7 @@ class DivExpr extends BinaryExpr {
8888
* ```
8989
*/
9090
class RemExpr extends BinaryExpr {
91-
RemExpr() { this.getFunction().(DotSyntaxCallExpr).getStaticTarget().getName() = "%(_:_:)" }
91+
RemExpr() { this.getStaticTarget().getName() = "%(_:_:)" }
9292
}
9393

9494
/**
@@ -108,5 +108,5 @@ class UnaryArithmeticOperation extends PrefixUnaryExpr {
108108
* ```
109109
*/
110110
class UnaryMinusExpr extends PrefixUnaryExpr {
111-
UnaryMinusExpr() { this.getFunction().(DotSyntaxCallExpr).getStaticTarget().getName() = "-(_:)" }
111+
UnaryMinusExpr() { this.getStaticTarget().getName() = "-(_:)" }
112112
}

0 commit comments

Comments
 (0)