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