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