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