Merge pull request #1899 from saper/resgencond
[mono.git] / mcs / mcs / method.cs
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
12 // Copyright 2011 Xamarin Inc.
13 //
14
15 using System;
16 using System.Collections.Generic;
17 using System.Security;
18 using System.Security.Permissions;
19 using System.Text;
20 using System.Linq;
21 using Mono.CompilerServices.SymbolWriter;
22 using System.Runtime.CompilerServices;
23
24 #if NET_2_1
25 using XmlElement = System.Object;
26 #else
27 using System.Xml;
28 #endif
29
30 #if STATIC
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;
35 #else
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;
40 #endif
41
42 namespace Mono.CSharp {
43
44         public abstract class MethodCore : InterfaceMemberBase, IParametersMember
45         {
46                 protected ParametersCompiled parameters;
47                 protected ToplevelBlock block;
48                 protected MethodSpec spec;
49
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)
53                 {
54                         this.parameters = parameters;
55                 }
56
57                 public override Variance ExpectedMemberTypeVariance {
58                         get {
59                                 return Variance.Covariant;
60                         }
61                 }
62
63                 //
64                 //  Returns the System.Type array for the parameters of this method
65                 //
66                 public TypeSpec [] ParameterTypes {
67                         get {
68                                 return parameters.Types;
69                         }
70                 }
71
72                 public ParametersCompiled ParameterInfo {
73                         get {
74                                 return parameters;
75                         }
76                 }
77
78                 AParametersCollection IParametersMember.Parameters {
79                         get { return parameters; }
80                 }
81                 
82                 public ToplevelBlock Block {
83                         get {
84                                 return block;
85                         }
86
87                         set {
88                                 block = value;
89                         }
90                 }
91
92                 public CallingConventions CallingConventions {
93                         get {
94                                 CallingConventions cc = parameters.CallingConvention;
95                                 if (!IsInterface)
96                                         if ((ModFlags & Modifiers.STATIC) == 0)
97                                                 cc |= CallingConventions.HasThis;
98
99                                 // FIXME: How is `ExplicitThis' used in C#?
100                         
101                                 return cc;
102                         }
103                 }
104
105                 protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
106                 {
107                         bool res = base.CheckOverrideAgainstBase (base_member);
108
109                         //
110                         // Check that the permissions are not being changed
111                         //
112                         if (!CheckAccessModifiers (this, base_member)) {
113                                 Error_CannotChangeAccessModifiers (this, base_member);
114                                 res = false;
115                         }
116
117                         return res;
118                 }
119
120                 protected override bool CheckBase ()
121                 {
122                         // Check whether arguments were correct.
123                         if (!DefineParameters (parameters))
124                                 return false;
125
126                         return base.CheckBase ();
127                 }
128
129                 //
130                 //   Represents header string for documentation comment.
131                 //
132                 public override string DocCommentHeader 
133                 {
134                         get { return "M:"; }
135                 }
136
137                 public override void Emit ()
138                 {
139                         if ((ModFlags & Modifiers.COMPILER_GENERATED) == 0) {
140                                 parameters.CheckConstraints (this);
141                         }
142
143                         base.Emit ();
144                 }
145
146                 public override bool EnableOverloadChecks (MemberCore overload)
147                 {
148                         if (overload is MethodCore) {
149                                 caching_flags |= Flags.MethodOverloadsExist;
150                                 return true;
151                         }
152
153                         if (overload is AbstractPropertyEventMethod)
154                                 return true;
155
156                         return base.EnableOverloadChecks (overload);
157                 }
158
159                 public override string GetSignatureForDocumentation ()
160                 {
161                         string s = base.GetSignatureForDocumentation ();
162                         if (MemberName.Arity > 0)
163                                 s += "``" + MemberName.Arity.ToString ();
164
165                         return s + parameters.GetSignatureForDocumentation ();
166                 }
167
168                 public override void PrepareEmit ()
169                 {
170                         base.PrepareEmit ();
171                         parameters.ResolveDefaultValues (this);
172                 }
173
174                 public MethodSpec Spec {
175                         get { return spec; }
176                 }
177
178                 protected override bool VerifyClsCompliance ()
179                 {
180                         if (!base.VerifyClsCompliance ())
181                                 return false;
182
183                         if (parameters.HasArglist) {
184                                 Report.Warning (3000, 1, Location, "Methods with variable arguments are not CLS-compliant");
185                         }
186
187                         if (member_type != null && !member_type.IsCLSCompliant ()) {
188                                 Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant",
189                                         GetSignatureForError ());
190                         }
191
192                         parameters.VerifyClsCompliance (this);
193                         return true;
194                 }
195         }
196
197         public interface IGenericMethodDefinition : IMethodDefinition
198         {
199                 TypeParameterSpec[] TypeParameters { get; }
200                 int TypeParametersCount { get; }
201
202 //              MethodInfo MakeGenericMethod (TypeSpec[] targs);
203         }
204
205         public sealed class MethodSpec : MemberSpec, IParametersMember
206         {
207                 MethodBase inflatedMetaInfo;
208                 AParametersCollection parameters;
209                 TypeSpec returnType;
210
211                 TypeSpec[] targs;
212                 TypeParameterSpec[] constraints;
213
214                 public static readonly MethodSpec Excluded = new MethodSpec (MemberKind.Method, InternalType.FakeInternalType, null, null, ParametersCompiled.EmptyReadOnlyParameters, 0);
215
216                 public MethodSpec (MemberKind kind, TypeSpec declaringType, IMethodDefinition details, TypeSpec returnType,
217                         AParametersCollection parameters, Modifiers modifiers)
218                         : base (kind, declaringType, details, modifiers)
219                 {
220                         this.parameters = parameters;
221                         this.returnType = returnType;
222                 }
223
224                 #region Properties
225
226                 public override int Arity {
227                         get {
228                                 return IsGeneric ? GenericDefinition.TypeParametersCount : 0;
229                         }
230                 }
231
232                 public TypeParameterSpec[] Constraints {
233                         get {
234                                 if (constraints == null && IsGeneric)
235                                         constraints = GenericDefinition.TypeParameters;
236
237                                 return constraints;
238                         }
239                 }
240
241                 public bool IsConstructor {
242                         get {
243                                 return Kind == MemberKind.Constructor;
244                         }
245                 }
246
247                 public new IMethodDefinition MemberDefinition {
248                         get {
249                                 return (IMethodDefinition) definition;
250                         }
251                 }
252
253                 public IGenericMethodDefinition GenericDefinition {
254                         get {
255                                 return (IGenericMethodDefinition) definition;
256                         }
257                 }
258
259                 public bool IsAsync {
260                         get {
261                                 return (Modifiers & Modifiers.ASYNC) != 0;
262                         }
263                 }
264
265                 public bool IsExtensionMethod {
266                         get {
267                                 return IsStatic && parameters.HasExtensionMethodType;
268                         }
269                 }
270
271                 public bool IsSealed {
272                         get {
273                                 return (Modifiers & Modifiers.SEALED) != 0;
274                         }
275                 }
276
277                 // When is virtual or abstract
278                 public bool IsVirtual {
279                         get {
280                                 return (Modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) != 0;
281                         }
282                 }
283
284                 public bool IsReservedMethod {
285                         get {
286                                 return Kind == MemberKind.Operator || IsAccessor;
287                         }
288                 }
289
290                 TypeSpec IInterfaceMemberSpec.MemberType {
291                         get {
292                                 return returnType;
293                         }
294                 }
295
296                 public AParametersCollection Parameters {
297                         get { 
298                                 return parameters;
299                         }
300                 }
301
302                 public TypeSpec ReturnType {
303                         get {
304                                 return returnType;
305                         }
306                 }
307
308                 public TypeSpec[] TypeArguments {
309                         get {
310                                 return targs;
311                         }
312                 }
313
314                 #endregion
315
316                 public MethodSpec GetGenericMethodDefinition ()
317                 {
318                         if (!IsGeneric && !DeclaringType.IsGeneric)
319                                 return this;
320
321                         return MemberCache.GetMember (declaringType, this);
322                 }
323
324                 public MethodBase GetMetaInfo ()
325                 {
326                         //
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
331                         //
332                         if (inflatedMetaInfo == null) {
333                                 if ((state & StateFlags.PendingMetaInflate) != 0) {
334                                         var dt_meta = DeclaringType.GetMetaInfo ();
335
336                                         if (DeclaringType.IsTypeBuilder) {
337                                                 if (IsConstructor)
338                                                         inflatedMetaInfo = TypeBuilder.GetConstructor (dt_meta, (ConstructorInfo) MemberDefinition.Metadata);
339                                                 else
340                                                         inflatedMetaInfo = TypeBuilder.GetMethod (dt_meta, (MethodInfo) MemberDefinition.Metadata);
341                                         } else {
342 #if STATIC
343                                                 // it should not be reached
344                                                 throw new NotImplementedException ();
345 #else
346                                                 inflatedMetaInfo = MethodInfo.GetMethodFromHandle (MemberDefinition.Metadata.MethodHandle, dt_meta.TypeHandle);
347 #endif
348                                         }
349
350                                         state &= ~StateFlags.PendingMetaInflate;
351                                 } else {
352                                         inflatedMetaInfo = MemberDefinition.Metadata;
353                                 }
354                         }
355
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 ();
360
361                                 inflatedMetaInfo = ((MethodInfo) inflatedMetaInfo).MakeGenericMethod (sre_targs);
362                                 state &= ~StateFlags.PendingMakeMethod;
363                         }
364
365                         return inflatedMetaInfo;
366                 }
367
368                 public override string GetSignatureForDocumentation ()
369                 {
370                         string name;
371                         switch (Kind) {
372                         case MemberKind.Constructor:
373                                 name = "#ctor";
374                                 break;
375                         case MemberKind.Method:
376                                 if (Arity > 0)
377                                         name = Name + "``" + Arity.ToString ();
378                                 else
379                                         name = Name;
380
381                                 break;
382                         default:
383                                 name = Name;
384                                 break;
385                         }
386
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 ();
392                                 }
393                         }
394
395                         return name;
396                 }
397
398                 public override string GetSignatureForError ()
399                 {
400                         string name;
401                         if (IsConstructor) {
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 ();
407                                 } else {
408                                         name = DeclaringType.GetSignatureForError () + ".operator " + Operator.GetName (op);
409                                 }
410                         } else if (IsAccessor) {
411                                 int split = Name.IndexOf ('_');
412                                 name = Name.Substring (split + 1);
413                                 var postfix = Name.Substring (0, split);
414                                 if (split == 3) {
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);
420                                         }
421                                 }
422
423                                 return DeclaringType.GetSignatureForError () + "." + name + "." + postfix;
424                         } else {
425                                 name = base.GetSignatureForError ();
426                                 if (targs != null)
427                                         name += "<" + TypeManager.CSharpName (targs) + ">";
428                                 else if (IsGeneric)
429                                         name += "<" + TypeManager.CSharpName (GenericDefinition.TypeParameters) + ">";
430                         }
431
432                         return name + parameters.GetSignatureForError ();
433                 }
434
435                 public override MemberSpec InflateMember (TypeParameterInflator inflator)
436                 {
437                         var ms = (MethodSpec) base.InflateMember (inflator);
438                         ms.inflatedMetaInfo = null;
439                         ms.returnType = inflator.Inflate (returnType);
440                         ms.parameters = parameters.Inflate (inflator);
441                         if (IsGeneric)
442                                 ms.constraints = TypeParameterSpec.InflateConstraints (inflator, Constraints);
443
444                         return ms;
445                 }
446
447                 public MethodSpec MakeGenericMethod (IMemberContext context, params TypeSpec[] targs)
448                 {
449                         if (targs == null)
450                                 throw new ArgumentNullException ();
451 // TODO MemberCache
452 //                      if (generic_intances != null && generic_intances.TryGetValue (targs, out ginstance))
453 //                              return ginstance;
454
455                         //if (generic_intances == null)
456                         //    generic_intances = new Dictionary<TypeSpec[], Method> (TypeSpecArrayComparer.Default);
457
458                         var inflator = new TypeParameterInflator (context, DeclaringType, GenericDefinition.TypeParameters, targs);
459
460                         var inflated = (MethodSpec) MemberwiseClone ();
461                         inflated.declaringType = inflator.TypeInstance;
462                         inflated.returnType = inflator.Inflate (returnType);
463                         inflated.parameters = parameters.Inflate (inflator);
464                         inflated.targs = targs;
465                         inflated.constraints = TypeParameterSpec.InflateConstraints (inflator, constraints ?? GenericDefinition.TypeParameters);
466                         inflated.state |= StateFlags.PendingMakeMethod;
467
468                         //                      if (inflated.parent == null)
469                         //                              inflated.parent = parent;
470
471                         //generic_intances.Add (targs, inflated);
472                         return inflated;
473                 }
474
475                 public MethodSpec Mutate (TypeParameterMutator mutator)
476                 {
477                         var targs = TypeArguments;
478                         if (targs != null)
479                                 targs = mutator.Mutate (targs);
480
481                         var decl = DeclaringType;
482                         if (DeclaringType.IsGenericOrParentIsGeneric) {
483                                 decl = mutator.Mutate (decl);
484                         }
485
486                         if (targs == TypeArguments && decl == DeclaringType)
487                                 return this;
488
489                         var ms = (MethodSpec) MemberwiseClone ();
490                         if (decl != DeclaringType) {
491                                 ms.inflatedMetaInfo = null;
492                                 ms.declaringType = decl;
493                                 ms.state |= StateFlags.PendingMetaInflate;
494                         }
495
496                         if (targs != null) {
497                                 ms.targs = targs;
498                                 ms.state |= StateFlags.PendingMakeMethod;
499                         }
500
501                         return ms;
502                 }
503
504                 public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
505                 {
506                         var missing = returnType.ResolveMissingDependencies (this);
507                         foreach (var pt in parameters.Types) {
508                                 var m = pt.GetMissingDependencies (this);
509                                 if (m == null)
510                                         continue;
511
512                                 if (missing == null)
513                                         missing = new List<MissingTypeSpecReference> ();
514
515                                 missing.AddRange (m);
516                         }
517
518                         if (Arity > 0) {
519                                 foreach (var tp in GenericDefinition.TypeParameters) {
520                                         var m = tp.GetMissingDependencies (this);
521
522                                         if (m == null)
523                                                 continue;
524
525                                         if (missing == null)
526                                                 missing = new List<MissingTypeSpecReference> ();
527
528                                         missing.AddRange (m);
529                                 }
530                         }
531
532                         return missing;                 
533                 }
534         }
535
536         public abstract class MethodOrOperator : MethodCore, IMethodData, IMethodDefinition
537         {
538                 ReturnParameter return_attributes;
539                 SecurityType declarative_security;
540                 protected MethodData MethodData;
541
542                 static readonly string[] attribute_targets = new string [] { "method", "return" };
543
544                 protected MethodOrOperator (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name,
545                                 Attributes attrs, ParametersCompiled parameters)
546                         : base (parent, type, mod, allowed_mod, name, attrs, parameters)
547                 {
548                 }
549
550                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
551                 {
552                         if (a.Target == AttributeTargets.ReturnValue) {
553                                 if (return_attributes == null)
554                                         return_attributes = new ReturnParameter (this, MethodBuilder, Location);
555
556                                 return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
557                                 return;
558                         }
559
560                         if (a.Type == pa.MethodImpl) {
561                                 if ((ModFlags & Modifiers.ASYNC) != 0 && (a.GetMethodImplOptions () & MethodImplOptions.Synchronized) != 0) {
562                                         Report.Error (4015, a.Location, "`{0}': Async methods cannot use `MethodImplOptions.Synchronized'",
563                                                 GetSignatureForError ());
564                                 }
565
566                                 is_external_implementation = a.IsInternalCall ();
567                         } else if (a.Type == pa.DllImport) {
568                                 const Modifiers extern_static = Modifiers.EXTERN | Modifiers.STATIC;
569                                 if ((ModFlags & extern_static) != extern_static) {
570                                         Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
571                                 }
572
573                                 if (MemberName.IsGeneric || Parent.IsGenericOrParentIsGeneric) {
574                                         Report.Error (7042, a.Location, 
575                                                 "The DllImport attribute cannot be applied to a method that is generic or contained in a generic type");
576                                 }
577
578                                 is_external_implementation = true;
579                         }
580
581                         if (a.IsValidSecurityAttribute ()) {
582                                 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
583                                 return;
584                         }
585
586                         if (MethodBuilder != null)
587                                 MethodBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
588                 }
589
590                 public override AttributeTargets AttributeTargets {
591                         get {
592                                 return AttributeTargets.Method; 
593                         }
594                 }
595
596                 MethodBase IMethodDefinition.Metadata {
597                         get {
598                                 return MethodData.MethodBuilder;
599                         }
600                 }
601
602                 // TODO: Remove and use MethodData abstraction
603                 public MethodBuilder MethodBuilder {
604                         get {
605                                 return MethodData.MethodBuilder;
606                         }
607                 }
608
609                 protected override bool CheckForDuplications ()
610                 {
611                         return Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
612                 }
613
614                 public virtual EmitContext CreateEmitContext (ILGenerator ig, SourceMethodBuilder sourceMethod)
615                 {
616                         return new EmitContext (this, ig, MemberType, sourceMethod);
617                 }
618
619                 public override bool Define ()
620                 {
621                         if (!base.Define ())
622                                 return false;
623
624                         if (!CheckBase ())
625                                 return false;
626
627                         MemberKind kind;
628                         if (this is Operator)
629                                 kind = MemberKind.Operator;
630                         else if (this is Destructor)
631                                 kind = MemberKind.Destructor;
632                         else
633                                 kind = MemberKind.Method;
634
635                         string explicit_name;
636
637                         if (IsPartialDefinition) {
638                                 caching_flags &= ~Flags.Excluded_Undetected;
639                                 caching_flags |= Flags.Excluded;
640
641                                 // Add to member cache only when a partial method implementation has not been found yet
642                                 if ((caching_flags & Flags.PartialDefinitionExists) != 0)
643                                         return true;
644
645                                 if (IsExplicitImpl)
646                                         return true;
647
648                                 explicit_name = null;
649                         } else {
650                                 MethodData = new MethodData (this, ModFlags, flags, this, base_method);
651
652                                 if (!MethodData.Define (Parent.PartialContainer, GetFullName (MemberName)))
653                                         return false;
654
655                                 explicit_name = MethodData.MetadataName;
656                         }
657
658                         spec = new MethodSpec (kind, Parent.Definition, this, ReturnType, parameters, ModFlags);
659                         if (MemberName.Arity > 0)
660                                 spec.IsGeneric = true;
661
662                         Parent.MemberCache.AddMember (this, explicit_name, spec);
663
664                         return true;
665                 }
666
667                 protected override void DoMemberTypeIndependentChecks ()
668                 {
669                         base.DoMemberTypeIndependentChecks ();
670
671                         CheckAbstractAndExtern (block != null);
672
673                         if ((ModFlags & Modifiers.PARTIAL) != 0) {
674                                 for (int i = 0; i < parameters.Count; ++i) {
675                                         IParameterData p = parameters.FixedParameters [i];
676                                         if ((p.ModFlags & Parameter.Modifier.OUT) != 0) {
677                                                 Report.Error (752, Location, "`{0}': A partial method parameters cannot use `out' modifier",
678                                                         GetSignatureForError ());
679                                         }
680
681                                         if (p.HasDefaultValue && IsPartialImplementation)
682                                                 ((Parameter) p).Warning_UselessOptionalParameter (Report);
683                                 }
684                         }
685                 }
686
687                 protected override void DoMemberTypeDependentChecks ()
688                 {
689                         base.DoMemberTypeDependentChecks ();
690
691                         if (MemberType.IsStatic) {
692                                 Error_StaticReturnType ();
693                         }
694                 }
695
696                 public override void Emit ()
697                 {
698                         if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
699                                 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (MethodBuilder);
700                         if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
701                                 Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (MethodBuilder);
702                         if ((ModFlags & Modifiers.DEBUGGER_STEP_THROUGH) != 0)
703                                 Module.PredefinedAttributes.DebuggerStepThrough.EmitAttribute (MethodBuilder);
704
705                         if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
706                                 return_attributes = new ReturnParameter (this, MethodBuilder, Location);
707                                 Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
708                         } else if (ReturnType.HasDynamicElement) {
709                                 return_attributes = new ReturnParameter (this, MethodBuilder, Location);
710                                 Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location);
711                         }
712
713                         if (OptAttributes != null)
714                                 OptAttributes.Emit ();
715
716                         if (declarative_security != null) {
717                                 foreach (var de in declarative_security) {
718 #if STATIC
719                                         MethodBuilder.__AddDeclarativeSecurity (de);
720 #else
721                                         MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value);
722 #endif
723                                 }
724                         }
725
726                         if (type_expr != null)
727                                 ConstraintChecker.Check (this, member_type, type_expr.Location);
728
729                         base.Emit ();
730
731                         if (MethodData != null)
732                                 MethodData.Emit (Parent);
733
734                         if (block != null && block.StateMachine is AsyncTaskStorey) {
735                                 var psm = Module.PredefinedAttributes.AsyncStateMachine;
736                                 psm.EmitAttribute (MethodBuilder, block.StateMachine);
737                         }
738
739                         if ((ModFlags & Modifiers.PARTIAL) == 0)
740                                 Block = null;
741                 }
742
743                 protected void Error_ConditionalAttributeIsNotValid ()
744                 {
745                         Report.Error (577, Location,
746                                 "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
747                                 GetSignatureForError ());
748                 }
749
750                 public bool IsPartialDefinition {
751                         get {
752                                 return (ModFlags & Modifiers.PARTIAL) != 0 && Block == null;
753                         }
754                 }
755
756                 public bool IsPartialImplementation {
757                         get {
758                                 return (ModFlags & Modifiers.PARTIAL) != 0 && Block != null;
759                         }
760                 }
761
762                 public override string[] ValidAttributeTargets {
763                         get {
764                                 return attribute_targets;
765                         }
766                 }
767
768                 #region IMethodData Members
769
770                 bool IMethodData.IsAccessor {
771                         get {
772                                 return false;
773                         }
774                 }
775
776                 public TypeSpec ReturnType {
777                         get {
778                                 return MemberType;
779                         }
780                 }
781
782                 public MemberName MethodName {
783                         get {
784                                 return MemberName;
785                         }
786                 }
787
788                 /// <summary>
789                 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
790                 /// </summary>
791                 public override string[] ConditionalConditions ()
792                 {
793                         if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
794                                 return null;
795
796                         if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.Excluded) != 0)
797                                 return new string [0];
798
799                         caching_flags &= ~Flags.Excluded_Undetected;
800                         string[] conditions;
801
802                         if (base_method == null) {
803                                 if (OptAttributes == null)
804                                         return null;
805
806                                 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
807                                 if (attrs == null)
808                                         return null;
809
810                                 conditions = new string[attrs.Length];
811                                 for (int i = 0; i < conditions.Length; ++i)
812                                         conditions[i] = attrs[i].GetConditionalAttributeValue ();
813                         } else {
814                                 conditions = base_method.MemberDefinition.ConditionalConditions();
815                         }
816
817                         if (conditions != null)
818                                 caching_flags |= Flags.Excluded;
819
820                         return conditions;
821                 }
822
823                 #endregion
824
825                 public override void PrepareEmit ()
826                 {
827                         base.PrepareEmit ();
828
829                         var mb = MethodData.DefineMethodBuilder (Parent);
830
831                         if (CurrentTypeParameters != null) {
832                                 string[] gnames = new string[CurrentTypeParameters.Count];
833                                 for (int i = 0; i < gnames.Length; ++i) {
834                                         gnames[i] = CurrentTypeParameters[i].Name;
835                                 }
836
837                                 var gen_params = MethodBuilder.DefineGenericParameters (gnames);
838
839                                 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
840                                         var tp = CurrentTypeParameters[i];
841
842                                         tp.Define (gen_params[i]);
843                                 }
844                         }
845
846                         //
847                         // Generic method has been already defined to resolve method parameters
848                         // correctly when they use type parameters
849                         //
850                         mb.SetParameters (parameters.GetMetaInfo ());
851                         mb.SetReturnType (ReturnType.GetMetaInfo ());
852                 }
853
854                 public override void WriteDebugSymbol (MonoSymbolFile file)
855                 {
856                         if (MethodData != null && !IsPartialDefinition)
857                                 MethodData.WriteDebugSymbol (file);
858                 }
859         }
860
861         public class Method : MethodOrOperator, IGenericMethodDefinition
862         {
863                 Method partialMethodImplementation;
864
865                 public Method (TypeDefinition parent, FullNamedExpression return_type, Modifiers mod, MemberName name, ParametersCompiled parameters, Attributes attrs)
866                         : base (parent, return_type, mod,
867                                 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface :
868                                 parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct | Modifiers.ASYNC :
869                                 AllowedModifiersClass | Modifiers.ASYNC,
870                                 name, attrs, parameters)
871                 {
872                 }
873
874                 protected Method (TypeDefinition parent, FullNamedExpression return_type, Modifiers mod, Modifiers amod,
875                                         MemberName name, ParametersCompiled parameters, Attributes attrs)
876                         : base (parent, return_type, mod, amod, name, attrs, parameters)
877                 {
878                 }
879
880                 #region Properties
881
882                 public override TypeParameters CurrentTypeParameters {
883                         get {
884                                 return MemberName.TypeParameters;
885                         }
886                 }
887
888                 public TypeParameterSpec[] TypeParameters {
889                         get {
890                                 return CurrentTypeParameters.Types;
891                         }
892                 }
893
894                 public int TypeParametersCount {
895                         get {
896                                 return CurrentTypeParameters == null ? 0 : CurrentTypeParameters.Count;
897                         }
898                 }
899
900                 #endregion
901
902                 public override void Accept (StructuralVisitor visitor)
903                 {
904                         visitor.Visit (this);
905                 }
906
907                 public static Method Create (TypeDefinition parent, FullNamedExpression returnType, Modifiers mod,
908                                    MemberName name, ParametersCompiled parameters, Attributes attrs)
909                 {
910                         var m = new Method (parent, returnType, mod, name, parameters, attrs);
911
912                         if ((mod & Modifiers.PARTIAL) != 0) {
913                                 const Modifiers invalid_partial_mod = Modifiers.AccessibilityMask | Modifiers.ABSTRACT | Modifiers.EXTERN |
914                                         Modifiers.NEW | Modifiers.OVERRIDE | Modifiers.SEALED | Modifiers.VIRTUAL;
915
916                                 if ((mod & invalid_partial_mod) != 0) {
917                                         m.Report.Error (750, m.Location,
918                                                 "A partial method cannot define access modifier or any of abstract, extern, new, override, sealed, or virtual modifiers");
919                                         mod &= ~invalid_partial_mod;
920                                 }
921
922                                 if ((parent.ModFlags & Modifiers.PARTIAL) == 0) {
923                                         m.Report.Error (751, m.Location, 
924                                                 "A partial method must be declared within a partial class or partial struct");
925                                 }
926                         }
927
928                         if ((mod & Modifiers.STATIC) == 0 && parameters.HasExtensionMethodType) {
929                                 m.Report.Error (1105, m.Location, "`{0}': Extension methods must be declared static",
930                                         m.GetSignatureForError ());
931                         }
932
933
934                         return m;
935                 }
936
937                 public override string GetSignatureForError()
938                 {
939                         return base.GetSignatureForError () + parameters.GetSignatureForError ();
940                 }
941
942                 void Error_DuplicateEntryPoint (Method b)
943                 {
944                         Report.Error (17, b.Location,
945                                 "Program `{0}' has more than one entry point defined: `{1}'",
946                                 b.Module.Builder.ScopeName, b.GetSignatureForError ());
947                 }
948
949                 bool IsEntryPoint ()
950                 {
951                         if (ReturnType.Kind != MemberKind.Void && ReturnType.BuiltinType != BuiltinTypeSpec.Type.Int)
952                                 return false;
953
954                         if (parameters.IsEmpty)
955                                 return true;
956
957                         if (parameters.Count > 1)
958                                 return false;
959
960                         var ac = parameters.Types [0] as ArrayContainer;
961                         return ac != null && ac.Rank == 1 && ac.Element.BuiltinType == BuiltinTypeSpec.Type.String &&
962                                         (parameters[0].ModFlags & Parameter.Modifier.RefOutMask) == 0;
963                 }
964
965                 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
966                 {
967                         if (arity == 0) {
968                                 var tp = CurrentTypeParameters;
969                                 if (tp != null) {
970                                         TypeParameter t = tp.Find (name);
971                                         if (t != null)
972                                                 return new TypeParameterExpr (t, loc);
973                                 }
974                         }
975
976                         return base.LookupNamespaceOrType (name, arity, mode, loc);
977                 }
978
979                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
980                 {
981                         if (a.Type == pa.Conditional) {
982                                 if (IsExplicitImpl) {
983                                         Error_ConditionalAttributeIsNotValid ();
984                                         return;
985                                 }
986
987                                 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
988                                         Report.Error (243, Location, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ());
989                                         return;
990                                 }
991
992                                 if (ReturnType.Kind != MemberKind.Void) {
993                                         Report.Error (578, Location, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ());
994                                         return;
995                                 }
996
997                                 if (IsInterface) {
998                                         Report.Error (582, Location, "Conditional not valid on interface members");
999                                         return;
1000                                 }
1001
1002                                 if (MethodData.implementing != null) {
1003                                         Report.SymbolRelatedToPreviousError (MethodData.implementing.DeclaringType);
1004                                         Report.Error (629, Location, "Conditional member `{0}' cannot implement interface member `{1}'",
1005                                                 GetSignatureForError (), TypeManager.CSharpSignature (MethodData.implementing));
1006                                         return;
1007                                 }
1008
1009                                 for (int i = 0; i < parameters.Count; ++i) {
1010                                         if ((parameters.FixedParameters [i].ModFlags & Parameter.Modifier.OUT) != 0) {
1011                                                 Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
1012                                                 return;
1013                                         }
1014                                 }
1015                         }
1016
1017                         if (a.Type == pa.Extension) {
1018                                 a.Error_MisusedExtensionAttribute ();
1019                                 return;
1020                         }
1021
1022                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1023                 }
1024
1025                 void CreateTypeParameters ()
1026                 {
1027                         var tparams = MemberName.TypeParameters;
1028                         var parent_tparams = Parent.TypeParametersAll;
1029
1030                         for (int i = 0; i < MemberName.Arity; i++) {
1031                                 string type_argument_name = tparams[i].MemberName.Name;
1032
1033                                 if (block == null) {
1034                                         int idx = parameters.GetParameterIndexByName (type_argument_name);
1035                                         if (idx >= 0) {
1036                                                 var b = block;
1037                                                 if (b == null)
1038                                                         b = new ToplevelBlock (Compiler, Location);
1039
1040                                                 b.Error_AlreadyDeclaredTypeParameter (type_argument_name, parameters[i].Location);
1041                                         }
1042                                 } else {
1043                                         INamedBlockVariable variable = null;
1044                                         block.GetLocalName (type_argument_name, block, ref variable);
1045                                         if (variable != null)
1046                                                 variable.Block.Error_AlreadyDeclaredTypeParameter (type_argument_name, variable.Location);
1047                                 }
1048
1049                                 if (parent_tparams != null) {
1050                                         var tp = parent_tparams.Find (type_argument_name);
1051                                         if (tp != null) {
1052                                                 tparams[i].WarningParentNameConflict (tp);
1053                                         }
1054                                 }
1055                         }
1056
1057                         tparams.Create (null, 0, Parent);
1058                 }
1059
1060                 protected virtual void DefineTypeParameters ()
1061                 {
1062                         var tparams = CurrentTypeParameters;
1063
1064                         TypeParameterSpec[] base_tparams = null;
1065                         TypeParameterSpec[] base_decl_tparams = TypeParameterSpec.EmptyTypes;
1066                         TypeSpec[] base_targs = TypeSpec.EmptyTypes;
1067                         if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
1068                                 MethodSpec base_override = base_method ?? MethodData.implementing;
1069
1070                                 if (base_override != null) {
1071                                         base_tparams = base_override.GenericDefinition.TypeParameters;
1072
1073                                         if (base_override.DeclaringType.IsGeneric) {
1074                                                 base_decl_tparams = base_override.DeclaringType.MemberDefinition.TypeParameters;
1075
1076                                                 if (base_method != null) {
1077                                                         var base_type_parent = CurrentType;
1078                                                         while (base_type_parent.BaseType != base_override.DeclaringType) {
1079                                                                 base_type_parent = base_type_parent.BaseType;
1080                                                         }
1081
1082                                                         base_targs = base_type_parent.BaseType.TypeArguments;
1083                                                 } else {
1084                                                         foreach (var iface in Parent.CurrentType.Interfaces) {
1085                                                                 if (iface == base_override.DeclaringType) {
1086                                                                         base_targs = iface.TypeArguments;
1087                                                                         break;
1088                                                                 }
1089                                                         }
1090                                                 }
1091                                         }
1092
1093                                         if (base_override.IsGeneric) {
1094                                                 foreach (var base_tp in base_tparams) {
1095                                                         base_tp.BaseType.CheckObsoleteness (this, Location);
1096
1097                                                         if (base_tp.InterfacesDefined != null) {
1098                                                                 foreach (var iface in base_tp.InterfacesDefined) {
1099                                                                         iface.CheckObsoleteness (this, Location);
1100                                                                 }
1101                                                         }
1102                                                 }
1103
1104                                                 if (base_decl_tparams.Length != 0) {
1105                                                         base_decl_tparams = base_decl_tparams.Concat (base_tparams).ToArray ();
1106                                                         base_targs = base_targs.Concat (tparams.Types).ToArray ();
1107                                                 } else {
1108                                                         base_decl_tparams = base_tparams;
1109                                                         base_targs = tparams.Types;
1110                                                 }
1111                                         }
1112                                 }
1113                         }
1114
1115                         for (int i = 0; i < tparams.Count; ++i) {
1116                                 var tp = tparams [i];
1117
1118                                 if (base_tparams == null) {
1119                                         tp.ResolveConstraints (this);
1120                                         continue;
1121                                 }
1122
1123                                 //
1124                                 // Copy base constraints for override/explicit methods
1125                                 //
1126                                 var base_tparam = base_tparams [i];
1127                                 var local_tparam = tp.Type;
1128                                 local_tparam.SpecialConstraint = base_tparam.SpecialConstraint;
1129
1130                                 var inflator = new TypeParameterInflator (this, CurrentType, base_decl_tparams, base_targs);
1131                                 base_tparam.InflateConstraints (inflator, local_tparam);
1132
1133                                 //
1134                                 // Check all type argument constraints for possible collision or unification
1135                                 // introduced by inflating inherited constraints in this context
1136                                 //
1137                                 // Conflict example:
1138                                 //
1139                                 // class A<T> { virtual void Foo<U> () where U : class, T {} }
1140                                 // class B : A<int> { override void Foo<U> {} }
1141                                 //
1142                                 var local_tparam_targs = local_tparam.TypeArguments;
1143                                 if (local_tparam_targs != null) {
1144                                         for (int ii = 0; ii < local_tparam_targs.Length; ++ii) {
1145                                                 var ta = local_tparam_targs [ii];
1146                                                 if (!ta.IsClass && !ta.IsStruct)
1147                                                         continue;
1148
1149                                                 TypeSpec[] unique_tparams = null;
1150                                                 for (int iii = ii + 1; iii < local_tparam_targs.Length; ++iii) {
1151                                                         //
1152                                                         // Remove any identical or unified constraint types
1153                                                         //
1154                                                         var tparam_checked = local_tparam_targs [iii];
1155                                                         if (TypeSpecComparer.IsEqual (ta, tparam_checked) || TypeSpec.IsBaseClass (ta, tparam_checked, false)) {
1156                                                                 unique_tparams = new TypeSpec[local_tparam_targs.Length - 1];
1157                                                                 Array.Copy (local_tparam_targs, 0, unique_tparams, 0, iii);
1158                                                                 Array.Copy (local_tparam_targs, iii + 1, unique_tparams, iii, local_tparam_targs.Length - iii - 1);
1159                                                         } else if (!TypeSpec.IsBaseClass (tparam_checked, ta, false)) {
1160                                                                 Constraints.Error_ConflictingConstraints (this, local_tparam, ta, tparam_checked, Location);
1161                                                         }
1162                                                 }
1163
1164                                                 if (unique_tparams != null) {
1165                                                         local_tparam_targs = unique_tparams;
1166                                                         local_tparam.TypeArguments = local_tparam_targs;
1167                                                         continue;
1168                                                 }
1169
1170                                                 Constraints.CheckConflictingInheritedConstraint (local_tparam, ta, this, Location);
1171                                         }
1172                                 }
1173                         }
1174
1175                         if (base_tparams == null && MethodData != null && MethodData.implementing != null) {
1176                                 CheckImplementingMethodConstraints (Parent, spec, MethodData.implementing);
1177                         }
1178                 }
1179
1180                 public static bool CheckImplementingMethodConstraints (TypeContainer container, MethodSpec method, MethodSpec baseMethod)
1181                 {
1182                         var tparams = method.Constraints;
1183                         var base_tparams = baseMethod.Constraints;
1184                         for (int i = 0; i < tparams.Length; ++i) {
1185                                 if (!tparams[i].HasSameConstraintsImplementation (base_tparams[i])) {
1186                                         container.Compiler.Report.SymbolRelatedToPreviousError (method);
1187                                         container.Compiler.Report.SymbolRelatedToPreviousError (baseMethod);
1188
1189                                         // Using container location because the interface can be implemented
1190                                         // by base class
1191                                         var tp = (tparams [i].MemberDefinition as MemberCore) ?? container;
1192                                         container.Compiler.Report.Error (425, tp.Location,
1193                                                 "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",
1194                                                 tparams[i].GetSignatureForError (), method.GetSignatureForError (),
1195                                                 base_tparams[i].GetSignatureForError (), baseMethod.GetSignatureForError ());
1196  
1197                                         return false;
1198                                 }
1199                         }
1200
1201                         return true;
1202                 }
1203
1204                 //
1205                 // Creates the type
1206                 //
1207                 public override bool Define ()
1208                 {
1209                         if (!base.Define ())
1210                                 return false;
1211
1212                         if (member_type.Kind == MemberKind.Void && parameters.IsEmpty && MemberName.Arity == 0 && MemberName.Name == Destructor.MetadataName) {
1213                                 Report.Warning (465, 1, Location,
1214                                         "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
1215                         }
1216
1217                         if (Compiler.Settings.StdLib && ReturnType.IsSpecialRuntimeType) {
1218                                 Error1599 (Location, ReturnType, Report);
1219                                 return false;
1220                         }
1221
1222                         if (CurrentTypeParameters == null) {
1223                                 if (base_method != null && !IsExplicitImpl) {
1224                                         if (parameters.Count == 1 && ParameterTypes[0].BuiltinType == BuiltinTypeSpec.Type.Object && MemberName.Name == "Equals")
1225                                                 Parent.PartialContainer.Mark_HasEquals ();
1226                                         else if (parameters.IsEmpty && MemberName.Name == "GetHashCode")
1227                                                 Parent.PartialContainer.Mark_HasGetHashCode ();
1228                                 }
1229                                         
1230                         } else {
1231                                 DefineTypeParameters ();
1232                         }
1233
1234                         if (block != null) {
1235                                 if (block.IsIterator) {
1236                                         //
1237                                         // Current method is turned into automatically generated
1238                                         // wrapper which creates an instance of iterator
1239                                         //
1240                                         Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
1241                                         ModFlags |= Modifiers.DEBUGGER_HIDDEN;
1242                                 }
1243
1244                                 if ((ModFlags & Modifiers.ASYNC) != 0) {
1245                                         if (ReturnType.Kind != MemberKind.Void &&
1246                                                 ReturnType != Module.PredefinedTypes.Task.TypeSpec &&
1247                                                 !ReturnType.IsGenericTask) {
1248                                                 Report.Error (1983, Location, "The return type of an async method must be void, Task, or Task<T>");
1249                                         }
1250
1251                                         block = (ToplevelBlock) block.ConvertToAsyncTask (this, Parent.PartialContainer, parameters, ReturnType, null, Location);
1252                                         ModFlags |= Modifiers.DEBUGGER_STEP_THROUGH;
1253                                 }
1254
1255                                 if (Compiler.Settings.WriteMetadataOnly)
1256                                         block = null;
1257                         }
1258
1259                         if ((ModFlags & Modifiers.STATIC) == 0)
1260                                 return true;
1261
1262                         if (parameters.HasExtensionMethodType) {
1263                                 if (Parent.PartialContainer.IsStatic && !Parent.IsGenericOrParentIsGeneric) {
1264                                         if (!Parent.IsTopLevel)
1265                                                 Report.Error (1109, Location, "`{0}': Extension methods cannot be defined in a nested class",
1266                                                         GetSignatureForError ());
1267
1268                                         PredefinedAttribute pa = Module.PredefinedAttributes.Extension;
1269                                         if (!pa.IsDefined) {
1270                                                 Report.Error (1110, Location,
1271                                                         "`{0}': Extension methods require `System.Runtime.CompilerServices.ExtensionAttribute' type to be available. Are you missing an assembly reference?",
1272                                                         GetSignatureForError ());
1273                                         }
1274
1275                                         ModFlags |= Modifiers.METHOD_EXTENSION;
1276                                         Parent.PartialContainer.ModFlags |= Modifiers.METHOD_EXTENSION;
1277                                         Spec.DeclaringType.SetExtensionMethodContainer ();
1278                                         Parent.Module.HasExtensionMethod = true;
1279                                 } else {
1280                                         Report.Error (1106, Location, "`{0}': Extension methods must be defined in a non-generic static class",
1281                                                 GetSignatureForError ());
1282                                 }
1283                         }
1284
1285                         //
1286                         // This is used to track the Entry Point,
1287                         //
1288                         var settings = Compiler.Settings;
1289                         if (settings.NeedsEntryPoint && MemberName.Name == "Main" && !IsPartialDefinition && (settings.MainClass == null || settings.MainClass == Parent.TypeBuilder.FullName)) {
1290                                 if (IsEntryPoint ()) {
1291                                         if (Parent.DeclaringAssembly.EntryPoint == null) {
1292                                                 if (Parent.IsGenericOrParentIsGeneric || MemberName.IsGeneric) {
1293                                                         Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type",
1294                                                                 GetSignatureForError ());
1295                                                 } else if ((ModFlags & Modifiers.ASYNC) != 0) {
1296                                                         Report.Error (4009, Location, "`{0}': an entry point cannot be async method",
1297                                                                 GetSignatureForError ());
1298                                                 } else {
1299                                                         SetIsUsed ();
1300                                                         Parent.DeclaringAssembly.EntryPoint = this;
1301                                                 }
1302                                         } else {
1303                                                 Error_DuplicateEntryPoint (Parent.DeclaringAssembly.EntryPoint);
1304                                                 Error_DuplicateEntryPoint (this);
1305                                         }
1306                                 } else {
1307                                         Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point",
1308                                                 GetSignatureForError ());
1309                                 }
1310                         }
1311
1312                         return true;
1313                 }
1314
1315                 public override void PrepareEmit ()
1316                 {
1317                         if (IsPartialDefinition) {
1318                                 //
1319                                 // Use partial method implementation builder for partial method declaration attributes
1320                                 //
1321                                 if (partialMethodImplementation != null) {
1322                                         MethodData = partialMethodImplementation.MethodData;
1323                                 }
1324
1325                                 return;
1326                         }
1327
1328                         base.PrepareEmit ();
1329                 }
1330
1331                 //
1332                 // Emits the code
1333                 // 
1334                 public override void Emit ()
1335                 {
1336                         try {
1337                                 if (IsPartialDefinition) {
1338                                         if (partialMethodImplementation != null && CurrentTypeParameters != null) {
1339                                                 CurrentTypeParameters.CheckPartialConstraints (partialMethodImplementation);
1340
1341                                                 var otp = partialMethodImplementation.CurrentTypeParameters;
1342                                                 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1343                                                         var tp = CurrentTypeParameters [i];
1344                                                         tp.Define (otp[i]);
1345                                                 }
1346                                         }
1347
1348                                         return;
1349                                 }
1350                                 
1351                                 if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.PartialDefinitionExists) == 0) {
1352                                         Report.Error (759, Location, "A partial method `{0}' implementation is missing a partial method declaration",
1353                                                 GetSignatureForError ());
1354                                 }
1355
1356                                 if (CurrentTypeParameters != null) {
1357                                         for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1358                                                 var tp = CurrentTypeParameters [i];
1359
1360                                                 tp.CheckGenericConstraints (false);
1361                                                 tp.Emit ();
1362                                         }
1363                                 }
1364
1365                                 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
1366                                         Module.PredefinedAttributes.Extension.EmitAttribute (MethodBuilder);
1367
1368                                 base.Emit ();
1369                         } catch (Exception e) {
1370                                 throw new InternalErrorException (this, e);
1371                         }
1372                 }
1373
1374                 public override bool EnableOverloadChecks (MemberCore overload)
1375                 {
1376                         if (overload is Indexer)
1377                                 return false;
1378
1379                         return base.EnableOverloadChecks (overload);
1380                 }
1381
1382                 public static void Error1599 (Location loc, TypeSpec t, Report Report)
1383                 {
1384                         Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", t.GetSignatureForError ());
1385                 }
1386
1387                 protected override bool ResolveMemberType ()
1388                 {
1389                         if (CurrentTypeParameters != null) {
1390                                 CreateTypeParameters ();
1391                         }
1392
1393                         return base.ResolveMemberType ();
1394                 }
1395
1396                 public void SetPartialDefinition (Method methodDefinition)
1397                 {
1398                         caching_flags |= Flags.PartialDefinitionExists;
1399                         methodDefinition.partialMethodImplementation = this;
1400
1401                         // Ensure we are always using method declaration parameters
1402                         for (int i = 0; i < methodDefinition.parameters.Count; ++i ) {
1403                                 var md_p = methodDefinition.parameters [i];
1404                                 var p = parameters [i];
1405                                 p.Name = md_p.Name;
1406                                 p.DefaultValue = md_p.DefaultValue;
1407                                 if (md_p.OptAttributes != null) {
1408                                         Attributes.AttachFromPartial (p, md_p);
1409                                 }
1410                         }
1411
1412                         if (methodDefinition.attributes != null) {
1413                                 if (attributes == null) {
1414                                         attributes = methodDefinition.attributes;
1415                                 } else {
1416                                         attributes.Attrs.AddRange (methodDefinition.attributes.Attrs);
1417                                 }
1418                         }
1419
1420                         if (CurrentTypeParameters != null) {
1421                                 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1422                                         var tp_other = methodDefinition.CurrentTypeParameters [i];
1423                                         if (tp_other.OptAttributes == null)
1424                                                 continue;
1425
1426                                         var tp = CurrentTypeParameters [i];
1427                                         if (tp.OptAttributes == null) {
1428                                                 tp.OptAttributes = tp_other.OptAttributes;
1429                                         } else {
1430                                                 tp.OptAttributes.Attrs.AddRange (tp.OptAttributes.Attrs);
1431                                         }
1432                                 }
1433                         }
1434                 }
1435         }
1436
1437         public abstract class ConstructorInitializer : ExpressionStatement
1438         {
1439                 Arguments argument_list;
1440                 MethodSpec base_ctor;
1441
1442                 protected ConstructorInitializer (Arguments argument_list, Location loc)
1443                 {
1444                         this.argument_list = argument_list;
1445                         this.loc = loc;
1446                 }
1447
1448                 public Arguments Arguments {
1449                         get {
1450                                 return argument_list;
1451                         }
1452                 }
1453
1454                 public override bool ContainsEmitWithAwait ()
1455                 {
1456                         throw new NotSupportedException ();
1457                 }
1458
1459                 public override Expression CreateExpressionTree (ResolveContext ec)
1460                 {
1461                         throw new NotSupportedException ("ET");
1462                 }
1463
1464                 protected override Expression DoResolve (ResolveContext ec)
1465                 {
1466                         eclass = ExprClass.Value;
1467
1468                         // FIXME: Hack
1469                         var caller_builder = (Constructor) ec.MemberContext;
1470
1471                         //
1472                         // Spec mandates that constructor initializer will not have `this' access
1473                         //
1474                         using (ec.Set (ResolveContext.Options.BaseInitializer)) {
1475                                 if (argument_list != null) {
1476                                         bool dynamic;
1477                                         argument_list.Resolve (ec, out dynamic);
1478
1479                                         if (dynamic) {
1480                                                 ec.Report.Error (1975, loc,
1481                                                         "The constructor call cannot be dynamically dispatched within constructor initializer");
1482
1483                                                 return null;
1484                                         }
1485                                 }
1486
1487                                 type = ec.CurrentType;
1488                                 if (this is ConstructorBaseInitializer) {
1489                                         if (ec.CurrentType.BaseType == null)
1490                                                 return this;
1491
1492                                         type = ec.CurrentType.BaseType;
1493                                         if (ec.CurrentType.IsStruct) {
1494                                                 ec.Report.Error (522, loc,
1495                                                         "`{0}': Struct constructors cannot call base constructors", caller_builder.GetSignatureForError ());
1496                                                 return this;
1497                                         }
1498                                 }
1499
1500                                 base_ctor = ConstructorLookup (ec, type, ref argument_list, loc);
1501                         }
1502         
1503                         if (base_ctor != null && base_ctor.MemberDefinition == caller_builder.Spec.MemberDefinition) {
1504                                 ec.Report.Error (516, loc, "Constructor `{0}' cannot call itself",
1505                                         caller_builder.GetSignatureForError ());
1506                         }
1507
1508                         return this;
1509                 }
1510
1511                 public override void Emit (EmitContext ec)
1512                 {
1513                         //
1514                         // It can be null for struct initializers or System.Object
1515                         //
1516                         if (base_ctor == null) {
1517                                 if (type == ec.BuiltinTypes.Object)
1518                                         return;
1519
1520                                 ec.Emit (OpCodes.Ldarg_0);
1521                                 ec.Emit (OpCodes.Initobj, type);
1522                                 return;
1523                         }
1524                         
1525                         var call = new CallEmitter ();
1526                         call.InstanceExpression = new CompilerGeneratedThis (type, loc); 
1527                         call.EmitPredefined (ec, base_ctor, argument_list, false);
1528                 }
1529
1530                 public override void EmitStatement (EmitContext ec)
1531                 {
1532                         Emit (ec);
1533                 }
1534
1535                 public override void FlowAnalysis (FlowAnalysisContext fc)
1536                 {
1537                         if (argument_list != null)
1538                                 argument_list.FlowAnalysis (fc);
1539                 }
1540         }
1541
1542         public class ConstructorBaseInitializer : ConstructorInitializer {
1543                 public ConstructorBaseInitializer (Arguments argument_list, Location l) :
1544                         base (argument_list, l)
1545                 {
1546                 }
1547         }
1548
1549         class GeneratedBaseInitializer: ConstructorBaseInitializer {
1550                 public GeneratedBaseInitializer (Location loc, Arguments arguments)
1551                         : base (arguments, loc)
1552                 {
1553                 }
1554         }
1555
1556         public class ConstructorThisInitializer : ConstructorInitializer {
1557                 public ConstructorThisInitializer (Arguments argument_list, Location l) :
1558                         base (argument_list, l)
1559                 {
1560                 }
1561         }
1562         
1563         public class Constructor : MethodCore, IMethodData, IMethodDefinition
1564         {
1565                 public ConstructorBuilder ConstructorBuilder;
1566                 public ConstructorInitializer Initializer;
1567                 SecurityType declarative_security;
1568                 bool has_compliant_args;
1569                 SourceMethodBuilder debug_builder;
1570
1571                 // <summary>
1572                 //   Modifiers allowed for a constructor.
1573                 // </summary>
1574                 public const Modifiers AllowedModifiers =
1575                         Modifiers.PUBLIC |
1576                         Modifiers.PROTECTED |
1577                         Modifiers.INTERNAL |
1578                         Modifiers.STATIC |
1579                         Modifiers.UNSAFE |
1580                         Modifiers.EXTERN |              
1581                         Modifiers.PRIVATE;
1582
1583                 static readonly string[] attribute_targets = new string [] { "method" };
1584
1585                 public static readonly string ConstructorName = ".ctor";
1586                 public static readonly string TypeConstructorName = ".cctor";
1587
1588                 public Constructor (TypeDefinition parent, string name, Modifiers mod, Attributes attrs, ParametersCompiled args, Location loc)
1589                         : base (parent, null, mod, AllowedModifiers, new MemberName (name, loc), attrs, args)
1590                 {
1591                 }
1592
1593                 public bool HasCompliantArgs {
1594                         get {
1595                                 return has_compliant_args;
1596                         }
1597                 }
1598
1599                 public override AttributeTargets AttributeTargets {
1600                         get {
1601                                 return AttributeTargets.Constructor;
1602                         }
1603                 }
1604
1605                 bool IMethodData.IsAccessor {
1606                     get {
1607                         return false;
1608                     }
1609                 }
1610
1611                 public bool IsPrimaryConstructor { get; set; }
1612                 
1613                 MethodBase IMethodDefinition.Metadata {
1614                         get {
1615                                 return ConstructorBuilder;
1616                         }
1617                 }
1618
1619                 //
1620                 // Returns true if this is a default constructor
1621                 //
1622                 public bool IsDefault ()
1623                 {
1624                         if ((ModFlags & Modifiers.STATIC) != 0)
1625                                 return parameters.IsEmpty;
1626
1627                         return parameters.IsEmpty &&
1628                                         (Initializer is ConstructorBaseInitializer) &&
1629                                         (Initializer.Arguments == null);
1630                 }
1631
1632                 public override void Accept (StructuralVisitor visitor)
1633                 {
1634                         visitor.Visit (this);
1635                 }
1636
1637                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1638                 {
1639                         if (a.IsValidSecurityAttribute ()) {
1640                                 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
1641                                 return;
1642                         }
1643
1644                         if (a.Type == pa.MethodImpl) {
1645                                 is_external_implementation = a.IsInternalCall ();
1646                         }
1647
1648                         ConstructorBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
1649                 }
1650
1651                 protected override bool CheckBase ()
1652                 {
1653                         if ((ModFlags & Modifiers.STATIC) != 0) {
1654                                 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
1655                                         Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1656
1657                                 // the rest can be ignored
1658                                 return true;
1659                         }
1660
1661                         // Check whether arguments were correct.
1662                         if (!DefineParameters (parameters))
1663                                 return false;
1664
1665                         if ((caching_flags & Flags.MethodOverloadsExist) != 0)
1666                                 Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1667
1668                         CheckProtectedModifier ();
1669                         
1670                         return true;
1671                 }
1672                 
1673                 //
1674                 // Creates the ConstructorBuilder
1675                 //
1676                 public override bool Define ()
1677                 {
1678                         if (ConstructorBuilder != null)
1679                                 return true;
1680
1681                         if (!CheckAbstractAndExtern (block != null))
1682                                 return false;
1683                         
1684                         // Check if arguments were correct.
1685                         if (!CheckBase ())
1686                                 return false;
1687
1688                         if (Parent.PrimaryConstructorParameters != null && !IsPrimaryConstructor && !IsStatic) {
1689                                 if (Parent.Kind == MemberKind.Struct && Initializer is ConstructorThisInitializer && Initializer.Arguments == null) {
1690                                         Report.Error (8043, Location, "`{0}': Structs with primary constructor cannot specify default constructor initializer",
1691                                                 GetSignatureForError ());
1692                                 } else if (Initializer == null || Initializer is ConstructorBaseInitializer) {
1693                                         Report.Error (8037, Location, "`{0}': Instance constructor of type with primary constructor must specify `this' constructor initializer",
1694                                                 GetSignatureForError ());
1695                                 }
1696                         }
1697
1698                         if ((ModFlags & Modifiers.EXTERN) != 0 && Initializer != null) {
1699                                 Report.Error (8091, Location, "`{0}': Contructors cannot be extern and have a constructor initializer",
1700                                         GetSignatureForError ());
1701                         }
1702
1703                         var ca = ModifiersExtensions.MethodAttr (ModFlags) | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName;
1704
1705                         ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
1706                                 ca, CallingConventions,
1707                                 parameters.GetMetaInfo ());
1708
1709                         spec = new MethodSpec (MemberKind.Constructor, Parent.Definition, this, Compiler.BuiltinTypes.Void, parameters, ModFlags);
1710                         
1711                         Parent.MemberCache.AddMember (spec);
1712                         
1713                         if (block != null) {
1714                                 // It's here only to report an error
1715                                 if (block.IsIterator) {
1716                                         member_type = Compiler.BuiltinTypes.Void;
1717                                         Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
1718                                 }
1719
1720                                 if (Compiler.Settings.WriteMetadataOnly)
1721                                         block = null;
1722                         }
1723
1724                         return true;
1725                 }
1726
1727                 //
1728                 // Emits the code
1729                 //
1730                 public override void Emit ()
1731                 {
1732                         if (Parent.PartialContainer.IsComImport) {
1733                                 if (!IsDefault ()) {
1734                                         Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
1735                                                 Parent.GetSignatureForError ());
1736                                 }
1737
1738                                 // Set as internal implementation and reset block data
1739                                 // to ensure no IL is generated
1740                                 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
1741                                 block = null;
1742                         }
1743
1744                         if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
1745                                 Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (ConstructorBuilder);
1746
1747                         if (OptAttributes != null)
1748                                 OptAttributes.Emit ();
1749
1750                         base.Emit ();
1751                         parameters.ApplyAttributes (this, ConstructorBuilder);
1752
1753
1754                         BlockContext bc = new BlockContext (this, block, Compiler.BuiltinTypes.Void);
1755                         bc.Set (ResolveContext.Options.ConstructorScope);
1756
1757                         if (block != null) {
1758                                 if (!IsStatic && Initializer == null && Parent.PartialContainer.Kind == MemberKind.Struct) {
1759                                         //
1760                                         // If this is a non-static `struct' constructor and doesn't have any
1761                                         // initializer, it must initialize all of the struct's fields.
1762                                         //
1763                                         block.AddThisVariable (bc);
1764                                 }
1765
1766                                 //
1767                                 // If we use a "this (...)" constructor initializer, then
1768                                 // do not emit field initializers, they are initialized in the other constructor
1769                                 //
1770                                 if (!(Initializer is ConstructorThisInitializer))
1771                                         Parent.PartialContainer.ResolveFieldInitializers (bc);
1772
1773                                 if (!IsStatic) {
1774                                         if (Initializer == null && Parent.PartialContainer.Kind == MemberKind.Class) {
1775                                                 Initializer = new GeneratedBaseInitializer (Location, null);
1776                                         }
1777
1778                                         if (Initializer != null) {
1779                                                 //
1780                                                 // mdb format does not support reqions. Try to workaround this by emitting the
1781                                                 // sequence point at initializer. Any breakpoint at constructor header should
1782                                                 // be adjusted to this sequence point as it's the next one which follows.
1783                                                 //
1784                                                 block.AddScopeStatement (new StatementExpression (Initializer));
1785                                         }
1786                                 }
1787
1788                                 if (block.Resolve (bc, this)) {
1789                                         debug_builder = Parent.CreateMethodSymbolEntry ();
1790                                         EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType, debug_builder);
1791                                         ec.With (EmitContext.Options.ConstructorScope, true);
1792
1793                                         block.Emit (ec);
1794                                 }
1795                         }
1796
1797                         if (declarative_security != null) {
1798                                 foreach (var de in declarative_security) {
1799 #if STATIC
1800                                         ConstructorBuilder.__AddDeclarativeSecurity (de);
1801 #else
1802                                         ConstructorBuilder.AddDeclarativeSecurity (de.Key, de.Value);
1803 #endif
1804                                 }
1805                         }
1806
1807                         block = null;
1808                 }
1809
1810                 protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
1811                 {
1812                         // Is never override
1813                         bestCandidate = null;
1814                         return null;
1815                 }
1816
1817                 public override string GetCallerMemberName ()
1818                 {
1819                         return IsStatic ? TypeConstructorName : ConstructorName;
1820                 }
1821
1822                 public override string GetSignatureForDocumentation ()
1823                 {
1824                         return Parent.GetSignatureForDocumentation () + ".#ctor" + parameters.GetSignatureForDocumentation ();
1825                 }
1826
1827                 public override string GetSignatureForError()
1828                 {
1829                         return base.GetSignatureForError () + parameters.GetSignatureForError ();
1830                 }
1831
1832                 public override string[] ValidAttributeTargets {
1833                         get {
1834                                 return attribute_targets;
1835                         }
1836                 }
1837
1838                 protected override bool VerifyClsCompliance ()
1839                 {
1840                         if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
1841                                 return false;
1842                         }
1843
1844                         if (!parameters.IsEmpty && Parent.Definition.IsAttribute) {
1845                                 foreach (TypeSpec param in parameters.Types) {
1846                                         if (param.IsArray) {
1847                                                 return true;
1848                                         }
1849                                 }
1850                         }
1851
1852                         has_compliant_args = true;
1853                         return true;
1854                 }
1855
1856                 public override void WriteDebugSymbol (MonoSymbolFile file)
1857                 {
1858                         if (debug_builder == null)
1859                                 return;
1860
1861                         var token = ConstructorBuilder.GetToken ();
1862                         int t = token.Token;
1863 #if STATIC
1864                         if (ModuleBuilder.IsPseudoToken (t))
1865                                 t = Module.Builder.ResolvePseudoToken (t);
1866 #endif
1867
1868                         debug_builder.DefineMethod (file, t);
1869                 }
1870
1871                 #region IMethodData Members
1872
1873                 public MemberName MethodName {
1874                         get {
1875                                 return MemberName;
1876                         }
1877                 }
1878
1879                 public TypeSpec ReturnType {
1880                         get {
1881                                 return MemberType;
1882                         }
1883                 }
1884
1885                 EmitContext IMethodData.CreateEmitContext (ILGenerator ig, SourceMethodBuilder sourceMethod)
1886                 {
1887                         throw new NotImplementedException ();
1888                 }
1889
1890                 #endregion
1891         }
1892
1893         /// <summary>
1894         /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
1895         /// </summary>
1896         public interface IMethodData : IMemberContext
1897         {
1898                 CallingConventions CallingConventions { get; }
1899                 Location Location { get; }
1900                 MemberName MethodName { get; }
1901                 TypeSpec ReturnType { get; }
1902                 ParametersCompiled ParameterInfo { get; }
1903                 MethodSpec Spec { get; }
1904                 bool IsAccessor { get; }
1905
1906                 Attributes OptAttributes { get; }
1907                 ToplevelBlock Block { get; set; }
1908
1909                 EmitContext CreateEmitContext (ILGenerator ig, SourceMethodBuilder sourceMethod);
1910         }
1911
1912         //
1913         // Encapsulates most of the Method's state
1914         //
1915         public class MethodData
1916         {
1917                 public readonly IMethodData method;
1918
1919                 //
1920                 // Are we implementing an interface ?
1921                 //
1922                 public MethodSpec implementing;
1923
1924                 //
1925                 // Protected data.
1926                 //
1927                 protected InterfaceMemberBase member;
1928                 protected Modifiers modifiers;
1929                 protected MethodAttributes flags;
1930                 protected TypeSpec declaring_type;
1931                 protected MethodSpec parent_method;
1932                 SourceMethodBuilder debug_builder;
1933                 string full_name;
1934
1935                 MethodBuilder builder;
1936                 public MethodBuilder MethodBuilder {
1937                         get {
1938                                 return builder;
1939                         }
1940                 }
1941
1942                 public TypeSpec DeclaringType {
1943                         get {
1944                                 return declaring_type;
1945                         }
1946                 }
1947
1948                 public string MetadataName {
1949                         get {
1950                                 return full_name;
1951                         }
1952                 }
1953
1954                 public MethodData (InterfaceMemberBase member,
1955                                    Modifiers modifiers, MethodAttributes flags, IMethodData method)
1956                 {
1957                         this.member = member;
1958                         this.modifiers = modifiers;
1959                         this.flags = flags;
1960
1961                         this.method = method;
1962                 }
1963
1964                 public MethodData (InterfaceMemberBase member,
1965                                    Modifiers modifiers, MethodAttributes flags, 
1966                                    IMethodData method,
1967                                    MethodSpec parent_method)
1968                         : this (member, modifiers, flags, method)
1969                 {
1970                         this.parent_method = parent_method;
1971                 }
1972
1973                 public bool Define (TypeDefinition container, string method_full_name)
1974                 {
1975                         PendingImplementation pending = container.PendingImplementations;
1976                         MethodSpec ambig_iface_method;
1977                         bool optional = false;
1978
1979                         if (pending != null) {
1980                                 implementing = pending.IsInterfaceMethod (method.MethodName, member.InterfaceType, this, out ambig_iface_method, ref optional);
1981
1982                                 if (member.InterfaceType != null) {
1983                                         if (implementing == null) {
1984                                                 if (member is PropertyBase) {
1985                                                         container.Compiler.Report.Error (550, method.Location,
1986                                                                 "`{0}' is an accessor not found in interface member `{1}{2}'",
1987                                                                           method.GetSignatureForError (), member.InterfaceType.GetSignatureForError (),
1988                                                                           member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
1989
1990                                                 } else {
1991                                                         container.Compiler.Report.Error (539, method.Location,
1992                                                                           "`{0}.{1}' in explicit interface declaration is not a member of interface",
1993                                                                           member.InterfaceType.GetSignatureForError (), member.ShortName);
1994                                                 }
1995                                                 return false;
1996                                         }
1997                                         if (implementing.IsAccessor && !method.IsAccessor) {
1998                                                 container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
1999                                                 container.Compiler.Report.Error (683, method.Location,
2000                                                         "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
2001                                                         member.GetSignatureForError (), implementing.GetSignatureForError ());
2002                                                 return false;
2003                                         }
2004                                 } else {
2005                                         if (implementing != null && !optional) {
2006                                                 if (!method.IsAccessor) {
2007                                                         if (implementing.IsAccessor) {
2008                                                                 container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
2009                                                                 container.Compiler.Report.Error (470, method.Location,
2010                                                                         "Method `{0}' cannot implement interface accessor `{1}'",
2011                                                                         method.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
2012                                                         }
2013                                                 } else if (implementing.DeclaringType.IsInterface) {
2014                                                         if (!implementing.IsAccessor) {
2015                                                                 container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
2016                                                                 container.Compiler.Report.Error (686, method.Location,
2017                                                                         "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
2018                                                                         method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
2019                                                         } else {
2020                                                                 PropertyBase.PropertyMethod pm = method as PropertyBase.PropertyMethod;
2021                                                                 if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
2022                                                                         container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
2023                                                                         container.Compiler.Report.Error (277, method.Location,
2024                                                                                 "Accessor `{0}' must be declared public to implement interface member `{1}'",
2025                                                                                 method.GetSignatureForError (), implementing.GetSignatureForError ());
2026                                                                 }
2027                                                         }
2028                                                 }
2029                                         }
2030                                 }
2031                         } else {
2032                                 ambig_iface_method = null;
2033                         }
2034
2035                         //
2036                         // For implicit implementations, make sure we are public, for
2037                         // explicit implementations, make sure we are private.
2038                         //
2039                         if (implementing != null){
2040                                 if (member.IsExplicitImpl) {
2041                                         if (method.ParameterInfo.HasParams && !implementing.Parameters.HasParams) {
2042                                                 container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
2043                                                 container.Compiler.Report.Error (466, method.Location,
2044                                                         "`{0}': the explicit interface implementation cannot introduce the params modifier",
2045                                                         method.GetSignatureForError ());
2046                                         }
2047
2048                                         if (ambig_iface_method != null) {
2049                                                 container.Compiler.Report.SymbolRelatedToPreviousError (ambig_iface_method);
2050                                                 container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
2051                                                 container.Compiler.Report.Warning (473, 2, method.Location,
2052                                                         "Explicit interface implementation `{0}' matches more than one interface member. Consider using a non-explicit implementation instead",
2053                                                         method.GetSignatureForError ());
2054                                         }
2055                                 } else {
2056                                         //
2057                                         // Setting implementin to null inside this block will trigger a more
2058                                         // verbose error reporting for missing interface implementations
2059                                         //
2060                                         if (implementing.DeclaringType.IsInterface) {
2061                                                 //
2062                                                 // If this is an interface method implementation,
2063                                                 // check for public accessibility
2064                                                 //
2065                                                 if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public) {
2066                                                         implementing = null;
2067                                                 } else if (optional && (container.Interfaces == null || !container.Definition.Interfaces.Contains (implementing.DeclaringType))) {
2068                                                         //
2069                                                         // We are not implementing interface when base class already implemented it
2070                                                         //
2071                                                         implementing = null;
2072                                                 }
2073                                         } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private) {
2074                                                 // We may never be private.
2075                                                 implementing = null;
2076
2077                                         } else if ((modifiers & Modifiers.OVERRIDE) == 0) {
2078                                                 //
2079                                                 // We may be protected if we're overriding something.
2080                                                 //
2081                                                 implementing = null;
2082                                         }
2083                                 }
2084                                         
2085                                 //
2086                                 // Static is not allowed
2087                                 //
2088                                 if ((modifiers & Modifiers.STATIC) != 0){
2089                                         implementing = null;
2090                                 }
2091                         }
2092                         
2093                         //
2094                         // If implementing is still valid, set flags
2095                         //
2096                         if (implementing != null){
2097                                 //
2098                                 // When implementing interface methods, set NewSlot
2099                                 // unless, we are overwriting a method.
2100                                 //
2101                                 if ((modifiers & Modifiers.OVERRIDE) == 0 && implementing.DeclaringType.IsInterface) {
2102                                         flags |= MethodAttributes.NewSlot;
2103                                 }
2104
2105                                 flags |= MethodAttributes.Virtual | MethodAttributes.HideBySig;
2106
2107                                 // Set Final unless we're virtual, abstract or already overriding a method.
2108                                 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
2109                                         flags |= MethodAttributes.Final;
2110
2111                                 //
2112                                 // clear the pending implementation flag (requires explicit methods to be defined first)
2113                                 //
2114                                 pending.ImplementMethod (method.MethodName,
2115                                         member.InterfaceType, this, member.IsExplicitImpl, out ambig_iface_method, ref optional);
2116
2117                                 //
2118                                 // Update indexer accessor name to match implementing abstract accessor
2119                                 //
2120                                 if (!implementing.DeclaringType.IsInterface && !member.IsExplicitImpl && implementing.IsAccessor)
2121                                         method_full_name = implementing.MemberDefinition.Name;
2122                         }
2123
2124                         full_name = method_full_name;
2125                         declaring_type = container.Definition;
2126
2127                         return true;
2128                 }
2129
2130                 void DefineOverride (TypeDefinition container)
2131                 {
2132                         if (implementing == null)
2133                                 return;
2134
2135                         if (!member.IsExplicitImpl)
2136                                 return;
2137
2138                         container.TypeBuilder.DefineMethodOverride (builder, (MethodInfo) implementing.GetMetaInfo ());
2139                 }
2140
2141                 //
2142                 // Creates partial MethodBuilder for the method when has generic parameters used
2143                 // as arguments or return type
2144                 //
2145                 public MethodBuilder DefineMethodBuilder (TypeDefinition container)
2146                 {
2147                         if (builder != null)
2148                                 throw new InternalErrorException ();
2149
2150                         builder = container.TypeBuilder.DefineMethod (full_name, flags, method.CallingConventions);
2151                         return builder;
2152                 }
2153
2154                 //
2155                 // Creates full MethodBuilder for the method 
2156                 //
2157                 public MethodBuilder DefineMethodBuilder (TypeDefinition container, ParametersCompiled param)
2158                 {
2159                         DefineMethodBuilder (container);
2160                         builder.SetReturnType (method.ReturnType.GetMetaInfo ());
2161                         builder.SetParameters (param.GetMetaInfo ());
2162                         return builder;
2163                 }
2164
2165                 //
2166                 // Emits the code
2167                 // 
2168                 public void Emit (TypeDefinition parent)
2169                 {
2170                         DefineOverride (parent);
2171
2172                         method.ParameterInfo.ApplyAttributes (method, MethodBuilder);
2173
2174                         ToplevelBlock block = method.Block;
2175                         if (block != null) {
2176                                 BlockContext bc = new BlockContext (method, block, method.ReturnType);
2177                                 if (block.Resolve (bc, method)) {
2178                                         debug_builder = member.Parent.CreateMethodSymbolEntry ();
2179                                         EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator (), debug_builder);
2180
2181                                         block.Emit (ec);
2182                                 }
2183                         }
2184                 }
2185
2186                 public void WriteDebugSymbol (MonoSymbolFile file)
2187                 {
2188                         if (debug_builder == null)
2189                                 return;
2190
2191                         var token = builder.GetToken ();
2192                         int t = token.Token;
2193 #if STATIC
2194                         if (ModuleBuilder.IsPseudoToken (t))
2195                                 t = member.Module.Builder.ResolvePseudoToken (t);
2196 #endif
2197
2198                         debug_builder.DefineMethod (file, t);
2199                 }
2200         }
2201
2202         public class Destructor : MethodOrOperator
2203         {
2204                 const Modifiers AllowedModifiers =
2205                         Modifiers.UNSAFE |
2206                         Modifiers.EXTERN;
2207
2208                 static readonly string[] attribute_targets = new string [] { "method" };
2209
2210                 public static readonly string MetadataName = "Finalize";
2211
2212                 public Destructor (TypeDefinition parent, Modifiers mod, ParametersCompiled parameters, Attributes attrs, Location l)
2213                         : base (parent, null, mod, AllowedModifiers, new MemberName (MetadataName, l), attrs, parameters)
2214                 {
2215                         ModFlags &= ~Modifiers.PRIVATE;
2216                         ModFlags |= Modifiers.PROTECTED | Modifiers.OVERRIDE;
2217                 }
2218
2219                 public override void Accept (StructuralVisitor visitor)
2220                 {
2221                         visitor.Visit (this);
2222                 }
2223
2224                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2225                 {
2226                         if (a.Type == pa.Conditional) {
2227                                 Error_ConditionalAttributeIsNotValid ();
2228                                 return;
2229                         }
2230
2231                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2232                 }
2233
2234                 protected override bool CheckBase ()
2235                 {
2236                         if ((caching_flags & Flags.MethodOverloadsExist) != 0)
2237                                 CheckForDuplications ();
2238
2239                         // Don't check base, destructors have special syntax
2240                         return true;
2241                 }
2242
2243                 public override bool Define ()
2244                 {
2245                         base.Define ();
2246
2247                         if (Compiler.Settings.WriteMetadataOnly)
2248                                 block = null;
2249
2250                         return true;
2251                 }
2252
2253                 public override void Emit()
2254                 {
2255                         var base_type = Parent.PartialContainer.BaseType;
2256                         if (base_type != null && Block != null) {
2257                                 var base_dtor = MemberCache.FindMember (base_type,
2258                                         new MemberFilter (MetadataName, 0, MemberKind.Destructor, null, null), BindingRestriction.InstanceOnly) as MethodSpec;
2259
2260                                 if (base_dtor == null)
2261                                         throw new NotImplementedException ();
2262
2263                                 MethodGroupExpr method_expr = MethodGroupExpr.CreatePredefined (base_dtor, base_type, Location);
2264                                 method_expr.InstanceExpression = new BaseThis (base_type, Location);
2265
2266                                 var try_block = new ExplicitBlock (block, block.StartLocation, block.EndLocation) {
2267                                         IsCompilerGenerated = true
2268                                 };
2269                                 var finaly_block = new ExplicitBlock (block, Location, Location) {
2270                                         IsCompilerGenerated = true
2271                                 };
2272
2273                                 //
2274                                 // 0-size arguments to avoid CS0250 error
2275                                 // TODO: Should use AddScopeStatement or something else which emits correct
2276                                 // debugger scope
2277                                 //
2278                                 finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0)), Location.Null));
2279
2280                                 var tf = new TryFinally (try_block, finaly_block, Location);
2281                                 block.WrapIntoDestructor (tf, try_block);
2282                         }
2283
2284                         base.Emit ();
2285                 }
2286
2287                 public override string GetSignatureForError ()
2288                 {
2289                         return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
2290                 }
2291
2292                 protected override bool ResolveMemberType ()
2293                 {
2294                         member_type = Compiler.BuiltinTypes.Void;
2295                         return true;
2296                 }
2297
2298                 public override string[] ValidAttributeTargets {
2299                         get {
2300                                 return attribute_targets;
2301                         }
2302                 }
2303         }
2304
2305         // Ooouh Martin, templates are missing here.
2306         // When it will be possible move here a lot of child code and template method type.
2307         public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData, IMethodDefinition {
2308                 protected MethodData method_data;
2309                 protected ToplevelBlock block;
2310                 protected SecurityType declarative_security;
2311
2312                 protected readonly string prefix;
2313
2314                 ReturnParameter return_attributes;
2315
2316                 protected AbstractPropertyEventMethod (InterfaceMemberBase member, string prefix, Attributes attrs, Location loc)
2317                         : base (member.Parent, SetupName (prefix, member, loc), attrs)
2318                 {
2319                         this.prefix = prefix;
2320                 }
2321
2322                 static MemberName SetupName (string prefix, InterfaceMemberBase member, Location loc)
2323                 {
2324                         return new MemberName (member.MemberName.Left, prefix + member.ShortName, member.MemberName.ExplicitInterface, loc);
2325                 }
2326
2327                 public void UpdateName (InterfaceMemberBase member)
2328                 {
2329                         SetMemberName (SetupName (prefix, member, Location));
2330                 }
2331
2332                 #region IMethodData Members
2333
2334                 public ToplevelBlock Block {
2335                         get {
2336                                 return block;
2337                         }
2338
2339                         set {
2340                                 block = value;
2341                         }
2342                 }
2343
2344                 public CallingConventions CallingConventions {
2345                         get {
2346                                 return CallingConventions.Standard;
2347                         }
2348                 }
2349
2350                 public EmitContext CreateEmitContext (ILGenerator ig, SourceMethodBuilder sourceMethod)
2351                 {
2352                         return new EmitContext (this, ig, ReturnType, sourceMethod);
2353                 }
2354
2355                 public bool IsAccessor {
2356                         get {
2357                                 return true;
2358                         }
2359                 }
2360
2361                 public MemberName MethodName {
2362                         get {
2363                                 return MemberName;
2364                         }
2365                 }
2366
2367                 public TypeSpec[] ParameterTypes { 
2368                         get {
2369                                 return ParameterInfo.Types;
2370                         }
2371                 }
2372
2373                 MethodBase IMethodDefinition.Metadata {
2374                         get {
2375                                 return method_data.MethodBuilder;
2376                         }
2377                 }
2378
2379                 public abstract ParametersCompiled ParameterInfo { get ; }
2380                 public abstract TypeSpec ReturnType { get; }
2381
2382                 #endregion
2383
2384                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2385                 {
2386                         if (a.Type == pa.CLSCompliant || a.Type == pa.Obsolete || a.Type == pa.Conditional) {
2387                                 Report.Error (1667, a.Location,
2388                                         "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
2389                                         a.Type.GetSignatureForError (), a.GetValidTargets ());
2390                                 return;
2391                         }
2392
2393                         if (a.IsValidSecurityAttribute ()) {
2394                                 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2395                                 return;
2396                         }
2397
2398                         if (a.Target == AttributeTargets.Method) {
2399                                 method_data.MethodBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
2400                                 return;
2401                         }
2402
2403                         if (a.Target == AttributeTargets.ReturnValue) {
2404                                 if (return_attributes == null)
2405                                         return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
2406
2407                                 return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
2408                                 return;
2409                         }
2410
2411                         ApplyToExtraTarget (a, ctor, cdata, pa);
2412                 }
2413
2414                 protected virtual void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2415                 {
2416                         throw new NotSupportedException ("You forgot to define special attribute target handling");
2417                 }
2418
2419                 // It is not supported for the accessors
2420                 public sealed override bool Define()
2421                 {
2422                         throw new NotSupportedException ();
2423                 }
2424
2425                 public virtual void Emit (TypeDefinition parent)
2426                 {
2427                         method_data.Emit (parent);
2428
2429                         if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2430                                 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (method_data.MethodBuilder);
2431                         if (((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0))
2432                                 Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (method_data.MethodBuilder);
2433
2434                         if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
2435                                 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
2436                                 Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
2437                         } else if (ReturnType.HasDynamicElement) {
2438                                 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
2439                                 Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location);
2440                         }
2441
2442                         if (OptAttributes != null)
2443                                 OptAttributes.Emit ();
2444
2445                         if (declarative_security != null) {
2446                                 foreach (var de in declarative_security) {
2447 #if STATIC
2448                                         method_data.MethodBuilder.__AddDeclarativeSecurity (de);
2449 #else
2450                                         method_data.MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2451 #endif
2452                                 }
2453                         }
2454
2455                         block = null;
2456                 }
2457
2458                 public override bool EnableOverloadChecks (MemberCore overload)
2459                 {
2460                         if (overload is MethodCore) {
2461                                 caching_flags |= Flags.MethodOverloadsExist;
2462                                 return true;
2463                         }
2464
2465                         // This can only happen with indexers and it will
2466                         // be catched as indexer difference
2467                         if (overload is AbstractPropertyEventMethod)
2468                                 return true;
2469
2470                         return false;
2471                 }
2472
2473                 public override string GetCallerMemberName ()
2474                 {
2475                         return base.GetCallerMemberName ().Substring (prefix.Length);
2476                 }
2477
2478                 public override string GetSignatureForDocumentation ()
2479                 {
2480                         // should not be called
2481                         throw new NotSupportedException ();
2482                 }
2483
2484                 public override bool IsClsComplianceRequired()
2485                 {
2486                         return false;
2487                 }
2488
2489                 public void PrepareEmit ()
2490                 {
2491                         method_data.DefineMethodBuilder (Parent.PartialContainer, ParameterInfo);
2492                 }
2493
2494                 public override void WriteDebugSymbol (MonoSymbolFile file)
2495                 {
2496                         if (method_data != null)
2497                                 method_data.WriteDebugSymbol (file);
2498                 }
2499
2500                 public MethodSpec Spec { get; protected set; }
2501
2502                 //
2503                 //   Represents header string for documentation comment.
2504                 //
2505                 public override string DocCommentHeader {
2506                         get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
2507                 }
2508         }
2509
2510         public class Operator : MethodOrOperator {
2511
2512                 const Modifiers AllowedModifiers =
2513                         Modifiers.PUBLIC |
2514                         Modifiers.UNSAFE |
2515                         Modifiers.EXTERN |
2516                         Modifiers.STATIC;
2517
2518                 public enum OpType : byte {
2519
2520                         // Unary operators
2521                         LogicalNot,
2522                         OnesComplement,
2523                         Increment,
2524                         Decrement,
2525                         True,
2526                         False,
2527
2528                         // Unary and Binary operators
2529                         Addition,
2530                         Subtraction,
2531
2532                         UnaryPlus,
2533                         UnaryNegation,
2534                         
2535                         // Binary operators
2536                         Multiply,
2537                         Division,
2538                         Modulus,
2539                         BitwiseAnd,
2540                         BitwiseOr,
2541                         ExclusiveOr,
2542                         LeftShift,
2543                         RightShift,
2544                         Equality,
2545                         Inequality,
2546                         GreaterThan,
2547                         LessThan,
2548                         GreaterThanOrEqual,
2549                         LessThanOrEqual,
2550
2551                         // Implicit and Explicit
2552                         Implicit,
2553                         Explicit,
2554
2555                         // Pattern matching
2556                         Is,
2557
2558                         // Just because of enum
2559                         TOP
2560                 };
2561
2562                 public readonly OpType OperatorType;
2563
2564                 static readonly string [] [] names;
2565
2566                 static Operator ()
2567                 {
2568                         names = new string[(int)OpType.TOP][];
2569                         names [(int) OpType.LogicalNot] = new string [] { "!", "op_LogicalNot" };
2570                         names [(int) OpType.OnesComplement] = new string [] { "~", "op_OnesComplement" };
2571                         names [(int) OpType.Increment] = new string [] { "++", "op_Increment" };
2572                         names [(int) OpType.Decrement] = new string [] { "--", "op_Decrement" };
2573                         names [(int) OpType.True] = new string [] { "true", "op_True" };
2574                         names [(int) OpType.False] = new string [] { "false", "op_False" };
2575                         names [(int) OpType.Addition] = new string [] { "+", "op_Addition" };
2576                         names [(int) OpType.Subtraction] = new string [] { "-", "op_Subtraction" };
2577                         names [(int) OpType.UnaryPlus] = new string [] { "+", "op_UnaryPlus" };
2578                         names [(int) OpType.UnaryNegation] = new string [] { "-", "op_UnaryNegation" };
2579                         names [(int) OpType.Multiply] = new string [] { "*", "op_Multiply" };
2580                         names [(int) OpType.Division] = new string [] { "/", "op_Division" };
2581                         names [(int) OpType.Modulus] = new string [] { "%", "op_Modulus" };
2582                         names [(int) OpType.BitwiseAnd] = new string [] { "&", "op_BitwiseAnd" };
2583                         names [(int) OpType.BitwiseOr] = new string [] { "|", "op_BitwiseOr" };
2584                         names [(int) OpType.ExclusiveOr] = new string [] { "^", "op_ExclusiveOr" };
2585                         names [(int) OpType.LeftShift] = new string [] { "<<", "op_LeftShift" };
2586                         names [(int) OpType.RightShift] = new string [] { ">>", "op_RightShift" };
2587                         names [(int) OpType.Equality] = new string [] { "==", "op_Equality" };
2588                         names [(int) OpType.Inequality] = new string [] { "!=", "op_Inequality" };
2589                         names [(int) OpType.GreaterThan] = new string [] { ">", "op_GreaterThan" };
2590                         names [(int) OpType.LessThan] = new string [] { "<", "op_LessThan" };
2591                         names [(int) OpType.GreaterThanOrEqual] = new string [] { ">=", "op_GreaterThanOrEqual" };
2592                         names [(int) OpType.LessThanOrEqual] = new string [] { "<=", "op_LessThanOrEqual" };
2593                         names [(int) OpType.Implicit] = new string [] { "implicit", "op_Implicit" };
2594                         names [(int) OpType.Explicit] = new string [] { "explicit", "op_Explicit" };
2595                         names [(int) OpType.Is] = new string[] { "is", "op_Is" };
2596                 }
2597
2598                 public Operator (TypeDefinition parent, OpType type, FullNamedExpression ret_type, Modifiers mod_flags, ParametersCompiled parameters,
2599                                  ToplevelBlock block, Attributes attrs, Location loc)
2600                         : base (parent, ret_type, mod_flags, AllowedModifiers, new MemberName (GetMetadataName (type), loc), attrs, parameters)
2601                 {
2602                         OperatorType = type;
2603                         Block = block;
2604                 }
2605
2606                 public override void Accept (StructuralVisitor visitor)
2607                 {
2608                         visitor.Visit (this);
2609                 }
2610
2611                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2612                 {
2613                         if (a.Type == pa.Conditional) {
2614                                 Error_ConditionalAttributeIsNotValid ();
2615                                 return;
2616                         }
2617
2618                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2619                 }
2620                 
2621                 public override bool Define ()
2622                 {
2623                         const Modifiers RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
2624                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
2625                                 Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
2626                         }
2627
2628                         if (!base.Define ())
2629                                 return false;
2630
2631                         if (block != null) {
2632                                 if (block.IsIterator) {
2633                                         //
2634                                         // Current method is turned into automatically generated
2635                                         // wrapper which creates an instance of iterator
2636                                         //
2637                                         Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
2638                                         ModFlags |= Modifiers.DEBUGGER_HIDDEN;
2639                                 }
2640
2641                                 if (Compiler.Settings.WriteMetadataOnly)
2642                                         block = null;
2643                         }
2644
2645                         // imlicit and explicit operator of same types are not allowed
2646                         if (OperatorType == OpType.Explicit)
2647                                 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Implicit), parameters);
2648                         else if (OperatorType == OpType.Implicit)
2649                                 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Explicit), parameters);
2650
2651                         TypeSpec declaring_type = Parent.PartialContainer.CurrentType;
2652                         TypeSpec return_type = MemberType;
2653                         TypeSpec first_arg_type = ParameterTypes [0];
2654                         
2655                         TypeSpec first_arg_type_unwrap = first_arg_type;
2656                         if (first_arg_type.IsNullableType)
2657                                 first_arg_type_unwrap = Nullable.NullableInfo.GetUnderlyingType (first_arg_type);
2658                         
2659                         TypeSpec return_type_unwrap = return_type;
2660                         if (return_type.IsNullableType)
2661                                 return_type_unwrap = Nullable.NullableInfo.GetUnderlyingType (return_type);
2662
2663                         //
2664                         // Rules for conversion operators
2665                         //
2666                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2667                                 if (first_arg_type_unwrap == return_type_unwrap && first_arg_type_unwrap == declaring_type) {
2668                                         Report.Error (555, Location,
2669                                                 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
2670                                         return false;
2671                                 }
2672
2673                                 TypeSpec conv_type;
2674                                 if (declaring_type == return_type || declaring_type == return_type_unwrap) {
2675                                         conv_type = first_arg_type;
2676                                 } else if (declaring_type == first_arg_type || declaring_type == first_arg_type_unwrap) {
2677                                         conv_type = return_type;
2678                                 } else {
2679                                         Report.Error (556, Location,
2680                                                 "User-defined conversion must convert to or from the enclosing type");
2681                                         return false;
2682                                 }
2683
2684                                 if (conv_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
2685                                         Report.Error (1964, Location,
2686                                                 "User-defined conversion `{0}' cannot convert to or from the dynamic type",
2687                                                 GetSignatureForError ());
2688
2689                                         return false;
2690                                 }
2691
2692                                 if (conv_type.IsInterface) {
2693                                         Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
2694                                                 GetSignatureForError ());
2695                                         return false;
2696                                 }
2697
2698                                 if (conv_type.IsClass) {
2699                                         if (TypeSpec.IsBaseClass (declaring_type, conv_type, true)) {
2700                                                 Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from a base class",
2701                                                         GetSignatureForError ());
2702                                                 return false;
2703                                         }
2704
2705                                         if (TypeSpec.IsBaseClass (conv_type, declaring_type, false)) {
2706                                                 Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from a derived class",
2707                                                         GetSignatureForError ());
2708                                                 return false;
2709                                         }
2710                                 }
2711                         } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
2712                                 if (first_arg_type != declaring_type || parameters.Types[1].BuiltinType != BuiltinTypeSpec.Type.Int) {
2713                                         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");
2714                                         return false;
2715                                 }
2716                         } else if (parameters.Count == 1) {
2717                                 // Checks for Unary operators
2718
2719                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
2720                                         if (return_type != declaring_type && !TypeSpec.IsBaseClass (return_type, declaring_type, false)) {
2721                                                 Report.Error (448, Location,
2722                                                         "The return type for ++ or -- operator must be the containing type or derived from the containing type");
2723                                                 return false;
2724                                         }
2725                                         if (first_arg_type != declaring_type) {
2726                                                 Report.Error (
2727                                                         559, Location, "The parameter type for ++ or -- operator must be the containing type");
2728                                                 return false;
2729                                         }
2730                                 }
2731
2732                                 if (first_arg_type_unwrap != declaring_type) {
2733                                         Report.Error (562, Location,
2734                                                 "The parameter type of a unary operator must be the containing type");
2735                                         return false;
2736                                 }
2737
2738                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
2739                                         if (return_type.BuiltinType != BuiltinTypeSpec.Type.Bool) {
2740                                                 Report.Error (
2741                                                         215, Location,
2742                                                         "The return type of operator True or False " +
2743                                                         "must be bool");
2744                                                 return false;
2745                                         }
2746                                 }
2747
2748                         } else if (first_arg_type_unwrap != declaring_type) {
2749                                 // Checks for Binary operators
2750
2751                                 var second_arg_type = ParameterTypes[1];
2752                                 if (second_arg_type.IsNullableType)
2753                                         second_arg_type = Nullable.NullableInfo.GetUnderlyingType (second_arg_type);
2754
2755                                 if (second_arg_type != declaring_type) {
2756                                         Report.Error (563, Location,
2757                                                 "One of the parameters of a binary operator must be the containing type");
2758                                         return false;
2759                                 }
2760                         }
2761
2762                         return true;
2763                 }
2764
2765                 protected override bool ResolveMemberType ()
2766                 {
2767                         if (!base.ResolveMemberType ())
2768                                 return false;
2769
2770                         flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2771                         return true;
2772                 }
2773
2774                 protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
2775                 {
2776                         // Operator cannot be override
2777                         bestCandidate = null;
2778                         return null;
2779                 }
2780
2781                 public static string GetName (OpType ot)
2782                 {
2783                         return names [(int) ot] [0];
2784                 }
2785
2786                 public static string GetName (string metadata_name)
2787                 {
2788                         for (int i = 0; i < names.Length; ++i) {
2789                                 if (names [i] [1] == metadata_name)
2790                                         return names [i] [0];
2791                         }
2792                         return null;
2793                 }
2794
2795                 public static string GetMetadataName (OpType ot)
2796                 {
2797                         return names [(int) ot] [1];
2798                 }
2799
2800                 public static string GetMetadataName (string name)
2801                 {
2802                         for (int i = 0; i < names.Length; ++i) {
2803                                 if (names [i] [0] == name)
2804                                         return names [i] [1];
2805                         }
2806                         return null;
2807                 }
2808
2809                 public static OpType? GetType (string metadata_name)
2810                 {
2811                         for (int i = 0; i < names.Length; ++i) {
2812                                 if (names[i][1] == metadata_name)
2813                                         return (OpType) i;
2814                         }
2815
2816                         return null;
2817                 }
2818
2819                 public OpType GetMatchingOperator ()
2820                 {
2821                         switch (OperatorType) {
2822                         case OpType.Equality:
2823                                 return OpType.Inequality;
2824                         case OpType.Inequality:
2825                                 return OpType.Equality;
2826                         case OpType.True:
2827                                 return OpType.False;
2828                         case OpType.False:
2829                                 return OpType.True;
2830                         case OpType.GreaterThan:
2831                                 return OpType.LessThan;
2832                         case OpType.LessThan:
2833                                 return OpType.GreaterThan;
2834                         case OpType.GreaterThanOrEqual:
2835                                 return OpType.LessThanOrEqual;
2836                         case OpType.LessThanOrEqual:
2837                                 return OpType.GreaterThanOrEqual;
2838                         default:
2839                                 return OpType.TOP;
2840                         }
2841                 }
2842
2843                 public override string GetSignatureForDocumentation ()
2844                 {
2845                         string s = base.GetSignatureForDocumentation ();
2846                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2847                                 s = s + "~" + ReturnType.GetSignatureForDocumentation ();
2848                         }
2849
2850                         return s;
2851                 }
2852
2853                 public override string GetSignatureForError ()
2854                 {
2855                         StringBuilder sb = new StringBuilder ();
2856                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2857                                 sb.AppendFormat ("{0}.{1} operator {2}",
2858                                         Parent.GetSignatureForError (), GetName (OperatorType),
2859                                         member_type == null ? type_expr.GetSignatureForError () : member_type.GetSignatureForError ());
2860                         }
2861                         else {
2862                                 sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
2863                         }
2864
2865                         sb.Append (parameters.GetSignatureForError ());
2866                         return sb.ToString ();
2867                 }
2868         }
2869 }
2870