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