Skip to content

Commit

Permalink
Disallow declaring readonly, volatile, or fixed size buffer fields as…
Browse files Browse the repository at this point in the history
… element fields of an inline array type. (#69096)
  • Loading branch information
AlekseyTs authored Jul 19, 2023
1 parent 9a2664f commit b36d125
Show file tree
Hide file tree
Showing 19 changed files with 187 additions and 48 deletions.
4 changes: 2 additions & 2 deletions src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -7679,7 +7679,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="WRN_PrimaryConstructorParameterIsShadowedAndNotPassedToBase_Title" xml:space="preserve">
<value>Primary constructor parameter is shadowed by a member from base</value>
</data>
<data name="ERR_InlineArrayRequiredElementField" xml:space="preserve">
<value>Inline array element field cannot be declared required.</value>
<data name="ERR_InlineArrayUnsupportedElementFieldModifier" xml:space="preserve">
<value>Inline array element field cannot be declared as required, readonly, volatile, or as a fixed size buffer.</value>
</data>
</root>
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2242,7 +2242,7 @@ internal enum ErrorCode

WRN_PrimaryConstructorParameterIsShadowedAndNotPassedToBase = 9179,

ERR_InlineArrayRequiredElementField = 9180,
ERR_InlineArrayUnsupportedElementFieldModifier = 9180,

#endregion

Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2362,7 +2362,7 @@ internal static bool IsBuildOnlyDiagnostic(ErrorCode code)
case ErrorCode.ERR_ExpressionTreeContainsCollectionLiteral:
case ErrorCode.ERR_CollectionLiteralNoTargetType:
case ErrorCode.WRN_PrimaryConstructorParameterIsShadowedAndNotPassedToBase:
case ErrorCode.ERR_InlineArrayRequiredElementField:
case ErrorCode.ERR_InlineArrayUnsupportedElementFieldModifier:
return false;
default:
// NOTE: All error codes must be explicitly handled in this switch statement
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1754,9 +1754,9 @@ protected override void AfterMembersCompletedChecks(BindingDiagnosticBag diagnos

if (TryGetPossiblyUnsupportedByLanguageInlineArrayElementField() is FieldSymbol elementField)
{
if (elementField.IsRequired)
if (elementField.IsRequired || elementField.IsReadOnly || elementField.IsVolatile || elementField.IsFixedSizeBuffer)
{
diagnostics.Add(ErrorCode.ERR_InlineArrayRequiredElementField, elementField.TryGetFirstLocation() ?? GetFirstLocation());
diagnostics.Add(ErrorCode.ERR_InlineArrayUnsupportedElementFieldModifier, elementField.TryGetFirstLocation() ?? GetFirstLocation());
}
}
else
Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2504,7 +2504,7 @@ ITypeSymbol ITypeSymbolInternal.GetITypeSymbol()

internal FieldSymbol? TryGetInlineArrayElementField()
{
return TryGetPossiblyUnsupportedByLanguageInlineArrayElementField() is { RefKind: RefKind.None } field ? field : null;
return TryGetPossiblyUnsupportedByLanguageInlineArrayElementField() is { RefKind: RefKind.None, IsFixedSizeBuffer: false } field ? field : null;
}
}
}
6 changes: 3 additions & 3 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

143 changes: 141 additions & 2 deletions src/Compilers/CSharp/Test/Emit2/Semantics/InlineArrayTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1906,9 +1906,9 @@ public struct Buffer
";
var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80);
comp.VerifyDiagnostics(
// (5,25): error CS9179: Inline array element field cannot be declared required.
// (5,25): error CS9180: Inline array element field cannot be declared as required, readonly, volatile, or as a fixed size buffer.
// required public int _element0;
Diagnostic(ErrorCode.ERR_InlineArrayRequiredElementField, "_element0").WithLocation(5, 25)
Diagnostic(ErrorCode.ERR_InlineArrayUnsupportedElementFieldModifier, "_element0").WithLocation(5, 25)
);
}

Expand Down Expand Up @@ -1951,6 +1951,145 @@ 01 00 00 00
);
}

[Fact]
public void InlineArrayType_45_Readonly()
{
var src = @"
[System.Runtime.CompilerServices.InlineArray(4)]
public struct Buffer1
{
public readonly int _element1;
}

[System.Runtime.CompilerServices.InlineArray(4)]
public readonly struct Buffer2
{
public readonly int _element2;
}

[System.Runtime.CompilerServices.InlineArray(4)]
public readonly struct Buffer3
{
public int _element3;
}
";
var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80);
comp.VerifyDiagnostics(
// (5,25): error CS9180: Inline array element field cannot be declared as required, readonly, volatile, or as a fixed size buffer.
// public readonly int _element1;
Diagnostic(ErrorCode.ERR_InlineArrayUnsupportedElementFieldModifier, "_element1").WithLocation(5, 25),
// (11,25): error CS9180: Inline array element field cannot be declared as required, readonly, volatile, or as a fixed size buffer.
// public readonly int _element2;
Diagnostic(ErrorCode.ERR_InlineArrayUnsupportedElementFieldModifier, "_element2").WithLocation(11, 25),
// (17,16): error CS8340: Instance fields of readonly structs must be readonly.
// public int _element3;
Diagnostic(ErrorCode.ERR_FieldsInRoStruct, "_element3").WithLocation(17, 16)
);
}

[Fact]
public void InlineArrayType_46_Volatile()
{
var src = @"
[System.Runtime.CompilerServices.InlineArray(4)]
public struct Buffer1
{
public volatile int _element1;
}
";
var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80);
comp.VerifyDiagnostics(
// (5,25): error CS9180: Inline array element field cannot be declared as required, readonly, volatile, or as a fixed size buffer.
// public volatile int _element1;
Diagnostic(ErrorCode.ERR_InlineArrayUnsupportedElementFieldModifier, "_element1").WithLocation(5, 25)
);
}

[Fact]
public void InlineArrayType_47_FixedSizeBuffer()
{
var src = @"
[System.Runtime.CompilerServices.InlineArray(4)]
public unsafe struct Buffer
{
public fixed int x[5];
}
";
var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.DebugDll.WithAllowUnsafe(true));
comp.VerifyDiagnostics(
// (5,22): error CS9180: Inline array element field cannot be declared as required, readonly, volatile, or as a fixed size buffer.
// public fixed int x[5];
Diagnostic(ErrorCode.ERR_InlineArrayUnsupportedElementFieldModifier, "x").WithLocation(5, 22)
);
}

[Fact]
public void InlineArrayType_48_FixedSizeBuffer()
{
// [System.Runtime.CompilerServices.InlineArray(4)]
// public unsafe struct Buffer
// {
// public fixed int x[5];
// }
var ilSource = @"
.class public sequential ansi sealed beforefieldinit Buffer
extends [mscorlib]System.ValueType
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.InlineArrayAttribute::.ctor(int32) = (
01 00 04 00 00 00 00 00
)

// Nested Types
.class nested public sequential ansi sealed beforefieldinit '<x>e__FixedBuffer'
extends [mscorlib]System.ValueType
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void [mscorlib]System.Runtime.CompilerServices.UnsafeValueTypeAttribute::.ctor() = (
01 00 00 00
)
.pack 0
.size 20

// Fields
.field public int32 FixedElementField

} // end of class <x>e__FixedBuffer


// Fields
.field public valuetype Buffer/'<x>e__FixedBuffer' x
.custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type, int32) = (
01 00 59 53 79 73 74 65 6D 2E 49 6E 74 33 32 2C // ..YSystem.Int32,
20 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 69 // mscorlib, Versi
6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C 74 // on=4.0.0.0, Cult
75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 // ure=neutral, Pub
6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 61 // licKeyToken=b77a
35 63 35 36 31 39 33 34 65 30 38 39 05 00 00 00 // 5c561934e089....
00 00
)
}
";

var src = @"
unsafe class Program
{
static void Main()
{
var a = new Buffer();
int* x = a[0];
}
}
";
var comp = CreateCompilationWithIL(src, ilSource, targetFramework: TargetFramework.Net80, options: TestOptions.DebugDll.WithAllowUnsafe(true));
comp.VerifyDiagnostics(
// (7,18): error CS0021: Cannot apply indexing with [] to an expression of type 'Buffer'
// int* x = a[0];
Diagnostic(ErrorCode.ERR_BadIndexLHS, "a[0]").WithArguments("Buffer").WithLocation(7, 18)
);
}

[Fact]
public void Access_ArgumentType_01()
{
Expand Down

0 comments on commit b36d125

Please sign in to comment.