未验证 提交 72a08087 编写于 作者: A AlekseyTs 提交者: GitHub

Support protected access for declarations in interfaces (#34012)

上级 92de39b0
......@@ -31,17 +31,17 @@ class Test1 : I1
- Supplying an implementation along with declaration of an event and recognizing that implementation as default implementation for the event when a type implements the interface.
- Using **partial**, **public**, **internal**, **private**, **static**, **virtual**, **sealed**, **abstract**, **extern** and **async** modifiers with interface methods.
- Using **partial**, **public**, **internal**, **private**, **protected**, **static**, **virtual**, **sealed**, **abstract**, **extern** and **async** modifiers with interface methods.
- Using **public**, **internal**, **private**, **static**, **virtual**, **sealed**, **abstract** and **extern** modifiers with interface properties.
- Using **public**, **internal**, **private**, **protected**, **static**, **virtual**, **sealed**, **abstract** and **extern** modifiers with interface properties.
- Using **public**, **internal**, **private**, **virtual**, **sealed**, **abstract** and **extern** modifiers with interface indexers.
- Using **public**, **internal**, **private**, **protected**, **virtual**, **sealed**, **abstract** and **extern** modifiers with interface indexers.
- Using **internal** and **private** modifiers with interface property/indexer accessors.
- Using **internal**, **private**, **protected** modifiers with interface property/indexer accessors.
- Using **public**, **internal**, **private**, **static**, **virtual**, **sealed**, **abstract** and **extern** modifiers with interface events.
- Using **public**, **internal**, **private**, **protected**, **static**, **virtual**, **sealed**, **abstract** and **extern** modifiers with interface events.
- Declaring types within interfaces. **Protected** and **protected internal** accessibility is not supported.
- Declaring types within interfaces.
- Implementing interface methods in derived interfaces by using explicit implementation syntax, accessibility matches accessibility of the implemented member, allowed modifiers: **extern** and **async**.
......@@ -49,7 +49,7 @@ class Test1 : I1
- Implementing interface events in derived interfaces by using explicit implementation syntax, accessibility matches accessibility of the implemented member, no allowed modifiers.
- Declaring static fields, auto-properties and field-like events (**protected** modifier is not allowed).
- Declaring static fields, auto-properties and field-like events.
- Declaring operators ```+ - ! ~ ++ -- true false * / % & | ^ << >> > < >= <=``` in interfaces.
......
......@@ -1002,6 +1002,8 @@ private bool CheckPropertyValueKind(SyntaxNode node, BoundExpression expr, BindV
{
return false;
}
CheckRuntimeSupportForSymbolAccess(node, receiver, setMethod, diagnostics);
}
}
......@@ -1043,6 +1045,8 @@ private bool CheckPropertyValueKind(SyntaxNode node, BoundExpression expr, BindV
{
return false;
}
CheckRuntimeSupportForSymbolAccess(node, receiver, getMethod, diagnostics);
}
}
......
......@@ -321,11 +321,6 @@ private BoundExpression CreateMethodGroupConversion(SyntaxNode syntax, BoundExpr
MethodSymbol method = conversion.Method;
bool hasErrors = false;
if (IsBadBaseAccess(syntax, receiverOpt, method, diagnostics))
{
hasErrors = true;
}
NamedTypeSymbol delegateType = (NamedTypeSymbol)destination;
if (MethodGroupConversionHasErrors(syntax, conversion, group.ReceiverOpt, conversion.IsExtensionMethod, delegateType, diagnostics))
{
......@@ -514,7 +509,10 @@ private BoundMethodGroup FixMethodGroupWithTypeOrValue(BoundMethodGroup group, C
/// </returns>
private bool MemberGroupFinalValidation(BoundExpression receiverOpt, MethodSymbol methodSymbol, SyntaxNode node, DiagnosticBag diagnostics, bool invokedAsExtensionMethod)
{
CheckRuntimeSupportForSymbolAccess(node, receiverOpt, methodSymbol, diagnostics);
if (!IsBadBaseAccess(node, receiverOpt, methodSymbol, diagnostics))
{
CheckRuntimeSupportForSymbolAccess(node, receiverOpt, methodSymbol, diagnostics);
}
if (MemberGroupFinalValidationAccessibilityChecks(receiverOpt, methodSymbol, node, diagnostics, invokedAsExtensionMethod))
{
......
......@@ -6492,6 +6492,8 @@ private static void CombineExtensionMethodArguments(BoundExpression receiver, An
WarnOnAccessOfOffDefault(node, receiver, diagnostics);
}
CheckRuntimeSupportForSymbolAccess(node, receiver, fieldSymbol, diagnostics);
TypeSymbol fieldType = fieldSymbol.GetFieldType(this.FieldsBeingBound).TypeSymbol;
BoundExpression expr = new BoundFieldAccess(node, receiver, fieldSymbol, constantValueOpt, resultKind, fieldType, hasErrors: (hasErrors || hasError));
......@@ -6562,18 +6564,30 @@ private bool InEnumMemberInitializer()
WarnOnAccessOfOffDefault(node, receiver, diagnostics);
}
CheckRuntimeSupportForSymbolAccess(node, receiver, propertySymbol, diagnostics);
return new BoundPropertyAccess(node, receiver, propertySymbol, lookupResult, propertySymbol.Type.TypeSymbol, hasErrors: (hasErrors || hasError));
}
private void CheckRuntimeSupportForSymbolAccess(SyntaxNode node, BoundExpression receiverOpt, Symbol symbol, DiagnosticBag diagnostics)
{
if (!symbol.IsStatic && symbol.ContainingType.IsInterface &&
(!symbol.IsImplementableInterfaceMember() || (receiverOpt as BoundBaseReference)?.ExplicitBaseReferenceOpt?.Type.IsInterfaceType() == true) &&
!Compilation.Assembly.RuntimeSupportsDefaultInterfaceImplementation)
if (symbol.ContainingType?.IsInterface == true && !Compilation.Assembly.RuntimeSupportsDefaultInterfaceImplementation && Compilation.SourceModule != symbol.ContainingModule)
{
Error(diagnostics, ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, node);
if (!symbol.IsStatic && !(symbol is TypeSymbol) &&
(!symbol.IsImplementableInterfaceMember() || (receiverOpt as BoundBaseReference)?.ExplicitBaseReferenceOpt?.Type.IsInterfaceType() == true))
{
Error(diagnostics, ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, node);
}
else
{
switch (symbol.DeclaredAccessibility)
{
case Accessibility.Protected:
case Accessibility.ProtectedOrInternal:
case Accessibility.ProtectedAndInternal:
Error(diagnostics, ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, node);
break;
}
}
}
}
......@@ -6596,8 +6610,6 @@ private void CheckRuntimeSupportForSymbolAccess(SyntaxNode node, BoundExpression
WarnOnAccessOfOffDefault(node, receiver, diagnostics);
}
CheckRuntimeSupportForSymbolAccess(node, receiver, eventSymbol, diagnostics);
return new BoundEventAccess(node, receiver, eventSymbol, isUsableAsField, lookupResult, eventSymbol.Type.TypeSymbol, hasErrors: (hasErrors || hasError));
}
......@@ -7389,8 +7401,6 @@ private BoundExpression BindIndexedPropertyAccess(SyntaxNode syntax, BoundExpres
diagnostics);
}
CheckRuntimeSupportForSymbolAccess(syntax, receiver, property, diagnostics);
propertyAccess = new BoundIndexerAccess(
syntax,
receiver,
......
......@@ -1114,11 +1114,6 @@ private void CheckRestrictedTypeReceiver(BoundExpression expression, Compilation
bool isDelegateCall = (object)delegateTypeOpt != null;
if (!isDelegateCall)
{
if (IsBadBaseAccess(node, receiver, method, diagnostics))
{
gotError = true;
}
if (!method.IsStatic)
{
WarnOnAccessOfOffDefault(node.Kind() == SyntaxKind.InvocationExpression ?
......
......@@ -659,7 +659,7 @@ internal virtual bool SupportsExtensionMethods
// Does a member lookup in a single type, without considering inheritance.
protected static void LookupMembersWithoutInheritance(LookupResult result, TypeSymbol type, string name, int arity,
LookupOptions options, Binder originalBinder, TypeSymbol accessThroughType, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics, ConsList<TypeSymbol> basesBeingResolved = null)
LookupOptions options, Binder originalBinder, TypeSymbol accessThroughType, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics, ConsList<TypeSymbol> basesBeingResolved)
{
var members = GetCandidateMembers(type, name, options, originalBinder);
......@@ -799,7 +799,7 @@ internal virtual bool SupportsExtensionMethods
{
if (ShouldAddWinRTMembersForInterface(iface, idictSymbol, iroDictSymbol, iListSymbol, iCollectionSymbol, inccSymbol, inpcSymbol))
{
LookupMembersWithoutInheritance(tmp, iface, name, arity, options, originalBinder, iface, diagnose, ref useSiteDiagnostics);
LookupMembersWithoutInheritance(tmp, iface, name, arity, options, originalBinder, iface, diagnose, ref useSiteDiagnostics, basesBeingResolved: null);
// only add viable members
if (tmp.IsMultiViable)
{
......@@ -897,6 +897,7 @@ private static Symbol GetNearestOtherSymbol(ConsList<TypeSymbol> list, TypeSymbo
NamedTypeSymbol type,
string name,
int arity,
ConsList<TypeSymbol> basesBeingResolved,
LookupOptions options,
Binder originalBinder,
TypeSymbol accessThroughType,
......@@ -906,10 +907,10 @@ private static Symbol GetNearestOtherSymbol(ConsList<TypeSymbol> list, TypeSymbo
Debug.Assert((object)type != null);
Debug.Assert(type.IsInterface);
LookupMembersWithoutInheritance(current, type, name, arity, options, originalBinder, accessThroughType, diagnose, ref useSiteDiagnostics);
LookupMembersWithoutInheritance(current, type, name, arity, options, originalBinder, accessThroughType, diagnose, ref useSiteDiagnostics, basesBeingResolved);
if ((options & (LookupOptions.NamespaceAliasesOnly | LookupOptions.NamespacesOrTypesOnly)) == 0 && !originalBinder.InCrefButNotParameterOrReturnType)
{
LookupMembersInInterfacesWithoutInheritance(current, type.AllInterfacesWithDefinitionUseSiteDiagnostics(ref useSiteDiagnostics), name, arity, options, originalBinder, accessThroughType, diagnose, ref useSiteDiagnostics);
LookupMembersInInterfacesWithoutInheritance(current, type.AllInterfacesWithDefinitionUseSiteDiagnostics(ref useSiteDiagnostics), name, arity, basesBeingResolved, options, originalBinder, accessThroughType, diagnose, ref useSiteDiagnostics);
}
}
......@@ -918,6 +919,7 @@ private static Symbol GetNearestOtherSymbol(ConsList<TypeSymbol> list, TypeSymbo
ImmutableArray<NamedTypeSymbol> interfaces,
string name,
int arity,
ConsList<TypeSymbol> basesBeingResolved,
LookupOptions options,
Binder originalBinder,
TypeSymbol accessThroughType,
......@@ -929,7 +931,7 @@ private static Symbol GetNearestOtherSymbol(ConsList<TypeSymbol> list, TypeSymbo
var tmp = LookupResult.GetInstance();
foreach (TypeSymbol baseInterface in interfaces)
{
LookupMembersWithoutInheritance(tmp, baseInterface, name, arity, options, originalBinder, accessThroughType, diagnose, ref useSiteDiagnostics);
LookupMembersWithoutInheritance(tmp, baseInterface, name, arity, options, originalBinder, accessThroughType, diagnose, ref useSiteDiagnostics, basesBeingResolved);
MergeHidingLookupResults(current, tmp, ref useSiteDiagnostics);
tmp.Clear();
}
......@@ -943,7 +945,7 @@ private void LookupMembersInInterface(LookupResult current, NamedTypeSymbol type
Debug.Assert((object)type != null);
Debug.Assert(type.IsInterface);
LookupMembersInInterfaceOnly(current, type, name, arity, options, originalBinder, type, diagnose, ref useSiteDiagnostics);
LookupMembersInInterfaceOnly(current, type, name, arity, basesBeingResolved, options, originalBinder, type, diagnose, ref useSiteDiagnostics);
if (!originalBinder.InCrefButNotParameterOrReturnType && (options & LookupOptions.NoObjectMembersOnInterfaces) == 0)
{
......@@ -972,7 +974,7 @@ private void LookupMembersInTypeParameter(LookupResult current, TypeParameterSym
// effective interfaces. AllEffectiveInterfaces is used rather than AllInterfaces
// to avoid including explicit implementations from the effective base class.
LookupMembersInClass(current, typeParameter.EffectiveBaseClass(ref useSiteDiagnostics), name, arity, basesBeingResolved, options, originalBinder, diagnose, ref useSiteDiagnostics);
LookupMembersInInterfacesWithoutInheritance(current, typeParameter.AllEffectiveInterfacesWithDefinitionUseSiteDiagnostics(ref useSiteDiagnostics), name, arity, options, originalBinder, typeParameter, diagnose, ref useSiteDiagnostics);
LookupMembersInInterfacesWithoutInheritance(current, typeParameter.AllEffectiveInterfacesWithDefinitionUseSiteDiagnostics(ref useSiteDiagnostics), name, arity, basesBeingResolved: null, options, originalBinder, typeParameter, diagnose, ref useSiteDiagnostics);
}
private static bool IsDerivedType(NamedTypeSymbol baseType, NamedTypeSymbol derivedType, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
......
......@@ -272,6 +272,10 @@ private BoundExpression BindEventAssignment(AssignmentExpressionSyntax node, Bou
{
hasErrors = true;
}
else
{
CheckRuntimeSupportForSymbolAccess(node, receiverOpt, method, diagnostics);
}
if (eventSymbol.IsWindowsRuntimeEvent)
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.CodeAnalysis.CSharp.Symbols;
......@@ -396,7 +397,7 @@ private static bool IsNamedTypeAccessible(NamedTypeSymbol type, Symbol within, r
{
Debug.Assert(current.IsDefinition);
if (current.InheritsFromIgnoringConstruction(originalContainingType, compilation, ref useSiteDiagnostics, basesBeingResolved))
if (current.InheritsFromOrImplementsIgnoringConstruction(originalContainingType, compilation, ref useSiteDiagnostics, basesBeingResolved))
{
// NOTE(cyrusn): We're continually walking up the 'throughType's inheritance
// chain. We could compute it up front and cache it in a set. However, we
......@@ -405,7 +406,7 @@ private static bool IsNamedTypeAccessible(NamedTypeSymbol type, Symbol within, r
// slower to create and check inside the set versus just walking the
// inheritance chain.
if ((object)originalThroughTypeOpt == null ||
originalThroughTypeOpt.InheritsFromIgnoringConstruction(current, compilation, ref useSiteDiagnostics))
originalThroughTypeOpt.InheritsFromOrImplementsIgnoringConstruction(current, compilation, ref useSiteDiagnostics))
{
return true;
}
......@@ -470,10 +471,10 @@ private static bool IsNamedTypeAccessible(NamedTypeSymbol type, Symbol within, r
}
/// <summary>
/// Determine if "type" inherits from "baseType", ignoring constructed types, and dealing
/// Determine if "type" inherits from or implements "baseType", ignoring constructed types, and dealing
/// only with original types.
/// </summary>
private static bool InheritsFromIgnoringConstruction(
private static bool InheritsFromOrImplementsIgnoringConstruction(
this TypeSymbol type,
NamedTypeSymbol baseType,
CSharpCompilation compilation,
......@@ -483,18 +484,33 @@ private static bool IsNamedTypeAccessible(NamedTypeSymbol type, Symbol within, r
Debug.Assert(type.IsDefinition);
Debug.Assert(baseType.IsDefinition);
PooledHashSet<NamedTypeSymbol> interfacesLookedAt = null;
ArrayBuilder<NamedTypeSymbol> baseInterfaces = null;
bool baseTypeIsInterface = baseType.IsInterface;
if (baseTypeIsInterface)
{
interfacesLookedAt = PooledHashSet<NamedTypeSymbol>.GetInstance();
baseInterfaces = ArrayBuilder<NamedTypeSymbol>.GetInstance();
}
PooledHashSet<NamedTypeSymbol> visited = null;
var current = type;
bool result = false;
while ((object)current != null)
{
if (current.Equals(baseType))
if (baseTypeIsInterface == current.IsInterfaceType() && current.Equals(baseType))
{
result = true;
break;
}
if (baseTypeIsInterface)
{
getBaseInterfaces(current, baseInterfaces, interfacesLookedAt, basesBeingResolved);
}
// NOTE(cyrusn): The base type of an 'original' type may not be 'original'. i.e.
// "class Goo : IBar<int>". We must map it back to the 'original' when as we walk up
// the base type hierarchy.
......@@ -511,7 +527,75 @@ private static bool IsNamedTypeAccessible(NamedTypeSymbol type, Symbol within, r
}
visited?.Free();
if (!result && baseTypeIsInterface)
{
Debug.Assert(!result);
while (baseInterfaces.Count != 0)
{
NamedTypeSymbol currentBase = baseInterfaces.Pop();
if (!currentBase.IsInterface)
{
continue;
}
if (currentBase.Equals(baseType))
{
result = true;
break;
}
getBaseInterfaces(currentBase, baseInterfaces, interfacesLookedAt, basesBeingResolved);
}
if (!result)
{
foreach (var candidate in interfacesLookedAt)
{
candidate.AddUseSiteDiagnostics(ref useSiteDiagnostics);
}
}
}
interfacesLookedAt?.Free();
baseInterfaces?.Free();
return result;
static void getBaseInterfaces(TypeSymbol derived, ArrayBuilder<NamedTypeSymbol> baseInterfaces, PooledHashSet<NamedTypeSymbol> interfacesLookedAt, ConsList<TypeSymbol> basesBeingResolved)
{
if (basesBeingResolved != null && basesBeingResolved.ContainsReference(derived))
{
return;
}
ImmutableArray<NamedTypeSymbol> declaredInterfaces;
switch (derived)
{
case TypeParameterSymbol typeParameter:
declaredInterfaces = typeParameter.AllEffectiveInterfacesNoUseSiteDiagnostics;
break;
case NamedTypeSymbol namedType:
declaredInterfaces = namedType.GetDeclaredInterfaces(basesBeingResolved);
break;
default:
declaredInterfaces = derived.InterfacesNoUseSiteDiagnostics(basesBeingResolved);
break;
}
foreach (var @interface in declaredInterfaces)
{
NamedTypeSymbol definition = @interface.OriginalDefinition;
if (interfacesLookedAt.Add(definition))
{
baseInterfaces.Add(definition);
}
}
}
}
/// <summary>
......
......@@ -9294,6 +9294,15 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to Target runtime doesn&apos;t support &apos;protected&apos;, &apos;protected internal&apos;, or &apos;private protected&apos; accessibility for a member of an interface..
/// </summary>
internal static string ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember {
get {
return ResourceManager.GetString("ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The type &apos;{1}&apos; exists in both &apos;{0}&apos; and &apos;{2}&apos;.
/// </summary>
......
......@@ -5811,4 +5811,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_NotBaseOrImplementedInterface" xml:space="preserve">
<value>'{0}' is not base type or interface of {1}.</value>
</data>
<data name="ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember" xml:space="preserve">
<value>Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</value>
</data>
</root>
\ No newline at end of file
......@@ -1699,7 +1699,7 @@ internal enum ErrorCode
// This PR can be used to find the relevant code and test files: https://github.com/dotnet/roslyn/pull/18045.
ERR_LanguageVersionDoesNotSupportDefaultInterfaceImplementationForMember = 8706,
// Available 8707,
ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember = 8707,
ERR_NotBaseOrImplementedInterface = 8708,
#endregion diagnostics introduced for C# 8.0
......
......@@ -282,7 +282,7 @@ public static string GetMemberNameWithoutInterfaceName(string fullName)
{
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
if (!AccessCheck.IsSymbolAccessible(implementedMember, implementingMember.ContainingType, ref useSiteDiagnostics, throughTypeOpt: implementedMember.ContainingType))
if (!AccessCheck.IsSymbolAccessible(implementedMember, implementingMember.ContainingType, ref useSiteDiagnostics, throughTypeOpt: null))
{
diagnostics.Add(ErrorCode.ERR_BadAccess, memberLocation, implementedMember);
}
......@@ -306,7 +306,7 @@ public static string GetMemberNameWithoutInterfaceName(string fullName)
void checkAccessorIsAccessibleIfImplementable(MethodSymbol accessor)
{
if (accessor.IsImplementable() &&
!AccessCheck.IsSymbolAccessible(accessor, implementingMember.ContainingType, ref useSiteDiagnostics, throughTypeOpt: accessor.ContainingType))
!AccessCheck.IsSymbolAccessible(accessor, implementingMember.ContainingType, ref useSiteDiagnostics, throughTypeOpt: null))
{
diagnostics.Add(ErrorCode.ERR_BadAccess, memberLocation, accessor);
}
......
......@@ -117,8 +117,6 @@ private static void ReportPartialError(Location errorLocation, DiagnosticBag dia
requiredVersionArgument);
}
}
// PROTOTYPE(DefaultInterfaceImplementation): Should we also check runtime support for some of the modifiers?
}
}
......@@ -308,7 +306,7 @@ private static DeclarationModifiers ToDeclarationModifier(SyntaxKind kind)
}
}
internal static CSDiagnosticInfo CheckAccessibility(DeclarationModifiers modifiers)
internal static CSDiagnosticInfo CheckAccessibility(DeclarationModifiers modifiers, Symbol symbol)
{
if (!IsValidAccessibility(modifiers))
{
......@@ -316,6 +314,22 @@ internal static CSDiagnosticInfo CheckAccessibility(DeclarationModifiers modifie
return new CSDiagnosticInfo(ErrorCode.ERR_BadMemberProtection);
}
if (symbol.Kind != SymbolKind.Method || (modifiers & DeclarationModifiers.Partial) == 0)
{
switch (modifiers & DeclarationModifiers.AccessibilityMask)
{
case DeclarationModifiers.Protected:
case DeclarationModifiers.ProtectedInternal:
case DeclarationModifiers.PrivateProtected:
if (symbol.ContainingType?.IsInterface == true && !symbol.ContainingAssembly.RuntimeSupportsDefaultInterfaceImplementation)
{
return new CSDiagnosticInfo(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember);
}
break;
}
}
return null;
}
......
......@@ -64,7 +64,7 @@ internal sealed class SourceConstructorSymbol : SourceMemberMethodSymbol
CheckFeatureAvailabilityAndRuntimeSupport(syntax, location, hasBody, diagnostics);
}
var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers);
var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers, this);
if (info != null)
{
diagnostics.Add(info, location);
......
......@@ -406,7 +406,7 @@ internal DeclarationModifiers Modifiers
private void CheckAccessibility(Location location, DiagnosticBag diagnostics)
{
var info = ModifierUtils.CheckAccessibility(_modifiers);
var info = ModifierUtils.CheckAccessibility(_modifiers, this);
if (info != null)
{
diagnostics.Add(new CSDiagnostic(info, location));
......@@ -429,29 +429,26 @@ private void CheckAccessibility(Location location, DiagnosticBag diagnostics)
DeclarationModifiers.Sealed |
DeclarationModifiers.Abstract |
DeclarationModifiers.Static |
DeclarationModifiers.Virtual;
DeclarationModifiers.Virtual |
DeclarationModifiers.AccessibilityMask;
if (!isInterface)
{
allowedModifiers |=
DeclarationModifiers.AccessibilityMask |
DeclarationModifiers.Override;
allowedModifiers |= DeclarationModifiers.Override;
}
else
{
const DeclarationModifiers allowedAccess = (DeclarationModifiers.AccessibilityMask & ~(DeclarationModifiers.Protected | DeclarationModifiers.ProtectedInternal));
// This is needed to make sure we can detect 'public' modifier specified explicitly and
// check it against language version below.
defaultAccess = DeclarationModifiers.None;
allowedModifiers |= allowedAccess | DeclarationModifiers.Extern;
allowedModifiers |= DeclarationModifiers.Extern;
defaultInterfaceImplementationModifiers |= DeclarationModifiers.Sealed |
DeclarationModifiers.Abstract |
DeclarationModifiers.Static |
DeclarationModifiers.Virtual |
DeclarationModifiers.Extern |
allowedAccess;
DeclarationModifiers.AccessibilityMask;
}
}
......
......@@ -43,7 +43,7 @@ internal bool IsNew
protected void CheckAccessibility(DiagnosticBag diagnostics)
{
var info = ModifierUtils.CheckAccessibility(Modifiers);
var info = ModifierUtils.CheckAccessibility(Modifiers, this);
if (info != null)
{
diagnostics.Add(new CSDiagnostic(info, this.ErrorLocation));
......
......@@ -253,7 +253,6 @@ private DeclarationModifiers MakeModifiers(TypeKind typeKind, DiagnosticBag diag
if (((NamedTypeSymbol)containingSymbol).IsInterface)
{
defaultAccess = DeclarationModifiers.Public;
allowedModifiers &= ~(DeclarationModifiers.Protected | DeclarationModifiers.ProtectedInternal);
}
else
{
......@@ -350,7 +349,7 @@ private DeclarationModifiers MakeModifiers(TypeKind typeKind, DiagnosticBag diag
// It is an error for the same modifier to appear multiple times.
if (!modifierErrors)
{
var info = ModifierUtils.CheckAccessibility(mods);
var info = ModifierUtils.CheckAccessibility(mods, this);
if (info != null)
{
diagnostics.Add(info, self.Locations[0]);
......
......@@ -146,11 +146,6 @@ internal static DeclarationModifiers MakeModifiers(NamedTypeSymbol containingTyp
DeclarationModifiers.Unsafe |
DeclarationModifiers.Abstract; // filtered out later
if (containingType.IsInterface)
{
allowedModifiers &= ~(DeclarationModifiers.Protected | DeclarationModifiers.ProtectedInternal);
}
var errorLocation = new SourceLocation(firstIdentifier);
DeclarationModifiers result = ModifierUtils.MakeAndCheckNontypeMemberModifiers(
modifiers, defaultAccess, allowedModifiers, errorLocation, diagnostics, out modifierErrors);
......
......@@ -122,7 +122,7 @@ internal sealed class SourceOrdinaryMethodSymbol : SourceMemberMethodSymbol
CheckModifiersForBody(syntax, location, diagnostics);
}
var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers);
var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers, this);
if (info != null)
{
diagnostics.Add(info, location);
......@@ -787,23 +787,19 @@ private DeclarationModifiers MakeModifiers(SyntaxTokenList modifiers, MethodKind
DeclarationModifiers.Sealed |
DeclarationModifiers.Abstract |
DeclarationModifiers.Static |
DeclarationModifiers.Virtual;
DeclarationModifiers.Virtual |
DeclarationModifiers.AccessibilityMask;
if (!isInterface)
{
allowedModifiers |=
DeclarationModifiers.AccessibilityMask |
DeclarationModifiers.Override;
allowedModifiers |= DeclarationModifiers.Override;
}
else
{
const DeclarationModifiers allowedAccess = (DeclarationModifiers.AccessibilityMask & ~(DeclarationModifiers.Protected | DeclarationModifiers.ProtectedInternal));
// This is needed to make sure we can detect 'public' modifier specified explicitly and
// check it against language version below.
defaultAccess = DeclarationModifiers.None;
allowedModifiers |= allowedAccess;
defaultInterfaceImplementationModifiers |= DeclarationModifiers.Sealed |
DeclarationModifiers.Abstract |
DeclarationModifiers.Static |
......@@ -811,7 +807,7 @@ private DeclarationModifiers MakeModifiers(SyntaxTokenList modifiers, MethodKind
DeclarationModifiers.Extern |
DeclarationModifiers.Async |
DeclarationModifiers.Partial |
allowedAccess;
DeclarationModifiers.AccessibilityMask;
}
}
......
......@@ -165,7 +165,7 @@ internal override bool IsExpressionBodied
CheckFeatureAvailabilityAndRuntimeSupport(syntax, location, hasBody: true, diagnostics: diagnostics);
CheckModifiersForBody(syntax, location, diagnostics);
var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers);
var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers, this);
if (info != null)
{
diagnostics.Add(info, location);
......@@ -235,7 +235,7 @@ internal override bool IsExpressionBodied
CheckModifiersForBody(syntax, location, diagnostics);
}
var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers);
var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers, this);
if (info != null)
{
diagnostics.Add(info, location);
......@@ -434,9 +434,7 @@ internal Accessibility LocalAccessibility
if (this.ContainingType.IsInterface && !isExplicitInterfaceImplementation)
{
const DeclarationModifiers disallow = DeclarationModifiers.Protected | DeclarationModifiers.ProtectedInternal;
allowedModifiers &= ~disallow;
defaultInterfaceImplementationModifiers = (DeclarationModifiers.AccessibilityMask & ~disallow);
defaultInterfaceImplementationModifiers = DeclarationModifiers.AccessibilityMask;
}
var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(syntax.Modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);
......
......@@ -815,7 +815,7 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions,
private void CheckAccessibility(Location location, DiagnosticBag diagnostics)
{
var info = ModifierUtils.CheckAccessibility(_modifiers);
var info = ModifierUtils.CheckAccessibility(_modifiers, this);
if (info != null)
{
diagnostics.Add(new CSDiagnostic(info, location));
......@@ -838,7 +838,8 @@ private void CheckAccessibility(Location location, DiagnosticBag diagnostics)
allowedModifiers |= DeclarationModifiers.New |
DeclarationModifiers.Sealed |
DeclarationModifiers.Abstract |
DeclarationModifiers.Virtual;
DeclarationModifiers.Virtual |
DeclarationModifiers.AccessibilityMask;
if (!isIndexer)
{
......@@ -847,25 +848,20 @@ private void CheckAccessibility(Location location, DiagnosticBag diagnostics)
if (!isInterface)
{
allowedModifiers |=
DeclarationModifiers.AccessibilityMask |
DeclarationModifiers.Override;
allowedModifiers |= DeclarationModifiers.Override;
}
else
{
const DeclarationModifiers allowedAccess = (DeclarationModifiers.AccessibilityMask & ~(DeclarationModifiers.Protected | DeclarationModifiers.ProtectedInternal));
// This is needed to make sure we can detect 'public' modifier specified explicitly and
// check it against language version below.
defaultAccess = DeclarationModifiers.None;
allowedModifiers |= allowedAccess;
defaultInterfaceImplementationModifiers |= DeclarationModifiers.Sealed |
DeclarationModifiers.Abstract |
(isIndexer ? 0 : DeclarationModifiers.Static) |
DeclarationModifiers.Virtual |
DeclarationModifiers.Extern |
allowedAccess;
DeclarationModifiers.AccessibilityMask;
}
}
......
......@@ -93,7 +93,7 @@ internal abstract class SourceUserDefinedOperatorSymbolBase : SourceMemberMethod
// SPEC: It is an error for the same modifier to appear multiple times in an
// SPEC: operator declaration.
var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers);
var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers, this);
if (info != null)
{
diagnostics.Add(info, location);
......
......@@ -277,6 +277,11 @@
<target state="translated">Levá strana přiřazení odkazu musí být lokální proměnná nebo parametr odkazu.</target>
<note />
</trans-unit>
<trans-unit id="ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember">
<source>Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</source>
<target state="new">Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</target>
<note />
</trans-unit>
<trans-unit id="ERR_SingleElementPositionalPatternRequiresDisambiguation">
<source>A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'.</source>
<target state="translated">Vzor deconstruct s jedním elementem vyžaduje určitou další syntaxi pro zajištění jednoznačnosti. Doporučuje se přidat designátor discard „_“ za koncovou závorku „)“.</target>
......
......@@ -277,6 +277,11 @@
<target state="translated">Die linke Seite einer ref-Zuweisung muss ein lokaler Verweis oder ein Parameter sein.</target>
<note />
</trans-unit>
<trans-unit id="ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember">
<source>Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</source>
<target state="new">Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</target>
<note />
</trans-unit>
<trans-unit id="ERR_SingleElementPositionalPatternRequiresDisambiguation">
<source>A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'.</source>
<target state="translated">Ein aus einem Element bestehendes deconstruct-Muster erfordert zur Vermeidung einer Mehrdeutigkeit eine etwas andere Syntax. Es wird empfohlen, nach der schließenden Klammer ")" einen discard-Kennzeichner "_" hinzuzufügen.</target>
......
......@@ -277,6 +277,11 @@
<target state="translated">La parte izquierda de una asignación de referencias debe ser una referencia local o un parámetro.</target>
<note />
</trans-unit>
<trans-unit id="ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember">
<source>Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</source>
<target state="new">Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</target>
<note />
</trans-unit>
<trans-unit id="ERR_SingleElementPositionalPatternRequiresDisambiguation">
<source>A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'.</source>
<target state="translated">Un patrón de deconstrucción de un solo elemento requiere más sintaxis para la desambiguación. Se recomienda agregar un designador de descarte "_" después del paréntesis de cierre ")".</target>
......
......@@ -277,6 +277,11 @@
<target state="translated">La partie gauche d'une assignation par référence doit être une variable locale ou un paramètre ref.</target>
<note />
</trans-unit>
<trans-unit id="ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember">
<source>Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</source>
<target state="new">Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</target>
<note />
</trans-unit>
<trans-unit id="ERR_SingleElementPositionalPatternRequiresDisambiguation">
<source>A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'.</source>
<target state="translated">Un modèle de déconstruction d'un seul élément nécessite une autre syntaxe pour la désambiguïsation. Il est recommandé d'ajouter un désignateur d'abandon '_' après la parenthèse de fermeture ')'.</target>
......
......@@ -277,6 +277,11 @@
<target state="translated">La parte sinistra di un'assegnazione ref deve essere un parametro o una variabile locale ref.</target>
<note />
</trans-unit>
<trans-unit id="ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember">
<source>Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</source>
<target state="new">Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</target>
<note />
</trans-unit>
<trans-unit id="ERR_SingleElementPositionalPatternRequiresDisambiguation">
<source>A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'.</source>
<target state="translated">Per risolvere le ambiguità, è necessario usare una sintassi diversa per il criterio di decostruzione di singoli elementi. È consigliabile aggiungere un indicatore di rimozione '_' dopo la parentesi di chiusura ')'.</target>
......
......@@ -277,6 +277,11 @@
<target state="translated">ref 割り当ての左辺は、ref ローカルまたはパラメーターにする必要があります。</target>
<note />
</trans-unit>
<trans-unit id="ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember">
<source>Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</source>
<target state="new">Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</target>
<note />
</trans-unit>
<trans-unit id="ERR_SingleElementPositionalPatternRequiresDisambiguation">
<source>A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'.</source>
<target state="translated">単一要素の分解パターンには、あいまいさを排除するための他の構文が必要です。破棄指定子 '_' を閉じかっこ ')' の後に追加することをお勧めします。</target>
......
......@@ -277,6 +277,11 @@
<target state="translated">참조 할당의 왼쪽은 참조 로컬 또는 매개 변수여야 합니다.</target>
<note />
</trans-unit>
<trans-unit id="ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember">
<source>Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</source>
<target state="new">Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</target>
<note />
</trans-unit>
<trans-unit id="ERR_SingleElementPositionalPatternRequiresDisambiguation">
<source>A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'.</source>
<target state="translated">단일 요소 분해 패턴은 명확성을 위해 다른 구문이 필요합니다. 닫는 괄호 ')' 뒤에 무시 항목 지정자 '_'을 추가하는 것이 좋습니다.</target>
......
......@@ -277,6 +277,11 @@
<target state="translated">Lewa strona przypisania odwołania musi być odwołaniem lokalnym lub parametrem.</target>
<note />
</trans-unit>
<trans-unit id="ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember">
<source>Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</source>
<target state="new">Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</target>
<note />
</trans-unit>
<trans-unit id="ERR_SingleElementPositionalPatternRequiresDisambiguation">
<source>A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'.</source>
<target state="translated">Wzorzec dekonstrukcji z jednym elementem wymaga innej składni w celu ujednoznacznienia. Zaleca się dodanie oznacznika odrzucania „_” po nawiasie zamykającym „)”.</target>
......
......@@ -277,6 +277,11 @@
<target state="translated">O lado esquerdo da atribuição ref precisa ser um parâmetro ou local ref.</target>
<note />
</trans-unit>
<trans-unit id="ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember">
<source>Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</source>
<target state="new">Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</target>
<note />
</trans-unit>
<trans-unit id="ERR_SingleElementPositionalPatternRequiresDisambiguation">
<source>A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'.</source>
<target state="translated">Um padrão de desconstrução de elemento único requer alguma outra sintaxe para desambiguação. É recomendado adicionar um designador de descarte '_' após o parêntese de fechamento ')'.</target>
......
......@@ -277,6 +277,11 @@
<target state="translated">Левая часть выражения присваивания ссылки должна быть локальной ссылкой или параметром.</target>
<note />
</trans-unit>
<trans-unit id="ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember">
<source>Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</source>
<target state="new">Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</target>
<note />
</trans-unit>
<trans-unit id="ERR_SingleElementPositionalPatternRequiresDisambiguation">
<source>A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'.</source>
<target state="translated">Для шаблона деконструкции с одним элементом требуется другой синтаксис для устранения неоднозначности. Рекомендуется добавить знак отмены "_" после закрывающей скобки ")".</target>
......
......@@ -277,6 +277,11 @@
<target state="translated">ref atamasının sol tarafı, yerel ref veya parametresi olmalıdır.</target>
<note />
</trans-unit>
<trans-unit id="ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember">
<source>Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</source>
<target state="new">Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</target>
<note />
</trans-unit>
<trans-unit id="ERR_SingleElementPositionalPatternRequiresDisambiguation">
<source>A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'.</source>
<target state="translated">Tek öğeli bir ayrıştırma deseni, kesinleştirme için başka bir söz dizimi gerektirir. ')' kapanış parantezinden sonra '_' atma belirleyicisinin eklenmesi önerilir.</target>
......
......@@ -277,6 +277,11 @@
<target state="translated">ref 赋值左侧必须为 ref 本地函数或参数。</target>
<note />
</trans-unit>
<trans-unit id="ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember">
<source>Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</source>
<target state="new">Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</target>
<note />
</trans-unit>
<trans-unit id="ERR_SingleElementPositionalPatternRequiresDisambiguation">
<source>A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'.</source>
<target state="translated">单元素解构模式需要一些其他语法来消除歧义。建议在关闭 paren ")" 之后添加放弃指示符 "_"。</target>
......
......@@ -277,6 +277,11 @@
<target state="translated">參考指派的左側必須為參考本機或參數。</target>
<note />
</trans-unit>
<trans-unit id="ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember">
<source>Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</source>
<target state="new">Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.</target>
<note />
</trans-unit>
<trans-unit id="ERR_SingleElementPositionalPatternRequiresDisambiguation">
<source>A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'.</source>
<target state="translated">單一元素解構模式需要一些其他語法才能使其明確。建議在右括弧 ')' 後新增捨棄指示項 '_'。</target>
......
......@@ -411,14 +411,14 @@ public void ForbiddenAccessorProtection_02()
{
private protected int M();
}";
CreateCompilation(source, parseOptions: TestOptions.Regular7) // PROTOTYPE(DefaultInterfaceImplementation): Change to TestOptions.Regular7_2
CreateCompilation(source, parseOptions: TestOptions.Regular7_2)
.VerifyDiagnostics(
// (3,27): error CS8107: Feature 'private protected' is not available in C# 7.0. Please use language version 7.2 or greater.
// (3,27): error CS8503: The modifier 'private protected' is not valid for this item in C# 7.2. Please use language version 'preview' or greater.
// private protected int M();
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "M").WithArguments("private protected", "7.2").WithLocation(3, 27),
// (3,27): error CS8503: The modifier 'private protected' is not valid for this item in C# 7.0. Please use language version 'preview' or greater.
Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "M").WithArguments("private protected", "7.2", "preview").WithLocation(3, 27),
// (3,27): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface.
// private protected int M();
Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "M").WithArguments("private protected", "7.0", "preview").WithLocation(3, 27)
Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "M").WithLocation(3, 27)
);
}
......
......@@ -1905,8 +1905,8 @@ public override U Property
}";
CreateCompilation(source).VerifyDiagnostics(
Diagnostic(ErrorCode.ERR_AbstractBaseCall, "base.Method(a, b)").WithArguments("Base<A, B>.Method(A, B)"),
Diagnostic(ErrorCode.ERR_AbstractBaseCall, "base.Method(x, y)").WithArguments("Base3<U, V>.Method(U, V)"),
Diagnostic(ErrorCode.ERR_AbstractBaseCall, "base.Method").WithArguments("Base<A, B>.Method(A, B)"),
Diagnostic(ErrorCode.ERR_AbstractBaseCall, "base.Method").WithArguments("Base3<U, V>.Method(U, V)"),
Diagnostic(ErrorCode.ERR_AbstractBaseCall, "base.Property").WithArguments("Base3<U, V>.Property"));
}
......@@ -1979,7 +1979,7 @@ class Derived : Base2<long>
";
CreateCompilation(source).VerifyDiagnostics(
Diagnostic(ErrorCode.ERR_AbstractBaseCall, "base.Method(x)").WithArguments("A.Base2<long>.Method(long)"));
Diagnostic(ErrorCode.ERR_AbstractBaseCall, "base.Method").WithArguments("A.Base2<long>.Method(long)"));
}
[Fact]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册