Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2579,7 +2579,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
or
exists(Parameter p, Variable v |
implicitParameterDecl(p, v) and
result = p.getType().getTypeAt(path) and
tm = p.getType() and
n = v.getAnAccess()
)
)
Expand All @@ -2606,6 +2606,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
or
exists(VariableDeclaration decl |
decl.preservesInitializerType() and
not exists(decl.getType()) and
n1 = decl.getInitializer() and
n2 = decl.getPattern()
)
Expand Down
8 changes: 8 additions & 0 deletions unified/ql/consistency-queries/TypeInferenceConsistency.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* @name Type inference inconsistencies
* @description Lists the type inference inconsistencies in the database. This query is intended for internal use.
* @kind table
* @id unified/diagnostics/type-inference-consistency
*/

import codeql.unified.internal.typeinference.TypeInferenceConsistency
2 changes: 1 addition & 1 deletion unified/ql/lib/codeql/Definitions.qll
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ private import codeql.unified.internal.NameBinding
*/
cached
predicate definitionOf(Identifier reference, NameBinding definition, string kind) {
definition = getStaticBindingTarget(reference) and
definition = getStaticBindingTargetFromIdentifier(reference) and
not reference instanceof NameBinding and
kind = "name"
}
4 changes: 2 additions & 2 deletions unified/ql/lib/codeql/unified/internal/AnalysisQuality.qll
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module StaticNameResolutionStats implements EntityStatsSig {
*/
private predicate resolvesToValue(Identifier name) {
exists(AstNode decl |
decl = getStaticBindingTarget(name).getDeclaration() and
decl = getStaticBindingTargetFromIdentifier(name).getDeclaration() and
not decl instanceof ClassLikeDeclaration and
not decl instanceof TypeAliasDeclaration and
not decl instanceof TypeParameter and
Expand Down Expand Up @@ -49,7 +49,7 @@ module StaticNameResolutionStats implements EntityStatsSig {
}

NameBindingNode getTarget() {
result.asIdentifier() = getStaticBindingTarget(this)
result.asIdentifier() = getStaticBindingTargetFromIdentifier(this)
or
result.isModuleScopeNode(_) and
result.(NamespaceNode).ref().isIdentifier(this)
Expand Down
17 changes: 16 additions & 1 deletion unified/ql/lib/codeql/unified/internal/ExprPositions.qll
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
private import unified
private import NameBinding as NameBinding
private import ExprPositionsPlugin

/**
* Holds if `expr` appears in the context of a type annotation.
* Holds if `expr` appears in a context where it must refer to a type.
*/
predicate isInTypeContext(Expr expr) {
expr = any(TypeCastExpr n).getType()
Expand All @@ -27,8 +28,22 @@ predicate isInTypeContext(Expr expr) {
or
expr = any(AssociatedTypeDeclaration n).getBound()
or
expr = any(ClassLikeDeclaration c).getExtensionTarget()
or
expr = any(GenericTypeExpr gte).getATypeArgument()
or
expr.getParent() instanceof TypeConstraint
or
exists(Identifier id | id = NameBinding::getStaticBindingTargetFromRef(expr) |
id = any(ClassLikeDeclaration c).getNameNode()
or
id = any(TypeAliasDeclaration t).getNameNode()
or
id = any(TypeParameter t).getNameNode()
)
or
any(ExprPositionsPlugin p).isInTypeContext(expr)
or
isInTypeContext(expr.getEnclosingExpr())
}

Expand Down
10 changes: 10 additions & 0 deletions unified/ql/lib/codeql/unified/internal/ExprPositionsPlugin.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
private import unified
private import codeql.util.Unit

private module Plugins {
private import ExprPositionsPluginSwift
}

class ExprPositionsPlugin extends Unit {
predicate isInTypeContext(Expr e) { none() }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
private import unified
private import ExprPositionsPlugin

private class ExprPositionsPluginSwift extends ExprPositionsPlugin {
override predicate isInTypeContext(Expr e) { e = any(GenericTypeExpr g).getBase() }
}
15 changes: 13 additions & 2 deletions unified/ql/lib/codeql/unified/internal/FacadeAst.qll
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,7 @@ module Unified {
/** Gets a direct base class of this class. */
ClassLikeDeclaration getABaseClass() {
result.getNameNode() =
NameBinding::getStaticBindingTarget(NameBinding::getIdentifierFromRef(this.getABaseType()
.getType()))
NameBinding::getStaticBindingTargetFromRef(this.getABaseType().getType())
}
}

Expand Down Expand Up @@ -217,6 +216,12 @@ module Unified {
}
}

/** A tuple expression. */
class TupleExpr extends G::TupleExpr {
/** Gets the number of elements in this tuple expression. */
int getNumberOfElements() { result = count(this.getAnElement()) }
}

class TypeAliasDeclaration extends G::TypeAliasDeclaration {
/** Gets the name of this type alias. */
string getName() { result = this.getNameNode().getValue() }
Expand Down Expand Up @@ -274,4 +279,10 @@ module Unified {
result = count(Argument arg | arg = this.getAnArgument() and arg.isPositional())
}
}

/** A function expression. */
class FunctionExpr extends G::FunctionExpr {
/** Gets the number of parameters of this function. */
int getNumberOfParameters() { result = count(this.getAParameter()) }
}
}
21 changes: 16 additions & 5 deletions unified/ql/lib/codeql/unified/internal/StaticNameBinding.qll
Original file line number Diff line number Diff line change
Expand Up @@ -717,14 +717,25 @@ module Public {
}
}

/** Gets the declaration being accessed by `access`, as determined by static name binding. */
NameBinding getStaticBindingTarget(Identifier access) {
/** Gets the declaration being accessed by identifier `i`, as determined by static name binding. */
NameBinding getStaticBindingTargetFromIdentifier(Identifier i) {
// For unqualified accesses, use the shadowing-aware lookup
result = access.(UnqualifiedMemberAccess).getTarget()
result = i.(UnqualifiedMemberAccess).getTarget()
or
// For others, just follow the name binding graph
not access instanceof UnqualifiedMemberAccess and
trackNameBinding(result).asIdentifier() = access
not i instanceof UnqualifiedMemberAccess and
trackNameBinding(result).asIdentifier() = i
}

/**
* Gets the declaration being accessed by `access`, as determined by static name binding.
*
* Unlike `getStaticBindingTargetFromIdentifier`, this works with any AST node that contains
* a reference to an identifier, for example `x.foo` and `foo<Int>` resolve to whatever the
* identifiers `foo` resolve to.
*/
NameBinding getStaticBindingTargetFromRef(AstNode access) {
result = getStaticBindingTargetFromIdentifier(getIdentifierFromRef(access))
}

/**
Expand Down
13 changes: 2 additions & 11 deletions unified/ql/lib/codeql/unified/internal/dataflow/CallGraph.qll
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
private import unified
private import AllDataFlow
private import codeql.unified.internal.NameBinding as N

private Callable getCallableFromNameBinding(NameBinding binding) {
binding = result.(FunctionDeclaration).getNameNode()
}
private import codeql.unified.internal.typeinference.TypeInference as T

DataFlowCallable viableCallable(DataFlowCall c) {
exists(CallExpr call, Callable callable, NameBinding target |
c.asExplicitCall() = call and
target = N::getStaticBindingTarget(N::getIdentifierFromRef(call.getCallee())) and
callable = getCallableFromNameBinding(target) and
result.asSourceCallable() = callable
)
result.asSourceCallable() = T::resolveCallTarget(c.asExplicitCall())
}
Loading
Loading