Skip to content

Commit 9d18e09

Browse files
committed
Fix assertions and crashes encountered when inferring types for ICSharpCode.Decompiler.
1 parent 87f1ac3 commit 9d18e09

File tree

4 files changed

+60
-14
lines changed

4 files changed

+60
-14
lines changed

NullabilityInference.Tests/InferenceTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,6 +1270,22 @@ public T Test<T>()
12701270
12711271
T Get() => default;
12721272
}
1273+
}");
1274+
}
1275+
1276+
[Fact]
1277+
public void FixedFieldAccess()
1278+
{
1279+
AssertNullabilityInference(@"
1280+
internal unsafe struct IMAGE_RESOURCE_DIRECTORY_STRING
1281+
{
1282+
public ushort Length;
1283+
public fixed char NameString[1];
1284+
}
1285+
unsafe class Program {
1286+
public bool Test(IMAGE_RESOURCE_DIRECTORY_STRING* ptr) {
1287+
return ptr->NameString == null;
1288+
}
12731289
}");
12741290
}
12751291
}

NullabilityInference/EdgeBuildingOperationVisitor.cs

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,22 +1093,25 @@ private List<TypeWithNode> HandleArguments(TypeSubstitution substitution, Immuta
10931093

10941094
public override TypeWithNode VisitObjectCreation(IObjectCreationOperation operation, EdgeBuildingContext argument)
10951095
{
1096+
TypeWithNode newObjectType;
10961097
if (operation.Syntax is ObjectCreationExpressionSyntax syntax) {
1097-
var newObjectType = syntax.Type.Accept(syntaxVisitor).WithNode(typeSystem.NonNullNode);
1098-
var substitution = new TypeSubstitution(newObjectType.TypeArguments, new TypeWithNode[0]);
1099-
HandleArguments(substitution, operation.Arguments, invocationContext: argument);
1100-
1101-
var oldObjectCreationType = currentObjectCreationType;
1102-
try {
1103-
currentObjectCreationType = newObjectType;
1104-
operation.Initializer?.Accept(this, EdgeBuildingContext.Normal);
1105-
} finally {
1106-
currentObjectCreationType = oldObjectCreationType;
1107-
}
1108-
return newObjectType;
1098+
newObjectType = syntax.Type.Accept(syntaxVisitor).WithNode(typeSystem.NonNullNode);
1099+
} else if (operation.Syntax is ImplicitObjectCreationExpressionSyntax) {
1100+
newObjectType = tsBuilder.CreateHelperType(operation.Type);
11091101
} else {
11101102
throw new NotImplementedException($"ObjectCreationOperation with syntax={operation.Syntax}");
11111103
}
1104+
var substitution = new TypeSubstitution(newObjectType.TypeArguments, new TypeWithNode[0]);
1105+
HandleArguments(substitution, operation.Arguments, invocationContext: argument);
1106+
1107+
var oldObjectCreationType = currentObjectCreationType;
1108+
try {
1109+
currentObjectCreationType = newObjectType;
1110+
operation.Initializer?.Accept(this, EdgeBuildingContext.Normal);
1111+
} finally {
1112+
currentObjectCreationType = oldObjectCreationType;
1113+
}
1114+
return newObjectType;
11121115
}
11131116

11141117
public override TypeWithNode VisitTypeParameterObjectCreation(ITypeParameterObjectCreationOperation operation, EdgeBuildingContext argument)
@@ -1790,6 +1793,18 @@ public override TypeWithNode VisitConstantPattern(IConstantPatternOperation oper
17901793
return typeSystem.GetObliviousType(operation.Type);
17911794
}
17921795

1796+
public override TypeWithNode VisitRelationalPattern(IRelationalPatternOperation operation, EdgeBuildingContext argument)
1797+
{
1798+
Visit(operation.Value, EdgeBuildingContext.Normal);
1799+
return typeSystem.GetObliviousType(operation.Type);
1800+
}
1801+
1802+
public override TypeWithNode VisitNegatedPattern(INegatedPatternOperation operation, EdgeBuildingContext argument)
1803+
{
1804+
Visit(operation.Pattern, EdgeBuildingContext.Normal);
1805+
return typeSystem.GetObliviousType(operation.Type);
1806+
}
1807+
17931808
public override TypeWithNode VisitAddressOf(IAddressOfOperation operation, EdgeBuildingContext argument)
17941809
{
17951810
Visit(operation.Reference, EdgeBuildingContext.LValue);

NullabilityInference/EdgeBuildingSyntaxVisitor.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,5 +447,12 @@ internal bool IsReducedExtensionMethodCall(InvocationExpressionSyntax invocation
447447
var symbolInfo = semanticModel.GetSymbolInfo(invocation, cancellationToken);
448448
return symbolInfo.Symbol is IMethodSymbol { MethodKind: MethodKind.ReducedExtension };
449449
}
450+
451+
public override TypeWithNode VisitVariableDeclarator(VariableDeclaratorSyntax node)
452+
{
453+
// skip node.ArgumentList (array size of fixed field), it doesn't have an associated operation
454+
node.Initializer?.Accept(this);
455+
return typeSystem.VoidType;
456+
}
450457
}
451458
}

NullabilityInference/NodeBuildingSyntaxVisitor.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,13 @@ public override TypeWithNode VisitVariableDeclaration(VariableDeclarationSyntax
189189
foreach (var v in node.Variables) {
190190
var symbol = semanticModel.GetDeclaredSymbol(v, cancellationToken);
191191
if (symbol != null) {
192-
typeSystem.AddSymbolType(symbol, type);
192+
if (v.ArgumentList != null && symbol is IFieldSymbol f) {
193+
// field field
194+
var arrayType = new TypeWithNode(f.Type, typeSystem.ObliviousNode, new[] { type });
195+
typeSystem.AddSymbolType(symbol, arrayType);
196+
} else {
197+
typeSystem.AddSymbolType(symbol, type);
198+
}
193199
}
194200
}
195201
}
@@ -252,6 +258,8 @@ public override TypeWithNode VisitRecursivePattern(RecursivePatternSyntax node)
252258
throw new NotImplementedException($"DeclarationPattern with explicit type unsupported designation: {node.Designation} near {node.GetLocation().StartPosToString()}");
253259
}
254260
}
261+
} else {
262+
node.Designation?.Accept(this);
255263
}
256264
node.PositionalPatternClause?.Accept(this);
257265
node.PropertyPatternClause?.Accept(this);
@@ -313,7 +321,7 @@ private bool CanUseOutParamFlow(IMethodSymbol? method)
313321
}
314322
return method.EffectiveReturnType().SpecialType == SpecialType.System_Boolean;
315323
}
316-
324+
317325

318326
public override TypeWithNode VisitNameMemberCref(NameMemberCrefSyntax node)
319327
{

0 commit comments

Comments
 (0)