Skip to content

Commit 2b28f75

Browse files
committed
unified: Expose handling of unqualified member accesses
UnqualifiedMemberAccess might go into Public one day
1 parent 981fc4d commit 2b28f75

2 files changed

Lines changed: 88 additions & 0 deletions

File tree

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ module Unified {
3030
not this instanceof ClassLikeDeclaration and
3131
result = this.getParent().getEnclosingClass()
3232
}
33+
34+
/** Gets the depth of this node in the AST. The root node has a depth of 0. */
35+
int getDepth() {
36+
not exists(this.getParent()) and result = 0
37+
or
38+
result = this.getParent().getDepth() + 1
39+
}
3340
}
3441

3542
/** An expression */

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

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,3 +559,84 @@ private module FolderHeuristic {
559559
)
560560
}
561561
}
562+
563+
/**
564+
* Holds if `access` may resolve to `target` through the enclosing `accessingClass`.
565+
*
566+
* `instanceAccess` indicates if this this member should be accessed as an instance of `accessingClass`
567+
* or as a static member.
568+
*/
569+
private predicate unqualifiedMemberAccessCand(
570+
PotentialLocalNameAccess access, boolean instanceAccess, NameDeclaration target,
571+
ClassLikeDeclaration accessingClass
572+
) {
573+
not access instanceof NameDeclaration and
574+
(
575+
// Resolved by local scoping
576+
exists(LocalName local |
577+
target.getLocalName() = local and
578+
access.getLocalName() = local and
579+
target.getDeclaration() = accessingClass.getAMember()
580+
|
581+
instanceAccess = true and
582+
isInstanceMember(target.getDeclaration())
583+
or
584+
instanceAccess = false and
585+
isStaticMember(target.getDeclaration())
586+
)
587+
or
588+
// Resolved in an uncertain scope
589+
exists(NamespaceNode namespace, string name |
590+
name = access.getName() and
591+
accessingClass = LocalNameBindingOutput::getAnUncertainScope(access, name)
592+
|
593+
instanceAccess = true and
594+
namespace.isInstanceMemberNamespace(accessingClass) and
595+
namespace.getMember(name).isIdentifier(target)
596+
or
597+
instanceAccess = false and
598+
namespace.isStaticMemberNamespace(accessingClass) and
599+
namespace.getMember(name).isIdentifier(target)
600+
)
601+
)
602+
}
603+
604+
private int unqualifiedMemberAccessDepth(PotentialLocalNameAccess access) {
605+
result = max(AstNode scope | unqualifiedMemberAccessCand(access, _, _, scope) | scope.getDepth())
606+
}
607+
608+
/**
609+
* Holds if `access` is an unqualified access to `target`.
610+
*
611+
* `accessingClass` is the enclosing class in which the member was found, and
612+
* `instanceAccess` indicates if it is an instance member or static member.
613+
*/
614+
predicate unqualifiedMemberAccess(
615+
PotentialLocalNameAccess access, boolean instanceAccess, NameDeclaration target,
616+
ClassLikeDeclaration accessingClass
617+
) {
618+
unqualifiedMemberAccessCand(access, instanceAccess, target, accessingClass) and
619+
accessingClass.getDepth() = unqualifiedMemberAccessDepth(access)
620+
}
621+
622+
/**
623+
* An identifier appearing in a unqualified position, referring to a member of an enclosing class.
624+
*/
625+
class UnqualifiedMemberAccess extends Identifier {
626+
private boolean instanceAccess;
627+
private NameDeclaration target;
628+
private ClassLikeDeclaration accessingClass;
629+
630+
UnqualifiedMemberAccess() {
631+
unqualifiedMemberAccess(this, instanceAccess, target, accessingClass)
632+
}
633+
634+
/** Gets the name declaration of the member being accessed. */
635+
NameDeclaration getTarget() { result = target }
636+
637+
/** Gets the enclosing class whose (possibly inherited) member is being accessed. */
638+
ClassLikeDeclaration getAccessingClass() { result = accessingClass }
639+
640+
/** Holds if this is an instance access on the accessing class. */
641+
predicate isInstanceAccess() { instanceAccess = true }
642+
}

0 commit comments

Comments
 (0)