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