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