C#: Introduce a class for ref structs.

This commit is contained in:
Michael Nebel
2025-01-03 14:57:30 +01:00
parent 33939a8041
commit c439beb4b4
3 changed files with 32 additions and 4 deletions

View File

@@ -656,7 +656,7 @@ private predicate convBoxingValueType(ValueType fromType, Type toType) {
or
toType instanceof SystemValueTypeClass
) and
not fromType.(Struct).isRef()
not fromType.isRefLikeType()
or
toType = fromType.getABaseInterface+()
}

View File

@@ -48,6 +48,11 @@ class Type extends Member, TypeContainer, @type {
/** Holds if this type is a value type, or a type parameter that is a value type. */
predicate isValueType() { none() }
/**
* Holds if this type is a ref like type.
*/
predicate isRefLikeType() { none() }
}
pragma[nomagic]
@@ -704,8 +709,12 @@ class Enum extends ValueType, @enum_type {
* ```
*/
class Struct extends ValueType, @struct_type {
/** Holds if this `struct` has a `ref` modifier. */
predicate isRef() { this.hasModifier("ref") }
/**
* DEPRECATED: Use `instanceof RefStruct` instead.
*
* Holds if this `struct` has a `ref` modifier.
*/
deprecated predicate isRef() { this.hasModifier("ref") }
/** Holds if this `struct` has a `readonly` modifier. */
predicate isReadonly() { this.hasModifier("readonly") }
@@ -713,6 +722,25 @@ class Struct extends ValueType, @struct_type {
override string getAPrimaryQlClass() { result = "Struct" }
}
/**
* A `ref struct`, for example
*
* ```csharp
* ref struct S {
* ...
* }
* ```
*/
class RefStruct extends Struct {
RefStruct() { this.hasModifier("ref") }
override string getAPrimaryQlClass() { result = "RefStruct" }
override predicate isValueType() { none() }
override predicate isRefLikeType() { any() }
}
/**
* A `record struct`, for example
* ```csharp

View File

@@ -703,7 +703,7 @@ module LocalFlow {
or
t = any(TypeParameter tp | not tp.isValueType())
or
t.(Struct).isRef()
t.isRefLikeType()
) and
not exists(getALastEvalNode(result))
}