private DeclarationModifiers MakeModifiers(SyntaxTokenList modifiers, MethodKind methodKind, Location location, DiagnosticBag diagnostics, out bool modifierErrors) { bool isInterface = this.ContainingType.IsInterface; var defaultAccess = isInterface ? DeclarationModifiers.Public : DeclarationModifiers.Private; // Check that the set of modifiers is allowed var allowedModifiers = DeclarationModifiers.Partial | DeclarationModifiers.Unsafe; if (methodKind != MethodKind.ExplicitInterfaceImplementation) { allowedModifiers |= DeclarationModifiers.New; if (!isInterface) { allowedModifiers |= DeclarationModifiers.AccessibilityMask | DeclarationModifiers.Sealed | DeclarationModifiers.Abstract | DeclarationModifiers.Static | DeclarationModifiers.Virtual | DeclarationModifiers.Override; } } if (!isInterface) { allowedModifiers |= DeclarationModifiers.Extern | DeclarationModifiers.Async; } var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors); this.CheckUnsafeModifier(mods, diagnostics); mods = AddImpliedModifiers(mods, isInterface, methodKind); return(mods); }
private static DeclarationModifiers AddImpliedModifiers( DeclarationModifiers mods, bool containingTypeIsInterface, MethodKind methodKind, bool hasBody ) { // Let's overwrite modifiers for interface and explicit interface implementation methods with what they are supposed to be. // Proper errors must have been reported by now. if (containingTypeIsInterface) { mods = ModifierUtils.AdjustModifiersForAnInterfaceMember( mods, hasBody, methodKind == MethodKind.ExplicitInterfaceImplementation ); } else if (methodKind == MethodKind.ExplicitInterfaceImplementation) { mods = (mods & ~DeclarationModifiers.AccessibilityMask) | DeclarationModifiers.Private; } return(mods); }
private DeclarationModifiers MakeModifiers(AccessorDeclarationSyntax syntax, bool isExplicitInterfaceImplementation, bool hasBody, Location location, DiagnosticBag diagnostics, out bool modifierErrors) { // No default accessibility. If unset, accessibility // will be inherited from the property. const DeclarationModifiers defaultAccess = DeclarationModifiers.None; // Check that the set of modifiers is allowed var allowedModifiers = isExplicitInterfaceImplementation ? DeclarationModifiers.None : DeclarationModifiers.AccessibilityMask; var defaultInterfaceImplementationModifiers = DeclarationModifiers.None; if (this.ContainingType.IsInterface && !isExplicitInterfaceImplementation) { defaultInterfaceImplementationModifiers = DeclarationModifiers.AccessibilityMask; } var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(syntax.Modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors); ModifierUtils.ReportDefaultInterfaceImplementationModifiers(hasBody, mods, defaultInterfaceImplementationModifiers, location, diagnostics); return(mods); }
private DeclarationModifiers MakeModifiers(AccessorDeclarationSyntax syntax, Location location, DiagnosticBag diagnostics, out bool modifierErrors) { // No default accessibility. If unset, accessibility // will be inherited from the property. const DeclarationModifiers defaultAccess = DeclarationModifiers.None; // Check that the set of modifiers is allowed const DeclarationModifiers allowedModifiers = DeclarationModifiers.AccessibilityMask; var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(syntax.Modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors); // For interface, check there are no accessibility modifiers. // (This check is handled outside of MakeAndCheckModifiers // since a distinct error message is reported for interfaces.) if (this.ContainingType.IsInterface) { if ((mods & DeclarationModifiers.AccessibilityMask) != 0) { diagnostics.Add(ErrorCode.ERR_PropertyAccessModInInterface, location, this); mods = (mods & ~DeclarationModifiers.AccessibilityMask); } } return(mods); }
private DeclarationModifiers MakeModifiers(SyntaxTokenList modifiers, MethodKind methodKind, bool hasBody, Location location, DiagnosticBag diagnostics, out bool modifierErrors) { var defaultAccess = (methodKind == MethodKind.StaticConstructor) ? DeclarationModifiers.None : DeclarationModifiers.Private; // Check that the set of modifiers is allowed const DeclarationModifiers allowedModifiers = DeclarationModifiers.AccessibilityMask | DeclarationModifiers.Static | DeclarationModifiers.Extern | DeclarationModifiers.Unsafe; var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors); this.CheckUnsafeModifier(mods, diagnostics); if (methodKind == MethodKind.StaticConstructor) { if ((mods & DeclarationModifiers.AccessibilityMask) != 0) { diagnostics.Add(ErrorCode.ERR_StaticConstructorWithAccessModifiers, location, this); mods = mods & ~DeclarationModifiers.AccessibilityMask; modifierErrors = true; } mods |= DeclarationModifiers.Private; // we mark static constructors private in the symbol table if (this.ContainingType.IsInterface) { ModifierUtils.ReportDefaultInterfaceImplementationModifiers(hasBody, mods, DeclarationModifiers.Extern, location, diagnostics); } } return(mods); }
private DeclarationModifiers MakeModifiers(SyntaxTokenList modifiers, bool explicitInterfaceImplementation, bool isFieldLike, Location location, DiagnosticBag diagnostics, out bool modifierErrors) { bool isInterface = this.ContainingType.IsInterface; var defaultAccess = isInterface && !explicitInterfaceImplementation ? DeclarationModifiers.Public : DeclarationModifiers.Private; var defaultInterfaceImplementationModifiers = DeclarationModifiers.None; // Check that the set of modifiers is allowed var allowedModifiers = DeclarationModifiers.Unsafe; if (!explicitInterfaceImplementation) { allowedModifiers |= DeclarationModifiers.New | DeclarationModifiers.Sealed | DeclarationModifiers.Abstract | DeclarationModifiers.Static | DeclarationModifiers.Virtual | DeclarationModifiers.AccessibilityMask; if (!isInterface) { allowedModifiers |= DeclarationModifiers.Override; } else { // This is needed to make sure we can detect 'public' modifier specified explicitly and // check it against language version below. defaultAccess = DeclarationModifiers.None; allowedModifiers |= DeclarationModifiers.Extern; defaultInterfaceImplementationModifiers |= DeclarationModifiers.Sealed | DeclarationModifiers.Abstract | DeclarationModifiers.Static | DeclarationModifiers.Virtual | DeclarationModifiers.Extern | DeclarationModifiers.AccessibilityMask; } } else if (isInterface) { Debug.Assert(explicitInterfaceImplementation); allowedModifiers |= DeclarationModifiers.Abstract; } if (this.ContainingType.IsStructType()) { allowedModifiers |= DeclarationModifiers.ReadOnly; } if (!isInterface) { allowedModifiers |= DeclarationModifiers.Extern; } var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors); this.CheckUnsafeModifier(mods, diagnostics); ModifierUtils.ReportDefaultInterfaceImplementationModifiers(!isFieldLike, mods, defaultInterfaceImplementationModifiers, location, diagnostics); // Let's overwrite modifiers for interface events with what they are supposed to be. // Proper errors must have been reported by now. if (isInterface) { mods = ModifierUtils.AdjustModifiersForAnInterfaceMember(mods, !isFieldLike, explicitInterfaceImplementation); } return(mods); }
private SourcePropertyAccessorSymbol( NamedTypeSymbol containingType, string name, SourcePropertySymbol property, DeclarationModifiers propertyModifiers, ImmutableArray <MethodSymbol> explicitInterfaceImplementations, Location location, AccessorDeclarationSyntax syntax, MethodKind methodKind, bool isAutoPropertyAccessor, bool isExplicitInterfaceImplementation, DiagnosticBag diagnostics) : base(containingType, syntax.GetReference(), location) { _property = property; _explicitInterfaceImplementations = explicitInterfaceImplementations; _name = name; _isAutoPropertyAccessor = isAutoPropertyAccessor; Debug.Assert(!_property.IsExpressionBodied, "Cannot have accessors in expression bodied lightweight properties"); var hasBody = syntax.Body != null; var hasExpressionBody = syntax.ExpressionBody != null; _isExpressionBodied = !hasBody && hasExpressionBody; bool modifierErrors; var declarationModifiers = this.MakeModifiers(syntax, isExplicitInterfaceImplementation, hasBody || hasExpressionBody, location, diagnostics, out modifierErrors); // Include modifiers from the containing property. propertyModifiers &= ~DeclarationModifiers.AccessibilityMask; if ((declarationModifiers & DeclarationModifiers.Private) != 0) { // Private accessors cannot be virtual. propertyModifiers &= ~DeclarationModifiers.Virtual; } declarationModifiers |= propertyModifiers & ~DeclarationModifiers.Indexer; // ReturnsVoid property is overridden in this class so // returnsVoid argument to MakeFlags is ignored. this.MakeFlags(methodKind, declarationModifiers, returnsVoid: false, isExtensionMethod: false, isMetadataVirtualIgnoringModifiers: explicitInterfaceImplementations.Any()); CheckFeatureAvailabilityAndRuntimeSupport(syntax, location, hasBody || hasExpressionBody, diagnostics); if (hasBody || hasExpressionBody) { CheckModifiersForBody(syntax, location, diagnostics); } var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers, this, isExplicitInterfaceImplementation); if (info != null) { diagnostics.Add(info, location); } if (!modifierErrors) { this.CheckModifiers(location, hasBody || hasExpressionBody, isAutoPropertyAccessor, diagnostics); } if (this.IsOverride) { MethodSymbol overriddenMethod = this.OverriddenMethod; if ((object)overriddenMethod != null) { // If this accessor is overriding a method from metadata, it is possible that // the name of the overridden method doesn't follow the C# get_X/set_X pattern. // We should copy the name so that the runtime will recognize this as an override. _name = overriddenMethod.Name; } } CheckForBlockAndExpressionBody( syntax.Body, syntax.ExpressionBody, syntax, diagnostics); }
internal static DeclarationModifiers CheckModifiers( bool isForTypeDeclaration, bool isForInterfaceMember, DeclarationModifiers modifiers, DeclarationModifiers allowedModifiers, Location errorLocation, BindingDiagnosticBag diagnostics, SyntaxTokenList?modifierTokens, out bool modifierErrors) { Debug.Assert(!isForTypeDeclaration || !isForInterfaceMember); modifierErrors = false; DeclarationModifiers reportStaticNotVirtualForModifiers = DeclarationModifiers.None; if (isForTypeDeclaration) { Debug.Assert((allowedModifiers & (DeclarationModifiers.Override | DeclarationModifiers.Virtual)) == 0); } else if ((modifiers & allowedModifiers & DeclarationModifiers.Static) != 0) { if (isForInterfaceMember) { reportStaticNotVirtualForModifiers = allowedModifiers & DeclarationModifiers.Override; } else { reportStaticNotVirtualForModifiers = allowedModifiers & (DeclarationModifiers.Abstract | DeclarationModifiers.Override | DeclarationModifiers.Virtual); } allowedModifiers &= ~reportStaticNotVirtualForModifiers; } DeclarationModifiers errorModifiers = modifiers & ~allowedModifiers; DeclarationModifiers result = modifiers & allowedModifiers; while (errorModifiers != DeclarationModifiers.None) { DeclarationModifiers oneError = errorModifiers & ~(errorModifiers - 1); Debug.Assert(oneError != DeclarationModifiers.None); errorModifiers = errorModifiers & ~oneError; switch (oneError) { case DeclarationModifiers.Partial: // Provide a specialized error message in the case of partial. ReportPartialError(errorLocation, diagnostics, modifierTokens); break; case DeclarationModifiers.Abstract: case DeclarationModifiers.Override: case DeclarationModifiers.Virtual: if ((reportStaticNotVirtualForModifiers & oneError) == 0) { goto default; } diagnostics.Add(ErrorCode.ERR_StaticNotVirtual, errorLocation, ModifierUtils.ConvertSingleModifierToSyntaxText(oneError)); break; default: diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, ConvertSingleModifierToSyntaxText(oneError)); break; } modifierErrors = true; } modifierErrors |= checkFeature(DeclarationModifiers.PrivateProtected, MessageID.IDS_FeaturePrivateProtected) | checkFeature(DeclarationModifiers.Required, MessageID.IDS_FeatureRequiredMembers); if ((result & DeclarationModifiers.File) != 0) { modifierErrors |= !Binder.CheckFeatureAvailability(errorLocation.SourceTree, MessageID.IDS_FeatureFileTypes, diagnostics, errorLocation); } return(result); bool checkFeature(DeclarationModifiers modifier, MessageID featureID) => ((result & modifier) != 0) && !Binder.CheckFeatureAvailability(errorLocation.SourceTree, featureID, diagnostics, errorLocation); }
internal static DeclarationModifiers MakeModifiers(NamedTypeSymbol containingType, SyntaxToken firstIdentifier, SyntaxTokenList modifiers, bool isRefField, BindingDiagnosticBag diagnostics, out bool modifierErrors) { bool isInterface = containingType.IsInterface; DeclarationModifiers defaultAccess = isInterface ? DeclarationModifiers.Public : DeclarationModifiers.Private; DeclarationModifiers allowedModifiers = DeclarationModifiers.AccessibilityMask | DeclarationModifiers.Const | DeclarationModifiers.New | DeclarationModifiers.ReadOnly | DeclarationModifiers.Static | DeclarationModifiers.Volatile | DeclarationModifiers.Fixed | DeclarationModifiers.Unsafe | DeclarationModifiers.Abstract | DeclarationModifiers.Required; // Some of these are filtered out later, when illegal, for better error messages. var errorLocation = new SourceLocation(firstIdentifier); DeclarationModifiers result = ModifierUtils.MakeAndCheckNontypeMemberModifiers( isOrdinaryMethod: false, isForInterfaceMember: isInterface, modifiers, defaultAccess, allowedModifiers, errorLocation, diagnostics, out modifierErrors); if ((result & DeclarationModifiers.Abstract) != 0) { diagnostics.Add(ErrorCode.ERR_AbstractField, errorLocation); result &= ~DeclarationModifiers.Abstract; } if ((result & DeclarationModifiers.Fixed) != 0) { reportBadMemberFlagIfAny(result, DeclarationModifiers.Static, diagnostics, errorLocation); reportBadMemberFlagIfAny(result, DeclarationModifiers.ReadOnly, diagnostics, errorLocation); reportBadMemberFlagIfAny(result, DeclarationModifiers.Const, diagnostics, errorLocation); reportBadMemberFlagIfAny(result, DeclarationModifiers.Volatile, diagnostics, errorLocation); reportBadMemberFlagIfAny(result, DeclarationModifiers.Required, diagnostics, errorLocation); result &= ~(DeclarationModifiers.Static | DeclarationModifiers.ReadOnly | DeclarationModifiers.Const | DeclarationModifiers.Volatile | DeclarationModifiers.Required); Debug.Assert((result & ~(DeclarationModifiers.AccessibilityMask | DeclarationModifiers.Fixed | DeclarationModifiers.Unsafe | DeclarationModifiers.New)) == 0); } if ((result & DeclarationModifiers.Const) != 0) { if ((result & DeclarationModifiers.Static) != 0) { // The constant '{0}' cannot be marked static diagnostics.Add(ErrorCode.ERR_StaticConstant, errorLocation, firstIdentifier.ValueText); } reportBadMemberFlagIfAny(result, DeclarationModifiers.ReadOnly, diagnostics, errorLocation); reportBadMemberFlagIfAny(result, DeclarationModifiers.Volatile, diagnostics, errorLocation); reportBadMemberFlagIfAny(result, DeclarationModifiers.Unsafe, diagnostics, errorLocation); if (reportBadMemberFlagIfAny(result, DeclarationModifiers.Required, diagnostics, errorLocation)) { result &= ~DeclarationModifiers.Required; } result |= DeclarationModifiers.Static; // "constants are considered static members" } else { if ((result & DeclarationModifiers.Static) != 0 && (result & DeclarationModifiers.Required) != 0) { // The modifier 'required' is not valid for this item diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.RequiredKeyword)); result &= ~DeclarationModifiers.Required; } // NOTE: always cascading on a const, so suppress. // NOTE: we're being a bit sneaky here - we're using the containingType rather than this symbol // to determine whether or not unsafe is allowed. Since this symbol and the containing type are // in the same compilation, it won't make a difference. We do, however, have to pass the error // location explicitly. containingType.CheckUnsafeModifier(result, errorLocation, diagnostics); } if (isRefField) { reportBadMemberFlagIfAny(result, DeclarationModifiers.Static, diagnostics, errorLocation); reportBadMemberFlagIfAny(result, DeclarationModifiers.Const, diagnostics, errorLocation); reportBadMemberFlagIfAny(result, DeclarationModifiers.Volatile, diagnostics, errorLocation); } return(result);
internal static DeclarationModifiers MakeModifiers(NamedTypeSymbol containingType, SyntaxToken firstIdentifier, SyntaxTokenList modifiers, DiagnosticBag diagnostics, out bool modifierErrors) { DeclarationModifiers defaultAccess = (containingType.IsInterface) ? DeclarationModifiers.Public : DeclarationModifiers.Private; DeclarationModifiers allowedModifiers = DeclarationModifiers.AccessibilityMask | DeclarationModifiers.Const | DeclarationModifiers.New | DeclarationModifiers.ReadOnly | DeclarationModifiers.Static | DeclarationModifiers.Volatile | DeclarationModifiers.Fixed | DeclarationModifiers.Unsafe | DeclarationModifiers.Abstract; // filtered out later var errorLocation = new SourceLocation(firstIdentifier); DeclarationModifiers result = ModifierUtils.MakeAndCheckNontypeMemberModifiers( modifiers, defaultAccess, allowedModifiers, errorLocation, diagnostics, out modifierErrors); if ((result & DeclarationModifiers.Abstract) != 0) { diagnostics.Add(ErrorCode.ERR_AbstractField, errorLocation); result &= ~DeclarationModifiers.Abstract; } if ((result & DeclarationModifiers.Fixed) != 0) { if ((result & DeclarationModifiers.Static) != 0) { // The modifier 'static' is not valid for this item diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.StaticKeyword)); } if ((result & DeclarationModifiers.ReadOnly) != 0) { // The modifier 'readonly' is not valid for this item diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.ReadOnlyKeyword)); } if ((result & DeclarationModifiers.Const) != 0) { // The modifier 'const' is not valid for this item diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.ConstKeyword)); } if ((result & DeclarationModifiers.Volatile) != 0) { // The modifier 'volatile' is not valid for this item diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.VolatileKeyword)); } result &= ~(DeclarationModifiers.Static | DeclarationModifiers.ReadOnly | DeclarationModifiers.Const | DeclarationModifiers.Volatile); Debug.Assert((result & ~(DeclarationModifiers.AccessibilityMask | DeclarationModifiers.Fixed | DeclarationModifiers.Unsafe | DeclarationModifiers.New)) == 0); } if ((result & DeclarationModifiers.Const) != 0) { if ((result & DeclarationModifiers.Static) != 0) { // The constant '{0}' cannot be marked static diagnostics.Add(ErrorCode.ERR_StaticConstant, errorLocation, firstIdentifier.ValueText); } if ((result & DeclarationModifiers.ReadOnly) != 0) { // The modifier 'readonly' is not valid for this item diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.ReadOnlyKeyword)); } if ((result & DeclarationModifiers.Volatile) != 0) { // The modifier 'volatile' is not valid for this item diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.VolatileKeyword)); } if ((result & DeclarationModifiers.Unsafe) != 0) { // The modifier 'unsafe' is not valid for this item diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.UnsafeKeyword)); } result |= DeclarationModifiers.Static; // "constants are considered static members" } else { // NOTE: always cascading on a const, so suppress. // NOTE: we're being a bit sneaky here - we're using the containingType rather than this symbol // to determine whether or not unsafe is allowed. Since this symbol and the containing type are // in the same compilation, it won't make a difference. We do, however, have to pass the error // location explicitly. containingType.CheckUnsafeModifier(result, errorLocation, diagnostics); } return(result); }
protected SourceOrdinaryMethodSymbolBase( NamedTypeSymbol containingType, string name, Location location, CSharpSyntaxNode syntax, MethodKind methodKind, bool isIterator, bool isExtensionMethod, bool isPartial, bool hasBody, bool isNullableAnalysisEnabled, BindingDiagnosticBag diagnostics ) : base(containingType, syntax.GetReference(), location, isIterator: isIterator) { Debug.Assert(diagnostics.DiagnosticBag is object); _name = name; // The following two values are used to compute and store the initial value of the flags // However, these two components are placeholders; the correct value will be // computed lazily later and then the flags will be fixed up. const bool returnsVoid = false; DeclarationModifiers declarationModifiers; (declarationModifiers, HasExplicitAccessModifier) = this.MakeModifiers( methodKind, isPartial, hasBody, location, diagnostics ); var isMetadataVirtualIgnoringModifiers = methodKind == MethodKind.ExplicitInterfaceImplementation; //explicit impls must be marked metadata virtual this.MakeFlags( methodKind, declarationModifiers, returnsVoid, isExtensionMethod: isExtensionMethod, isNullableAnalysisEnabled: isNullableAnalysisEnabled, isMetadataVirtualIgnoringModifiers: isMetadataVirtualIgnoringModifiers ); _typeParameters = MakeTypeParameters(syntax, diagnostics); CheckFeatureAvailabilityAndRuntimeSupport(syntax, location, hasBody, diagnostics); if (hasBody) { CheckModifiersForBody(location, diagnostics); } var info = ModifierUtils.CheckAccessibility( this.DeclarationModifiers, this, isExplicitInterfaceImplementation: methodKind == MethodKind.ExplicitInterfaceImplementation ); if (info != null) { diagnostics.Add(info, location); } }
protected SourceUserDefinedOperatorSymbolBase( MethodKind methodKind, string name, SourceMemberContainerTypeSymbol containingType, Location location, BaseMethodDeclarationSyntax syntax, DiagnosticBag diagnostics) : base(containingType, syntax.GetReference(), location, isIterator: SyntaxFacts.HasYieldOperations(syntax.Body)) { _name = name; _isExpressionBodied = syntax.Body == null && syntax.ExpressionBody != null; var defaultAccess = DeclarationModifiers.Private; var allowedModifiers = DeclarationModifiers.AccessibilityMask | DeclarationModifiers.Static | DeclarationModifiers.Extern | DeclarationModifiers.Unsafe; bool modifierErrors; var declarationModifiers = ModifierUtils.MakeAndCheckNontypeMemberModifiers( syntax.Modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors); this.CheckUnsafeModifier(declarationModifiers, diagnostics); // We will bind the formal parameters and the return type lazily. For now, // assume that the return type is non-void; when we do the lazy initialization // of the parameters and return type we will update the flag if necessary. this.MakeFlags(methodKind, declarationModifiers, returnsVoid: false, isExtensionMethod: false); if (this.ContainingType.IsInterface && (methodKind == MethodKind.Conversion || name == WellKnownMemberNames.EqualityOperatorName || name == WellKnownMemberNames.InequalityOperatorName)) { // If we have a conversion or equality/inequality operator in an interface, we already have reported that fact as // an error. No need to cascade the error further. return; } if (this.ContainingType.IsStatic) { // Similarly if we're in a static class, though we have not reported it yet. // CS0715: '{0}': static classes cannot contain user-defined operators diagnostics.Add(ErrorCode.ERR_OperatorInStaticClass, location, this); return; } // SPEC: An operator declaration must include both a public and a // SPEC: static modifier if (this.DeclaredAccessibility != Accessibility.Public || !this.IsStatic) { // CS0558: User-defined operator '...' must be declared static and public diagnostics.Add(ErrorCode.ERR_OperatorsMustBeStatic, this.Locations[0], this); } // SPEC: Because an external operator provides no actual implementation, // SPEC: its operator body consists of a semicolon. For expression-bodied // SPEC: operators, the body is an expression. For all other operators, // SPEC: the operator body consists of a block... bool hasBody = syntax.HasAnyBody(); if (hasBody && IsExtern) { diagnostics.Add(ErrorCode.ERR_ExternHasBody, location, this); } else if (!hasBody && !IsExtern && !IsAbstract && !IsPartial) { // Do not report that the body is missing if the operator is marked as // partial or abstract; we will already have given an error for that so // there's no need to "cascade" the error. diagnostics.Add(ErrorCode.ERR_ConcreteMissingBody, location, this); } // SPEC: It is an error for the same modifier to appear multiple times in an // SPEC: operator declaration. var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers, this, isExplicitInterfaceImplementation: false); if (info != null) { diagnostics.Add(info, location); } }
private SourcePropertyAccessorSymbol( NamedTypeSymbol containingType, string name, SourcePropertySymbol property, DeclarationModifiers propertyModifiers, ImmutableArray <MethodSymbol> explicitInterfaceImplementations, Location location, AccessorDeclarationSyntax syntax, MethodKind methodKind, bool isAutoPropertyAccessor, DiagnosticBag diagnostics) : base(containingType, syntax.GetReference(), syntax.Body.GetReferenceOrNull(), location) { this.property = property; this.explicitInterfaceImplementations = explicitInterfaceImplementations; this.name = name; this.isAutoPropertyAccessor = isAutoPropertyAccessor; bool modifierErrors; var declarationModifiers = this.MakeModifiers(syntax, location, diagnostics, out modifierErrors); // Include modifiers from the containing property. propertyModifiers &= ~DeclarationModifiers.AccessibilityMask; if ((declarationModifiers & DeclarationModifiers.Private) != 0) { // Private accessors cannot be virtual. propertyModifiers &= ~DeclarationModifiers.Virtual; } declarationModifiers |= propertyModifiers & ~DeclarationModifiers.Indexer; // ReturnsVoid property is overridden in this class so // returnsVoid argument to MakeFlags is ignored. this.flags = MakeFlags(methodKind, declarationModifiers, returnsVoid: false, isExtensionMethod: false, isMetadataVirtualIgnoringModifiers: explicitInterfaceImplementations.Any()); var bodyOpt = syntax.Body; if (bodyOpt != null) { if (containingType.IsInterface) { diagnostics.Add(ErrorCode.ERR_InterfaceMemberHasBody, location, this); } else if (IsExtern && !IsAbstract) { diagnostics.Add(ErrorCode.ERR_ExternHasBody, location, this); } else if (IsAbstract && !IsExtern) { diagnostics.Add(ErrorCode.ERR_AbstractHasBody, location, this); } // Do not report error for IsAbstract && IsExtern. Dev10 reports CS0180 only // in that case ("member cannot be both extern and abstract"). } var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers); if (info != null) { diagnostics.Add(info, location); } if (!modifierErrors) { this.CheckModifiers(location, isAutoPropertyAccessor, diagnostics); } if (this.IsOverride) { MethodSymbol overriddenMethod = this.OverriddenMethod; if ((object)overriddenMethod != null) { // If this accessor is overriding a method from metadata, it is possible that // the name of the overridden method doesn't follow the C# get_X/set_X pattern. // We should copy the name so that the runtime will recognize this as an override. this.name = overriddenMethod.Name; } } }
private DeclarationModifiers MakeModifiers( SyntaxTokenList modifiers, MethodKind methodKind, bool hasBody, Location location, BindingDiagnosticBag diagnostics, out bool modifierErrors ) { var defaultAccess = (methodKind == MethodKind.StaticConstructor) ? DeclarationModifiers.None : DeclarationModifiers.Private; // Check that the set of modifiers is allowed const DeclarationModifiers allowedModifiers = DeclarationModifiers.AccessibilityMask | DeclarationModifiers.Static | DeclarationModifiers.Extern | DeclarationModifiers.Unsafe; var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers( modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors ); this.CheckUnsafeModifier(mods, diagnostics); if (methodKind == MethodKind.StaticConstructor) { // Don't report ERR_StaticConstructorWithAccessModifiers if the ctor symbol name doesn't match the containing type name. // This avoids extra unnecessary errors. // There will already be a diagnostic saying Method must have a return type. if ( (mods & DeclarationModifiers.AccessibilityMask) != 0 && ContainingType.Name == ((ConstructorDeclarationSyntax)this.SyntaxNode).Identifier.ValueText ) { diagnostics.Add( ErrorCode.ERR_StaticConstructorWithAccessModifiers, location, this ); mods = mods & ~DeclarationModifiers.AccessibilityMask; modifierErrors = true; } mods |= DeclarationModifiers.Private; // we mark static constructors private in the symbol table if (this.ContainingType.IsInterface) { ModifierUtils.ReportDefaultInterfaceImplementationModifiers( hasBody, mods, DeclarationModifiers.Extern, location, diagnostics ); } } return(mods); }
private SourceOrdinaryMethodSymbol( NamedTypeSymbol containingType, TypeSymbol explicitInterfaceType, string name, Location location, MethodDeclarationSyntax syntax, MethodKind methodKind, DiagnosticBag diagnostics) : base(containingType, syntax.GetReference(), location) { _name = name; _explicitInterfaceType = explicitInterfaceType; SyntaxTokenList modifiers = syntax.Modifiers; // The following two values are used to compute and store the initial value of the flags // However, these two components are placeholders; the correct value will be // computed lazily later and then the flags will be fixed up. const bool returnsVoid = false; var firstParam = syntax.ParameterList.Parameters.FirstOrDefault(); bool isExtensionMethod = firstParam != null && !firstParam.IsArgList && firstParam.Modifiers.Any(SyntaxKind.ThisKeyword); bool modifierErrors; var declarationModifiers = this.MakeModifiers(modifiers, methodKind, location, diagnostics, out modifierErrors); var isMetadataVirtualIgnoringModifiers = (object)explicitInterfaceType != null; //explicit impls must be marked metadata virtual this.MakeFlags(methodKind, declarationModifiers, returnsVoid, isExtensionMethod, isMetadataVirtualIgnoringModifiers); if (syntax.Arity == 0) { _typeParameters = ImmutableArray <TypeParameterSymbol> .Empty; ReportErrorIfHasConstraints(syntax.ConstraintClauses, diagnostics); } else { _typeParameters = MakeTypeParameters(syntax, diagnostics); } bool hasBlockBody = syntax.Body != null; _isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null; _hasAnyBody = hasBlockBody || _isExpressionBodied; _refKind = syntax.ReturnType.GetRefKind(); if (_hasAnyBody) { CheckModifiersForBody(location, diagnostics); } var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers); if (info != null) { diagnostics.Add(info, location); } // When a generic method overrides a generic method declared in a base class, or is an // explicit interface member implementation of a method in a base interface, the method // shall not specify any type-parameter-constraints-clauses. In these cases, the type // parameters of the method inherit constraints from the method being overridden or // implemented if (syntax.ConstraintClauses.Count > 0) { if (syntax.ExplicitInterfaceSpecifier != null || syntax.Modifiers.Any(SyntaxKind.OverrideKeyword)) { diagnostics.Add( ErrorCode.ERR_OverrideWithConstraints, syntax.ConstraintClauses[0].WhereKeyword.GetLocation()); } } CheckForBlockAndExpressionBody( syntax.Body, syntax.ExpressionBody, syntax, diagnostics); }
protected SourceUserDefinedOperatorSymbolBase( MethodKind methodKind, string name, // @MattWindsor91 (Concept-C# 2017) // // Default structs can contain these, so I've relaxed the class // requirement on 'containingType' to allow for this. // // A more robust approach to this would be to make a new symbol // for default user-defined operators and set this back to // SourceMemberContainerTypeSymbol. NamedTypeSymbol containingType, Location location, SyntaxReference syntaxReference, SyntaxReference bodySyntaxReference, SyntaxTokenList modifiersSyntax, DiagnosticBag diagnostics, bool isExpressionBodied) : base(containingType, syntaxReference, bodySyntaxReference, location) { _name = name; _isExpressionBodied = isExpressionBodied; var isConceptOperator = ContainingType.IsInstance || ContainingType.IsConcept || ContainingType.IsDefaultStruct; // @t-mawind (is this a good idea?) var defaultAccess = isConceptOperator ? DeclarationModifiers.Public : DeclarationModifiers.Private; var allowedModifiers = DeclarationModifiers.AccessibilityMask | DeclarationModifiers.Static | DeclarationModifiers.Extern | DeclarationModifiers.Unsafe; bool modifierErrors; var declarationModifiers = ModifierUtils.MakeAndCheckNontypeMemberModifiers( modifiersSyntax, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors); this.CheckUnsafeModifier(declarationModifiers, diagnostics); if (ContainingType.IsConcept) { // @t-mawind Is there any easier way of doing this? declarationModifiers |= DeclarationModifiers.Abstract; } // We will bind the formal parameters and the return type lazily. For now, // assume that the return type is non-void; when we do the lazy initialization // of the parameters and return type we will update the flag if necessary. this.MakeFlags(methodKind, declarationModifiers, returnsVoid: false, isExtensionMethod: false); if (this.ContainingType.IsInterface && !this.ContainingType.IsConcept) { // If we have an operator in an interface, we already have reported that fact as // an error. No need to cascade the error further. return; } if (this.ContainingType.IsStatic) { // Similarly if we're in a static class, though we have not reported it yet. // CS0715: '{0}': static classes cannot contain user-defined operators diagnostics.Add(ErrorCode.ERR_OperatorInStaticClass, location, this); return; } // @t-mawind // Concept operators must be public and _non_-static. if (isConceptOperator) { if (DeclaredAccessibility != Accessibility.Public || IsStatic) { // CS4038: User-defined concept operator '...' must be declared non-static and public. diagnostics.Add(ErrorCode.ERR_ConceptOperatorsMustBeNonStatic, Locations[0], this); } } else { // SPEC: An operator declaration must include both a public and a // SPEC: static modifier if (this.DeclaredAccessibility != Accessibility.Public || !this.IsStatic) { // CS0558: User-defined operator '...' must be declared static and public diagnostics.Add(ErrorCode.ERR_OperatorsMustBeStatic, this.Locations[0], this); } } // SPEC: Because an external operator provides no actual implementation, // SPEC: its operator body consists of a semicolon. For expression-bodied // SPEC: operators, the body is an expression. For all other operators, // SPEC: the operator body consists of a block... if (bodySyntaxReference != null && IsExtern) { diagnostics.Add(ErrorCode.ERR_ExternHasBody, location, this); } else if (bodySyntaxReference == null && !IsExtern && !IsAbstract && !IsPartial) { // Do not report that the body is missing if the operator is marked as // partial or abstract; we will already have given an error for that so // there's no need to "cascade" the error. diagnostics.Add(ErrorCode.ERR_ConcreteMissingBody, location, this); } // SPEC: It is an error for the same modifier to appear multiple times in an // SPEC: operator declaration. var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers); if (info != null) { diagnostics.Add(info, location); } }
private (DeclarationModifiers mods, bool hasExplicitAccessMod) MakeModifiers(MethodKind methodKind, bool isPartial, bool hasBody, Location location, DiagnosticBag diagnostics) { bool isInterface = this.ContainingType.IsInterface; bool isExplicitInterfaceImplementation = methodKind == MethodKind.ExplicitInterfaceImplementation; var defaultAccess = isInterface && isPartial && !isExplicitInterfaceImplementation ? DeclarationModifiers.Public : DeclarationModifiers.Private; // Check that the set of modifiers is allowed var allowedModifiers = DeclarationModifiers.Partial | DeclarationModifiers.Unsafe; var defaultInterfaceImplementationModifiers = DeclarationModifiers.None; if (!isExplicitInterfaceImplementation) { allowedModifiers |= DeclarationModifiers.New | DeclarationModifiers.Sealed | DeclarationModifiers.Abstract | DeclarationModifiers.Static | DeclarationModifiers.Virtual | DeclarationModifiers.AccessibilityMask; if (!isInterface) { allowedModifiers |= DeclarationModifiers.Override; } else { // This is needed to make sure we can detect 'public' modifier specified explicitly and // check it against language version below. defaultAccess = DeclarationModifiers.None; defaultInterfaceImplementationModifiers |= DeclarationModifiers.Sealed | DeclarationModifiers.Abstract | DeclarationModifiers.Static | DeclarationModifiers.Virtual | DeclarationModifiers.Extern | DeclarationModifiers.Async | DeclarationModifiers.Partial | DeclarationModifiers.AccessibilityMask; } } else if (isInterface) { Debug.Assert(isExplicitInterfaceImplementation); allowedModifiers |= DeclarationModifiers.Abstract; } allowedModifiers |= DeclarationModifiers.Extern | DeclarationModifiers.Async; if (ContainingType.IsStructType()) { allowedModifiers |= DeclarationModifiers.ReadOnly; } // In order to detect whether explicit accessibility mods were provided, we pass the default value // for 'defaultAccess' and manually add in the 'defaultAccess' flags after the call. bool hasExplicitAccessMod; DeclarationModifiers mods = MakeDeclarationModifiers(allowedModifiers, diagnostics); if ((mods & DeclarationModifiers.AccessibilityMask) == 0) { hasExplicitAccessMod = false; mods |= defaultAccess; } else { hasExplicitAccessMod = true; } this.CheckUnsafeModifier(mods, diagnostics); ModifierUtils.ReportDefaultInterfaceImplementationModifiers(hasBody, mods, defaultInterfaceImplementationModifiers, location, diagnostics); mods = AddImpliedModifiers(mods, isInterface, methodKind, hasBody); return(mods, hasExplicitAccessMod); }
protected void CheckAccessibility(BindingDiagnosticBag diagnostics) { ModifierUtils.CheckAccessibility(Modifiers, this, isExplicitInterfaceImplementation: false, diagnostics, ErrorLocation); }
private SourceMemberMethodSymbol( NamedTypeSymbol containingType, TypeSymbol explicitInterfaceType, string name, Location location, MethodDeclarationSyntax syntax, MethodKind methodKind, DiagnosticBag diagnostics) : base(containingType, syntax.GetReference(), // Prefer a block body if both exist syntax.Body?.GetReference() ?? syntax.ExpressionBody?.GetReference(), location) { _name = name; _explicitInterfaceType = explicitInterfaceType; SyntaxTokenList modifiers = syntax.Modifiers; // The following two values are used to compute and store the initial value of the flags // However, these two components are placeholders; the correct value will be // computed lazily later and then the flags will be fixed up. const bool returnsVoid = false; var firstParam = syntax.ParameterList.Parameters.FirstOrDefault(); bool isExtensionMethod = firstParam != null && !firstParam.IsArgList && firstParam.Modifiers.Any(SyntaxKind.ThisKeyword); bool modifierErrors; var declarationModifiers = this.MakeModifiers(modifiers, methodKind, location, diagnostics, out modifierErrors); var isMetadataVirtualIgnoringModifiers = (object)explicitInterfaceType != null; //explicit impls must be marked metadata virtual this.MakeFlags(methodKind, declarationModifiers, returnsVoid, isExtensionMethod, isMetadataVirtualIgnoringModifiers); // We, of course, have to deal with the possibility of the // type parameter list being null in MakeTypeParameters now. _typeParameters = (syntax.Arity == 0) ? ImmutableArray <TypeParameterSymbol> .Empty : MakeTypeParameters(syntax, diagnostics); bool hasBlockBody = syntax.Body != null; _isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null; // @t-mawind // If this method is on a concept and has a body, then we pretend // it isn't there in various parts of this class, as it's meant for // the default struct. // First, we don't check modifiers for it here. if (!containingType.IsConcept && (hasBlockBody || _isExpressionBodied)) { CheckModifiersForBody(location, diagnostics); } _refKind = syntax.RefKeyword.Kind().GetRefKind(); var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers); if (info != null) { diagnostics.Add(info, location); } }
private SourceConstructorSymbol( SourceMemberContainerTypeSymbol containingType, Location location, ConstructorDeclarationSyntax syntax, MethodKind methodKind, bool isNullableAnalysisEnabled, BindingDiagnosticBag diagnostics ) : base(containingType, location, syntax, SyntaxFacts.HasYieldOperations(syntax)) { bool hasBlockBody = syntax.Body != null; _isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null; bool hasBody = hasBlockBody || _isExpressionBodied; _hasThisInitializer = syntax.Initializer?.Kind() == SyntaxKind.ThisConstructorInitializer; bool modifierErrors; var declarationModifiers = this.MakeModifiers( syntax.Modifiers, methodKind, hasBody, location, diagnostics, out modifierErrors ); this.MakeFlags( methodKind, declarationModifiers, returnsVoid: true, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled ); if (syntax.Identifier.ValueText != containingType.Name) { // This is probably a method declaration with the type missing. diagnostics.Add(ErrorCode.ERR_MemberNeedsType, location); } if (IsExtern) { if (methodKind == MethodKind.Constructor && syntax.Initializer != null) { diagnostics.Add(ErrorCode.ERR_ExternHasConstructorInitializer, location, this); } if (hasBody) { diagnostics.Add(ErrorCode.ERR_ExternHasBody, location, this); } } if (methodKind == MethodKind.StaticConstructor) { CheckFeatureAvailabilityAndRuntimeSupport(syntax, location, hasBody, diagnostics); } var info = ModifierUtils.CheckAccessibility( this.DeclarationModifiers, this, isExplicitInterfaceImplementation: false ); if (info != null) { diagnostics.Add(info, location); } if (!modifierErrors) { this.CheckModifiers(methodKind, hasBody, location, diagnostics); } CheckForBlockAndExpressionBody(syntax.Body, syntax.ExpressionBody, syntax, diagnostics); }
private SourceMemberMethodSymbol( NamedTypeSymbol containingType, TypeSymbol explicitInterfaceType, string name, Location location, Binder bodyBinder, MethodDeclarationSyntax syntax, MethodKind methodKind, DiagnosticBag diagnostics) : base(containingType, syntax.GetReference(), // Prefer a block body if both exist syntax.Body?.GetReference() ?? syntax.ExpressionBody?.GetReference(), location) { _name = name; _explicitInterfaceType = explicitInterfaceType; SyntaxTokenList modifiers = syntax.Modifiers; // The following two values are used to compute and store the initial value of the flags // However, these two components are placeholders; the correct value will be // computed lazily later and then the flags will be fixed up. const bool returnsVoid = false; var firstParam = syntax.ParameterList.Parameters.FirstOrDefault(); bool isExtensionMethod = firstParam != null && !firstParam.IsArgList && firstParam.Modifiers.Any(SyntaxKind.ThisKeyword); bool modifierErrors; var declarationModifiers = this.MakeModifiers(modifiers, methodKind, location, diagnostics, out modifierErrors); var isMetadataVirtualIgnoringModifiers = (object)explicitInterfaceType != null; //explicit impls must be marked metadata virtual this.MakeFlags(methodKind, declarationModifiers, returnsVoid, isExtensionMethod, isMetadataVirtualIgnoringModifiers); // NOTE: by creating a WithMethodTypeParametersBinder, we are effectively duplicating the // functionality of the BinderFactory. Unfortunately, we cannot use the BinderFactory // because it depends on having access to the member list of our containing type and // that list cannot be complete because we're not finished constructing this member. // TODO: at least keep this in sync with BinderFactory.VisitMethodDeclaration. bodyBinder = bodyBinder.WithUnsafeRegionIfNecessary(modifiers); Binder withTypeParamsBinder; if (syntax.Arity == 0) { withTypeParamsBinder = bodyBinder; _typeParameters = ImmutableArray <TypeParameterSymbol> .Empty; } else { var parameterBinder = new WithMethodTypeParametersBinder(this, bodyBinder); withTypeParamsBinder = parameterBinder; _typeParameters = MakeTypeParameters(syntax, diagnostics); } bool hasBlockBody = syntax.Body != null; _isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null; if (hasBlockBody || _isExpressionBodied) { CheckModifiersForBody(location, diagnostics); } var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers); if (info != null) { diagnostics.Add(info, location); } if (this.IsPartial) { // Partial methods must be completed early because they are matched up // by signature while producing the enclosing type's member list. However, // that means any type parameter constraints will be bound before the method // is added to the containing type. To enable binding of constraints before the // .ctor completes we hold on to the current binder while the .ctor is executing. // If we change the handling of partial methods, so that partial methods are // completed lazily, the 'constraintClauseBinder' field should be removed. _constraintClauseBinder = withTypeParamsBinder; state.NotePartComplete(CompletionPart.StartMethodChecks); MethodChecks(syntax, withTypeParamsBinder, diagnostics); state.NotePartComplete(CompletionPart.FinishMethodChecks); _constraintClauseBinder = null; } }