File: Symbols\Source\SynthesizedEventAccessorSymbol.vb
Web Access
Project: src\src\Compilers\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.vbproj (Microsoft.CodeAnalysis.VisualBasic)
' Licensed to the .NET Foundation under one or more agreements.
' The .NET Foundation licenses this file to you under the MIT license.
' See the LICENSE file in the project root for more information.
 
Imports System.Collections.Immutable
Imports System.Reflection
Imports System.Threading
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.RuntimeMembers
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Emit
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
 
Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
 
    Friend MustInherit Class SynthesizedEventAccessorSymbol
        Inherits SynthesizedAccessor(Of SourceEventSymbol)
 
        Private _lazyReturnType As TypeSymbol
        Private _lazyParameters As ImmutableArray(Of ParameterSymbol)
        Private _lazyExplicitImplementations As ImmutableArray(Of MethodSymbol) ' lazily populated with explicit implementations
 
        Protected Sub New(container As SourceMemberContainerTypeSymbol,
                          [event] As SourceEventSymbol)
            MyBase.New(container, [event])
            ' TODO: custom modifiers
        End Sub
 
        Private ReadOnly Property SourceEvent As SourceEventSymbol
            Get
                Return m_propertyOrEvent
            End Get
        End Property
 
        Public Overrides ReadOnly Property ExplicitInterfaceImplementations As ImmutableArray(Of MethodSymbol)
            Get
                If _lazyExplicitImplementations.IsDefault Then
                    ImmutableInterlocked.InterlockedInitialize(
                        _lazyExplicitImplementations,
                        SourceEvent.GetAccessorImplementations(Me.MethodKind))
                End If
 
                Return _lazyExplicitImplementations
            End Get
        End Property
 
        Public Overrides ReadOnly Property Parameters As ImmutableArray(Of ParameterSymbol)
            Get
                If _lazyParameters.IsDefault Then
                    Dim diagnostics = BindingDiagnosticBag.GetInstance()
 
                    Dim parameterType As TypeSymbol
                    If Me.MethodKind = MethodKind.EventRemove AndAlso m_propertyOrEvent.IsWindowsRuntimeEvent Then
                        parameterType = Me.DeclaringCompilation.GetWellKnownType(WellKnownType.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationToken)
                        diagnostics.Add(Binder.GetUseSiteInfoForWellKnownType(parameterType), Me.Locations(0))
                    Else
                        parameterType = SourceEvent.Type
                    End If
 
                    Dim parameter = New SynthesizedParameterSymbol(Me, parameterType, 0, False, "obj")
                    Dim parameterList = ImmutableArray.Create(Of ParameterSymbol)(parameter)
 
                    DirectCast(Me.ContainingModule, SourceModuleSymbol).AtomicStoreArrayAndDiagnostics(_lazyParameters, parameterList, diagnostics)
 
                    diagnostics.Free()
                End If
 
                Return _lazyParameters
            End Get
        End Property
 
        Public Overrides ReadOnly Property ReturnType As TypeSymbol
            Get
                If _lazyReturnType Is Nothing Then
                    Dim diagnostics = BindingDiagnosticBag.GetInstance()
 
                    Dim compilation = Me.DeclaringCompilation
                    Dim type As TypeSymbol
                    Dim useSiteInfo As UseSiteInfo(Of AssemblySymbol)
                    If Me.IsSub Then
                        type = compilation.GetSpecialType(SpecialType.System_Void)
                        ' Don't report on add, because it will be the same for remove.
                        useSiteInfo = If(Me.MethodKind = MethodKind.EventRemove, Binder.GetUseSiteInfoForSpecialType(type), Nothing)
                    Else
                        type = compilation.GetWellKnownType(WellKnownType.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationToken)
                        useSiteInfo = Binder.GetUseSiteInfoForWellKnownType(type)
                    End If
 
                    diagnostics.Add(useSiteInfo, Me.Locations(0))
 
                    DirectCast(Me.ContainingModule, SourceModuleSymbol).AtomicStoreReferenceAndDiagnostics(_lazyReturnType, type, diagnostics)
 
                    diagnostics.Free()
                End If
 
                Debug.Assert(_lazyReturnType IsNot Nothing)
                Return _lazyReturnType
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsSub As Boolean
            Get
                Return Not (Me.MethodKind = MethodKind.EventAdd AndAlso m_propertyOrEvent.IsWindowsRuntimeEvent)
            End Get
        End Property
 
        Friend Overrides Function GetBoundMethodBody(compilationState As TypeCompilationState, diagnostics As BindingDiagnosticBag, Optional ByRef methodBodyBinder As Binder = Nothing) As BoundBlock
            Dim compilation = Me.DeclaringCompilation
            Return ConstructFieldLikeEventAccessorBody(Me.m_propertyOrEvent, Me.MethodKind = MethodKind.EventAdd, compilation, diagnostics)
        End Function
 
        Protected Shared Function ConstructFieldLikeEventAccessorBody(eventSymbol As SourceEventSymbol,
                                                           isAddMethod As Boolean,
                                                           compilation As VisualBasicCompilation,
                                                           diagnostics As BindingDiagnosticBag) As BoundBlock
            Debug.Assert(eventSymbol.HasAssociatedField)
            Dim result As BoundBlock = If(eventSymbol.IsWindowsRuntimeEvent,
                       ConstructFieldLikeEventAccessorBody_WinRT(eventSymbol, isAddMethod, compilation, diagnostics),
                       ConstructFieldLikeEventAccessorBody_Regular(eventSymbol, isAddMethod, compilation, diagnostics))
 
            ' Contract guarantees non-nothing return.
            Return If(result,
                      New BoundBlock(
                        DirectCast(eventSymbol.SyntaxReference.GetSyntax(), VisualBasicSyntaxNode),
                        Nothing,
                        ImmutableArray(Of LocalSymbol).Empty,
                        ImmutableArray(Of BoundStatement).Empty,
                        hasErrors:=True))
        End Function
 
        Private Shared Function ConstructFieldLikeEventAccessorBody_WinRT(eventSymbol As SourceEventSymbol,
                                                           isAddMethod As Boolean,
                                                           compilation As VisualBasicCompilation,
                                                           diagnostics As BindingDiagnosticBag) As BoundBlock
            Dim syntax = eventSymbol.SyntaxReference.GetVisualBasicSyntax()
 
            Dim accessor As MethodSymbol = If(isAddMethod, eventSymbol.AddMethod, eventSymbol.RemoveMethod)
            Debug.Assert(accessor IsNot Nothing)
 
            Dim field As FieldSymbol = eventSymbol.AssociatedField
            Debug.Assert(field IsNot Nothing)
 
            Dim fieldType As NamedTypeSymbol = DirectCast(field.Type, NamedTypeSymbol)
            Debug.Assert(fieldType.Name = "EventRegistrationTokenTable")
 
            ' Don't cascade.
            If fieldType.IsErrorType Then
                Return Nothing
            End If
 
            Dim useSiteInfo As UseSiteInfo(Of AssemblySymbol) = Nothing
 
            Dim getOrCreateMethod As MethodSymbol = DirectCast(Binder.GetWellKnownTypeMember(
                compilation,
                WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__GetOrCreateEventRegistrationTokenTable,
                useSiteInfo), MethodSymbol)
 
            diagnostics.Add(useSiteInfo, syntax.GetLocation())
            Debug.Assert(getOrCreateMethod IsNot Nothing OrElse useSiteInfo.DiagnosticInfo IsNot Nothing)
 
            If getOrCreateMethod Is Nothing Then
                Return Nothing
            End If
 
            getOrCreateMethod = getOrCreateMethod.AsMember(fieldType)
 
            Dim processHandlerMember As WellKnownMember = If(isAddMethod,
                WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__AddEventHandler,
                WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__RemoveEventHandler)
 
            useSiteInfo = Nothing
            Dim processHandlerMethod As MethodSymbol = DirectCast(Binder.GetWellKnownTypeMember(
                compilation,
                processHandlerMember,
                useSiteInfo), MethodSymbol)
 
            diagnostics.Add(useSiteInfo, syntax.GetLocation())
            Debug.Assert(processHandlerMethod IsNot Nothing OrElse useSiteInfo.DiagnosticInfo IsNot Nothing)
 
            If processHandlerMethod Is Nothing Then
                Return Nothing
            End If
 
            processHandlerMethod = processHandlerMethod.AsMember(fieldType)
 
            ' _tokenTable
            Dim fieldAccess = New BoundFieldAccess(
                syntax,
                If(field.IsShared, Nothing, New BoundMeReference(syntax, accessor.MeParameter.Type)),
                field,
                isLValue:=True,
                type:=field.Type).MakeCompilerGenerated()
 
            ' EventRegistrationTokenTable(Of Event).GetOrCreateEventRegistrationTokenTable(_tokenTable)
            Dim getOrCreateCall = New BoundCall(
                syntax:=syntax,
                method:=getOrCreateMethod,
                methodGroupOpt:=Nothing,
                receiverOpt:=Nothing,
                arguments:=ImmutableArray.Create(Of BoundExpression)(fieldAccess),
                constantValueOpt:=Nothing,
                type:=getOrCreateMethod.ReturnType).MakeCompilerGenerated()
 
            Dim parameterSymbol As ParameterSymbol = accessor.Parameters.Single()
 
            ' value
            Dim parameterAccess = New BoundParameter(
                syntax,
                parameterSymbol,
                isLValue:=False,
                type:=parameterSymbol.Type).MakeCompilerGenerated()
 
            ' EventRegistrationTokenTable(Of Event).GetOrCreateEventRegistrationTokenTable(_tokenTable).AddHandler(value) ' or RemoveHandler
            Dim processHandlerCall = New BoundCall(
                syntax:=syntax,
                method:=processHandlerMethod,
                methodGroupOpt:=Nothing,
                receiverOpt:=getOrCreateCall,
                arguments:=ImmutableArray.Create(Of BoundExpression)(parameterAccess),
                constantValueOpt:=Nothing,
                type:=processHandlerMethod.ReturnType).MakeCompilerGenerated()
 
            If isAddMethod Then
                ' {
                '     return EventRegistrationTokenTable(Of Event).GetOrCreateEventRegistrationTokenTable(_tokenTable).AddHandler(value)
                ' }   
                Dim returnStatement = New BoundReturnStatement(syntax, processHandlerCall, functionLocalOpt:=Nothing, exitLabelOpt:=Nothing)
                Return New BoundBlock(
                    syntax,
                    statementListSyntax:=Nothing,
                    locals:=ImmutableArray(Of LocalSymbol).Empty,
                    statements:=ImmutableArray.Create(Of BoundStatement)(returnStatement)).MakeCompilerGenerated()
            Else
                ' {
                '     EventRegistrationTokenTable(Of Event).GetOrCreateEventRegistrationTokenTable(_tokenTable).RemoveHandler(value)
                '     return
                ' }  
                Dim callStatement = New BoundExpressionStatement(syntax, processHandlerCall).MakeCompilerGenerated()
                Dim returnStatement = New BoundReturnStatement(syntax, expressionOpt:=Nothing, functionLocalOpt:=Nothing, exitLabelOpt:=Nothing)
                Return New BoundBlock(
                    syntax,
                    statementListSyntax:=Nothing,
                    locals:=ImmutableArray(Of LocalSymbol).Empty,
                    statements:=ImmutableArray.Create(Of BoundStatement)(callStatement, returnStatement)).MakeCompilerGenerated()
            End If
 
        End Function
 
        ''' <summary>
        ''' Generate a thread-safe accessor for a field-like event.
        ''' 
        ''' DelegateType tmp0 = _event; //backing field
        ''' DelegateType tmp1;
        ''' DelegateType tmp2;
        ''' do {
        '''     tmp1 = tmp0;
        '''     tmp2 = (DelegateType)Delegate.Combine(tmp1, value); //Remove for -=
        '''     tmp0 = Interlocked.CompareExchange&lt; DelegateType&gt; (ref _event, tmp2, tmp1);
        ''' } while ((object)tmp0 != (object)tmp1);
        ''' 
        ''' Note, if System.Threading.Interlocked.CompareExchange&lt;T&gt; Is Not available,
        ''' we emit the following code And mark the method Synchronized (unless it Is a struct).
        ''' 
        ''' _event = (DelegateType)Delegate.Combine(_event, value); //Remove for -=
        ''' 
        ''' </summary>
        Private Shared Function ConstructFieldLikeEventAccessorBody_Regular(eventSymbol As SourceEventSymbol,
                                                                   isAddMethod As Boolean,
                                                                   compilation As VisualBasicCompilation,
                                                                   diagnostics As BindingDiagnosticBag) As BoundBlock
 
            If Not eventSymbol.Type.IsDelegateType() Then
                Return Nothing
            End If
 
            Dim syntax = eventSymbol.SyntaxReference.GetVisualBasicSyntax
            Dim delegateType As TypeSymbol = eventSymbol.Type
            Dim accessor As MethodSymbol = If(isAddMethod, eventSymbol.AddMethod, eventSymbol.RemoveMethod)
            Dim meParameter As ParameterSymbol = accessor.MeParameter
            Dim boolType As TypeSymbol = compilation.GetSpecialType(SpecialType.System_Boolean)
 
            Dim updateMethodId As SpecialMember = If(isAddMethod, SpecialMember.System_Delegate__Combine, SpecialMember.System_Delegate__Remove)
 
            Dim useSiteInfo As UseSiteInfo(Of AssemblySymbol) = Nothing
            Dim updateMethod As MethodSymbol = DirectCast(Binder.GetSpecialTypeMember(compilation.Assembly, updateMethodId, useSiteInfo), MethodSymbol)
 
            diagnostics.Add(useSiteInfo, syntax.GetLocation())
 
            Dim [return] As BoundStatement = New BoundReturnStatement(syntax,
                                                                      Nothing,
                                                                      Nothing,
                                                                      Nothing).MakeCompilerGenerated
 
            If updateMethod Is Nothing Then
                Return New BoundBlock(syntax,
                                  Nothing,
                                  ImmutableArray(Of LocalSymbol).Empty,
                                  ImmutableArray.Create(Of BoundStatement)([return])
                                  ).MakeCompilerGenerated
            End If
 
            useSiteInfo = Nothing
            Dim compareExchangeMethod As MethodSymbol = DirectCast(Binder.GetWellKnownTypeMember(compilation, WellKnownMember.System_Threading_Interlocked__CompareExchange_T, useSiteInfo), MethodSymbol)
 
            Dim fieldReceiver As BoundMeReference = If(eventSymbol.IsShared,
                                                       Nothing,
                                                       New BoundMeReference(syntax, meParameter.Type).MakeCompilerGenerated)
 
            Dim fieldSymbol = eventSymbol.AssociatedField
            Dim boundBackingField As BoundFieldAccess = New BoundFieldAccess(syntax,
                                                                             fieldReceiver,
                                                                             fieldSymbol,
                                                                             True,
                                                                             fieldSymbol.Type).MakeCompilerGenerated
 
            Dim parameterSymbol = accessor.Parameters(0)
            Dim boundParameter As BoundParameter = New BoundParameter(syntax,
                                                                      parameterSymbol,
                                                                      isLValue:=False,
                                                                      type:=parameterSymbol.Type).MakeCompilerGenerated
 
            Dim delegateUpdate As BoundExpression
            Dim conversionsUseSiteInfo As New CompoundUseSiteInfo(Of AssemblySymbol)(diagnostics, compilation.Assembly)
            Dim conversionKind1 As ConversionKind
            Dim conversionKind2 As ConversionKind
 
            If compareExchangeMethod Is Nothing Then
 
                ' (DelegateType)Delegate.Combine(_event, value)
                conversionKind1 = Conversions.ClassifyDirectCastConversion(fieldSymbol.Type, updateMethod.Parameters(0).Type, conversionsUseSiteInfo)
                conversionKind2 = Conversions.ClassifyDirectCastConversion(boundParameter.Type, updateMethod.Parameters(1).Type, conversionsUseSiteInfo)
                Debug.Assert(conversionKind1 = ConversionKind.WideningReference)
                Debug.Assert(conversionKind2 = ConversionKind.WideningReference)
 
                diagnostics.Add(syntax.GetLocation(), conversionsUseSiteInfo)
 
                delegateUpdate = New BoundDirectCast(syntax,
                                                     New BoundCall(syntax,
                                                                   updateMethod,
                                                                   Nothing,
                                                                   Nothing,
                                                                   ImmutableArray.Create(Of BoundExpression)(
                                                                       New BoundDirectCast(syntax, boundBackingField.MakeRValue(), ConversionKind.WideningReference, updateMethod.Parameters(0).Type),
                                                                       New BoundDirectCast(syntax, boundParameter, ConversionKind.WideningReference, updateMethod.Parameters(1).Type)),
                                                                   Nothing,
                                                                   updateMethod.ReturnType),
                                                               ConversionKind.NarrowingReference,
                                                               delegateType,
                                                               delegateType.IsErrorType).MakeCompilerGenerated
 
                ' _event = (DelegateType)Delegate.Combine(_event, value);
                Dim eventUpdate As BoundStatement = New BoundExpressionStatement(syntax,
                                                                            New BoundAssignmentOperator(syntax,
                                                                                                        boundBackingField,
                                                                                                        delegateUpdate,
                                                                                                        True,
                                                                                                        delegateType).MakeCompilerGenerated
                                                                                                    ).MakeCompilerGenerated
 
                Return New BoundBlock(syntax,
                                  Nothing,
                                  ImmutableArray(Of LocalSymbol).Empty,
                                  ImmutableArray.Create(Of BoundStatement)(
                                      eventUpdate,
                                      [return])
                                  ).MakeCompilerGenerated
            End If
 
            diagnostics.Add(useSiteInfo, syntax.GetLocation())
 
            compareExchangeMethod = compareExchangeMethod.Construct(ImmutableArray.Create(Of TypeSymbol)(delegateType))
 
            Dim loopLabel As GeneratedLabelSymbol = New GeneratedLabelSymbol("LOOP")
            Const numTemps As Integer = 3
            Dim tmps As LocalSymbol() = New LocalSymbol(numTemps - 1) {}
            Dim boundTmps As BoundLocal() = New BoundLocal(numTemps - 1) {}
 
            Dim i As Integer = 0
            While i < tmps.Length
                tmps(i) = New SynthesizedLocal(accessor, delegateType, SynthesizedLocalKind.LoweringTemp)
                boundTmps(i) = New BoundLocal(syntax, tmps(i), delegateType)
                i = i + 1
            End While
 
            ' tmp0 = _event;
            Dim tmp0Init As BoundStatement = New BoundExpressionStatement(syntax,
                                                                          New BoundAssignmentOperator(syntax,
                                                                                                      boundTmps(0),
                                                                                                      boundBackingField.MakeRValue(),
                                                                                                      True,
                                                                                                      delegateType).MakeCompilerGenerated
                                                                                                  ).MakeCompilerGenerated
 
            ' LOOP:
            Dim loopStart As BoundStatement = New BoundLabelStatement(syntax, loopLabel).MakeCompilerGenerated
 
            ' tmp1 = tmp0;
            Dim tmp1Update As BoundStatement = New BoundExpressionStatement(syntax,
                                                                            New BoundAssignmentOperator(syntax,
                                                                                                        boundTmps(1),
                                                                                                        boundTmps(0).MakeRValue(),
                                                                                                        True,
                                                                                                        delegateType).MakeCompilerGenerated
                                                                                                    ).MakeCompilerGenerated
 
            ' (DelegateType)Delegate.Combine(tmp1, value)
            conversionKind1 = Conversions.ClassifyDirectCastConversion(boundTmps(1).Type, updateMethod.Parameters(0).Type, CompoundUseSiteInfo(Of AssemblySymbol).Discarded)
            conversionKind2 = Conversions.ClassifyDirectCastConversion(boundParameter.Type, updateMethod.Parameters(1).Type, CompoundUseSiteInfo(Of AssemblySymbol).Discarded)
            Debug.Assert(conversionKind1 = ConversionKind.WideningReference)
            Debug.Assert(conversionKind2 = ConversionKind.WideningReference)
 
            diagnostics.Add(syntax.GetLocation(), conversionsUseSiteInfo)
 
            delegateUpdate = New BoundDirectCast(syntax,
                                                 New BoundCall(syntax,
                                                               updateMethod,
                                                               Nothing,
                                                               Nothing,
                                                               ImmutableArray.Create(Of BoundExpression)(
                                                                   New BoundDirectCast(syntax, boundTmps(1).MakeRValue(), ConversionKind.WideningReference, updateMethod.Parameters(0).Type),
                                                                   New BoundDirectCast(syntax, boundParameter, ConversionKind.WideningReference, updateMethod.Parameters(1).Type)),
                                                               Nothing,
                                                               updateMethod.ReturnType),
                                                           ConversionKind.NarrowingReference,
                                                           delegateType,
                                                           delegateType.IsErrorType).MakeCompilerGenerated
 
            ' tmp2 = (DelegateType)Delegate.Combine(tmp1, value);
            Dim tmp2Update As BoundStatement = New BoundExpressionStatement(syntax,
                                                                            New BoundAssignmentOperator(syntax,
                                                                                                        boundTmps(2),
                                                                                                        delegateUpdate,
                                                                                                        True,
                                                                                                        delegateType).MakeCompilerGenerated
                                                                                                    ).MakeCompilerGenerated
 
            ' Interlocked.CompareExchange<DelegateType>(ref _event, tmp2, tmp1)
            Dim compareExchange As BoundExpression = New BoundCall(syntax,
                                                                   compareExchangeMethod,
                                                                   Nothing,
                                                                   Nothing,
                                                                   ImmutableArray.Create(Of BoundExpression)(boundBackingField, boundTmps(2).MakeRValue(), boundTmps(1).MakeRValue()),
                                                                   Nothing,
                                                                   compareExchangeMethod.ReturnType)
 
            ' tmp0 = Interlocked.CompareExchange<DelegateType>(ref _event, tmp2, tmp1);
            Dim tmp0Update As BoundStatement = New BoundExpressionStatement(syntax,
                                                                            New BoundAssignmentOperator(syntax,
                                                                                                        boundTmps(0),
                                                                                                        compareExchange,
                                                                                                        True,
                                                                                                        delegateType).MakeCompilerGenerated
                                                                                                    ).MakeCompilerGenerated
 
            ' tmp[0] == tmp[1] // i.e. exit when they are equal, jump to start otherwise
            Dim loopExitCondition As BoundExpression = New BoundBinaryOperator(syntax,
                                                                               BinaryOperatorKind.Is,
                                                                               boundTmps(0).MakeRValue(),
                                                                               boundTmps(1).MakeRValue(),
                                                                               False,
                                                                               boolType).MakeCompilerGenerated
 
            ' branchfalse (tmp[0] == tmp[1]) LOOP
            Dim loopEnd As BoundStatement = New BoundConditionalGoto(syntax,
                                                                     loopExitCondition,
                                                                     False,
                                                                     loopLabel).MakeCompilerGenerated
 
            Return New BoundBlock(syntax,
                                  Nothing,
                                  tmps.AsImmutable(),
                                  ImmutableArray.Create(Of BoundStatement)(
                                      tmp0Init,
                                      loopStart,
                                      tmp1Update,
                                      tmp2Update,
                                      tmp0Update,
                                      loopEnd,
                                      [return])
                                  ).MakeCompilerGenerated
        End Function
 
        Friend Overrides Sub GenerateDeclarationErrors(cancellationToken As CancellationToken)
            MyBase.GenerateDeclarationErrors(cancellationToken)
 
            cancellationToken.ThrowIfCancellationRequested()
            Dim unusedParameters = Me.Parameters
            Dim unusedReturnType = Me.ReturnType
        End Sub
 
        Friend Overrides Sub AddSynthesizedAttributes(moduleBuilder As PEModuleBuilder, ByRef attributes As ArrayBuilder(Of SynthesizedAttributeData))
            MyBase.AddSynthesizedAttributes(moduleBuilder, attributes)
 
            Debug.Assert(Not ContainingType.IsImplicitlyDeclared)
            Dim compilation = Me.DeclaringCompilation
            AddSynthesizedAttribute(attributes,
                                    compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_CompilerGeneratedAttribute__ctor))
 
            ' Dev11 adds DebuggerNonUserCode; there is no reason to do so since:
            ' - we emit no debug info for the body
            ' - the code doesn't call any user code that could inspect the stack and find the accessor's frame
            ' - the code doesn't throw exceptions whose stack frames we would need to hide
            ' 
            ' C# also doesn't add DebuggerHidden nor DebuggerNonUserCode attributes.
        End Sub
 
        Friend NotOverridable Overrides ReadOnly Property GenerateDebugInfoImpl As Boolean
            Get
                Return False
            End Get
        End Property
 
        Friend NotOverridable Overrides Function CalculateLocalSyntaxOffset(localPosition As Integer, localTree As SyntaxTree) As Integer
            Throw ExceptionUtilities.Unreachable
        End Function
 
        Friend Overrides ReadOnly Property ImplementationAttributes As MethodImplAttributes
            Get
                Dim result = MyBase.ImplementationAttributes
 
                If Not IsMustOverride AndAlso Not SourceEvent.IsWindowsRuntimeEvent AndAlso Not ContainingType.IsStructureType() AndAlso
                   DeclaringCompilation.GetWellKnownTypeMember(WellKnownMember.System_Threading_Interlocked__CompareExchange_T) Is Nothing Then
                    ' Under these conditions, this method needs to be synchronized.
                    result = result Or MethodImplAttributes.Synchronized
                End If
 
                Return result
            End Get
        End Property
    End Class
 
    Friend NotInheritable Class SynthesizedAddAccessorSymbol
        Inherits SynthesizedEventAccessorSymbol
 
        Public Sub New(container As SourceMemberContainerTypeSymbol,
                          [event] As SourceEventSymbol)
            MyBase.New(container, [event])
        End Sub
 
        Public Overrides ReadOnly Property MethodKind As MethodKind
            Get
                Return MethodKind.EventAdd
            End Get
        End Property
    End Class
 
    Friend NotInheritable Class SynthesizedRemoveAccessorSymbol
        Inherits SynthesizedEventAccessorSymbol
 
        Public Sub New(container As SourceMemberContainerTypeSymbol,
                          [event] As SourceEventSymbol)
            MyBase.New(container, [event])
        End Sub
 
        Public Overrides ReadOnly Property MethodKind As MethodKind
            Get
                Return MethodKind.EventRemove
            End Get
        End Property
    End Class
 
End Namespace