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