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