internal sealed override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { // Check constraints on return type and parameters. Note: Dev10 uses the // method name location for any such errors. We'll do the same for return // type errors but for parameter errors, we'll use the parameter location. var compilation = DeclaringCompilation; this.ReturnType.CheckAllConstraints(compilation, conversions, this.Locations[0], diagnostics); foreach (var parameter in this.Parameters) { parameter.Type.CheckAllConstraints(compilation, conversions, parameter.Locations[0], diagnostics); } ParameterHelpers.EnsureIsReadOnlyAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); if (ReturnType.ContainsNativeInteger()) { compilation.EnsureNativeIntegerAttributeExists(diagnostics, ReturnTypeSyntax.Location, modifyCompilation: true); } ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); if (compilation.ShouldEmitNullableAttributes(this) && ReturnTypeWithAnnotations.NeedsNullableAttribute()) { compilation.EnsureNullableAttributeExists(diagnostics, ReturnTypeSyntax.Location, modifyCompilation: true); } ParameterHelpers.EnsureNullableAttributeExists(compilation, this, Parameters, diagnostics, modifyCompilation: true); }
internal InvokeMethod( SourceMemberContainerTypeSymbol delegateType, RefKind refKind, TypeSymbol returnType, DelegateDeclarationSyntax syntax, Binder binder, DiagnosticBag diagnostics) : base(delegateType, returnType, syntax, MethodKind.DelegateInvoke, DeclarationModifiers.Virtual | DeclarationModifiers.Public) { this.refKind = refKind; SyntaxToken arglistToken; var parameters = ParameterHelpers.MakeParameters( binder, this, syntax.ParameterList, out arglistToken, allowRefOrOut: true, allowThis: false, diagnostics: diagnostics); if (arglistToken.Kind() == SyntaxKind.ArgListKeyword) { // This is a parse-time error in the native compiler; it is a semantic analysis error in Roslyn. // error CS1669: __arglist is not valid in this context diagnostics.Add(ErrorCode.ERR_IllegalVarArgs, new SourceLocation(arglistToken)); } InitializeParameters(parameters); }
protected override void MethodChecks(DiagnosticBag diagnostics) { var syntax = GetSyntax(); var binderFactory = this.DeclaringCompilation.GetBinderFactory(syntax.SyntaxTree); ParameterListSyntax parameterList = syntax.ParameterList; // NOTE: if we asked for the binder for the body of the constructor, we'd risk a stack overflow because // we might still be constructing the member list of the containing type. However, getting the binder // for the parameters should be safe. var bodyBinder = binderFactory.GetBinder(parameterList).WithContainingMemberOrLambda(this); SyntaxToken arglistToken; _lazyParameters = ParameterHelpers.MakeParameters(bodyBinder, this, parameterList, true, out arglistToken, diagnostics); _lazyIsVararg = (arglistToken.Kind() == SyntaxKind.ArgListKeyword); _lazyReturnType = bodyBinder.GetSpecialType(SpecialType.System_Void, diagnostics, syntax); var location = this.Locations[0]; if (MethodKind == MethodKind.StaticConstructor && (_lazyParameters.Length != 0)) { diagnostics.Add(ErrorCode.ERR_StaticConstParam, location, this); } this.CheckEffectiveAccessibility(_lazyReturnType, _lazyParameters, diagnostics); if (_lazyIsVararg && (IsGenericMethod || ContainingType.IsGenericType || _lazyParameters.Length > 0 && _lazyParameters[_lazyParameters.Length - 1].IsParams)) { diagnostics.Add(ErrorCode.ERR_BadVarargs, location); } }
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { // Check constraints on return type and parameters. Note: Dev10 uses the // method name location for any such errors. We'll do the same for return // type errors but for parameter errors, we'll use the parameter location. if ((object)_explicitInterfaceType != null) { var syntax = this.GetSyntax(); Debug.Assert(syntax.ExplicitInterfaceSpecifier != null); _explicitInterfaceType.CheckAllConstraints(conversions, new SourceLocation(syntax.ExplicitInterfaceSpecifier.Name), diagnostics); } this.ReturnType.CheckAllConstraints(conversions, this.Locations[0], diagnostics); foreach (var parameter in this.Parameters) { parameter.Type.CheckAllConstraints(conversions, parameter.Locations[0], diagnostics); } var implementingPart = this.SourcePartialImplementation; if ((object)implementingPart != null) { PartialMethodChecks(this, implementingPart, diagnostics); } if (_refKind == RefKind.RefReadOnly) { this.DeclaringCompilation.EnsureIsReadOnlyAttributeExists(diagnostics, GetSyntax().ReturnType.Location, modifyCompilationForRefReadOnly: true); } ParameterHelpers.EnsureIsReadOnlyAttributeExists(Parameters, diagnostics, modifyCompilationForRefReadOnly: true); }
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { base.AfterAddingTypeMembersChecks(conversions, diagnostics); ParameterHelpers.EnsureIsReadOnlyAttributeExists(Parameters, diagnostics, modifyCompilation: true); ParameterHelpers.EnsureNullableAttributeExists(Parameters, diagnostics, modifyCompilation: true); }
private void ComputeParameters() { if (_lazyParametersAndDiagnostics != null) { return; } var diagnostics = DiagnosticBag.GetInstance(); SyntaxToken arglistToken; foreach (var param in _syntax.ParameterList.Parameters) { ReportAnyAttributes(diagnostics, param.AttributeLists); } var parameters = ParameterHelpers.MakeParameters( _binder, this, _syntax.ParameterList, arglistToken: out arglistToken, diagnostics: diagnostics, allowRefOrOut: true, allowThis: true, beStrict: true); var isVararg = (arglistToken.Kind() == SyntaxKind.ArgListKeyword); if (IsAsync && diagnostics.IsEmptyWithoutResolution) { SourceMemberMethodSymbol.ReportAsyncParameterErrors(parameters, diagnostics, this.Locations[0]); } var value = new ParametersAndDiagnostics(parameters, isVararg, diagnostics.ToReadOnlyAndFree()); Interlocked.CompareExchange(ref _lazyParametersAndDiagnostics, value, null); }
protected override void MethodChecks(DiagnosticBag diagnostics) { var binder = this.DeclaringCompilation. GetBinderFactory(syntaxReferenceOpt.SyntaxTree).GetBinder(ReturnTypeSyntax, GetSyntax(), this); SyntaxToken arglistToken; var signatureBinder = binder.WithAdditionalFlags(BinderFlags.SuppressConstraintChecks); _lazyParameters = ParameterHelpers.MakeParameters( signatureBinder, this, ParameterListSyntax, out arglistToken, diagnostics, allowRefOrOut: true, allowThis: false, beStrict: false); if (arglistToken.Kind() == SyntaxKind.ArgListKeyword) { // This is a parse-time error in the native compiler; it is a semantic analysis error in Roslyn. // error CS1669: __arglist is not valid in this context diagnostics.Add(ErrorCode.ERR_IllegalVarArgs, new SourceLocation(arglistToken)); // Regardless of whether __arglist appears in the source code, we do not mark // the operator method as being a varargs method. } _lazyReturnType = signatureBinder.BindType(ReturnTypeSyntax, diagnostics); if (_lazyReturnType.IsRestrictedType()) { // Method or delegate cannot return type '{0}' diagnostics.Add(ErrorCode.ERR_MethodReturnCantBeRefAny, ReturnTypeSyntax.Location, _lazyReturnType); } if (_lazyReturnType.IsStatic) { // '{0}': static types cannot be used as return types diagnostics.Add(ErrorCode.ERR_ReturnTypeIsStaticClass, ReturnTypeSyntax.Location, _lazyReturnType); } this.SetReturnsVoid(_lazyReturnType.SpecialType == SpecialType.System_Void); // If we have an operator in an interface or static class then we already // have reported that fact as an error. No need to cascade the error further. if (this.ContainingType.IsInterfaceType() || this.ContainingType.IsStatic) { return; } // SPEC: All types referenced in an operator declaration must be at least as accessible // SPEC: as the operator itself. CheckEffectiveAccessibility(_lazyReturnType, _lazyParameters, diagnostics); CheckValueParameters(diagnostics); CheckOperatorSignatures(diagnostics); }
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { var syntax = (DelegateDeclarationSyntax)SyntaxRef.GetSyntax(); var location = syntax.ReturnType.GetLocation(); var compilation = DeclaringCompilation; Debug.Assert(location != null); base.AfterAddingTypeMembersChecks(conversions, diagnostics); if (_refKind == RefKind.RefReadOnly) { compilation.EnsureIsReadOnlyAttributeExists(diagnostics, location, modifyCompilation: true); } ParameterHelpers.EnsureIsReadOnlyAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); if (ReturnType.ContainsNativeInteger()) { compilation.EnsureNativeIntegerAttributeExists(diagnostics, location, modifyCompilation: true); } ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); if (compilation.ShouldEmitNullableAttributes(this) && ReturnTypeWithAnnotations.NeedsNullableAttribute()) { compilation.EnsureNullableAttributeExists(diagnostics, location, modifyCompilation: true); } ParameterHelpers.EnsureNullableAttributeExists(compilation, this, Parameters, diagnostics, modifyCompilation: true); }
// If binder is null, then get it from the compilation. Otherwise use the provided binder. // Don't always get it from the compilation because we might be in a speculative context (local function parameter), // in which case the declaring compilation is the wrong one. protected ConstantValue MakeDefaultExpression(DiagnosticBag diagnostics, Binder binder) { var parameterSyntax = this.CSharpSyntaxNode; if (parameterSyntax == null) { return(ConstantValue.NotAvailable); } var defaultSyntax = parameterSyntax.Default; if (defaultSyntax == null) { return(ConstantValue.NotAvailable); } if (binder == null) { var syntaxTree = _syntaxRef.SyntaxTree; var compilation = this.DeclaringCompilation; var binderFactory = compilation.GetBinderFactory(syntaxTree); binder = binderFactory.GetBinder(defaultSyntax); } Debug.Assert(binder.GetBinder(defaultSyntax) == null); Binder binderForDefault = binder.CreateBinderForParameterDefaultValue(this, defaultSyntax); Debug.Assert(binderForDefault.InParameterDefaultValue); Debug.Assert(binderForDefault.ContainingMemberOrLambda == ContainingSymbol); BoundExpression valueBeforeConversion; var convertedExpression = binderForDefault.BindParameterDefaultValue(defaultSyntax, parameterType, diagnostics, out valueBeforeConversion); bool hasErrors = ParameterHelpers.ReportDefaultParameterErrors(binder, ContainingSymbol, parameterSyntax, this, valueBeforeConversion, diagnostics); if (hasErrors) { return(ConstantValue.Bad); } // If we have something like M(double? x = 1) then the expression we'll get is (double?)1, which // does not have a constant value. The constant value we want is (double)1. if (convertedExpression.ConstantValue == null && convertedExpression.Kind == BoundKind.Conversion) { if (parameterType.IsNullableType()) { convertedExpression = binder.GenerateConversionForAssignment(parameterType.GetNullableUnderlyingType(), valueBeforeConversion, diagnostics, isDefaultParameter: true); } } // represent default(struct) by a Null constant: var value = convertedExpression.ConstantValue ?? ConstantValue.Null; VerifyParamDefaultValueMatchesAttributeIfAny(value, defaultSyntax.Value, diagnostics); return(value); }
internal InvokeMethod( SourceMemberContainerTypeSymbol delegateType, RefKind refKind, TypeWithAnnotations returnType, DelegateDeclarationSyntax syntax, Binder binder, BindingDiagnosticBag diagnostics ) : base( delegateType, returnType, syntax, MethodKind.DelegateInvoke, DeclarationModifiers.Virtual | DeclarationModifiers.Public ) { this._refKind = refKind; SyntaxToken arglistToken; var parameters = ParameterHelpers.MakeParameters( binder, this, syntax.ParameterList, out arglistToken, allowRefOrOut: true, allowThis: false, addRefReadOnlyModifier: true, diagnostics: diagnostics ); if (arglistToken.Kind() == SyntaxKind.ArgListKeyword) { // This is a parse-time error in the native compiler; it is a semantic analysis error in Roslyn. // error CS1669: __arglist is not valid in this context diagnostics.Add(ErrorCode.ERR_IllegalVarArgs, new SourceLocation(arglistToken)); } if (_refKind == RefKind.RefReadOnly) { var modifierType = binder.GetWellKnownType( WellKnownType.System_Runtime_InteropServices_InAttribute, diagnostics, syntax.ReturnType ); _refCustomModifiers = ImmutableArray.Create( CSharpCustomModifier.CreateRequired(modifierType) ); } else { _refCustomModifiers = ImmutableArray<CustomModifier>.Empty; } InitializeParameters(parameters); }
internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder <SynthesizedAttributeData> attributes) { base.AddSynthesizedAttributes(moduleBuilder, ref attributes); var compilation = this.DeclaringCompilation; if (this.IsParams) { AddSynthesizedAttribute(ref attributes, compilation.TrySynthesizeAttribute(WellKnownMember.System_ParamArrayAttribute__ctor)); } // Synthesize DecimalConstantAttribute if we don't have an explicit custom attribute already: var defaultValue = this.ExplicitDefaultConstantValue; if (defaultValue != ConstantValue.NotAvailable && defaultValue.SpecialType == SpecialType.System_Decimal && DefaultValueFromAttributes == ConstantValue.NotAvailable) { AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDecimalConstantAttribute(defaultValue.DecimalValue)); } var type = this.TypeWithAnnotations; if (type.Type.ContainsDynamic()) { AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDynamicAttribute(type.Type, type.CustomModifiers.Length + this.RefCustomModifiers.Length, this.RefKind)); } if (compilation.ShouldEmitNativeIntegerAttributes(type.Type)) { AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNativeIntegerAttribute(this, type.Type)); } if (ParameterHelpers.RequiresLifetimeAnnotationAttribute(this)) { AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeLifetimeAnnotationAttribute(this, Scope)); } if (type.Type.ContainsTupleNames()) { AddSynthesizedAttribute(ref attributes, compilation.SynthesizeTupleNamesAttribute(type.Type)); } if (this.RefKind == RefKind.RefReadOnly) { AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeIsReadOnlyAttribute(this)); } if (compilation.ShouldEmitNullableAttributes(this)) { AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNullableAttributeIfNecessary(this, GetNullableContextValue(), type)); } }
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { base.AfterAddingTypeMembersChecks(conversions, diagnostics); if (_refKind == RefKind.RefReadOnly) { var syntax = (DelegateDeclarationSyntax)SyntaxRef.GetSyntax(); DeclaringCompilation.EnsureIsReadOnlyAttributeExists(diagnostics, syntax.ReturnType.GetLocation(), modifyCompilationForRefReadOnly: true); } ParameterHelpers.EnsureIsReadOnlyAttributeExists(Parameters, diagnostics, modifyCompilationForRefReadOnly: true); }
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { base.AfterAddingTypeMembersChecks(conversions, diagnostics); ParameterHelpers.EnsureIsReadOnlyAttributeExists(Parameters, diagnostics, modifyCompilation: true); ParameterHelpers.EnsureNullableAttributeExists(Parameters, diagnostics, modifyCompilation: true); foreach (var parameter in this.Parameters) { parameter.Type.CheckAllConstraints(DeclaringCompilation, conversions, parameter.Locations[0], diagnostics); } }
protected override void MethodChecks(DiagnosticBag diagnostics) { var syntax = (CSharpSyntaxNode)syntaxReference.GetSyntax(); var binderFactory = this.DeclaringCompilation.GetBinderFactory(syntaxReference.SyntaxTree); ParameterListSyntax parameterList; if (syntax.Kind == SyntaxKind.ParameterList) { // Primary constructor case parameterList = (ParameterListSyntax)syntax; } else { parameterList = ((ConstructorDeclarationSyntax)syntax).ParameterList; } // NOTE: if we asked for the binder for the body of the constructor, we'd risk a stack overflow because // we might still be constructing the member list of the containing type. However, getting the binder // for the parameters should be safe. var bodyBinder = binderFactory.GetBinder(parameterList).WithContainingMemberOrLambda(this); SyntaxToken arglistToken; this.lazyParameters = ParameterHelpers.MakeParameters(bodyBinder, this, parameterList, true, out arglistToken, diagnostics); this.lazyIsVararg = (arglistToken.CSharpKind() == SyntaxKind.ArgListKeyword); this.lazyReturnType = bodyBinder.GetSpecialType(SpecialType.System_Void, diagnostics, syntax); if (MethodKind == MethodKind.StaticConstructor && (lazyParameters.Length != 0)) { diagnostics.Add(ErrorCode.ERR_StaticConstParam, Locations[0], this); } this.CheckEffectiveAccessibility(lazyReturnType, lazyParameters, diagnostics); if (this.lazyIsVararg && (IsGenericMethod || ContainingType.IsGenericType || this.lazyParameters.Length > 0 && this.lazyParameters[this.lazyParameters.Length - 1].IsParams)) { diagnostics.Add(ErrorCode.ERR_BadVarargs, Locations[0]); } if (this.IsPrimaryCtor) { string typeName = ContainingType.Name; foreach (var p in this.lazyParameters) { if (typeName.Equals(p.Name)) { diagnostics.Add(ErrorCode.ERR_PrimaryCtorParameterSameNameAsContainingType, p.Locations[0], ContainingType); break; } } } }
protected (TypeWithAnnotations ReturnType, ImmutableArray <ParameterSymbol> Parameters) MakeParametersAndBindReturnType(BaseMethodDeclarationSyntax declarationSyntax, TypeSyntax returnTypeSyntax, DiagnosticBag diagnostics) { TypeWithAnnotations returnType; ImmutableArray <ParameterSymbol> parameters; var binder = this.DeclaringCompilation. GetBinderFactory(declarationSyntax.SyntaxTree).GetBinder(returnTypeSyntax, declarationSyntax, this); SyntaxToken arglistToken; var signatureBinder = binder.WithAdditionalFlags(BinderFlags.SuppressConstraintChecks); parameters = ParameterHelpers.MakeParameters( signatureBinder, this, declarationSyntax.ParameterList, out arglistToken, allowRefOrOut: true, allowThis: false, addRefReadOnlyModifier: false, diagnostics: diagnostics); if (arglistToken.Kind() == SyntaxKind.ArgListKeyword) { // This is a parse-time error in the native compiler; it is a semantic analysis error in Roslyn. // error CS1669: __arglist is not valid in this context diagnostics.Add(ErrorCode.ERR_IllegalVarArgs, new SourceLocation(arglistToken)); // Regardless of whether __arglist appears in the source code, we do not mark // the operator method as being a varargs method. } returnType = signatureBinder.BindType(returnTypeSyntax, diagnostics); // restricted types cannot be returned. // NOTE: Span-like types can be returned (if expression is returnable). if (returnType.IsRestrictedType(ignoreSpanLikeTypes: true)) { // The return type of a method, delegate, or function pointer cannot be '{0}' diagnostics.Add(ErrorCode.ERR_MethodReturnCantBeRefAny, returnTypeSyntax.Location, returnType.Type); } if (returnType.Type.IsStatic) { // Operators in interfaces was introduced in C# 8, so there's no need to be specially concerned about // maintaining backcompat with the native compiler bug around interfaces. // '{0}': static types cannot be used as return types diagnostics.Add(ErrorFacts.GetStaticClassReturnCode(useWarning: false), returnTypeSyntax.Location, returnType.Type); } return(returnType, parameters); }
private void ComputeParameters() { if (_lazyParameters != null) { return; } SyntaxToken arglistToken; var diagnostics = DiagnosticBag.GetInstance(); var parameters = ParameterHelpers.MakeParameters( _binder, this, _syntax.ParameterList, arglistToken: out arglistToken, allowRefOrOut: true, allowThis: true, addRefReadOnlyModifier: false, diagnostics: diagnostics); var compilation = DeclaringCompilation; ParameterHelpers.EnsureIsReadOnlyAttributeExists(compilation, parameters, diagnostics, modifyCompilation: false); ParameterHelpers.EnsureNullableAttributeExists(compilation, this, parameters, diagnostics, modifyCompilation: false); // Note: we don't need to warn on annotations used in #nullable disable context for local functions, as this is handled in binding already var isVararg = arglistToken.Kind() == SyntaxKind.ArgListKeyword; if (isVararg) { diagnostics.Add(ErrorCode.ERR_IllegalVarArgs, arglistToken.GetLocation()); } if (IsAsync) { SourceOrdinaryMethodSymbol.ReportAsyncParameterErrors(parameters, diagnostics, this.Locations[0]); } lock (_declarationDiagnostics) { if (_lazyParameters != null) { diagnostics.Free(); return; } _declarationDiagnostics.AddRangeAndFree(diagnostics); _lazyIsVarArg = isVararg; _lazyParameters = parameters; } }
protected sealed override void MethodChecks(BindingDiagnosticBag diagnostics) { var syntax = (CSharpSyntaxNode)syntaxReferenceOpt.GetSyntax(); var binderFactory = this.DeclaringCompilation.GetBinderFactory(syntax.SyntaxTree); ParameterListSyntax parameterList = GetParameterList(); // NOTE: if we asked for the binder for the body of the constructor, we'd risk a stack overflow because // we might still be constructing the member list of the containing type. However, getting the binder // for the parameters should be safe. var bodyBinder = binderFactory.GetBinder(parameterList, syntax, this).WithContainingMemberOrLambda(this); // Constraint checking for parameter and return types must be delayed until // the method has been added to the containing type member list since // evaluating the constraints may depend on accessing this method from // the container (comparing this method to others to find overrides for // instance). Constraints are checked in AfterAddingTypeMembersChecks. var signatureBinder = bodyBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.SuppressConstraintChecks, this); SyntaxToken arglistToken; _lazyParameters = ParameterHelpers.MakeParameters( signatureBinder, this, parameterList, out arglistToken, allowRefOrOut: AllowRefOrOut, allowThis: false, addRefReadOnlyModifier: false, diagnostics: diagnostics); _lazyIsVararg = (arglistToken.Kind() == SyntaxKind.ArgListKeyword); _lazyReturnType = TypeWithAnnotations.Create(bodyBinder.GetSpecialType(SpecialType.System_Void, diagnostics, syntax)); var location = this.Locations[0]; // Don't report ERR_StaticConstParam 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 (MethodKind == MethodKind.StaticConstructor && (_lazyParameters.Length != 0) && ContainingType.Name == ((ConstructorDeclarationSyntax)this.SyntaxNode).Identifier.ValueText) { diagnostics.Add(ErrorCode.ERR_StaticConstParam, location, this); } this.CheckEffectiveAccessibility(_lazyReturnType, _lazyParameters, diagnostics); this.CheckFileTypeUsage(_lazyReturnType, _lazyParameters, diagnostics); if (_lazyIsVararg && (IsGenericMethod || ContainingType.IsGenericType || _lazyParameters.Length > 0 && _lazyParameters[_lazyParameters.Length - 1].IsParams)) { diagnostics.Add(ErrorCode.ERR_BadVarargs, location); } }
internal sealed override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { // Check constraints on return type and parameters. Note: Dev10 uses the // method name location for any such errors. We'll do the same for return // type errors but for parameter errors, we'll use the parameter location. this.ReturnType.CheckAllConstraints(conversions, this.Locations[0], diagnostics); foreach (var parameter in this.Parameters) { parameter.Type.CheckAllConstraints(conversions, parameter.Locations[0], diagnostics); } ParameterHelpers.EnsureIsReadOnlyAttributeExists(Parameters, diagnostics, modifyCompilationForRefReadOnly: true); }
private void ComputeParameters() { if (_lazyParameters != null) { return; } SyntaxToken arglistToken; var diagnostics = DiagnosticBag.GetInstance(); var parameters = ParameterHelpers.MakeParameters( _binder, this, _syntax.ParameterList, arglistToken: out arglistToken, allowRefOrOut: true, allowThis: true, addRefReadOnlyModifier: false, diagnostics: diagnostics); ParameterHelpers.EnsureIsReadOnlyAttributeExists(parameters, diagnostics, modifyCompilationForRefReadOnly: false); var isVararg = arglistToken.Kind() == SyntaxKind.ArgListKeyword; if (isVararg) { diagnostics.Add(ErrorCode.ERR_IllegalVarArgs, arglistToken.GetLocation()); } if (IsAsync) { SourceOrdinaryMethodSymbol.ReportAsyncParameterErrors(parameters, diagnostics, this.Locations[0]); } lock (_declarationDiagnostics) { if (_lazyParameters != null) { diagnostics.Free(); return; } _declarationDiagnostics.AddRangeAndFree(diagnostics); _lazyIsVarArg = isVararg; _lazyParameters = parameters; } }
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, BindingDiagnosticBag diagnostics) { base.AfterAddingTypeMembersChecks(conversions, diagnostics); var location = ReturnTypeLocation; var compilation = DeclaringCompilation; Debug.Assert(location != null); // Check constraints on return type and parameters. Note: Dev10 uses the // method name location for any such errors. We'll do the same for return // type errors but for parameter errors, we'll use the parameter location. CheckConstraintsForExplicitInterfaceType(conversions, diagnostics); this.ReturnType.CheckAllConstraints(compilation, conversions, this.Locations[0], diagnostics); foreach (var parameter in this.Parameters) { parameter.Type.CheckAllConstraints(compilation, conversions, parameter.Locations[0], diagnostics); } PartialMethodChecks(diagnostics); if (RefKind == RefKind.RefReadOnly) { compilation.EnsureIsReadOnlyAttributeExists(diagnostics, location, modifyCompilation: true); } ParameterHelpers.EnsureIsReadOnlyAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); if (compilation.ShouldEmitNativeIntegerAttributes(ReturnType)) { compilation.EnsureNativeIntegerAttributeExists(diagnostics, location, modifyCompilation: true); } ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); ParameterHelpers.EnsureLifetimeAnnotationAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); if (compilation.ShouldEmitNullableAttributes(this) && ReturnTypeWithAnnotations.NeedsNullableAttribute()) { compilation.EnsureNullableAttributeExists(diagnostics, location, modifyCompilation: true); } ParameterHelpers.EnsureNullableAttributeExists(compilation, this, Parameters, diagnostics, modifyCompilation: true); }
private void ComputeParameters() { if (!_parameters.IsDefault) { return; } var diagnostics = DiagnosticBag.GetInstance(); SyntaxToken arglistToken; _parameters = ParameterHelpers.MakeParameters(_binder, this, _syntax.ParameterList, true, out arglistToken, diagnostics, true); _isVararg = (arglistToken.Kind() == SyntaxKind.ArgListKeyword); if (diagnostics.IsEmptyWithoutResolution) { SourceMemberMethodSymbol.ReportAsyncParameterErrors(this, diagnostics, this.Locations[0]); } AddDiagnostics(diagnostics.ToReadOnlyAndFree()); }
internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder <SynthesizedAttributeData> attributes) { // Emit [Dynamic] on synthesized parameter symbols when the original parameter was dynamic // in order to facilitate debugging. In the case the necessary attributes are missing // this is a no-op. Emitting an error here, or when the original parameter was bound, would // adversely effect the compilation or potentially change overload resolution. var compilation = this.DeclaringCompilation; var type = this.TypeWithAnnotations; if (type.Type.ContainsDynamic() && compilation.HasDynamicEmitAttributes(BindingDiagnosticBag.Discarded, Location.None) && compilation.CanEmitBoolean()) { AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDynamicAttribute(type.Type, type.CustomModifiers.Length + this.RefCustomModifiers.Length, this.RefKind)); } if (compilation.ShouldEmitNativeIntegerAttributes(type.Type)) { AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNativeIntegerAttribute(this, type.Type)); } if (ParameterHelpers.RequiresLifetimeAnnotationAttribute(this)) { AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeLifetimeAnnotationAttribute(this, Scope)); } if (type.Type.ContainsTupleNames() && compilation.HasTupleNamesAttributes(BindingDiagnosticBag.Discarded, Location.None) && compilation.CanEmitSpecialType(SpecialType.System_String)) { AddSynthesizedAttribute(ref attributes, compilation.SynthesizeTupleNamesAttribute(type.Type)); } if (compilation.ShouldEmitNullableAttributes(this)) { AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNullableAttributeIfNecessary(this, GetNullableContextValue(), type)); } if (this.RefKind == RefKind.RefReadOnly) { AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeIsReadOnlyAttribute(this)); } }
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { var syntax = (DelegateDeclarationSyntax)SyntaxRef.GetSyntax(); var location = syntax.ReturnType.GetLocation(); Debug.Assert(location != null); base.AfterAddingTypeMembersChecks(conversions, diagnostics); if (_refKind == RefKind.RefReadOnly) { DeclaringCompilation.EnsureIsReadOnlyAttributeExists(diagnostics, location, modifyCompilation: true); } ParameterHelpers.EnsureIsReadOnlyAttributeExists(Parameters, diagnostics, modifyCompilation: true); if (ReturnType.NeedsNullableAttribute()) { this.DeclaringCompilation.EnsureNullableAttributeExists(diagnostics, location, modifyCompilation: true); } ParameterHelpers.EnsureNullableAttributeExists(Parameters, diagnostics, modifyCompilation: true); }
private void MethodChecks(MethodDeclarationSyntax syntax, Binder withTypeParamsBinder, DiagnosticBag diagnostics) { SyntaxToken arglistToken; // Constraint checking for parameter and return types must be delayed until // the method has been added to the containing type member list since // evaluating the constraints may depend on accessing this method from // the container (comparing this method to others to find overrides for // instance). Constraints are checked in AfterAddingTypeMembersChecks. var signatureBinder = withTypeParamsBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.SuppressConstraintChecks, this); _lazyParameters = ParameterHelpers.MakeParameters(signatureBinder, this, syntax.ParameterList, true, out arglistToken, diagnostics, false); _lazyIsVararg = (arglistToken.Kind() == SyntaxKind.ArgListKeyword); RefKind refKind; var returnTypeSyntax = syntax.ReturnType.SkipRef(out refKind); _lazyReturnType = signatureBinder.BindType(returnTypeSyntax, diagnostics); if (_lazyReturnType.IsRestrictedType()) { if (_lazyReturnType.SpecialType == SpecialType.System_TypedReference && (this.ContainingType.SpecialType == SpecialType.System_TypedReference || this.ContainingType.SpecialType == SpecialType.System_ArgIterator)) { // Two special cases: methods in the special types TypedReference and ArgIterator are allowed to return TypedReference } else { // Method or delegate cannot return type '{0}' diagnostics.Add(ErrorCode.ERR_MethodReturnCantBeRefAny, syntax.ReturnType.Location, _lazyReturnType); } } var returnsVoid = _lazyReturnType.SpecialType == SpecialType.System_Void; if (this.RefKind != RefKind.None && returnsVoid) { Debug.Assert(returnTypeSyntax.HasErrors); } // set ReturnsVoid flag this.SetReturnsVoid(returnsVoid); var location = this.Locations[0]; this.CheckEffectiveAccessibility(_lazyReturnType, _lazyParameters, diagnostics); // Checks taken from MemberDefiner::defineMethod if (this.Name == WellKnownMemberNames.DestructorName && this.ParameterCount == 0 && this.Arity == 0 && this.ReturnsVoid) { diagnostics.Add(ErrorCode.WRN_FinalizeMethod, location); } // errors relevant for extension methods if (IsExtensionMethod) { var parameter0Type = this.Parameters[0].Type; if (!parameter0Type.IsValidExtensionParameterType()) { // Duplicate Dev10 behavior by selecting the parameter type. var parameterSyntax = syntax.ParameterList.Parameters[0]; Debug.Assert(parameterSyntax.Type != null); var loc = parameterSyntax.Type.Location; diagnostics.Add(ErrorCode.ERR_BadTypeforThis, loc, parameter0Type); } else if ((object)ContainingType.ContainingType != null) { diagnostics.Add(ErrorCode.ERR_ExtensionMethodsDecl, location, ContainingType.Name); } else if (!ContainingType.IsScriptClass && !(ContainingType.IsStatic && ContainingType.Arity == 0)) { // Duplicate Dev10 behavior by selecting the containing type identifier. However if there // is no containing type (in the interactive case for instance), select the method identifier. var typeDecl = syntax.Parent as TypeDeclarationSyntax; var identifier = (typeDecl != null) ? typeDecl.Identifier : syntax.Identifier; var loc = identifier.GetLocation(); diagnostics.Add(ErrorCode.ERR_BadExtensionAgg, loc); } else if (!IsStatic) { diagnostics.Add(ErrorCode.ERR_BadExtensionMeth, location); } else { // Verify ExtensionAttribute is available. var attributeConstructor = withTypeParamsBinder.Compilation.GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_ExtensionAttribute__ctor); if ((object)attributeConstructor == null) { var memberDescriptor = WellKnownMembers.GetDescriptor(WellKnownMember.System_Runtime_CompilerServices_ExtensionAttribute__ctor); // do not use Binder.ReportUseSiteErrorForAttributeCtor in this case, because we'll need to report a special error id, not a generic use site error. diagnostics.Add( ErrorCode.ERR_ExtensionAttrNotFound, syntax.ParameterList.Parameters[0].Modifiers.FirstOrDefault(SyntaxKind.ThisKeyword).GetLocation(), memberDescriptor.DeclaringTypeMetadataName); } } } if (this.MethodKind == MethodKind.UserDefinedOperator) { foreach (var p in this.Parameters) { if (p.RefKind != RefKind.None) { diagnostics.Add(ErrorCode.ERR_IllegalRefParam, location); break; } } } else if (IsPartial) { // check that there are no out parameters in a partial foreach (var p in this.Parameters) { if (p.RefKind == RefKind.Out) { diagnostics.Add(ErrorCode.ERR_PartialMethodCannotHaveOutParameters, location); break; } } if (MethodKind == MethodKind.ExplicitInterfaceImplementation) { diagnostics.Add(ErrorCode.ERR_PartialMethodNotExplicit, location); } if (!ContainingType.IsPartial() || ContainingType.IsInterface) { diagnostics.Add(ErrorCode.ERR_PartialMethodOnlyInPartialClass, location); } } if (!IsPartial) { LazyAsyncMethodChecks(CancellationToken.None); Debug.Assert(state.HasComplete(CompletionPart.FinishAsyncMethodChecks)); } // The runtime will not treat this method as an override or implementation of another // method unless both the signatures and the custom modifiers match. Hence, in the // case of overrides and *explicit* implementations, we need to copy the custom modifiers // that are in the signature of the overridden/implemented method. (From source, we know // that there can only be one such method, so there are no conflicts.) This is // unnecessary for implicit implementations because, if the custom modifiers don't match, // we'll insert a bridge method (an explicit implementation that delegates to the implicit // implementation) with the correct custom modifiers // (see SourceNamedTypeSymbol.ImplementInterfaceMember). // Note: we're checking if the syntax indicates explicit implementation rather, // than if explicitInterfaceType is null because we don't want to look for an // overridden property if this is supposed to be an explicit implementation. if (syntax.ExplicitInterfaceSpecifier == null) { Debug.Assert(_lazyExplicitInterfaceImplementations.IsDefault); _lazyExplicitInterfaceImplementations = ImmutableArray <MethodSymbol> .Empty; // This value may not be correct, but we need something while we compute this.OverriddenMethod. // May be re-assigned below. Debug.Assert(_lazyReturnTypeCustomModifiers.IsDefault); Debug.Assert(_lazyCountOfCustomModifiersPrecedingByRef == 0); _lazyReturnTypeCustomModifiers = ImmutableArray <CustomModifier> .Empty; _lazyCountOfCustomModifiersPrecedingByRef = 0; // If this method is an override, we may need to copy custom modifiers from // the overridden method (so that the runtime will recognize it as an override). // We check for this case here, while we can still modify the parameters and // return type without losing the appearance of immutability. if (this.IsOverride) { // This computation will necessarily be performed with partially incomplete // information. There is no way we can determine the complete signature // (i.e. including custom modifiers) until we have found the method that // this method overrides. To accommodate this, MethodSymbol.OverriddenOrHiddenMembers // is written to allow relaxed matching of custom modifiers for source methods, // on the assumption that they will be updated appropriately. MethodSymbol overriddenMethod = this.OverriddenMethod; if ((object)overriddenMethod != null) { CustomModifierUtils.CopyMethodCustomModifiers(overriddenMethod, this, out _lazyReturnType, out _lazyReturnTypeCustomModifiers, out _lazyCountOfCustomModifiersPrecedingByRef, out _lazyParameters, alsoCopyParamsModifier: true); } } } else if ((object)_explicitInterfaceType != null) { //do this last so that it can assume the method symbol is constructed (except for ExplicitInterfaceImplementation) MethodSymbol implementedMethod = this.FindExplicitlyImplementedMethod(_explicitInterfaceType, syntax.Identifier.ValueText, syntax.ExplicitInterfaceSpecifier, diagnostics); if ((object)implementedMethod != null) { Debug.Assert(_lazyExplicitInterfaceImplementations.IsDefault); _lazyExplicitInterfaceImplementations = ImmutableArray.Create <MethodSymbol>(implementedMethod); CustomModifierUtils.CopyMethodCustomModifiers(implementedMethod, this, out _lazyReturnType, out _lazyReturnTypeCustomModifiers, out _lazyCountOfCustomModifiersPrecedingByRef, out _lazyParameters, alsoCopyParamsModifier: false); } else { Debug.Assert(_lazyExplicitInterfaceImplementations.IsDefault); _lazyExplicitInterfaceImplementations = ImmutableArray <MethodSymbol> .Empty; Debug.Assert(_lazyReturnTypeCustomModifiers.IsDefault); Debug.Assert(_lazyCountOfCustomModifiersPrecedingByRef == 0); _lazyReturnTypeCustomModifiers = ImmutableArray <CustomModifier> .Empty; _lazyCountOfCustomModifiersPrecedingByRef = 0; } } CheckModifiers(location, diagnostics); }
protected override void MethodChecks(DiagnosticBag diagnostics) { var binder = this.DeclaringCompilation. GetBinderFactory(syntaxReferenceOpt.SyntaxTree).GetBinder(ReturnTypeSyntax, GetSyntax(), this); SyntaxToken arglistToken; var signatureBinder = binder.WithAdditionalFlags(BinderFlags.SuppressConstraintChecks); _lazyParameters = ParameterHelpers.MakeParameters( signatureBinder, this, ParameterListSyntax, out arglistToken, allowRefOrOut: true, allowThis: false, addRefReadOnlyModifier: false, diagnostics: diagnostics); if (arglistToken.Kind() == SyntaxKind.ArgListKeyword) { // This is a parse-time error in the native compiler; it is a semantic analysis error in Roslyn. // error CS1669: __arglist is not valid in this context diagnostics.Add(ErrorCode.ERR_IllegalVarArgs, new SourceLocation(arglistToken)); // Regardless of whether __arglist appears in the source code, we do not mark // the operator method as being a varargs method. } _lazyReturnType = signatureBinder.BindType(ReturnTypeSyntax, diagnostics); // restricted types cannot be returned. // NOTE: Span-like types can be returned (if expression is returnable). if (_lazyReturnType.IsRestrictedType(ignoreSpanLikeTypes: true)) { // The return type of a method, delegate, or function pointer cannot be '{0}' diagnostics.Add(ErrorCode.ERR_MethodReturnCantBeRefAny, ReturnTypeSyntax.Location, _lazyReturnType.Type); } if (_lazyReturnType.Type.IsStatic) { // '{0}': static types cannot be used as return types diagnostics.Add(ErrorCode.ERR_ReturnTypeIsStaticClass, ReturnTypeSyntax.Location, _lazyReturnType.Type); } this.SetReturnsVoid(_lazyReturnType.IsVoidType()); // If we have a conversion/equality/inequality operator in an interface or static class then we already // have reported that fact as an error. No need to cascade the error further. if ((this.ContainingType.IsInterfaceType() && (MethodKind == MethodKind.Conversion || Name == WellKnownMemberNames.EqualityOperatorName || Name == WellKnownMemberNames.InequalityOperatorName)) || this.ContainingType.IsStatic) { return; } // SPEC: All types referenced in an operator declaration must be at least as accessible // SPEC: as the operator itself. CheckEffectiveAccessibility(_lazyReturnType, _lazyParameters, diagnostics); CheckValueParameters(diagnostics); CheckOperatorSignatures(diagnostics); }
public static SourceParameterSymbol Create( Binder context, Symbol owner, TypeWithAnnotations parameterType, ParameterSyntax syntax, RefKind refKind, SyntaxToken identifier, int ordinal, bool isParams, bool isExtensionMethodThis, bool addRefReadOnlyModifier, DiagnosticBag declarationDiagnostics) { Debug.Assert(!(owner is LambdaSymbol)); // therefore we don't need to deal with discard parameters var name = identifier.ValueText; var locations = ImmutableArray.Create <Location>(new SourceLocation(identifier)); if (isParams) { // touch the constructor in order to generate proper use-site diagnostics Binder.ReportUseSiteDiagnosticForSynthesizedAttribute(context.Compilation, WellKnownMember.System_ParamArrayAttribute__ctor, declarationDiagnostics, identifier.Parent.GetLocation()); } ImmutableArray <CustomModifier> inModifiers = ParameterHelpers.ConditionallyCreateInModifiers(refKind, addRefReadOnlyModifier, context, declarationDiagnostics, syntax); if (!inModifiers.IsDefaultOrEmpty) { return(new SourceComplexParameterSymbolWithCustomModifiersPrecedingByRef( owner, ordinal, parameterType, refKind, inModifiers, name, locations, syntax.GetReference(), isParams, isExtensionMethodThis)); } if (!isParams && !isExtensionMethodThis && (syntax.Default == null) && (syntax.AttributeLists.Count == 0) && !owner.IsPartialMethod()) { return(new SourceSimpleParameterSymbol(owner, parameterType, ordinal, refKind, name, isDiscard: false, locations)); } return(new SourceComplexParameterSymbol( owner, ordinal, parameterType, refKind, name, locations, syntax.GetReference(), isParams, isExtensionMethodThis)); }