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