2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / method.cs
blob7c7e12e10858008c4526f82f1abd9d05550b1ffe
1 //
2 // method.cs: Method based declarations
3 //
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@ximian.com)
6 // Marek Safar (marek.safar@gmail.com)
7 //
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 //
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004-2008 Novell, Inc
14 using System;
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;
22 using System.Text;
24 #if NET_2_1
25 using XmlElement = System.Object;
26 #else
27 using System.Xml;
28 #endif
30 using Mono.CompilerServices.SymbolWriter;
32 namespace Mono.CSharp {
34 public abstract class MethodCore : InterfaceMemberBase
36 public readonly ParametersCompiled Parameters;
37 protected ToplevelBlock block;
38 protected MethodSpec spec;
40 public MethodCore (DeclSpace parent, GenericMethod generic,
41 FullNamedExpression type, Modifiers mod, Modifiers allowed_mod,
42 MemberName name, Attributes attrs, ParametersCompiled parameters)
43 : base (parent, generic, type, mod, allowed_mod, name, attrs)
45 Parameters = parameters;
49 // Returns the System.Type array for the parameters of this method
51 public Type [] ParameterTypes {
52 get {
53 return Parameters.Types;
57 public ParametersCompiled ParameterInfo {
58 get {
59 return Parameters;
63 public ToplevelBlock Block {
64 get {
65 return block;
68 set {
69 block = value;
73 public CallingConventions CallingConventions {
74 get {
75 CallingConventions cc = Parameters.CallingConvention;
76 if (!IsInterface)
77 if ((ModFlags & Modifiers.STATIC) == 0)
78 cc |= CallingConventions.HasThis;
80 // FIXME: How is `ExplicitThis' used in C#?
82 return cc;
86 protected override bool CheckBase ()
88 // Check whether arguments were correct.
89 if (!DefineParameters (Parameters))
90 return false;
92 return base.CheckBase ();
96 // Returns a string that represents the signature for this
97 // member which should be used in XML documentation.
99 public override string GetDocCommentName (DeclSpace ds)
101 return DocUtil.GetMethodDocCommentName (this, Parameters, ds);
105 // Raised (and passed an XmlElement that contains the comment)
106 // when GenerateDocComment is writing documentation expectedly.
108 // FIXME: with a few effort, it could be done with XmlReader,
109 // that means removal of DOM use.
111 internal override void OnGenerateDocComment (XmlElement el)
113 DocUtil.OnMethodGenerateDocComment (this, el, Report);
117 // Represents header string for documentation comment.
119 public override string DocCommentHeader
121 get { return "M:"; }
124 public override bool EnableOverloadChecks (MemberCore overload)
126 if (overload is MethodCore || overload is AbstractPropertyEventMethod) {
127 caching_flags |= Flags.MethodOverloadsExist;
128 return true;
131 return base.EnableOverloadChecks (overload);
134 public MethodSpec Spec {
135 get { return spec; }
138 protected override bool VerifyClsCompliance ()
140 if (!base.VerifyClsCompliance ())
141 return false;
143 if (Parameters.HasArglist) {
144 Report.Warning (3000, 1, Location, "Methods with variable arguments are not CLS-compliant");
147 if (!AttributeTester.IsClsCompliant (MemberType)) {
148 Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant",
149 GetSignatureForError ());
152 Parameters.VerifyClsCompliance (this);
153 return true;
157 interface IGenericMethodDefinition : IMemberDefinition
159 MethodInfo MakeGenericMethod (Type[] targs);
162 public class MethodSpec : MemberSpec
164 MethodBase metaInfo;
165 readonly AParametersCollection parameters;
167 public MethodSpec (MemberKind kind, IMemberDefinition details, MethodBase info, AParametersCollection parameters, Modifiers modifiers)
168 : base (kind, details, info.Name, modifiers)
170 this.MetaInfo = info;
171 this.parameters = parameters;
174 public override Type DeclaringType {
175 get {
176 return MetaInfo.DeclaringType;
180 public Type[] GetGenericArguments ()
182 return MetaInfo.GetGenericArguments ();
185 public MethodSpec Inflate (Type[] targs)
187 // TODO: Only create MethodSpec and inflate parameters, defer the call for later
188 var mb = ((IGenericMethodDefinition) definition).MakeGenericMethod (targs);
190 // TODO: Does not work on .NET
191 var par = TypeManager.GetParameterData (mb);
193 return new MethodSpec (Kind, definition, mb, par, Modifiers);
196 public bool IsAbstract {
197 get {
198 return (Modifiers & Modifiers.ABSTRACT) != 0;
202 public bool IsConstructor {
203 get {
204 return MetaInfo.IsConstructor;
208 public bool IsGenericMethod {
209 get {
210 return MetaInfo.IsGenericMethod;
214 // When is virtual or abstract
215 public bool IsVirtual {
216 get {
217 return (Modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) != 0;
221 public MethodBase MetaInfo {
222 get {
223 return metaInfo;
225 set {
226 metaInfo = value;
230 public AParametersCollection Parameters {
231 get { return parameters; }
234 public Type ReturnType {
235 get {
236 return IsConstructor ?
237 TypeManager.void_type : ((MethodInfo) MetaInfo).ReturnType;
242 public abstract class MethodOrOperator : MethodCore, IMethodData
244 public MethodBuilder MethodBuilder;
245 ReturnParameter return_attributes;
246 Dictionary<SecurityAction, PermissionSet> declarative_security;
247 protected MethodData MethodData;
249 static string[] attribute_targets = new string [] { "method", "return" };
251 protected MethodOrOperator (DeclSpace parent, GenericMethod generic, FullNamedExpression type, Modifiers mod,
252 Modifiers allowed_mod, MemberName name,
253 Attributes attrs, ParametersCompiled parameters)
254 : base (parent, generic, type, mod, allowed_mod, name,
255 attrs, parameters)
259 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
261 if (a.Target == AttributeTargets.ReturnValue) {
262 if (return_attributes == null)
263 return_attributes = new ReturnParameter (this, MethodBuilder, Location);
265 return_attributes.ApplyAttributeBuilder (a, cb, pa);
266 return;
269 if (a.IsInternalMethodImplAttribute) {
270 is_external_implementation = true;
273 if (a.Type == pa.DllImport) {
274 const Modifiers extern_static = Modifiers.EXTERN | Modifiers.STATIC;
275 if ((ModFlags & extern_static) != extern_static) {
276 Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
278 is_external_implementation = true;
281 if (a.IsValidSecurityAttribute ()) {
282 if (declarative_security == null)
283 declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
284 a.ExtractSecurityPermissionSet (declarative_security);
285 return;
288 if (MethodBuilder != null)
289 MethodBuilder.SetCustomAttribute (cb);
292 public override AttributeTargets AttributeTargets {
293 get {
294 return AttributeTargets.Method;
298 protected override bool CheckForDuplications ()
300 string name = GetFullName (MemberName);
301 if (MemberName.IsGeneric)
302 name = MemberName.MakeName (name, MemberName.TypeArguments);
304 return Parent.MemberCache.CheckExistingMembersOverloads (this, name, Parameters, Report);
307 public virtual EmitContext CreateEmitContext (ILGenerator ig)
309 return new EmitContext (
310 this, ig, MemberType);
313 protected override bool ResolveMemberType ()
315 if (GenericMethod != null) {
316 MethodBuilder = Parent.TypeBuilder.DefineMethod (GetFullName (MemberName), flags);
317 if (!GenericMethod.Define (this))
318 return false;
321 return base.ResolveMemberType ();
324 public override bool Define ()
326 if (!base.Define ())
327 return false;
329 if (!CheckBase ())
330 return false;
332 if (block != null && block.IsIterator && !(Parent is IteratorStorey)) {
334 // Current method is turned into automatically generated
335 // wrapper which creates an instance of iterator
337 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
338 ModFlags |= Modifiers.DEBUGGER_HIDDEN;
341 MemberKind kind;
342 if (this is Operator)
343 kind = MemberKind.Operator;
344 else if (this is Destructor)
345 kind = MemberKind.Destructor;
346 else
347 kind = MemberKind.Method;
349 if (IsPartialDefinition) {
350 caching_flags &= ~Flags.Excluded_Undetected;
351 caching_flags |= Flags.Excluded;
353 // Add to member cache only when a partial method implementation has not been found yet
354 if ((caching_flags & Flags.PartialDefinitionExists) == 0) {
355 MethodBase mb = new PartialMethodDefinitionInfo (this);
357 spec = new MethodSpec (kind, this, mb, Parameters, ModFlags);
358 Parent.MemberCache.AddMember (mb, spec);
359 TypeManager.AddMethod (mb, this);
362 return true;
365 MethodData = new MethodData (
366 this, ModFlags, flags, this, MethodBuilder, GenericMethod, base_method);
368 if (!MethodData.Define (Parent.PartialContainer, GetFullName (MemberName), Report))
369 return false;
371 MethodBuilder = MethodData.MethodBuilder;
373 spec = new MethodSpec (kind, this, MethodBuilder, Parameters, ModFlags);
375 if (TypeManager.IsGenericMethod (MethodBuilder))
376 Parent.MemberCache.AddGenericMember (MethodBuilder, this);
378 Parent.MemberCache.AddMember (MethodBuilder, spec);
380 return true;
383 protected override void DoMemberTypeIndependentChecks ()
385 base.DoMemberTypeIndependentChecks ();
387 CheckAbstractAndExtern (block != null);
389 if ((ModFlags & Modifiers.PARTIAL) != 0) {
390 for (int i = 0; i < Parameters.Count; ++i) {
391 IParameterData p = Parameters.FixedParameters [i];
392 if (p.ModFlags == Parameter.Modifier.OUT) {
393 Report.Error (752, Location, "`{0}': A partial method parameters cannot use `out' modifier",
394 GetSignatureForError ());
397 if (p.HasDefaultValue && IsPartialImplementation)
398 ((Parameter) p).Warning_UselessOptionalParameter (Report);
403 protected override void DoMemberTypeDependentChecks ()
405 base.DoMemberTypeDependentChecks ();
407 if (!TypeManager.IsGenericParameter (MemberType)) {
408 if (MemberType.IsAbstract && MemberType.IsSealed) {
409 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
414 public override void Emit ()
416 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
417 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (MethodBuilder);
418 if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
419 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (MethodBuilder);
421 if (TypeManager.IsDynamicType (ReturnType)) {
422 return_attributes = new ReturnParameter (this, MethodBuilder, Location);
423 PredefinedAttributes.Get.Dynamic.EmitAttribute (return_attributes.Builder);
424 } else {
425 var trans_flags = TypeManager.HasDynamicTypeUsed (ReturnType);
426 if (trans_flags != null) {
427 var pa = PredefinedAttributes.Get.DynamicTransform;
428 if (pa.Constructor != null || pa.ResolveConstructor (Location, TypeManager.bool_type.MakeArrayType ())) {
429 return_attributes = new ReturnParameter (this, MethodBuilder, Location);
430 return_attributes.Builder.SetCustomAttribute (
431 new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags }));
436 if (OptAttributes != null)
437 OptAttributes.Emit ();
439 if (declarative_security != null) {
440 foreach (var de in declarative_security) {
441 MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value);
445 if (MethodData != null)
446 MethodData.Emit (Parent);
448 base.Emit ();
450 Block = null;
451 MethodData = null;
454 protected void Error_ConditionalAttributeIsNotValid ()
456 Report.Error (577, Location,
457 "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
458 GetSignatureForError ());
461 public bool IsPartialDefinition {
462 get {
463 return (ModFlags & Modifiers.PARTIAL) != 0 && Block == null;
467 public bool IsPartialImplementation {
468 get {
469 return (ModFlags & Modifiers.PARTIAL) != 0 && Block != null;
473 public override string[] ValidAttributeTargets {
474 get {
475 return attribute_targets;
479 #region IMethodData Members
481 public Type ReturnType {
482 get {
483 return MemberType;
487 public MemberName MethodName {
488 get {
489 return MemberName;
493 /// <summary>
494 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
495 /// </summary>
496 public bool IsExcluded () {
497 if ((caching_flags & Flags.Excluded_Undetected) == 0)
498 return (caching_flags & Flags.Excluded) != 0;
500 caching_flags &= ~Flags.Excluded_Undetected;
502 if (base_method == null) {
503 if (OptAttributes == null)
504 return false;
506 Attribute[] attrs = OptAttributes.SearchMulti (PredefinedAttributes.Get.Conditional);
508 if (attrs == null)
509 return false;
511 foreach (Attribute a in attrs) {
512 string condition = a.GetConditionalAttributeValue ();
513 if (condition == null)
514 return false;
516 if (Location.CompilationUnit.IsConditionalDefined (condition))
517 return false;
520 caching_flags |= Flags.Excluded;
521 return true;
524 IMethodData md = TypeManager.GetMethod (TypeManager.DropGenericMethodArguments (base_method));
525 if (md == null) {
526 if (AttributeTester.IsConditionalMethodExcluded (base_method, Location)) {
527 caching_flags |= Flags.Excluded;
528 return true;
530 return false;
533 if (md.IsExcluded ()) {
534 caching_flags |= Flags.Excluded;
535 return true;
537 return false;
540 GenericMethod IMethodData.GenericMethod {
541 get {
542 return GenericMethod;
546 public virtual void EmitExtraSymbolInfo (SourceMethod source)
549 #endregion
553 public class SourceMethod : IMethodDef
555 MethodBase method;
556 SourceMethodBuilder builder;
558 protected SourceMethod (DeclSpace parent, MethodBase method, ICompileUnit file)
560 this.method = method;
562 builder = SymbolWriter.OpenMethod (file, parent.NamespaceEntry.SymbolFileID, this);
565 public string Name {
566 get { return method.Name; }
569 public int Token {
570 get {
571 if (method is MethodBuilder)
572 return ((MethodBuilder) method).GetToken ().Token;
573 else if (method is ConstructorBuilder)
574 return ((ConstructorBuilder) method).GetToken ().Token;
575 else
576 throw new NotSupportedException ();
580 public void CloseMethod ()
582 SymbolWriter.CloseMethod ();
585 public void SetRealMethodName (string name)
587 if (builder != null)
588 builder.SetRealMethodName (name);
591 public static SourceMethod Create (DeclSpace parent, MethodBase method, Block block)
593 if (!SymbolWriter.HasSymbolWriter)
594 return null;
595 if (block == null)
596 return null;
598 Location start_loc = block.StartLocation;
599 if (start_loc.IsNull)
600 return null;
602 ICompileUnit compile_unit = start_loc.CompilationUnit;
603 if (compile_unit == null)
604 return null;
606 return new SourceMethod (parent, method, compile_unit);
610 public class Method : MethodOrOperator, IGenericMethodDefinition
612 /// <summary>
613 /// Modifiers allowed in a class declaration
614 /// </summary>
615 const Modifiers AllowedModifiers =
616 Modifiers.NEW |
617 Modifiers.PUBLIC |
618 Modifiers.PROTECTED |
619 Modifiers.INTERNAL |
620 Modifiers.PRIVATE |
621 Modifiers.STATIC |
622 Modifiers.VIRTUAL |
623 Modifiers.SEALED |
624 Modifiers.OVERRIDE |
625 Modifiers.ABSTRACT |
626 Modifiers.UNSAFE |
627 Modifiers.EXTERN;
629 const Modifiers AllowedInterfaceModifiers =
630 Modifiers.NEW | Modifiers.UNSAFE;
632 Method partialMethodImplementation;
634 public Method (DeclSpace parent, GenericMethod generic,
635 FullNamedExpression return_type, Modifiers mod,
636 MemberName name, ParametersCompiled parameters, Attributes attrs)
637 : base (parent, generic, return_type, mod,
638 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
639 name, attrs, parameters)
643 protected Method (DeclSpace parent, FullNamedExpression return_type, Modifiers mod, Modifiers amod,
644 MemberName name, ParametersCompiled parameters, Attributes attrs)
645 : base (parent, null, return_type, mod, amod, name, attrs, parameters)
649 public override string GetSignatureForError()
651 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
654 void Error_DuplicateEntryPoint (Method b)
656 Report.Error (17, b.Location,
657 "Program `{0}' has more than one entry point defined: `{1}'",
658 CodeGen.FileName, b.GetSignatureForError ());
661 bool IsEntryPoint ()
663 if (ReturnType != TypeManager.void_type &&
664 ReturnType != TypeManager.int32_type)
665 return false;
667 if (Parameters.Count == 0)
668 return true;
670 if (Parameters.Count > 1)
671 return false;
673 Type t = Parameters.Types [0];
674 return t.IsArray && t.GetArrayRank () == 1 &&
675 TypeManager.GetElementType (t) == TypeManager.string_type &&
676 (Parameters[0].ModFlags & ~Parameter.Modifier.PARAMS) == Parameter.Modifier.NONE;
679 public override FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104)
681 TypeParameter[] tp = CurrentTypeParameters;
682 if (tp != null) {
683 TypeParameter t = TypeParameter.FindTypeParameter (tp, name);
684 if (t != null)
685 return new TypeParameterExpr (t, loc);
688 return base.LookupNamespaceOrType (name, loc, ignore_cs0104);
691 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
693 if (a.Type == pa.Conditional) {
694 if (IsExplicitImpl) {
695 Error_ConditionalAttributeIsNotValid ();
696 return;
699 if (ReturnType != TypeManager.void_type) {
700 Report.Error (578, Location, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ());
701 return;
704 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
705 Report.Error (243, Location, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ());
706 return;
709 if (IsInterface) {
710 Report.Error (582, Location, "Conditional not valid on interface members");
711 return;
714 if (MethodData.implementing != null) {
715 Report.SymbolRelatedToPreviousError (MethodData.implementing.DeclaringType);
716 Report.Error (629, Location, "Conditional member `{0}' cannot implement interface member `{1}'",
717 GetSignatureForError (), TypeManager.CSharpSignature (MethodData.implementing));
718 return;
721 for (int i = 0; i < Parameters.Count; ++i) {
722 if (Parameters.FixedParameters [i].ModFlags == Parameter.Modifier.OUT) {
723 Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
724 return;
729 if (a.Type == pa.Extension) {
730 a.Error_MisusedExtensionAttribute ();
731 return;
734 base.ApplyAttributeBuilder (a, cb, pa);
737 protected override bool CheckForDuplications ()
739 if (!base.CheckForDuplications ())
740 return false;
742 var ar = Parent.PartialContainer.Properties;
743 if (ar != null) {
744 for (int i = 0; i < ar.Count; ++i) {
745 PropertyBase pb = (PropertyBase) ar [i];
746 if (pb.AreAccessorsDuplicateImplementation (this))
747 return false;
751 ar = Parent.PartialContainer.Indexers;
752 if (ar != null) {
753 for (int i = 0; i < ar.Count; ++i) {
754 PropertyBase pb = (PropertyBase) ar [i];
755 if (pb.AreAccessorsDuplicateImplementation (this))
756 return false;
760 return true;
763 protected override bool CheckBase ()
765 if (!base.CheckBase ())
766 return false;
768 if (base_method != null && (ModFlags & Modifiers.OVERRIDE) != 0 && Name == Destructor.MetadataName) {
769 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
770 TypeManager.CSharpSignature (base_method));
773 return true;
776 public override TypeParameter[] CurrentTypeParameters {
777 get {
778 if (GenericMethod != null)
779 return GenericMethod.CurrentTypeParameters;
781 return null;
786 // Creates the type
788 public override bool Define ()
790 if (type_name == TypeManager.system_void_expr && Parameters.IsEmpty && Name == Destructor.MetadataName) {
791 Report.Warning (465, 1, Location, "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
794 if (!base.Define ())
795 return false;
797 if (partialMethodImplementation != null && IsPartialDefinition)
798 MethodBuilder = partialMethodImplementation.MethodBuilder;
800 if (RootContext.StdLib && TypeManager.IsSpecialType (ReturnType)) {
801 Error1599 (Location, ReturnType, Report);
802 return false;
805 if (base_method != null && (ModFlags & Modifiers.NEW) == 0) {
806 if (Parameters.Count == 1 && ParameterTypes [0] == TypeManager.object_type && Name == "Equals")
807 Parent.PartialContainer.Mark_HasEquals ();
808 else if (Parameters.IsEmpty && Name == "GetHashCode")
809 Parent.PartialContainer.Mark_HasGetHashCode ();
812 if ((ModFlags & Modifiers.STATIC) == 0)
813 return true;
815 if (Parameters.HasExtensionMethodType) {
816 if (Parent.PartialContainer.IsStaticClass && !Parent.IsGeneric) {
817 if (!Parent.IsTopLevel)
818 Report.Error (1109, Location, "`{0}': Extension methods cannot be defined in a nested class",
819 GetSignatureForError ());
821 PredefinedAttribute pa = PredefinedAttributes.Get.Extension;
822 if (!pa.IsDefined) {
823 Report.Error (1110, Location,
824 "`{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",
825 GetSignatureForError ());
828 ModFlags |= Modifiers.METHOD_EXTENSION;
829 Parent.PartialContainer.ModFlags |= Modifiers.METHOD_EXTENSION;
830 CodeGen.Assembly.HasExtensionMethods = true;
831 } else {
832 Report.Error (1106, Location, "`{0}': Extension methods must be defined in a non-generic static class",
833 GetSignatureForError ());
838 // This is used to track the Entry Point,
840 if (RootContext.NeedsEntryPoint &&
841 Name == "Main" &&
842 (RootContext.MainClass == null ||
843 RootContext.MainClass == Parent.TypeBuilder.FullName)){
844 if (IsEntryPoint ()) {
846 if (RootContext.EntryPoint == null) {
847 if (Parent.IsGeneric || MemberName.IsGeneric) {
848 Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type",
849 GetSignatureForError ());
850 } else {
851 SetIsUsed ();
852 RootContext.EntryPoint = this;
854 } else {
855 Error_DuplicateEntryPoint (RootContext.EntryPoint);
856 Error_DuplicateEntryPoint (this);
858 } else {
859 Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point",
860 GetSignatureForError ());
864 return true;
868 // Emits the code
870 public override void Emit ()
872 try {
873 Report.Debug (64, "METHOD EMIT", this, MethodBuilder, Location, Block, MethodData);
874 if (IsPartialDefinition) {
876 // Use partial method implementation builder for partial method declaration attributes
878 if (partialMethodImplementation != null) {
879 MethodBuilder = partialMethodImplementation.MethodBuilder;
880 return;
882 } else if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.PartialDefinitionExists) == 0) {
883 Report.Error (759, Location, "A partial method `{0}' implementation is missing a partial method declaration",
884 GetSignatureForError ());
887 base.Emit ();
889 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
890 PredefinedAttributes.Get.Extension.EmitAttribute (MethodBuilder);
891 } catch {
892 Console.WriteLine ("Internal compiler error at {0}: exception caught while emitting {1}",
893 Location, MethodBuilder);
894 throw;
898 public override bool EnableOverloadChecks (MemberCore overload)
900 // TODO: It can be deleted when members will be defined in correct order
901 if (overload is Operator)
902 return overload.EnableOverloadChecks (this);
904 if (overload is Indexer)
905 return false;
907 return base.EnableOverloadChecks (overload);
910 public static void Error1599 (Location loc, Type t, Report Report)
912 Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t));
915 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
917 MethodInfo mi = (MethodInfo) Parent.PartialContainer.BaseCache.FindMemberToOverride (
918 Parent.TypeBuilder, Name, Parameters, GenericMethod, false);
920 if (mi == null)
921 return null;
923 if (mi.IsSpecialName)
924 return null;
926 base_ret_type = TypeManager.TypeToCoreType (mi.ReturnType);
927 return mi;
930 public MethodInfo MakeGenericMethod (Type[] targs)
932 return MethodBuilder.MakeGenericMethod (targs);
935 public void SetPartialDefinition (Method methodDefinition)
937 caching_flags |= Flags.PartialDefinitionExists;
938 methodDefinition.partialMethodImplementation = this;
940 // Ensure we are always using method declaration parameters
941 for (int i = 0; i < methodDefinition.Parameters.Count; ++i ) {
942 Parameters [i].Name = methodDefinition.Parameters [i].Name;
943 Parameters [i].DefaultValue = methodDefinition.Parameters [i].DefaultValue;
946 if (methodDefinition.attributes == null)
947 return;
949 if (attributes == null) {
950 attributes = methodDefinition.attributes;
951 } else {
952 attributes.Attrs.AddRange (methodDefinition.attributes.Attrs);
956 protected override bool VerifyClsCompliance ()
958 if (!base.VerifyClsCompliance ())
959 return false;
961 if (!Parameters.IsEmpty) {
962 var al = Parent.PartialContainer.MemberCache.Members [Name];
963 if (al.Count > 1)
964 MemberCache.VerifyClsParameterConflict (al, this, MethodBuilder, Report);
967 return true;
971 public abstract class ConstructorInitializer : ExpressionStatement
973 Arguments argument_list;
974 MethodGroupExpr base_constructor_group;
976 public ConstructorInitializer (Arguments argument_list, Location loc)
978 this.argument_list = argument_list;
979 this.loc = loc;
982 public Arguments Arguments {
983 get {
984 return argument_list;
988 public override Expression CreateExpressionTree (ResolveContext ec)
990 throw new NotSupportedException ("ET");
993 protected override Expression DoResolve (ResolveContext ec)
995 eclass = ExprClass.Value;
997 // TODO: ec.GetSignatureForError ()
998 ConstructorBuilder caller_builder = ((Constructor) ec.MemberContext).ConstructorBuilder;
1000 if (argument_list != null) {
1001 bool dynamic;
1004 // Spec mandates that constructor initializer will not have `this' access
1006 using (ec.Set (ResolveContext.Options.BaseInitializer)) {
1007 argument_list.Resolve (ec, out dynamic);
1010 if (dynamic) {
1011 ec.Report.Error (1975, loc,
1012 "The constructor call cannot be dynamically dispatched within constructor initializer");
1014 return null;
1018 type = ec.CurrentType;
1019 if (this is ConstructorBaseInitializer) {
1020 if (ec.CurrentType.BaseType == null)
1021 return this;
1023 type = ec.CurrentType.BaseType;
1024 if (TypeManager.IsStruct (ec.CurrentType)) {
1025 ec.Report.Error (522, loc,
1026 "`{0}': Struct constructors cannot call base constructors", TypeManager.CSharpSignature (caller_builder));
1027 return this;
1029 } else {
1031 // It is legal to have "this" initializers that take no arguments
1032 // in structs, they are just no-ops.
1034 // struct D { public D (int a) : this () {}
1036 if (TypeManager.IsStruct (ec.CurrentType) && argument_list == null)
1037 return this;
1040 base_constructor_group = MemberLookupFinal (
1041 ec, null, type, ConstructorBuilder.ConstructorName, MemberTypes.Constructor,
1042 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
1043 loc) as MethodGroupExpr;
1045 if (base_constructor_group == null)
1046 return this;
1048 base_constructor_group = base_constructor_group.OverloadResolve (
1049 ec, ref argument_list, false, loc);
1051 if (base_constructor_group == null)
1052 return this;
1054 if (!ec.IsStatic)
1055 base_constructor_group.InstanceExpression = ec.GetThis (loc);
1057 var base_ctor = base_constructor_group.BestCandidate;
1059 if (base_ctor.MetaInfo == caller_builder){
1060 ec.Report.Error (516, loc, "Constructor `{0}' cannot call itself", TypeManager.CSharpSignature (caller_builder));
1063 return this;
1066 public override void Emit (EmitContext ec)
1068 // It can be null for static initializers
1069 if (base_constructor_group == null)
1070 return;
1072 ec.Mark (loc);
1074 base_constructor_group.EmitCall (ec, argument_list);
1077 public override void EmitStatement (EmitContext ec)
1079 Emit (ec);
1083 public class ConstructorBaseInitializer : ConstructorInitializer {
1084 public ConstructorBaseInitializer (Arguments argument_list, Location l) :
1085 base (argument_list, l)
1090 class GeneratedBaseInitializer: ConstructorBaseInitializer {
1091 public GeneratedBaseInitializer (Location loc):
1092 base (null, loc)
1097 public class ConstructorThisInitializer : ConstructorInitializer {
1098 public ConstructorThisInitializer (Arguments argument_list, Location l) :
1099 base (argument_list, l)
1104 public class Constructor : MethodCore, IMethodData {
1105 public ConstructorBuilder ConstructorBuilder;
1106 public ConstructorInitializer Initializer;
1107 Dictionary<SecurityAction, PermissionSet> declarative_security;
1108 bool has_compliant_args;
1110 // <summary>
1111 // Modifiers allowed for a constructor.
1112 // </summary>
1113 public const Modifiers AllowedModifiers =
1114 Modifiers.PUBLIC |
1115 Modifiers.PROTECTED |
1116 Modifiers.INTERNAL |
1117 Modifiers.STATIC |
1118 Modifiers.UNSAFE |
1119 Modifiers.EXTERN |
1120 Modifiers.PRIVATE;
1122 static readonly string[] attribute_targets = new string [] { "method" };
1125 // The spec claims that static is not permitted, but
1126 // my very own code has static constructors.
1128 public Constructor (DeclSpace parent, string name, Modifiers mod, Attributes attrs, ParametersCompiled args,
1129 ConstructorInitializer init, Location loc)
1130 : base (parent, null, null, mod, AllowedModifiers,
1131 new MemberName (name, loc), attrs, args)
1133 Initializer = init;
1136 public bool HasCompliantArgs {
1137 get { return has_compliant_args; }
1140 public override AttributeTargets AttributeTargets {
1141 get { return AttributeTargets.Constructor; }
1145 // Returns true if this is a default constructor
1147 public bool IsDefault ()
1149 if ((ModFlags & Modifiers.STATIC) != 0)
1150 return Parameters.IsEmpty;
1152 return Parameters.IsEmpty &&
1153 (Initializer is ConstructorBaseInitializer) &&
1154 (Initializer.Arguments == null);
1157 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
1159 if (a.IsValidSecurityAttribute ()) {
1160 if (declarative_security == null) {
1161 declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
1163 a.ExtractSecurityPermissionSet (declarative_security);
1164 return;
1167 if (a.IsInternalMethodImplAttribute) {
1168 is_external_implementation = true;
1171 ConstructorBuilder.SetCustomAttribute (cb);
1174 protected override bool CheckBase ()
1176 if ((ModFlags & Modifiers.STATIC) != 0) {
1177 if (!Parameters.IsEmpty) {
1178 Report.Error (132, Location, "`{0}': The static constructor must be parameterless",
1179 GetSignatureForError ());
1180 return false;
1183 // the rest can be ignored
1184 return true;
1187 // Check whether arguments were correct.
1188 if (!DefineParameters (Parameters))
1189 return false;
1191 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
1192 Parent.MemberCache.CheckExistingMembersOverloads (this, ConstructorInfo.ConstructorName,
1193 Parameters, Report);
1195 if (Parent.PartialContainer.Kind == MemberKind.Struct) {
1196 if (Parameters.Count == 0) {
1197 Report.Error (568, Location,
1198 "Structs cannot contain explicit parameterless constructors");
1199 return false;
1203 CheckProtectedModifier ();
1205 return true;
1209 // Creates the ConstructorBuilder
1211 public override bool Define ()
1213 if (ConstructorBuilder != null)
1214 return true;
1216 MethodAttributes ca = (MethodAttributes.RTSpecialName |
1217 MethodAttributes.SpecialName);
1219 if ((ModFlags & Modifiers.STATIC) != 0) {
1220 ca |= MethodAttributes.Static | MethodAttributes.Private;
1221 } else {
1222 ca |= MethodAttributes.HideBySig;
1224 if ((ModFlags & Modifiers.PUBLIC) != 0)
1225 ca |= MethodAttributes.Public;
1226 else if ((ModFlags & Modifiers.PROTECTED) != 0){
1227 if ((ModFlags & Modifiers.INTERNAL) != 0)
1228 ca |= MethodAttributes.FamORAssem;
1229 else
1230 ca |= MethodAttributes.Family;
1231 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
1232 ca |= MethodAttributes.Assembly;
1233 else
1234 ca |= MethodAttributes.Private;
1237 if (!CheckAbstractAndExtern (block != null))
1238 return false;
1240 // Check if arguments were correct.
1241 if (!CheckBase ())
1242 return false;
1244 ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
1245 ca, CallingConventions,
1246 Parameters.GetEmitTypes ());
1248 spec = new MethodSpec (MemberKind.Constructor, this, ConstructorBuilder, Parameters, ModFlags);
1250 if (Parent.PartialContainer.IsComImport) {
1251 if (!IsDefault ()) {
1252 Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
1253 Parent.GetSignatureForError ());
1255 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
1258 Parent.MemberCache.AddMember (ConstructorBuilder, spec);
1259 TypeManager.AddMethod (ConstructorBuilder, this);
1261 // It's here only to report an error
1262 if (block != null && block.IsIterator) {
1263 member_type = TypeManager.void_type;
1264 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
1267 return true;
1271 // Emits the code
1273 public override void Emit ()
1275 if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
1276 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (ConstructorBuilder);
1278 if (OptAttributes != null)
1279 OptAttributes.Emit ();
1281 base.Emit ();
1284 // If we use a "this (...)" constructor initializer, then
1285 // do not emit field initializers, they are initialized in the other constructor
1287 bool emit_field_initializers = ((ModFlags & Modifiers.STATIC) != 0) ||
1288 !(Initializer is ConstructorThisInitializer);
1290 BlockContext bc = new BlockContext (this, block, TypeManager.void_type);
1291 bc.Set (ResolveContext.Options.ConstructorScope);
1293 if (emit_field_initializers)
1294 Parent.PartialContainer.ResolveFieldInitializers (bc);
1296 if (block != null) {
1297 // If this is a non-static `struct' constructor and doesn't have any
1298 // initializer, it must initialize all of the struct's fields.
1299 if ((Parent.PartialContainer.Kind == MemberKind.Struct) &&
1300 ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
1301 block.AddThisVariable (Parent, Location);
1303 if (block != null && (ModFlags & Modifiers.STATIC) == 0){
1304 if (Parent.PartialContainer.Kind == MemberKind.Class && Initializer == null)
1305 Initializer = new GeneratedBaseInitializer (Location);
1307 if (Initializer != null) {
1308 block.AddScopeStatement (new StatementExpression (Initializer));
1313 Parameters.ApplyAttributes (ConstructorBuilder);
1315 SourceMethod source = SourceMethod.Create (Parent, ConstructorBuilder, block);
1317 if (block != null) {
1318 if (block.Resolve (null, bc, Parameters, this)) {
1319 EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType);
1320 ec.With (EmitContext.Options.ConstructorScope, true);
1322 if (!ec.HasReturnLabel && bc.HasReturnLabel) {
1323 ec.ReturnLabel = bc.ReturnLabel;
1324 ec.HasReturnLabel = true;
1327 block.Emit (ec);
1331 if (source != null)
1332 source.CloseMethod ();
1334 if (declarative_security != null) {
1335 foreach (var de in declarative_security) {
1336 ConstructorBuilder.AddDeclarativeSecurity (de.Key, de.Value);
1340 block = null;
1343 // Is never override
1344 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
1346 return null;
1349 public override string GetSignatureForError()
1351 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
1354 public override string[] ValidAttributeTargets {
1355 get {
1356 return attribute_targets;
1360 protected override bool VerifyClsCompliance ()
1362 if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
1363 return false;
1366 if (!Parameters.IsEmpty) {
1367 var al = Parent.MemberCache.Members [ConstructorInfo.ConstructorName];
1368 if (al.Count > 2)
1369 MemberCache.VerifyClsParameterConflict (al, this, ConstructorBuilder, Report);
1371 if (TypeManager.IsSubclassOf (Parent.TypeBuilder, TypeManager.attribute_type)) {
1372 foreach (Type param in Parameters.Types) {
1373 if (param.IsArray) {
1374 return true;
1379 has_compliant_args = true;
1380 return true;
1383 #region IMethodData Members
1385 public MemberName MethodName {
1386 get {
1387 return MemberName;
1391 public Type ReturnType {
1392 get {
1393 return MemberType;
1397 public EmitContext CreateEmitContext (ILGenerator ig)
1399 throw new NotImplementedException ();
1402 public bool IsExcluded()
1404 return false;
1407 GenericMethod IMethodData.GenericMethod {
1408 get {
1409 return null;
1413 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
1416 #endregion
1419 /// <summary>
1420 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
1421 /// </summary>
1422 public interface IMethodData
1424 CallingConventions CallingConventions { get; }
1425 Location Location { get; }
1426 MemberName MethodName { get; }
1427 Type ReturnType { get; }
1428 GenericMethod GenericMethod { get; }
1429 ParametersCompiled ParameterInfo { get; }
1431 Attributes OptAttributes { get; }
1432 ToplevelBlock Block { get; set; }
1434 EmitContext CreateEmitContext (ILGenerator ig);
1435 ObsoleteAttribute GetObsoleteAttribute ();
1436 string GetSignatureForError ();
1437 bool IsExcluded ();
1438 bool IsClsComplianceRequired ();
1439 void SetIsUsed ();
1440 void EmitExtraSymbolInfo (SourceMethod source);
1444 // Encapsulates most of the Method's state
1446 public class MethodData {
1447 static FieldInfo methodbuilder_attrs_field;
1448 public readonly IMethodData method;
1450 public readonly GenericMethod GenericMethod;
1453 // Are we implementing an interface ?
1455 public MethodInfo implementing;
1458 // Protected data.
1460 protected InterfaceMemberBase member;
1461 protected Modifiers modifiers;
1462 protected MethodAttributes flags;
1463 protected Type declaring_type;
1464 protected MethodInfo parent_method;
1466 MethodBuilder builder = null;
1467 public MethodBuilder MethodBuilder {
1468 get {
1469 return builder;
1473 public Type DeclaringType {
1474 get {
1475 return declaring_type;
1479 public MethodData (InterfaceMemberBase member,
1480 Modifiers modifiers, MethodAttributes flags, IMethodData method)
1482 this.member = member;
1483 this.modifiers = modifiers;
1484 this.flags = flags;
1486 this.method = method;
1489 public MethodData (InterfaceMemberBase member,
1490 Modifiers modifiers, MethodAttributes flags,
1491 IMethodData method, MethodBuilder builder,
1492 GenericMethod generic, MethodInfo parent_method)
1493 : this (member, modifiers, flags, method)
1495 this.builder = builder;
1496 this.GenericMethod = generic;
1497 this.parent_method = parent_method;
1500 public bool Define (DeclSpace parent, string method_full_name, Report Report)
1502 string name = method.MethodName.Basename;
1504 TypeContainer container = parent.PartialContainer;
1506 PendingImplementation pending = container.PendingImplementations;
1507 if (pending != null){
1508 implementing = pending.IsInterfaceMethod (name, member.InterfaceType, this);
1510 if (member.InterfaceType != null){
1511 if (implementing == null){
1512 if (member is PropertyBase) {
1513 Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'",
1514 method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType),
1515 member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
1517 } else {
1518 Report.Error (539, method.Location,
1519 "`{0}.{1}' in explicit interface declaration is not a member of interface",
1520 TypeManager.CSharpName (member.InterfaceType), member.ShortName);
1522 return false;
1524 if (implementing.IsSpecialName && !(method is AbstractPropertyEventMethod)) {
1525 Report.SymbolRelatedToPreviousError (implementing);
1526 Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
1527 member.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
1528 return false;
1530 } else {
1531 if (implementing != null) {
1532 AbstractPropertyEventMethod prop_method = method as AbstractPropertyEventMethod;
1533 if (prop_method == null) {
1534 if (TypeManager.IsSpecialMethod (implementing)) {
1535 Report.SymbolRelatedToPreviousError (implementing);
1536 Report.Error (470, method.Location, "Method `{0}' cannot implement interface accessor `{1}.{2}'",
1537 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing),
1538 implementing.Name.StartsWith ("get_") ? "get" : "set");
1540 } else if (implementing.DeclaringType.IsInterface) {
1541 if (!implementing.IsSpecialName) {
1542 Report.SymbolRelatedToPreviousError (implementing);
1543 Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
1544 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
1545 return false;
1547 PropertyBase.PropertyMethod pm = prop_method as PropertyBase.PropertyMethod;
1548 if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
1549 Report.SymbolRelatedToPreviousError (implementing);
1550 Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'",
1551 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing, true));
1552 return false;
1560 // For implicit implementations, make sure we are public, for
1561 // explicit implementations, make sure we are private.
1563 if (implementing != null){
1565 // Setting null inside this block will trigger a more
1566 // verbose error reporting for missing interface implementations
1568 // The "candidate" function has been flagged already
1569 // but it wont get cleared
1571 if (member.IsExplicitImpl){
1572 if (method.ParameterInfo.HasParams && !TypeManager.GetParameterData (implementing).HasParams) {
1573 Report.SymbolRelatedToPreviousError (implementing);
1574 Report.Error (466, method.Location, "`{0}': the explicit interface implementation cannot introduce the params modifier",
1575 method.GetSignatureForError ());
1576 return false;
1578 } else {
1579 if (implementing.DeclaringType.IsInterface) {
1581 // If this is an interface method implementation,
1582 // check for public accessibility
1584 if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public)
1586 implementing = null;
1588 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
1589 // We may never be private.
1590 implementing = null;
1592 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
1594 // We may be protected if we're overriding something.
1596 implementing = null;
1601 // Static is not allowed
1603 if ((modifiers & Modifiers.STATIC) != 0){
1604 implementing = null;
1609 // If implementing is still valid, set flags
1611 if (implementing != null){
1613 // When implementing interface methods, set NewSlot
1614 // unless, we are overwriting a method.
1616 if (implementing.DeclaringType.IsInterface){
1617 if ((modifiers & Modifiers.OVERRIDE) == 0)
1618 flags |= MethodAttributes.NewSlot;
1620 flags |=
1621 MethodAttributes.Virtual |
1622 MethodAttributes.HideBySig;
1624 // Set Final unless we're virtual, abstract or already overriding a method.
1625 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
1626 flags |= MethodAttributes.Final;
1629 DefineMethodBuilder (container, method_full_name, method.ParameterInfo);
1631 if (builder == null)
1632 return false;
1634 if (container.CurrentType != null)
1635 declaring_type = container.CurrentType;
1636 else
1637 declaring_type = container.TypeBuilder;
1639 if (implementing != null && member.IsExplicitImpl) {
1640 container.TypeBuilder.DefineMethodOverride (builder, implementing);
1643 TypeManager.AddMethod (builder, method);
1645 if (GenericMethod != null) {
1646 bool is_override = member.IsExplicitImpl |
1647 ((modifiers & Modifiers.OVERRIDE) != 0);
1649 if (implementing != null)
1650 parent_method = implementing;
1652 if (!GenericMethod.DefineType (GenericMethod, builder, parent_method, is_override))
1653 return false;
1656 return true;
1660 /// <summary>
1661 /// Create the MethodBuilder for the method
1662 /// </summary>
1663 void DefineMethodBuilder (TypeContainer container, string method_name, ParametersCompiled param)
1665 if (builder == null) {
1666 builder = container.TypeBuilder.DefineMethod (
1667 method_name, flags, method.CallingConventions,
1668 method.ReturnType,
1669 param.GetEmitTypes ());
1670 return;
1674 // Generic method has been already defined to resolve method parameters
1675 // correctly when they use type parameters
1677 builder.SetParameters (param.GetEmitTypes ());
1678 builder.SetReturnType (method.ReturnType);
1679 if (builder.Attributes != flags) {
1680 try {
1681 if (methodbuilder_attrs_field == null)
1682 methodbuilder_attrs_field = typeof (MethodBuilder).GetField ("attrs", BindingFlags.NonPublic | BindingFlags.Instance);
1683 methodbuilder_attrs_field.SetValue (builder, flags);
1684 } catch {
1685 container.Compiler.Report.RuntimeMissingSupport (method.Location, "Generic method MethodAttributes");
1691 // Emits the code
1693 public void Emit (DeclSpace parent)
1695 method.ParameterInfo.ApplyAttributes (MethodBuilder);
1697 if (GenericMethod != null)
1698 GenericMethod.EmitAttributes ();
1701 // clear the pending implementation flag
1703 if (implementing != null)
1704 parent.PartialContainer.PendingImplementations.ImplementMethod (method.MethodName.Basename,
1705 member.InterfaceType, this, member.IsExplicitImpl);
1707 SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
1709 ToplevelBlock block = method.Block;
1710 if (block != null) {
1711 BlockContext bc = new BlockContext ((IMemberContext) method, block, method.ReturnType);
1712 if (block.Resolve (null, bc, method.ParameterInfo, method)) {
1713 EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator ());
1714 if (!ec.HasReturnLabel && bc.HasReturnLabel) {
1715 ec.ReturnLabel = bc.ReturnLabel;
1716 ec.HasReturnLabel = true;
1719 block.Emit (ec);
1723 if (source != null) {
1724 method.EmitExtraSymbolInfo (source);
1725 source.CloseMethod ();
1730 public class Destructor : MethodOrOperator
1732 const Modifiers AllowedModifiers =
1733 Modifiers.UNSAFE |
1734 Modifiers.EXTERN;
1736 static readonly string[] attribute_targets = new string [] { "method" };
1738 public static readonly string MetadataName = "Finalize";
1740 public Destructor (DeclSpace parent, Modifiers mod, ParametersCompiled parameters, Attributes attrs, Location l)
1741 : base (parent, null, TypeManager.system_void_expr, mod, AllowedModifiers,
1742 new MemberName (MetadataName, l), attrs, parameters)
1744 ModFlags &= ~Modifiers.PRIVATE;
1745 ModFlags |= Modifiers.PROTECTED | Modifiers.OVERRIDE;
1748 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
1750 if (a.Type == pa.Conditional) {
1751 Error_ConditionalAttributeIsNotValid ();
1752 return;
1755 base.ApplyAttributeBuilder (a, cb, pa);
1758 protected override bool CheckBase ()
1760 if (!base.CheckBase ())
1761 return false;
1763 if (Parent.PartialContainer.BaseCache == null)
1764 return true;
1766 Type base_type = Parent.PartialContainer.BaseCache.Container.Type;
1767 if (base_type != null && Block != null) {
1768 MethodGroupExpr method_expr = Expression.MethodLookup (Parent.Module.Compiler, Parent.TypeBuilder, base_type, MetadataName, Location);
1769 if (method_expr == null)
1770 throw new NotImplementedException ();
1772 method_expr.IsBase = true;
1773 method_expr.InstanceExpression = new CompilerGeneratedThis (Parent.TypeBuilder, Location);
1775 ToplevelBlock new_block = new ToplevelBlock (Compiler, Block.StartLocation);
1776 new_block.EndLocation = Block.EndLocation;
1778 Block finaly_block = new ExplicitBlock (new_block, Location, Location);
1779 Block try_block = new Block (new_block, block);
1782 // 0-size arguments to avoid CS0250 error
1783 // TODO: Should use AddScopeStatement or something else which emits correct
1784 // debugger scope
1786 finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0))));
1787 new_block.AddStatement (new TryFinally (try_block, finaly_block, Location));
1789 block = new_block;
1792 return true;
1795 public override string GetSignatureForError ()
1797 return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
1800 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
1802 return null;
1805 public override string[] ValidAttributeTargets {
1806 get {
1807 return attribute_targets;
1812 // Ooouh Martin, templates are missing here.
1813 // When it will be possible move here a lot of child code and template method type.
1814 public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData {
1815 protected MethodData method_data;
1816 protected ToplevelBlock block;
1817 protected Dictionary<SecurityAction, PermissionSet> declarative_security;
1819 // The accessor are created even if they are not wanted.
1820 // But we need them because their names are reserved.
1821 // Field says whether accessor will be emited or not
1822 public readonly bool IsDummy;
1824 protected readonly string prefix;
1826 ReturnParameter return_attributes;
1828 public AbstractPropertyEventMethod (PropertyBasedMember member, string prefix)
1829 : base (member.Parent, SetupName (prefix, member, member.Location), null)
1831 this.prefix = prefix;
1832 IsDummy = true;
1835 public AbstractPropertyEventMethod (InterfaceMemberBase member, Accessor accessor,
1836 string prefix)
1837 : base (member.Parent, SetupName (prefix, member, accessor.Location),
1838 accessor.Attributes)
1840 this.prefix = prefix;
1841 this.block = accessor.Block;
1844 static MemberName SetupName (string prefix, InterfaceMemberBase member, Location loc)
1846 return new MemberName (member.MemberName.Left, prefix + member.ShortName, loc);
1849 public void UpdateName (InterfaceMemberBase member)
1851 SetMemberName (SetupName (prefix, member, Location));
1854 #region IMethodData Members
1856 public ToplevelBlock Block {
1857 get {
1858 return block;
1861 set {
1862 block = value;
1866 public CallingConventions CallingConventions {
1867 get {
1868 return CallingConventions.Standard;
1872 public EmitContext CreateEmitContext (ILGenerator ig)
1874 return new EmitContext (this, ig, ReturnType);
1877 public bool IsExcluded ()
1879 return false;
1882 GenericMethod IMethodData.GenericMethod {
1883 get {
1884 return null;
1888 public MemberName MethodName {
1889 get {
1890 return MemberName;
1894 public Type[] ParameterTypes {
1895 get {
1896 return ParameterInfo.Types;
1900 public abstract ParametersCompiled ParameterInfo { get ; }
1901 public abstract Type ReturnType { get; }
1903 #endregion
1905 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
1907 if (a.Type == pa.CLSCompliant || a.Type == pa.Obsolete || a.Type == pa.Conditional) {
1908 Report.Error (1667, a.Location,
1909 "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
1910 TypeManager.CSharpName (a.Type), a.GetValidTargets ());
1911 return;
1914 if (a.IsValidSecurityAttribute ()) {
1915 if (declarative_security == null)
1916 declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
1917 a.ExtractSecurityPermissionSet (declarative_security);
1918 return;
1921 if (a.Target == AttributeTargets.Method) {
1922 method_data.MethodBuilder.SetCustomAttribute (cb);
1923 return;
1926 if (a.Target == AttributeTargets.ReturnValue) {
1927 if (return_attributes == null)
1928 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
1930 return_attributes.ApplyAttributeBuilder (a, cb, pa);
1931 return;
1934 ApplyToExtraTarget (a, cb, pa);
1937 protected virtual void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
1939 throw new NotSupportedException ("You forgot to define special attribute target handling");
1942 // It is not supported for the accessors
1943 public sealed override bool Define()
1945 throw new NotSupportedException ();
1948 public virtual void Emit (DeclSpace parent)
1950 method_data.Emit (parent);
1952 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
1953 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (method_data.MethodBuilder);
1954 if (((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0))
1955 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (method_data.MethodBuilder);
1957 if (TypeManager.IsDynamicType (ReturnType)) {
1958 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
1959 PredefinedAttributes.Get.Dynamic.EmitAttribute (return_attributes.Builder);
1960 } else {
1961 var trans_flags = TypeManager.HasDynamicTypeUsed (ReturnType);
1962 if (trans_flags != null) {
1963 var pa = PredefinedAttributes.Get.DynamicTransform;
1964 if (pa.Constructor != null || pa.ResolveConstructor (Location, TypeManager.bool_type.MakeArrayType ())) {
1965 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
1966 return_attributes.Builder.SetCustomAttribute (
1967 new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags }));
1972 if (OptAttributes != null)
1973 OptAttributes.Emit ();
1975 if (declarative_security != null) {
1976 foreach (var de in declarative_security) {
1977 method_data.MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value);
1981 block = null;
1984 public override bool EnableOverloadChecks (MemberCore overload)
1986 // This can only happen with indexers and it will
1987 // be catched as indexer difference
1988 if (overload is AbstractPropertyEventMethod)
1989 return true;
1991 if (overload is MethodCore) {
1992 caching_flags |= Flags.MethodOverloadsExist;
1993 return true;
1995 return false;
1998 public override bool IsClsComplianceRequired()
2000 return false;
2003 public bool IsDuplicateImplementation (MethodCore method)
2005 if (!MemberName.Equals (method.MemberName))
2006 return false;
2008 Type[] param_types = method.ParameterTypes;
2010 if (param_types == null || param_types.Length != ParameterTypes.Length)
2011 return false;
2013 for (int i = 0; i < param_types.Length; i++)
2014 if (param_types [i] != ParameterTypes [i])
2015 return false;
2017 Report.SymbolRelatedToPreviousError (method);
2018 Report.Error (82, Location, "A member `{0}' is already reserved",
2019 method.GetSignatureForError ());
2020 return true;
2023 public override bool IsUsed {
2024 get {
2025 if (IsDummy)
2026 return false;
2028 return base.IsUsed;
2032 public MethodSpec Spec { get; protected set; }
2035 // Represents header string for documentation comment.
2037 public override string DocCommentHeader {
2038 get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
2041 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
2045 public class Operator : MethodOrOperator {
2047 const Modifiers AllowedModifiers =
2048 Modifiers.PUBLIC |
2049 Modifiers.UNSAFE |
2050 Modifiers.EXTERN |
2051 Modifiers.STATIC;
2053 public enum OpType : byte {
2055 // Unary operators
2056 LogicalNot,
2057 OnesComplement,
2058 Increment,
2059 Decrement,
2060 True,
2061 False,
2063 // Unary and Binary operators
2064 Addition,
2065 Subtraction,
2067 UnaryPlus,
2068 UnaryNegation,
2070 // Binary operators
2071 Multiply,
2072 Division,
2073 Modulus,
2074 BitwiseAnd,
2075 BitwiseOr,
2076 ExclusiveOr,
2077 LeftShift,
2078 RightShift,
2079 Equality,
2080 Inequality,
2081 GreaterThan,
2082 LessThan,
2083 GreaterThanOrEqual,
2084 LessThanOrEqual,
2086 // Implicit and Explicit
2087 Implicit,
2088 Explicit,
2090 // Just because of enum
2094 public readonly OpType OperatorType;
2096 static readonly string [] [] names;
2098 static Operator ()
2100 names = new string[(int)OpType.TOP][];
2101 names [(int) OpType.LogicalNot] = new string [] { "!", "op_LogicalNot" };
2102 names [(int) OpType.OnesComplement] = new string [] { "~", "op_OnesComplement" };
2103 names [(int) OpType.Increment] = new string [] { "++", "op_Increment" };
2104 names [(int) OpType.Decrement] = new string [] { "--", "op_Decrement" };
2105 names [(int) OpType.True] = new string [] { "true", "op_True" };
2106 names [(int) OpType.False] = new string [] { "false", "op_False" };
2107 names [(int) OpType.Addition] = new string [] { "+", "op_Addition" };
2108 names [(int) OpType.Subtraction] = new string [] { "-", "op_Subtraction" };
2109 names [(int) OpType.UnaryPlus] = new string [] { "+", "op_UnaryPlus" };
2110 names [(int) OpType.UnaryNegation] = new string [] { "-", "op_UnaryNegation" };
2111 names [(int) OpType.Multiply] = new string [] { "*", "op_Multiply" };
2112 names [(int) OpType.Division] = new string [] { "/", "op_Division" };
2113 names [(int) OpType.Modulus] = new string [] { "%", "op_Modulus" };
2114 names [(int) OpType.BitwiseAnd] = new string [] { "&", "op_BitwiseAnd" };
2115 names [(int) OpType.BitwiseOr] = new string [] { "|", "op_BitwiseOr" };
2116 names [(int) OpType.ExclusiveOr] = new string [] { "^", "op_ExclusiveOr" };
2117 names [(int) OpType.LeftShift] = new string [] { "<<", "op_LeftShift" };
2118 names [(int) OpType.RightShift] = new string [] { ">>", "op_RightShift" };
2119 names [(int) OpType.Equality] = new string [] { "==", "op_Equality" };
2120 names [(int) OpType.Inequality] = new string [] { "!=", "op_Inequality" };
2121 names [(int) OpType.GreaterThan] = new string [] { ">", "op_GreaterThan" };
2122 names [(int) OpType.LessThan] = new string [] { "<", "op_LessThan" };
2123 names [(int) OpType.GreaterThanOrEqual] = new string [] { ">=", "op_GreaterThanOrEqual" };
2124 names [(int) OpType.LessThanOrEqual] = new string [] { "<=", "op_LessThanOrEqual" };
2125 names [(int) OpType.Implicit] = new string [] { "implicit", "op_Implicit" };
2126 names [(int) OpType.Explicit] = new string [] { "explicit", "op_Explicit" };
2129 public Operator (DeclSpace parent, OpType type, FullNamedExpression ret_type,
2130 Modifiers mod_flags, ParametersCompiled parameters,
2131 ToplevelBlock block, Attributes attrs, Location loc)
2132 : base (parent, null, ret_type, mod_flags, AllowedModifiers,
2133 new MemberName (GetMetadataName (type), loc), attrs, parameters)
2135 OperatorType = type;
2136 Block = block;
2139 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
2141 if (a.Type == pa.Conditional) {
2142 Error_ConditionalAttributeIsNotValid ();
2143 return;
2146 base.ApplyAttributeBuilder (a, cb, pa);
2149 public override bool Define ()
2151 const Modifiers RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
2152 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
2153 Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
2156 if (!base.Define ())
2157 return false;
2159 // imlicit and explicit operator of same types are not allowed
2160 if (OperatorType == OpType.Explicit)
2161 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Implicit), Parameters, Report);
2162 else if (OperatorType == OpType.Implicit)
2163 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Explicit), Parameters, Report);
2165 Type declaring_type = MethodData.DeclaringType;
2166 Type return_type = MemberType;
2167 Type first_arg_type = ParameterTypes [0];
2169 Type first_arg_type_unwrap = first_arg_type;
2170 if (TypeManager.IsNullableType (first_arg_type))
2171 first_arg_type_unwrap = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (first_arg_type) [0]);
2173 Type return_type_unwrap = return_type;
2174 if (TypeManager.IsNullableType (return_type))
2175 return_type_unwrap = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (return_type) [0]);
2177 if (TypeManager.IsDynamicType (return_type) || TypeManager.IsDynamicType (first_arg_type)) {
2178 Report.Error (1964, Location,
2179 "User-defined operator `{0}' cannot convert to or from the dynamic type",
2180 GetSignatureForError ());
2182 return false;
2186 // Rules for conversion operators
2188 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2189 if (first_arg_type_unwrap == return_type_unwrap && first_arg_type_unwrap == declaring_type){
2190 Report.Error (555, Location,
2191 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
2192 return false;
2195 Type conv_type;
2196 if (TypeManager.IsEqual (declaring_type, return_type) || declaring_type == return_type_unwrap) {
2197 conv_type = first_arg_type;
2198 } else if (TypeManager.IsEqual (declaring_type, first_arg_type) || declaring_type == first_arg_type_unwrap) {
2199 conv_type = return_type;
2200 } else {
2201 Report.Error (556, Location,
2202 "User-defined conversion must convert to or from the enclosing type");
2203 return false;
2207 // Because IsInterface and IsClass are not supported
2209 if (!TypeManager.IsGenericParameter (conv_type)) {
2210 if (conv_type.IsInterface) {
2211 Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
2212 GetSignatureForError ());
2213 return false;
2216 if (conv_type.IsClass) {
2217 if (TypeManager.IsSubclassOf (declaring_type, conv_type)) {
2218 Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from a base class",
2219 GetSignatureForError ());
2220 return false;
2223 if (TypeManager.IsSubclassOf (conv_type, declaring_type)) {
2224 Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from a derived class",
2225 GetSignatureForError ());
2226 return false;
2230 } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
2231 if (first_arg_type != declaring_type || Parameters.Types [1] != TypeManager.int32_type) {
2232 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");
2233 return false;
2235 } else if (Parameters.Count == 1) {
2236 // Checks for Unary operators
2238 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
2239 if (return_type != declaring_type && !TypeManager.IsSubclassOf (return_type, declaring_type)) {
2240 Report.Error (448, Location,
2241 "The return type for ++ or -- operator must be the containing type or derived from the containing type");
2242 return false;
2244 if (first_arg_type != declaring_type) {
2245 Report.Error (
2246 559, Location, "The parameter type for ++ or -- operator must be the containing type");
2247 return false;
2251 if (!TypeManager.IsEqual (first_arg_type_unwrap, declaring_type)){
2252 Report.Error (562, Location,
2253 "The parameter type of a unary operator must be the containing type");
2254 return false;
2257 if (OperatorType == OpType.True || OperatorType == OpType.False) {
2258 if (return_type != TypeManager.bool_type){
2259 Report.Error (
2260 215, Location,
2261 "The return type of operator True or False " +
2262 "must be bool");
2263 return false;
2267 } else if (!TypeManager.IsEqual (first_arg_type_unwrap, declaring_type)) {
2268 // Checks for Binary operators
2270 var second_arg_type = ParameterTypes [1];
2271 if (TypeManager.IsNullableType (second_arg_type))
2272 second_arg_type = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (second_arg_type) [0]);
2274 if (!TypeManager.IsEqual (second_arg_type, declaring_type)) {
2275 Report.Error (563, Location,
2276 "One of the parameters of a binary operator must be the containing type");
2277 return false;
2281 return true;
2284 protected override bool ResolveMemberType ()
2286 if (!base.ResolveMemberType ())
2287 return false;
2289 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2290 return true;
2293 // Operator cannot be override
2294 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
2296 return null;
2299 public static string GetName (OpType ot)
2301 return names [(int) ot] [0];
2304 public static string GetName (string metadata_name)
2306 for (int i = 0; i < names.Length; ++i) {
2307 if (names [i] [1] == metadata_name)
2308 return names [i] [0];
2310 return null;
2313 public static string GetMetadataName (OpType ot)
2315 return names [(int) ot] [1];
2318 public static string GetMetadataName (string name)
2320 for (int i = 0; i < names.Length; ++i) {
2321 if (names [i] [0] == name)
2322 return names [i] [1];
2324 return null;
2327 public static OpType? GetType (string metadata_name)
2329 for (int i = 0; i < names.Length; ++i) {
2330 if (names[i][1] == metadata_name)
2331 return (OpType) i;
2334 return null;
2337 public OpType GetMatchingOperator ()
2339 switch (OperatorType) {
2340 case OpType.Equality:
2341 return OpType.Inequality;
2342 case OpType.Inequality:
2343 return OpType.Equality;
2344 case OpType.True:
2345 return OpType.False;
2346 case OpType.False:
2347 return OpType.True;
2348 case OpType.GreaterThan:
2349 return OpType.LessThan;
2350 case OpType.LessThan:
2351 return OpType.GreaterThan;
2352 case OpType.GreaterThanOrEqual:
2353 return OpType.LessThanOrEqual;
2354 case OpType.LessThanOrEqual:
2355 return OpType.GreaterThanOrEqual;
2356 default:
2357 return OpType.TOP;
2361 public override string GetSignatureForError ()
2363 StringBuilder sb = new StringBuilder ();
2364 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2365 sb.AppendFormat ("{0}.{1} operator {2}",
2366 Parent.GetSignatureForError (), GetName (OperatorType), type_name.GetSignatureForError ());
2368 else {
2369 sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
2372 sb.Append (Parameters.GetSignatureForError ());
2373 return sb.ToString ();
2378 // This is used to compare method signatures
2380 struct MethodSignature {
2381 public string Name;
2382 public Type RetType;
2383 public Type [] Parameters;
2385 /// <summary>
2386 /// This delegate is used to extract methods which have the
2387 /// same signature as the argument
2388 /// </summary>
2389 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
2391 public MethodSignature (string name, Type ret_type, Type [] parameters)
2393 Name = name;
2394 RetType = ret_type;
2396 if (parameters == null)
2397 Parameters = Type.EmptyTypes;
2398 else
2399 Parameters = parameters;
2402 public override string ToString ()
2404 string pars = "";
2405 if (Parameters.Length != 0){
2406 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
2407 for (int i = 0; i < Parameters.Length; i++){
2408 sb.Append (Parameters [i]);
2409 if (i+1 < Parameters.Length)
2410 sb.Append (", ");
2412 pars = sb.ToString ();
2415 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
2418 public override int GetHashCode ()
2420 return Name.GetHashCode ();
2423 public override bool Equals (Object o)
2425 MethodSignature other = (MethodSignature) o;
2427 if (other.Name != Name)
2428 return false;
2430 if (other.RetType != RetType)
2431 return false;
2433 if (Parameters == null){
2434 if (other.Parameters == null)
2435 return true;
2436 return false;
2439 if (other.Parameters == null)
2440 return false;
2442 int c = Parameters.Length;
2443 if (other.Parameters.Length != c)
2444 return false;
2446 for (int i = 0; i < c; i++)
2447 if (other.Parameters [i] != Parameters [i])
2448 return false;
2450 return true;
2453 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
2455 MethodSignature sig = (MethodSignature) filter_criteria;
2457 if (m.Name != sig.Name)
2458 return false;
2460 Type ReturnType;
2461 MethodInfo mi = m as MethodInfo;
2462 PropertyInfo pi = m as PropertyInfo;
2464 if (mi != null)
2465 ReturnType = mi.ReturnType;
2466 else if (pi != null)
2467 ReturnType = pi.PropertyType;
2468 else
2469 return false;
2472 // we use sig.RetType == null to mean `do not check the
2473 // method return value.
2475 if (sig.RetType != null) {
2476 if (!TypeManager.IsEqual (ReturnType, sig.RetType))
2477 return false;
2480 Type [] args;
2481 if (mi != null)
2482 args = TypeManager.GetParameterData (mi).Types;
2483 else
2484 args = TypeManager.GetParameterData (pi).Types;
2485 Type [] sigp = sig.Parameters;
2487 if (args.Length != sigp.Length)
2488 return false;
2490 for (int i = args.Length - 1; i >= 0; i--)
2491 if (!TypeManager.IsEqual (args [i], sigp [i]))
2492 return false;
2494 return true;