private static void CheckNonOverrideMember(
            Symbol hidingMember,
            bool hidingMemberIsNew,
            OverriddenOrHiddenMembersResult overriddenOrHiddenMembers,
            DiagnosticBag diagnostics, out bool suppressAccessors)
        {
            suppressAccessors = false;

            var hidingMemberLocation = hidingMember.Locations[0];

            Debug.Assert(overriddenOrHiddenMembers != null);
            Debug.Assert(!overriddenOrHiddenMembers.OverriddenMembers.Any()); //since hidingMethod.IsOverride is false
            Debug.Assert(!overriddenOrHiddenMembers.RuntimeOverriddenMembers.Any()); //since hidingMethod.IsOverride is false

            var hiddenMembers = overriddenOrHiddenMembers.HiddenMembers;
            Debug.Assert(!hiddenMembers.IsDefault);

            if (hiddenMembers.Length == 0)
            {
                if (hidingMemberIsNew && !hidingMember.IsAccessor())
                {
                    diagnostics.Add(ErrorCode.WRN_NewNotRequired, hidingMemberLocation, hidingMember);
                }
            }
            else
            {
                var diagnosticAdded = false;

                //for interfaces, we always report WRN_NewRequired
                //if we went into the loop, the pseudo-abstract nature of interfaces would throw off the other checks
                if (!hidingMember.ContainingType.IsInterface)
                {
                    foreach (var hiddenMember in hiddenMembers)
                    {
                        diagnosticAdded |= AddHidingAbstractDiagnostic(hidingMember, hidingMemberLocation, hiddenMember, diagnostics, ref suppressAccessors);

                        //can actually get both, so don't use else if
                        if (!hidingMemberIsNew && hiddenMember.Kind == hidingMember.Kind &&
                            !hidingMember.IsAccessor() &&
                            (hiddenMember.IsAbstract || hiddenMember.IsVirtual || hiddenMember.IsOverride))
                        {
                            diagnostics.Add(ErrorCode.WRN_NewOrOverrideExpected, hidingMemberLocation, hidingMember, hiddenMember);
                            diagnosticAdded = true;
                        }

                        if (diagnosticAdded)
                        {
                            break;
                        }
                    }
                }

                if (!hidingMemberIsNew && !diagnosticAdded && !hidingMember.IsAccessor() && !hidingMember.IsOperator())
                {
                    diagnostics.Add(ErrorCode.WRN_NewRequired, hidingMemberLocation, hidingMember, hiddenMembers[0]);
                }
            }
        }
        private static void CheckOverrideMember(Symbol overridingMember, OverriddenOrHiddenMembersResult overriddenOrHiddenMembers,
            DiagnosticBag diagnostics, out bool suppressAccessors)
        {
            Debug.Assert((object)overridingMember != null);
            Debug.Assert(overriddenOrHiddenMembers != null);

            suppressAccessors = false;

            var overridingMemberIsMethod = overridingMember.Kind == SymbolKind.Method;
            var overridingMemberIsProperty = overridingMember.Kind == SymbolKind.Property;
            var overridingMemberIsEvent = overridingMember.Kind == SymbolKind.Event;

            Debug.Assert(overridingMemberIsMethod ^ overridingMemberIsProperty ^ overridingMemberIsEvent);

            var overridingMemberLocation = overridingMember.Locations[0];

            var overriddenMembers = overriddenOrHiddenMembers.OverriddenMembers;
            Debug.Assert(!overriddenMembers.IsDefault);

            if (overriddenMembers.Length == 0)
            {
                var hiddenMembers = overriddenOrHiddenMembers.HiddenMembers;
                Debug.Assert(!hiddenMembers.IsDefault);

                if (hiddenMembers.Any())
                {
                    ErrorCode errorCode =
                        overridingMemberIsMethod ? ErrorCode.ERR_CantOverrideNonFunction :
                        overridingMemberIsProperty ? ErrorCode.ERR_CantOverrideNonProperty :
                        ErrorCode.ERR_CantOverrideNonEvent;

                    diagnostics.Add(errorCode, overridingMemberLocation, overridingMember, hiddenMembers[0]);
                }
                else
                {
                    Symbol associatedPropertyOrEvent = null;
                    if (overridingMemberIsMethod)
                    {
                        associatedPropertyOrEvent = ((MethodSymbol)overridingMember).AssociatedSymbol;
                    }

                    if ((object)associatedPropertyOrEvent == null)
                    {
                        diagnostics.Add(ErrorCode.ERR_OverrideNotExpected, overridingMemberLocation, overridingMember);
                    }
                    else if (associatedPropertyOrEvent.Kind == SymbolKind.Property) //no specific errors for event accessors
                    {
                        PropertySymbol associatedProperty = (PropertySymbol)associatedPropertyOrEvent;
                        PropertySymbol overriddenProperty = associatedProperty.OverriddenProperty;

                        if ((object)overriddenProperty == null)
                        {
                            //skip remaining checks
                        }
                        else if (associatedProperty.GetMethod == overridingMember && (object)overriddenProperty.GetMethod == null)
                        {
                            diagnostics.Add(ErrorCode.ERR_NoGetToOverride, overridingMemberLocation, overridingMember, overriddenProperty);
                        }
                        else if (associatedProperty.SetMethod == overridingMember && (object)overriddenProperty.SetMethod == null)
                        {
                            diagnostics.Add(ErrorCode.ERR_NoSetToOverride, overridingMemberLocation, overridingMember, overriddenProperty);
                        }
                        else
                        {
                            diagnostics.Add(ErrorCode.ERR_OverrideNotExpected, overridingMemberLocation, overridingMember);
                        }
                    }
                }
            }
            else
            {
                NamedTypeSymbol overridingType = overridingMember.ContainingType;
                if (overriddenMembers.Length > 1)
                {
                    diagnostics.Add(ErrorCode.ERR_AmbigOverride, overridingMemberLocation,
                        overriddenMembers[0].OriginalDefinition, overriddenMembers[1].OriginalDefinition, overridingType);
                    suppressAccessors = true;
                }
                else
                {
                    var overriddenMember = overriddenMembers[0];

                    //otherwise, it would have been excluded during lookup
                    HashSet<DiagnosticInfo> useSiteDiagnosticsNotUsed = null;
                    Debug.Assert(AccessCheck.IsSymbolAccessible(overriddenMember, overridingType, ref useSiteDiagnosticsNotUsed));

                    Debug.Assert(overriddenMember.Kind == overridingMember.Kind);

                    if (overriddenMember.MustCallMethodsDirectly())
                    {
                        diagnostics.Add(ErrorCode.ERR_CantOverrideBogusMethod, overridingMemberLocation, overridingMember, overriddenMember);
                        suppressAccessors = true;
                    }
                    else if (!overriddenMember.IsVirtual && !overriddenMember.IsAbstract && !overriddenMember.IsOverride &&
                        !(overridingMemberIsMethod && ((MethodSymbol)overriddenMember).MethodKind == MethodKind.Destructor)) //destructors are metadata virtual
                    {
                        // CONSIDER: To match Dev10, skip the error for properties, and don't suppressAccessors
                        diagnostics.Add(ErrorCode.ERR_CantOverrideNonVirtual, overridingMemberLocation, overridingMember, overriddenMember);
                        suppressAccessors = true;
                    }
                    else if (overriddenMember.IsSealed)
                    {
                        // CONSIDER: To match Dev10, skip the error for properties, and don't suppressAccessors
                        diagnostics.Add(ErrorCode.ERR_CantOverrideSealed, overridingMemberLocation, overridingMember, overriddenMember);
                        suppressAccessors = true;
                    }
                    else if (!overridingMember.IsPartialMethod() && !OverrideHasCorrectAccessibility(overriddenMember, overridingMember))
                    {
                        var accessibility = SyntaxFacts.GetText(overriddenMember.DeclaredAccessibility);
                        diagnostics.Add(ErrorCode.ERR_CantChangeAccessOnOverride, overridingMemberLocation, overridingMember, accessibility, overriddenMember);
                        suppressAccessors = true;
                    }
                    else
                    {
                        // As in dev11, we don't compare obsoleteness to the immediately-overridden member,
                        // but to the least-overridden member.
                        var leastOverriddenMember = overriddenMember.GetLeastOverriddenMember(overriddenMember.ContainingType);

                        overridingMember.ForceCompleteObsoleteAttribute();
                        leastOverriddenMember.ForceCompleteObsoleteAttribute();

                        Debug.Assert(overridingMember.ObsoleteState != ThreeState.Unknown);
                        Debug.Assert(leastOverriddenMember.ObsoleteState != ThreeState.Unknown);

                        bool overridingMemberIsObsolete = overridingMember.ObsoleteState == ThreeState.True;
                        bool leastOverriddenMemberIsObsolete = leastOverriddenMember.ObsoleteState == ThreeState.True;

                        if (overridingMemberIsObsolete != leastOverriddenMemberIsObsolete)
                        {
                            ErrorCode code = overridingMemberIsObsolete
                                ? ErrorCode.WRN_ObsoleteOverridingNonObsolete
                                : ErrorCode.WRN_NonObsoleteOverridingObsolete;

                            diagnostics.Add(code, overridingMemberLocation, overridingMember, leastOverriddenMember);
                        }
                        else if (overridingMemberIsProperty)
                        {
                            PropertySymbol overridingProperty = (PropertySymbol)overridingMember;
                            PropertySymbol overriddenProperty = (PropertySymbol)overriddenMember;

                            TypeSymbol overridingMemberType = overridingProperty.Type;
                            TypeSymbol overriddenMemberType = overriddenProperty.Type;

                            // Ignore custom modifiers because this diagnostic is based on the C# semantics.
                            if (!overridingMemberType.Equals(overriddenMemberType, ignoreCustomModifiersAndArraySizesAndLowerBounds: true, ignoreDynamic: true))
                            {
                                diagnostics.Add(ErrorCode.ERR_CantChangeTypeOnOverride, overridingMemberLocation, overridingMember, overriddenMember, overriddenMemberType);
                                suppressAccessors = true; //we get really unhelpful errors from the accessor if the type is mismatched
                            }

                            // If the overriding property is sealed, then the overridden accessors cannot be inaccessible, since we
                            // have to override them to make them sealed in metadata.
                            // CONSIDER: It might be nice if this had its own error code(s) since it's an implementation restriction,
                            // rather than a language restriction as above.
                            if (overridingProperty.IsSealed)
                            {
                                MethodSymbol ownOrInheritedGetMethod = overridingProperty.GetOwnOrInheritedGetMethod();
                                HashSet<DiagnosticInfo> useSiteDiagnostics = null;
                                if (overridingProperty.GetMethod != ownOrInheritedGetMethod && !AccessCheck.IsSymbolAccessible(ownOrInheritedGetMethod, overridingType, ref useSiteDiagnostics))
                                {
                                    diagnostics.Add(ErrorCode.ERR_NoGetToOverride, overridingMemberLocation, overridingProperty, overriddenProperty);
                                }

                                MethodSymbol ownOrInheritedSetMethod = overridingProperty.GetOwnOrInheritedSetMethod();
                                if (overridingProperty.SetMethod != ownOrInheritedSetMethod && !AccessCheck.IsSymbolAccessible(ownOrInheritedSetMethod, overridingType, ref useSiteDiagnostics))
                                {
                                    diagnostics.Add(ErrorCode.ERR_NoSetToOverride, overridingMemberLocation, overridingProperty, overriddenProperty);
                                }

                                diagnostics.Add(overridingMemberLocation, useSiteDiagnostics);
                            }
                        }
                        else if (overridingMemberIsEvent)
                        {
                            EventSymbol overridingEvent = (EventSymbol)overridingMember;
                            EventSymbol overriddenEvent = (EventSymbol)overriddenMember;

                            TypeSymbol overridingMemberType = overridingEvent.Type;
                            TypeSymbol overriddenMemberType = overriddenEvent.Type;

                            // Ignore custom modifiers because this diagnostic is based on the C# semantics.
                            if (!overridingMemberType.Equals(overriddenMemberType, ignoreCustomModifiersAndArraySizesAndLowerBounds: true, ignoreDynamic: true))
                            {
                                diagnostics.Add(ErrorCode.ERR_CantChangeTypeOnOverride, overridingMemberLocation, overridingMember, overriddenMember, overriddenMemberType);
                                suppressAccessors = true; //we get really unhelpful errors from the accessor if the type is mismatched
                            }
                        }
                        else
                        {
                            Debug.Assert(overridingMemberIsMethod);

                            var overridingMethod = (MethodSymbol)overridingMember;
                            var overriddenMethod = (MethodSymbol)overriddenMember;

                            // Ignore custom modifiers, because this diagnostic is based on the C# semantics.
                            if (!MemberSignatureComparer.HaveSameReturnTypes(overridingMethod, overriddenMethod, considerCustomModifiers: false))
                            {
                                // Suppose we have a virtual base class method M<T>() that returns C<T>, and the overriding
                                // method M<V> returns void. The error should be "return type must be C<V>", not 
                                // "return type must be C<T>".

                                TypeSymbol returnType = overriddenMethod.IsGenericMethod ?
                                    overriddenMethod.Construct(overridingMethod.TypeParameters.Cast<TypeParameterSymbol, TypeSymbol>()).ReturnType :
                                    overriddenMethod.ReturnType;

                                // error CS0508: return type must be 'C<V>' to match overridden member 'M<T>()'
                                diagnostics.Add(ErrorCode.ERR_CantChangeReturnTypeOnOverride, overridingMemberLocation, overridingMember, overriddenMember, returnType);
                            }
                            else if (overriddenMethod.IsRuntimeFinalizer())
                            {
                                diagnostics.Add(ErrorCode.ERR_OverrideFinalizeDeprecated, overridingMemberLocation);
                            }
                        }

                        // NOTE: this error may be redundant (if an error has already been reported
                        // for the return type or parameter type in question), but the scenario is
                        // too rare to justify complicated checks.
                        DiagnosticInfo useSiteDiagnostic = overriddenMember.GetUseSiteDiagnostic();
                        if (useSiteDiagnostic != null)
                        {
                            suppressAccessors = ReportUseSiteDiagnostic(useSiteDiagnostic, diagnostics, overridingMember.Locations[0]);
                        }
                    }
                }
            }

            // From: SymbolPreparer.cpp
            // DevDiv Bugs 115384: Both out and ref parameters are implemented as references. In addition, out parameters are 
            // decorated with OutAttribute. In CLR when a signature is looked up in virtual dispatch, CLR does not distinguish
            // between these to parameter types. The choice is the last method in the vtable. Therefore we check and warn if 
            // there would potentially be a mismatch in CLRs and C#s choice of the overridden method. Unfortunately we have no 
            // way of communicating to CLR which method is the overridden one. We only run into this problem when the 
            // parameters are generic.
            var runtimeOverriddenMembers = overriddenOrHiddenMembers.RuntimeOverriddenMembers;
            Debug.Assert(!runtimeOverriddenMembers.IsDefault);
            if (runtimeOverriddenMembers.Length > 1 && overridingMember.Kind == SymbolKind.Method) // The runtime doesn't define overriding for properties or events.
            {
                // CONSIDER: Dev10 doesn't seem to report this warning for indexers.
                var ambiguousMethod = runtimeOverriddenMembers[0];
                diagnostics.Add(ErrorCode.WRN_MultipleRuntimeOverrideMatches, ambiguousMethod.Locations[0], ambiguousMethod, overridingMember);
                suppressAccessors = true;
            }
        }