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