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(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, 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 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); }
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); }
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);
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 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); }
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); } }