Skip to content

Commit a358617

Browse files
committed
C#: Introduce a class for ref structs.
1 parent 20c23bb commit a358617

File tree

3 files changed

+32
-4
lines changed

3 files changed

+32
-4
lines changed

csharp/ql/lib/semmle/code/csharp/Conversion.qll

+1-1
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ private predicate convBoxingValueType(ValueType fromType, Type toType) {
656656
or
657657
toType instanceof SystemValueTypeClass
658658
) and
659-
not fromType.(Struct).isRef()
659+
not fromType.isRefLikeType()
660660
or
661661
toType = fromType.getABaseInterface+()
662662
}

csharp/ql/lib/semmle/code/csharp/Type.qll

+30-2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ class Type extends Member, TypeContainer, @type {
4848

4949
/** Holds if this type is a value type, or a type parameter that is a value type. */
5050
predicate isValueType() { none() }
51+
52+
/**
53+
* Holds if this type is a ref like type, or a type parameter that is a ref like type.
54+
*/
55+
predicate isRefLikeType() { none() }
5156
}
5257

5358
pragma[nomagic]
@@ -704,15 +709,38 @@ class Enum extends ValueType, @enum_type {
704709
* ```
705710
*/
706711
class Struct extends ValueType, @struct_type {
707-
/** Holds if this `struct` has a `ref` modifier. */
708-
predicate isRef() { this.hasModifier("ref") }
712+
/**
713+
* DEPRECATED: Use `instanceof RefStruct` instead.
714+
*
715+
* Holds if this `struct` has a `ref` modifier.
716+
*/
717+
deprecated predicate isRef() { this.hasModifier("ref") }
709718

710719
/** Holds if this `struct` has a `readonly` modifier. */
711720
predicate isReadonly() { this.hasModifier("readonly") }
712721

713722
override string getAPrimaryQlClass() { result = "Struct" }
714723
}
715724

725+
/**
726+
* A `ref struct`, for example
727+
*
728+
* ```csharp
729+
* ref struct S {
730+
* ...
731+
* }
732+
* ```
733+
*/
734+
class RefStruct extends Struct {
735+
RefStruct() { this.hasModifier("ref") }
736+
737+
override string getAPrimaryQlClass() { result = "RefStruct" }
738+
739+
override predicate isValueType() { none() }
740+
741+
override predicate isRefLikeType() { any() }
742+
}
743+
716744
/**
717745
* A `record struct`, for example
718746
* ```csharp

csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll

+1-1
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ module LocalFlow {
703703
or
704704
t = any(TypeParameter tp | not tp.isValueType())
705705
or
706-
t.(Struct).isRef()
706+
t.isRefLikeType()
707707
) and
708708
not exists(getALastEvalNode(result))
709709
}

0 commit comments

Comments
 (0)