Skip to content

Commit 97522c5

Browse files
committed
C#: Add more CIL consistency tests.
1 parent b776421 commit 97522c5

2 files changed

Lines changed: 74 additions & 2 deletions

File tree

csharp/ql/src/semmle/code/cil/ConsistencyChecks.qll

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,19 @@ class TypeIsBothConstructedAndUnbound extends TypeViolation {
371371
override string getMessage() { result = "Type is both constructed and unbound" }
372372
}
373373

374+
/**
375+
* The location of a constructed generic type should be the same
376+
* as the location of its unbound generic type.
377+
*/
378+
class InconsistentTypeLocation extends TypeViolation {
379+
InconsistentTypeLocation() {
380+
exists(this.getType().getLocation()) and
381+
this.getType().getLocation() != this.getType().getSourceDeclaration().getLocation()
382+
}
383+
384+
override string getMessage() { result = "Inconsistent constructed type location" }
385+
}
386+
374387
/**
375388
* A constructed type that does not match its unbound generic type.
376389
*/
@@ -403,6 +416,19 @@ class MethodViolation extends ConsistencyViolation, DeclarationCheck {
403416
override string getMessage() { none() }
404417
}
405418

419+
/**
420+
* The location of a constructed method should be equal to the
421+
* location of its unbound generic.
422+
*/
423+
class InconsistentMethodLocation extends MethodViolation {
424+
InconsistentMethodLocation() {
425+
exists(this.getMethod().getLocation()) and
426+
this.getMethod().getLocation() != this.getMethod().getSourceDeclaration().getLocation()
427+
}
428+
429+
override string getMessage() { result = "Inconsistent constructed method location" }
430+
}
431+
406432
/**
407433
* A constructed method that does not match its unbound method.
408434
*/
@@ -431,7 +457,10 @@ abstract class MissingEntityViolation extends ConsistencyViolation, MissingEntit
431457
* The type `object` is missing from the database.
432458
*/
433459
class MissingObjectViolation extends MissingEntityViolation {
434-
MissingObjectViolation() { not exists(ObjectType o) }
460+
MissingObjectViolation() {
461+
exists(this) and
462+
not exists(ObjectType o)
463+
}
435464

436465
override string getMessage() { result = "Object missing" }
437466
}
@@ -480,6 +509,43 @@ class ArrayTypeInvalidRank extends TypeViolation {
480509
override string getMessage() { result = "Invalid ArrayType.getRank()" }
481510
}
482511

512+
/**
513+
* A type should have at most one kind, except for missing referenced types
514+
* where the interface/class is unknown.
515+
*/
516+
class KindViolation extends TypeViolation {
517+
KindViolation() {
518+
count(typeKind(this.getType())) != 1 and
519+
exists(this.getType().getLocation())
520+
}
521+
522+
override string getMessage() {
523+
result = "Incorrect class/interface on type: " + concat(typeKind(this.getType()), " ")
524+
}
525+
}
526+
527+
/**
528+
* The type of a kind must be consistent between a constructed generic and its
529+
* unbound generic.
530+
*/
531+
class InconsistentKind extends TypeViolation {
532+
InconsistentKind() { typeKind(this.getType()) != typeKind(this.getType().getSourceDeclaration()) }
533+
534+
override string getMessage() { result = "Inconsistent type kind of source declaration" }
535+
}
536+
537+
private string typeKind(Type t) {
538+
t instanceof Interface and result = "interface"
539+
or
540+
t instanceof Class and result = "class"
541+
or
542+
t instanceof TypeParameter and result = "type parameter"
543+
or
544+
t instanceof ArrayType and result = "array"
545+
or
546+
t instanceof PointerType and result = "pointer"
547+
}
548+
483549
/**
484550
* A violation in a `Member`.
485551
*/

csharp/ql/src/semmle/code/cil/Generics.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,13 @@ class UnboundGenericType extends UnboundGeneric, Type { }
3535
class UnboundGenericMethod extends UnboundGeneric, Method { }
3636

3737
/** A constructed generic type. */
38-
class ConstructedType extends ConstructedGeneric, Type { }
38+
class ConstructedType extends ConstructedGeneric, Type {
39+
final override UnboundGenericType getUnboundGeneric() { result = this.getUnboundType() }
40+
41+
override predicate isInterface() { this.getUnboundType().isInterface() }
42+
43+
override predicate isClass() { this.getUnboundType().isClass() }
44+
}
3945

4046
/** A constructed generic method. */
4147
class ConstructedMethod extends ConstructedGeneric, Method {

0 commit comments

Comments
 (0)