Skip to content

Commit 36248cc

Browse files
authored
QL: Merge pull request #15 from github/inheritance
Resolve inheritable members (fields and member predicates)
2 parents 3a3f809 + d4d7c6d commit 36248cc

2 files changed

Lines changed: 85 additions & 0 deletions

File tree

ql/src/codeql_ql/ast/Ast.qll

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ class Predicate extends TPredicate, AstNode {
106106
*/
107107
VarDecl getParameter(int i) { none() }
108108

109+
int getArity() { result = count(getParameter(_)) }
110+
109111
// TODO: ReturnType.
110112
override AstNode getAChild(string pred) {
111113
pred = "getBody" and result = this.getBody()
@@ -212,11 +214,22 @@ class ClassPredicate extends TClassPredicate, Predicate {
212214

213215
override Class getParent() { result.getAClassPredicate() = this }
214216

217+
predicate isPrivate() {
218+
exists(Generated::ClassMember member |
219+
pred = member.getChild(_) and
220+
member.getAFieldOrChild().(Generated::Annotation).getName().getValue() = "private"
221+
)
222+
}
223+
215224
override VarDecl getParameter(int i) {
216225
toGenerated(result) =
217226
rank[i](Generated::VarDecl decl, int index | decl = pred.getChild(index) | decl order by index)
218227
}
219228

229+
ClassType getDeclaringType() { result.getDeclaration() = getParent() }
230+
231+
predicate overrides(ClassPredicate other) { predOverrides(this, other) }
232+
220233
override AstNode getAChild(string pred_name) {
221234
pred_name = "getBody" and result = this.getBody()
222235
or
@@ -270,6 +283,18 @@ class VarDecl extends TVarDecl, AstNode {
270283

271284
TypeExpr getType() { toGenerated(result) = var.getChild(0) }
272285

286+
predicate isPrivate() {
287+
exists(Generated::ClassMember member |
288+
var = member.getChild(_).(Generated::Field).getChild() and
289+
member.getAFieldOrChild().(Generated::Annotation).getName().getValue() = "private"
290+
)
291+
}
292+
293+
/** If this is a field, returns the class type that declares it. */
294+
ClassType getDeclaringType() { result.getDeclaration().getAField() = this }
295+
296+
predicate overrides(VarDecl other) { fieldOverrides(this, other) }
297+
273298
override AstNode getAChild(string pred) { pred = "getType" and result = this.getType() }
274299
}
275300

@@ -451,6 +476,9 @@ class Class extends TClass, TypeDeclaration, ModuleDeclaration {
451476
toGenerated(result) = cls.getChild(_).(Generated::TypeUnionBody).getChild(_)
452477
}
453478

479+
/** Gets the class type defined by this class declaration. */
480+
Type getType() { result.getDeclaration() = this }
481+
454482
override AstNode getAChild(string pred) {
455483
pred = "getAliasType" and result = this.getAliasType()
456484
or

ql/src/codeql_ql/ast/internal/Type.qll

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,63 @@ class ClassType extends Type, TClass {
7777
or
7878
result = super.getAnInternalSuperType()
7979
}
80+
81+
ClassPredicate getClassPredicate(string name, int arity) {
82+
result = classPredCandidate(this, name, arity) and
83+
not exists(ClassPredicate other | other = classPredCandidate(this, name, arity) |
84+
other.getDeclaringType().getASuperType+() = result.getDeclaringType()
85+
)
86+
}
87+
88+
VarDecl getField(string name) {
89+
result = fieldCandidate(this, name) and
90+
not exists(VarDecl other | other = fieldCandidate(this, name) |
91+
other.getDeclaringType().getASuperType+() = result.getDeclaringType()
92+
)
93+
}
94+
}
95+
96+
private ClassPredicate declaredPred(ClassType ty, string name, int arity) {
97+
result = ty.getDeclaration().getAClassPredicate() and
98+
result.getName() = name and
99+
result.getArity() = arity
100+
}
101+
102+
private ClassPredicate classPredCandidate(ClassType ty, string name, int arity) {
103+
result = declaredPred(ty, name, arity)
104+
or
105+
not exists(declaredPred(ty, name, arity)) and
106+
result = inherClassPredCandidate(ty, name, arity)
107+
}
108+
109+
private ClassPredicate inherClassPredCandidate(ClassType ty, string name, int arity) {
110+
result = classPredCandidate(ty.getASuperType(), name, arity) and
111+
not result.isPrivate()
112+
}
113+
114+
predicate predOverrides(ClassPredicate sub, ClassPredicate sup) {
115+
sup = inherClassPredCandidate(sub.getDeclaringType(), sub.getName(), sub.getArity())
116+
}
117+
118+
private VarDecl declaredField(ClassType ty, string name) {
119+
result = ty.getDeclaration().getAField() and
120+
result.getName() = name
121+
}
122+
123+
private VarDecl fieldCandidate(ClassType ty, string name) {
124+
result = declaredField(ty, name)
125+
or
126+
not exists(declaredField(ty, name)) and
127+
result = inherFieldCandidate(ty, name)
128+
}
129+
130+
private VarDecl inherFieldCandidate(ClassType ty, string name) {
131+
result = fieldCandidate(ty.getASuperType(), name) and
132+
not result.isPrivate()
133+
}
134+
135+
predicate fieldOverrides(VarDecl sub, VarDecl sup) {
136+
sup = inherFieldCandidate(sub.getDeclaringType(), sub.getName())
80137
}
81138

82139
class ClassCharType extends Type, TClassChar {

0 commit comments

Comments
 (0)