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