Merge pull request #15625 from michaelnebel/csharp/primaryconstructorinitializer

C# 12: Primary constructor inititalizers.
This commit is contained in:
Michael Nebel
2024-02-20 15:12:19 +01:00
committed by GitHub
15 changed files with 222 additions and 82 deletions

View File

@@ -1,3 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
@@ -10,8 +12,16 @@ namespace Semmle.Extraction.CSharp.Entities
{
internal class Constructor : Method
{
private readonly List<SyntaxNode> declaringReferenceSyntax;
private Constructor(Context cx, IMethodSymbol init)
: base(cx, init) { }
: base(cx, init)
{
declaringReferenceSyntax =
Symbol.DeclaringSyntaxReferences
.Select(r => r.GetSyntax())
.ToList();
}
public override void Populate(TextWriter trapFile)
{
@@ -22,6 +32,12 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.constructors(this, Symbol.ContainingType.Name, ContainingType, (Constructor)OriginalDefinition);
trapFile.constructor_location(this, Location);
if (IsPrimary)
{
// Create a synthetic empty body for primary constructors.
Statements.SyntheticEmptyBlock.Create(Context, this, 0, Location);
}
if (Symbol.IsImplicitlyDeclared)
{
var lineCounts = new LineCounts() { Total = 2, Code = 1, Comment = 0 };
@@ -33,68 +49,79 @@ namespace Semmle.Extraction.CSharp.Entities
protected override void ExtractInitializers(TextWriter trapFile)
{
// Do not extract initializers for constructed types.
if (!IsSourceDeclaration)
return;
var syntax = Syntax;
var initializer = syntax?.Initializer;
if (initializer is null)
// Only extract initializers for constructors with a body and primary constructors.
if (Block is null && ExpressionBody is null && !IsPrimary ||
!IsSourceDeclaration)
{
if (Symbol.MethodKind is MethodKind.Constructor)
return;
}
if (OrdinaryConstructorSyntax?.Initializer is ConstructorInitializerSyntax initializer)
{
ITypeSymbol initializerType;
var initializerInfo = Context.GetSymbolInfo(initializer);
switch (initializer.Kind())
{
var baseType = Symbol.ContainingType.BaseType;
if (baseType is null)
{
if (Symbol.ContainingType.SpecialType != SpecialType.System_Object)
{
Context.ModelError(Symbol, "Unable to resolve base type in implicit constructor initializer");
}
case SyntaxKind.BaseConstructorInitializer:
initializerType = Symbol.ContainingType.BaseType!;
break;
case SyntaxKind.ThisConstructorInitializer:
initializerType = Symbol.ContainingType;
break;
default:
Context.ModelError(initializer, "Unknown initializer");
return;
}
var baseConstructor = baseType.InstanceConstructors.FirstOrDefault(c => c.Arity is 0);
if (baseConstructor is null)
{
Context.ModelError(Symbol, "Unable to resolve implicit constructor initializer call");
return;
}
var baseConstructorTarget = Create(Context, baseConstructor);
var info = new ExpressionInfo(Context,
AnnotatedTypeSymbol.CreateNotAnnotated(baseType),
Location,
Kinds.ExprKind.CONSTRUCTOR_INIT,
this,
-1,
isCompilerGenerated: true,
null);
trapFile.expr_call(new Expression(info), baseConstructorTarget);
}
return;
ExtractSourceInitializer(trapFile, initializerType, (IMethodSymbol?)initializerInfo.Symbol, initializer.ArgumentList, initializer.ThisOrBaseKeyword.GetLocation());
}
ITypeSymbol initializerType;
var symbolInfo = Context.GetSymbolInfo(initializer);
switch (initializer.Kind())
else if (PrimaryBase is PrimaryConstructorBaseTypeSyntax primaryInitializer)
{
case SyntaxKind.BaseConstructorInitializer:
initializerType = Symbol.ContainingType.BaseType!;
break;
case SyntaxKind.ThisConstructorInitializer:
initializerType = Symbol.ContainingType;
break;
default:
Context.ModelError(initializer, "Unknown initializer");
return;
}
var primaryInfo = Context.GetSymbolInfo(primaryInitializer);
var primarySymbol = primaryInfo.Symbol;
ExtractSourceInitializer(trapFile, primarySymbol?.ContainingType, (IMethodSymbol?)primarySymbol, primaryInitializer.ArgumentList, primaryInitializer.GetLocation());
}
else if (Symbol.MethodKind is MethodKind.Constructor)
{
var baseType = Symbol.ContainingType.BaseType;
if (baseType is null)
{
if (Symbol.ContainingType.SpecialType != SpecialType.System_Object)
{
Context.ModelError(Symbol, "Unable to resolve base type in implicit constructor initializer");
}
return;
}
var baseConstructor = baseType.InstanceConstructors.FirstOrDefault(c => c.Arity is 0);
if (baseConstructor is null)
{
Context.ModelError(Symbol, "Unable to resolve implicit constructor initializer call");
return;
}
var baseConstructorTarget = Create(Context, baseConstructor);
var info = new ExpressionInfo(Context,
AnnotatedTypeSymbol.CreateNotAnnotated(baseType),
Location,
Kinds.ExprKind.CONSTRUCTOR_INIT,
this,
-1,
isCompilerGenerated: true,
null);
trapFile.expr_call(new Expression(info), baseConstructorTarget);
}
}
private void ExtractSourceInitializer(TextWriter trapFile, ITypeSymbol? type, IMethodSymbol? symbol, ArgumentListSyntax arguments, Location location)
{
var initInfo = new ExpressionInfo(Context,
AnnotatedTypeSymbol.CreateNotAnnotated(initializerType),
Context.CreateLocation(initializer.ThisOrBaseKeyword.GetLocation()),
AnnotatedTypeSymbol.CreateNotAnnotated(type),
Context.CreateLocation(location),
Kinds.ExprKind.CONSTRUCTOR_INIT,
this,
-1,
@@ -103,7 +130,7 @@ namespace Semmle.Extraction.CSharp.Entities
var init = new Expression(initInfo);
var target = Constructor.Create(Context, (IMethodSymbol?)symbolInfo.Symbol);
var target = Constructor.Create(Context, symbol);
if (target is null)
{
Context.ModelError(Symbol, "Unable to resolve call");
@@ -112,19 +139,27 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.expr_call(init, target);
init.PopulateArguments(trapFile, initializer.ArgumentList, 0);
init.PopulateArguments(trapFile, arguments, 0);
}
private ConstructorDeclarationSyntax? Syntax
{
get
{
return Symbol.DeclaringSyntaxReferences
.Select(r => r.GetSyntax())
.OfType<ConstructorDeclarationSyntax>()
.FirstOrDefault();
}
}
private ConstructorDeclarationSyntax? OrdinaryConstructorSyntax =>
declaringReferenceSyntax
.OfType<ConstructorDeclarationSyntax>()
.FirstOrDefault();
private TypeDeclarationSyntax? PrimaryConstructorSyntax =>
declaringReferenceSyntax
.OfType<TypeDeclarationSyntax>()
.FirstOrDefault(t => t is ClassDeclarationSyntax or StructDeclarationSyntax or RecordDeclarationSyntax);
private PrimaryConstructorBaseTypeSyntax? PrimaryBase =>
PrimaryConstructorSyntax?
.BaseList?
.Types
.OfType<PrimaryConstructorBaseTypeSyntax>()
.FirstOrDefault();
private bool IsPrimary => PrimaryConstructorSyntax is not null;
[return: NotNullIfNotNull(nameof(constructor))]
public static new Constructor? Create(Context cx, IMethodSymbol? constructor)
@@ -160,19 +195,20 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.Write(";constructor");
}
private ConstructorDeclarationSyntax? GetSyntax() =>
Symbol.DeclaringSyntaxReferences.Select(r => r.GetSyntax()).OfType<ConstructorDeclarationSyntax>().FirstOrDefault();
public override Microsoft.CodeAnalysis.Location? FullLocation => ReportingLocation;
public override Microsoft.CodeAnalysis.Location? ReportingLocation
{
get
{
var syn = GetSyntax();
if (syn is not null)
if (OrdinaryConstructorSyntax is not null)
{
return syn.Identifier.GetLocation();
return OrdinaryConstructorSyntax.Identifier.GetLocation();
}
if (PrimaryConstructorSyntax is not null)
{
return PrimaryConstructorSyntax.Identifier.GetLocation();
}
if (Symbol.IsImplicitlyDeclared)

View File

@@ -54,12 +54,13 @@ namespace Semmle.Extraction.CSharp.Entities
var block = Block;
var expr = ExpressionBody;
Context.PopulateLater(() => ExtractInitializers(trapFile));
if (block is not null || expr is not null)
{
Context.PopulateLater(
() =>
{
ExtractInitializers(trapFile);
if (block is not null)
Statements.Block.Create(Context, block, this, 0);
else

View File

@@ -0,0 +1,24 @@
using System.IO;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Entities;
using Semmle.Extraction.Kinds;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
internal class SyntheticEmptyBlock : Statement<BlockSyntax>
{
private SyntheticEmptyBlock(Context cx, BlockSyntax block, IStatementParentEntity parent, int child, Location location)
: base(cx, block, StmtKind.BLOCK, parent, child, location) { }
public static SyntheticEmptyBlock Create(Context cx, IStatementParentEntity parent, int child, Location location)
{
var block = SyntaxFactory.Block();
var ret = new SyntheticEmptyBlock(cx, block, parent, child, location);
ret.TryPopulate();
return ret;
}
protected override void PopulateStatement(TextWriter trapFile) { }
}
}

View File

@@ -57,7 +57,7 @@ namespace Semmle.Extraction.CSharp.Entities
{
return Kinds.TypeKind.TUPLE;
}
return Symbol.IsInlineArray()
return Symbol.IsInlineArray()
? Kinds.TypeKind.INLINE_ARRAY
: Kinds.TypeKind.STRUCT;
}

View File

@@ -416,7 +416,9 @@ class InstanceConstructor extends Constructor {
*/
class PrimaryConstructor extends Constructor {
PrimaryConstructor() {
not this.hasBody() and
// In the extractor we use the constructor location as the location for the
// synthesized empty body of the constructor.
this.getLocation() = this.getBody().getLocation() and
this.getDeclaringType().fromSource() and
this.fromSource()
}

View File

@@ -953,12 +953,8 @@ private module Cached {
callCfn = any(Call c | isParamsArg(c, _, _)).getAControlFlowNode()
} or
TFlowInsensitiveFieldNode(FieldOrProperty f) { f.isFieldLike() } or
TInstanceParameterAccessNode(ControlFlow::Node cfn, boolean isPostUpdate) {
exists(ParameterAccess pa | cfn = getAPrimaryConstructorParameterCfn(pa) |
isPostUpdate = false
or
pa instanceof ParameterWrite and isPostUpdate = true
)
TInstanceParameterAccessNode(ControlFlow::Node cfn, Boolean isPostUpdate) {
cfn = getAPrimaryConstructorParameterCfn(_)
} or
TPrimaryConstructorThisAccessNode(Parameter p, Boolean isPostUpdate) {
p.getCallable() instanceof PrimaryConstructor

View File

@@ -25,6 +25,7 @@ constructors.cs:
# 23| -1: [TypeMention] object
# 23| 1: [Parameter] s
# 23| -1: [TypeMention] string
# 23| 4: [BlockStmt] {...}
# 25| 5: [InstanceConstructor] C1
#-----| 2: (Parameters)
# 25| 0: [Parameter] o
@@ -44,3 +45,7 @@ constructors.cs:
# 28| -1: [TypeMention] string
# 28| 2: [Parameter] i
# 28| -1: [TypeMention] int
# 28| 3: [ConstructorInitializer] call to constructor C1
# 28| 0: [ParameterAccess] access to parameter o
# 28| 1: [ParameterAccess] access to parameter s
# 28| 4: [BlockStmt] {...}

View File

@@ -884,6 +884,7 @@ Record.cs:
# 27| -1: [TypeMention] string
# 27| 1: [Parameter] LastName
# 27| -1: [TypeMention] string
# 27| 4: [BlockStmt] {...}
# 27| 16: [Property] FirstName
# 27| 3: [Getter] get_FirstName
# 27| 4: [Setter] set_FirstName
@@ -913,6 +914,10 @@ Record.cs:
# 29| -1: [TypeMention] string
# 29| 2: [Parameter] Subject
# 29| -1: [TypeMention] string
# 30| 3: [ConstructorInitializer] call to constructor Person1
# 30| 0: [ParameterAccess] access to parameter FirstName
# 30| 1: [ParameterAccess] access to parameter LastName
# 29| 4: [BlockStmt] {...}
# 29| 17: [Property] Subject
# 29| 3: [Getter] get_Subject
# 29| 4: [Setter] set_Subject
@@ -937,6 +942,10 @@ Record.cs:
# 32| -1: [TypeMention] string
# 32| 2: [Parameter] Level
# 32| -1: [TypeMention] int
# 33| 3: [ConstructorInitializer] call to constructor Person1
# 33| 0: [ParameterAccess] access to parameter FirstName
# 33| 1: [ParameterAccess] access to parameter LastName
# 32| 4: [BlockStmt] {...}
# 32| 17: [Property] Level
# 32| 3: [Getter] get_Level
# 32| 4: [Setter] set_Level
@@ -957,6 +966,7 @@ Record.cs:
#-----| 2: (Parameters)
# 35| 0: [Parameter] Name
# 35| -1: [TypeMention] string
# 35| 4: [BlockStmt] {...}
# 35| 16: [Property] Name
# 35| 3: [Getter] get_Name
# 35| 4: [Setter] set_Name
@@ -981,6 +991,9 @@ Record.cs:
#-----| 2: (Parameters)
# 41| 0: [Parameter] Name
# 41| -1: [TypeMention] string
# 41| 3: [ConstructorInitializer] call to constructor Pet
# 41| 0: [ParameterAccess] access to parameter Name
# 41| 4: [BlockStmt] {...}
# 41| 15: [Property] EqualityContract
# 41| 3: [Getter] get_EqualityContract
# 43| 16: [Method] WagTail
@@ -1022,6 +1035,7 @@ Record.cs:
#-----| 2: (Parameters)
# 54| 0: [Parameter] A
# 54| -1: [TypeMention] string
# 54| 4: [BlockStmt] {...}
# 54| 16: [Property] A
# 54| 3: [Getter] get_A
# 54| 4: [Setter] set_A
@@ -1044,6 +1058,9 @@ Record.cs:
# 56| -1: [TypeMention] string
# 56| 1: [Parameter] B
# 56| -1: [TypeMention] string
# 56| 3: [ConstructorInitializer] call to constructor R1
# 56| 0: [ParameterAccess] access to parameter A
# 56| 4: [BlockStmt] {...}
# 56| 17: [Property] B
# 56| 3: [Getter] get_B
# 56| 4: [Setter] set_B

View File

@@ -14,7 +14,9 @@ edges
| Constructors.cs:33:18:33:19 | this access : C_with_ctor [field s1] : Object | Constructors.cs:33:18:33:19 | access to field s1 | provenance | |
| Constructors.cs:41:26:41:26 | o : Object | Constructors.cs:41:38:41:38 | access to parameter o : Object | provenance | |
| Constructors.cs:41:38:41:38 | access to parameter o : Object | Constructors.cs:41:32:41:34 | [post] this access : C1 [field Obj] : Object | provenance | |
| Constructors.cs:44:28:44:35 | o21param : Object | Constructors.cs:46:23:46:27 | this access : C2 [parameter o21param] : Object | provenance | |
| Constructors.cs:44:28:44:35 | o21param : Object | Constructors.cs:46:31:46:38 | access to parameter o21param : Object | provenance | |
| Constructors.cs:46:23:46:27 | this access : C2 [parameter o21param] : Object | Constructors.cs:46:31:46:38 | access to parameter o21param : Object | provenance | |
| Constructors.cs:46:31:46:38 | access to parameter o21param : Object | Constructors.cs:46:23:46:27 | [post] this access : C2 [field Obj21] : Object | provenance | |
| Constructors.cs:48:32:48:39 | this : C2 [parameter o22param] : Object | Constructors.cs:48:32:48:39 | access to parameter o22param : Object | provenance | |
| Constructors.cs:50:32:50:36 | this : C2 [field Obj21] : Object | Constructors.cs:50:32:50:36 | this access : C2 [field Obj21] : Object | provenance | |
@@ -55,6 +57,13 @@ edges
| Constructors.cs:100:25:100:29 | access to local variable taint : Object | Constructors.cs:100:9:100:10 | [post] access to local variable c2 : C2 [parameter o22param] : Object | provenance | |
| Constructors.cs:101:14:101:15 | access to local variable c2 : C2 [parameter o22param] : Object | Constructors.cs:48:32:48:39 | this : C2 [parameter o22param] : Object | provenance | |
| Constructors.cs:101:14:101:15 | access to local variable c2 : C2 [parameter o22param] : Object | Constructors.cs:101:14:101:21 | access to property Obj22 | provenance | |
| Constructors.cs:106:32:106:39 | this : C3 [parameter o31param] : Object | Constructors.cs:106:32:106:39 | access to parameter o31param : Object | provenance | |
| Constructors.cs:111:19:111:35 | call to method Source<Object> : Object | Constructors.cs:112:25:112:27 | access to local variable o31 : Object | provenance | |
| Constructors.cs:112:18:112:28 | object creation of type C3 : C3 [parameter o31param] : Object | Constructors.cs:113:14:113:15 | access to local variable c3 : C3 [parameter o31param] : Object | provenance | |
| Constructors.cs:112:25:112:27 | access to local variable o31 : Object | Constructors.cs:104:28:104:35 | o31param : Object | provenance | |
| Constructors.cs:112:25:112:27 | access to local variable o31 : Object | Constructors.cs:112:18:112:28 | object creation of type C3 : C3 [parameter o31param] : Object | provenance | |
| Constructors.cs:113:14:113:15 | access to local variable c3 : C3 [parameter o31param] : Object | Constructors.cs:106:32:106:39 | this : C3 [parameter o31param] : Object | provenance | |
| Constructors.cs:113:14:113:15 | access to local variable c3 : C3 [parameter o31param] : Object | Constructors.cs:113:14:113:21 | access to property Obj31 | provenance | |
nodes
| Constructors.cs:5:24:5:25 | [post] this access : C_no_ctor [field s1] : Object | semmle.label | [post] this access : C_no_ctor [field s1] : Object |
| Constructors.cs:5:29:5:45 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
@@ -76,6 +85,7 @@ nodes
| Constructors.cs:44:28:44:35 | o21param : Object | semmle.label | o21param : Object |
| Constructors.cs:44:45:44:52 | o22param : Object | semmle.label | o22param : Object |
| Constructors.cs:46:23:46:27 | [post] this access : C2 [field Obj21] : Object | semmle.label | [post] this access : C2 [field Obj21] : Object |
| Constructors.cs:46:23:46:27 | this access : C2 [parameter o21param] : Object | semmle.label | this access : C2 [parameter o21param] : Object |
| Constructors.cs:46:31:46:38 | access to parameter o21param : Object | semmle.label | access to parameter o21param : Object |
| Constructors.cs:48:32:48:39 | access to parameter o22param : Object | semmle.label | access to parameter o22param : Object |
| Constructors.cs:48:32:48:39 | this : C2 [parameter o22param] : Object | semmle.label | this : C2 [parameter o22param] : Object |
@@ -116,6 +126,14 @@ nodes
| Constructors.cs:100:25:100:29 | access to local variable taint : Object | semmle.label | access to local variable taint : Object |
| Constructors.cs:101:14:101:15 | access to local variable c2 : C2 [parameter o22param] : Object | semmle.label | access to local variable c2 : C2 [parameter o22param] : Object |
| Constructors.cs:101:14:101:21 | access to property Obj22 | semmle.label | access to property Obj22 |
| Constructors.cs:104:28:104:35 | o31param : Object | semmle.label | o31param : Object |
| Constructors.cs:106:32:106:39 | access to parameter o31param : Object | semmle.label | access to parameter o31param : Object |
| Constructors.cs:106:32:106:39 | this : C3 [parameter o31param] : Object | semmle.label | this : C3 [parameter o31param] : Object |
| Constructors.cs:111:19:111:35 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
| Constructors.cs:112:18:112:28 | object creation of type C3 : C3 [parameter o31param] : Object | semmle.label | object creation of type C3 : C3 [parameter o31param] : Object |
| Constructors.cs:112:25:112:27 | access to local variable o31 : Object | semmle.label | access to local variable o31 : Object |
| Constructors.cs:113:14:113:15 | access to local variable c3 : C3 [parameter o31param] : Object | semmle.label | access to local variable c3 : C3 [parameter o31param] : Object |
| Constructors.cs:113:14:113:21 | access to property Obj31 | semmle.label | access to property Obj31 |
subpaths
| Constructors.cs:64:37:64:37 | access to parameter o : Object | Constructors.cs:57:54:57:55 | o2 : Object | Constructors.cs:59:13:59:19 | SSA def(o1) : Object | Constructors.cs:64:27:64:34 | SSA def(o22param) : Object |
| Constructors.cs:71:25:71:25 | access to local variable o : Object | Constructors.cs:41:26:41:26 | o : Object | Constructors.cs:41:32:41:34 | [post] this access : C1 [field Obj] : Object | Constructors.cs:71:18:71:26 | object creation of type C1 : C1 [field Obj] : Object |
@@ -127,6 +145,8 @@ subpaths
| Constructors.cs:93:14:93:15 | access to local variable c2 : C2 [parameter o22param] : Object | Constructors.cs:48:32:48:39 | this : C2 [parameter o22param] : Object | Constructors.cs:48:32:48:39 | access to parameter o22param : Object | Constructors.cs:93:14:93:21 | access to property Obj22 |
| Constructors.cs:100:25:100:29 | access to local variable taint : Object | Constructors.cs:62:41:62:41 | o : Object | Constructors.cs:64:27:64:34 | SSA def(o22param) : Object | Constructors.cs:100:9:100:10 | [post] access to local variable c2 : C2 [parameter o22param] : Object |
| Constructors.cs:101:14:101:15 | access to local variable c2 : C2 [parameter o22param] : Object | Constructors.cs:48:32:48:39 | this : C2 [parameter o22param] : Object | Constructors.cs:48:32:48:39 | access to parameter o22param : Object | Constructors.cs:101:14:101:21 | access to property Obj22 |
| Constructors.cs:112:25:112:27 | access to local variable o31 : Object | Constructors.cs:104:28:104:35 | o31param : Object | Constructors.cs:104:28:104:35 | o31param : Object | Constructors.cs:112:18:112:28 | object creation of type C3 : C3 [parameter o31param] : Object |
| Constructors.cs:113:14:113:15 | access to local variable c3 : C3 [parameter o31param] : Object | Constructors.cs:106:32:106:39 | this : C3 [parameter o31param] : Object | Constructors.cs:106:32:106:39 | access to parameter o31param : Object | Constructors.cs:113:14:113:21 | access to property Obj31 |
#select
| Constructors.cs:15:18:15:19 | access to field s1 | Constructors.cs:5:29:5:45 | call to method Source<Object> : Object | Constructors.cs:15:18:15:19 | access to field s1 | $@ | Constructors.cs:5:29:5:45 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| Constructors.cs:33:18:33:19 | access to field s1 | Constructors.cs:21:29:21:45 | call to method Source<Object> : Object | Constructors.cs:33:18:33:19 | access to field s1 | $@ | Constructors.cs:21:29:21:45 | call to method Source<Object> : Object | call to method Source<Object> : Object |
@@ -136,3 +156,4 @@ subpaths
| Constructors.cs:82:14:82:21 | access to property Obj23 | Constructors.cs:77:19:77:35 | call to method Source<Object> : Object | Constructors.cs:82:14:82:21 | access to property Obj23 | $@ | Constructors.cs:77:19:77:35 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| Constructors.cs:93:14:93:21 | access to property Obj22 | Constructors.cs:91:21:91:37 | call to method Source<Object> : Object | Constructors.cs:93:14:93:21 | access to property Obj22 | $@ | Constructors.cs:91:21:91:37 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| Constructors.cs:101:14:101:21 | access to property Obj22 | Constructors.cs:99:21:99:37 | call to method Source<Object> : Object | Constructors.cs:101:14:101:21 | access to property Obj22 | $@ | Constructors.cs:99:21:99:37 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| Constructors.cs:113:14:113:21 | access to property Obj31 | Constructors.cs:111:19:111:35 | call to method Source<Object> : Object | Constructors.cs:113:14:113:21 | access to property Obj31 | $@ | Constructors.cs:111:19:111:35 | call to method Source<Object> : Object | call to method Source<Object> : Object |

View File

@@ -101,6 +101,18 @@ public class Constructors
Sink(c2.Obj22); // $ hasValueFlow=5
}
public class C3(object o31param)
{
public object Obj31 => o31param;
}
public void M5()
{
var o31 = Source<object>(6);
var c3 = new C3(o31);
Sink(c3.Obj31); // $ hasValueFlow=6
}
public static void Sink(object o) { }
public static T Source<T>(object source) => throw null;

View File

@@ -135,6 +135,9 @@
| Tuples.cs:87:27:87:27 | SSA def(q) | Tuples.cs:91:18:91:18 | access to local variable q |
| Tuples.cs:87:30:87:30 | SSA def(r) | Tuples.cs:90:18:90:18 | access to local variable r |
| Tuples.cs:91:18:91:18 | access to local variable q | Tuples.cs:91:18:91:18 | (...) ... |
| Tuples.cs:95:12:95:13 | this | Tuples.cs:95:22:95:22 | this |
| Tuples.cs:95:22:95:22 | [post] this | Tuples.cs:95:29:95:29 | this |
| Tuples.cs:95:22:95:22 | this | Tuples.cs:95:29:95:29 | this |
| Tuples.cs:99:13:99:33 | SSA def(o) | Tuples.cs:100:24:100:24 | access to local variable o |
| Tuples.cs:99:17:99:33 | call to method Source<String> | Tuples.cs:99:13:99:33 | SSA def(o) |
| Tuples.cs:99:32:99:32 | 9 | Tuples.cs:99:32:99:32 | (...) ... |

View File

@@ -369,6 +369,7 @@ Tuples.cs:
# 95| -1: [TypeMention] string
# 95| 1: [Parameter] j
# 95| -1: [TypeMention] int
# 95| 4: [BlockStmt] {...}
# 95| 16: [Property] i
# 95| 3: [Getter] get_i
# 95| 4: [Setter] set_i

View File

@@ -6,3 +6,5 @@
| expressions.cs:271:16:271:24 | IntVector | expressions.cs:271:16:271:24 | call to constructor Object | file://:0:0:0:0 | Object |
| expressions.cs:311:16:311:20 | Digit | expressions.cs:311:16:311:20 | call to constructor ValueType | file://:0:0:0:0 | ValueType |
| expressions.cs:481:20:481:22 | Num | expressions.cs:481:20:481:22 | call to constructor Object | file://:0:0:0:0 | Object |
| expressions.cs:518:11:518:17 | ClassC1 | expressions.cs:518:11:518:17 | call to constructor Object | file://:0:0:0:0 | Object |
| expressions.cs:520:11:520:17 | ClassC2 | expressions.cs:520:33:520:44 | call to constructor ClassC1 | expressions.cs:518:11:518:17 | ClassC1 |

View File

@@ -2406,3 +2406,19 @@ expressions.cs:
# 512| 0: [IntLiteral] 10
# 515| 5: [Field] myInlineArrayElements
# 515| -1: [TypeMention] int
# 518| 22: [Class] ClassC1
# 518| 4: [InstanceConstructor,PrimaryConstructor] ClassC1
#-----| 2: (Parameters)
# 518| 0: [Parameter] oc1
# 518| -1: [TypeMention] object
# 518| 4: [BlockStmt] {...}
# 520| 23: [Class] ClassC2
#-----| 3: (Base types)
# 520| 0: [TypeMention] ClassC1
# 520| 4: [InstanceConstructor,PrimaryConstructor] ClassC2
#-----| 2: (Parameters)
# 520| 0: [Parameter] oc2
# 520| -1: [TypeMention] object
# 520| 3: [ConstructorInitializer] call to constructor ClassC1
# 520| 0: [ParameterAccess] access to parameter oc2
# 520| 4: [BlockStmt] {...}

View File

@@ -514,4 +514,8 @@ namespace Expressions
{
private int myInlineArrayElements;
}
class ClassC1(object oc1) { }
class ClassC2(object oc2) : ClassC1(oc2) { }
}