Skip to content

Commit 49277f5

Browse files
committed
model the last parts of the EquivalenceRelation module
1 parent a11e618 commit 49277f5

File tree

5 files changed

+78
-19
lines changed

5 files changed

+78
-19
lines changed

ql/ql/src/codeql_ql/ast/Ast.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,9 +537,15 @@ class ClasslessPredicate extends TClasslessPredicate, Predicate, ModuleDeclarati
537537
|
538538
decl order by index
539539
)
540+
or
541+
toMock(result) = pred.asRight().getParameter(i)
540542
}
541543

542-
override TypeExpr getReturnTypeExpr() { toQL(result) = pred.asLeft().getReturnType() }
544+
override TypeExpr getReturnTypeExpr() {
545+
toQL(result) = pred.asLeft().getReturnType()
546+
or
547+
toMock(result) = pred.asRight().getReturnTypeExpr()
548+
}
543549

544550
override AstNode getAChild(string pred_name) {
545551
result = Predicate.super.getAChild(pred_name)

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,9 @@ class MockClasslessPredicate extends MockAst {
156156

157157
final string getName() { result = range.getName() }
158158

159-
// TODO: VarDecl.
160-
final MockAst getParameter(int i) { result.getId() = range.getParameter(i) }
159+
final MockVarDecl getParameter(int i) { result.getId() = range.getParameter(i) }
160+
161+
final MockTypeExpr getReturnTypeExpr() { result.getId() = range.getReturnTypeExpr() }
161162
}
162163

163164
module MockClasslessPredicate {
@@ -170,6 +171,10 @@ module MockClasslessPredicate {
170171

171172
/** Gets the `i`th parameter of the predicate. */
172173
abstract string getParameter(int i);
174+
175+
MockTypeExpr::Range getReturnTypeExpr() {
176+
none() // may be overridden in subclasses
177+
}
173178
}
174179
}
175180

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

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -120,16 +120,16 @@ module QlBuiltinsMocks {
120120

121121
/**
122122
* A mock that implements the `EquivalenceRelation` module.
123-
* The equivalent to the following is implemented: (TODO: WIP, MISSING THE LINES WITH //)
123+
* The equivalent to the following is implemented:
124124
* ```CodeQL
125125
* module QlBuiltins {
126126
* signature class T;
127-
* module EdgeSig<T MyT> {
127+
* module EdgeSig<T MyT> { // This might not be needed.
128128
* signature predicate edgeSig(MyT a, MyT b);
129129
* }
130-
* module EquivalenceRelation<T MyT, EdgeSig<MyT>::edgeSig/2 edge> { //
131-
* class EquivalenceClass; //
132-
* EquivalenceClass getEquivalenceClass(MyT a); //
130+
* module EquivalenceRelation<T MyT, EdgeSig<MyT>::edgeSig/2 edge> { // the `edge` parameter is not modeled
131+
* class EquivalenceClass;
132+
* EquivalenceClass getEquivalenceClass(MyT a);
133133
* }
134134
*}
135135
*/
@@ -140,25 +140,26 @@ module QlBuiltinsMocks {
140140
override string getName() { result = "T" }
141141
}
142142

143+
/** A mock TypeExpr with classname `T`. */
144+
class DummyTTypeExpr extends MockTypeExpr::Range {
145+
DummyTTypeExpr() { this = "Mock: QlBuiltins::T" }
146+
147+
override string getClassName() { result = "T" }
148+
}
149+
143150
module EdgeSig {
144151
class EdgeSigModule extends MockModule::Range {
145152
EdgeSigModule() { this = "Mock: QlBuiltins::EdgeSig" }
146153

147154
override string getName() { result = "EdgeSig" }
148155

149156
override predicate hasTypeParam(int i, string type, string name) {
150-
i = 0 and name = "MyT" and type instanceof EdgeSigType
157+
i = 0 and name = "MyT" and type instanceof DummyTTypeExpr
151158
}
152159

153160
override string getMember(int i) { i = 0 and result instanceof EdgeSigPred }
154161
}
155162

156-
class EdgeSigType extends MockTypeExpr::Range {
157-
EdgeSigType() { this = "Mock: QlBuiltins::EdgeSig::MyT" }
158-
159-
override string getClassName() { result = "MyT" }
160-
}
161-
162163
class EdgeSigPred extends MockClasslessPredicate::Range {
163164
EdgeSigPred() { this = "Mock: QlBuiltins::EdgeSig::edgeSig" }
164165

@@ -182,7 +183,7 @@ module QlBuiltinsMocks {
182183

183184
override string getName() { result = name }
184185

185-
override MockTypeExpr::Range getType() { result instanceof EdgeSigType } // TODO: I'm just using one typeexpr for everything, that might break the parent relation.
186+
override MockTypeExpr::Range getType() { result instanceof DummyTTypeExpr }
186187
}
187188
}
188189

@@ -191,9 +192,50 @@ module QlBuiltinsMocks {
191192

192193
override string getName() { result = "EquivalenceRelation" }
193194

194-
override MockModule::Range getMember(int i) {
195-
none() // TODO: EquivalenceClass/getEquivalenceClass
195+
override string getMember(int i) {
196+
i = 0 and result instanceof EquivalenceClassClass
197+
or
198+
i = 1 and result instanceof GetEquivalenceClassPredicate
199+
}
200+
201+
override predicate hasTypeParam(int i, string type, string name) {
202+
i = 0 and name = "MyT" and type instanceof DummyTTypeExpr
203+
or
204+
none() // TODO: `EdgeSig<MyT>::edgeSig/2 edge` is not implemented.
205+
}
206+
}
207+
208+
class GetEquivalenceClassPredicate extends MockClasslessPredicate::Range {
209+
GetEquivalenceClassPredicate() {
210+
this = "Mock: QlBuiltins::EquivalenceRelation::getEquivalenceClass"
211+
}
212+
213+
override string getName() { result = "getEquivalenceClass" }
214+
215+
override MockVarDecl::Range getParameter(int i) {
216+
result.(EdgeSig::EdgeSigPredParam).getName() = "a" and // just reusing another mock node that has the right name and type.
217+
i = 0
218+
}
219+
220+
override MockTypeExpr::Range getReturnTypeExpr() {
221+
result instanceof EquivalenceClassTypeExpr
222+
}
223+
}
224+
225+
class EquivalenceClassClass extends MockClass::Range {
226+
EquivalenceClassClass() {
227+
this = "Mock: QlBuiltins::EquivalenceRelation::EquivalenceClass(Class)"
228+
}
229+
230+
override string getName() { result = "EquivalenceClass" }
231+
}
232+
233+
class EquivalenceClassTypeExpr extends MockTypeExpr::Range {
234+
EquivalenceClassTypeExpr() {
235+
this = "Mock: QlBuiltins::EquivalenceRelation::EquivalenceClass(TypeExpr)"
196236
}
237+
238+
override string getClassName() { result = "EquivalenceClass" }
197239
}
198240
}
199241
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,9 @@ predicate resolveTypeExpr2(TypeExpr te, Type t) {
322322
or
323323
// e.g. alias for primitives.
324324
not exists(t.getDeclaration())
325+
or
326+
// mocks are fine.
327+
exists(AstNode decl | decl = t.getDeclaration() | exists(AstNodes::toMock(decl)))
325328
)
326329
)
327330
}

ql/ql/src/queries/diagnostics/EmptyConsistencies.ql

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import codeql_ql.ast.internal.Builtins::BuiltinsConsistency as BuiltinsConsisten
1515
import codeql_ql.ast.internal.Module::ModConsistency as ModConsistency
1616
import codeql_ql.ast.internal.Variable::VarConsistency as VarConsistency
1717
import codeql_ql.ast.internal.AstNodes::AstConsistency as AstConsistency
18+
import codeql_ql.ast.internal.AstNodes as AstNodes
1819

1920
from AstNode node, string msg
2021
where
@@ -42,7 +43,9 @@ where
4243
or
4344
AstConsistency::nonTotalGetParent(node) and msg = "AstConsistency::nonTotalGetParent"
4445
or
45-
AstConsistency::nonUniqueParent(node) and msg = "AstConsistency::nonUniqueParent"
46+
AstConsistency::nonUniqueParent(node) and
47+
msg = "AstConsistency::nonUniqueParent" and
48+
not exists(AstNodes::toMock(node)) // we don't care about the mocks, they are nasty by design.
4649
or
4750
TypeConsistency::noResolve(node) and msg = "TypeConsistency::noResolve"
4851
or

0 commit comments

Comments
 (0)