2 // method.cs: Method based declarations
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@ximian.com)
6 // Marek Safar (marek.safar@gmail.com)
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004-2008 Novell, Inc
15 using System
.Collections
.Generic
;
16 using System
.Reflection
;
17 using System
.Reflection
.Emit
;
18 using System
.Runtime
.CompilerServices
;
19 using System
.Runtime
.InteropServices
;
20 using System
.Security
;
21 using System
.Security
.Permissions
;
26 using XmlElement
= System
.Object
;
31 using Mono
.CompilerServices
.SymbolWriter
;
33 namespace Mono
.CSharp
{
35 public abstract class MethodCore
: InterfaceMemberBase
, IParametersMember
37 protected ParametersCompiled parameters
;
38 protected ToplevelBlock block
;
39 protected MethodSpec spec
;
41 public MethodCore (DeclSpace parent
, GenericMethod generic
,
42 FullNamedExpression type
, Modifiers mod
, Modifiers allowed_mod
,
43 MemberName name
, Attributes attrs
, ParametersCompiled parameters
)
44 : base (parent
, generic
, type
, mod
, allowed_mod
, name
, attrs
)
46 this.parameters
= parameters
;
50 // Returns the System.Type array for the parameters of this method
52 public TypeSpec
[] ParameterTypes
{
54 return parameters
.Types
;
58 public ParametersCompiled ParameterInfo
{
64 AParametersCollection IParametersMember
.Parameters
{
65 get { return parameters; }
68 public ToplevelBlock Block
{
78 public CallingConventions CallingConventions
{
80 CallingConventions cc
= parameters
.CallingConvention
;
82 if ((ModFlags
& Modifiers
.STATIC
) == 0)
83 cc
|= CallingConventions
.HasThis
;
85 // FIXME: How is `ExplicitThis' used in C#?
91 protected override bool CheckOverrideAgainstBase (MemberSpec base_member
)
93 bool res
= base.CheckOverrideAgainstBase (base_member
);
96 // Check that the permissions are not being changed
98 if (!CheckAccessModifiers (this, base_member
)) {
99 Error_CannotChangeAccessModifiers (this, base_member
);
106 protected override bool CheckBase ()
108 // Check whether arguments were correct.
109 if (!DefineParameters (parameters
))
112 return base.CheckBase ();
116 // Returns a string that represents the signature for this
117 // member which should be used in XML documentation.
119 public override string GetDocCommentName (DeclSpace ds
)
121 return DocUtil
.GetMethodDocCommentName (this, parameters
, ds
);
125 // Raised (and passed an XmlElement that contains the comment)
126 // when GenerateDocComment is writing documentation expectedly.
128 // FIXME: with a few effort, it could be done with XmlReader,
129 // that means removal of DOM use.
131 internal override void OnGenerateDocComment (XmlElement el
)
133 DocUtil
.OnMethodGenerateDocComment (this, el
, Report
);
137 // Represents header string for documentation comment.
139 public override string DocCommentHeader
144 public override bool EnableOverloadChecks (MemberCore overload
)
146 if (overload
is MethodCore
) {
147 caching_flags
|= Flags
.MethodOverloadsExist
;
151 if (overload
is AbstractPropertyEventMethod
)
154 return base.EnableOverloadChecks (overload
);
157 public MethodSpec Spec
{
161 protected override bool VerifyClsCompliance ()
163 if (!base.VerifyClsCompliance ())
166 if (parameters
.HasArglist
) {
167 Report
.Warning (3000, 1, Location
, "Methods with variable arguments are not CLS-compliant");
170 if (member_type
!= null && !member_type
.IsCLSCompliant ()) {
171 Report
.Warning (3002, 1, Location
, "Return type of `{0}' is not CLS-compliant",
172 GetSignatureForError ());
175 parameters
.VerifyClsCompliance (this);
180 public interface IGenericMethodDefinition
: IMemberDefinition
182 TypeParameterSpec
[] TypeParameters { get; }
183 int TypeParametersCount { get; }
185 // MethodInfo MakeGenericMethod (TypeSpec[] targs);
188 public class MethodSpec
: MemberSpec
, IParametersMember
191 AParametersCollection parameters
;
195 TypeParameterSpec
[] constraints
;
197 public MethodSpec (MemberKind kind
, TypeSpec declaringType
, IMemberDefinition details
, TypeSpec returnType
,
198 MethodBase info
, AParametersCollection parameters
, Modifiers modifiers
)
199 : base (kind
, declaringType
, details
, modifiers
)
201 this.metaInfo
= info
;
202 this.parameters
= parameters
;
203 this.returnType
= returnType
;
208 public override int Arity
{
210 return IsGeneric
? GenericDefinition
.TypeParametersCount
: 0;
214 public TypeParameterSpec
[] Constraints
{
216 if (constraints
== null && IsGeneric
)
217 constraints
= GenericDefinition
.TypeParameters
;
223 public bool IsConstructor
{
225 return Kind
== MemberKind
.Constructor
;
229 public IGenericMethodDefinition GenericDefinition
{
231 return (IGenericMethodDefinition
) definition
;
235 public bool IsExtensionMethod
{
237 return IsStatic
&& parameters
.HasExtensionMethodType
;
241 public bool IsSealed
{
243 return (Modifiers
& Modifiers
.SEALED
) != 0;
247 // When is virtual or abstract
248 public bool IsVirtual
{
250 return (Modifiers
& (Modifiers
.VIRTUAL
| Modifiers
.ABSTRACT
| Modifiers
.OVERRIDE
)) != 0;
254 public bool IsReservedMethod
{
256 return Kind
== MemberKind
.Operator
|| IsAccessor
;
260 TypeSpec IInterfaceMemberSpec
.MemberType
{
266 public AParametersCollection Parameters
{
272 public TypeSpec ReturnType
{
278 public TypeSpec
[] TypeArguments
{
286 public MethodSpec
GetGenericMethodDefinition ()
288 if (!IsGeneric
&& !DeclaringType
.IsGeneric
)
291 return MemberCache
.GetMember (declaringType
, this);
294 public MethodBase
GetMetaInfo ()
296 if ((state
& StateFlags
.PendingMetaInflate
) != 0) {
297 if (DeclaringType
.IsTypeBuilder
) {
299 metaInfo
= TypeBuilder
.GetConstructor (DeclaringType
.GetMetaInfo (), (ConstructorInfo
) metaInfo
);
301 metaInfo
= TypeBuilder
.GetMethod (DeclaringType
.GetMetaInfo (), (MethodInfo
) metaInfo
);
303 metaInfo
= MethodInfo
.GetMethodFromHandle (metaInfo
.MethodHandle
, DeclaringType
.GetMetaInfo ().TypeHandle
);
306 state
&= ~StateFlags
.PendingMetaInflate
;
309 if ((state
& StateFlags
.PendingMakeMethod
) != 0) {
310 metaInfo
= ((MethodInfo
) metaInfo
).MakeGenericMethod (targs
.Select (l
=> l
.GetMetaInfo ()).ToArray ());
311 state
&= ~StateFlags
.PendingMakeMethod
;
317 public override string GetSignatureForError ()
321 name
= DeclaringType
.GetSignatureForError () + "." + DeclaringType
.Name
;
322 } else if (Kind
== MemberKind
.Operator
) {
323 var op
= Operator
.GetType (Name
).Value
;
324 if (op
== Operator
.OpType
.Implicit
|| op
== Operator
.OpType
.Explicit
) {
325 name
= DeclaringType
.GetSignatureForError () + "." + Operator
.GetName (op
) + " operator " + returnType
.GetSignatureForError ();
327 name
= DeclaringType
.GetSignatureForError () + ".operator " + Operator
.GetName (op
);
329 } else if (IsAccessor
) {
330 int split
= Name
.IndexOf ('_');
331 name
= Name
.Substring (split
+ 1);
332 var postfix
= Name
.Substring (0, split
);
334 var pc
= parameters
.Count
;
335 if (pc
> 0 && postfix
== "get") {
336 name
= "this" + parameters
.GetSignatureForError ("[", "]", pc
);
337 } else if (pc
> 1 && postfix
== "set") {
338 name
= "this" + parameters
.GetSignatureForError ("[", "]", pc
- 1);
342 return DeclaringType
.GetSignatureForError () + "." + name
+ "." + postfix
;
344 name
= base.GetSignatureForError ();
346 name
+= "<" + TypeManager
.CSharpName (targs
) + ">";
348 name
+= "<" + TypeManager
.CSharpName (GenericDefinition
.TypeParameters
) + ">";
351 return name
+ parameters
.GetSignatureForError ();
354 public override MemberSpec
InflateMember (TypeParameterInflator inflator
)
356 var ms
= (MethodSpec
) base.InflateMember (inflator
);
357 ms
.returnType
= inflator
.Inflate (returnType
);
358 ms
.parameters
= parameters
.Inflate (inflator
);
360 ms
.constraints
= TypeParameterSpec
.InflateConstraints (inflator
, GenericDefinition
.TypeParameters
);
365 public MethodSpec
MakeGenericMethod (params TypeSpec
[] targs
)
368 throw new ArgumentNullException ();
370 // if (generic_intances != null && generic_intances.TryGetValue (targs, out ginstance))
373 //if (generic_intances == null)
374 // generic_intances = new Dictionary<TypeSpec[], Method> (TypeSpecArrayComparer.Default);
376 var inflator
= new TypeParameterInflator (DeclaringType
, GenericDefinition
.TypeParameters
, targs
);
378 var inflated
= (MethodSpec
) MemberwiseClone ();
379 inflated
.declaringType
= inflator
.TypeInstance
;
380 inflated
.returnType
= inflator
.Inflate (returnType
);
381 inflated
.parameters
= parameters
.Inflate (inflator
);
382 inflated
.targs
= targs
;
383 inflated
.constraints
= TypeParameterSpec
.InflateConstraints (inflator
, constraints
?? GenericDefinition
.TypeParameters
);
384 inflated
.state
|= StateFlags
.PendingMakeMethod
;
386 // if (inflated.parent == null)
387 // inflated.parent = parent;
389 //generic_intances.Add (targs, inflated);
393 public MethodSpec
Mutate (TypeParameterMutator mutator
)
395 var targs
= TypeArguments
;
397 targs
= mutator
.Mutate (targs
);
399 var decl
= DeclaringType
;
400 if (DeclaringType
.IsGenericOrParentIsGeneric
) {
401 decl
= mutator
.Mutate (decl
);
404 if (targs
== TypeArguments
&& decl
== DeclaringType
)
407 var ms
= (MethodSpec
) MemberwiseClone ();
408 if (decl
!= DeclaringType
) {
409 // Gets back MethodInfo in case of metaInfo was inflated
410 ms
.metaInfo
= MemberCache
.GetMember (DeclaringType
.GetDefinition (), this).metaInfo
;
412 ms
.declaringType
= decl
;
413 ms
.state
|= StateFlags
.PendingMetaInflate
;
418 ms
.state
|= StateFlags
.PendingMakeMethod
;
424 public void SetMetaInfo (MethodInfo info
)
426 if (this.metaInfo
!= null)
427 throw new InternalErrorException ("MetaInfo reset");
429 this.metaInfo
= info
;
433 public abstract class MethodOrOperator
: MethodCore
, IMethodData
435 public MethodBuilder MethodBuilder
;
436 ReturnParameter return_attributes
;
437 Dictionary
<SecurityAction
, PermissionSet
> declarative_security
;
438 protected MethodData MethodData
;
440 static string[] attribute_targets
= new string [] { "method", "return" }
;
442 protected MethodOrOperator (DeclSpace parent
, GenericMethod generic
, FullNamedExpression type
, Modifiers mod
,
443 Modifiers allowed_mod
, MemberName name
,
444 Attributes attrs
, ParametersCompiled parameters
)
445 : base (parent
, generic
, type
, mod
, allowed_mod
, name
,
450 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
452 if (a
.Target
== AttributeTargets
.ReturnValue
) {
453 if (return_attributes
== null)
454 return_attributes
= new ReturnParameter (this, MethodBuilder
, Location
);
456 return_attributes
.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
460 if (a
.IsInternalMethodImplAttribute
) {
461 is_external_implementation
= true;
464 if (a
.Type
== pa
.DllImport
) {
465 const Modifiers extern_static
= Modifiers
.EXTERN
| Modifiers
.STATIC
;
466 if ((ModFlags
& extern_static
) != extern_static
) {
467 Report
.Error (601, a
.Location
, "The DllImport attribute must be specified on a method marked `static' and `extern'");
469 is_external_implementation
= true;
472 if (a
.IsValidSecurityAttribute ()) {
473 if (declarative_security
== null)
474 declarative_security
= new Dictionary
<SecurityAction
, PermissionSet
> ();
475 a
.ExtractSecurityPermissionSet (declarative_security
);
479 if (MethodBuilder
!= null)
480 MethodBuilder
.SetCustomAttribute ((ConstructorInfo
) ctor
.GetMetaInfo (), cdata
);
483 public override AttributeTargets AttributeTargets
{
485 return AttributeTargets
.Method
;
489 protected override bool CheckForDuplications ()
491 return Parent
.MemberCache
.CheckExistingMembersOverloads (this, parameters
);
494 public virtual EmitContext
CreateEmitContext (ILGenerator ig
)
496 return new EmitContext (this, ig
, MemberType
);
499 public override bool Define ()
508 if (this is Operator
)
509 kind
= MemberKind
.Operator
;
510 else if (this is Destructor
)
511 kind
= MemberKind
.Destructor
;
513 kind
= MemberKind
.Method
;
515 if (IsPartialDefinition
) {
516 caching_flags
&= ~Flags
.Excluded_Undetected
;
517 caching_flags
|= Flags
.Excluded
;
519 // Add to member cache only when a partial method implementation has not been found yet
520 if ((caching_flags
& Flags
.PartialDefinitionExists
) == 0) {
521 // MethodBase mb = new PartialMethodDefinitionInfo (this);
523 spec
= new MethodSpec (kind
, Parent
.Definition
, this, ReturnType
, null, parameters
, ModFlags
);
524 Parent
.MemberCache
.AddMember (spec
);
530 MethodData
= new MethodData (
531 this, ModFlags
, flags
, this, MethodBuilder
, GenericMethod
, base_method
);
533 if (!MethodData
.Define (Parent
.PartialContainer
, GetFullName (MemberName
), Report
))
536 MethodBuilder
= MethodData
.MethodBuilder
;
538 spec
= new MethodSpec (kind
, Parent
.Definition
, this, ReturnType
, MethodBuilder
, parameters
, ModFlags
);
539 if (MemberName
.Arity
> 0)
540 spec
.IsGeneric
= true;
542 Parent
.MemberCache
.AddMember (this, MethodBuilder
.Name
, spec
);
547 protected override void DoMemberTypeIndependentChecks ()
549 base.DoMemberTypeIndependentChecks ();
551 CheckAbstractAndExtern (block
!= null);
553 if ((ModFlags
& Modifiers
.PARTIAL
) != 0) {
554 for (int i
= 0; i
< parameters
.Count
; ++i
) {
555 IParameterData p
= parameters
.FixedParameters
[i
];
556 if (p
.ModFlags
== Parameter
.Modifier
.OUT
) {
557 Report
.Error (752, Location
, "`{0}': A partial method parameters cannot use `out' modifier",
558 GetSignatureForError ());
561 if (p
.HasDefaultValue
&& IsPartialImplementation
)
562 ((Parameter
) p
).Warning_UselessOptionalParameter (Report
);
567 protected override void DoMemberTypeDependentChecks ()
569 base.DoMemberTypeDependentChecks ();
571 if (MemberType
.IsStatic
) {
572 Error_StaticReturnType ();
576 public override void Emit ()
578 if ((ModFlags
& Modifiers
.COMPILER_GENERATED
) != 0 && !Parent
.IsCompilerGenerated
)
579 PredefinedAttributes
.Get
.CompilerGenerated
.EmitAttribute (MethodBuilder
);
580 if ((ModFlags
& Modifiers
.DEBUGGER_HIDDEN
) != 0)
581 PredefinedAttributes
.Get
.DebuggerHidden
.EmitAttribute (MethodBuilder
);
583 if (ReturnType
== InternalType
.Dynamic
) {
584 return_attributes
= new ReturnParameter (this, MethodBuilder
, Location
);
585 PredefinedAttributes
.Get
.Dynamic
.EmitAttribute (return_attributes
.Builder
);
587 var trans_flags
= TypeManager
.HasDynamicTypeUsed (ReturnType
);
588 if (trans_flags
!= null) {
589 var pa
= PredefinedAttributes
.Get
.DynamicTransform
;
590 if (pa
.Constructor
!= null || pa
.ResolveConstructor (Location
, ArrayContainer
.MakeType (TypeManager
.bool_type
))) {
591 return_attributes
= new ReturnParameter (this, MethodBuilder
, Location
);
592 return_attributes
.Builder
.SetCustomAttribute (
593 new CustomAttributeBuilder (pa
.Constructor
, new object [] { trans_flags }
));
598 if (OptAttributes
!= null)
599 OptAttributes
.Emit ();
601 if (declarative_security
!= null) {
602 foreach (var de
in declarative_security
) {
603 MethodBuilder
.AddDeclarativeSecurity (de
.Key
, de
.Value
);
607 if (MethodData
!= null)
608 MethodData
.Emit (Parent
);
616 protected void Error_ConditionalAttributeIsNotValid ()
618 Report
.Error (577, Location
,
619 "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
620 GetSignatureForError ());
623 public bool IsPartialDefinition
{
625 return (ModFlags
& Modifiers
.PARTIAL
) != 0 && Block
== null;
629 public bool IsPartialImplementation
{
631 return (ModFlags
& Modifiers
.PARTIAL
) != 0 && Block
!= null;
635 public override string[] ValidAttributeTargets
{
637 return attribute_targets
;
641 #region IMethodData Members
643 public TypeSpec ReturnType
{
649 public MemberName MethodName
{
656 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
658 public override string[] ConditionalConditions ()
660 if ((caching_flags
& (Flags
.Excluded_Undetected
| Flags
.Excluded
)) == 0)
663 if ((ModFlags
& Modifiers
.PARTIAL
) != 0 && (caching_flags
& Flags
.Excluded
) != 0)
664 return new string [0];
666 caching_flags
&= ~Flags
.Excluded_Undetected
;
669 if (base_method
== null) {
670 if (OptAttributes
== null)
673 Attribute
[] attrs
= OptAttributes
.SearchMulti (PredefinedAttributes
.Get
.Conditional
);
677 conditions
= new string[attrs
.Length
];
678 for (int i
= 0; i
< conditions
.Length
; ++i
)
679 conditions
[i
] = attrs
[i
].GetConditionalAttributeValue ();
681 conditions
= base_method
.MemberDefinition
.ConditionalConditions();
684 if (conditions
!= null)
685 caching_flags
|= Flags
.Excluded
;
690 GenericMethod IMethodData
.GenericMethod
{
692 return GenericMethod
;
696 public virtual void EmitExtraSymbolInfo (SourceMethod source
)
703 public class SourceMethod
: IMethodDef
706 SourceMethodBuilder builder
;
708 protected SourceMethod (DeclSpace parent
, MethodBase method
, ICompileUnit file
)
710 this.method
= method
;
712 builder
= SymbolWriter
.OpenMethod (file
, parent
.NamespaceEntry
.SymbolFileID
, this);
716 get { return method.Name; }
721 if (method
is MethodBuilder
)
722 return ((MethodBuilder
) method
).GetToken ().Token
;
723 else if (method
is ConstructorBuilder
)
724 return ((ConstructorBuilder
) method
).GetToken ().Token
;
726 throw new NotSupportedException ();
730 public void CloseMethod ()
732 SymbolWriter
.CloseMethod ();
735 public void SetRealMethodName (string name
)
738 builder
.SetRealMethodName (name
);
741 public static SourceMethod
Create (DeclSpace parent
, MethodBase method
, Block block
)
743 if (!SymbolWriter
.HasSymbolWriter
)
748 Location start_loc
= block
.StartLocation
;
749 if (start_loc
.IsNull
)
752 ICompileUnit compile_unit
= start_loc
.CompilationUnit
;
753 if (compile_unit
== null)
756 return new SourceMethod (parent
, method
, compile_unit
);
760 public class Method
: MethodOrOperator
, IGenericMethodDefinition
763 /// Modifiers allowed in a class declaration
765 const Modifiers AllowedModifiers
=
768 Modifiers
.PROTECTED
|
779 const Modifiers AllowedInterfaceModifiers
=
780 Modifiers
.NEW
| Modifiers
.UNSAFE
;
782 Method partialMethodImplementation
;
784 public Method (DeclSpace parent
, GenericMethod generic
,
785 FullNamedExpression return_type
, Modifiers mod
,
786 MemberName name
, ParametersCompiled parameters
, Attributes attrs
)
787 : base (parent
, generic
, return_type
, mod
,
788 parent
.PartialContainer
.Kind
== MemberKind
.Interface
? AllowedInterfaceModifiers
: AllowedModifiers
,
789 name
, attrs
, parameters
)
793 protected Method (DeclSpace parent
, FullNamedExpression return_type
, Modifiers mod
, Modifiers amod
,
794 MemberName name
, ParametersCompiled parameters
, Attributes attrs
)
795 : base (parent
, null, return_type
, mod
, amod
, name
, attrs
, parameters
)
801 public override TypeParameter
[] CurrentTypeParameters
{
803 if (GenericMethod
!= null)
804 return GenericMethod
.CurrentTypeParameters
;
810 public override bool HasUnresolvedConstraints
{
812 if (CurrentTypeParameters
== null)
815 // When overriding base method constraints are fetched from
816 // base method but to find it we have to resolve parameters
817 // to find exact base method match
818 if (IsExplicitImpl
|| (ModFlags
& Modifiers
.OVERRIDE
) != 0)
819 return base_method
== null;
821 // Even for non-override generic method constraints check has to be
822 // delayed after all constraints are resolved
827 public TypeParameterSpec
[] TypeParameters
{
829 return CurrentTypeParameters
.Select (l
=> l
.Type
).ToArray ();
833 public int TypeParametersCount
{
835 return CurrentTypeParameters
== null ? 0 : CurrentTypeParameters
.Length
;
841 public override string GetSignatureForError()
843 return base.GetSignatureForError () + parameters
.GetSignatureForError ();
846 void Error_DuplicateEntryPoint (Method b
)
848 Report
.Error (17, b
.Location
,
849 "Program `{0}' has more than one entry point defined: `{1}'",
850 CodeGen
.FileName
, b
.GetSignatureForError ());
855 if (ReturnType
!= TypeManager
.void_type
&&
856 ReturnType
!= TypeManager
.int32_type
)
859 if (parameters
.IsEmpty
)
862 if (parameters
.Count
> 1)
865 var ac
= parameters
.Types
[0] as ArrayContainer
;
866 return ac
!= null && ac
.Rank
== 1 && ac
.Element
== TypeManager
.string_type
&&
867 (parameters
[0].ModFlags
& ~Parameter
.Modifier
.PARAMS
) == Parameter
.Modifier
.NONE
;
870 public override FullNamedExpression
LookupNamespaceOrType (string name
, int arity
, Location loc
, bool ignore_cs0104
)
873 TypeParameter
[] tp
= CurrentTypeParameters
;
875 TypeParameter t
= TypeParameter
.FindTypeParameter (tp
, name
);
877 return new TypeParameterExpr (t
, loc
);
881 return base.LookupNamespaceOrType (name
, arity
, loc
, ignore_cs0104
);
884 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
886 if (a
.Type
== pa
.Conditional
) {
887 if (IsExplicitImpl
) {
888 Error_ConditionalAttributeIsNotValid ();
892 if (ReturnType
!= TypeManager
.void_type
) {
893 Report
.Error (578, Location
, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ());
897 if ((ModFlags
& Modifiers
.OVERRIDE
) != 0) {
898 Report
.Error (243, Location
, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ());
903 Report
.Error (582, Location
, "Conditional not valid on interface members");
907 if (MethodData
.implementing
!= null) {
908 Report
.SymbolRelatedToPreviousError (MethodData
.implementing
.DeclaringType
);
909 Report
.Error (629, Location
, "Conditional member `{0}' cannot implement interface member `{1}'",
910 GetSignatureForError (), TypeManager
.CSharpSignature (MethodData
.implementing
));
914 for (int i
= 0; i
< parameters
.Count
; ++i
) {
915 if (parameters
.FixedParameters
[i
].ModFlags
== Parameter
.Modifier
.OUT
) {
916 Report
.Error (685, Location
, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
922 if (a
.Type
== pa
.Extension
) {
923 a
.Error_MisusedExtensionAttribute ();
927 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
930 protected virtual void DefineTypeParameters ()
932 var tparams
= CurrentTypeParameters
;
934 TypeParameterSpec
[] base_tparams
= null;
935 TypeParameterSpec
[] base_decl_tparams
= TypeParameterSpec
.EmptyTypes
;
936 TypeSpec
[] base_targs
= TypeSpec
.EmptyTypes
;
937 if (((ModFlags
& Modifiers
.OVERRIDE
) != 0 || IsExplicitImpl
)) {
938 if (base_method
!= null) {
939 base_tparams
= base_method
.GenericDefinition
.TypeParameters
;
940 if (base_method
.DeclaringType
.IsGeneric
) {
941 base_decl_tparams
= base_method
.DeclaringType
.MemberDefinition
.TypeParameters
;
942 base_targs
= Parent
.BaseType
.TypeArguments
;
944 } else if (MethodData
.implementing
!= null) {
945 base_tparams
= MethodData
.implementing
.GenericDefinition
.TypeParameters
;
946 if (MethodData
.implementing
.DeclaringType
.IsGeneric
) {
947 base_decl_tparams
= MethodData
.implementing
.DeclaringType
.MemberDefinition
.TypeParameters
;
948 foreach (var iface
in Parent
.CurrentType
.Interfaces
) {
949 if (iface
== MethodData
.implementing
.DeclaringType
) {
950 base_targs
= iface
.TypeArguments
;
958 for (int i
= 0; i
< tparams
.Length
; ++i
) {
961 if (!tp
.ResolveConstraints (this))
965 // Copy base constraints for override/explicit methods
967 if (base_tparams
!= null) {
968 var base_tparam
= base_tparams
[i
];
969 tp
.Type
.SpecialConstraint
= base_tparam
.SpecialConstraint
;
971 var inflator
= new TypeParameterInflator (CurrentType
, base_decl_tparams
, base_targs
);
972 base_tparam
.InflateConstraints (inflator
, tp
.Type
);
973 } else if (MethodData
.implementing
!= null) {
974 var base_tp
= MethodData
.implementing
.Constraints
[i
];
975 if (!tp
.Type
.HasSameConstraintsImplementation (base_tp
)) {
976 Report
.SymbolRelatedToPreviousError (MethodData
.implementing
);
977 Report
.Error (425, Location
,
978 "The constraints for type parameter `{0}' of method `{1}' must match the constraints for type parameter `{2}' of interface method `{3}'. Consider using an explicit interface implementation instead",
979 tp
.GetSignatureForError (), GetSignatureForError (), base_tp
.GetSignatureForError (), MethodData
.implementing
.GetSignatureForError ());
988 public override bool Define ()
990 if (type_expr
.Type
== TypeManager
.void_type
&& parameters
.IsEmpty
&& MemberName
.Arity
== 0 && MemberName
.Name
== Destructor
.MetadataName
) {
991 Report
.Warning (465, 1, Location
, "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
997 if (partialMethodImplementation
!= null && IsPartialDefinition
)
998 MethodBuilder
= partialMethodImplementation
.MethodBuilder
;
1000 if (RootContext
.StdLib
&& TypeManager
.IsSpecialType (ReturnType
)) {
1001 Error1599 (Location
, ReturnType
, Report
);
1005 if (CurrentTypeParameters
== null) {
1006 if (base_method
!= null) {
1007 if (parameters
.Count
== 1 && ParameterTypes
[0] == TypeManager
.object_type
&& Name
== "Equals")
1008 Parent
.PartialContainer
.Mark_HasEquals ();
1009 else if (parameters
.IsEmpty
&& Name
== "GetHashCode")
1010 Parent
.PartialContainer
.Mark_HasGetHashCode ();
1014 DefineTypeParameters ();
1017 if (block
!= null && block
.IsIterator
&& !(Parent
is IteratorStorey
)) {
1019 // Current method is turned into automatically generated
1020 // wrapper which creates an instance of iterator
1022 Iterator
.CreateIterator (this, Parent
.PartialContainer
, ModFlags
, Compiler
);
1023 ModFlags
|= Modifiers
.DEBUGGER_HIDDEN
;
1026 if ((ModFlags
& Modifiers
.STATIC
) == 0)
1029 if (parameters
.HasExtensionMethodType
) {
1030 if (Parent
.PartialContainer
.IsStatic
&& !Parent
.IsGeneric
) {
1031 if (!Parent
.IsTopLevel
)
1032 Report
.Error (1109, Location
, "`{0}': Extension methods cannot be defined in a nested class",
1033 GetSignatureForError ());
1035 PredefinedAttribute pa
= PredefinedAttributes
.Get
.Extension
;
1036 if (!pa
.IsDefined
) {
1037 Report
.Error (1110, Location
,
1038 "`{0}': Extension methods cannot be declared without a reference to System.Core.dll assembly. Add the assembly reference or remove `this' modifer from the first parameter",
1039 GetSignatureForError ());
1042 ModFlags
|= Modifiers
.METHOD_EXTENSION
;
1043 Parent
.PartialContainer
.ModFlags
|= Modifiers
.METHOD_EXTENSION
;
1044 Spec
.DeclaringType
.SetExtensionMethodContainer ();
1045 CodeGen
.Assembly
.HasExtensionMethods
= true;
1047 Report
.Error (1106, Location
, "`{0}': Extension methods must be defined in a non-generic static class",
1048 GetSignatureForError ());
1053 // This is used to track the Entry Point,
1055 if (RootContext
.NeedsEntryPoint
&&
1057 (RootContext
.MainClass
== null ||
1058 RootContext
.MainClass
== Parent
.TypeBuilder
.FullName
)){
1059 if (IsEntryPoint ()) {
1061 if (RootContext
.EntryPoint
== null) {
1062 if (Parent
.IsGeneric
|| MemberName
.IsGeneric
) {
1063 Report
.Warning (402, 4, Location
, "`{0}': an entry point cannot be generic or in a generic type",
1064 GetSignatureForError ());
1067 RootContext
.EntryPoint
= this;
1070 Error_DuplicateEntryPoint (RootContext
.EntryPoint
);
1071 Error_DuplicateEntryPoint (this);
1074 Report
.Warning (28, 4, Location
, "`{0}' has the wrong signature to be an entry point",
1075 GetSignatureForError ());
1085 public override void Emit ()
1088 Report
.Debug (64, "METHOD EMIT", this, MethodBuilder
, Location
, Block
, MethodData
);
1089 if (IsPartialDefinition
) {
1091 // Use partial method implementation builder for partial method declaration attributes
1093 if (partialMethodImplementation
!= null) {
1094 MethodBuilder
= partialMethodImplementation
.MethodBuilder
;
1097 } else if ((ModFlags
& Modifiers
.PARTIAL
) != 0 && (caching_flags
& Flags
.PartialDefinitionExists
) == 0) {
1098 Report
.Error (759, Location
, "A partial method `{0}' implementation is missing a partial method declaration",
1099 GetSignatureForError ());
1102 if (CurrentTypeParameters
!= null) {
1103 var ge
= type_expr
as GenericTypeExpr
;
1105 ge
.CheckConstraints (this);
1107 foreach (Parameter p
in parameters
.FixedParameters
) {
1108 ge
= p
.TypeExpression
as GenericTypeExpr
;
1110 ge
.CheckConstraints (this);
1113 for (int i
= 0; i
< CurrentTypeParameters
.Length
; ++i
) {
1114 var tp
= CurrentTypeParameters
[i
];
1115 tp
.CheckGenericConstraints ();
1122 if ((ModFlags
& Modifiers
.METHOD_EXTENSION
) != 0)
1123 PredefinedAttributes
.Get
.Extension
.EmitAttribute (MethodBuilder
);
1125 Console
.WriteLine ("Internal compiler error at {0}: exception caught while emitting {1}",
1126 Location
, MethodBuilder
);
1131 public override bool EnableOverloadChecks (MemberCore overload
)
1133 // TODO: It can be deleted when members will be defined in correct order
1134 if (overload
is Operator
)
1135 return overload
.EnableOverloadChecks (this);
1137 if (overload
is Indexer
)
1140 return base.EnableOverloadChecks (overload
);
1143 public static void Error1599 (Location loc
, TypeSpec t
, Report Report
)
1145 Report
.Error (1599, loc
, "Method or delegate cannot return type `{0}'", TypeManager
.CSharpName (t
));
1148 protected override bool ResolveMemberType ()
1150 if (GenericMethod
!= null) {
1151 MethodBuilder
= Parent
.TypeBuilder
.DefineMethod (GetFullName (MemberName
), flags
);
1152 if (!GenericMethod
.Define (this))
1156 return base.ResolveMemberType ();
1159 public void SetPartialDefinition (Method methodDefinition
)
1161 caching_flags
|= Flags
.PartialDefinitionExists
;
1162 methodDefinition
.partialMethodImplementation
= this;
1164 // Ensure we are always using method declaration parameters
1165 for (int i
= 0; i
< methodDefinition
.parameters
.Count
; ++i
) {
1166 parameters
[i
].Name
= methodDefinition
.parameters
[i
].Name
;
1167 parameters
[i
].DefaultValue
= methodDefinition
.parameters
[i
].DefaultValue
;
1170 if (methodDefinition
.attributes
== null)
1173 if (attributes
== null) {
1174 attributes
= methodDefinition
.attributes
;
1176 attributes
.Attrs
.AddRange (methodDefinition
.attributes
.Attrs
);
1181 public abstract class ConstructorInitializer
: ExpressionStatement
1183 Arguments argument_list
;
1184 MethodGroupExpr base_constructor_group
;
1186 public ConstructorInitializer (Arguments argument_list
, Location loc
)
1188 this.argument_list
= argument_list
;
1192 public Arguments Arguments
{
1194 return argument_list
;
1198 public override Expression
CreateExpressionTree (ResolveContext ec
)
1200 throw new NotSupportedException ("ET");
1203 protected override Expression
DoResolve (ResolveContext ec
)
1205 eclass
= ExprClass
.Value
;
1208 var caller_builder
= (Constructor
) ec
.MemberContext
;
1210 if (argument_list
!= null) {
1214 // Spec mandates that constructor initializer will not have `this' access
1216 using (ec
.Set (ResolveContext
.Options
.BaseInitializer
)) {
1217 argument_list
.Resolve (ec
, out dynamic);
1221 ec
.Report
.Error (1975, loc
,
1222 "The constructor call cannot be dynamically dispatched within constructor initializer");
1228 type
= ec
.CurrentType
;
1229 if (this is ConstructorBaseInitializer
) {
1230 if (ec
.CurrentType
.BaseType
== null)
1233 type
= ec
.CurrentType
.BaseType
;
1234 if (ec
.CurrentType
.IsStruct
) {
1235 ec
.Report
.Error (522, loc
,
1236 "`{0}': Struct constructors cannot call base constructors", caller_builder
.GetSignatureForError ());
1241 // It is legal to have "this" initializers that take no arguments
1242 // in structs, they are just no-ops.
1244 // struct D { public D (int a) : this () {}
1246 if (TypeManager
.IsStruct (ec
.CurrentType
) && argument_list
== null)
1250 base_constructor_group
= MemberLookupFinal (
1251 ec
, null, type
, ConstructorBuilder
.ConstructorName
, 0, MemberKind
.Constructor
,
1252 BindingRestriction
.AccessibleOnly
| BindingRestriction
.DeclaredOnly
,
1253 loc
) as MethodGroupExpr
;
1255 if (base_constructor_group
== null)
1258 base_constructor_group
= base_constructor_group
.OverloadResolve (
1259 ec
, ref argument_list
, false, loc
);
1261 if (base_constructor_group
== null)
1265 base_constructor_group
.InstanceExpression
= ec
.GetThis (loc
);
1267 var base_ctor
= base_constructor_group
.BestCandidate
;
1269 // TODO MemberCache: Does it work for inflated types ?
1270 if (base_ctor
== caller_builder
.Spec
){
1271 ec
.Report
.Error (516, loc
, "Constructor `{0}' cannot call itself",
1272 caller_builder
.GetSignatureForError ());
1278 public override void Emit (EmitContext ec
)
1280 // It can be null for static initializers
1281 if (base_constructor_group
== null)
1286 base_constructor_group
.EmitCall (ec
, argument_list
);
1289 public override void EmitStatement (EmitContext ec
)
1295 public class ConstructorBaseInitializer
: ConstructorInitializer
{
1296 public ConstructorBaseInitializer (Arguments argument_list
, Location l
) :
1297 base (argument_list
, l
)
1302 class GeneratedBaseInitializer
: ConstructorBaseInitializer
{
1303 public GeneratedBaseInitializer (Location loc
):
1309 public class ConstructorThisInitializer
: ConstructorInitializer
{
1310 public ConstructorThisInitializer (Arguments argument_list
, Location l
) :
1311 base (argument_list
, l
)
1316 public class Constructor
: MethodCore
, IMethodData
{
1317 public ConstructorBuilder ConstructorBuilder
;
1318 public ConstructorInitializer Initializer
;
1319 Dictionary
<SecurityAction
, PermissionSet
> declarative_security
;
1320 bool has_compliant_args
;
1323 // Modifiers allowed for a constructor.
1325 public const Modifiers AllowedModifiers
=
1327 Modifiers
.PROTECTED
|
1328 Modifiers
.INTERNAL
|
1334 static readonly string[] attribute_targets
= new string [] { "method" }
;
1337 // The spec claims that static is not permitted, but
1338 // my very own code has static constructors.
1340 public Constructor (DeclSpace parent
, string name
, Modifiers mod
, Attributes attrs
, ParametersCompiled args
,
1341 ConstructorInitializer init
, Location loc
)
1342 : base (parent
, null, null, mod
, AllowedModifiers
,
1343 new MemberName (name
, loc
), attrs
, args
)
1348 public bool HasCompliantArgs
{
1349 get { return has_compliant_args; }
1352 public override AttributeTargets AttributeTargets
{
1353 get { return AttributeTargets.Constructor; }
1357 // Returns true if this is a default constructor
1359 public bool IsDefault ()
1361 if ((ModFlags
& Modifiers
.STATIC
) != 0)
1362 return parameters
.IsEmpty
;
1364 return parameters
.IsEmpty
&&
1365 (Initializer
is ConstructorBaseInitializer
) &&
1366 (Initializer
.Arguments
== null);
1369 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
1371 if (a
.IsValidSecurityAttribute ()) {
1372 if (declarative_security
== null) {
1373 declarative_security
= new Dictionary
<SecurityAction
, PermissionSet
> ();
1375 a
.ExtractSecurityPermissionSet (declarative_security
);
1379 if (a
.IsInternalMethodImplAttribute
) {
1380 is_external_implementation
= true;
1383 ConstructorBuilder
.SetCustomAttribute ((ConstructorInfo
) ctor
.GetMetaInfo (), cdata
);
1386 protected override bool CheckBase ()
1388 if ((ModFlags
& Modifiers
.STATIC
) != 0) {
1389 if (!parameters
.IsEmpty
) {
1390 Report
.Error (132, Location
, "`{0}': The static constructor must be parameterless",
1391 GetSignatureForError ());
1395 // the rest can be ignored
1399 // Check whether arguments were correct.
1400 if (!DefineParameters (parameters
))
1403 if ((caching_flags
& Flags
.MethodOverloadsExist
) != 0)
1404 Parent
.MemberCache
.CheckExistingMembersOverloads (this, parameters
);
1406 if (Parent
.PartialContainer
.Kind
== MemberKind
.Struct
&& parameters
.IsEmpty
) {
1407 Report
.Error (568, Location
,
1408 "Structs cannot contain explicit parameterless constructors");
1412 CheckProtectedModifier ();
1418 // Creates the ConstructorBuilder
1420 public override bool Define ()
1422 if (ConstructorBuilder
!= null)
1425 var ca
= MethodAttributes
.RTSpecialName
| MethodAttributes
.SpecialName
;
1427 if ((ModFlags
& Modifiers
.STATIC
) != 0) {
1428 ca
|= MethodAttributes
.Static
| MethodAttributes
.Private
;
1430 ca
|= ModifiersExtensions
.MethodAttr (ModFlags
);
1433 if (!CheckAbstractAndExtern (block
!= null))
1436 // Check if arguments were correct.
1440 ConstructorBuilder
= Parent
.TypeBuilder
.DefineConstructor (
1441 ca
, CallingConventions
,
1442 parameters
.GetMetaInfo ());
1444 spec
= new MethodSpec (MemberKind
.Constructor
, Parent
.Definition
, this, TypeManager
.void_type
, ConstructorBuilder
, parameters
, ModFlags
);
1446 Parent
.MemberCache
.AddMember (spec
);
1448 // It's here only to report an error
1449 if (block
!= null && block
.IsIterator
) {
1450 member_type
= TypeManager
.void_type
;
1451 Iterator
.CreateIterator (this, Parent
.PartialContainer
, ModFlags
, Compiler
);
1460 public override void Emit ()
1462 if (Parent
.PartialContainer
.IsComImport
) {
1463 if (!IsDefault ()) {
1464 Report
.Error (669, Location
, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
1465 Parent
.GetSignatureForError ());
1467 ConstructorBuilder
.SetImplementationFlags (MethodImplAttributes
.InternalCall
);
1470 if ((ModFlags
& Modifiers
.DEBUGGER_HIDDEN
) != 0)
1471 PredefinedAttributes
.Get
.DebuggerHidden
.EmitAttribute (ConstructorBuilder
);
1473 if (OptAttributes
!= null)
1474 OptAttributes
.Emit ();
1479 // If we use a "this (...)" constructor initializer, then
1480 // do not emit field initializers, they are initialized in the other constructor
1482 bool emit_field_initializers
= ((ModFlags
& Modifiers
.STATIC
) != 0) ||
1483 !(Initializer
is ConstructorThisInitializer
);
1485 BlockContext bc
= new BlockContext (this, block
, TypeManager
.void_type
);
1486 bc
.Set (ResolveContext
.Options
.ConstructorScope
);
1488 if (emit_field_initializers
)
1489 Parent
.PartialContainer
.ResolveFieldInitializers (bc
);
1491 if (block
!= null) {
1492 // If this is a non-static `struct' constructor and doesn't have any
1493 // initializer, it must initialize all of the struct's fields.
1494 if ((Parent
.PartialContainer
.Kind
== MemberKind
.Struct
) &&
1495 ((ModFlags
& Modifiers
.STATIC
) == 0) && (Initializer
== null))
1496 block
.AddThisVariable (Parent
, Location
);
1498 if (block
!= null && (ModFlags
& Modifiers
.STATIC
) == 0){
1499 if (Parent
.PartialContainer
.Kind
== MemberKind
.Class
&& Initializer
== null)
1500 Initializer
= new GeneratedBaseInitializer (Location
);
1502 if (Initializer
!= null) {
1503 block
.AddScopeStatement (new StatementExpression (Initializer
));
1508 parameters
.ApplyAttributes (ConstructorBuilder
);
1510 SourceMethod source
= SourceMethod
.Create (Parent
, ConstructorBuilder
, block
);
1512 if (block
!= null) {
1513 if (block
.Resolve (null, bc
, parameters
, this)) {
1514 EmitContext ec
= new EmitContext (this, ConstructorBuilder
.GetILGenerator (), bc
.ReturnType
);
1515 ec
.With (EmitContext
.Options
.ConstructorScope
, true);
1517 if (!ec
.HasReturnLabel
&& bc
.HasReturnLabel
) {
1518 ec
.ReturnLabel
= bc
.ReturnLabel
;
1519 ec
.HasReturnLabel
= true;
1527 source
.CloseMethod ();
1529 if (declarative_security
!= null) {
1530 foreach (var de
in declarative_security
) {
1531 ConstructorBuilder
.AddDeclarativeSecurity (de
.Key
, de
.Value
);
1538 protected override MemberSpec
FindBaseMember (out MemberSpec bestCandidate
)
1540 // Is never override
1541 bestCandidate
= null;
1545 public override string GetSignatureForError()
1547 return base.GetSignatureForError () + parameters
.GetSignatureForError ();
1550 public override string[] ValidAttributeTargets
{
1552 return attribute_targets
;
1556 protected override bool VerifyClsCompliance ()
1558 if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
1562 if (!parameters
.IsEmpty
&& Parent
.Definition
.IsAttribute
) {
1563 foreach (TypeSpec param
in parameters
.Types
) {
1564 if (param
.IsArray
) {
1570 has_compliant_args
= true;
1574 #region IMethodData Members
1576 public MemberName MethodName
{
1582 public TypeSpec ReturnType
{
1588 public EmitContext
CreateEmitContext (ILGenerator ig
)
1590 throw new NotImplementedException ();
1593 public bool IsExcluded()
1598 GenericMethod IMethodData
.GenericMethod
{
1604 void IMethodData
.EmitExtraSymbolInfo (SourceMethod source
)
1611 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
1613 public interface IMethodData
1615 CallingConventions CallingConventions { get; }
1616 Location Location { get; }
1617 MemberName MethodName { get; }
1618 TypeSpec ReturnType { get; }
1619 GenericMethod GenericMethod { get; }
1620 ParametersCompiled ParameterInfo { get; }
1621 MethodSpec Spec { get; }
1623 Attributes OptAttributes { get; }
1624 ToplevelBlock Block { get; set; }
1626 EmitContext
CreateEmitContext (ILGenerator ig
);
1627 string GetSignatureForError ();
1628 void EmitExtraSymbolInfo (SourceMethod source
);
1632 // Encapsulates most of the Method's state
1634 public class MethodData
{
1635 static FieldInfo methodbuilder_attrs_field
;
1636 public readonly IMethodData method
;
1638 public readonly GenericMethod GenericMethod
;
1641 // Are we implementing an interface ?
1643 public MethodSpec implementing
;
1648 protected InterfaceMemberBase member
;
1649 protected Modifiers modifiers
;
1650 protected MethodAttributes flags
;
1651 protected TypeSpec declaring_type
;
1652 protected MethodSpec parent_method
;
1654 MethodBuilder builder
;
1655 public MethodBuilder MethodBuilder
{
1661 public TypeSpec DeclaringType
{
1663 return declaring_type
;
1667 public MethodData (InterfaceMemberBase member
,
1668 Modifiers modifiers
, MethodAttributes flags
, IMethodData method
)
1670 this.member
= member
;
1671 this.modifiers
= modifiers
;
1674 this.method
= method
;
1677 public MethodData (InterfaceMemberBase member
,
1678 Modifiers modifiers
, MethodAttributes flags
,
1679 IMethodData method
, MethodBuilder builder
,
1680 GenericMethod generic
, MethodSpec parent_method
)
1681 : this (member
, modifiers
, flags
, method
)
1683 this.builder
= builder
;
1684 this.GenericMethod
= generic
;
1685 this.parent_method
= parent_method
;
1688 public bool Define (DeclSpace parent
, string method_full_name
, Report Report
)
1690 TypeContainer container
= parent
.PartialContainer
;
1692 PendingImplementation pending
= container
.PendingImplementations
;
1693 if (pending
!= null){
1694 implementing
= pending
.IsInterfaceMethod (method
.MethodName
, member
.InterfaceType
, this);
1696 if (member
.InterfaceType
!= null){
1697 if (implementing
== null){
1698 if (member
is PropertyBase
) {
1699 Report
.Error (550, method
.Location
, "`{0}' is an accessor not found in interface member `{1}{2}'",
1700 method
.GetSignatureForError (), TypeManager
.CSharpName (member
.InterfaceType
),
1701 member
.GetSignatureForError ().Substring (member
.GetSignatureForError ().LastIndexOf ('.')));
1704 Report
.Error (539, method
.Location
,
1705 "`{0}.{1}' in explicit interface declaration is not a member of interface",
1706 TypeManager
.CSharpName (member
.InterfaceType
), member
.ShortName
);
1710 if (implementing
.IsAccessor
&& !(method
is AbstractPropertyEventMethod
)) {
1711 Report
.SymbolRelatedToPreviousError (implementing
);
1712 Report
.Error (683, method
.Location
, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
1713 member
.GetSignatureForError (), TypeManager
.CSharpSignature (implementing
));
1717 if (implementing
!= null) {
1718 AbstractPropertyEventMethod prop_method
= method
as AbstractPropertyEventMethod
;
1719 if (prop_method
== null) {
1720 if (implementing
.IsAccessor
) {
1721 Report
.SymbolRelatedToPreviousError (implementing
);
1722 Report
.Error (470, method
.Location
, "Method `{0}' cannot implement interface accessor `{1}'",
1723 method
.GetSignatureForError (), TypeManager
.CSharpSignature (implementing
));
1725 } else if (implementing
.DeclaringType
.IsInterface
) {
1726 if (!implementing
.IsAccessor
) {
1727 Report
.SymbolRelatedToPreviousError (implementing
);
1728 Report
.Error (686, method
.Location
, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
1729 method
.GetSignatureForError (), TypeManager
.CSharpSignature (implementing
), container
.GetSignatureForError ());
1731 PropertyBase
.PropertyMethod pm
= prop_method
as PropertyBase
.PropertyMethod
;
1732 if (pm
!= null && pm
.HasCustomAccessModifier
&& (pm
.ModFlags
& Modifiers
.PUBLIC
) == 0) {
1733 Report
.SymbolRelatedToPreviousError (implementing
);
1734 Report
.Error (277, method
.Location
, "Accessor `{0}' must be declared public to implement interface member `{1}'",
1735 method
.GetSignatureForError (), implementing
.GetSignatureForError ());
1744 // For implicit implementations, make sure we are public, for
1745 // explicit implementations, make sure we are private.
1747 if (implementing
!= null){
1749 // Setting null inside this block will trigger a more
1750 // verbose error reporting for missing interface implementations
1752 // The "candidate" function has been flagged already
1753 // but it wont get cleared
1755 if (member
.IsExplicitImpl
){
1756 if (method
.ParameterInfo
.HasParams
&& !implementing
.Parameters
.HasParams
) {
1757 Report
.SymbolRelatedToPreviousError (implementing
);
1758 Report
.Error (466, method
.Location
, "`{0}': the explicit interface implementation cannot introduce the params modifier",
1759 method
.GetSignatureForError ());
1762 if (implementing
.DeclaringType
.IsInterface
) {
1764 // If this is an interface method implementation,
1765 // check for public accessibility
1767 if ((flags
& MethodAttributes
.MemberAccessMask
) != MethodAttributes
.Public
)
1769 implementing
= null;
1771 } else if ((flags
& MethodAttributes
.MemberAccessMask
) == MethodAttributes
.Private
){
1772 // We may never be private.
1773 implementing
= null;
1775 } else if ((modifiers
& Modifiers
.OVERRIDE
) == 0){
1777 // We may be protected if we're overriding something.
1779 implementing
= null;
1784 // Static is not allowed
1786 if ((modifiers
& Modifiers
.STATIC
) != 0){
1787 implementing
= null;
1792 // If implementing is still valid, set flags
1794 if (implementing
!= null){
1796 // When implementing interface methods, set NewSlot
1797 // unless, we are overwriting a method.
1799 if (implementing
.DeclaringType
.IsInterface
){
1800 if ((modifiers
& Modifiers
.OVERRIDE
) == 0)
1801 flags
|= MethodAttributes
.NewSlot
;
1804 flags
|= MethodAttributes
.Virtual
| MethodAttributes
.HideBySig
;
1806 // Set Final unless we're virtual, abstract or already overriding a method.
1807 if ((modifiers
& (Modifiers
.VIRTUAL
| Modifiers
.ABSTRACT
| Modifiers
.OVERRIDE
)) == 0)
1808 flags
|= MethodAttributes
.Final
;
1811 // clear the pending implementation flag (requires explicit methods to be defined first)
1813 parent
.PartialContainer
.PendingImplementations
.ImplementMethod (method
.MethodName
,
1814 member
.InterfaceType
, this, member
.IsExplicitImpl
);
1817 // Update indexer accessor name to match implementing abstract accessor
1819 if (!implementing
.DeclaringType
.IsInterface
&& !member
.IsExplicitImpl
&& implementing
.IsAccessor
)
1820 method_full_name
= implementing
.MemberDefinition
.Name
;
1823 DefineMethodBuilder (container
, method_full_name
, method
.ParameterInfo
);
1825 if (builder
== null)
1828 // if (container.CurrentType != null)
1829 // declaring_type = container.CurrentType;
1831 declaring_type
= container
.Definition
;
1833 if (implementing
!= null && member
.IsExplicitImpl
) {
1834 container
.TypeBuilder
.DefineMethodOverride (builder
, (MethodInfo
) implementing
.GetMetaInfo ());
1842 /// Create the MethodBuilder for the method
1844 void DefineMethodBuilder (TypeContainer container
, string method_name
, ParametersCompiled param
)
1846 var return_type
= method
.ReturnType
.GetMetaInfo ();
1847 var p_types
= param
.GetMetaInfo ();
1849 if (builder
== null) {
1850 builder
= container
.TypeBuilder
.DefineMethod (
1851 method_name
, flags
, method
.CallingConventions
,
1852 return_type
, p_types
);
1857 // Generic method has been already defined to resolve method parameters
1858 // correctly when they use type parameters
1860 builder
.SetParameters (p_types
);
1861 builder
.SetReturnType (return_type
);
1862 if (builder
.Attributes
!= flags
) {
1864 if (methodbuilder_attrs_field
== null)
1865 methodbuilder_attrs_field
= typeof (MethodBuilder
).GetField ("attrs", BindingFlags
.NonPublic
| BindingFlags
.Instance
);
1866 methodbuilder_attrs_field
.SetValue (builder
, flags
);
1868 container
.Compiler
.Report
.RuntimeMissingSupport (method
.Location
, "Generic method MethodAttributes");
1876 public void Emit (DeclSpace parent
)
1878 if (GenericMethod
!= null)
1879 GenericMethod
.EmitAttributes ();
1881 method
.ParameterInfo
.ApplyAttributes (MethodBuilder
);
1883 SourceMethod source
= SourceMethod
.Create (parent
, MethodBuilder
, method
.Block
);
1885 ToplevelBlock block
= method
.Block
;
1886 if (block
!= null) {
1887 BlockContext bc
= new BlockContext ((IMemberContext
) method
, block
, method
.ReturnType
);
1888 if (block
.Resolve (null, bc
, method
.ParameterInfo
, method
)) {
1889 EmitContext ec
= method
.CreateEmitContext (MethodBuilder
.GetILGenerator ());
1890 if (!ec
.HasReturnLabel
&& bc
.HasReturnLabel
) {
1891 ec
.ReturnLabel
= bc
.ReturnLabel
;
1892 ec
.HasReturnLabel
= true;
1899 if (source
!= null) {
1900 method
.EmitExtraSymbolInfo (source
);
1901 source
.CloseMethod ();
1906 public class Destructor
: MethodOrOperator
1908 const Modifiers AllowedModifiers
=
1912 static readonly string[] attribute_targets
= new string [] { "method" }
;
1914 public static readonly string MetadataName
= "Finalize";
1916 public Destructor (DeclSpace parent
, Modifiers mod
, ParametersCompiled parameters
, Attributes attrs
, Location l
)
1917 : base (parent
, null, null, mod
, AllowedModifiers
,
1918 new MemberName (MetadataName
, l
), attrs
, parameters
)
1920 ModFlags
&= ~Modifiers
.PRIVATE
;
1921 ModFlags
|= Modifiers
.PROTECTED
| Modifiers
.OVERRIDE
;
1924 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
1926 if (a
.Type
== pa
.Conditional
) {
1927 Error_ConditionalAttributeIsNotValid ();
1931 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
1934 protected override bool CheckBase ()
1936 // Don't check base, destructors have special syntax
1940 public override void Emit()
1942 var base_type
= Parent
.PartialContainer
.BaseType
;
1943 if (base_type
!= null && Block
!= null) {
1944 MethodGroupExpr method_expr
= Expression
.MethodLookup (Parent
.Module
.Compiler
, Parent
.Definition
, base_type
, MemberKind
.Destructor
, MetadataName
, 0, Location
);
1945 if (method_expr
== null)
1946 throw new NotImplementedException ();
1948 method_expr
.QueriedBaseType
= base_type
;
1949 method_expr
.InstanceExpression
= new CompilerGeneratedThis (Parent
.Definition
, Location
);
1951 ToplevelBlock new_block
= new ToplevelBlock (Compiler
, Block
.StartLocation
);
1952 new_block
.EndLocation
= Block
.EndLocation
;
1954 Block finaly_block
= new ExplicitBlock (new_block
, Location
, Location
);
1955 Block try_block
= new Block (new_block
, block
);
1958 // 0-size arguments to avoid CS0250 error
1959 // TODO: Should use AddScopeStatement or something else which emits correct
1962 finaly_block
.AddStatement (new StatementExpression (new Invocation (method_expr
, new Arguments (0))));
1963 new_block
.AddStatement (new TryFinally (try_block
, finaly_block
, Location
));
1971 public override string GetSignatureForError ()
1973 return Parent
.GetSignatureForError () + ".~" + Parent
.MemberName
.Name
+ "()";
1976 protected override bool ResolveMemberType ()
1978 member_type
= TypeManager
.void_type
;
1982 public override string[] ValidAttributeTargets
{
1984 return attribute_targets
;
1989 // Ooouh Martin, templates are missing here.
1990 // When it will be possible move here a lot of child code and template method type.
1991 public abstract class AbstractPropertyEventMethod
: MemberCore
, IMethodData
{
1992 protected MethodData method_data
;
1993 protected ToplevelBlock block
;
1994 protected Dictionary
<SecurityAction
, PermissionSet
> declarative_security
;
1996 protected readonly string prefix
;
1998 ReturnParameter return_attributes
;
2000 public AbstractPropertyEventMethod (InterfaceMemberBase member
, string prefix
, Attributes attrs
, Location loc
)
2001 : base (member
.Parent
, SetupName (prefix
, member
, loc
), attrs
)
2003 this.prefix
= prefix
;
2006 static MemberName
SetupName (string prefix
, InterfaceMemberBase member
, Location loc
)
2008 return new MemberName (member
.MemberName
.Left
, prefix
+ member
.ShortName
, loc
);
2011 public void UpdateName (InterfaceMemberBase member
)
2013 SetMemberName (SetupName (prefix
, member
, Location
));
2016 #region IMethodData Members
2018 public ToplevelBlock Block
{
2028 public CallingConventions CallingConventions
{
2030 return CallingConventions
.Standard
;
2034 public EmitContext
CreateEmitContext (ILGenerator ig
)
2036 return new EmitContext (this, ig
, ReturnType
);
2039 public bool IsExcluded ()
2044 GenericMethod IMethodData
.GenericMethod
{
2050 public MemberName MethodName
{
2056 public TypeSpec
[] ParameterTypes
{
2058 return ParameterInfo
.Types
;
2062 public abstract ParametersCompiled ParameterInfo { get ; }
2063 public abstract TypeSpec ReturnType { get; }
2067 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
2069 if (a
.Type
== pa
.CLSCompliant
|| a
.Type
== pa
.Obsolete
|| a
.Type
== pa
.Conditional
) {
2070 Report
.Error (1667, a
.Location
,
2071 "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
2072 TypeManager
.CSharpName (a
.Type
), a
.GetValidTargets ());
2076 if (a
.IsValidSecurityAttribute ()) {
2077 if (declarative_security
== null)
2078 declarative_security
= new Dictionary
<SecurityAction
, PermissionSet
> ();
2079 a
.ExtractSecurityPermissionSet (declarative_security
);
2083 if (a
.Target
== AttributeTargets
.Method
) {
2084 method_data
.MethodBuilder
.SetCustomAttribute ((ConstructorInfo
) ctor
.GetMetaInfo (), cdata
);
2088 if (a
.Target
== AttributeTargets
.ReturnValue
) {
2089 if (return_attributes
== null)
2090 return_attributes
= new ReturnParameter (this, method_data
.MethodBuilder
, Location
);
2092 return_attributes
.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
2096 ApplyToExtraTarget (a
, ctor
, cdata
, pa
);
2099 protected virtual void ApplyToExtraTarget (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
2101 throw new NotSupportedException ("You forgot to define special attribute target handling");
2104 // It is not supported for the accessors
2105 public sealed override bool Define()
2107 throw new NotSupportedException ();
2110 public virtual void Emit (DeclSpace parent
)
2112 method_data
.Emit (parent
);
2114 if ((ModFlags
& Modifiers
.COMPILER_GENERATED
) != 0 && !Parent
.IsCompilerGenerated
)
2115 PredefinedAttributes
.Get
.CompilerGenerated
.EmitAttribute (method_data
.MethodBuilder
);
2116 if (((ModFlags
& Modifiers
.DEBUGGER_HIDDEN
) != 0))
2117 PredefinedAttributes
.Get
.DebuggerHidden
.EmitAttribute (method_data
.MethodBuilder
);
2119 if (ReturnType
== InternalType
.Dynamic
) {
2120 return_attributes
= new ReturnParameter (this, method_data
.MethodBuilder
, Location
);
2121 PredefinedAttributes
.Get
.Dynamic
.EmitAttribute (return_attributes
.Builder
);
2123 var trans_flags
= TypeManager
.HasDynamicTypeUsed (ReturnType
);
2124 if (trans_flags
!= null) {
2125 var pa
= PredefinedAttributes
.Get
.DynamicTransform
;
2126 if (pa
.Constructor
!= null || pa
.ResolveConstructor (Location
, ArrayContainer
.MakeType (TypeManager
.bool_type
))) {
2127 return_attributes
= new ReturnParameter (this, method_data
.MethodBuilder
, Location
);
2128 return_attributes
.Builder
.SetCustomAttribute (
2129 new CustomAttributeBuilder (pa
.Constructor
, new object [] { trans_flags }
));
2134 if (OptAttributes
!= null)
2135 OptAttributes
.Emit ();
2137 if (declarative_security
!= null) {
2138 foreach (var de
in declarative_security
) {
2139 method_data
.MethodBuilder
.AddDeclarativeSecurity (de
.Key
, de
.Value
);
2146 public override bool EnableOverloadChecks (MemberCore overload
)
2148 if (overload
is MethodCore
) {
2149 caching_flags
|= Flags
.MethodOverloadsExist
;
2153 // This can only happen with indexers and it will
2154 // be catched as indexer difference
2155 if (overload
is AbstractPropertyEventMethod
)
2161 public override bool IsClsComplianceRequired()
2166 public MethodSpec Spec { get; protected set; }
2169 // Represents header string for documentation comment.
2171 public override string DocCommentHeader
{
2172 get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
2175 void IMethodData
.EmitExtraSymbolInfo (SourceMethod source
)
2179 public class Operator
: MethodOrOperator
{
2181 const Modifiers AllowedModifiers
=
2187 public enum OpType
: byte {
2197 // Unary and Binary operators
2220 // Implicit and Explicit
2224 // Just because of enum
2228 public readonly OpType OperatorType
;
2230 static readonly string [] [] names
;
2234 names
= new string[(int)OpType
.TOP
][];
2235 names
[(int) OpType
.LogicalNot
] = new string [] { "!", "op_LogicalNot" }
;
2236 names
[(int) OpType
.OnesComplement
] = new string [] { "~", "op_OnesComplement" }
;
2237 names
[(int) OpType
.Increment
] = new string [] { "++", "op_Increment" }
;
2238 names
[(int) OpType
.Decrement
] = new string [] { "--", "op_Decrement" }
;
2239 names
[(int) OpType
.True
] = new string [] { "true", "op_True" }
;
2240 names
[(int) OpType
.False
] = new string [] { "false", "op_False" }
;
2241 names
[(int) OpType
.Addition
] = new string [] { "+", "op_Addition" }
;
2242 names
[(int) OpType
.Subtraction
] = new string [] { "-", "op_Subtraction" }
;
2243 names
[(int) OpType
.UnaryPlus
] = new string [] { "+", "op_UnaryPlus" }
;
2244 names
[(int) OpType
.UnaryNegation
] = new string [] { "-", "op_UnaryNegation" }
;
2245 names
[(int) OpType
.Multiply
] = new string [] { "*", "op_Multiply" }
;
2246 names
[(int) OpType
.Division
] = new string [] { "/", "op_Division" }
;
2247 names
[(int) OpType
.Modulus
] = new string [] { "%", "op_Modulus" }
;
2248 names
[(int) OpType
.BitwiseAnd
] = new string [] { "&", "op_BitwiseAnd" }
;
2249 names
[(int) OpType
.BitwiseOr
] = new string [] { "|", "op_BitwiseOr" }
;
2250 names
[(int) OpType
.ExclusiveOr
] = new string [] { "^", "op_ExclusiveOr" }
;
2251 names
[(int) OpType
.LeftShift
] = new string [] { "<<", "op_LeftShift" }
;
2252 names
[(int) OpType
.RightShift
] = new string [] { ">>", "op_RightShift" }
;
2253 names
[(int) OpType
.Equality
] = new string [] { "==", "op_Equality" }
;
2254 names
[(int) OpType
.Inequality
] = new string [] { "!=", "op_Inequality" }
;
2255 names
[(int) OpType
.GreaterThan
] = new string [] { ">", "op_GreaterThan" }
;
2256 names
[(int) OpType
.LessThan
] = new string [] { "<", "op_LessThan" }
;
2257 names
[(int) OpType
.GreaterThanOrEqual
] = new string [] { ">=", "op_GreaterThanOrEqual" }
;
2258 names
[(int) OpType
.LessThanOrEqual
] = new string [] { "<=", "op_LessThanOrEqual" }
;
2259 names
[(int) OpType
.Implicit
] = new string [] { "implicit", "op_Implicit" }
;
2260 names
[(int) OpType
.Explicit
] = new string [] { "explicit", "op_Explicit" }
;
2263 public Operator (DeclSpace parent
, OpType type
, FullNamedExpression ret_type
,
2264 Modifiers mod_flags
, ParametersCompiled parameters
,
2265 ToplevelBlock block
, Attributes attrs
, Location loc
)
2266 : base (parent
, null, ret_type
, mod_flags
, AllowedModifiers
,
2267 new MemberName (GetMetadataName (type
), loc
), attrs
, parameters
)
2269 OperatorType
= type
;
2273 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
2275 if (a
.Type
== pa
.Conditional
) {
2276 Error_ConditionalAttributeIsNotValid ();
2280 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
2283 public override bool Define ()
2285 const Modifiers RequiredModifiers
= Modifiers
.PUBLIC
| Modifiers
.STATIC
;
2286 if ((ModFlags
& RequiredModifiers
) != RequiredModifiers
){
2287 Report
.Error (558, Location
, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
2290 if (!base.Define ())
2293 if (block
!= null && block
.IsIterator
&& !(Parent
is IteratorStorey
)) {
2295 // Current method is turned into automatically generated
2296 // wrapper which creates an instance of iterator
2298 Iterator
.CreateIterator (this, Parent
.PartialContainer
, ModFlags
, Compiler
);
2299 ModFlags
|= Modifiers
.DEBUGGER_HIDDEN
;
2302 // imlicit and explicit operator of same types are not allowed
2303 if (OperatorType
== OpType
.Explicit
)
2304 Parent
.MemberCache
.CheckExistingMembersOverloads (this, GetMetadataName (OpType
.Implicit
), parameters
);
2305 else if (OperatorType
== OpType
.Implicit
)
2306 Parent
.MemberCache
.CheckExistingMembersOverloads (this, GetMetadataName (OpType
.Explicit
), parameters
);
2308 TypeSpec declaring_type
= Parent
.CurrentType
;
2309 TypeSpec return_type
= MemberType
;
2310 TypeSpec first_arg_type
= ParameterTypes
[0];
2312 TypeSpec first_arg_type_unwrap
= first_arg_type
;
2313 if (TypeManager
.IsNullableType (first_arg_type
))
2314 first_arg_type_unwrap
= TypeManager
.GetTypeArguments (first_arg_type
) [0];
2316 TypeSpec return_type_unwrap
= return_type
;
2317 if (TypeManager
.IsNullableType (return_type
))
2318 return_type_unwrap
= TypeManager
.GetTypeArguments (return_type
) [0];
2321 // Rules for conversion operators
2323 if (OperatorType
== OpType
.Implicit
|| OperatorType
== OpType
.Explicit
) {
2324 if (first_arg_type_unwrap
== return_type_unwrap
&& first_arg_type_unwrap
== declaring_type
) {
2325 Report
.Error (555, Location
,
2326 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
2331 if (TypeManager
.IsEqual (declaring_type
, return_type
) || declaring_type
== return_type_unwrap
) {
2332 conv_type
= first_arg_type
;
2333 } else if (TypeManager
.IsEqual (declaring_type
, first_arg_type
) || declaring_type
== first_arg_type_unwrap
) {
2334 conv_type
= return_type
;
2336 Report
.Error (556, Location
,
2337 "User-defined conversion must convert to or from the enclosing type");
2341 if (conv_type
== InternalType
.Dynamic
) {
2342 Report
.Error (1964, Location
,
2343 "User-defined conversion `{0}' cannot convert to or from the dynamic type",
2344 GetSignatureForError ());
2349 if (conv_type
.IsInterface
) {
2350 Report
.Error (552, Location
, "User-defined conversion `{0}' cannot convert to or from an interface type",
2351 GetSignatureForError ());
2355 if (conv_type
.IsClass
) {
2356 if (TypeManager
.IsSubclassOf (declaring_type
, conv_type
)) {
2357 Report
.Error (553, Location
, "User-defined conversion `{0}' cannot convert to or from a base class",
2358 GetSignatureForError ());
2362 if (TypeManager
.IsSubclassOf (conv_type
, declaring_type
)) {
2363 Report
.Error (554, Location
, "User-defined conversion `{0}' cannot convert to or from a derived class",
2364 GetSignatureForError ());
2368 } else if (OperatorType
== OpType
.LeftShift
|| OperatorType
== OpType
.RightShift
) {
2369 if (first_arg_type
!= declaring_type
|| parameters
.Types
[1] != TypeManager
.int32_type
) {
2370 Report
.Error (564, Location
, "Overloaded shift operator must have the type of the first operand be the containing type, and the type of the second operand must be int");
2373 } else if (parameters
.Count
== 1) {
2374 // Checks for Unary operators
2376 if (OperatorType
== OpType
.Increment
|| OperatorType
== OpType
.Decrement
) {
2377 if (return_type
!= declaring_type
&& !TypeManager
.IsSubclassOf (return_type
, declaring_type
)) {
2378 Report
.Error (448, Location
,
2379 "The return type for ++ or -- operator must be the containing type or derived from the containing type");
2382 if (first_arg_type
!= declaring_type
) {
2384 559, Location
, "The parameter type for ++ or -- operator must be the containing type");
2389 if (!TypeManager
.IsEqual (first_arg_type_unwrap
, declaring_type
)) {
2390 Report
.Error (562, Location
,
2391 "The parameter type of a unary operator must be the containing type");
2395 if (OperatorType
== OpType
.True
|| OperatorType
== OpType
.False
) {
2396 if (return_type
!= TypeManager
.bool_type
) {
2399 "The return type of operator True or False " +
2405 } else if (!TypeManager
.IsEqual (first_arg_type_unwrap
, declaring_type
)) {
2406 // Checks for Binary operators
2408 var second_arg_type
= ParameterTypes
[1];
2409 if (TypeManager
.IsNullableType (second_arg_type
))
2410 second_arg_type
= TypeManager
.GetTypeArguments (second_arg_type
)[0];
2412 if (!TypeManager
.IsEqual (second_arg_type
, declaring_type
)) {
2413 Report
.Error (563, Location
,
2414 "One of the parameters of a binary operator must be the containing type");
2422 protected override bool ResolveMemberType ()
2424 if (!base.ResolveMemberType ())
2427 flags
|= MethodAttributes
.SpecialName
| MethodAttributes
.HideBySig
;
2431 protected override MemberSpec
FindBaseMember (out MemberSpec bestCandidate
)
2433 // Operator cannot be override
2434 bestCandidate
= null;
2438 public static string GetName (OpType ot
)
2440 return names
[(int) ot
] [0];
2443 public static string GetName (string metadata_name
)
2445 for (int i
= 0; i
< names
.Length
; ++i
) {
2446 if (names
[i
] [1] == metadata_name
)
2447 return names
[i
] [0];
2452 public static string GetMetadataName (OpType ot
)
2454 return names
[(int) ot
] [1];
2457 public static string GetMetadataName (string name
)
2459 for (int i
= 0; i
< names
.Length
; ++i
) {
2460 if (names
[i
] [0] == name
)
2461 return names
[i
] [1];
2466 public static OpType
? GetType (string metadata_name
)
2468 for (int i
= 0; i
< names
.Length
; ++i
) {
2469 if (names
[i
][1] == metadata_name
)
2476 public OpType
GetMatchingOperator ()
2478 switch (OperatorType
) {
2479 case OpType
.Equality
:
2480 return OpType
.Inequality
;
2481 case OpType
.Inequality
:
2482 return OpType
.Equality
;
2484 return OpType
.False
;
2487 case OpType
.GreaterThan
:
2488 return OpType
.LessThan
;
2489 case OpType
.LessThan
:
2490 return OpType
.GreaterThan
;
2491 case OpType
.GreaterThanOrEqual
:
2492 return OpType
.LessThanOrEqual
;
2493 case OpType
.LessThanOrEqual
:
2494 return OpType
.GreaterThanOrEqual
;
2500 public override string GetSignatureForError ()
2502 StringBuilder sb
= new StringBuilder ();
2503 if (OperatorType
== OpType
.Implicit
|| OperatorType
== OpType
.Explicit
) {
2504 sb
.AppendFormat ("{0}.{1} operator {2}",
2505 Parent
.GetSignatureForError (), GetName (OperatorType
), type_expr
.GetSignatureForError ());
2508 sb
.AppendFormat ("{0}.operator {1}", Parent
.GetSignatureForError (), GetName (OperatorType
));
2511 sb
.Append (parameters
.GetSignatureForError ());
2512 return sb
.ToString ();