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