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
12 // Copyright 2011 Xamarin Inc.
16 using System
.Collections
.Generic
;
17 using System
.Security
;
18 using System
.Security
.Permissions
;
21 using Mono
.CompilerServices
.SymbolWriter
;
22 using System
.Runtime
.CompilerServices
;
25 using XmlElement
= System
.Object
;
31 using MetaType
= IKVM
.Reflection
.Type
;
32 using SecurityType
= System
.Collections
.Generic
.List
<IKVM
.Reflection
.Emit
.CustomAttributeBuilder
>;
33 using IKVM
.Reflection
;
34 using IKVM
.Reflection
.Emit
;
36 using MetaType
= System
.Type
;
37 using SecurityType
= System
.Collections
.Generic
.Dictionary
<System
.Security
.Permissions
.SecurityAction
, System
.Security
.PermissionSet
>;
38 using System
.Reflection
;
39 using System
.Reflection
.Emit
;
42 namespace Mono
.CSharp
{
44 public abstract class MethodCore
: InterfaceMemberBase
, IParametersMember
46 protected ParametersCompiled parameters
;
47 protected ToplevelBlock block
;
48 protected MethodSpec spec
;
50 protected MethodCore (TypeDefinition parent
, FullNamedExpression type
, Modifiers mod
, Modifiers allowed_mod
,
51 MemberName name
, Attributes attrs
, ParametersCompiled parameters
)
52 : base (parent
, type
, mod
, allowed_mod
, name
, attrs
)
54 this.parameters
= parameters
;
57 public override Variance ExpectedMemberTypeVariance
{
59 return Variance
.Covariant
;
64 // Returns the System.Type array for the parameters of this method
66 public TypeSpec
[] ParameterTypes
{
68 return parameters
.Types
;
72 public ParametersCompiled ParameterInfo
{
78 AParametersCollection IParametersMember
.Parameters
{
79 get { return parameters; }
82 public ToplevelBlock Block
{
92 public CallingConventions CallingConventions
{
94 CallingConventions cc
= parameters
.CallingConvention
;
96 if ((ModFlags
& Modifiers
.STATIC
) == 0)
97 cc
|= CallingConventions
.HasThis
;
99 // FIXME: How is `ExplicitThis' used in C#?
105 protected override bool CheckOverrideAgainstBase (MemberSpec base_member
)
107 bool res
= base.CheckOverrideAgainstBase (base_member
);
110 // Check that the permissions are not being changed
112 if (!CheckAccessModifiers (this, base_member
)) {
113 Error_CannotChangeAccessModifiers (this, base_member
);
120 protected override bool CheckBase ()
122 // Check whether arguments were correct.
123 if (!DefineParameters (parameters
))
126 return base.CheckBase ();
130 // Represents header string for documentation comment.
132 public override string DocCommentHeader
137 public override void Emit ()
139 if ((ModFlags
& Modifiers
.COMPILER_GENERATED
) == 0) {
140 parameters
.CheckConstraints (this);
146 public override bool EnableOverloadChecks (MemberCore overload
)
148 if (overload
is MethodCore
) {
149 caching_flags
|= Flags
.MethodOverloadsExist
;
153 if (overload
is AbstractPropertyEventMethod
)
156 return base.EnableOverloadChecks (overload
);
159 public override string GetSignatureForDocumentation ()
161 string s
= base.GetSignatureForDocumentation ();
162 if (MemberName
.Arity
> 0)
163 s
+= "``" + MemberName
.Arity
.ToString ();
165 return s
+ parameters
.GetSignatureForDocumentation ();
168 public override void PrepareEmit ()
171 parameters
.ResolveDefaultValues (this);
174 public MethodSpec Spec
{
178 protected override bool VerifyClsCompliance ()
180 if (!base.VerifyClsCompliance ())
183 if (parameters
.HasArglist
) {
184 Report
.Warning (3000, 1, Location
, "Methods with variable arguments are not CLS-compliant");
187 if (member_type
!= null && !member_type
.IsCLSCompliant ()) {
188 Report
.Warning (3002, 1, Location
, "Return type of `{0}' is not CLS-compliant",
189 GetSignatureForError ());
192 parameters
.VerifyClsCompliance (this);
197 public interface IGenericMethodDefinition
: IMethodDefinition
199 TypeParameterSpec
[] TypeParameters { get; }
200 int TypeParametersCount { get; }
202 // MethodInfo MakeGenericMethod (TypeSpec[] targs);
205 public sealed class MethodSpec
: MemberSpec
, IParametersMember
207 MethodBase inflatedMetaInfo
;
208 AParametersCollection parameters
;
212 TypeParameterSpec
[] constraints
;
214 public static readonly MethodSpec Excluded
= new MethodSpec (MemberKind
.Method
, InternalType
.FakeInternalType
, null, null, ParametersCompiled
.EmptyReadOnlyParameters
, 0);
216 public MethodSpec (MemberKind kind
, TypeSpec declaringType
, IMethodDefinition details
, TypeSpec returnType
,
217 AParametersCollection parameters
, Modifiers modifiers
)
218 : base (kind
, declaringType
, details
, modifiers
)
220 this.parameters
= parameters
;
221 this.returnType
= returnType
;
226 public override int Arity
{
228 return IsGeneric
? GenericDefinition
.TypeParametersCount
: 0;
232 public TypeParameterSpec
[] Constraints
{
234 if (constraints
== null && IsGeneric
)
235 constraints
= GenericDefinition
.TypeParameters
;
241 public bool IsConstructor
{
243 return Kind
== MemberKind
.Constructor
;
247 public new IMethodDefinition MemberDefinition
{
249 return (IMethodDefinition
) definition
;
253 public IGenericMethodDefinition GenericDefinition
{
255 return (IGenericMethodDefinition
) definition
;
259 public bool IsAsync
{
261 return (Modifiers
& Modifiers
.ASYNC
) != 0;
265 public bool IsExtensionMethod
{
267 return IsStatic
&& parameters
.HasExtensionMethodType
;
271 public bool IsSealed
{
273 return (Modifiers
& Modifiers
.SEALED
) != 0;
277 // When is virtual or abstract
278 public bool IsVirtual
{
280 return (Modifiers
& (Modifiers
.VIRTUAL
| Modifiers
.ABSTRACT
| Modifiers
.OVERRIDE
)) != 0;
284 public bool IsReservedMethod
{
286 return Kind
== MemberKind
.Operator
|| IsAccessor
;
290 TypeSpec IInterfaceMemberSpec
.MemberType
{
296 public AParametersCollection Parameters
{
302 public TypeSpec ReturnType
{
308 public TypeSpec
[] TypeArguments
{
316 public MethodSpec
GetGenericMethodDefinition ()
318 if (!IsGeneric
&& !DeclaringType
.IsGeneric
)
321 return MemberCache
.GetMember (declaringType
, this);
324 public MethodBase
GetMetaInfo ()
327 // inflatedMetaInfo is extra field needed for cases where we
328 // inflate method but another nested type can later inflate
329 // again (the cache would be build with inflated metaInfo) and
330 // TypeBuilder can work with method definitions only
332 if (inflatedMetaInfo
== null) {
333 if ((state
& StateFlags
.PendingMetaInflate
) != 0) {
334 var dt_meta
= DeclaringType
.GetMetaInfo ();
336 if (DeclaringType
.IsTypeBuilder
) {
338 inflatedMetaInfo
= TypeBuilder
.GetConstructor (dt_meta
, (ConstructorInfo
) MemberDefinition
.Metadata
);
340 inflatedMetaInfo
= TypeBuilder
.GetMethod (dt_meta
, (MethodInfo
) MemberDefinition
.Metadata
);
343 // it should not be reached
344 throw new NotImplementedException ();
346 inflatedMetaInfo
= MethodInfo
.GetMethodFromHandle (MemberDefinition
.Metadata
.MethodHandle
, dt_meta
.TypeHandle
);
350 state
&= ~StateFlags
.PendingMetaInflate
;
352 inflatedMetaInfo
= MemberDefinition
.Metadata
;
356 if ((state
& StateFlags
.PendingMakeMethod
) != 0) {
357 var sre_targs
= new MetaType
[targs
.Length
];
358 for (int i
= 0; i
< sre_targs
.Length
; ++i
)
359 sre_targs
[i
] = targs
[i
].GetMetaInfo ();
361 inflatedMetaInfo
= ((MethodInfo
) inflatedMetaInfo
).MakeGenericMethod (sre_targs
);
362 state
&= ~StateFlags
.PendingMakeMethod
;
365 return inflatedMetaInfo
;
368 public override string GetSignatureForDocumentation ()
372 case MemberKind
.Constructor
:
375 case MemberKind
.Method
:
377 name
= Name
+ "``" + Arity
.ToString ();
387 name
= DeclaringType
.GetSignatureForDocumentation () + "." + name
+ parameters
.GetSignatureForDocumentation ();
388 if (Kind
== MemberKind
.Operator
) {
389 var op
= Operator
.GetType (Name
).Value
;
390 if (op
== Operator
.OpType
.Explicit
|| op
== Operator
.OpType
.Implicit
) {
391 name
+= "~" + ReturnType
.GetSignatureForDocumentation ();
398 public override string GetSignatureForError ()
402 name
= DeclaringType
.GetSignatureForError () + "." + DeclaringType
.Name
;
403 } else if (Kind
== MemberKind
.Operator
) {
404 var op
= Operator
.GetType (Name
).Value
;
405 if (op
== Operator
.OpType
.Implicit
|| op
== Operator
.OpType
.Explicit
) {
406 name
= DeclaringType
.GetSignatureForError () + "." + Operator
.GetName (op
) + " operator " + returnType
.GetSignatureForError ();
408 name
= DeclaringType
.GetSignatureForError () + ".operator " + Operator
.GetName (op
);
410 } else if (IsAccessor
) {
411 int split
= Name
.IndexOf ('_');
412 name
= Name
.Substring (split
+ 1);
413 var postfix
= Name
.Substring (0, split
);
415 var pc
= parameters
.Count
;
416 if (pc
> 0 && postfix
== "get") {
417 name
= "this" + parameters
.GetSignatureForError ("[", "]", pc
);
418 } else if (pc
> 1 && postfix
== "set") {
419 name
= "this" + parameters
.GetSignatureForError ("[", "]", pc
- 1);
423 return DeclaringType
.GetSignatureForError () + "." + name
+ "." + postfix
;
425 name
= base.GetSignatureForError ();
427 name
+= "<" + TypeManager
.CSharpName (targs
) + ">";
429 name
+= "<" + TypeManager
.CSharpName (GenericDefinition
.TypeParameters
) + ">";
432 return name
+ parameters
.GetSignatureForError ();
435 public override MemberSpec
InflateMember (TypeParameterInflator inflator
)
437 var ms
= (MethodSpec
) base.InflateMember (inflator
);
438 ms
.inflatedMetaInfo
= null;
439 ms
.returnType
= inflator
.Inflate (returnType
);
440 ms
.parameters
= parameters
.Inflate (inflator
);
442 ms
.constraints
= TypeParameterSpec
.InflateConstraints (inflator
, Constraints
);
448 int counter
= 100000;
451 public MethodSpec
MakeGenericMethod (IMemberContext context
, params TypeSpec
[] targs
)
454 throw new ArgumentNullException ();
456 // if (generic_intances != null && generic_intances.TryGetValue (targs, out ginstance))
459 //if (generic_intances == null)
460 // generic_intances = new Dictionary<TypeSpec[], Method> (TypeSpecArrayComparer.Default);
462 var inflator
= new TypeParameterInflator (context
, DeclaringType
, GenericDefinition
.TypeParameters
, targs
);
464 var inflated
= (MethodSpec
) MemberwiseClone ();
465 inflated
.declaringType
= inflator
.TypeInstance
;
466 inflated
.returnType
= inflator
.Inflate (returnType
);
467 inflated
.parameters
= parameters
.Inflate (inflator
);
468 inflated
.targs
= targs
;
469 inflated
.constraints
= TypeParameterSpec
.InflateConstraints (inflator
, constraints
?? GenericDefinition
.TypeParameters
);
470 inflated
.state
|= StateFlags
.PendingMakeMethod
;
473 inflated
.ID
+= counter
;
476 // if (inflated.parent == null)
477 // inflated.parent = parent;
479 //generic_intances.Add (targs, inflated);
483 public MethodSpec
Mutate (TypeParameterMutator mutator
)
485 var targs
= TypeArguments
;
487 targs
= mutator
.Mutate (targs
);
489 var decl
= DeclaringType
;
490 if (DeclaringType
.IsGenericOrParentIsGeneric
) {
491 decl
= mutator
.Mutate (decl
);
494 if (targs
== TypeArguments
&& decl
== DeclaringType
)
497 var ms
= (MethodSpec
) MemberwiseClone ();
498 if (decl
!= DeclaringType
) {
499 ms
.inflatedMetaInfo
= null;
500 ms
.declaringType
= decl
;
501 ms
.state
|= StateFlags
.PendingMetaInflate
;
506 ms
.state
|= StateFlags
.PendingMakeMethod
;
512 public override List
<MissingTypeSpecReference
> ResolveMissingDependencies (MemberSpec caller
)
514 var missing
= returnType
.ResolveMissingDependencies (this);
515 foreach (var pt
in parameters
.Types
) {
516 var m
= pt
.GetMissingDependencies (this);
521 missing
= new List
<MissingTypeSpecReference
> ();
523 missing
.AddRange (m
);
527 foreach (var tp
in GenericDefinition
.TypeParameters
) {
528 var m
= tp
.GetMissingDependencies (this);
534 missing
= new List
<MissingTypeSpecReference
> ();
536 missing
.AddRange (m
);
544 public abstract class MethodOrOperator
: MethodCore
, IMethodData
, IMethodDefinition
546 ReturnParameter return_attributes
;
547 SecurityType declarative_security
;
548 protected MethodData MethodData
;
550 static readonly string[] attribute_targets
= new string [] { "method", "return" }
;
552 protected MethodOrOperator (TypeDefinition parent
, FullNamedExpression type
, Modifiers mod
, Modifiers allowed_mod
, MemberName name
,
553 Attributes attrs
, ParametersCompiled parameters
)
554 : base (parent
, type
, mod
, allowed_mod
, name
, attrs
, parameters
)
558 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
560 if (a
.Target
== AttributeTargets
.ReturnValue
) {
561 if (return_attributes
== null)
562 return_attributes
= new ReturnParameter (this, MethodBuilder
, Location
);
564 return_attributes
.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
568 if (a
.Type
== pa
.MethodImpl
) {
569 if ((ModFlags
& Modifiers
.ASYNC
) != 0 && (a
.GetMethodImplOptions () & MethodImplOptions
.Synchronized
) != 0) {
570 Report
.Error (4015, a
.Location
, "`{0}': Async methods cannot use `MethodImplOptions.Synchronized'",
571 GetSignatureForError ());
574 is_external_implementation
= a
.IsInternalCall ();
575 } else if (a
.Type
== pa
.DllImport
) {
576 const Modifiers extern_static
= Modifiers
.EXTERN
| Modifiers
.STATIC
;
577 if ((ModFlags
& extern_static
) != extern_static
) {
578 Report
.Error (601, a
.Location
, "The DllImport attribute must be specified on a method marked `static' and `extern'");
581 if (MemberName
.IsGeneric
|| Parent
.IsGenericOrParentIsGeneric
) {
582 Report
.Error (7042, a
.Location
,
583 "The DllImport attribute cannot be applied to a method that is generic or contained in a generic type");
586 is_external_implementation
= true;
589 if (a
.IsValidSecurityAttribute ()) {
590 a
.ExtractSecurityPermissionSet (ctor
, ref declarative_security
);
594 if (MethodBuilder
!= null)
595 MethodBuilder
.SetCustomAttribute ((ConstructorInfo
) ctor
.GetMetaInfo (), cdata
);
598 public override AttributeTargets AttributeTargets
{
600 return AttributeTargets
.Method
;
604 MethodBase IMethodDefinition
.Metadata
{
606 return MethodData
.MethodBuilder
;
610 // TODO: Remove and use MethodData abstraction
611 public MethodBuilder MethodBuilder
{
613 return MethodData
.MethodBuilder
;
617 protected override bool CheckForDuplications ()
619 return Parent
.MemberCache
.CheckExistingMembersOverloads (this, parameters
);
622 public virtual EmitContext
CreateEmitContext (ILGenerator ig
, SourceMethodBuilder sourceMethod
)
624 return new EmitContext (this, ig
, MemberType
, sourceMethod
);
627 public override bool Define ()
636 if (this is Operator
)
637 kind
= MemberKind
.Operator
;
638 else if (this is Destructor
)
639 kind
= MemberKind
.Destructor
;
641 kind
= MemberKind
.Method
;
643 string explicit_name
;
645 if (IsPartialDefinition
) {
646 caching_flags
&= ~Flags
.Excluded_Undetected
;
647 caching_flags
|= Flags
.Excluded
;
649 // Add to member cache only when a partial method implementation has not been found yet
650 if ((caching_flags
& Flags
.PartialDefinitionExists
) != 0)
656 explicit_name
= null;
658 MethodData
= new MethodData (this, ModFlags
, flags
, this, base_method
);
660 if (!MethodData
.Define (Parent
.PartialContainer
, GetFullName (MemberName
)))
663 explicit_name
= MethodData
.MetadataName
;
666 spec
= new MethodSpec (kind
, Parent
.Definition
, this, ReturnType
, parameters
, ModFlags
);
667 if (MemberName
.Arity
> 0)
668 spec
.IsGeneric
= true;
670 Parent
.MemberCache
.AddMember (this, explicit_name
, spec
);
675 protected override void DoMemberTypeIndependentChecks ()
677 base.DoMemberTypeIndependentChecks ();
679 CheckAbstractAndExtern (block
!= null);
681 if ((ModFlags
& Modifiers
.PARTIAL
) != 0) {
682 for (int i
= 0; i
< parameters
.Count
; ++i
) {
683 IParameterData p
= parameters
.FixedParameters
[i
];
684 if ((p
.ModFlags
& Parameter
.Modifier
.OUT
) != 0) {
685 Report
.Error (752, Location
, "`{0}': A partial method parameters cannot use `out' modifier",
686 GetSignatureForError ());
689 if (p
.HasDefaultValue
&& IsPartialImplementation
)
690 ((Parameter
) p
).Warning_UselessOptionalParameter (Report
);
695 protected override void DoMemberTypeDependentChecks ()
697 base.DoMemberTypeDependentChecks ();
699 if (MemberType
.IsStatic
) {
700 Error_StaticReturnType ();
704 public override void Emit ()
706 if ((ModFlags
& Modifiers
.COMPILER_GENERATED
) != 0 && !Parent
.IsCompilerGenerated
)
707 Module
.PredefinedAttributes
.CompilerGenerated
.EmitAttribute (MethodBuilder
);
708 if ((ModFlags
& Modifiers
.DEBUGGER_HIDDEN
) != 0)
709 Module
.PredefinedAttributes
.DebuggerHidden
.EmitAttribute (MethodBuilder
);
710 if ((ModFlags
& Modifiers
.DEBUGGER_STEP_THROUGH
) != 0)
711 Module
.PredefinedAttributes
.DebuggerStepThrough
.EmitAttribute (MethodBuilder
);
713 if (ReturnType
.BuiltinType
== BuiltinTypeSpec
.Type
.Dynamic
) {
714 return_attributes
= new ReturnParameter (this, MethodBuilder
, Location
);
715 Module
.PredefinedAttributes
.Dynamic
.EmitAttribute (return_attributes
.Builder
);
716 } else if (ReturnType
.HasDynamicElement
) {
717 return_attributes
= new ReturnParameter (this, MethodBuilder
, Location
);
718 Module
.PredefinedAttributes
.Dynamic
.EmitAttribute (return_attributes
.Builder
, ReturnType
, Location
);
721 if (OptAttributes
!= null)
722 OptAttributes
.Emit ();
724 if (declarative_security
!= null) {
725 foreach (var de
in declarative_security
) {
727 MethodBuilder
.__AddDeclarativeSecurity (de
);
729 MethodBuilder
.AddDeclarativeSecurity (de
.Key
, de
.Value
);
735 // Optimization but it also covers cases where we cannot check
736 // constraints because method is captured into generated class
737 // and type parameters context is now different
739 if (type_expr
!= null && !IsCompilerGenerated
)
740 ConstraintChecker
.Check (this, member_type
, type_expr
.Location
);
744 if (MethodData
!= null)
745 MethodData
.Emit (Parent
);
747 if (block
!= null && block
.StateMachine
is AsyncTaskStorey
) {
748 var psm
= Module
.PredefinedAttributes
.AsyncStateMachine
;
749 psm
.EmitAttribute (MethodBuilder
, block
.StateMachine
);
752 if ((ModFlags
& Modifiers
.PARTIAL
) == 0)
756 protected void Error_ConditionalAttributeIsNotValid ()
758 Report
.Error (577, Location
,
759 "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
760 GetSignatureForError ());
763 public bool IsPartialDefinition
{
765 return (ModFlags
& Modifiers
.PARTIAL
) != 0 && Block
== null;
769 public bool IsPartialImplementation
{
771 return (ModFlags
& Modifiers
.PARTIAL
) != 0 && Block
!= null;
775 public override string[] ValidAttributeTargets
{
777 return attribute_targets
;
781 #region IMethodData Members
783 bool IMethodData
.IsAccessor
{
789 public TypeSpec ReturnType
{
795 public MemberName MethodName
{
802 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
804 public override string[] ConditionalConditions ()
806 if ((caching_flags
& (Flags
.Excluded_Undetected
| Flags
.Excluded
)) == 0)
809 if ((ModFlags
& Modifiers
.PARTIAL
) != 0 && (caching_flags
& Flags
.Excluded
) != 0)
810 return new string [0];
812 caching_flags
&= ~Flags
.Excluded_Undetected
;
815 if (base_method
== null) {
816 if (OptAttributes
== null)
819 Attribute
[] attrs
= OptAttributes
.SearchMulti (Module
.PredefinedAttributes
.Conditional
);
823 conditions
= new string[attrs
.Length
];
824 for (int i
= 0; i
< conditions
.Length
; ++i
)
825 conditions
[i
] = attrs
[i
].GetConditionalAttributeValue ();
827 conditions
= base_method
.MemberDefinition
.ConditionalConditions();
830 if (conditions
!= null)
831 caching_flags
|= Flags
.Excluded
;
838 public override void PrepareEmit ()
842 var mb
= MethodData
.DefineMethodBuilder (Parent
);
844 if (CurrentTypeParameters
!= null) {
845 string[] gnames
= new string[CurrentTypeParameters
.Count
];
846 for (int i
= 0; i
< gnames
.Length
; ++i
) {
847 gnames
[i
] = CurrentTypeParameters
[i
].Name
;
850 var gen_params
= MethodBuilder
.DefineGenericParameters (gnames
);
852 for (int i
= 0; i
< CurrentTypeParameters
.Count
; ++i
) {
853 var tp
= CurrentTypeParameters
[i
];
855 tp
.Define (gen_params
[i
]);
860 // Generic method has been already defined to resolve method parameters
861 // correctly when they use type parameters
863 mb
.SetParameters (parameters
.GetMetaInfo ());
864 mb
.SetReturnType (ReturnType
.GetMetaInfo ());
867 public override void WriteDebugSymbol (MonoSymbolFile file
)
869 if (MethodData
!= null && !IsPartialDefinition
)
870 MethodData
.WriteDebugSymbol (file
);
874 public class Method
: MethodOrOperator
, IGenericMethodDefinition
876 Method partialMethodImplementation
;
878 public Method (TypeDefinition parent
, FullNamedExpression return_type
, Modifiers mod
, MemberName name
, ParametersCompiled parameters
, Attributes attrs
)
879 : base (parent
, return_type
, mod
,
880 parent
.PartialContainer
.Kind
== MemberKind
.Interface
? AllowedModifiersInterface
:
881 parent
.PartialContainer
.Kind
== MemberKind
.Struct
? AllowedModifiersStruct
| Modifiers
.ASYNC
:
882 AllowedModifiersClass
| Modifiers
.ASYNC
,
883 name
, attrs
, parameters
)
887 protected Method (TypeDefinition parent
, FullNamedExpression return_type
, Modifiers mod
, Modifiers amod
,
888 MemberName name
, ParametersCompiled parameters
, Attributes attrs
)
889 : base (parent
, return_type
, mod
, amod
, name
, attrs
, parameters
)
895 public override TypeParameters CurrentTypeParameters
{
897 return MemberName
.TypeParameters
;
901 public TypeParameterSpec
[] TypeParameters
{
903 return CurrentTypeParameters
.Types
;
907 public int TypeParametersCount
{
909 return CurrentTypeParameters
== null ? 0 : CurrentTypeParameters
.Count
;
915 public override void Accept (StructuralVisitor visitor
)
917 visitor
.Visit (this);
920 public static Method
Create (TypeDefinition parent
, FullNamedExpression returnType
, Modifiers mod
,
921 MemberName name
, ParametersCompiled parameters
, Attributes attrs
)
923 var m
= new Method (parent
, returnType
, mod
, name
, parameters
, attrs
);
925 if ((mod
& Modifiers
.PARTIAL
) != 0) {
926 const Modifiers invalid_partial_mod
= Modifiers
.AccessibilityMask
| Modifiers
.ABSTRACT
| Modifiers
.EXTERN
|
927 Modifiers
.NEW
| Modifiers
.OVERRIDE
| Modifiers
.SEALED
| Modifiers
.VIRTUAL
;
929 if ((mod
& invalid_partial_mod
) != 0) {
930 m
.Report
.Error (750, m
.Location
,
931 "A partial method cannot define access modifier or any of abstract, extern, new, override, sealed, or virtual modifiers");
932 mod
&= ~invalid_partial_mod
;
935 if ((parent
.ModFlags
& Modifiers
.PARTIAL
) == 0) {
936 m
.Report
.Error (751, m
.Location
,
937 "A partial method must be declared within a partial class or partial struct");
941 if ((mod
& Modifiers
.STATIC
) == 0 && parameters
.HasExtensionMethodType
) {
942 m
.Report
.Error (1105, m
.Location
, "`{0}': Extension methods must be declared static",
943 m
.GetSignatureForError ());
950 public override string GetSignatureForError()
952 return base.GetSignatureForError () + parameters
.GetSignatureForError ();
955 void Error_DuplicateEntryPoint (Method b
)
957 Report
.Error (17, b
.Location
,
958 "Program `{0}' has more than one entry point defined: `{1}'",
959 b
.Module
.Builder
.ScopeName
, b
.GetSignatureForError ());
964 if (ReturnType
.Kind
!= MemberKind
.Void
&& ReturnType
.BuiltinType
!= BuiltinTypeSpec
.Type
.Int
)
967 if (parameters
.IsEmpty
)
970 if (parameters
.Count
> 1)
973 var ac
= parameters
.Types
[0] as ArrayContainer
;
974 return ac
!= null && ac
.Rank
== 1 && ac
.Element
.BuiltinType
== BuiltinTypeSpec
.Type
.String
&&
975 (parameters
[0].ModFlags
& Parameter
.Modifier
.RefOutMask
) == 0;
978 public override FullNamedExpression
LookupNamespaceOrType (string name
, int arity
, LookupMode mode
, Location loc
)
981 var tp
= CurrentTypeParameters
;
983 TypeParameter t
= tp
.Find (name
);
985 return new TypeParameterExpr (t
, loc
);
989 return base.LookupNamespaceOrType (name
, arity
, mode
, loc
);
992 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
994 if (a
.Type
== pa
.Conditional
) {
995 if (IsExplicitImpl
) {
996 Error_ConditionalAttributeIsNotValid ();
1000 if ((ModFlags
& Modifiers
.OVERRIDE
) != 0) {
1001 Report
.Error (243, Location
, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ());
1005 if (ReturnType
.Kind
!= MemberKind
.Void
) {
1006 Report
.Error (578, Location
, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ());
1011 Report
.Error (582, Location
, "Conditional not valid on interface members");
1015 if (MethodData
.implementing
!= null) {
1016 Report
.SymbolRelatedToPreviousError (MethodData
.implementing
.DeclaringType
);
1017 Report
.Error (629, Location
, "Conditional member `{0}' cannot implement interface member `{1}'",
1018 GetSignatureForError (), TypeManager
.CSharpSignature (MethodData
.implementing
));
1022 for (int i
= 0; i
< parameters
.Count
; ++i
) {
1023 if ((parameters
.FixedParameters
[i
].ModFlags
& Parameter
.Modifier
.OUT
) != 0) {
1024 Report
.Error (685, Location
, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
1030 if (a
.Type
== pa
.Extension
) {
1031 a
.Error_MisusedExtensionAttribute ();
1035 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
1038 void CreateTypeParameters ()
1040 var tparams
= MemberName
.TypeParameters
;
1041 var parent_tparams
= Parent
.TypeParametersAll
;
1043 for (int i
= 0; i
< MemberName
.Arity
; i
++) {
1044 string type_argument_name
= tparams
[i
].MemberName
.Name
;
1046 if (block
== null) {
1047 int idx
= parameters
.GetParameterIndexByName (type_argument_name
);
1051 b
= new ToplevelBlock (Compiler
, Location
);
1053 b
.Error_AlreadyDeclaredTypeParameter (type_argument_name
, parameters
[i
].Location
);
1056 INamedBlockVariable variable
= null;
1057 block
.GetLocalName (type_argument_name
, block
, ref variable
);
1058 if (variable
!= null)
1059 variable
.Block
.Error_AlreadyDeclaredTypeParameter (type_argument_name
, variable
.Location
);
1062 if (parent_tparams
!= null) {
1063 var tp
= parent_tparams
.Find (type_argument_name
);
1065 tparams
[i
].WarningParentNameConflict (tp
);
1070 tparams
.Create (null, 0, Parent
);
1073 protected virtual void DefineTypeParameters ()
1075 var tparams
= CurrentTypeParameters
;
1077 TypeParameterSpec
[] base_tparams
= null;
1078 TypeParameterSpec
[] base_decl_tparams
= TypeParameterSpec
.EmptyTypes
;
1079 TypeSpec
[] base_targs
= TypeSpec
.EmptyTypes
;
1080 if (((ModFlags
& Modifiers
.OVERRIDE
) != 0 || IsExplicitImpl
)) {
1081 MethodSpec base_override
= base_method
?? MethodData
.implementing
;
1083 if (base_override
!= null) {
1084 base_tparams
= base_override
.GenericDefinition
.TypeParameters
;
1086 if (base_override
.DeclaringType
.IsGeneric
) {
1087 base_decl_tparams
= base_override
.DeclaringType
.MemberDefinition
.TypeParameters
;
1089 if (base_method
!= null) {
1090 var base_type_parent
= CurrentType
;
1091 while (base_type_parent
.BaseType
!= base_override
.DeclaringType
) {
1092 base_type_parent
= base_type_parent
.BaseType
;
1095 base_targs
= base_type_parent
.BaseType
.TypeArguments
;
1097 foreach (var iface
in Parent
.CurrentType
.Interfaces
) {
1098 if (iface
== base_override
.DeclaringType
) {
1099 base_targs
= iface
.TypeArguments
;
1106 if (base_override
.IsGeneric
) {
1107 foreach (var base_tp
in base_tparams
) {
1108 base_tp
.BaseType
.CheckObsoleteness (this, Location
);
1110 if (base_tp
.InterfacesDefined
!= null) {
1111 foreach (var iface
in base_tp
.InterfacesDefined
) {
1112 iface
.CheckObsoleteness (this, Location
);
1117 if (base_decl_tparams
.Length
!= 0) {
1118 base_decl_tparams
= base_decl_tparams
.Concat (base_tparams
).ToArray ();
1119 base_targs
= base_targs
.Concat (tparams
.Types
).ToArray ();
1121 base_decl_tparams
= base_tparams
;
1122 base_targs
= tparams
.Types
;
1128 for (int i
= 0; i
< tparams
.Count
; ++i
) {
1129 var tp
= tparams
[i
];
1131 if (base_tparams
== null) {
1132 tp
.ResolveConstraints (this);
1137 // Copy base constraints for override/explicit methods
1139 var base_tparam
= base_tparams
[i
];
1140 var local_tparam
= tp
.Type
;
1141 local_tparam
.SpecialConstraint
= base_tparam
.SpecialConstraint
;
1143 var inflator
= new TypeParameterInflator (this, CurrentType
, base_decl_tparams
, base_targs
);
1144 base_tparam
.InflateConstraints (inflator
, local_tparam
);
1147 // Check all type argument constraints for possible collision or unification
1148 // introduced by inflating inherited constraints in this context
1150 // Conflict example:
1152 // class A<T> { virtual void Foo<U> () where U : class, T {} }
1153 // class B : A<int> { override void Foo<U> {} }
1155 var local_tparam_targs
= local_tparam
.TypeArguments
;
1156 if (local_tparam_targs
!= null) {
1157 for (int ii
= 0; ii
< local_tparam_targs
.Length
; ++ii
) {
1158 var ta
= local_tparam_targs
[ii
];
1159 if (!ta
.IsClass
&& !ta
.IsStruct
)
1162 TypeSpec
[] unique_tparams
= null;
1163 for (int iii
= ii
+ 1; iii
< local_tparam_targs
.Length
; ++iii
) {
1165 // Remove any identical or unified constraint types
1167 var tparam_checked
= local_tparam_targs
[iii
];
1168 if (TypeSpecComparer
.IsEqual (ta
, tparam_checked
) || TypeSpec
.IsBaseClass (ta
, tparam_checked
, false)) {
1169 unique_tparams
= new TypeSpec
[local_tparam_targs
.Length
- 1];
1170 Array
.Copy (local_tparam_targs
, 0, unique_tparams
, 0, iii
);
1171 Array
.Copy (local_tparam_targs
, iii
+ 1, unique_tparams
, iii
, local_tparam_targs
.Length
- iii
- 1);
1172 } else if (!TypeSpec
.IsBaseClass (tparam_checked
, ta
, false)) {
1173 Constraints
.Error_ConflictingConstraints (this, local_tparam
, ta
, tparam_checked
, Location
);
1177 if (unique_tparams
!= null) {
1178 local_tparam_targs
= unique_tparams
;
1179 local_tparam
.TypeArguments
= local_tparam_targs
;
1183 Constraints
.CheckConflictingInheritedConstraint (local_tparam
, ta
, this, Location
);
1188 if (base_tparams
== null && MethodData
!= null && MethodData
.implementing
!= null) {
1189 CheckImplementingMethodConstraints (Parent
, spec
, MethodData
.implementing
);
1193 public static bool CheckImplementingMethodConstraints (TypeContainer container
, MethodSpec method
, MethodSpec baseMethod
)
1195 var tparams
= method
.Constraints
;
1196 var base_tparams
= baseMethod
.Constraints
;
1197 for (int i
= 0; i
< tparams
.Length
; ++i
) {
1198 if (!tparams
[i
].HasSameConstraintsImplementation (base_tparams
[i
])) {
1199 container
.Compiler
.Report
.SymbolRelatedToPreviousError (method
);
1200 container
.Compiler
.Report
.SymbolRelatedToPreviousError (baseMethod
);
1202 // Using container location because the interface can be implemented
1204 var tp
= (tparams
[i
].MemberDefinition
as MemberCore
) ?? container
;
1205 container
.Compiler
.Report
.Error (425, tp
.Location
,
1206 "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",
1207 tparams
[i
].GetSignatureForError (), method
.GetSignatureForError (),
1208 base_tparams
[i
].GetSignatureForError (), baseMethod
.GetSignatureForError ());
1220 public override bool Define ()
1222 if (!base.Define ())
1225 if (member_type
.Kind
== MemberKind
.Void
&& parameters
.IsEmpty
&& MemberName
.Arity
== 0 && MemberName
.Name
== Destructor
.MetadataName
) {
1226 Report
.Warning (465, 1, Location
,
1227 "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
1230 if (Compiler
.Settings
.StdLib
&& ReturnType
.IsSpecialRuntimeType
) {
1231 Error1599 (Location
, ReturnType
, Report
);
1235 if (CurrentTypeParameters
== null) {
1236 if (base_method
!= null && !IsExplicitImpl
) {
1237 if (parameters
.Count
== 1 && ParameterTypes
[0].BuiltinType
== BuiltinTypeSpec
.Type
.Object
&& MemberName
.Name
== "Equals")
1238 Parent
.PartialContainer
.Mark_HasEquals ();
1239 else if (parameters
.IsEmpty
&& MemberName
.Name
== "GetHashCode")
1240 Parent
.PartialContainer
.Mark_HasGetHashCode ();
1244 DefineTypeParameters ();
1247 if (block
!= null) {
1248 if (block
.IsIterator
) {
1250 // Current method is turned into automatically generated
1251 // wrapper which creates an instance of iterator
1253 Iterator
.CreateIterator (this, Parent
.PartialContainer
, ModFlags
);
1254 ModFlags
|= Modifiers
.DEBUGGER_HIDDEN
;
1257 if ((ModFlags
& Modifiers
.ASYNC
) != 0) {
1258 if (ReturnType
.Kind
!= MemberKind
.Void
&&
1259 ReturnType
!= Module
.PredefinedTypes
.Task
.TypeSpec
&&
1260 !ReturnType
.IsGenericTask
) {
1261 Report
.Error (1983, Location
, "The return type of an async method must be void, Task, or Task<T>");
1264 block
= (ToplevelBlock
) block
.ConvertToAsyncTask (this, Parent
.PartialContainer
, parameters
, ReturnType
, null, Location
);
1265 ModFlags
|= Modifiers
.DEBUGGER_STEP_THROUGH
;
1268 if (Compiler
.Settings
.WriteMetadataOnly
)
1272 if ((ModFlags
& Modifiers
.STATIC
) == 0)
1275 if (parameters
.HasExtensionMethodType
) {
1276 if (Parent
.PartialContainer
.IsStatic
&& !Parent
.IsGenericOrParentIsGeneric
) {
1277 if (!Parent
.IsTopLevel
)
1278 Report
.Error (1109, Location
, "`{0}': Extension methods cannot be defined in a nested class",
1279 GetSignatureForError ());
1281 PredefinedAttribute pa
= Module
.PredefinedAttributes
.Extension
;
1282 if (!pa
.IsDefined
) {
1283 Report
.Error (1110, Location
,
1284 "`{0}': Extension methods require `System.Runtime.CompilerServices.ExtensionAttribute' type to be available. Are you missing an assembly reference?",
1285 GetSignatureForError ());
1288 ModFlags
|= Modifiers
.METHOD_EXTENSION
;
1289 Parent
.PartialContainer
.ModFlags
|= Modifiers
.METHOD_EXTENSION
;
1290 Spec
.DeclaringType
.SetExtensionMethodContainer ();
1291 Parent
.Module
.HasExtensionMethod
= true;
1293 Report
.Error (1106, Location
, "`{0}': Extension methods must be defined in a non-generic static class",
1294 GetSignatureForError ());
1299 // This is used to track the Entry Point,
1301 var settings
= Compiler
.Settings
;
1302 if (settings
.NeedsEntryPoint
&& MemberName
.Name
== "Main" && !IsPartialDefinition
&& (settings
.MainClass
== null || settings
.MainClass
== Parent
.TypeBuilder
.FullName
)) {
1303 if (IsEntryPoint ()) {
1304 if (Parent
.DeclaringAssembly
.EntryPoint
== null) {
1305 if (Parent
.IsGenericOrParentIsGeneric
|| MemberName
.IsGeneric
) {
1306 Report
.Warning (402, 4, Location
, "`{0}': an entry point cannot be generic or in a generic type",
1307 GetSignatureForError ());
1308 } else if ((ModFlags
& Modifiers
.ASYNC
) != 0) {
1309 Report
.Error (4009, Location
, "`{0}': an entry point cannot be async method",
1310 GetSignatureForError ());
1313 Parent
.DeclaringAssembly
.EntryPoint
= this;
1316 Error_DuplicateEntryPoint (Parent
.DeclaringAssembly
.EntryPoint
);
1317 Error_DuplicateEntryPoint (this);
1320 Report
.Warning (28, 4, Location
, "`{0}' has the wrong signature to be an entry point",
1321 GetSignatureForError ());
1328 public override void PrepareEmit ()
1330 if (IsPartialDefinition
) {
1332 // Use partial method implementation builder for partial method declaration attributes
1334 if (partialMethodImplementation
!= null) {
1335 MethodData
= partialMethodImplementation
.MethodData
;
1341 base.PrepareEmit ();
1347 public override void Emit ()
1350 if (IsPartialDefinition
) {
1351 if (partialMethodImplementation
!= null && CurrentTypeParameters
!= null) {
1352 CurrentTypeParameters
.CheckPartialConstraints (partialMethodImplementation
);
1354 var otp
= partialMethodImplementation
.CurrentTypeParameters
;
1355 for (int i
= 0; i
< CurrentTypeParameters
.Count
; ++i
) {
1356 var tp
= CurrentTypeParameters
[i
];
1364 if ((ModFlags
& Modifiers
.PARTIAL
) != 0 && (caching_flags
& Flags
.PartialDefinitionExists
) == 0) {
1365 Report
.Error (759, Location
, "A partial method `{0}' implementation is missing a partial method declaration",
1366 GetSignatureForError ());
1369 if (CurrentTypeParameters
!= null) {
1370 for (int i
= 0; i
< CurrentTypeParameters
.Count
; ++i
) {
1371 var tp
= CurrentTypeParameters
[i
];
1373 tp
.CheckGenericConstraints (false);
1378 if ((ModFlags
& Modifiers
.METHOD_EXTENSION
) != 0)
1379 Module
.PredefinedAttributes
.Extension
.EmitAttribute (MethodBuilder
);
1382 } catch (Exception e
) {
1383 throw new InternalErrorException (this, e
);
1387 public override bool EnableOverloadChecks (MemberCore overload
)
1389 if (overload
is Indexer
)
1392 return base.EnableOverloadChecks (overload
);
1395 public static void Error1599 (Location loc
, TypeSpec t
, Report Report
)
1397 Report
.Error (1599, loc
, "Method or delegate cannot return type `{0}'", t
.GetSignatureForError ());
1400 protected override bool ResolveMemberType ()
1402 if (CurrentTypeParameters
!= null) {
1403 CreateTypeParameters ();
1406 return base.ResolveMemberType ();
1409 public void SetPartialDefinition (Method methodDefinition
)
1411 caching_flags
|= Flags
.PartialDefinitionExists
;
1412 methodDefinition
.partialMethodImplementation
= this;
1414 // Ensure we are always using method declaration parameters
1415 for (int i
= 0; i
< methodDefinition
.parameters
.Count
; ++i
) {
1416 var md_p
= methodDefinition
.parameters
[i
];
1417 var p
= parameters
[i
];
1419 p
.DefaultValue
= md_p
.DefaultValue
;
1420 if (md_p
.OptAttributes
!= null) {
1421 Attributes
.AttachFromPartial (p
, md_p
);
1425 if (methodDefinition
.attributes
!= null) {
1426 if (attributes
== null) {
1427 attributes
= methodDefinition
.attributes
;
1429 attributes
.Attrs
.AddRange (methodDefinition
.attributes
.Attrs
);
1433 if (CurrentTypeParameters
!= null) {
1434 for (int i
= 0; i
< CurrentTypeParameters
.Count
; ++i
) {
1435 var tp_other
= methodDefinition
.CurrentTypeParameters
[i
];
1436 if (tp_other
.OptAttributes
== null)
1439 var tp
= CurrentTypeParameters
[i
];
1440 if (tp
.OptAttributes
== null) {
1441 tp
.OptAttributes
= tp_other
.OptAttributes
;
1443 tp
.OptAttributes
.Attrs
.AddRange (tp
.OptAttributes
.Attrs
);
1450 public abstract class ConstructorInitializer
: ExpressionStatement
1452 Arguments argument_list
;
1453 MethodSpec base_ctor
;
1455 protected ConstructorInitializer (Arguments argument_list
, Location loc
)
1457 this.argument_list
= argument_list
;
1461 public Arguments Arguments
{
1463 return argument_list
;
1467 public override bool ContainsEmitWithAwait ()
1469 throw new NotSupportedException ();
1472 public override Expression
CreateExpressionTree (ResolveContext ec
)
1474 throw new NotSupportedException ("ET");
1477 protected override Expression
DoResolve (ResolveContext ec
)
1479 eclass
= ExprClass
.Value
;
1482 var caller_builder
= (Constructor
) ec
.MemberContext
;
1485 // Spec mandates that constructor initializer will not have `this' access
1487 using (ec
.Set (ResolveContext
.Options
.BaseInitializer
)) {
1488 if (argument_list
!= null) {
1490 argument_list
.Resolve (ec
, out dynamic);
1493 ec
.Report
.Error (1975, loc
,
1494 "The constructor call cannot be dynamically dispatched within constructor initializer");
1500 type
= ec
.CurrentType
;
1501 if (this is ConstructorBaseInitializer
) {
1502 if (ec
.CurrentType
.BaseType
== null)
1505 type
= ec
.CurrentType
.BaseType
;
1506 if (ec
.CurrentType
.IsStruct
) {
1507 ec
.Report
.Error (522, loc
,
1508 "`{0}': Struct constructors cannot call base constructors", caller_builder
.GetSignatureForError ());
1513 base_ctor
= ConstructorLookup (ec
, type
, ref argument_list
, loc
);
1516 if (base_ctor
!= null && base_ctor
.MemberDefinition
== caller_builder
.Spec
.MemberDefinition
) {
1517 ec
.Report
.Error (516, loc
, "Constructor `{0}' cannot call itself",
1518 caller_builder
.GetSignatureForError ());
1524 public override void Emit (EmitContext ec
)
1527 // It can be null for struct initializers or System.Object
1529 if (base_ctor
== null) {
1530 if (type
== ec
.BuiltinTypes
.Object
)
1533 ec
.Emit (OpCodes
.Ldarg_0
);
1534 ec
.Emit (OpCodes
.Initobj
, type
);
1538 var call
= new CallEmitter ();
1539 call
.InstanceExpression
= new CompilerGeneratedThis (type
, loc
);
1540 call
.EmitPredefined (ec
, base_ctor
, argument_list
, false);
1543 public override void EmitStatement (EmitContext ec
)
1548 public override void FlowAnalysis (FlowAnalysisContext fc
)
1550 if (argument_list
!= null)
1551 argument_list
.FlowAnalysis (fc
);
1555 public class ConstructorBaseInitializer
: ConstructorInitializer
{
1556 public ConstructorBaseInitializer (Arguments argument_list
, Location l
) :
1557 base (argument_list
, l
)
1562 class GeneratedBaseInitializer
: ConstructorBaseInitializer
{
1563 public GeneratedBaseInitializer (Location loc
, Arguments arguments
)
1564 : base (arguments
, loc
)
1569 public class ConstructorThisInitializer
: ConstructorInitializer
{
1570 public ConstructorThisInitializer (Arguments argument_list
, Location l
) :
1571 base (argument_list
, l
)
1576 public class Constructor
: MethodCore
, IMethodData
, IMethodDefinition
1578 public ConstructorBuilder ConstructorBuilder
;
1579 public ConstructorInitializer Initializer
;
1580 SecurityType declarative_security
;
1581 bool has_compliant_args
;
1582 SourceMethodBuilder debug_builder
;
1585 // Modifiers allowed for a constructor.
1587 public const Modifiers AllowedModifiers
=
1589 Modifiers
.PROTECTED
|
1590 Modifiers
.INTERNAL
|
1596 static readonly string[] attribute_targets
= new string [] { "method" }
;
1598 public static readonly string ConstructorName
= ".ctor";
1599 public static readonly string TypeConstructorName
= ".cctor";
1601 public Constructor (TypeDefinition parent
, string name
, Modifiers mod
, Attributes attrs
, ParametersCompiled args
, Location loc
)
1602 : base (parent
, null, mod
, AllowedModifiers
, new MemberName (name
, loc
), attrs
, args
)
1606 public bool HasCompliantArgs
{
1608 return has_compliant_args
;
1612 public override AttributeTargets AttributeTargets
{
1614 return AttributeTargets
.Constructor
;
1618 bool IMethodData
.IsAccessor
{
1624 public bool IsPrimaryConstructor { get; set; }
1626 MethodBase IMethodDefinition
.Metadata
{
1628 return ConstructorBuilder
;
1633 // Returns true if this is a default constructor
1635 public bool IsDefault ()
1637 if ((ModFlags
& Modifiers
.STATIC
) != 0)
1638 return parameters
.IsEmpty
;
1640 return parameters
.IsEmpty
&&
1641 (Initializer
is ConstructorBaseInitializer
) &&
1642 (Initializer
.Arguments
== null);
1645 public override void Accept (StructuralVisitor visitor
)
1647 visitor
.Visit (this);
1650 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
1652 if (a
.IsValidSecurityAttribute ()) {
1653 a
.ExtractSecurityPermissionSet (ctor
, ref declarative_security
);
1657 if (a
.Type
== pa
.MethodImpl
) {
1658 is_external_implementation
= a
.IsInternalCall ();
1661 ConstructorBuilder
.SetCustomAttribute ((ConstructorInfo
) ctor
.GetMetaInfo (), cdata
);
1664 protected override bool CheckBase ()
1666 if ((ModFlags
& Modifiers
.STATIC
) != 0) {
1667 if ((caching_flags
& Flags
.MethodOverloadsExist
) != 0)
1668 Parent
.MemberCache
.CheckExistingMembersOverloads (this, parameters
);
1670 // the rest can be ignored
1674 // Check whether arguments were correct.
1675 if (!DefineParameters (parameters
))
1678 if ((caching_flags
& Flags
.MethodOverloadsExist
) != 0)
1679 Parent
.MemberCache
.CheckExistingMembersOverloads (this, parameters
);
1681 CheckProtectedModifier ();
1687 // Creates the ConstructorBuilder
1689 public override bool Define ()
1691 if (ConstructorBuilder
!= null)
1694 if (!CheckAbstractAndExtern (block
!= null))
1697 // Check if arguments were correct.
1701 if (Parent
.PrimaryConstructorParameters
!= null && !IsPrimaryConstructor
&& !IsStatic
) {
1702 if (Parent
.Kind
== MemberKind
.Struct
&& Initializer
is ConstructorThisInitializer
&& Initializer
.Arguments
== null) {
1703 Report
.Error (8043, Location
, "`{0}': Structs with primary constructor cannot specify default constructor initializer",
1704 GetSignatureForError ());
1705 } else if (Initializer
== null || Initializer
is ConstructorBaseInitializer
) {
1706 Report
.Error (8037, Location
, "`{0}': Instance constructor of type with primary constructor must specify `this' constructor initializer",
1707 GetSignatureForError ());
1711 if ((ModFlags
& Modifiers
.EXTERN
) != 0 && Initializer
!= null) {
1712 Report
.Error (8091, Location
, "`{0}': Contructors cannot be extern and have a constructor initializer",
1713 GetSignatureForError ());
1716 var ca
= ModifiersExtensions
.MethodAttr (ModFlags
) | MethodAttributes
.RTSpecialName
| MethodAttributes
.SpecialName
;
1718 ConstructorBuilder
= Parent
.TypeBuilder
.DefineConstructor (
1719 ca
, CallingConventions
,
1720 parameters
.GetMetaInfo ());
1722 spec
= new MethodSpec (MemberKind
.Constructor
, Parent
.Definition
, this, Compiler
.BuiltinTypes
.Void
, parameters
, ModFlags
);
1724 Parent
.MemberCache
.AddMember (spec
);
1726 if (block
!= null) {
1727 // It's here only to report an error
1728 if (block
.IsIterator
) {
1729 member_type
= Compiler
.BuiltinTypes
.Void
;
1730 Iterator
.CreateIterator (this, Parent
.PartialContainer
, ModFlags
);
1733 if (Compiler
.Settings
.WriteMetadataOnly
)
1743 public override void Emit ()
1745 if (Parent
.PartialContainer
.IsComImport
) {
1746 if (!IsDefault ()) {
1747 Report
.Error (669, Location
, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
1748 Parent
.GetSignatureForError ());
1751 // Set as internal implementation and reset block data
1752 // to ensure no IL is generated
1753 ConstructorBuilder
.SetImplementationFlags (MethodImplAttributes
.InternalCall
);
1757 if ((ModFlags
& Modifiers
.DEBUGGER_HIDDEN
) != 0)
1758 Module
.PredefinedAttributes
.DebuggerHidden
.EmitAttribute (ConstructorBuilder
);
1760 if (OptAttributes
!= null)
1761 OptAttributes
.Emit ();
1764 parameters
.ApplyAttributes (this, ConstructorBuilder
);
1767 BlockContext bc
= new BlockContext (this, block
, Compiler
.BuiltinTypes
.Void
);
1768 bc
.Set (ResolveContext
.Options
.ConstructorScope
);
1770 if (block
!= null) {
1771 if (!IsStatic
&& Initializer
== null && Parent
.PartialContainer
.Kind
== MemberKind
.Struct
) {
1773 // If this is a non-static `struct' constructor and doesn't have any
1774 // initializer, it must initialize all of the struct's fields.
1776 block
.AddThisVariable (bc
);
1780 // If we use a "this (...)" constructor initializer, then
1781 // do not emit field initializers, they are initialized in the other constructor
1783 if (!(Initializer
is ConstructorThisInitializer
)) {
1784 var errors
= Compiler
.Report
.Errors
;
1785 Parent
.PartialContainer
.ResolveFieldInitializers (bc
);
1786 if (errors
!= Compiler
.Report
.Errors
)
1791 if (Initializer
== null && Parent
.PartialContainer
.Kind
== MemberKind
.Class
) {
1792 Initializer
= new GeneratedBaseInitializer (Location
, null);
1795 if (Initializer
!= null) {
1797 // mdb format does not support reqions. Try to workaround this by emitting the
1798 // sequence point at initializer. Any breakpoint at constructor header should
1799 // be adjusted to this sequence point as it's the next one which follows.
1801 block
.AddScopeStatement (new StatementExpression (Initializer
));
1805 if (block
.Resolve (bc
, this)) {
1806 debug_builder
= Parent
.CreateMethodSymbolEntry ();
1807 EmitContext ec
= new EmitContext (this, ConstructorBuilder
.GetILGenerator (), bc
.ReturnType
, debug_builder
);
1808 ec
.With (EmitContext
.Options
.ConstructorScope
, true);
1814 if (declarative_security
!= null) {
1815 foreach (var de
in declarative_security
) {
1817 ConstructorBuilder
.__AddDeclarativeSecurity (de
);
1819 ConstructorBuilder
.AddDeclarativeSecurity (de
.Key
, de
.Value
);
1827 protected override MemberSpec
FindBaseMember (out MemberSpec bestCandidate
, ref bool overrides
)
1829 // Is never override
1830 bestCandidate
= null;
1834 public override string GetCallerMemberName ()
1836 return IsStatic
? TypeConstructorName
: ConstructorName
;
1839 public override string GetSignatureForDocumentation ()
1841 return Parent
.GetSignatureForDocumentation () + ".#ctor" + parameters
.GetSignatureForDocumentation ();
1844 public override string GetSignatureForError()
1846 return base.GetSignatureForError () + parameters
.GetSignatureForError ();
1849 public override string[] ValidAttributeTargets
{
1851 return attribute_targets
;
1855 protected override bool VerifyClsCompliance ()
1857 if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
1861 if (!parameters
.IsEmpty
&& Parent
.Definition
.IsAttribute
) {
1862 foreach (TypeSpec param
in parameters
.Types
) {
1863 if (param
.IsArray
) {
1869 has_compliant_args
= true;
1873 public override void WriteDebugSymbol (MonoSymbolFile file
)
1875 if (debug_builder
== null)
1878 var token
= ConstructorBuilder
.GetToken ();
1879 int t
= token
.Token
;
1881 if (ModuleBuilder
.IsPseudoToken (t
))
1882 t
= Module
.Builder
.ResolvePseudoToken (t
);
1885 debug_builder
.DefineMethod (file
, t
);
1888 #region IMethodData Members
1890 public MemberName MethodName
{
1896 public TypeSpec ReturnType
{
1902 EmitContext IMethodData
.CreateEmitContext (ILGenerator ig
, SourceMethodBuilder sourceMethod
)
1904 throw new NotImplementedException ();
1911 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
1913 public interface IMethodData
: IMemberContext
1915 CallingConventions CallingConventions { get; }
1916 Location Location { get; }
1917 MemberName MethodName { get; }
1918 TypeSpec ReturnType { get; }
1919 ParametersCompiled ParameterInfo { get; }
1920 MethodSpec Spec { get; }
1921 bool IsAccessor { get; }
1923 Attributes OptAttributes { get; }
1924 ToplevelBlock Block { get; set; }
1926 EmitContext
CreateEmitContext (ILGenerator ig
, SourceMethodBuilder sourceMethod
);
1930 // Encapsulates most of the Method's state
1932 public class MethodData
1934 public readonly IMethodData method
;
1937 // Are we implementing an interface ?
1939 public MethodSpec implementing
;
1944 protected InterfaceMemberBase member
;
1945 protected Modifiers modifiers
;
1946 protected MethodAttributes flags
;
1947 protected TypeSpec declaring_type
;
1948 protected MethodSpec parent_method
;
1949 SourceMethodBuilder debug_builder
;
1952 MethodBuilder builder
;
1953 public MethodBuilder MethodBuilder
{
1959 public TypeSpec DeclaringType
{
1961 return declaring_type
;
1965 public string MetadataName
{
1971 public MethodData (InterfaceMemberBase member
,
1972 Modifiers modifiers
, MethodAttributes flags
, IMethodData method
)
1974 this.member
= member
;
1975 this.modifiers
= modifiers
;
1978 this.method
= method
;
1981 public MethodData (InterfaceMemberBase member
,
1982 Modifiers modifiers
, MethodAttributes flags
,
1984 MethodSpec parent_method
)
1985 : this (member
, modifiers
, flags
, method
)
1987 this.parent_method
= parent_method
;
1990 public bool Define (TypeDefinition container
, string method_full_name
)
1992 PendingImplementation pending
= container
.PendingImplementations
;
1993 MethodSpec ambig_iface_method
;
1994 bool optional
= false;
1996 if (pending
!= null) {
1997 implementing
= pending
.IsInterfaceMethod (method
.MethodName
, member
.InterfaceType
, this, out ambig_iface_method
, ref optional
);
1999 if (member
.InterfaceType
!= null) {
2000 if (implementing
== null) {
2001 if (member
is PropertyBase
) {
2002 container
.Compiler
.Report
.Error (550, method
.Location
,
2003 "`{0}' is an accessor not found in interface member `{1}{2}'",
2004 method
.GetSignatureForError (), member
.InterfaceType
.GetSignatureForError (),
2005 member
.GetSignatureForError ().Substring (member
.GetSignatureForError ().LastIndexOf ('.')));
2008 container
.Compiler
.Report
.Error (539, method
.Location
,
2009 "`{0}.{1}' in explicit interface declaration is not a member of interface",
2010 member
.InterfaceType
.GetSignatureForError (), member
.ShortName
);
2014 if (implementing
.IsAccessor
&& !method
.IsAccessor
) {
2015 container
.Compiler
.Report
.SymbolRelatedToPreviousError (implementing
);
2016 container
.Compiler
.Report
.Error (683, method
.Location
,
2017 "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
2018 member
.GetSignatureForError (), implementing
.GetSignatureForError ());
2022 if (implementing
!= null && !optional
) {
2023 if (!method
.IsAccessor
) {
2024 if (implementing
.IsAccessor
) {
2025 container
.Compiler
.Report
.SymbolRelatedToPreviousError (implementing
);
2026 container
.Compiler
.Report
.Error (470, method
.Location
,
2027 "Method `{0}' cannot implement interface accessor `{1}'",
2028 method
.GetSignatureForError (), TypeManager
.CSharpSignature (implementing
));
2030 } else if (implementing
.DeclaringType
.IsInterface
) {
2031 if (!implementing
.IsAccessor
) {
2032 container
.Compiler
.Report
.SymbolRelatedToPreviousError (implementing
);
2033 container
.Compiler
.Report
.Error (686, method
.Location
,
2034 "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
2035 method
.GetSignatureForError (), TypeManager
.CSharpSignature (implementing
), container
.GetSignatureForError ());
2037 PropertyBase
.PropertyMethod pm
= method
as PropertyBase
.PropertyMethod
;
2038 if (pm
!= null && pm
.HasCustomAccessModifier
&& (pm
.ModFlags
& Modifiers
.PUBLIC
) == 0) {
2039 container
.Compiler
.Report
.SymbolRelatedToPreviousError (implementing
);
2040 container
.Compiler
.Report
.Error (277, method
.Location
,
2041 "Accessor `{0}' must be declared public to implement interface member `{1}'",
2042 method
.GetSignatureForError (), implementing
.GetSignatureForError ());
2049 ambig_iface_method
= null;
2053 // For implicit implementations, make sure we are public, for
2054 // explicit implementations, make sure we are private.
2056 if (implementing
!= null){
2057 if (member
.IsExplicitImpl
) {
2058 if (method
.ParameterInfo
.HasParams
&& !implementing
.Parameters
.HasParams
) {
2059 container
.Compiler
.Report
.SymbolRelatedToPreviousError (implementing
);
2060 container
.Compiler
.Report
.Error (466, method
.Location
,
2061 "`{0}': the explicit interface implementation cannot introduce the params modifier",
2062 method
.GetSignatureForError ());
2065 if (ambig_iface_method
!= null) {
2066 container
.Compiler
.Report
.SymbolRelatedToPreviousError (ambig_iface_method
);
2067 container
.Compiler
.Report
.SymbolRelatedToPreviousError (implementing
);
2068 container
.Compiler
.Report
.Warning (473, 2, method
.Location
,
2069 "Explicit interface implementation `{0}' matches more than one interface member. Consider using a non-explicit implementation instead",
2070 method
.GetSignatureForError ());
2074 // Setting implementin to null inside this block will trigger a more
2075 // verbose error reporting for missing interface implementations
2077 if (implementing
.DeclaringType
.IsInterface
) {
2079 // If this is an interface method implementation,
2080 // check for public accessibility
2082 if ((flags
& MethodAttributes
.MemberAccessMask
) != MethodAttributes
.Public
) {
2083 implementing
= null;
2084 } else if (optional
&& (container
.Interfaces
== null || !container
.Definition
.Interfaces
.Contains (implementing
.DeclaringType
))) {
2086 // We are not implementing interface when base class already implemented it
2088 implementing
= null;
2090 } else if ((flags
& MethodAttributes
.MemberAccessMask
) == MethodAttributes
.Private
) {
2091 // We may never be private.
2092 implementing
= null;
2094 } else if ((modifiers
& Modifiers
.OVERRIDE
) == 0) {
2096 // We may be protected if we're overriding something.
2098 implementing
= null;
2103 // Static is not allowed
2105 if ((modifiers
& Modifiers
.STATIC
) != 0){
2106 implementing
= null;
2111 // If implementing is still valid, set flags
2113 if (implementing
!= null){
2115 // When implementing interface methods, set NewSlot
2116 // unless, we are overwriting a method.
2118 if ((modifiers
& Modifiers
.OVERRIDE
) == 0 && implementing
.DeclaringType
.IsInterface
) {
2119 flags
|= MethodAttributes
.NewSlot
;
2122 flags
|= MethodAttributes
.Virtual
| MethodAttributes
.HideBySig
;
2124 // Set Final unless we're virtual, abstract or already overriding a method.
2125 if ((modifiers
& (Modifiers
.VIRTUAL
| Modifiers
.ABSTRACT
| Modifiers
.OVERRIDE
)) == 0)
2126 flags
|= MethodAttributes
.Final
;
2129 // clear the pending implementation flag (requires explicit methods to be defined first)
2131 pending
.ImplementMethod (method
.MethodName
,
2132 member
.InterfaceType
, this, member
.IsExplicitImpl
, out ambig_iface_method
, ref optional
);
2135 // Update indexer accessor name to match implementing abstract accessor
2137 if (!implementing
.DeclaringType
.IsInterface
&& !member
.IsExplicitImpl
&& implementing
.IsAccessor
)
2138 method_full_name
= implementing
.MemberDefinition
.Name
;
2141 full_name
= method_full_name
;
2142 declaring_type
= container
.Definition
;
2147 void DefineOverride (TypeDefinition container
)
2149 if (implementing
== null)
2152 if (!member
.IsExplicitImpl
)
2155 container
.TypeBuilder
.DefineMethodOverride (builder
, (MethodInfo
) implementing
.GetMetaInfo ());
2159 // Creates partial MethodBuilder for the method when has generic parameters used
2160 // as arguments or return type
2162 public MethodBuilder
DefineMethodBuilder (TypeDefinition container
)
2164 if (builder
!= null)
2165 throw new InternalErrorException ();
2167 builder
= container
.TypeBuilder
.DefineMethod (full_name
, flags
, method
.CallingConventions
);
2172 // Creates full MethodBuilder for the method
2174 public MethodBuilder
DefineMethodBuilder (TypeDefinition container
, ParametersCompiled param
)
2176 DefineMethodBuilder (container
);
2177 builder
.SetReturnType (method
.ReturnType
.GetMetaInfo ());
2178 builder
.SetParameters (param
.GetMetaInfo ());
2185 public void Emit (TypeDefinition parent
)
2187 DefineOverride (parent
);
2189 method
.ParameterInfo
.ApplyAttributes (method
, MethodBuilder
);
2191 ToplevelBlock block
= method
.Block
;
2192 if (block
!= null) {
2193 BlockContext bc
= new BlockContext (method
, block
, method
.ReturnType
);
2194 if (block
.Resolve (bc
, method
)) {
2195 debug_builder
= member
.Parent
.CreateMethodSymbolEntry ();
2196 EmitContext ec
= method
.CreateEmitContext (MethodBuilder
.GetILGenerator (), debug_builder
);
2203 public void WriteDebugSymbol (MonoSymbolFile file
)
2205 if (debug_builder
== null)
2208 var token
= builder
.GetToken ();
2209 int t
= token
.Token
;
2211 if (ModuleBuilder
.IsPseudoToken (t
))
2212 t
= member
.Module
.Builder
.ResolvePseudoToken (t
);
2215 debug_builder
.DefineMethod (file
, t
);
2219 public class Destructor
: MethodOrOperator
2221 const Modifiers AllowedModifiers
=
2225 static readonly string[] attribute_targets
= new string [] { "method" }
;
2227 public static readonly string MetadataName
= "Finalize";
2229 public Destructor (TypeDefinition parent
, Modifiers mod
, ParametersCompiled parameters
, Attributes attrs
, Location l
)
2230 : base (parent
, null, mod
, AllowedModifiers
, new MemberName (MetadataName
, l
), attrs
, parameters
)
2232 ModFlags
&= ~Modifiers
.PRIVATE
;
2233 ModFlags
|= Modifiers
.PROTECTED
| Modifiers
.OVERRIDE
;
2236 public override void Accept (StructuralVisitor visitor
)
2238 visitor
.Visit (this);
2241 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
2243 if (a
.Type
== pa
.Conditional
) {
2244 Error_ConditionalAttributeIsNotValid ();
2248 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
2251 protected override bool CheckBase ()
2253 if ((caching_flags
& Flags
.MethodOverloadsExist
) != 0)
2254 CheckForDuplications ();
2256 // Don't check base, destructors have special syntax
2260 public override bool Define ()
2264 if (Compiler
.Settings
.WriteMetadataOnly
)
2270 public override void Emit()
2272 var base_type
= Parent
.PartialContainer
.BaseType
;
2273 if (base_type
!= null && Block
!= null) {
2274 var base_dtor
= MemberCache
.FindMember (base_type
,
2275 new MemberFilter (MetadataName
, 0, MemberKind
.Destructor
, null, null), BindingRestriction
.InstanceOnly
) as MethodSpec
;
2277 if (base_dtor
== null)
2278 throw new NotImplementedException ();
2280 MethodGroupExpr method_expr
= MethodGroupExpr
.CreatePredefined (base_dtor
, base_type
, Location
);
2281 method_expr
.InstanceExpression
= new BaseThis (base_type
, Location
);
2283 var try_block
= new ExplicitBlock (block
, block
.StartLocation
, block
.EndLocation
) {
2284 IsCompilerGenerated
= true
2286 var finaly_block
= new ExplicitBlock (block
, Location
, Location
) {
2287 IsCompilerGenerated
= true
2291 // 0-size arguments to avoid CS0250 error
2292 // TODO: Should use AddScopeStatement or something else which emits correct
2295 finaly_block
.AddStatement (new StatementExpression (new Invocation (method_expr
, new Arguments (0)), Location
.Null
));
2297 var tf
= new TryFinally (try_block
, finaly_block
, Location
);
2298 block
.WrapIntoDestructor (tf
, try_block
);
2304 public override string GetSignatureForError ()
2306 return Parent
.GetSignatureForError () + ".~" + Parent
.MemberName
.Name
+ "()";
2309 protected override bool ResolveMemberType ()
2311 member_type
= Compiler
.BuiltinTypes
.Void
;
2315 public override string[] ValidAttributeTargets
{
2317 return attribute_targets
;
2322 // Ooouh Martin, templates are missing here.
2323 // When it will be possible move here a lot of child code and template method type.
2324 public abstract class AbstractPropertyEventMethod
: MemberCore
, IMethodData
, IMethodDefinition
{
2325 protected MethodData method_data
;
2326 protected ToplevelBlock block
;
2327 protected SecurityType declarative_security
;
2329 protected readonly string prefix
;
2331 ReturnParameter return_attributes
;
2333 protected AbstractPropertyEventMethod (InterfaceMemberBase member
, string prefix
, Attributes attrs
, Location loc
)
2334 : base (member
.Parent
, SetupName (prefix
, member
, loc
), attrs
)
2336 this.prefix
= prefix
;
2339 static MemberName
SetupName (string prefix
, InterfaceMemberBase member
, Location loc
)
2341 return new MemberName (member
.MemberName
.Left
, prefix
+ member
.ShortName
, member
.MemberName
.ExplicitInterface
, loc
);
2344 public void UpdateName (InterfaceMemberBase member
)
2346 SetMemberName (SetupName (prefix
, member
, Location
));
2349 #region IMethodData Members
2351 public ToplevelBlock Block
{
2361 public CallingConventions CallingConventions
{
2363 return CallingConventions
.Standard
;
2367 public EmitContext
CreateEmitContext (ILGenerator ig
, SourceMethodBuilder sourceMethod
)
2369 return new EmitContext (this, ig
, ReturnType
, sourceMethod
);
2372 public bool IsAccessor
{
2378 public MemberName MethodName
{
2384 public TypeSpec
[] ParameterTypes
{
2386 return ParameterInfo
.Types
;
2390 MethodBase IMethodDefinition
.Metadata
{
2392 return method_data
.MethodBuilder
;
2396 public abstract ParametersCompiled ParameterInfo { get ; }
2397 public abstract TypeSpec ReturnType { get; }
2401 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
2403 if (a
.Type
== pa
.CLSCompliant
|| a
.Type
== pa
.Obsolete
|| a
.Type
== pa
.Conditional
) {
2404 Report
.Error (1667, a
.Location
,
2405 "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
2406 a
.Type
.GetSignatureForError (), a
.GetValidTargets ());
2410 if (a
.IsValidSecurityAttribute ()) {
2411 a
.ExtractSecurityPermissionSet (ctor
, ref declarative_security
);
2415 if (a
.Target
== AttributeTargets
.Method
) {
2416 method_data
.MethodBuilder
.SetCustomAttribute ((ConstructorInfo
) ctor
.GetMetaInfo (), cdata
);
2420 if (a
.Target
== AttributeTargets
.ReturnValue
) {
2421 if (return_attributes
== null)
2422 return_attributes
= new ReturnParameter (this, method_data
.MethodBuilder
, Location
);
2424 return_attributes
.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
2428 ApplyToExtraTarget (a
, ctor
, cdata
, pa
);
2431 protected virtual void ApplyToExtraTarget (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
2433 throw new NotSupportedException ("You forgot to define special attribute target handling");
2436 // It is not supported for the accessors
2437 public sealed override bool Define()
2439 throw new NotSupportedException ();
2442 public virtual void Emit (TypeDefinition parent
)
2444 method_data
.Emit (parent
);
2446 if ((ModFlags
& Modifiers
.COMPILER_GENERATED
) != 0 && !Parent
.IsCompilerGenerated
)
2447 Module
.PredefinedAttributes
.CompilerGenerated
.EmitAttribute (method_data
.MethodBuilder
);
2448 if (((ModFlags
& Modifiers
.DEBUGGER_HIDDEN
) != 0))
2449 Module
.PredefinedAttributes
.DebuggerHidden
.EmitAttribute (method_data
.MethodBuilder
);
2451 if (ReturnType
.BuiltinType
== BuiltinTypeSpec
.Type
.Dynamic
) {
2452 return_attributes
= new ReturnParameter (this, method_data
.MethodBuilder
, Location
);
2453 Module
.PredefinedAttributes
.Dynamic
.EmitAttribute (return_attributes
.Builder
);
2454 } else if (ReturnType
.HasDynamicElement
) {
2455 return_attributes
= new ReturnParameter (this, method_data
.MethodBuilder
, Location
);
2456 Module
.PredefinedAttributes
.Dynamic
.EmitAttribute (return_attributes
.Builder
, ReturnType
, Location
);
2459 if (OptAttributes
!= null)
2460 OptAttributes
.Emit ();
2462 if (declarative_security
!= null) {
2463 foreach (var de
in declarative_security
) {
2465 method_data
.MethodBuilder
.__AddDeclarativeSecurity (de
);
2467 method_data
.MethodBuilder
.AddDeclarativeSecurity (de
.Key
, de
.Value
);
2475 public override bool EnableOverloadChecks (MemberCore overload
)
2477 if (overload
is MethodCore
) {
2478 caching_flags
|= Flags
.MethodOverloadsExist
;
2482 // This can only happen with indexers and it will
2483 // be catched as indexer difference
2484 if (overload
is AbstractPropertyEventMethod
)
2490 public override string GetCallerMemberName ()
2492 return base.GetCallerMemberName ().Substring (prefix
.Length
);
2495 public override string GetSignatureForDocumentation ()
2497 // should not be called
2498 throw new NotSupportedException ();
2501 public override bool IsClsComplianceRequired()
2506 public void PrepareEmit ()
2508 method_data
.DefineMethodBuilder (Parent
.PartialContainer
, ParameterInfo
);
2511 public override void WriteDebugSymbol (MonoSymbolFile file
)
2513 if (method_data
!= null)
2514 method_data
.WriteDebugSymbol (file
);
2517 public MethodSpec Spec { get; protected set; }
2520 // Represents header string for documentation comment.
2522 public override string DocCommentHeader
{
2523 get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
2527 public class Operator
: MethodOrOperator
{
2529 const Modifiers AllowedModifiers
=
2535 public enum OpType
: byte {
2545 // Unary and Binary operators
2568 // Implicit and Explicit
2575 // Just because of enum
2579 public readonly OpType OperatorType
;
2581 static readonly string [] [] names
;
2585 names
= new string[(int)OpType
.TOP
][];
2586 names
[(int) OpType
.LogicalNot
] = new string [] { "!", "op_LogicalNot" }
;
2587 names
[(int) OpType
.OnesComplement
] = new string [] { "~", "op_OnesComplement" }
;
2588 names
[(int) OpType
.Increment
] = new string [] { "++", "op_Increment" }
;
2589 names
[(int) OpType
.Decrement
] = new string [] { "--", "op_Decrement" }
;
2590 names
[(int) OpType
.True
] = new string [] { "true", "op_True" }
;
2591 names
[(int) OpType
.False
] = new string [] { "false", "op_False" }
;
2592 names
[(int) OpType
.Addition
] = new string [] { "+", "op_Addition" }
;
2593 names
[(int) OpType
.Subtraction
] = new string [] { "-", "op_Subtraction" }
;
2594 names
[(int) OpType
.UnaryPlus
] = new string [] { "+", "op_UnaryPlus" }
;
2595 names
[(int) OpType
.UnaryNegation
] = new string [] { "-", "op_UnaryNegation" }
;
2596 names
[(int) OpType
.Multiply
] = new string [] { "*", "op_Multiply" }
;
2597 names
[(int) OpType
.Division
] = new string [] { "/", "op_Division" }
;
2598 names
[(int) OpType
.Modulus
] = new string [] { "%", "op_Modulus" }
;
2599 names
[(int) OpType
.BitwiseAnd
] = new string [] { "&", "op_BitwiseAnd" }
;
2600 names
[(int) OpType
.BitwiseOr
] = new string [] { "|", "op_BitwiseOr" }
;
2601 names
[(int) OpType
.ExclusiveOr
] = new string [] { "^", "op_ExclusiveOr" }
;
2602 names
[(int) OpType
.LeftShift
] = new string [] { "<<", "op_LeftShift" }
;
2603 names
[(int) OpType
.RightShift
] = new string [] { ">>", "op_RightShift" }
;
2604 names
[(int) OpType
.Equality
] = new string [] { "==", "op_Equality" }
;
2605 names
[(int) OpType
.Inequality
] = new string [] { "!=", "op_Inequality" }
;
2606 names
[(int) OpType
.GreaterThan
] = new string [] { ">", "op_GreaterThan" }
;
2607 names
[(int) OpType
.LessThan
] = new string [] { "<", "op_LessThan" }
;
2608 names
[(int) OpType
.GreaterThanOrEqual
] = new string [] { ">=", "op_GreaterThanOrEqual" }
;
2609 names
[(int) OpType
.LessThanOrEqual
] = new string [] { "<=", "op_LessThanOrEqual" }
;
2610 names
[(int) OpType
.Implicit
] = new string [] { "implicit", "op_Implicit" }
;
2611 names
[(int) OpType
.Explicit
] = new string [] { "explicit", "op_Explicit" }
;
2612 names
[(int) OpType
.Is
] = new string[] { "is", "op_Is" }
;
2615 public Operator (TypeDefinition parent
, OpType type
, FullNamedExpression ret_type
, Modifiers mod_flags
, ParametersCompiled parameters
,
2616 ToplevelBlock block
, Attributes attrs
, Location loc
)
2617 : base (parent
, ret_type
, mod_flags
, AllowedModifiers
, new MemberName (GetMetadataName (type
), loc
), attrs
, parameters
)
2619 OperatorType
= type
;
2623 public override void Accept (StructuralVisitor visitor
)
2625 visitor
.Visit (this);
2628 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
2630 if (a
.Type
== pa
.Conditional
) {
2631 Error_ConditionalAttributeIsNotValid ();
2635 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
2638 public override bool Define ()
2640 const Modifiers RequiredModifiers
= Modifiers
.PUBLIC
| Modifiers
.STATIC
;
2641 if ((ModFlags
& RequiredModifiers
) != RequiredModifiers
){
2642 Report
.Error (558, Location
, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
2645 if (!base.Define ())
2648 if (block
!= null) {
2649 if (block
.IsIterator
) {
2651 // Current method is turned into automatically generated
2652 // wrapper which creates an instance of iterator
2654 Iterator
.CreateIterator (this, Parent
.PartialContainer
, ModFlags
);
2655 ModFlags
|= Modifiers
.DEBUGGER_HIDDEN
;
2658 if (Compiler
.Settings
.WriteMetadataOnly
)
2662 // imlicit and explicit operator of same types are not allowed
2663 if (OperatorType
== OpType
.Explicit
)
2664 Parent
.MemberCache
.CheckExistingMembersOverloads (this, GetMetadataName (OpType
.Implicit
), parameters
);
2665 else if (OperatorType
== OpType
.Implicit
)
2666 Parent
.MemberCache
.CheckExistingMembersOverloads (this, GetMetadataName (OpType
.Explicit
), parameters
);
2668 TypeSpec declaring_type
= Parent
.PartialContainer
.CurrentType
;
2669 TypeSpec return_type
= MemberType
;
2670 TypeSpec first_arg_type
= ParameterTypes
[0];
2672 TypeSpec first_arg_type_unwrap
= first_arg_type
;
2673 if (first_arg_type
.IsNullableType
)
2674 first_arg_type_unwrap
= Nullable
.NullableInfo
.GetUnderlyingType (first_arg_type
);
2676 TypeSpec return_type_unwrap
= return_type
;
2677 if (return_type
.IsNullableType
)
2678 return_type_unwrap
= Nullable
.NullableInfo
.GetUnderlyingType (return_type
);
2681 // Rules for conversion operators
2683 if (OperatorType
== OpType
.Implicit
|| OperatorType
== OpType
.Explicit
) {
2684 if (first_arg_type_unwrap
== return_type_unwrap
&& first_arg_type_unwrap
== declaring_type
) {
2685 Report
.Error (555, Location
,
2686 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
2691 if (declaring_type
== return_type
|| declaring_type
== return_type_unwrap
) {
2692 conv_type
= first_arg_type
;
2693 } else if (declaring_type
== first_arg_type
|| declaring_type
== first_arg_type_unwrap
) {
2694 conv_type
= return_type
;
2696 Report
.Error (556, Location
,
2697 "User-defined conversion must convert to or from the enclosing type");
2701 if (conv_type
.BuiltinType
== BuiltinTypeSpec
.Type
.Dynamic
) {
2702 Report
.Error (1964, Location
,
2703 "User-defined conversion `{0}' cannot convert to or from the dynamic type",
2704 GetSignatureForError ());
2709 if (conv_type
.IsInterface
) {
2710 Report
.Error (552, Location
, "User-defined conversion `{0}' cannot convert to or from an interface type",
2711 GetSignatureForError ());
2715 if (conv_type
.IsClass
) {
2716 if (TypeSpec
.IsBaseClass (declaring_type
, conv_type
, true)) {
2717 Report
.Error (553, Location
, "User-defined conversion `{0}' cannot convert to or from a base class",
2718 GetSignatureForError ());
2722 if (TypeSpec
.IsBaseClass (conv_type
, declaring_type
, false)) {
2723 Report
.Error (554, Location
, "User-defined conversion `{0}' cannot convert to or from a derived class",
2724 GetSignatureForError ());
2728 } else if (OperatorType
== OpType
.LeftShift
|| OperatorType
== OpType
.RightShift
) {
2729 if (first_arg_type
!= declaring_type
|| parameters
.Types
[1].BuiltinType
!= BuiltinTypeSpec
.Type
.Int
) {
2730 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");
2733 } else if (parameters
.Count
== 1) {
2734 // Checks for Unary operators
2736 if (OperatorType
== OpType
.Increment
|| OperatorType
== OpType
.Decrement
) {
2737 if (return_type
!= declaring_type
&& !TypeSpec
.IsBaseClass (return_type
, declaring_type
, false)) {
2738 Report
.Error (448, Location
,
2739 "The return type for ++ or -- operator must be the containing type or derived from the containing type");
2742 if (first_arg_type
!= declaring_type
) {
2744 559, Location
, "The parameter type for ++ or -- operator must be the containing type");
2749 if (first_arg_type_unwrap
!= declaring_type
) {
2750 Report
.Error (562, Location
,
2751 "The parameter type of a unary operator must be the containing type");
2755 if (OperatorType
== OpType
.True
|| OperatorType
== OpType
.False
) {
2756 if (return_type
.BuiltinType
!= BuiltinTypeSpec
.Type
.Bool
) {
2759 "The return type of operator True or False " +
2765 } else if (first_arg_type_unwrap
!= declaring_type
) {
2766 // Checks for Binary operators
2768 var second_arg_type
= ParameterTypes
[1];
2769 if (second_arg_type
.IsNullableType
)
2770 second_arg_type
= Nullable
.NullableInfo
.GetUnderlyingType (second_arg_type
);
2772 if (second_arg_type
!= declaring_type
) {
2773 Report
.Error (563, Location
,
2774 "One of the parameters of a binary operator must be the containing type");
2782 protected override bool ResolveMemberType ()
2784 if (!base.ResolveMemberType ())
2787 flags
|= MethodAttributes
.SpecialName
| MethodAttributes
.HideBySig
;
2791 protected override MemberSpec
FindBaseMember (out MemberSpec bestCandidate
, ref bool overrides
)
2793 // Operator cannot be override
2794 bestCandidate
= null;
2798 public static string GetName (OpType ot
)
2800 return names
[(int) ot
] [0];
2803 public static string GetName (string metadata_name
)
2805 for (int i
= 0; i
< names
.Length
; ++i
) {
2806 if (names
[i
] [1] == metadata_name
)
2807 return names
[i
] [0];
2812 public static string GetMetadataName (OpType ot
)
2814 return names
[(int) ot
] [1];
2817 public static string GetMetadataName (string name
)
2819 for (int i
= 0; i
< names
.Length
; ++i
) {
2820 if (names
[i
] [0] == name
)
2821 return names
[i
] [1];
2826 public static OpType
? GetType (string metadata_name
)
2828 for (int i
= 0; i
< names
.Length
; ++i
) {
2829 if (names
[i
][1] == metadata_name
)
2836 public OpType
GetMatchingOperator ()
2838 switch (OperatorType
) {
2839 case OpType
.Equality
:
2840 return OpType
.Inequality
;
2841 case OpType
.Inequality
:
2842 return OpType
.Equality
;
2844 return OpType
.False
;
2847 case OpType
.GreaterThan
:
2848 return OpType
.LessThan
;
2849 case OpType
.LessThan
:
2850 return OpType
.GreaterThan
;
2851 case OpType
.GreaterThanOrEqual
:
2852 return OpType
.LessThanOrEqual
;
2853 case OpType
.LessThanOrEqual
:
2854 return OpType
.GreaterThanOrEqual
;
2860 public override string GetSignatureForDocumentation ()
2862 string s
= base.GetSignatureForDocumentation ();
2863 if (OperatorType
== OpType
.Implicit
|| OperatorType
== OpType
.Explicit
) {
2864 s
= s
+ "~" + ReturnType
.GetSignatureForDocumentation ();
2870 public override string GetSignatureForError ()
2872 StringBuilder sb
= new StringBuilder ();
2873 if (OperatorType
== OpType
.Implicit
|| OperatorType
== OpType
.Explicit
) {
2874 sb
.AppendFormat ("{0}.{1} operator {2}",
2875 Parent
.GetSignatureForError (), GetName (OperatorType
),
2876 member_type
== null ? type_expr
.GetSignatureForError () : member_type
.GetSignatureForError ());
2879 sb
.AppendFormat ("{0}.operator {1}", Parent
.GetSignatureForError (), GetName (OperatorType
));
2882 sb
.Append (parameters
.GetSignatureForError ());
2883 return sb
.ToString ();