diff --git a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs index 314e1f74b39df..74d2b52440105 100644 --- a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs +++ b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs @@ -520,7 +520,7 @@ private void CompileNamedType(NamedTypeSymbol containingType) var member = members[memberOrdinal]; //When a filter is supplied, limit the compilation of members passing the filter. - if (member is not SourcePropertyAccessorSymbol { ContainsFieldKeyword: true } accessor || + if (member is not SourcePropertyAccessorSymbol { ContainsFieldIdentifier: true } accessor || !PassesFilter(_filterOpt, member)) { continue; @@ -579,7 +579,7 @@ private void CompileNamedType(NamedTypeSymbol containingType) Debug.Assert(!method.IsPartialDefinition()); } - if (member is SourcePropertyAccessorSymbol { ContainsFieldKeyword: true }) + if (member is SourcePropertyAccessorSymbol { ContainsFieldIdentifier: true }) { // We already compiled these accessors in the loop above. continue; diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs index 66ce3b0db4ed7..ced5649c591fb 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs @@ -389,6 +389,12 @@ private static void GetDocumentsForMethodsAndNestedTypes(PooledHashSet GetSimpleNonTypeMembers(string name) /// For source symbols may be called while calculating /// . /// - internal virtual IEnumerable GetInstanceFieldsAndEvents() + internal virtual IEnumerable GetInstanceFieldsAndEventsAndProperties() { - return GetMembersUnordered().Where(IsInstanceFieldOrEvent); + return GetMembersUnordered().Where(IsInstanceFieldOrEventOrProperty); } - protected static Func IsInstanceFieldOrEvent = symbol => + protected static Func IsInstanceFieldOrEventOrProperty = symbol => { if (!symbol.IsStatic) { @@ -563,6 +563,7 @@ internal virtual IEnumerable GetInstanceFieldsAndEvents() { case SymbolKind.Field: case SymbolKind.Event: + case SymbolKind.Property: return true; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs index 81985dabfefe0..8af91857dc44e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs @@ -1597,10 +1597,10 @@ private Dictionary> GetMembersByNameSlow() return _lazyMembersDictionary; } - internal override IEnumerable GetInstanceFieldsAndEvents() + internal override IEnumerable GetInstanceFieldsAndEventsAndProperties() { var membersAndInitializers = this.GetMembersAndInitializers(); - return membersAndInitializers.NonTypeMembers.Where(IsInstanceFieldOrEvent); + return membersAndInitializers.NonTypeMembers.Where(IsInstanceFieldOrEventOrProperty); } protected void AfterMembersChecks(BindingDiagnosticBag diagnostics) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs index 1fbb6f138471f..2a74415e38f5d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs @@ -24,7 +24,7 @@ internal class SourcePropertyAccessorSymbol : SourceMemberMethodSymbol private string _lazyName; private readonly bool _bodyShouldBeSynthesized; private readonly bool _isExpressionBodied; - private readonly bool _containsFieldKeyword; + private readonly bool _containsFieldIdentifier; private readonly bool _usesInit; public static SourcePropertyAccessorSymbol CreateAccessorSymbol( @@ -113,7 +113,7 @@ public static SourcePropertyAccessorSymbol CreateAccessorSymbol( // PROTOTYPE(semi-auto-props): Figure out what is going to be more efficient, to go after tokens and then // checking their parent, or to go after nodes (IdentifierNameSyntax) first and then checking the underlying token. // PROTOTYPE(semi-auto-props): Filter out identifiers that syntactically cannot be keywords. For example those that follow a ., a -> or a :: in names. Something else? - private static bool NodeContainsFieldKeyword(CSharpSyntaxNode? node) + private static bool NodeContainsFieldIdentifier(CSharpSyntaxNode? node) { if (node is null) { @@ -151,7 +151,7 @@ private SourcePropertyAccessorSymbol( _property = property; _bodyShouldBeSynthesized = false; _isExpressionBodied = true; - _containsFieldKeyword = property.IsIndexer ? false : NodeContainsFieldKeyword(syntax); + _containsFieldIdentifier = !property.IsIndexer && NodeContainsFieldIdentifier(syntax); // The modifiers for the accessor are the same as the modifiers for the property, // minus the indexer and readonly bit @@ -197,7 +197,7 @@ protected SourcePropertyAccessorSymbol( { _property = property; _bodyShouldBeSynthesized = bodyShouldBeSynthesized; - _containsFieldKeyword = property.IsIndexer ? false : NodeContainsFieldKeyword(getAccessorSyntax(syntax)); + _containsFieldIdentifier = !property.IsIndexer && NodeContainsFieldIdentifier(getAccessorSyntax(syntax)); Debug.Assert(!_property.IsExpressionBodied, "Cannot have accessors in expression bodied lightweight properties"); _isExpressionBodied = !hasBlockBody && hasExpressionBody; _usesInit = usesInit; @@ -459,8 +459,7 @@ internal Accessibility LocalAccessibility /// This is only calculated from syntax, so we don't know if it /// will bind to something or will create a backing field. /// - // PROTOTYPE(semi-auto-props): Rename to ContainsFieldKeywordSyntactically or similar. - internal bool ContainsFieldKeyword => _containsFieldKeyword; + internal bool ContainsFieldIdentifier => _containsFieldIdentifier; /// /// Indicates whether this accessor has no body in source and a body will be synthesized by the compiler. diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs index d8b0326529b89..13baeee0dfe3f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs @@ -447,7 +447,7 @@ private void EnsureBackingFieldIsSynthesized() if (this is SourcePropertySymbol propertySymbol) { - if (propertySymbol.GetMethod is SourcePropertyAccessorSymbol { ContainsFieldKeyword: true } getMethod) + if (propertySymbol.GetMethod is SourcePropertyAccessorSymbol { ContainsFieldIdentifier: true } getMethod) { noteAccessorBinding(); var binder = getMethod.TryGetBodyBinder(); @@ -456,7 +456,7 @@ private void EnsureBackingFieldIsSynthesized() // If we still don't have a backing field after binding the getter, try binding the setter. if (_lazyBackingFieldSymbol == _lazyBackingFieldSymbolSentinel && - propertySymbol.SetMethod is SourcePropertyAccessorSymbol { ContainsFieldKeyword: true } setMethod) + propertySymbol.SetMethod is SourcePropertyAccessorSymbol { ContainsFieldIdentifier: true } setMethod) { noteAccessorBinding(); setMethod.TryGetBodyBinder()?.BindMethodBody(setMethod.SyntaxNode, BindingDiagnosticBag.Discarded); @@ -813,7 +813,7 @@ private bool AllowFieldAttributeTarget { get { - // PROTOTYPE(semi-auto-props): Fix implementation for semi auto properties. + // PROTOTYPE(semi-auto-props): Fix implementation for semi auto properties. Consider also the BackingField?.GetAttributes() call in GetAttributesBag. Should it handle FieldKeywordBackingField? Add a test. return _getMethod?.BodyShouldBeSynthesized == true || _setMethod?.BodyShouldBeSynthesized == true; } @@ -1626,6 +1626,7 @@ internal override void ForceComplete(SourceLocation locationOpt, CancellationTok { var diagnostics = BindingDiagnosticBag.GetInstance(); var conversions = new TypeConversions(this.ContainingAssembly.CorLibrary); + foreach (var parameter in this.Parameters) { parameter.ForceComplete(locationOpt, cancellationToken); diff --git a/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs index 65ccbac349bc6..61e76da05a5bf 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs @@ -1081,6 +1081,7 @@ SmallDictionary computeDefinitionToMemberMap() case SymbolKind.Event: var underlyingEvent = (EventSymbol)member; + // PROTOTYPE(semi-auto-props): Do we need to do something for properties with FieldKeywordBackingField? var underlyingAssociatedField = underlyingEvent.AssociatedField; // The field is not part of the members list if (underlyingAssociatedField is object) diff --git a/src/Compilers/CSharp/Test/Emit/PDB/PDBWinMdExpTests.cs b/src/Compilers/CSharp/Test/Emit/PDB/PDBWinMdExpTests.cs index 544095b648524..9c601dad59233 100644 --- a/src/Compilers/CSharp/Test/Emit/PDB/PDBWinMdExpTests.cs +++ b/src/Compilers/CSharp/Test/Emit/PDB/PDBWinMdExpTests.cs @@ -242,6 +242,34 @@ public int this[int a] AssertXml.Equal(expected, actual); } + [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] + public void TestWinMdExpData_SemiAutoProperty() + { + var text = @" +public class C +{ + public int P { get => field; } +} +"; + + string expected = @" + + + + + + +"; + + var compilation = CreateCompilationWithMscorlib45( + text, + options: TestOptions.ReleaseWinMD, + sourceFileName: "source.cs").VerifyDiagnostics(); + + string actual = PdbTestUtilities.GetTokenToLocationMap(compilation, true); + AssertXml.Equal(expected, actual); + } + [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void TestWinMdExpData_AnonymousTypes() { diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs index 3a7c2877e996e..41f350ece572e 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs @@ -3461,7 +3461,7 @@ public Point(int x, int y) } [Fact] - public void Test_ContainsFieldKeywordAPI() + public void Test_ContainsFieldIdentifierAPI() { var comp = CreateCompilation(@" public class C1 @@ -3483,12 +3483,12 @@ public class C2 var accessorsC1 = comp.GetTypeByMetadataName("C1").GetMembers().OfType().ToArray(); Assert.Equal(2, accessorsC1.Length); - Assert.False(accessorsC1[0].ContainsFieldKeyword); - Assert.False(accessorsC1[1].ContainsFieldKeyword); + Assert.False(accessorsC1[0].ContainsFieldIdentifier); + Assert.False(accessorsC1[1].ContainsFieldIdentifier); var accessorsC2 = comp.GetTypeByMetadataName("C2").GetMembers().OfType().ToArray(); Assert.Equal(1, accessorsC2.Length); - Assert.False(accessorsC2[0].ContainsFieldKeyword); + Assert.False(accessorsC2[0].ContainsFieldIdentifier); Assert.Equal(0, accessorBindingData.NumberOfPerformedAccessorBinding); } @@ -6094,5 +6094,357 @@ public class C Assert.Equal(0, accessorBindingData.NumberOfPerformedAccessorBinding); } + + [Fact] + public void TestERR_ManagedAddr01() + { + var comp = CreateCompilation(@" +public unsafe struct S1 +{ + public S1* s; + public object P { get => field; } +} +public unsafe struct S2 +{ + public S2* s; + public int P { get => field; } +} +", options: TestOptions.UnsafeDebugDll); + var accessorBindingData = new SourcePropertySymbolBase.AccessorBindingData(); + comp.TestOnlyCompilationData = accessorBindingData; + + comp.VerifyDiagnostics( + // (4,16): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('S1') + // public S1* s; + Diagnostic(ErrorCode.ERR_ManagedAddr, "s").WithArguments("S1").WithLocation(4, 16)); + // PROTOTYPE(semi-auto-props): (Applies to all TestERR_ManagedAddrXX tests) There shouldn't be extra bindings. + Assert.Equal(2, accessorBindingData.NumberOfPerformedAccessorBinding); + } + + [Fact] + public void TestERR_ManagedAddr02() + { + var comp = CreateCompilation(@" +public unsafe struct S1 +{ + public object s; + public S1* P { get => field; } +} +public unsafe struct S2 +{ + public int s; + public S2* P { get => field; } +} +", options: TestOptions.UnsafeDebugDll); + var accessorBindingData = new SourcePropertySymbolBase.AccessorBindingData(); + comp.TestOnlyCompilationData = accessorBindingData; + + comp.VerifyDiagnostics( + // (5,16): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('S1') + // public S1* P { get => field; } + Diagnostic(ErrorCode.ERR_ManagedAddr, "P").WithArguments("S1").WithLocation(5, 16)); + + Assert.Equal(1, accessorBindingData.NumberOfPerformedAccessorBinding); + } + + [Fact] + public void TestERR_ManagedAddr03() + { + var comp = CreateCompilation(@" +public struct S1 +{ + public object P { get => field; } +} + +public unsafe class C +{ + public void M(S1* x) { } +} +", options: TestOptions.UnsafeDebugDll); + var accessorBindingData = new SourcePropertySymbolBase.AccessorBindingData(); + comp.TestOnlyCompilationData = accessorBindingData; + + comp.VerifyDiagnostics( + // (9,23): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('S1') + // public void M(S1* x) { } + Diagnostic(ErrorCode.ERR_ManagedAddr, "x").WithArguments("S1").WithLocation(9, 23)); + + Assert.Equal(1, accessorBindingData.NumberOfPerformedAccessorBinding); + } + + [Fact] + public void TestERR_ManagedAddr04() + { + var comp = CreateCompilation(@" +public struct S1 +{ + public object P { get => field; } +} + +public unsafe interface I +{ + void M(); +} + +public unsafe class C : I +{ + void I.M() { } +} +", options: TestOptions.UnsafeDebugDll); + var accessorBindingData = new SourcePropertySymbolBase.AccessorBindingData(); + comp.TestOnlyCompilationData = accessorBindingData; + + comp.VerifyDiagnostics( + // (12,21): error CS0306: The type 'S1*' may not be used as a type argument + // public unsafe class C : I + Diagnostic(ErrorCode.ERR_BadTypeArgument, "C").WithArguments("S1*").WithLocation(12, 21), + // (12,21): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('S1') + // public unsafe class C : I + Diagnostic(ErrorCode.ERR_ManagedAddr, "C").WithArguments("S1").WithLocation(12, 21), + // (14,10): error CS0306: The type 'S1*' may not be used as a type argument + // void I.M() { } + Diagnostic(ErrorCode.ERR_BadTypeArgument, "I").WithArguments("S1*").WithLocation(14, 10), + // (14,10): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('S1') + // void I.M() { } + Diagnostic(ErrorCode.ERR_ManagedAddr, "I").WithArguments("S1").WithLocation(14, 10)); + + Assert.Equal(1, accessorBindingData.NumberOfPerformedAccessorBinding); + } + + [Fact] + public void TestERR_ManagedAddr05() + { + var comp = CreateCompilation(@" +public struct S1 +{ + public object P { get => field; } +} + +public unsafe interface I +{ + int P { get; set; } +} + +public unsafe class C : I +{ + int I.P { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); } +} +", options: TestOptions.UnsafeDebugDll); + var accessorBindingData = new SourcePropertySymbolBase.AccessorBindingData(); + comp.TestOnlyCompilationData = accessorBindingData; + + comp.VerifyDiagnostics( + // (12,21): error CS0306: The type 'S1*' may not be used as a type argument + // public unsafe class C : I + Diagnostic(ErrorCode.ERR_BadTypeArgument, "C").WithArguments("S1*").WithLocation(12, 21), + // (12,21): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('S1') + // public unsafe class C : I + Diagnostic(ErrorCode.ERR_ManagedAddr, "C").WithArguments("S1").WithLocation(12, 21), + // (14,9): error CS0306: The type 'S1*' may not be used as a type argument + // int I.P { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); } + Diagnostic(ErrorCode.ERR_BadTypeArgument, "I").WithArguments("S1*").WithLocation(14, 9), + // (14,9): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('S1') + // int I.P { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); } + Diagnostic(ErrorCode.ERR_ManagedAddr, "I").WithArguments("S1").WithLocation(14, 9)); + + Assert.Equal(1, accessorBindingData.NumberOfPerformedAccessorBinding); + } + + [Fact] + public void TestERR_ManagedAddr06() + { + var comp = CreateCompilation(@" +public struct S1 +{ + public object P { get => field; } +} + +public unsafe class C +{ + public int this[S1* i] + { + get => 0; + set => _ = value; + } +} +", options: TestOptions.UnsafeDebugDll); + var accessorBindingData = new SourcePropertySymbolBase.AccessorBindingData(); + comp.TestOnlyCompilationData = accessorBindingData; + + comp.VerifyDiagnostics( + // (9,24): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('S1') + // public int this[S1* i] + Diagnostic(ErrorCode.ERR_ManagedAddr, "i").WithArguments("S1").WithLocation(9, 25)); + + Assert.Equal(1, accessorBindingData.NumberOfPerformedAccessorBinding); + } + + [Fact] + public void TestERR_ManagedAddr07() + { + var comp = CreateCompilation(@" +public struct S1 +{ + public object P { get => field; } +} + +public unsafe class C +{ + public C(S1* x) { } +} +", options: TestOptions.UnsafeDebugDll); + var accessorBindingData = new SourcePropertySymbolBase.AccessorBindingData(); + comp.TestOnlyCompilationData = accessorBindingData; + + comp.VerifyDiagnostics( + // (9,18): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('S1') + // public C(S1* x) { } + Diagnostic(ErrorCode.ERR_ManagedAddr, "x").WithArguments("S1").WithLocation(9, 18)); + + Assert.Equal(1, accessorBindingData.NumberOfPerformedAccessorBinding); + } + + [Fact] + public void TestERR_ManagedAddr08() + { + var comp = CreateCompilation(@" +using System; + +public struct S1 +{ + public object P { get => field; } +} + +public unsafe interface I +{ + event EventHandler E; +} + +public unsafe class C : I +{ + event EventHandler I.E { add { } remove { } } +} +", options: TestOptions.UnsafeDebugDll); + var accessorBindingData = new SourcePropertySymbolBase.AccessorBindingData(); + comp.TestOnlyCompilationData = accessorBindingData; + + comp.VerifyDiagnostics( + // (14,21): error CS0306: The type 'S1*' may not be used as a type argument + // public unsafe class C : I + Diagnostic(ErrorCode.ERR_BadTypeArgument, "C").WithArguments("S1*").WithLocation(14, 21), + // (14,21): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('S1') + // public unsafe class C : I + Diagnostic(ErrorCode.ERR_ManagedAddr, "C").WithArguments("S1").WithLocation(14, 21), + // (16,24): error CS0306: The type 'S1*' may not be used as a type argument + // event EventHandler I.E { add { } remove { } } + Diagnostic(ErrorCode.ERR_BadTypeArgument, "I").WithArguments("S1*").WithLocation(16, 24), + // (16,24): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('S1') + // event EventHandler I.E { add { } remove { } } + Diagnostic(ErrorCode.ERR_ManagedAddr, "I").WithArguments("S1").WithLocation(16, 24)); + + Assert.Equal(1, accessorBindingData.NumberOfPerformedAccessorBinding); + } + + [Fact] + public void TestERR_ManagedAddr09() + { + var comp = CreateCompilation(@" +using System; +using MyAlias = S1; + +public struct S1 +{ + public object P { get => field; } +} + +public unsafe interface I +{ + event EventHandler E; +} + +public unsafe class C : I +{ + event EventHandler I.E { add { } remove { } } +} +", options: TestOptions.UnsafeDebugDll); + var accessorBindingData = new SourcePropertySymbolBase.AccessorBindingData(); + comp.TestOnlyCompilationData = accessorBindingData; + + comp.VerifyDiagnostics( + // (15,21): error CS0306: The type 'S1*' may not be used as a type argument + // public unsafe class C : I + Diagnostic(ErrorCode.ERR_BadTypeArgument, "C").WithArguments("S1*").WithLocation(15, 21), + // (15,21): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('S1') + // public unsafe class C : I + Diagnostic(ErrorCode.ERR_ManagedAddr, "C").WithArguments("S1").WithLocation(15, 21), + // (17,24): error CS0306: The type 'S1*' may not be used as a type argument + // event EventHandler I.E { add { } remove { } } + Diagnostic(ErrorCode.ERR_BadTypeArgument, "I").WithArguments("S1*").WithLocation(17, 24), + // (17,24): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('S1') + // event EventHandler I.E { add { } remove { } } + Diagnostic(ErrorCode.ERR_ManagedAddr, "I").WithArguments("S1").WithLocation(17, 24)); + + Assert.Equal(1, accessorBindingData.NumberOfPerformedAccessorBinding); + } + + [Fact] + public void TestERR_ManagedAddr10() + { + var comp = CreateCompilation(@" +public struct S1 +{ + public object P { get => field; } +} + +public unsafe class C +{ + event S1* E; +} +", options: TestOptions.UnsafeDebugDll); + var accessorBindingData = new SourcePropertySymbolBase.AccessorBindingData(); + comp.TestOnlyCompilationData = accessorBindingData; + + comp.VerifyDiagnostics( + // (9,15): error CS0066: 'C.E': event must be of a delegate type + // event S1* E; + Diagnostic(ErrorCode.ERR_EventNotDelegate, "E").WithArguments("C.E").WithLocation(9, 15), + // (9,15): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('S1') + // event S1* E; + Diagnostic(ErrorCode.ERR_ManagedAddr, "E").WithArguments("S1").WithLocation(9, 15), + // (9,15): warning CS0067: The event 'C.E' is never used + // event S1* E; + Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E").WithArguments("C.E").WithLocation(9, 15)); + + Assert.Equal(1, accessorBindingData.NumberOfPerformedAccessorBinding); + } + + [Fact] + public void TestERR_ManagedAddr11() + { + var comp = CreateCompilation(@" +public struct S1 +{ + public object P { get => field; } +} + +public interface I { } + +public unsafe class C where T : I +{ +} +", options: TestOptions.UnsafeDebugDll); + var accessorBindingData = new SourcePropertySymbolBase.AccessorBindingData(); + comp.TestOnlyCompilationData = accessorBindingData; + + comp.VerifyDiagnostics( + // (9,23): error CS0306: The type 'S1*' may not be used as a type argument + // public unsafe class C where T : I + Diagnostic(ErrorCode.ERR_BadTypeArgument, "T").WithArguments("S1*").WithLocation(9, 23), + // (9,23): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('S1') + // public unsafe class C where T : I + Diagnostic(ErrorCode.ERR_ManagedAddr, "T").WithArguments("S1").WithLocation(9, 23)); + + Assert.Equal(1, accessorBindingData.NumberOfPerformedAccessorBinding); + } } }