Merge pull request #7605 from michaelnebel/csharp/record-struct

C#: Support for record structs
This commit is contained in:
Michael Nebel
2022-01-19 10:39:52 +01:00
committed by GitHub
15 changed files with 169 additions and 81 deletions

View File

@@ -111,6 +111,9 @@ namespace Semmle.Extraction.CSharp.Entities
if (nt is null)
throw new InternalError(symbol, "Symbol kind is inconsistent with its type");
if (nt.IsRecord)
HasModifier(cx, trapFile, key, "record");
if (nt.TypeKind == TypeKind.Struct)
{
if (nt.IsReadOnly)

View File

@@ -61,7 +61,7 @@ class Class extends ValueOrRefType {
}
/** A `record`. */
class Record extends Class {
deprecated class Record extends Class {
Record() { this.isRecord() }
}

View File

@@ -372,6 +372,8 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_
nested_types(this, _, result)
}
override predicate isRecord() { this.hasModifier("record") }
override string toString() { result = Type.super.toString() }
}
@@ -449,6 +451,14 @@ class SimpleType extends ValueType, @simple_type {
override SystemNamespace getDeclaringNamespace() { any() }
}
/**
* A `record` like type.
* This can be either a `class` or a `struct`.
*/
class RecordType extends ValueOrRefType {
RecordType() { this.isRecord() }
}
/**
* The Boolean type, `bool`.
*/
@@ -711,6 +721,18 @@ class Struct extends ValueType, @struct_type {
override string getAPrimaryQlClass() { result = "Struct" }
}
/**
* A `record struct`, for example
* ```csharp
* record struct RS {
* ...
* }
* ```
*/
class RecordStruct extends RecordType, Struct {
override string getAPrimaryQlClass() { result = "RecordStruct" }
}
/**
* A reference type.
*
@@ -765,6 +787,16 @@ class Class extends RefType, @class_type {
override string getAPrimaryQlClass() { result = "Class" }
}
/**
* DEPRECATED: Use `RecordClass` instead.
*/
deprecated class Record extends Class {
Record() { this.isRecord() }
/** Gets the clone method of this record. */
RecordCloneMethod getCloneMethod() { result = this.getAMember() }
}
/**
* A `record`, for example
*
@@ -774,13 +806,11 @@ class Class extends RefType, @class_type {
* }
* ```
*/
class Record extends Class {
Record() { this.isRecord() }
class RecordClass extends RecordType, Class {
/** Gets the clone method of this record. */
RecordCloneMethod getCloneMethod() { result = this.getAMember() }
override string getAPrimaryQlClass() { result = "Record" }
override string getAPrimaryQlClass() { result = "RecordClass" }
}
/**

View File

@@ -111,7 +111,7 @@ module SummaryComponentStack {
class SummarizedCallable = Impl::Public::SummarizedCallable;
private predicate recordConstructorFlow(Constructor c, int i, Property p) {
c = any(Record r).getAMember() and
c = any(RecordType r).getAMember() and
exists(string name |
c.getParameter(i).getName() = name and
c.getDeclaringType().getAMember(name) = p

View File

@@ -1175,7 +1175,9 @@ class WithExpr extends Expr, @with_expr {
Expr getExpr() { result = this.getChild(0) }
/** Gets the clone method of the `record` that is targetted by this `with` expression. */
RecordCloneMethod getCloneMethod() { result = this.getExpr().getType().(Record).getCloneMethod() }
RecordCloneMethod getCloneMethod() {
result = this.getExpr().getType().(RecordClass).getCloneMethod()
}
override string toString() { result = "... with { ... }" }

View File

@@ -1,6 +0,0 @@
using System;
public record MyEntry(string Name, string Address)
{
sealed public override string ToString() => $"{Name} lives at {Address}";
};

View File

@@ -0,0 +1,12 @@
using System;
public record MyEntry(string Name, string Address)
{
sealed public override string ToString() => $"{Name} lives at {Address}";
};
public record class MyClassRecord(DateTime stuff) { }
public readonly record struct MyReadonlyRecordStruct(string Stuff) { }
public record struct MyRecordStruct(int Stuff) { }

View File

@@ -1 +1 @@
| RecordTypeSealedToString.cs:5:35:5:42 | ToString |
| RecordTypes.cs:5:35:5:42 | ToString |

View File

@@ -0,0 +1,11 @@
recordTypes
| RecordTypes.cs:3:1:6:2 | MyEntry |
| RecordTypes.cs:8:1:8:53 | MyClassRecord |
| RecordTypes.cs:10:1:10:70 | MyReadonlyRecordStruct |
| RecordTypes.cs:12:1:12:50 | MyRecordStruct |
recordStructs
| RecordTypes.cs:10:1:10:70 | MyReadonlyRecordStruct |
| RecordTypes.cs:12:1:12:50 | MyRecordStruct |
recordClass
| RecordTypes.cs:3:1:6:2 | MyEntry |
| RecordTypes.cs:8:1:8:53 | MyClassRecord |

View File

@@ -0,0 +1,7 @@
import csharp
query predicate recordTypes(RecordType rt) { any() }
query predicate recordStructs(RecordStruct rs) { any() }
query predicate recordClass(RecordClass r) { any() }

View File

@@ -776,7 +776,7 @@ ParenthesizedPattern.cs:
# 26| 0: [TypeMention] string
# 26| 2: [IntLiteral] 5
Record.cs:
# 4| [Record] Person
# 4| [RecordClass] Person
# 4| 11: [NEOperator] !=
#-----| 2: (Parameters)
# 4| 0: [Parameter] left
@@ -806,7 +806,7 @@ Record.cs:
# 9| 1: [TupleExpr] (..., ...)
# 9| 0: [ParameterAccess] access to parameter first
# 9| 1: [ParameterAccess] access to parameter last
# 12| [Record] Teacher
# 12| [RecordClass] Teacher
# 12| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 12| 0: [Parameter] left
@@ -834,7 +834,7 @@ Record.cs:
# 17| 4: [AssignExpr] ... = ...
# 17| 0: [PropertyCall] access to property Subject
# 17| 1: [ParameterAccess] access to parameter sub
# 20| [Record] Student
# 20| [RecordClass] Student
# 20| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 20| 0: [Parameter] left
@@ -862,7 +862,7 @@ Record.cs:
# 24| 4: [AssignExpr] ... = ...
# 24| 0: [PropertyCall] access to property Level
# 24| 1: [ParameterAccess] access to parameter level
# 27| [Record] Person1
# 27| [RecordClass] Person1
# 27| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 27| 0: [Parameter] left
@@ -889,7 +889,7 @@ Record.cs:
# 27| 4: [Setter] set_LastName
#-----| 2: (Parameters)
# 27| 0: [Parameter] value
# 29| [Record] Teacher1
# 29| [RecordClass] Teacher1
# 29| 13: [NEOperator] !=
#-----| 2: (Parameters)
# 29| 0: [Parameter] left
@@ -913,7 +913,7 @@ Record.cs:
# 29| 4: [Setter] set_Subject
#-----| 2: (Parameters)
# 29| 0: [Parameter] value
# 32| [Record] Student1
# 32| [RecordClass] Student1
# 32| 13: [NEOperator] !=
#-----| 2: (Parameters)
# 32| 0: [Parameter] left
@@ -937,7 +937,7 @@ Record.cs:
# 32| 4: [Setter] set_Level
#-----| 2: (Parameters)
# 32| 0: [Parameter] value
# 35| [Record] Pet
# 35| [RecordClass] Pet
# 35| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 35| 0: [Parameter] left
@@ -963,7 +963,7 @@ Record.cs:
# 38| -1: [TypeAccess] access to type Console
# 38| 0: [TypeMention] Console
# 38| 0: [StringLiteral] "Shredding furniture"
# 41| [Record] Dog
# 41| [RecordClass] Dog
# 41| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 41| 0: [Parameter] left
@@ -1002,7 +1002,7 @@ Record.cs:
# 50| 0: [MethodCall] call to method ToString
# 50| -1: [LocalVariableAccess] access to local variable s
# 50| 1: [StringLiteral] " is a dog"
# 54| [Record] R1
# 54| [RecordClass] R1
# 54| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 54| 0: [Parameter] left
@@ -1022,7 +1022,7 @@ Record.cs:
# 54| 4: [Setter] set_A
#-----| 2: (Parameters)
# 54| 0: [Parameter] value
# 56| [Record] R2
# 56| [RecordClass] R2
# 56| 13: [NEOperator] !=
#-----| 2: (Parameters)
# 56| 0: [Parameter] left

View File

@@ -1,6 +1,6 @@
import csharp
query predicate records(Record t, string i, RecordCloneMethod clone) {
query predicate records(RecordClass t, string i, RecordCloneMethod clone) {
t.getABaseInterface().toStringWithTypes() = i and
clone = t.getCloneMethod() and
t.fromSource()
@@ -10,7 +10,7 @@ private string getMemberName(Member m) {
result = m.getDeclaringType().getQualifiedName() + "." + m.toStringWithTypes()
}
query predicate members(Record t, string ms, string l) {
query predicate members(RecordClass t, string ms, string l) {
t.fromSource() and
exists(Member m | t.hasMember(m) |
ms = getMemberName(m) and

View File

@@ -776,28 +776,36 @@ edges
| I.cs:39:9:39:9 | access to parameter i [field Field1] : Object | I.cs:40:14:40:14 | access to parameter i [field Field1] : Object |
| I.cs:40:14:40:14 | access to parameter i [field Field1] : Object | I.cs:40:14:40:21 | access to field Field1 |
| I.cs:40:14:40:14 | access to parameter i [field Field1] : Object | I.cs:40:14:40:21 | access to field Field1 |
| J.cs:12:17:12:33 | call to method Source<Object> : Object | J.cs:13:29:13:29 | access to local variable o : Object |
| J.cs:12:17:12:33 | call to method Source<Object> : Object | J.cs:13:29:13:29 | access to local variable o : Object |
| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object |
| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object |
| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object |
| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object |
| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object |
| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object |
| J.cs:13:29:13:29 | access to local variable o : Object | J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object |
| J.cs:13:29:13:29 | access to local variable o : Object | J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object |
| J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | J.cs:14:14:14:21 | access to property Prop1 |
| J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | J.cs:14:14:14:21 | access to property Prop1 |
| J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | J.cs:18:14:18:21 | access to property Prop1 |
| J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | J.cs:18:14:18:21 | access to property Prop1 |
| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object |
| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object |
| J.cs:21:36:21:52 | call to method Source<Object> : Object | J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object |
| J.cs:21:36:21:52 | call to method Source<Object> : Object | J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object |
| J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | J.cs:22:14:22:21 | access to property Prop1 |
| J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | J.cs:22:14:22:21 | access to property Prop1 |
| J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | J.cs:23:14:23:21 | access to property Prop2 |
| J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | J.cs:23:14:23:21 | access to property Prop2 |
| J.cs:14:17:14:33 | call to method Source<Object> : Object | J.cs:15:34:15:34 | access to local variable o : Object |
| J.cs:14:17:14:33 | call to method Source<Object> : Object | J.cs:15:34:15:34 | access to local variable o : Object |
| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:16:14:16:15 | access to local variable r1 [property Prop1] : Object |
| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:16:14:16:15 | access to local variable r1 [property Prop1] : Object |
| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:20:14:20:15 | access to local variable r2 [property Prop1] : Object |
| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:20:14:20:15 | access to local variable r2 [property Prop1] : Object |
| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:24:14:24:15 | access to local variable r3 [property Prop1] : Object |
| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:24:14:24:15 | access to local variable r3 [property Prop1] : Object |
| J.cs:15:34:15:34 | access to local variable o : Object | J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object |
| J.cs:15:34:15:34 | access to local variable o : Object | J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object |
| J.cs:16:14:16:15 | access to local variable r1 [property Prop1] : Object | J.cs:16:14:16:21 | access to property Prop1 |
| J.cs:16:14:16:15 | access to local variable r1 [property Prop1] : Object | J.cs:16:14:16:21 | access to property Prop1 |
| J.cs:20:14:20:15 | access to local variable r2 [property Prop1] : Object | J.cs:20:14:20:21 | access to property Prop1 |
| J.cs:20:14:20:15 | access to local variable r2 [property Prop1] : Object | J.cs:20:14:20:21 | access to property Prop1 |
| J.cs:23:18:23:54 | ... with { ... } [property Prop2] : Object | J.cs:25:14:25:15 | access to local variable r3 [property Prop2] : Object |
| J.cs:23:18:23:54 | ... with { ... } [property Prop2] : Object | J.cs:25:14:25:15 | access to local variable r3 [property Prop2] : Object |
| J.cs:23:36:23:52 | call to method Source<Object> : Object | J.cs:23:18:23:54 | ... with { ... } [property Prop2] : Object |
| J.cs:23:36:23:52 | call to method Source<Object> : Object | J.cs:23:18:23:54 | ... with { ... } [property Prop2] : Object |
| J.cs:24:14:24:15 | access to local variable r3 [property Prop1] : Object | J.cs:24:14:24:21 | access to property Prop1 |
| J.cs:24:14:24:15 | access to local variable r3 [property Prop1] : Object | J.cs:24:14:24:21 | access to property Prop1 |
| J.cs:25:14:25:15 | access to local variable r3 [property Prop2] : Object | J.cs:25:14:25:21 | access to property Prop2 |
| J.cs:25:14:25:15 | access to local variable r3 [property Prop2] : Object | J.cs:25:14:25:21 | access to property Prop2 |
| J.cs:34:17:34:33 | call to method Source<Object> : Object | J.cs:35:35:35:35 | access to local variable o : Object |
| J.cs:34:17:34:33 | call to method Source<Object> : Object | J.cs:35:35:35:35 | access to local variable o : Object |
| J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:36:14:36:15 | access to local variable r1 [property Prop1] : Object |
| J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:36:14:36:15 | access to local variable r1 [property Prop1] : Object |
| J.cs:35:35:35:35 | access to local variable o : Object | J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object |
| J.cs:35:35:35:35 | access to local variable o : Object | J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object |
| J.cs:36:14:36:15 | access to local variable r1 [property Prop1] : Object | J.cs:36:14:36:21 | access to property Prop1 |
| J.cs:36:14:36:15 | access to local variable r1 [property Prop1] : Object | J.cs:36:14:36:21 | access to property Prop1 |
nodes
| A.cs:5:17:5:28 | call to method Source<C> : C | semmle.label | call to method Source<C> : C |
| A.cs:5:17:5:28 | call to method Source<C> : C | semmle.label | call to method Source<C> : C |
@@ -1637,32 +1645,42 @@ nodes
| I.cs:40:14:40:14 | access to parameter i [field Field1] : Object | semmle.label | access to parameter i [field Field1] : Object |
| I.cs:40:14:40:21 | access to field Field1 | semmle.label | access to field Field1 |
| I.cs:40:14:40:21 | access to field Field1 | semmle.label | access to field Field1 |
| J.cs:12:17:12:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
| J.cs:12:17:12:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | semmle.label | object creation of type Record [property Prop1] : Object |
| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | semmle.label | object creation of type Record [property Prop1] : Object |
| J.cs:13:29:13:29 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| J.cs:13:29:13:29 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object |
| J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object |
| J.cs:14:14:14:21 | access to property Prop1 | semmle.label | access to property Prop1 |
| J.cs:14:14:14:21 | access to property Prop1 | semmle.label | access to property Prop1 |
| J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object |
| J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object |
| J.cs:18:14:18:21 | access to property Prop1 | semmle.label | access to property Prop1 |
| J.cs:18:14:18:21 | access to property Prop1 | semmle.label | access to property Prop1 |
| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object |
| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object |
| J.cs:21:36:21:52 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
| J.cs:21:36:21:52 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
| J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object |
| J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object |
| J.cs:22:14:22:21 | access to property Prop1 | semmle.label | access to property Prop1 |
| J.cs:22:14:22:21 | access to property Prop1 | semmle.label | access to property Prop1 |
| J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object |
| J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object |
| J.cs:23:14:23:21 | access to property Prop2 | semmle.label | access to property Prop2 |
| J.cs:23:14:23:21 | access to property Prop2 | semmle.label | access to property Prop2 |
| J.cs:14:17:14:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
| J.cs:14:17:14:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | semmle.label | object creation of type RecordClass [property Prop1] : Object |
| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | semmle.label | object creation of type RecordClass [property Prop1] : Object |
| J.cs:15:34:15:34 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| J.cs:15:34:15:34 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| J.cs:16:14:16:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object |
| J.cs:16:14:16:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object |
| J.cs:16:14:16:21 | access to property Prop1 | semmle.label | access to property Prop1 |
| J.cs:16:14:16:21 | access to property Prop1 | semmle.label | access to property Prop1 |
| J.cs:20:14:20:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object |
| J.cs:20:14:20:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object |
| J.cs:20:14:20:21 | access to property Prop1 | semmle.label | access to property Prop1 |
| J.cs:20:14:20:21 | access to property Prop1 | semmle.label | access to property Prop1 |
| J.cs:23:18:23:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object |
| J.cs:23:18:23:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object |
| J.cs:23:36:23:52 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
| J.cs:23:36:23:52 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
| J.cs:24:14:24:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object |
| J.cs:24:14:24:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object |
| J.cs:24:14:24:21 | access to property Prop1 | semmle.label | access to property Prop1 |
| J.cs:24:14:24:21 | access to property Prop1 | semmle.label | access to property Prop1 |
| J.cs:25:14:25:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object |
| J.cs:25:14:25:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object |
| J.cs:25:14:25:21 | access to property Prop2 | semmle.label | access to property Prop2 |
| J.cs:25:14:25:21 | access to property Prop2 | semmle.label | access to property Prop2 |
| J.cs:34:17:34:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
| J.cs:34:17:34:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
| J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | semmle.label | object creation of type RecordStruct [property Prop1] : Object |
| J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | semmle.label | object creation of type RecordStruct [property Prop1] : Object |
| J.cs:35:35:35:35 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| J.cs:35:35:35:35 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| J.cs:36:14:36:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object |
| J.cs:36:14:36:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object |
| J.cs:36:14:36:21 | access to property Prop1 | semmle.label | access to property Prop1 |
| J.cs:36:14:36:21 | access to property Prop1 | semmle.label | access to property Prop1 |
subpaths
| A.cs:6:24:6:24 | access to local variable c : C | A.cs:147:32:147:32 | c : C | A.cs:149:20:149:27 | object creation of type B [field c] : C | A.cs:6:17:6:25 | call to method Make [field c] : C |
| A.cs:6:24:6:24 | access to local variable c : C | A.cs:147:32:147:32 | c : C | A.cs:149:20:149:27 | object creation of type B [field c] : C | A.cs:6:17:6:25 | call to method Make [field c] : C |
@@ -1815,7 +1833,8 @@ subpaths
| I.cs:23:14:23:21 | access to field Field1 | I.cs:7:18:7:34 | call to method Source<Object> : Object | I.cs:23:14:23:21 | access to field Field1 | $@ | I.cs:7:18:7:34 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| I.cs:27:14:27:21 | access to field Field1 | I.cs:7:18:7:34 | call to method Source<Object> : Object | I.cs:27:14:27:21 | access to field Field1 | $@ | I.cs:7:18:7:34 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| I.cs:40:14:40:21 | access to field Field1 | I.cs:31:13:31:29 | call to method Source<Object> : Object | I.cs:40:14:40:21 | access to field Field1 | $@ | I.cs:31:13:31:29 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| J.cs:14:14:14:21 | access to property Prop1 | J.cs:12:17:12:33 | call to method Source<Object> : Object | J.cs:14:14:14:21 | access to property Prop1 | $@ | J.cs:12:17:12:33 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| J.cs:18:14:18:21 | access to property Prop1 | J.cs:12:17:12:33 | call to method Source<Object> : Object | J.cs:18:14:18:21 | access to property Prop1 | $@ | J.cs:12:17:12:33 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| J.cs:22:14:22:21 | access to property Prop1 | J.cs:12:17:12:33 | call to method Source<Object> : Object | J.cs:22:14:22:21 | access to property Prop1 | $@ | J.cs:12:17:12:33 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| J.cs:23:14:23:21 | access to property Prop2 | J.cs:21:36:21:52 | call to method Source<Object> : Object | J.cs:23:14:23:21 | access to property Prop2 | $@ | J.cs:21:36:21:52 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| J.cs:16:14:16:21 | access to property Prop1 | J.cs:14:17:14:33 | call to method Source<Object> : Object | J.cs:16:14:16:21 | access to property Prop1 | $@ | J.cs:14:17:14:33 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| J.cs:20:14:20:21 | access to property Prop1 | J.cs:14:17:14:33 | call to method Source<Object> : Object | J.cs:20:14:20:21 | access to property Prop1 | $@ | J.cs:14:17:14:33 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| J.cs:24:14:24:21 | access to property Prop1 | J.cs:14:17:14:33 | call to method Source<Object> : Object | J.cs:24:14:24:21 | access to property Prop1 | $@ | J.cs:14:17:14:33 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| J.cs:25:14:25:21 | access to property Prop2 | J.cs:23:36:23:52 | call to method Source<Object> : Object | J.cs:25:14:25:21 | access to property Prop2 | $@ | J.cs:23:36:23:52 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| J.cs:36:14:36:21 | access to property Prop1 | J.cs:34:17:34:33 | call to method Source<Object> : Object | J.cs:36:14:36:21 | access to property Prop1 | $@ | J.cs:34:17:34:33 | call to method Source<Object> : Object | call to method Source<Object> : Object |

View File

@@ -3,14 +3,16 @@ namespace System.Runtime.CompilerServices
internal static class IsExternalInit { }
}
public record Record(object Prop1, object Prop2) { }
public record class RecordClass(object Prop1, object Prop2) { }
public record struct RecordStruct(object Prop1, object Prop2) { }
public class J
{
private void M1()
{
var o = Source<object>(1);
var r1 = new Record(o, null);
var r1 = new RecordClass(o, null);
Sink(r1.Prop1); // $ hasValueFlow=1
Sink(r1.Prop2); // no flow
@@ -27,6 +29,14 @@ public class J
Sink(r4.Prop2); // no flow
}
private void M2()
{
var o = Source<object>(2);
var r1 = new RecordStruct(o, null);
Sink(r1.Prop1); // $ hasValueFlow=2
Sink(r1.Prop2); // no flow
}
public static void Sink(object o) { }
static T Source<T>(object source) => throw null;

View File

@@ -281,7 +281,7 @@ Tuples.cs:
# 81| 2: [ExprStmt] ...;
# 81| 0: [MethodCall] call to method Sink<Int32>
# 81| 0: [LocalVariableAccess] access to local variable q
# 85| 9: [Record] R1
# 85| 9: [RecordClass] R1
# 85| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 85| 0: [Parameter] left