mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
model the last parts of the EquivalenceRelation module
This commit is contained in:
@@ -537,9 +537,15 @@ class ClasslessPredicate extends TClasslessPredicate, Predicate, ModuleDeclarati
|
||||
|
|
||||
decl order by index
|
||||
)
|
||||
or
|
||||
toMock(result) = pred.asRight().getParameter(i)
|
||||
}
|
||||
|
||||
override TypeExpr getReturnTypeExpr() { toQL(result) = pred.asLeft().getReturnType() }
|
||||
override TypeExpr getReturnTypeExpr() {
|
||||
toQL(result) = pred.asLeft().getReturnType()
|
||||
or
|
||||
toMock(result) = pred.asRight().getReturnTypeExpr()
|
||||
}
|
||||
|
||||
override AstNode getAChild(string pred_name) {
|
||||
result = Predicate.super.getAChild(pred_name)
|
||||
|
||||
@@ -156,8 +156,9 @@ class MockClasslessPredicate extends MockAst {
|
||||
|
||||
final string getName() { result = range.getName() }
|
||||
|
||||
// TODO: VarDecl.
|
||||
final MockAst getParameter(int i) { result.getId() = range.getParameter(i) }
|
||||
final MockVarDecl getParameter(int i) { result.getId() = range.getParameter(i) }
|
||||
|
||||
final MockTypeExpr getReturnTypeExpr() { result.getId() = range.getReturnTypeExpr() }
|
||||
}
|
||||
|
||||
module MockClasslessPredicate {
|
||||
@@ -170,6 +171,10 @@ module MockClasslessPredicate {
|
||||
|
||||
/** Gets the `i`th parameter of the predicate. */
|
||||
abstract string getParameter(int i);
|
||||
|
||||
MockTypeExpr::Range getReturnTypeExpr() {
|
||||
none() // may be overridden in subclasses
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -120,16 +120,16 @@ module QlBuiltinsMocks {
|
||||
|
||||
/**
|
||||
* A mock that implements the `EquivalenceRelation` module.
|
||||
* The equivalent to the following is implemented: (TODO: WIP, MISSING THE LINES WITH //)
|
||||
* The equivalent to the following is implemented:
|
||||
* ```CodeQL
|
||||
* module QlBuiltins {
|
||||
* signature class T;
|
||||
* module EdgeSig<T MyT> {
|
||||
* module EdgeSig<T MyT> { // This might not be needed.
|
||||
* signature predicate edgeSig(MyT a, MyT b);
|
||||
* }
|
||||
* module EquivalenceRelation<T MyT, EdgeSig<MyT>::edgeSig/2 edge> { //
|
||||
* class EquivalenceClass; //
|
||||
* EquivalenceClass getEquivalenceClass(MyT a); //
|
||||
* module EquivalenceRelation<T MyT, EdgeSig<MyT>::edgeSig/2 edge> { // the `edge` parameter is not modeled
|
||||
* class EquivalenceClass;
|
||||
* EquivalenceClass getEquivalenceClass(MyT a);
|
||||
* }
|
||||
*}
|
||||
*/
|
||||
@@ -140,6 +140,13 @@ module QlBuiltinsMocks {
|
||||
override string getName() { result = "T" }
|
||||
}
|
||||
|
||||
/** A mock TypeExpr with classname `T`. */
|
||||
class DummyTTypeExpr extends MockTypeExpr::Range {
|
||||
DummyTTypeExpr() { this = "Mock: QlBuiltins::T" }
|
||||
|
||||
override string getClassName() { result = "T" }
|
||||
}
|
||||
|
||||
module EdgeSig {
|
||||
class EdgeSigModule extends MockModule::Range {
|
||||
EdgeSigModule() { this = "Mock: QlBuiltins::EdgeSig" }
|
||||
@@ -147,18 +154,12 @@ module QlBuiltinsMocks {
|
||||
override string getName() { result = "EdgeSig" }
|
||||
|
||||
override predicate hasTypeParam(int i, string type, string name) {
|
||||
i = 0 and name = "MyT" and type instanceof EdgeSigType
|
||||
i = 0 and name = "MyT" and type instanceof DummyTTypeExpr
|
||||
}
|
||||
|
||||
override string getMember(int i) { i = 0 and result instanceof EdgeSigPred }
|
||||
}
|
||||
|
||||
class EdgeSigType extends MockTypeExpr::Range {
|
||||
EdgeSigType() { this = "Mock: QlBuiltins::EdgeSig::MyT" }
|
||||
|
||||
override string getClassName() { result = "MyT" }
|
||||
}
|
||||
|
||||
class EdgeSigPred extends MockClasslessPredicate::Range {
|
||||
EdgeSigPred() { this = "Mock: QlBuiltins::EdgeSig::edgeSig" }
|
||||
|
||||
@@ -182,7 +183,7 @@ module QlBuiltinsMocks {
|
||||
|
||||
override string getName() { result = name }
|
||||
|
||||
override MockTypeExpr::Range getType() { result instanceof EdgeSigType } // TODO: I'm just using one typeexpr for everything, that might break the parent relation.
|
||||
override MockTypeExpr::Range getType() { result instanceof DummyTTypeExpr }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,9 +192,50 @@ module QlBuiltinsMocks {
|
||||
|
||||
override string getName() { result = "EquivalenceRelation" }
|
||||
|
||||
override MockModule::Range getMember(int i) {
|
||||
none() // TODO: EquivalenceClass/getEquivalenceClass
|
||||
override string getMember(int i) {
|
||||
i = 0 and result instanceof EquivalenceClassClass
|
||||
or
|
||||
i = 1 and result instanceof GetEquivalenceClassPredicate
|
||||
}
|
||||
|
||||
override predicate hasTypeParam(int i, string type, string name) {
|
||||
i = 0 and name = "MyT" and type instanceof DummyTTypeExpr
|
||||
or
|
||||
none() // TODO: `EdgeSig<MyT>::edgeSig/2 edge` is not implemented.
|
||||
}
|
||||
}
|
||||
|
||||
class GetEquivalenceClassPredicate extends MockClasslessPredicate::Range {
|
||||
GetEquivalenceClassPredicate() {
|
||||
this = "Mock: QlBuiltins::EquivalenceRelation::getEquivalenceClass"
|
||||
}
|
||||
|
||||
override string getName() { result = "getEquivalenceClass" }
|
||||
|
||||
override MockVarDecl::Range getParameter(int i) {
|
||||
result.(EdgeSig::EdgeSigPredParam).getName() = "a" and // just reusing another mock node that has the right name and type.
|
||||
i = 0
|
||||
}
|
||||
|
||||
override MockTypeExpr::Range getReturnTypeExpr() {
|
||||
result instanceof EquivalenceClassTypeExpr
|
||||
}
|
||||
}
|
||||
|
||||
class EquivalenceClassClass extends MockClass::Range {
|
||||
EquivalenceClassClass() {
|
||||
this = "Mock: QlBuiltins::EquivalenceRelation::EquivalenceClass(Class)"
|
||||
}
|
||||
|
||||
override string getName() { result = "EquivalenceClass" }
|
||||
}
|
||||
|
||||
class EquivalenceClassTypeExpr extends MockTypeExpr::Range {
|
||||
EquivalenceClassTypeExpr() {
|
||||
this = "Mock: QlBuiltins::EquivalenceRelation::EquivalenceClass(TypeExpr)"
|
||||
}
|
||||
|
||||
override string getClassName() { result = "EquivalenceClass" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,6 +322,9 @@ predicate resolveTypeExpr2(TypeExpr te, Type t) {
|
||||
or
|
||||
// e.g. alias for primitives.
|
||||
not exists(t.getDeclaration())
|
||||
or
|
||||
// mocks are fine.
|
||||
exists(AstNode decl | decl = t.getDeclaration() | exists(AstNodes::toMock(decl)))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import codeql_ql.ast.internal.Builtins::BuiltinsConsistency as BuiltinsConsisten
|
||||
import codeql_ql.ast.internal.Module::ModConsistency as ModConsistency
|
||||
import codeql_ql.ast.internal.Variable::VarConsistency as VarConsistency
|
||||
import codeql_ql.ast.internal.AstNodes::AstConsistency as AstConsistency
|
||||
import codeql_ql.ast.internal.AstNodes as AstNodes
|
||||
|
||||
from AstNode node, string msg
|
||||
where
|
||||
@@ -42,7 +43,9 @@ where
|
||||
or
|
||||
AstConsistency::nonTotalGetParent(node) and msg = "AstConsistency::nonTotalGetParent"
|
||||
or
|
||||
AstConsistency::nonUniqueParent(node) and msg = "AstConsistency::nonUniqueParent"
|
||||
AstConsistency::nonUniqueParent(node) and
|
||||
msg = "AstConsistency::nonUniqueParent" and
|
||||
not exists(AstNodes::toMock(node)) // we don't care about the mocks, they are nasty by design.
|
||||
or
|
||||
TypeConsistency::noResolve(node) and msg = "TypeConsistency::noResolve"
|
||||
or
|
||||
|
||||
Reference in New Issue
Block a user