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