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