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