context: //
  // method.cs: Method based declarations
  //
  // Authors: Miguel de Icaza (miguel@gnu.org)
  //          Martin Baulig (martin@ximian.com)
  //          Marek Safar (marek.safar@gmail.com)
  //
  // Dual licensed under the terms of the MIT X11 or GNU GPL
  //
  // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
  // Copyright 2004-2008 Novell, Inc
  // Copyright 2011 Xamarin Inc.
  //
  
  using System;
  using System.Collections.Generic;
  using System.Security;
  using System.Security.Permissions;
  using System.Text;
  using System.Linq;
  using Mono.CompilerServices.SymbolWriter;
  using System.Runtime.CompilerServices;
  
  #if NET_2_1
  using XmlElement = System.Object;
  #else
  using System.Xml;
  #endif
  
  #if STATIC
  using MetaType = IKVM.Reflection.Type;
  using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
  using IKVM.Reflection;
  using IKVM.Reflection.Emit;
  #else
  using MetaType = System.Type;
  using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
  using System.Reflection;
  using System.Reflection.Emit;
  #endif
  
  namespace Mono.CSharp {
  
  	public abstract class MethodCore : InterfaceMemberBase, IParametersMember
  	{
  		protected ParametersCompiled parameters;
  		protected ToplevelBlock block;
  		protected MethodSpec spec;
  
  		protected MethodCore (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod,
  			MemberName name, Attributes attrs, ParametersCompiled parameters)
  			: base (parent, type, mod, allowed_mod, name, attrs)
  		{
  			this.parameters = parameters;
  		}
  
  		public override Variance ExpectedMemberTypeVariance {
  			get {
  				return Variance.Covariant;
  			}
  		}
  
  		//
  		//  Returns the System.Type array for the parameters of this method
  		//
  		public TypeSpec [] ParameterTypes {
  			get {
  				return parameters.Types;
  			}
  		}
  
  		public ParametersCompiled ParameterInfo {
  			get {
  				return parameters;
  			}
  		}
  
  		AParametersCollection IParametersMember.Parameters {
  			get { return parameters; }
  		}
  		
  		public ToplevelBlock Block {
  			get {
  				return block;
  			}
  
  			set {
  				block = value;
  			}
  		}
  
  		public CallingConventions CallingConventions {
  			get {
  				CallingConventions cc = parameters.CallingConvention;
  				if (!IsInterface)
  					if ((ModFlags & Modifiers.STATIC) == 0)
  						cc |= CallingConventions.HasThis;
  
  				// FIXME: How is `ExplicitThis' used in C#?
  			
  				return cc;
  			}
  		}
  
  		protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
  		{
  			bool res = base.CheckOverrideAgainstBase (base_member);
  
  			//
  			// Check that the permissions are not being changed
  			//
  			if (!CheckAccessModifiers (this, base_member)) {
  				Error_CannotChangeAccessModifiers (this, base_member);
  				res = false;
  			}
  
  			return res;
  		}
  
  		protected override bool CheckBase ()
  		{
  			// Check whether arguments were correct.
  			if (!DefineParameters (parameters))
  				return false;
  
  			return base.CheckBase ();
  		}
  
  		//
  		//   Represents header string for documentation comment.
  		//
  		public override string DocCommentHeader 
  		{
  			get { return "M:"; }
  		}
  
  		public override void Emit ()
  		{
  			if ((ModFlags & Modifiers.COMPILER_GENERATED) == 0) {
  				parameters.CheckConstraints (this);
  			}
  
  			base.Emit ();
  		}
  
  		public override bool EnableOverloadChecks (MemberCore overload)
  		{
  			if (overload is MethodCore) {
  				caching_flags |= Flags.MethodOverloadsExist;
  				return true;
  			}
  
  			if (overload is AbstractPropertyEventMethod)
  				return true;
  
  			return base.EnableOverloadChecks (overload);
  		}
  
  		public override string GetSignatureForDocumentation ()
  		{
  			string s = base.GetSignatureForDocumentation ();
  			if (MemberName.Arity > 0)
  				s += "``" + MemberName.Arity.ToString ();
  
  			return s + parameters.GetSignatureForDocumentation ();
  		}
  
  		public MethodSpec Spec {
  			get { return spec; }
  		}
  
  		protected override bool VerifyClsCompliance ()
  		{
  			if (!base.VerifyClsCompliance ())
  				return false;
  
  			if (parameters.HasArglist) {
  				Report.Warning (3000, 1, Location, "Methods with variable arguments are not CLS-compliant");
  			}
  
  			if (member_type != null && !member_type.IsCLSCompliant ()) {
  				Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant",
  					GetSignatureForError ());
  			}
  
  			parameters.VerifyClsCompliance (this);
  			return true;
  		}
  	}
  
  	public interface IGenericMethodDefinition : IMethodDefinition
  	{
  		TypeParameterSpec[] TypeParameters { get; }
  		int TypeParametersCount { get; }
  
  //		MethodInfo MakeGenericMethod (TypeSpec[] targs);
  	}
  
  	public sealed class MethodSpec : MemberSpec, IParametersMember
  	{
  		MethodBase inflatedMetaInfo;
  		AParametersCollection parameters;
  		TypeSpec returnType;
  
  		TypeSpec[] targs;
  		TypeParameterSpec[] constraints;
  
  		public static readonly MethodSpec Excluded = new MethodSpec (MemberKind.Method, InternalType.FakeInternalType, null, null, ParametersCompiled.EmptyReadOnlyParameters, 0);
  
  		public MethodSpec (MemberKind kind, TypeSpec declaringType, IMethodDefinition details, TypeSpec returnType,
  			AParametersCollection parameters, Modifiers modifiers)
  			: base (kind, declaringType, details, modifiers)
  		{
  			this.parameters = parameters;
  			this.returnType = returnType;
  		}
  
  		#region Properties
  
  		public override int Arity {
  			get {
  				return IsGeneric ? GenericDefinition.TypeParametersCount : 0;
  			}
  		}
  
  		public TypeParameterSpec[] Constraints {
  			get {
  				if (constraints == null && IsGeneric)
  					constraints = GenericDefinition.TypeParameters;
  
  				return constraints;
  			}
  		}
  
  		public bool IsConstructor {
  			get {
  				return Kind == MemberKind.Constructor;
  			}
  		}
  
  		public new IMethodDefinition MemberDefinition {
  			get {
  				return (IMethodDefinition) definition;
  			}
  		}
  
  		public IGenericMethodDefinition GenericDefinition {
  			get {
  				return (IGenericMethodDefinition) definition;
  			}
  		}
  
  		public bool IsAsync {
  			get {
  				return (Modifiers & Modifiers.ASYNC) != 0;
  			}
  		}
  
  		public bool IsExtensionMethod {
  			get {
  				return IsStatic && parameters.HasExtensionMethodType;
  			}
  		}
  
  		public bool IsSealed {
  			get {
  				return (Modifiers & Modifiers.SEALED) != 0;
  			}
  		}
  
  		// When is virtual or abstract
  		public bool IsVirtual {
  			get {
  				return (Modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) != 0;
  			}
  		}
  
  		public bool IsReservedMethod {
  			get {
  				return Kind == MemberKind.Operator || IsAccessor;
  			}
  		}
  
  		TypeSpec IInterfaceMemberSpec.MemberType {
  			get {
  				return returnType;
  			}
  		}
  
  		public AParametersCollection Parameters {
  			get { 
  				return parameters;
  			}
  		}
  
  		public TypeSpec ReturnType {
  			get {
  				return returnType;
  			}
  		}
  
  		public TypeSpec[] TypeArguments {
  			get {
  				return targs;
  			}
  		}
  
  		#endregion
  
  		public MethodSpec GetGenericMethodDefinition ()
  		{
  			if (!IsGeneric && !DeclaringType.IsGeneric)
  				return this;
  
  			return MemberCache.GetMember (declaringType, this);
  		}
  
  		public MethodBase GetMetaInfo ()
  		{
  			//
  			// inflatedMetaInfo is extra field needed for cases where we
  			// inflate method but another nested type can later inflate
  			// again (the cache would be build with inflated metaInfo) and
  			// TypeBuilder can work with method definitions only
  			//
  
gt: 			if (inflatedMetaInfo == null) {