Skip to content

Commit fc530c8

Browse files
authored
Merge pull request #22548 from hvitved/unified/implicit-self
Unified: Resolve `Self` in static name binding
2 parents 201e7a4 + c0bc400 commit fc530c8

5 files changed

Lines changed: 77 additions & 0 deletions

File tree

unified/ql/lib/codeql/unified/internal/LocalNameBinding.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,12 @@ private module LocalNameBindingInput implements LocalNameBindingInputSig<Locatio
333333
name = any(NameBindingPlugin p).getImplicitReceiverParameterName(callable) and
334334
scope = callable
335335
)
336+
or
337+
exists(ClassLikeDeclaration cls |
338+
isLocalVariable = false and
339+
name = any(NameBindingPlugin p).getStaticSelfName(cls) and
340+
scope = cls
341+
)
336342
}
337343

338344
predicate implicitDeclInScope(string name, AstNode scope) { implicitDeclInScope(name, scope, _) }

unified/ql/lib/codeql/unified/internal/NameBindingPlugin.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ class NameBindingPlugin extends Unit {
4242

4343
/** Gets the name of the implicit receiver parameter in `callable`, if it has one. */
4444
string getImplicitReceiverParameterName(Callable callable) { none() }
45+
46+
/**
47+
* Gets the name through which static members of the enclosing class `cls` can be
48+
* accessed, for example `Self` in Swift.
49+
*/
50+
bindingset[cls]
51+
string getStaticSelfName(ClassLikeDeclaration cls) { none() }
4552
}
4653

4754
/** Holds if `member` is an instance member. */

unified/ql/lib/codeql/unified/internal/NameBindingPluginSwift.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ class NameBindingPluginSwift extends NameBindingPlugin {
4444
callable = any(ClassLikeDeclaration cls).getAMember() and
4545
result = "self"
4646
}
47+
48+
bindingset[cls]
49+
override string getStaticSelfName(ClassLikeDeclaration cls) { exists(cls) and result = "Self" }
4750
}
4851

4952
/** Holds if `node` is in a context where a bare name node should be seen as a reference rather than a declaration. */

unified/ql/lib/codeql/unified/internal/StaticNameBinding.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,12 @@ predicate valueStep(NameBindingNode node1, NameBindingNode node2) {
263263
)
264264
or
265265
FolderHeuristic::valueStep(node1, node2)
266+
or
267+
exists(ClassLikeDeclaration cls, LocalNameBindingOutput::ImplicitLocal self |
268+
node1.isIdentifier(cls.getNameNode()) and
269+
node2.isLocalName(self) and
270+
self.hasNameAndScope(any(NameBindingPlugin p).getStaticSelfName(cls), cls)
271+
)
266272
}
267273

268274
private predicate isImportPrefix(Expr e) {
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
private class A {
2+
let x = 123 // name=A.instance.x
3+
4+
func getX() {
5+
return self.x // not handled by static name binding
6+
}
7+
8+
static let y = 456 // name=A.type.y
9+
10+
func getY1() {
11+
return Self.y // $ access=A access=A.type.y
12+
}
13+
14+
static func getY2() {
15+
return self.y // $ not handled by static name binding
16+
}
17+
18+
class func z() -> Int { // name=A.type.z
19+
return 789
20+
}
21+
22+
class func getZ() {
23+
return self.z // $ not handled by static name binding
24+
}
25+
}
26+
27+
private class B : A { // $ access=A
28+
func getX2() {
29+
return self.x // not handled by static name binding
30+
}
31+
32+
func getY3() {
33+
return Self.y // $ access=B access=A.type.y
34+
}
35+
36+
static func getY4() {
37+
return self.y // $ not handled by static name binding
38+
}
39+
40+
class func z() -> Int { // name=B.type.z
41+
return 789
42+
}
43+
44+
class func getZ2() {
45+
return self.z // $ not handled by static name binding
46+
}
47+
}
48+
49+
private class C {
50+
static let x = 1
51+
class D {
52+
static let x = 2
53+
static let foo = Self.x // $ access=C.D access=C.D.x
54+
}
55+
}

0 commit comments

Comments
 (0)